diff --git a/sgx-jvm/avian/.clang-format b/sgx-jvm/avian/.clang-format new file mode 100644 index 0000000000..910160fcbe --- /dev/null +++ b/sgx-jvm/avian/.clang-format @@ -0,0 +1,7 @@ +--- +BasedOnStyle: Chromium +IndentCaseLabels: false +BreakBeforeBraces: Stroustrup +AllowShortFunctionsOnASingleLine: false +BreakBeforeBinaryOperators: true +... diff --git a/sgx-jvm/avian/.gitignore b/sgx-jvm/avian/.gitignore new file mode 100644 index 0000000000..989c2222e8 --- /dev/null +++ b/sgx-jvm/avian/.gitignore @@ -0,0 +1,17 @@ +.gdb_history +/build +*~ +.classpath +.project +.settings +bin +/lib +/distrib +*.pdb +*.swp +/.gradle +/*.sublime-* +workspace/ +src/.cproject +/cmake-build +/cmake-build diff --git a/sgx-jvm/avian/.mailmap b/sgx-jvm/avian/.mailmap new file mode 100644 index 0000000000..12fd7d9627 --- /dev/null +++ b/sgx-jvm/avian/.mailmap @@ -0,0 +1,27 @@ +Carsten Elton Sørensen +Carsten Elton Sørensen +Dain Darnell +Dain Darnell +Edison Guo +Jason Treadwell +Jason Treadwell +Jason Treadwell +Jason Treadwell +Jason Treadwell +Jason Treadwell +Jason Treadwell +Jason Treadwell +Jason Treadwell +Joel Dice +Joel Dice +Joel Dice +Joel Dice +Anonymous +Joshua Warner +Matt Weaver +Mike Jensen +Mike Jensen +Mike Jensen +Terek Campbell +Thiago Bedin Frustaci +Zsombor Gegesy diff --git a/sgx-jvm/avian/.travis.yml b/sgx-jvm/avian/.travis.yml new file mode 100644 index 0000000000..42265efb47 --- /dev/null +++ b/sgx-jvm/avian/.travis.yml @@ -0,0 +1,25 @@ +language: cpp +cache: apt + +os: + - linux + - osx + +env: + matrix: + - BUILD_STEP="" +# disabled until/unless jfrog.org credentials are updated and someone +# decides they care about published artifacts: +# - BUILD_STEP="PUBLISH" + global: + - TERM=dumb + - secure: rh1utD4shKmYtokItuRYEF9WsfTnvZO5XqnTU4DHTS7quHHgLihtOO2/3+B+2W2hEd5Obr2or8zx+zmzWcNUyLokZ0j/FRLWSScNkLzTtm12pupLrncY+/g1NIdfbhn+OLRIzBz6zB6m6a2qWFEJ+bScUNGD/7wZVtzkujqlDEE= + - secure: j9DOzZMCYk/BzhKK9u4XMKpCzyGOsvP2cLTp6cXE7/tkWDAPVv6BFmeqNbiLTEqk0aGX+HYbY/2YVtpRZmDzfeWtnBFF5mL1Y1tgzx1Kf155C+P6rZgt5PiQTUdXlp2umuRifY1BbXAPc3DZ2UOPUjWKnLHVbZLQRgO1zimmMx8= + +matrix: + fast_finish: true + exclude: + - os: osx + env: BUILD_STEP="" + +script: ./test/ci.sh ${BUILD_STEP} diff --git a/sgx-jvm/avian/.utility/push-javadoc-to-gh-pages.sh b/sgx-jvm/avian/.utility/push-javadoc-to-gh-pages.sh new file mode 100755 index 0000000000..c3690b49de --- /dev/null +++ b/sgx-jvm/avian/.utility/push-javadoc-to-gh-pages.sh @@ -0,0 +1,31 @@ +#!/bin/bash +# This script was originally written by maxiaohao in the aws-mock GitHub project. +# https://github.com/treelogic-swe/aws-mock/ + +if [ "$TRAVIS_PULL_REQUEST" == "false" ]; then + + echo "Start to publish lastest Javadoc to gh-pages..." + + cd build/ + + if test -d gh-pages/avian-web + then + cd gh-pages/avian-web + git pull + else + git clone --quiet https://${GH_TOKEN}@github.com/ReadyTalk/readytalk.github.io gh-pages > /dev/null + cd gh-pages/avian-web + git config user.email "travis@travis-ci.org" + git config user.name "travis-ci" + fi + + git rm -rf ./javadoc + cp -Rf ../javadoc ./javadoc + git add -f . + git commit -m "Latest javadoc on successful Travis build $TRAVIS_BUILD_NUMBER auto-pushed to readytalk.github.io" + if ! git push -fq origin master &> /dev/null; then + echo "Error pushing gh-pages to origin. Bad GH_TOKEN? GitHub down?" + else + echo "Done magic with auto publishment to readytalk.github.io." + fi +fi diff --git a/sgx-jvm/avian/CMakeLists.txt b/sgx-jvm/avian/CMakeLists.txt new file mode 100644 index 0000000000..19c4b900b6 --- /dev/null +++ b/sgx-jvm/avian/CMakeLists.txt @@ -0,0 +1,29 @@ +# NOTE that this CMake file doesn't current build all of avian. +# It only builds what's required for example/kaleidoscope. + +cmake_minimum_required (VERSION 2.6) +project (avian) + +include_directories (include src) + +add_definitions ( + -DAVIAN_TARGET_FORMAT=AVIAN_FORMAT_MACHO + + -DAVIAN_TARGET_ARCH=AVIAN_ARCH_X86_64 + + -DTARGET_BYTES_PER_WORD=8 + -D__STDC_LIMIT_MACROS + -D__STDC_CONSTANT_MACROS +) + +include ("cmake/Platform.cmake") + +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${PLATFORM_CXX_FLAGS}") + +include (CTest) + +# Sadly, we can't use the 'test' target, as that's coopted by ctest +add_custom_target(check ${CMAKE_CTEST_COMMAND} -V) + +add_subdirectory (src) +add_subdirectory (unittest) diff --git a/sgx-jvm/avian/LICENSE.txt b/sgx-jvm/avian/LICENSE.txt new file mode 100644 index 0000000000..71731a35a9 --- /dev/null +++ b/sgx-jvm/avian/LICENSE.txt @@ -0,0 +1,15 @@ +ISC License + +Copyright (c) 2008-2015, Avian Contributors + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/sgx-jvm/avian/README.md b/sgx-jvm/avian/README.md new file mode 100644 index 0000000000..80434004dc --- /dev/null +++ b/sgx-jvm/avian/README.md @@ -0,0 +1,750 @@ +Avian - A lightweight Java Virtual Machine (JVM) +================================================ + +[![Build Status](https://travis-ci.org/ReadyTalk/avian.png?branch=master)](https://travis-ci.org/ReadyTalk/avian) + +Quick Start +----------- + +These are examples of building Avian on various operating systems for +the x86_64 architecture. You may need to modify JAVA_HOME according +to where the JDK is installed on your system. In all cases, be sure +to use forward slashes in the path. + +#### on Linux: + $ export JAVA_HOME=/usr/lib/jvm/java-7-openjdk-amd64 + $ make + $ build/linux-x86_64/avian -cp build/linux-x86_64/test Hello + +#### on Mac OS X: + $ export JAVA_HOME=$(/usr/libexec/java_home) + $ make + $ build/macosx-x86_64/avian -cp build/macosx-x86_64/test Hello + +#### on Windows (Cygwin): + $ git clone git@github.com:ReadyTalk/win64.git ../win64 + $ export JAVA_HOME="/cygdrive/c/Program Files/Java/jdk1.7.0_45" + $ make + $ build/windows-x86_64/avian -cp build/windows-x86_64/test Hello + +#### on FreeBSD: + $ export JAVA_HOME=/usr/local/openjdk7 + $ gmake + $ build/freebsd-x86_64/avian -cp build/freebsd-x86_64/test Hello + + +Introduction +------------ + +Avian is a lightweight virtual machine and class library designed to +provide a useful subset of Java's features, suitable for building +self-contained applications. More information is available at the +project [web site](http://readytalk.github.io/avian). + +If you have any trouble building, running, or embedding Avian, please +post a message to our [discussion group](http://groups.google.com/group/avian). + +That's also the place for any other questions, comments, or +suggestions you might have. + + +Supported Platforms +------------------- + +Avian can currently target the following platforms: + + * Linux (i386, x86_64, ARM, and ARM64) + * Windows (i386 and x86_64) + * Mac OS X (i386 and x86_64) + * Apple iOS (i386, x86_64, ARM, and ARM64) + * FreeBSD (i386, x86_64) + + +Building +-------- + +Build requirements include: + + * GNU make 3.80 or later + * GCC 4.6 or later + or LLVM Clang 3.1 or later (see use-clang option below) + * JDK 1.6 or later + * MinGW 3.4 or later (only if compiling for Windows) + * zlib 1.2.3 or later + +Earlier versions of some of these packages may also work but have not +been tested. + +The build is directed by a single makefile and may be influenced via +certain flags described below, all of which are optional. + + $ make \ + platform={linux,windows,macosx,ios,freebsd} \ + arch={i386,x86_64,arm,arm64} \ + process={compile,interpret} \ + mode={debug,debug-fast,fast,small} \ + lzma= \ + bootimage={true,false} \ + tails={true,false} \ + continuations={true,false} \ + use-clang={true,false} \ + openjdk= \ + openjdk-src= \ + android= + + * `platform` - the target platform + * _default:_ output of $(uname -s | tr [:upper:] [:lower:]), +normalized in some cases (e.g. CYGWIN_NT-5.1 -> windows) + + * `arch` - the target architecture + * _default:_ output of $(uname -m), normalized in some cases +(e.g. i686 -> i386) + + * `process` - choice between pure interpreter or JIT compiler + * _default:_ compile + + * `mode` - which set of compilation flags to use to determine +optimization level, debug symbols, and whether to enable +assertions + * _default:_ fast + + * `lzma` - if set, support use of LZMA to compress embedded JARs and +boot images. The value of this option should be a directory +containing a recent LZMA SDK (available [here](http://www.7-zip.org/sdk.html)). Currently, only version 9.20 of +the SDK has been tested, but other versions might work. + * _default:_ not set + + * `armv6` - if true, don't use any instructions newer than armv6. By +default, we assume the target is armv7 or later, and thus requires explicit +memory barrier instructions to ensure cache coherency + + * `bootimage` - if true, create a boot image containing the pre-parsed +class library and ahead-of-time compiled methods. This option is +only valid for process=compile builds. Note that you may need to +specify both build-arch=x86_64 and arch=x86_64 on 64-bit systems +where "uname -m" prints "i386". + * _default:_ false + + * `tails` - if true, optimize each tail call by replacing the caller's +stack frame with the callee's. This convention ensures proper +tail recursion, suitable for languages such as Scheme. This +option is only valid for process=compile builds. + * _default:_ false + + * `continuations` - if true, support continuations via the +avian.Continuations methods callWithCurrentContinuation and +dynamicWind. See Continuations.java for details. This option is +only valid for process=compile builds. + * _default:_ false + + * `use-clang` - if true, use LLVM's clang instead of GCC to build. +Note that this does not currently affect cross compiles, only +native builds. + * _default:_ false + + * `openjdk` - if set, use the OpenJDK class library instead of the +default Avian class library. See "Building with the OpenJDK Class +Library" below for details. + * _default:_ not set + + * `openjdk-src` - if this and the openjdk option above are both set, +build an embeddable VM using the OpenJDK class library. The JNI +components of the OpenJDK class library will be built from the +sources found under the specified directory. See "Building with +the OpenJDK Class Library" below for details. + * _default:_ not set + + * `android` - if set, use the Android class library instead of the +default Avian class library. See "Building with the Android Class +Library" below for details. + * _default:_ not set + +These flags determine the name of the directory used for the build. +The name always starts with _${platform}-${arch}_, and each non-default +build option is appended to the name. For example, a debug build with +bootimage enabled on Linux/x86_64 would be built in +_build/linux-x86_64-debug-bootimage_. This allows you to build with +several different sets of options independently and even +simultaneously without doing a clean build each time. + +Note that not all combinations of these flags are valid. For instance, +non-jailbroken iOS devices do not allow JIT compilation, so only +process=interpret or bootimage=true builds will run on such +devices. See [here](https://github.com/ReadyTalk/hello-ios) for an +example of an Xcode project for iOS which uses Avian. + +If you are compiling for Windows, you may either cross-compile using +MinGW or build natively on Windows under Cygwin. + +#### Installing Cygwin: + + __1.__ Download and run setup.exe from [cygwin's website](http://www.cygwin.com), installing the base + system and these packages: make, gcc-mingw-g++, + mingw64-i686-gcc-g++, mingw64-x86_64-gcc-g++, and (optionally) git. + +You may also find our win32 repository useful: (run this from the +directory containing the avian directory) + + $ git clone git@github.com:ReadyTalk/win32.git + +This gives you the Windows JNI headers, zlib headers and library, and +a few other useful libraries like OpenSSL, libjpeg, and libpng. +There's also a win64 repository for 64-bit builds: + + $ git clone git@github.com:ReadyTalk/win64.git + + +Building with the Microsoft Visual C++ Compiler +----------------------------------------------- + +You can also build using the MSVC compiler, which makes debugging with +tools like WinDbg and Visual Studio much easier. Note that you will +still need to have GCC installed - MSVC is only used to compile the +C++ portions of the VM, while the assembly code and helper tools are +built using GCC. + +*Note that the MSVC build isn't tested regularly, so is fairly likely to be broken.* + +Avian targets MSVC 11 and above (it uses c++ features not available in older versions). + +To build with MSVC, install Cygwin as described above and set the +following environment variables: + + $ export PATH="/usr/local/bin:/usr/bin:/bin:/usr/X11R6/bin:/cygdrive/c/Program Files/Microsoft Visual Studio 11.0/Common7/IDE:/cygdrive/c/Program Files/Microsoft Visual Studio 11.0/VC/BIN:/cygdrive/c/Program Files/Microsoft Visual Studio 11.0/Common7/Tools:/cygdrive/c/WINDOWS/Microsoft.NET/Framework/v3.5:/cygdrive/c/WINDOWS/Microsoft.NET/Framework/v2.0.50727:/cygdrive/c/Program Files/Microsoft Visual Studio 11.0/VC/VCPackages:/cygdrive/c/Program Files/Microsoft SDKs/Windows/v6.0A/bin:/cygdrive/c/WINDOWS/system32:/cygdrive/c/WINDOWS:/cygdrive/c/WINDOWS/System32/Wbem" + $ export LIBPATH="C:\WINDOWS\Microsoft.NET\Framework\v3.5;C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727;C:\Program Files\Microsoft Visual Studio 11.0\VC\LIB;" + $ export VCINSTALLDIR="C:\Program Files\Microsoft Visual Studio 11.0\VC" + $ export LIB="C:\Program Files\Microsoft Visual Studio 11.0\VC\LIB;C:\Program Files\Microsoft SDKs\Windows\v6.0A\lib;" + $ export INCLUDE="C:\Program Files\Microsoft Visual Studio 11.0\VC\INCLUDE;C:\Program Files\Microsoft SDKs\Windows\v6.0A\include;" + +Adjust these definitions as necessary according to your MSVC +installation. + +Finally, build with the msvc flag set to the MSVC tool directory: + + $ make msvc="/cygdrive/c/Program Files/Microsoft Visual Studio 11.0/VC" + + +Building with the OpenJDK Class Library +--------------------------------------- + +By default, Avian uses its own lightweight class library. However, +that library only contains a relatively small subset of the classes +and methods included in the JRE. If your application requires +features beyond that subset, you may want to tell Avian to use +OpenJDK's class library instead. To do so, specify the directory +where OpenJDK is installed, e.g.: + + $ make openjdk=/usr/lib/jvm/java-7-openjdk + +This will build Avian as a conventional JVM (e.g. libjvm.so) which +loads its boot class library and native libraries (e.g. libjava.so) +from _/usr/lib/jvm/java-7-openjdk/jre_ at runtime. Note that you must +use an absolute path here, or else the result will not work when run +from other directories. In this configuration, OpenJDK needs to +remain installed for Avian to work, and you can run applications like +this: + + $ build/linux-x86_64-openjdk/avian-dynamic -cp /path/to/my/application \ + com.example.MyApplication + +Alternatively, you can enable a stand-alone build using OpenJDK by +specifying the location of the OpenJDK source code, e.g.: + + $ make openjdk=$(pwd)/../jdk7/build/linux-amd64/j2sdk-image \ + openjdk-src=$(pwd)/../jdk7/jdk/src + +You must ensure that the path specified for openjdk-src does not have +any spaces in it; make gets confused when dependency paths include +spaces, and we haven't found away around that except to avoid paths +with spaces entirely. + +The result of such a build is a self-contained binary which does not +depend on external libraries, jars, or other files. In this case, the +specified paths are used only at build time; anything needed at +runtime is embedded in the binary. Thus, the process of running an +application is simplified: + + $ build/linux-x86_64-openjdk-src/avian -cp /path/to/my/application \ + com.example.MyApplication + +Note that the resulting binary will be very large due to the size of +OpenJDK's class library. This can be mitigated using UPX, preferably +an LZMA-enabled version: + + $ upx --lzma --best build/linux-x86_64-openjdk-src/avian + +You can reduce the size futher for embedded builds by using ProGuard +and the supplied openjdk.pro configuration file (see "Embedding with +ProGuard and a Boot Image" below). Note that you'll still need to use +vm.pro in that case -- openjdk.pro just adds additional constraints +specific to the OpenJDK port. Also see +[app.mk](https://github.com/ReadyTalk/avian-swt-examples/blob/master/app.mk) +in the _avian-swt-examples_ project for an example of using Avian, +OpenJDK, ProGuard, and UPX in concert. + +Here are some examples of how to install OpenJDK and build Avian with +it on various OSes: + +#### Debian-based Linux: +_Conventional build:_ + + $ apt-get install openjdk-7-jdk + $ make openjdk=/usr/lib/jvm/java-7-openjdk test + +_Stand-alone build:_ + + $ apt-get install openjdk-7-jdk + $ apt-get source openjdk-7-jdk + $ apt-get build-dep openjdk-7-jdk + $ (cd openjdk-7-7~b147-2.0 && dpkg-buildpackage) + $ make openjdk=/usr/lib/jvm/java-7-openjdk \ + openjdk-src=$(pwd)/openjdk-7-7~b147-2.0/build/openjdk/jdk/src \ + test + +####Mac OS X: +_Prerequisite:_ Build OpenJDK 7 according to [this site](https://wikis.oracle.com/display/OpenJDK/Mac+OS+X+Port). + +_Conventional build:_ + + $ make openjdk=$(pwd)/../jdk7u-dev/build/macosx-amd64/j2sdk-image test + +_Stand-alone build:_ + + $ make openjdk=$(pwd)/../jdk7u-dev/build/macosx-amd64/j2sdk-image \ + openjdk-src=$(pwd)/../p/jdk7u-dev/jdk/src test + +####Windows (Cygwin): +_Prerequisite:_ Build OpenJDK 7 according to [this site](http://weblogs.java.net/blog/simonis/archive/2011/10/28/yaojowbi-yet-another-openjdk-windows-build-instruction). Alternatively, use https://github.com/alexkasko/openjdk-unofficial-builds. + +_Conventional build:_ + + $ make openjdk=$(pwd)/../jdk7u-dev/build/windows-i586/j2sdk-image test + +_Stand-alone build:_ + + $ make openjdk=$(pwd)/../jdk7u-dev/build/windows-i586/j2sdk-image \ + openjdk-src=$(pwd)/../p/jdk7u-dev/jdk/src test + +Currently, only OpenJDK 7 is supported. Later versions might work, +but have not yet been tested. + + +Building with the Android Class Library +--------------------------------------- +As an alternative to both the Avian and OpenJDK class libaries, you +can also build with the Android class library. Now it should work on Linux, OS X and Windows. + +The simpliest way to build Avian with Android classpath is to use `avian-pack` project: https://github.com/bigfatbrowncat/avian-pack + +Avian-pack consists of Avian itself with some Android components (such as libcore and icu4c). + +Note that we use the upstream OpenSSL repository and apply the +Android patches to it. This is because it is not clear how to build +the Android fork of OpenSSL directly without checking out and building +the entire platform. As of this writing, the patches apply cleanly +against OpenSSL 1.0.1h, so that's the tag we check out, but this may +change in the future when the Android fork rebases against a new +OpenSSL version. + +Installing +---------- + +Installing Avian is as simple as copying the executable to the desired +directory: + + $ cp build/${platform}-${arch}/avian ~/bin/ + + +Embedding +--------- + +The following series of commands illustrates how to produce a +stand-alone executable out of a Java application using Avian. + +Note: if you are building on Cygwin, prepend "x86_64-w64-mingw32-" or +"i686-w64-mingw32-" to the ar, g++, gcc, strip, and dlltool commands +below (e.g. x86_64-w64-mingw32-gcc). + +__1.__ Build Avian, create a new directory, and populate it with the +VM object files and bootstrap classpath jar. + + $ make + $ mkdir hello + $ cd hello + $ ar x ../build/${platform}-${arch}/libavian.a + $ cp ../build/${platform}-${arch}/classpath.jar boot.jar + +__2.__ Build the Java code and add it to the jar. + + $ cat >Hello.java <embedded-jar-main.cpp <("-Xbootclasspath:[bootJar]"); + + JavaVM* vm; + void* env; + JNI_CreateJavaVM(&vm, &env, &vmArgs); + JNIEnv* e = static_cast(env); + + jclass c = e->FindClass("Hello"); + if (not e->ExceptionCheck()) { + jmethodID m = e->GetStaticMethodID(c, "main", "([Ljava/lang/String;)V"); + if (not e->ExceptionCheck()) { + jclass stringClass = e->FindClass("java/lang/String"); + if (not e->ExceptionCheck()) { + jobjectArray a = e->NewObjectArray(ac-1, stringClass, 0); + if (not e->ExceptionCheck()) { + for (int i = 1; i < ac; ++i) { + e->SetObjectArrayElement(a, i-1, e->NewStringUTF(av[i])); + } + + e->CallStaticVoidMethod(c, m, a); + } + } + } + } + + int exitCode = 0; + if (e->ExceptionCheck()) { + exitCode = -1; + e->ExceptionDescribe(); + } + + vm->DestroyJavaVM(); + + return exitCode; + } + EOF + +__on Linux:__ + + $ g++ -I$JAVA_HOME/include -I$JAVA_HOME/include/linux \ + -D_JNI_IMPLEMENTATION_ -c embedded-jar-main.cpp -o main.o + +__on Mac OS X:__ + + $ g++ -I$JAVA_HOME/include -I$JAVA_HOME/include/darwin \ + -D_JNI_IMPLEMENTATION_ -c embedded-jar-main.cpp -o main.o + +__on Windows:__ + + $ g++ -fno-exceptions -fno-rtti -I"$JAVA_HOME/include" -I"$JAVA_HOME/include/win32" \ + -D_JNI_IMPLEMENTATION_ -c embedded-jar-main.cpp -o main.o + +__5.__ Link the objects produced above to produce the final +executable, and optionally strip its symbols. + +__on Linux:__ + + $ g++ -rdynamic *.o -ldl -lpthread -lz -o hello + $ strip --strip-all hello + +__on Mac OS X:__ + + $ g++ -rdynamic *.o -ldl -lpthread -lz -o hello -framework CoreFoundation + $ strip -S -x hello + +__on Windows:__ + + $ dlltool -z hello.def *.o + $ dlltool -d hello.def -e hello.exp + $ gcc hello.exp *.o -L../../win32/lib -lmingwthrd -lm -lz -lws2_32 \ + -lIphlpapi -mwindows -mconsole -o hello.exe + $ strip --strip-all hello.exe + +Embedding with ProGuard and a Boot Image +---------------------------------------- + +The following illustrates how to embed an application as above, except +this time we preprocess the code using ProGuard and build a boot image +from it for quicker startup. The pros and cons of using ProGuard are +as follow: + + * Pros: ProGuard will eliminate unused code, optimize the rest, and + obfuscate it as well for maximum space savings + + * Cons: increased build time, especially for large applications, and + extra effort needed to configure it for applications which rely + heavily on reflection and/or calls to Java from native code + +For boot image builds: + + * Pros: the boot image build pre-parses all the classes and compiles + all the methods, obviating the need for JIT compilation at runtime. + This also makes garbage collection faster, since the pre-parsed + classes are never visited. + + * Cons: the pre-parsed classes and AOT-compiled methods take up more + space in the executable than the equivalent class files. In + practice, this can make the executable 30-50% larger. Also, AOT + compilation does not yet yield significantly faster or smaller code + than JIT compilation. Finally, floating point code may be slower + on 32-bit x86 since the compiler cannot assume SSE2 support will be + available at runtime, and the x87 FPU is not supported except via + out-of-line helper functions. + +Note you can use ProGuard without using a boot image and vice-versa, +as desired. + +The following instructions assume we are building for Linux/x86_64. +Please refer to the previous example for guidance on other platforms. + +__1.__ Build Avian, create a new directory, and populate it with the +VM object files. + + $ make bootimage=true + $ mkdir hello + $ cd hello + $ ar x ../build/linux-x86_64-bootimage/libavian.a + +__2.__ Create a stage1 directory and extract the contents of the +class library jar into it. + + $ mkdir stage1 + $ (cd stage1 && jar xf ../../build/linux-x86_64-bootimage/classpath.jar) + +__3.__ Build the Java code and add it to stage1. + + $ cat >Hello.java <hello.pro <bootimage-main.cpp <("-Davian.bootimage=bootimageBin"); + + options[1].optionString + = const_cast("-Davian.codeimage=codeimageBin"); + + JavaVM* vm; + void* env; + JNI_CreateJavaVM(&vm, &env, &vmArgs); + JNIEnv* e = static_cast(env); + + jclass c = e->FindClass("Hello"); + if (not e->ExceptionCheck()) { + jmethodID m = e->GetStaticMethodID(c, "main", "([Ljava/lang/String;)V"); + if (not e->ExceptionCheck()) { + jclass stringClass = e->FindClass("java/lang/String"); + if (not e->ExceptionCheck()) { + jobjectArray a = e->NewObjectArray(ac-1, stringClass, 0); + if (not e->ExceptionCheck()) { + for (int i = 1; i < ac; ++i) { + e->SetObjectArrayElement(a, i-1, e->NewStringUTF(av[i])); + } + + e->CallStaticVoidMethod(c, m, a); + } + } + } + } + + int exitCode = 0; + if (e->ExceptionCheck()) { + exitCode = -1; + e->ExceptionDescribe(); + } + + vm->DestroyJavaVM(); + + return exitCode; + } + EOF + + $ g++ -I$JAVA_HOME/include -I$JAVA_HOME/include/linux \ + -D_JNI_IMPLEMENTATION_ -c bootimage-main.cpp -o main.o + +__8.__ Link the objects produced above to produce the final + executable, and optionally strip its symbols. + + $ g++ -rdynamic *.o -ldl -lpthread -lz -o hello + $ strip --strip-all hello + + +Trademarks +---------- + +Oracle and Java are registered trademarks of Oracle and/or its +affiliates. Other names may be trademarks of their respective owners. + +The Avian project is not affiliated with Oracle. diff --git a/sgx-jvm/avian/android.pro b/sgx-jvm/avian/android.pro new file mode 100644 index 0000000000..00941ff874 --- /dev/null +++ b/sgx-jvm/avian/android.pro @@ -0,0 +1,89 @@ +# these are referenced in JniConstants.cpp: + +-keep class java.text.Bidi$Run +-keep class java.math.BigDecimal +-keep class java.lang.Boolean +-keep class java.lang.Byte +-keep class java.nio.charset.CharsetICU { + CharsetICU(java.lang.String, java.lang.String, java.lang.String[]); + } +-keep class java.lang.reflect.Constructor +-keep class java.util.zip.Deflater +-keep class java.lang.Double +-keep class libcore.io.ErrnoException +-keep class java.lang.reflect.Field +-keep class libcore.icu.NativeDecimalFormat$FieldPositionIterator { + void setData(int[]); + } +-keep class java.io.FileDescriptor +-keep class libcore.io.GaiException +-keep class java.net.Inet6Address +-keep class java.net.InetAddress +-keep class java.net.InetSocketAddress +-keep class java.net.InetUnixAddress +-keep class java.util.zip.Inflater +-keep class java.lang.Integer +-keep class libcore.icu.LocaleData +-keep class java.lang.Long +-keep class java.lang.reflect.Method +-keep class libcore.util.MutableInt +-keep class libcore.util.MutableLong +-keep class java.text.ParsePosition +-keep class java.util.regex.PatternSyntaxException +-keep class java.lang.RealToString +-keep class java.net.Socket +-keep class java.net.SocketImpl +-keep class java.lang.String +-keep class libcore.io.StructAddrinfo { + ; + } +-keep class libcore.io.StructFlock +-keep class libcore.io.StructGroupReq +-keep class libcore.io.StructLinger +-keep class libcore.io.StructPasswd { + StructPasswd(java.lang.String, int, int, java.lang.String, java.lang.String); + } +-keep class libcore.io.StructPollfd +-keep class libcore.io.StructStat { + StructStat(long, long, int, long, int, int, long, long, long, long, long, long, long); + } +-keep class libcore.io.StructStatFs +-keep class libcore.io.StructTimeval +-keep class libcore.io.StructUtsname { + StructUtsname(java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String); + } +-keep class libcore.io.StructUcred + +# referenced from libcore native code + +-keep class libcore.icu.LocaleData { + ; + } + +-keep class org.conscrypt.OpenSSLBIOInputStream { + ; + } + +-keep class java.util.Calendar { + void set(int, int, int, int, int, int); + } + +# called from the VM + +-keep class java.lang.Thread { + Thread(java.lang.ThreadGroup, java.lang.String, int, boolean); + } + +-keep class avian.Classes { + java.lang.Class forName(java.lang.String, boolean, java.lang.ClassLoader); + int findField(avian.VMClass, java.lang.String); + int findMethod(avian.VMClass, java.lang.String, java.lang.Class[]); + java.lang.annotation.Annotation getAnnotation(java.lang.ClassLoader, java.lang.Object[]); + } + +-keep class java.lang.VMThread { + VMThread(java.lang.Thread); + } + +# loaded reflectively to handle embedded resources: +-keep class avian.avianvmresource.Handler diff --git a/sgx-jvm/avian/build.gradle b/sgx-jvm/avian/build.gradle new file mode 100644 index 0000000000..7c49e302bc --- /dev/null +++ b/sgx-jvm/avian/build.gradle @@ -0,0 +1,323 @@ +buildscript { + repositories { + jcenter() + } + + dependencies { + classpath 'org.jfrog.buildinfo:build-info-extractor-gradle:2.2.4' + } +} + +apply plugin: 'native-component' +apply plugin: 'ivy-publish' +apply plugin: 'java' +apply plugin: 'artifactory-publish' + +enum SupportedOS implements OperatingSystem { + LINUX, WINDOWS, MACOSX; + + public static final SupportedOS CURRENT; + + static { + String p = System.properties['os.name'] + switch(p.replaceAll(' ', '').toLowerCase()) { + case ~/.*linux.*/: CURRENT = LINUX; break; + case ~/.*darwin.*/: CURRENT = MACOSX; break; + case ~/.*osx.*/: CURRENT = MACOSX; break; + case ~/.*win.*/: CURRENT = WINDOWS; break; + default: + String m = "SupportedOS: unrecognized platform: ${p}" + println(m) + throw new IllegalArgumentException(m) + } + } + + public String getName() { + return toString().toLowerCase() + } + + public String getDisplayName() { + return getName() + } + public boolean isCurrent() { return this == CURRENT } + public boolean isFreeBSD() { return false } + public boolean isLinux() { return this == LINUX } + public boolean isMacOsX() { return this == MACOSX } + public boolean isSolaris() { return false } + public boolean isWindows() { return this == WINDOWS } + +} + +public String adjustArch(String arch) { + switch(arch) { + case ~/.*64.*/: return 'x86_64' + default: return 'i386' + } +} + +ext { + currentPlatform = SupportedOS.CURRENT.getName() + currentArch = adjustArch(System.properties['os.arch']) + currentPlatformArch = "${currentPlatform}-${currentArch}" + + platform = project.hasProperty('platform') ? platform : currentPlatform + arch = project.hasProperty('arch') ? arch : currentArch + platformArch = "${platform}-${arch}" + + java_home = System.properties.'java.home' + if(java_home.endsWith("/jre")) { + java_home = java_home.substring(0, java_home.length() - "/jre".length()) + } + java_home = java_home + + libDir = "${buildDir}/lib" + lzmaDir = "${libDir}/lzma" + + buildOptions = ['', '-lzma'] +} + +repositories { + ivy { + name "ivyLocal" + url "${System.env.HOME}/.ivy2/local" + layout 'maven' + } + + ivy { + name "jcenter" + if(version.contains("SNAPSHOT")) { + url "http://oss.jfrog.org/artifactory/oss-snapshot-local" + } else { + url "http://oss.jfrog.org/artifactory/oss-release-local" + } + layout 'maven' + } +} + +configurations { + create('windows-i386') + create('windows-x86_64') +} + +dependencies { + 'windows-i386' "com.readytalk:win32:1.0.0-SNAPSHOT" + 'windows-x86_64' "com.readytalk:win64:1.0.0-SNAPSHOT" +} + +model { + platforms { + create(platformArch) { + operatingSystem SupportedOS.valueOf(platform.toUpperCase()) + architecture "${arch}" + } + } + + tasks { + buildOptions.each { buildOption -> + platforms.each { platform -> + if(platform.operatingSystem.name == "windows") { + def artifactName = platform.architecture.name == "i386" ? 'win32' : 'win64' + + task "extract${platform.name}${buildOption}"(type: Copy) { + from { + tarTree(configurations."${platform.name}".find { it.name =~ artifactName }) + } + into "${libDir}/tools" + } + } + + task "build${platform.name}${buildOption}"(type: Exec) { + executable "make" + args "platform=${platform.operatingSystem.name}", + "arch=${platform.architecture.name}" + + if(buildOption == "-lzma") { + dependsOn 'extractLzma' + args "lzma=${lzmaDir}" + } + + if(platform.operatingSystem.name == "windows") { + dependsOn "extract${platform.name}${buildOption}" + args "win32=${libDir}/tools/win32", + "win64=${libDir}/tools/win64" + } + environment JAVA_HOME: java_home + } + + assemble { + dependsOn "build${platform.name}${buildOption}" + } + } + } + } +} + +tasks.withType(JavaCompile) { + sourceCompatibility = "1.6" + targetCompatibility = "1.6" + + options.with { + encoding = "UTF-8" + bootClasspath = sourceSets.main.output.classesDir + } +} + +sourceSets { + main { + java { + srcDir 'classpath' + } + } +} + +javadoc { + title = "Avian v${version} Class Library API" +} + +task javadocJar(type: Jar) { + dependsOn javadoc + classifier = 'javadoc' + from { + javadoc.destinationDir + } +} + +jar { + baseName "classpath-avian" +} + +task downloadLzma(type: Exec) { + commandLine "curl" + args "--create-dirs", "-o", "${lzmaDir}/lzma920.tar.bz2", "-f", "http://oss.readytalk.com/avian-web/lzma920.tar.bz2" +} + +task extractLzma(type: Copy) { + dependsOn downloadLzma + from { + tarTree(resources.bzip2("${lzmaDir}/lzma920.tar.bz2")) + } + into lzmaDir +} + +task install { + dependsOn assemble, publish +} + +publishing { + repositories { + add(project.repositories."ivyLocal") + } + + publications { + + ivy(IvyPublication) { + from components.java + + artifact(javadocJar) + + artifact("vm.pro") { + name "vm" + type "proguard" + extension "pro" + } + + module "classpath-avian" + } + + create("tools-avian-${currentPlatformArch}", IvyPublication) { + module "tools-avian-${currentPlatformArch}" + + def publishBinSuffix = currentPlatform == "windows" ? "exe" : "bin" + def binSuffix = currentPlatform == "windows" ? ".exe" : "" + artifact("${buildDir}/${currentPlatform}-${currentArch}/binaryToObject/binaryToObject${binSuffix}") { + name "binaryToObject" + type publishBinSuffix + extension publishBinSuffix + } + } + + buildOptions.each { buildOption -> + platforms.each { platform -> + def binSuffix="" + def publishBinSuffix="bin" + + create("${platform.name}${buildOption}", IvyPublication) { + def nativeBuildDir = "${buildDir}/${platform.operatingSystem.name}-${platform.architecture.name}${buildOption}" + + if(platform.operatingSystem.name == "windows") { + publishBinSuffix = "exe" + binSuffix = ".${publishBinSuffix}" + } + + module "runtime-avian${buildOption}-${platform.name}" + + artifact("${nativeBuildDir}/avian${binSuffix}") { + name "avian" + type publishBinSuffix + extension publishBinSuffix + } + + artifact("${nativeBuildDir}/libavian.a") { + name "libavian" + type "a" + extension "a" + } + + if (buildOption == "-lzma") { + artifact("${nativeBuildDir}/libavian-lzma.a") { + name "libavian-lzma" + type "a" + extension "a" + } + + artifact("${nativeBuildDir}/lzma/lzma${binSuffix}") { + name "lzma" + type publishBinSuffix + extension publishBinSuffix + } + } + } + } + } + } +} + +artifactoryPublish { + onlyIf { + // TRAVIS_BRANCH reports master if it is a master build or a PR going to master + // TRAVIS_PULL_REQUEST reports false if not a pull request and the PR number if it is + System.env.'TRAVIS_BRANCH' == "master" && System.env.'TRAVIS_PULL_REQUEST' == "false" + } + dependsOn assemble +} + +artifactory { + contextUrl = "http://oss.jfrog.org" + + resolve { + repository { + repoKey = 'libs-releases' + } + } + + publish { + repository { + repoKey = 'oss-snapshot-local' + username = System.env.BINTRAY_USER + password = System.env.BINTRAY_API_KEY + ivy { + ivyLayout = "[organisation]/[module]/[revision]/ivy-[revision].xml" + } + } + + defaults { + platforms.each { + publications it.name + } + } + } +} + +task wrapper(type: Wrapper) { + distributionUrl = 'http://services.gradle.org/distributions/gradle-2.0-bin.zip' +} diff --git a/sgx-jvm/avian/classpath/avian/Addendum.java b/sgx-jvm/avian/classpath/avian/Addendum.java new file mode 100644 index 0000000000..79c9a75577 --- /dev/null +++ b/sgx-jvm/avian/classpath/avian/Addendum.java @@ -0,0 +1,17 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package avian; + +public class Addendum { + public Singleton pool; + public Object annotationTable; + public Object signature; +} diff --git a/sgx-jvm/avian/classpath/avian/AnnotationInvocationHandler.java b/sgx-jvm/avian/classpath/avian/AnnotationInvocationHandler.java new file mode 100644 index 0000000000..a15e716f2e --- /dev/null +++ b/sgx-jvm/avian/classpath/avian/AnnotationInvocationHandler.java @@ -0,0 +1,32 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package avian; + +import java.lang.reflect.Method; +import java.lang.reflect.InvocationHandler; + +public class AnnotationInvocationHandler implements InvocationHandler { + private Object[] data; + + public AnnotationInvocationHandler(Object[] data) { + this.data = data; + } + + public Object invoke(Object proxy, Method method, Object[] arguments) { + String name = method.getName(); + for (int i = 2; i < data.length; i += 2) { + if (name.equals(data[i])) { + return data[i + 1]; + } + } + return method.getDefaultValue(); + } +} diff --git a/sgx-jvm/avian/classpath/avian/Assembler.java b/sgx-jvm/avian/classpath/avian/Assembler.java new file mode 100644 index 0000000000..64a06fdf81 --- /dev/null +++ b/sgx-jvm/avian/classpath/avian/Assembler.java @@ -0,0 +1,135 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package avian; + +import static avian.Stream.write1; +import static avian.Stream.write2; +import static avian.Stream.write4; + +import avian.ConstantPool.PoolEntry; + +import java.util.List; +import java.io.OutputStream; +import java.io.IOException; + +public class Assembler { + public static final int ACC_PUBLIC = 1 << 0; + public static final int ACC_STATIC = 1 << 3; + + public static final int aaload = 0x32; + public static final int aastore = 0x53; + public static final int aload = 0x19; + public static final int aload_0 = 0x2a; + public static final int aload_1 = 0x2b; + public static final int astore_0 = 0x4b; + public static final int anewarray = 0xbd; + public static final int areturn = 0xb0; + public static final int dload = 0x18; + public static final int dreturn = 0xaf; + public static final int dup = 0x59; + public static final int fload = 0x17; + public static final int freturn = 0xae; + public static final int getfield = 0xb4; + public static final int goto_ = 0xa7; + public static final int iload = 0x15; + public static final int invokeinterface = 0xb9; + public static final int invokespecial = 0xb7; + public static final int invokestatic = 0xb8; + public static final int invokevirtual = 0xb6; + public static final int ireturn = 0xac; + public static final int jsr = 0xa8; + public static final int ldc_w = 0x13; + public static final int lload = 0x16; + public static final int lreturn = 0xad; + public static final int new_ = 0xbb; + public static final int pop = 0x57; + public static final int putfield = 0xb5; + public static final int ret = 0xa9; + public static final int return_ = 0xb1; + + public static void writeClass(OutputStream out, + List pool, + int name, + int super_, + int[] interfaces, + FieldData[] fields, + MethodData[] methods) + throws IOException + { + int codeAttributeName = ConstantPool.addUtf8(pool, "Code"); + + write4(out, 0xCAFEBABE); + write2(out, 0); // minor version + write2(out, 50); // major version + + write2(out, pool.size() + 1); + for (PoolEntry e: pool) { + e.writeTo(out); + } + + write2(out, ACC_PUBLIC); // flags + write2(out, name + 1); + write2(out, super_ + 1); + + write2(out, interfaces.length); + for (int i: interfaces) { + write2(out, i + 1); + } + + write2(out, fields.length); + for (FieldData f: fields) { + write2(out, f.flags); + write2(out, f.nameIndex + 1); + write2(out, f.specIndex + 1); + write2(out, 0); // attribute count + } + + write2(out, methods.length); + for (MethodData m: methods) { + write2(out, m.flags); + write2(out, m.nameIndex + 1); + write2(out, m.specIndex + 1); + + write2(out, 1); // attribute count + write2(out, codeAttributeName + 1); + write4(out, m.code.length); + out.write(m.code); + } + + write2(out, 0); // attribute count + } + + public static class MethodData { + public final int flags; + public final int nameIndex; + public final int specIndex; + public final byte[] code; + + public MethodData(int flags, int nameIndex, int specIndex, byte[] code) { + this.flags = flags; + this.nameIndex = nameIndex; + this.specIndex = specIndex; + this.code = code; + } + } + + public static class FieldData { + public final int flags; + public final int nameIndex; + public final int specIndex; + + public FieldData(int flags, int nameIndex, int specIndex) { + this.flags = flags; + this.nameIndex = nameIndex; + this.specIndex = specIndex; + } + } +} diff --git a/sgx-jvm/avian/classpath/avian/Atomic.java b/sgx-jvm/avian/classpath/avian/Atomic.java new file mode 100644 index 0000000000..53b52da665 --- /dev/null +++ b/sgx-jvm/avian/classpath/avian/Atomic.java @@ -0,0 +1,20 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package avian; + +import java.lang.reflect.Field; + +public class Atomic { + public static native long getOffset(Field field); + + public static native boolean compareAndSwapObject + (Object o, long offset, Object old, Object new_); +} diff --git a/sgx-jvm/avian/classpath/avian/Callback.java b/sgx-jvm/avian/classpath/avian/Callback.java new file mode 100644 index 0000000000..57c0976452 --- /dev/null +++ b/sgx-jvm/avian/classpath/avian/Callback.java @@ -0,0 +1,16 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package avian; + +public interface Callback { + public void handleResult(T result); + public void handleException(Throwable exception); +} diff --git a/sgx-jvm/avian/classpath/avian/Cell.java b/sgx-jvm/avian/classpath/avian/Cell.java new file mode 100644 index 0000000000..1425955fec --- /dev/null +++ b/sgx-jvm/avian/classpath/avian/Cell.java @@ -0,0 +1,54 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package avian; + +public class Cell { + public T value; + public Cell next; + + public Cell(T value, Cell next) { + this.value = value; + this.next = next; + } + + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("("); + for (Cell c = this; c != null; c = c.next) { + sb.append(value); + if (c.next != null) { + sb.append(" "); + } + } + sb.append(")"); + return sb.toString(); + } + + public static Cell cons(Car car, Cell cdr) { + return new Cell(car, cdr); + } + + public static boolean equal(T a, T b) { + return (a == null && b == null) || (a != null && a.equals(b)); + } + + public static boolean equal(Cell a, Cell b) { + while (a != null) { + if (b == null || (! equal(a.value, b.value))) { + return false; + } + a = a.next; + b = b.next; + } + + return b == null; + } +} diff --git a/sgx-jvm/avian/classpath/avian/ClassAddendum.java b/sgx-jvm/avian/classpath/avian/ClassAddendum.java new file mode 100644 index 0000000000..ef558b59c4 --- /dev/null +++ b/sgx-jvm/avian/classpath/avian/ClassAddendum.java @@ -0,0 +1,32 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package avian; + +public class ClassAddendum extends Addendum { + public Object[] interfaceTable; + public InnerClassReference[] innerClassTable; + /** + * If this value is negative, all the methods in VMClass.methodTable + * were declared in that class. Otherwise, only the first + * declaredMethodCount methods in that table were declared in that + * class, while the rest were declared in interfaces implemented or + * extended by that class. + */ + public int declaredMethodCount; + + public byte[] enclosingClass; + + public Pair enclosingMethod; + + public VMMethod[] bootstrapMethodTable; + + public VMMethod[] bootstrapLambdaTable; +} diff --git a/sgx-jvm/avian/classpath/avian/Classes.java b/sgx-jvm/avian/classpath/avian/Classes.java new file mode 100644 index 0000000000..b55408834c --- /dev/null +++ b/sgx-jvm/avian/classpath/avian/Classes.java @@ -0,0 +1,604 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package avian; + +import static avian.Stream.read1; +import static avian.Stream.read2; + +import java.net.URL; +import java.net.MalformedURLException; +import java.security.CodeSource; +import java.security.AllPermission; +import java.security.Permissions; +import java.security.ProtectionDomain; +import java.security.cert.Certificate; +import java.lang.reflect.Modifier; +import java.lang.reflect.Method; +import java.lang.reflect.Field; +import java.lang.reflect.Proxy; +import java.lang.annotation.Annotation; +import java.io.InputStream; +import java.io.ByteArrayInputStream; +import java.io.IOException; + +public class Classes { + private static final int LinkFlag = 1 << 8; + + public static native VMClass defineVMClass + (ClassLoader loader, byte[] b, int offset, int length); + + public static native VMClass primitiveClass(char name); + + public static native void initialize(VMClass vmClass); + + public static native boolean isAssignableFrom(VMClass a, VMClass b); + + public static native VMClass getVMClass(Object o); + + public static native VMClass toVMClass(Class c); + + public static native VMMethod toVMMethod(Method m); + + private static native VMClass resolveVMClass(ClassLoader loader, byte[] spec) + throws ClassNotFoundException; + + public static VMClass loadVMClass(ClassLoader loader, + byte[] nameBytes, int offset, int length) + { + byte[] spec = new byte[length + 1]; + System.arraycopy(nameBytes, offset, spec, 0, length); + + try { + VMClass c = resolveVMClass(loader, spec); + if (c == null) { + throw new NoClassDefFoundError(); + } + return c; + } catch (ClassNotFoundException e) { + NoClassDefFoundError error = new NoClassDefFoundError + (new String(nameBytes, offset, length)); + error.initCause(e); + throw error; + } + } + + private static Object parseAnnotationValue(ClassLoader loader, + Object pool, + InputStream in) + throws IOException + { + switch (read1(in)) { + case 'Z': + return Boolean.valueOf(Singleton.getInt(pool, read2(in) - 1) != 0); + + case 'B': + return Byte.valueOf((byte) Singleton.getInt(pool, read2(in) - 1)); + + case 'C': + return Character.valueOf((char) Singleton.getInt(pool, read2(in) - 1)); + + case 'S': + return Short.valueOf((short) Singleton.getInt(pool, read2(in) - 1)); + + case 'I': + return Integer.valueOf(Singleton.getInt(pool, read2(in) - 1)); + + case 'F': + return Float.valueOf + (Float.intBitsToFloat(Singleton.getInt(pool, read2(in) - 1))); + + case 'J': { + return Long.valueOf(Singleton.getLong(pool, read2(in) - 1)); + } + + case 'D': { + return Double.valueOf + (Double.longBitsToDouble(Singleton.getLong(pool, read2(in) - 1))); + } + + case 's': { + byte[] data = (byte[]) Singleton.getObject(pool, read2(in) - 1); + + return new String(data, 0, data.length - 1); + } + + case 'e': { + byte[] typeName = (byte[]) Singleton.getObject(pool, read2(in) - 1); + byte[] name = (byte[]) Singleton.getObject(pool, read2(in) - 1); + + return Enum.valueOf + (SystemClassLoader.getClass + (loadVMClass(loader, typeName, 1, typeName.length - 3)), + new String(name, 0, name.length - 1)); + } + + case 'c':{ + byte[] name = (byte[]) Singleton.getObject(pool, read2(in) - 1); + + return SystemClassLoader.getClass + (loadVMClass(loader, name, 1, name.length - 3)); + } + + case '@': + return getAnnotation(loader, parseAnnotation(loader, pool, in)); + + case '[': { + Object[] array = new Object[read2(in)]; + for (int i = 0; i < array.length; ++i) { + array[i] = parseAnnotationValue(loader, pool, in); + } + return array; + } + + default: throw new AssertionError(); + } + } + + private static Object[] parseAnnotation(ClassLoader loader, + Object pool, + InputStream in) + throws IOException + { + byte[] typeName = (byte[]) Singleton.getObject(pool, read2(in) - 1); + Object[] annotation = new Object[(read2(in) + 1) * 2]; + annotation[1] = SystemClassLoader.getClass + (loadVMClass(loader, typeName, 1, typeName.length - 3)); + + for (int i = 2; i < annotation.length; i += 2) { + byte[] name = (byte[]) Singleton.getObject(pool, read2(in) - 1); + annotation[i] = new String(name, 0, name.length - 1); + annotation[i + 1] = parseAnnotationValue(loader, pool, in); + } + + return annotation; + } + + private static Object[] parseAnnotationTable(ClassLoader loader, + Object pool, + InputStream in) + throws IOException + { + Object[] table = new Object[read2(in)]; + for (int i = 0; i < table.length; ++i) { + table[i] = parseAnnotation(loader, pool, in); + } + return table; + } + + private static void parseAnnotationTable(ClassLoader loader, + Addendum addendum) + { + if (addendum != null && addendum.annotationTable instanceof byte[]) { + try { + addendum.annotationTable = parseAnnotationTable + (loader, addendum.pool, new ByteArrayInputStream + ((byte[]) addendum.annotationTable)); + } catch (IOException e) { + AssertionError error = new AssertionError(); + error.initCause(e); + throw error; + } + } + } + + private static int resolveSpec(ClassLoader loader, byte[] spec, int start) { + int result; + int end; + switch (spec[start]) { + case 'L': + ++ start; + end = start; + while (spec[end] != ';') ++ end; + result = end + 1; + break; + + case '[': + end = start + 1; + while (spec[end] == '[') ++ end; + switch (spec[end]) { + case 'L': + ++ end; + while (spec[end] != ';') ++ end; + ++ end; + break; + + default: + ++ end; + } + result = end; + break; + + default: + return start + 1; + } + + loadVMClass(loader, spec, start, end - start); + + return result; + } + + private static int declaredMethodCount(VMClass c) { + ClassAddendum a = c.addendum; + if (a != null) { + int count = a.declaredMethodCount; + if (count >= 0) { + return count; + } + } + VMMethod[] table = c.methodTable; + return table == null ? 0 : table.length; + } + + public static void link(VMClass c, ClassLoader loader) { + acquireClassLock(); + try { + if ((c.vmFlags & LinkFlag) == 0) { + if (c.super_ != null) { + link(c.super_, loader); + } + + parseAnnotationTable(loader, c.addendum); + + if (c.interfaceTable != null) { + int stride = ((c.flags & Modifier.INTERFACE) != 0 ? 1 : 2); + for (int i = 0; i < c.interfaceTable.length; i += stride) { + link((VMClass) c.interfaceTable[i], loader); + } + } + + VMMethod[] methodTable = c.methodTable; + if (methodTable != null) { + for (int i = 0; i < methodTable.length; ++i) { + VMMethod m = methodTable[i]; + + for (int j = 1; j < m.spec.length;) { + j = resolveSpec(loader, m.spec, j); + } + + parseAnnotationTable(loader, m.addendum); + } + } + + if (c.fieldTable != null) { + for (int i = 0; i < c.fieldTable.length; ++i) { + VMField f = c.fieldTable[i]; + + resolveSpec(loader, f.spec, 0); + + parseAnnotationTable(loader, f.addendum); + } + } + + c.vmFlags |= LinkFlag; + } + } finally { + releaseClassLock(); + } + } + + public static void link(VMClass c) { + link(c, c.loader); + } + + public static Class forName(String name, boolean initialize, + ClassLoader loader) + throws ClassNotFoundException + { + if (loader == null) { + loader = Class.class.getClassLoader(); + } + Class c = loader.loadClass(name); + VMClass vmc = SystemClassLoader.vmClass(c); + link(vmc, loader); + if (initialize) { + initialize(vmc); + } + return c; + } + + public static Class forCanonicalName(String name) { + return forCanonicalName(null, name); + } + + public static Class forCanonicalName(ClassLoader loader, String name) { + try { + if (name.startsWith("[")) { + return forName(name, true, loader); + } else if (name.startsWith("L")) { + return forName(name.substring(1, name.length() - 1), true, loader); + } else { + if (name.length() == 1) { + return SystemClassLoader.getClass + (primitiveClass(name.charAt(0))); + } else { + throw new ClassNotFoundException(name); + } + } + } catch (ClassNotFoundException e) { + throw new RuntimeException(e); + } + } + + private static int next(char c, String s, int start) { + for (int i = start; i < s.length(); ++i) { + if (s.charAt(i) == c) return i; + } + throw new RuntimeException(); + } + + public static Class[] getParameterTypes(VMMethod vmMethod) { + int count = vmMethod.parameterCount; + + Class[] types = new Class[count]; + int index = 0; + + String spec = new String + (vmMethod.spec, 1, vmMethod.spec.length - 2); + + try { + for (int i = 0; i < spec.length(); ++i) { + char c = spec.charAt(i); + if (c == ')') { + break; + } else if (c == 'L') { + int start = i + 1; + i = next(';', spec, start); + String name = spec.substring(start, i).replace('/', '.'); + types[index++] = Class.forName(name, true, vmMethod.class_.loader); + } else if (c == '[') { + int start = i; + while (spec.charAt(i) == '[') ++i; + + if (spec.charAt(i) == 'L') { + i = next(';', spec, i + 1); + String name = spec.substring(start, i).replace('/', '.'); + types[index++] = Class.forName + (name, true, vmMethod.class_.loader); + } else { + String name = spec.substring(start, i + 1); + types[index++] = forCanonicalName(vmMethod.class_.loader, name); + } + } else { + String name = spec.substring(i, i + 1); + types[index++] = forCanonicalName(vmMethod.class_.loader, name); + } + } + } catch (ClassNotFoundException e) { + throw new RuntimeException(e); + } + + return types; + } + + public static int findField(VMClass vmClass, String name) { + if (vmClass.fieldTable != null) { + link(vmClass); + + for (int i = 0; i < vmClass.fieldTable.length; ++i) { + if (toString(vmClass.fieldTable[i].name).equals(name)) { + return i; + } + } + } + return -1; + } + + public static String toString(byte[] array) { + return new String(array, 0, array.length - 1); + } + + private static boolean match(VMClass a, VMClass b) { + // TODO: in theory we should be able to just do an == comparison + // here instead of recursively comparing array element types. + // However, the VM currently can create multiple array classes for + // the same element type. We should fix that so that there's only + // ever one of each per classloader, eliminating the need for a + // recursive comparison. See also the native implementation of + // isAssignableFrom. + if (a.arrayDimensions > 0) { + return match(a.arrayElementClass, b.arrayElementClass); + } else { + return a == b; + } + } + + public static boolean match(Class[] a, Class[] b) { + if (a.length == b.length) { + for (int i = 0; i < a.length; ++i) { + if (! match(toVMClass(a[i]), toVMClass(b[i]))) { + return false; + } + } + return true; + } else { + return false; + } + } + + public static VMMethod findMethod(ClassLoader loader, + String class_, + String name, + String spec) + throws ClassNotFoundException + { + VMClass c = SystemClassLoader.vmClass(loader.loadClass(class_)); + VMMethod[] methodTable = c.methodTable; + if (methodTable != null) { + link(c); + + for (int i = 0; i < methodTable.length; ++i) { + VMMethod m = methodTable[i]; + if (toString(m.name).equals(name) && toString(m.spec).equals(spec)) { + return m; + } + } + } + return null; + } + + public static int findMethod(VMClass vmClass, String name, + Class[] parameterTypes) + { + VMMethod[] methodTable = vmClass.methodTable; + if (methodTable != null) { + link(vmClass); + + if (parameterTypes == null) { + parameterTypes = new Class[0]; + } + + for (int i = 0; i < methodTable.length; ++i) { + VMMethod m = methodTable[i]; + if (toString(m.name).equals(name) + && match(parameterTypes, getParameterTypes(m))) + { + return i; + } + } + } + return -1; + } + + public static int countMethods(VMClass vmClass, boolean publicOnly) { + int count = 0; + VMMethod[] methodTable = vmClass.methodTable; + if (methodTable != null) { + for (int i = 0, j = declaredMethodCount(vmClass); i < j; ++i) { + VMMethod m = methodTable[i]; + if (((! publicOnly) || ((m.flags & Modifier.PUBLIC)) != 0) + && (! toString(m.name).startsWith("<"))) + { + ++ count; + } + } + } + return count; + } + + public static Method[] getMethods(VMClass vmClass, boolean publicOnly) { + Method[] array = new Method[countMethods(vmClass, publicOnly)]; + VMMethod[] methodTable = vmClass.methodTable; + if (methodTable != null) { + link(vmClass); + + int ai = 0; + for (int i = 0, j = declaredMethodCount(vmClass); i < j; ++i) { + VMMethod m = methodTable[i]; + if (((! publicOnly) || ((m.flags & Modifier.PUBLIC) != 0)) + && ! toString(m.name).startsWith("<")) + { + array[ai++] = makeMethod(SystemClassLoader.getClass(vmClass), i); + } + } + } + + return array; + } + + public static int countFields(VMClass vmClass, boolean publicOnly) { + int count = 0; + if (vmClass.fieldTable != null) { + for (int i = 0; i < vmClass.fieldTable.length; ++i) { + if ((! publicOnly) + || ((vmClass.fieldTable[i].flags & Modifier.PUBLIC)) + != 0) + { + ++ count; + } + } + } + return count; + } + + public static Field[] getFields(VMClass vmClass, boolean publicOnly) { + Field[] array = new Field[countFields(vmClass, publicOnly)]; + if (vmClass.fieldTable != null) { + link(vmClass); + + int ai = 0; + for (int i = 0; i < vmClass.fieldTable.length; ++i) { + if (((vmClass.fieldTable[i].flags & Modifier.PUBLIC) != 0) + || (! publicOnly)) + { + array[ai++] = makeField(SystemClassLoader.getClass(vmClass), i); + } + } + } + + return array; + } + + public static Annotation getAnnotation(ClassLoader loader, Object[] a) { + if (a[0] == null) { + a[0] = Proxy.newProxyInstance + (loader, new Class[] { (Class) a[1] }, + new AnnotationInvocationHandler(a)); + } + return (Annotation) a[0]; + } + + public static Object getAnnotationDefaultValue(ClassLoader loader, + MethodAddendum addendum) { + if (addendum == null) { + return null; + } + byte[] annotationDefault = (byte[]) addendum.annotationDefault; + if (annotationDefault == null) { + return null; + } + try { + return parseAnnotationValue(loader, addendum.pool, + new ByteArrayInputStream(annotationDefault)); + } catch (IOException e) { + AssertionError error = new AssertionError(); + error.initCause(e); + throw error; + } + } + + private static int index(VMMethod m) { + VMMethod[] table = m.class_.methodTable; + for (int i = 0; i < table.length; ++i) { + if (m == table[i]) return i; + } + throw new AssertionError(); + } + + public static Method makeMethod(VMMethod m) { + return makeMethod(SystemClassLoader.getClass(m.class_), index(m)); + } + + public static ProtectionDomain getProtectionDomain(VMClass c) { + CodeSource source = null; + if (c.source != null) { + try { + source = new CodeSource + (new URL(new String(c.source, 0, c.source.length - 1)), + (Certificate[]) null); + } catch (MalformedURLException ignored) { } + } + + Permissions p = new Permissions(); + p.add(new AllPermission()); + + return new ProtectionDomain(source, p); + } + + public static native Method makeMethod(Class c, int slot); + + public static native Field makeField(Class c, int slot); + + private static native void acquireClassLock(); + + private static native void releaseClassLock(); + + public static native String makeString(byte[] array, int offset, int length); +} diff --git a/sgx-jvm/avian/classpath/avian/Code.java b/sgx-jvm/avian/classpath/avian/Code.java new file mode 100644 index 0000000000..957099107d --- /dev/null +++ b/sgx-jvm/avian/classpath/avian/Code.java @@ -0,0 +1,5 @@ +package avian; + +abstract class Code { + // VM-visible fields in types.def +} diff --git a/sgx-jvm/avian/classpath/avian/ConstantPool.java b/sgx-jvm/avian/classpath/avian/ConstantPool.java new file mode 100644 index 0000000000..f795c19e7e --- /dev/null +++ b/sgx-jvm/avian/classpath/avian/ConstantPool.java @@ -0,0 +1,242 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package avian; + +import static avian.Stream.write1; +import static avian.Stream.write2; +import static avian.Stream.write4; + +import java.util.List; +import java.io.OutputStream; +import java.io.IOException; + +public class ConstantPool { + private static final int CONSTANT_Integer = 3; + private static final int CONSTANT_Utf8 = 1; + private static final int CONSTANT_String = 8; + private static final int CONSTANT_Class = 7; + private static final int CONSTANT_NameAndType = 12; + private static final int CONSTANT_Fieldref = 9; + private static final int CONSTANT_Methodref = 10; + + public static int add(List pool, PoolEntry e) { + int i = 0; + for (PoolEntry existing: pool) { + if (existing.equals(e)) { + return i; + } else { + ++i; + } + } + pool.add(e); + return pool.size() - 1; + } + + public static int addInteger(List pool, int value) { + return add(pool, new IntegerPoolEntry(value)); + } + + public static int addUtf8(List pool, String value) { + return add(pool, new Utf8PoolEntry(value)); + } + + public static int addString(List pool, String value) { + return add(pool, new StringPoolEntry(addUtf8(pool, value))); + } + + public static int addClass(List pool, String name) { + return add(pool, new ClassPoolEntry(addUtf8(pool, name))); + } + + public static int addNameAndType(List pool, + String name, + String type) + { + return add(pool, new NameAndTypePoolEntry + (addUtf8(pool, name), + addUtf8(pool, type))); + } + + public static int addFieldRef(List pool, + String className, + String name, + String spec) + { + return add(pool, new FieldRefPoolEntry + (addClass(pool, className), + addNameAndType(pool, name, spec))); + } + + public static int addMethodRef(List pool, + String className, + String name, + String spec) + { + return add(pool, new MethodRefPoolEntry + (addClass(pool, className), + addNameAndType(pool, name, spec))); + } + + public interface PoolEntry { + public void writeTo(OutputStream out) throws IOException; + } + + private static class IntegerPoolEntry implements PoolEntry { + private final int value; + + public IntegerPoolEntry(int value) { + this.value = value; + } + + public void writeTo(OutputStream out) throws IOException { + write1(out, CONSTANT_Integer); + write4(out, value); + } + + public boolean equals(Object o) { + return o instanceof IntegerPoolEntry + && ((IntegerPoolEntry) o).value == value; + } + } + + private static class Utf8PoolEntry implements PoolEntry { + private final String data; + + public Utf8PoolEntry(String data) { + this.data = data; + } + + public void writeTo(OutputStream out) throws IOException { + write1(out, CONSTANT_Utf8); + byte[] bytes = data.getBytes(); + write2(out, bytes.length); + out.write(bytes); + } + + public boolean equals(Object o) { + return o instanceof Utf8PoolEntry + && ((Utf8PoolEntry) o).data.equals(data); + } + } + + private static class StringPoolEntry implements PoolEntry { + private final int valueIndex; + + public StringPoolEntry(int valueIndex) { + this.valueIndex = valueIndex; + } + + public void writeTo(OutputStream out) throws IOException { + write1(out, CONSTANT_String); + write2(out, valueIndex + 1); + } + + public boolean equals(Object o) { + return o instanceof StringPoolEntry + && ((StringPoolEntry) o).valueIndex == valueIndex; + } + } + + private static class ClassPoolEntry implements PoolEntry { + private final int nameIndex; + + public ClassPoolEntry(int nameIndex) { + this.nameIndex = nameIndex; + } + + public void writeTo(OutputStream out) throws IOException { + write1(out, CONSTANT_Class); + write2(out, nameIndex + 1); + } + + public boolean equals(Object o) { + return o instanceof ClassPoolEntry + && ((ClassPoolEntry) o).nameIndex == nameIndex; + } + } + + private static class NameAndTypePoolEntry implements PoolEntry { + private final int nameIndex; + private final int typeIndex; + + public NameAndTypePoolEntry(int nameIndex, int typeIndex) { + this.nameIndex = nameIndex; + this.typeIndex = typeIndex; + } + + public void writeTo(OutputStream out) throws IOException { + write1(out, CONSTANT_NameAndType); + write2(out, nameIndex + 1); + write2(out, typeIndex + 1); + } + + public boolean equals(Object o) { + if (o instanceof NameAndTypePoolEntry) { + NameAndTypePoolEntry other = (NameAndTypePoolEntry) o; + return other.nameIndex == nameIndex && other.typeIndex == typeIndex; + } else { + return false; + } + } + } + + private static class FieldRefPoolEntry implements PoolEntry { + private final int classIndex; + private final int nameAndTypeIndex; + + public FieldRefPoolEntry(int classIndex, int nameAndTypeIndex) { + this.classIndex = classIndex; + this.nameAndTypeIndex = nameAndTypeIndex; + } + + public void writeTo(OutputStream out) throws IOException { + write1(out, CONSTANT_Fieldref); + write2(out, classIndex + 1); + write2(out, nameAndTypeIndex + 1); + } + + public boolean equals(Object o) { + if (o instanceof FieldRefPoolEntry) { + FieldRefPoolEntry other = (FieldRefPoolEntry) o; + return other.classIndex == classIndex + && other.nameAndTypeIndex == nameAndTypeIndex; + } else { + return false; + } + } + } + + private static class MethodRefPoolEntry implements PoolEntry { + private final int classIndex; + private final int nameAndTypeIndex; + + public MethodRefPoolEntry(int classIndex, int nameAndTypeIndex) { + this.classIndex = classIndex; + this.nameAndTypeIndex = nameAndTypeIndex; + } + + public void writeTo(OutputStream out) throws IOException { + write1(out, CONSTANT_Methodref); + write2(out, classIndex + 1); + write2(out, nameAndTypeIndex + 1); + } + + public boolean equals(Object o) { + if (o instanceof MethodRefPoolEntry) { + MethodRefPoolEntry other = (MethodRefPoolEntry) o; + return other.classIndex == classIndex + && other.nameAndTypeIndex == nameAndTypeIndex; + } else { + return false; + } + } + } +} diff --git a/sgx-jvm/avian/classpath/avian/Continuations.java b/sgx-jvm/avian/classpath/avian/Continuations.java new file mode 100644 index 0000000000..2c930970b0 --- /dev/null +++ b/sgx-jvm/avian/classpath/avian/Continuations.java @@ -0,0 +1,327 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package avian; + +import java.util.concurrent.Callable; + +/** + * This class provides methods to capture continuations and manage + * control flow when calling continuations. + * + *

A continuation is a snapshot of a thread's call stack which can + * be captured via callWithCurrentContinuation and later + * restored any number of times. The program may restore this + * snapshot by either feeding it a result (to be returned by + * callWithCurrentContinuation) or feeding it an + * exception (to be thrown by + * callWithCurrentContinuation). Continuations may be + * used to implement features such as coroutines, generators, and + * cooperative multitasking. + * + *

This class provides two static methods, + * callWithCurrentContinuation and + * dynamicWind, with similar semantics to the Scheme + * functions call-with-current-continuation and + * dynamic-wind, respectively. In addition, we define + * how continuations work with respect to native code, exceptions, + * try/finally blocks, synchronized blocks, and multithreading. + * + *

Continuations and Continuation Contexts

+ * + *

A continuation can be thought of as a singly-linked list of + * stack frames representing the call trace, where the head of the + * list is the frame of the method most recently called (i.e. the top + * of the stack). However, this trace only extends as far as the most + * recent chain of Java frames - it ends just prior to the most recent + * native frame in the stack. The reason for this is that the VM + * cannot, in general, safely capture and restore native frames. + * Therefore, each call from native code to Java (including the + * original invocation of main(String[]) or + * Thread.run()) represents a new continuation context in + * which continuations may be captured, and these will only contain + * frames from within that context. + * + *

Calling a continuation (i.e. feeding it a result or exception) + * causes the current continuation to be replaced with the called + * continuation. When the last method in this new continuation + * returns, it returns to the native frame which created the current + * context, which may or may not be the same as the context in which + * that continuation was created. + * + *

We define the return type of a continuation context as the + * return type of the first method called in that context. A + * continuation may be called from a different context than the one in + * which it was created, provided the return type of the latter is + * compatible with the current context. + * + *

Given a thread executing in context "A" which wants to call a + * continuation created in context "B", the following rules apply: + * + *

    + * + *
  • If the return type of "A" is void, the return + * type of "B" may be anything, including void
  • + * + *
  • If the return type of "A" is a primitive type, the return + * type of "B" must match exactly
  • + * + *
  • If the return type of "A" is an object type, that type must + * be assignable from the return type of "B" (i.e. the latter must + * either be the same as the former or a superclass or + * superinterface of it)
  • + * + *
+ * + *

A thread may call a continuation created by a different thread + * provided the return types are compatible. Multiple threads may + * safely call the same continuation simultaneously without + * synchronization. Any attempt to call a continuation from a context + * with an incompatible return type will throw an {@link + * avian.IncompatibleContinuationException}. + * + *

Winding, Unwinding, and Rewinding

+ * + *

Traditionally, Java provides one way to wind the execution stack + * (method calls) and two ways to unwind it (normal returns and + * exception unwinding). With continuations, we add a new way to + * rewind the stack and a new way to unwind it. + * + *

The call stack of a continuation may share frames with other + * continuations - in which case they share a common history. When + * calling a continuation "B" from the current continuation "A", the + * VM must unwind past any frames which are in "A" but not in "B" and + * rewind past any frames in "B" but not in "A". During this + * unwinding and rewinding, control may pass through synchronized and + * try/finally blocks while going down the old stack and up the new + * stack. + * + *

However, unlike the traditional processes of winding and + * unwinding, the VM will ignore these blocks - monitors will not be + * released or acquired and finally blocks will not execute. This is + * by design. The purpose of such a block is to acquire a resource, + * such as a file handle or monitor, once before executing a task and + * release it after the task is finished, regardless of how often the + * task might temporarily yield control to other continuations. + * + *

Alternatively, one might wish to acquire and release a resource + * each time control (re)winds to or unwinds from a continuation, + * respectively. In this case, one may use dynamicWind + * to register functions which will run every time that frame is + * passed, regardless of how the stack is wound or unwound. + */ +public class Continuations { + private Continuations() { } + + private static final ThreadLocal latestReset = new ThreadLocal(); + + /** + * Captures the current continuation, passing a reference to the + * specified receiver. + * + *

This method will either return the result returned by + * receiver.call(Callback), propagate the exception + * thrown by that method, return the result passed to the + * handleResult(T) method of the continuation, or throw the + * exception passed to the handleException(Throwable) method of the + * continuation. + */ + public static native T callWithCurrentContinuation + (Function,T> receiver) throws Exception; + + /** + * Calls the specified "before" and "after" tasks each time a + * continuation containing the call is wound or unwound, + * respectively. + * + *

This method first calls before.run(), then + * thunk.call(), and finally after.run(), + * returning the result of the second call. If + * before.run() does not return normally, the second + * and third calls will not happen. If thunk.call() + * throws an exception, after.run(), will be called + * before the exception is propagated. + * + *

If thunk.call() calls a continuation (directly or + * via a subroutine) which does not include the current call to + * dynamicWind, after.run() will be called + * before control passes to that continuation. If this call throws + * an exception, the exception will propagate to the current caller + * of dynamicWind. + * + *

If thunk.call() creates a continuation which is + * later called from a continuation which does not include the + * current call to dynamicWind, + * before.run() will be called before control passes to + * that continuation. As above, if this call throws an exception, + * the exception will propagate to the current caller of + * dynamicWind. + */ + public static T dynamicWind(Runnable before, + Callable thunk, + Runnable after) + throws Exception + { + UnwindResult result = dynamicWind2(before, thunk, after); + if (result.continuation != null) { + after.run(); + if (result.exception != null) { + result.continuation.handleException(result.exception); + } else { + result.continuation.handleResult(result.result); + } + throw new AssertionError(); + } else { + return (T) result.result; + } + } + + public static C reset(final Callable thunk) throws Exception { + final Reset reset = new Reset(latestReset.get()); + latestReset.set(reset); + try { + Object result = callWithCurrentContinuation + (new Function,Object>() { + public Object call(Callback continuation) throws Exception { + reset.continuation = continuation; + return thunk.call(); + } + }); + + while (true) { + Cell shift = reset.shifts; + if (shift != null) { + reset.shifts = shift.next; + result = shift.value.call(result); + } else { + return (C) result; + } + } + } finally { + latestReset.set(reset.next); + } + } + + public static A shift + (final Function,C> receiver) + throws Exception + { + return (A) callWithCurrentContinuation + (new Function,Object>() { + public Object call(final Callback continuation) { + final Reset reset = latestReset.get(); + reset.shifts = new Cell(new Function() { + public Object call(Object ignored) throws Exception { + return receiver.call + (new Function() { + public Object call(final Object argument) + throws Exception + { + return callWithCurrentContinuation + (new Function,Object>() { + public Object call + (final Callback shiftContinuation) + throws Exception + { + reset.shifts = new Cell + (new Function() { + public Object call(Object result) + throws Exception + { + shiftContinuation.handleResult(result); + throw new AssertionError(); + } + }, + reset.shifts); + + continuation.handleResult(argument); + throw new AssertionError(); + } + }); + } + }); + } + + public void handleException(Throwable exception) { + throw new AssertionError(); + } + }, reset.shifts); + + reset.continuation.handleResult(null); + throw new AssertionError(); + } + }); + } + + private static native UnwindResult dynamicWind2(Runnable before, + Callable thunk, + Runnable after) + throws Exception; + + private static UnwindResult wind(Runnable before, + Callable thunk, + Runnable after) + throws Exception + { + before.run(); + + try { + return new UnwindResult(null, thunk.call(), null); + } finally { + after.run(); + } + } + + private static void rewind(Runnable before, + Callback continuation, + Object result, + Throwable exception) + throws Exception + { + before.run(); + + if (exception != null) { + continuation.handleException(exception); + } else { + continuation.handleResult(result); + } + + throw new AssertionError(); + } + + private static class Continuation implements Callback { + public native void handleResult(T result); + public native void handleException(Throwable exception); + } + + private static class UnwindResult { + public final Continuation continuation; + public final Object result; + public final Throwable exception; + + public UnwindResult(Continuation continuation, Object result, + Throwable exception) + { + this.continuation = continuation; + this.result = result; + this.exception = exception; + } + } + + private static class Reset { + public Callback continuation; + public final Reset next; + public Cell shifts; + + public Reset(Reset next) { + this.next = next; + } + } +} diff --git a/sgx-jvm/avian/classpath/avian/Data.java b/sgx-jvm/avian/classpath/avian/Data.java new file mode 100644 index 0000000000..0914362e83 --- /dev/null +++ b/sgx-jvm/avian/classpath/avian/Data.java @@ -0,0 +1,310 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package avian; + +import java.util.Map; +import java.util.Map.Entry; +import java.util.AbstractSet; +import java.util.Collection; +import java.util.Iterator; +import java.util.Collections; + +public class Data { + public static int nextPowerOfTwo(int n) { + int r = 1; + while (r < n) r <<= 1; + return r; + } + + public static boolean equal(V a, V b) { + return a == null ? b == null : a.equals(b); + } + + public static T[] toArray(Collection collection, T[] array) { + Class c = array.getClass().getComponentType(); + + if (array.length < collection.size()) { + array = (T[]) java.lang.reflect.Array.newInstance(c, collection.size()); + } + + int i = 0; + for (Object o: collection) { + if (c.isInstance(o)) { + array[i++] = (T) o; + } else { + throw new ArrayStoreException(); + } + } + + return array; + } + + public static String toString(Collection c) { + StringBuilder sb = new StringBuilder(); + sb.append("["); + for (Iterator it = c.iterator(); it.hasNext();) { + sb.append(it.next()); + if (it.hasNext()) { + sb.append(","); + } + } + sb.append("]"); + return sb.toString(); + } + + public static String toString(Map m) { + StringBuilder sb = new StringBuilder(); + sb.append("{"); + for (Iterator it = m.entrySet().iterator(); it.hasNext();) { + Entry e = it.next(); + sb.append(e.getKey()) + .append("=") + .append(e.getValue()); + if (it.hasNext()) { + sb.append(","); + } + } + sb.append("}"); + return sb.toString(); + } + + public interface EntryMap { + public int size(); + + public Entry find(Object key); + + public Entry remove(Object key); + + public void clear(); + + public Iterator> iterator(); + } + + public static class EntrySet extends AbstractSet> { + private final EntryMap map; + + public EntrySet(EntryMap map) { + this.map = map; + } + + public int size() { + return map.size(); + } + + public boolean isEmpty() { + return map.size() == 0; + } + + public boolean contains(Object o) { + return (o instanceof Entry) + && map.find(((Entry)o).getKey()) != null; + } + + public boolean add(Entry e) { + throw new UnsupportedOperationException(); + } + + public boolean remove(Object o) { + return (o instanceof Entry) + && map.remove(((Entry) o).getKey()) != null; + } + + public boolean remove(Entry e) { + return map.remove(e.getKey()) != null; + } + + public Object[] toArray() { + return toArray(new Object[size()]); + } + + public T[] toArray(T[] array) { + return Data.toArray(this, array); + } + + public void clear() { + map.clear(); + } + + public Iterator> iterator() { + return map.iterator(); + } + } + + public static class KeySet extends AbstractSet { + private final EntryMap map; + + public KeySet(EntryMap map) { + this.map = map; + } + + public int size() { + return map.size(); + } + + public boolean isEmpty() { + return map.size() == 0; + } + + public boolean contains(Object key) { + return map.find(key) != null; + } + + public boolean add(K key) { + throw new UnsupportedOperationException(); + } + + public boolean remove(Object key) { + return map.remove(key) != null; + } + + public Object[] toArray() { + return toArray(new Object[size()]); + } + + public T[] toArray(T[] array) { + return Data.toArray(this, array); + } + + public void clear() { + map.clear(); + } + + public Iterator iterator() { + return new KeyIterator(map.iterator()); + } + } + + public static class Values implements Collection { + private final EntryMap map; + + public Values(EntryMap map) { + this.map = map; + } + + public int size() { + return map.size(); + } + + public boolean isEmpty() { + return map.size() == 0; + } + + public boolean contains(Object value) { + for (Iterator> it = map.iterator(); it.hasNext();) { + if (equal(it.next().getValue(), value)) { + return true; + } + } + return false; + } + + public boolean containsAll(Collection c) { + if (c == null) { + throw new NullPointerException("collection is null"); + } + + for (Iterator it = c.iterator(); it.hasNext();) { + if (! contains(it.next())) { + return false; + } + } + + return true; + } + + public boolean add(V value) { + throw new UnsupportedOperationException(); + } + + public boolean addAll(Collection collection) { + throw new UnsupportedOperationException(); + } + + public boolean remove(Object value) { + for (Iterator> it = map.iterator(); + it.hasNext();) + { + if (equal(it.next().getValue(), value)) { + it.remove(); + return true; + } + } + return false; + } + + public boolean removeAll(Collection c) { + boolean changed = false; + for (Iterator> it = map.iterator(); it.hasNext();) { + if (c.contains(it.next().getValue())) { + it.remove(); + changed = true; + } + } + return changed; + } + + public Object[] toArray() { + return toArray(new Object[size()]); + } + + public T[] toArray(T[] array) { + return Data.toArray(this, array); + } + + public void clear() { + map.clear(); + } + + public Iterator iterator() { + return new ValueIterator(map.iterator()); + } + } + + public static class KeyIterator implements Iterator { + private final Iterator> it; + + public KeyIterator(Iterator> it) { + this.it = it; + } + + public K next() { + return it.next().getKey(); + } + + public boolean hasNext() { + return it.hasNext(); + } + + public void remove() { + it.remove(); + } + } + + public static class ValueIterator implements Iterator { + private final Iterator> it; + + public ValueIterator(Iterator> it) { + this.it = it; + } + + public V next() { + return it.next().getValue(); + } + + public boolean hasNext() { + return it.hasNext(); + } + + public void remove() { + it.remove(); + } + } +} diff --git a/sgx-jvm/avian/classpath/avian/FieldAddendum.java b/sgx-jvm/avian/classpath/avian/FieldAddendum.java new file mode 100644 index 0000000000..525dfc6f3c --- /dev/null +++ b/sgx-jvm/avian/classpath/avian/FieldAddendum.java @@ -0,0 +1,13 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package avian; + +public class FieldAddendum extends Addendum { } diff --git a/sgx-jvm/avian/classpath/avian/FormatString.java b/sgx-jvm/avian/classpath/avian/FormatString.java new file mode 100644 index 0000000000..a66c3cfa9e --- /dev/null +++ b/sgx-jvm/avian/classpath/avian/FormatString.java @@ -0,0 +1,992 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package avian; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.IllegalFormatException; +import java.util.List; + +// ------------------------------------------------------------------------- // +// things that must be done in order to call this semi-complete: +// ------------------------------------------------------------------------- // +// * get the date formatter working for individual fields at a minimum +// ------------------------------------------------------------------------- // + +/** + * A Java flavored printf for classpath-challenged JVMs. + * + * Each instance of this class is a threadsafe pre-parsed format pattern. Refer + * to the very detailed class description of java.util.Formatter in the OpenJDK + * API documentation for an explanation of the supported formats. + * + * Should be easily portable to other Java runtimes that do not include the + * printf functionality that was introduced in Java 5. + * + * Aims to be lightweight and reasonably fast, and provide reasonably complete + * API compatibility with the OpenJDK implementation. To clarify what + * "reasonably complete" means in this context, this implementation should + * accept any valid format string that the OpenJDK version accepts. However, + * it should not be relied upon to throw an Exception for every format pattern + * that the OpenJDK implementation does. + * + * If your program's behavior relies on the side effects from an Exception + * being thrown for an invalid format string, this might not be for you. + * + * Perhaps more troubling is the fact that the correct localization of numbers + * and temporal values is barely even attempted, even though the parser accepts + * the flags without even a warning. However, now you have been warned. + * + * @author bcg + */ +public final class FormatString { + + /** Parses a format string and returns a compiled representation of it. */ + public static final FormatString compile(String fmt) { + return new FormatString(fmt); + } + + /** The original string value that was parsed */ + public String source() { + return _source; + } + + /** Processes the supplied arguments through the compiled format string + and returns the result as a String. */ + public final String format(Object... args) { + final StringBuilder bldr = new StringBuilder(); + try { + format(bldr, args); + return bldr.toString(); + } catch (IOException e) { + throw new IllegalStateException( + "Should not get IOException when writing to StringBuilder", e + ); + } + } + + /** Processes the supplied arguments through the compiled format string + and writes the result of each component directly to an Appendable */ + public final void format(final Appendable a, Object... fmt_args) + throws IOException { + final Object[] args = fmt_args != null ? fmt_args : new Object[0]; + int cntr = 0; + for (final FmtCmpnt cmp : _components) { + if (cmp._conversion == CONV_LITRL) { + a.append(cmp._source); + continue; + } + final Object arg; + if (!acceptsArgument(cmp._conversion)) { + arg = null; + } else { + final int index = cmp._argument_index; + switch (index) { + case AIDX_NONE: + if ((cntr) >= args.length) { + throw new IllegalFormatException( + "Format specified at least " + (cntr+1) + + " arguments, but " + cntr + " were supplied." + ); + } + arg = args[cntr++]; + break; + case AIDX_PREV: + arg = args[cntr]; + break; + default: + if (index < 1) { + throw new IllegalArgumentException(); + } else if (index > args.length) { + throw new IllegalArgumentException(); + } else { + arg = args[index - 1]; + } + } + } + convert(a, arg, cmp._conversion, cmp._flags, cmp._width, cmp._precision); + } + } + + //- conversions + static final byte CONV_LITRL = 0x0; + static final byte CONV_NLINE = 0x1; + static final byte CONV_PRCNT = 0x2; + static final byte CONV_BOOLN = 0x3; + static final byte CONV_DTIME = 0x4; + static final byte CONV_STRNG = 0x5; + static final byte CONV_HCODE = 0x6; + static final byte CONV_CHRCT = 0x7; + static final byte CONV_DECML = 0x8; + static final byte CONV_OCTAL = 0x9; + static final byte CONV_HXDEC = 0xA; + static final byte CONV_CPSCI = 0xB; + static final byte CONV_GNSCI = 0xC; + static final byte CONV_FLOAT = 0xD; + static final byte CONV_HXEXP = 0xE; + + //- format component flags + static final byte FLAG_FORCE_UPPER_CASE = (byte)(1<<7); + static final byte FLAG_NEGATIVES_IN_PARENS = (byte)(1<<6); // ('(') + static final byte FLAG_GROUPING_SEPARATORS = (byte)(1<<5); // (',') + static final byte FLAG_LEADING_ZERO_PADDED = (byte)(1<<4); // ('0') + static final byte FLAG_LEADING_SPACE_PADDED = (byte)(1<<3); // (' ') + static final byte FLAG_ALWAYS_INCLUDES_SIGN = (byte)(1<<2); // ('+') + static final byte FLAG_ALTERNATE_FORM = (byte)(1<<1); // ('#') + static final byte FLAG_LEFT_JUSTIFIED = (byte)(1<<0); // ('-') + + //- conversion capability flags + static final byte CFLG_WDTH_SUPPRT = CONV_PRCNT; + static final byte CFLG_ACCEPTS_ARG = CONV_BOOLN; + static final byte CFLG_NUMERIC_VAL = CONV_DECML; + static final byte CFLG_PREC_SUPPRT = CONV_STRNG; + + //- special argument indices + static final int AIDX_PREV = -1; + static final int AIDX_NONE = 0; + + /** the original serialized format string */ + private final String _source; + + /** array of components parsed from the source string */ + private final FmtCmpnt[] _components; + + /*/ keeping this private for now to encourage access through the static + compile method, which might allow caching format string instances if it + turns out there is an advantage to that. /*/ + /** Constructor */ + private FormatString(final String fmt) { + this._source = fmt; + final List cmps = new ArrayList(); + for ( int i = 0; (i = next(fmt, cmps, i)) > -1; ); + this._components = cmps.toArray(new FmtCmpnt[cmps.size()]); + } + + /** Iterates over the tokens in an input string to extract the components */ + private static final int next( + final String fmt, final List cmps, final int startIndex) { + final int strln = fmt.length(); + if (startIndex >= strln) { + return -1; + } + final char c = fmt.charAt(startIndex); + if (c == '%') { + // this is the start of a specifier + final FmtSpecBldr bldr = new FmtSpecBldr(); + for (int i = startIndex + 1; i < strln; i++) { + final char ch = fmt.charAt(i); + final FmtCmpnt cmp = bldr.append(ch); + if (cmp != null) { + cmps.add(cmp); + return (i+1); + } + } + throw new IllegalFormatException("Incomplete specifier at end of fmt"); + } else { + // this is the start of a literal + final StringBuilder literal = new StringBuilder(); + literal.append(c); + for (int i = startIndex + 1; i < strln; i++) { + final char ch = fmt.charAt(i); + // write the current buffer if the next character starts a specifier + if (ch == '%') { + final FmtCmpnt cmp = new FmtCmpnt(literal.toString()); + cmps.add(cmp); + return i; + } + literal.append(ch); + } + // write the current buffer if the end of the format has been reached + final FmtCmpnt cmp = new FmtCmpnt(literal.toString()); + cmps.add(cmp); + return -1; + } + } + + /** Checks a flag byte to see if a given flag is set. Only FLAG_* constants + from the enclosing class should be passed in for toCheck... otherwise the + behavior is undefined. */ + static final boolean checkFlag(final byte flags, final byte toCheck) { + return (flags & toCheck) != 0; + } + + /** Checks if a given conversion accepts(requires) an argument. Only the CONV_ + flags from the enclosing class should be passed in, otherwise the result + of this method is undefined as should not be used. */ + static final boolean acceptsArgument(final byte conversion) { + return conversion >= CFLG_ACCEPTS_ARG; + } + + /** Checks if a given conversion allows specifying a precision. Only the CONV_ + flags from the enclosing class should be passed in, otherwise the result + of this method is undefined as should not be used. */ + static final boolean precisionSupported(final byte conversion) { + return conversion >= CFLG_PREC_SUPPRT; + } + + /** Checks if a given conversion allows specifying a width. Only the CONV_ + flags from the enclosing class should be passed in, otherwise the result + of this method is undefined and should not be trusted. */ + static final boolean widthSupported(final byte conversion) { + return conversion >= CFLG_WDTH_SUPPRT; + } + + /** Checks if a given conversion expects a numeric value. Only the CONV_ + flags from the enclosing class should be passed in, otherwise the result + of this method is undefined and should not be trusted. */ + static final boolean isNumeric(final byte conversion) { + return conversion >= CFLG_NUMERIC_VAL; + } + + /** The newline character for the current platform. */ + static final String NEWLINE = System.getProperty("line.separator"); + + /** Performs conversion on the supplied argument */ + static final void convert( + final Appendable appendable, + final Object arg, + final byte conversion, + final byte flags, + final int width, + final int precision) throws IOException { + int radix = 0; + switch (conversion) { + case CONV_LITRL: + throw new IllegalArgumentException("cannot convert a literal"); + case CONV_NLINE: + appendable.append(NEWLINE); + return; + case CONV_PRCNT: + convertPercent(appendable, arg, flags, width, precision); + return; + case CONV_BOOLN: + convertBoolean(appendable, arg, flags, width, precision); + return; + case CONV_DTIME: + convertDate(appendable, arg, flags, width, precision); + return; + case CONV_STRNG: + convertString(appendable, arg, flags, width, precision); + return; + case CONV_HCODE: + convertHashcode(appendable, arg, flags, width, precision); + return; + case CONV_CHRCT: + convertChar(appendable, arg, flags, width, precision); + return; + case CONV_DECML: if (radix == 0) { radix = 10; }; + case CONV_OCTAL: if (radix == 0) { radix = 8; }; + case CONV_HXDEC: if (radix == 0) { radix = 16; }; + if (arg instanceof Long) { + convertLong(appendable, (Long) arg, flags, width, precision, radix); + } else { + convertInteger(appendable, arg, flags, width, precision, radix); + } + return; + case CONV_CPSCI: + case CONV_GNSCI: + case CONV_FLOAT: + case CONV_HXEXP: + convertFloat(appendable, arg, flags, width, precision, 10); + return; + } + throw new IllegalStateException("not implemented: " + conversion); + } + + static void convertPercent( + final Appendable a, + final Object arg, + final byte flags, + final int width, + final int precision) throws IOException { + final String val = "%"; + appendify(a, val, flags, width, precision); + } + + static void convertDate( + final Appendable a, + final Object arg, + final byte flags, + final int width, + final int precision) throws IOException { + final String val = (arg == null) ? "null" : arg.toString(); + appendify(a, val, flags, width, precision); + } + + static void convertString( + final Appendable a, + final Object arg, + final byte flags, + final int width, + final int precision) throws IOException { + final String val = (arg == null) ? "null" : arg.toString(); + appendify(a, val, flags, width, precision); + } + + static void convertHashcode( + final Appendable a, + final Object arg, + final byte flags, + final int width, + final int precision) throws IOException { + final String val = (arg == null) + ? "null" + : Integer.toHexString(arg.hashCode()); + appendify(a, val, flags, width, precision); + } + + static void convertBoolean( + final Appendable a, + final Object arg, + final byte flags, + final int width, + final int precision) throws IOException { + final String val; + if (arg == null) { + val = "false"; + } else if (arg instanceof Boolean) { + val = String.valueOf(arg); + } else { + val = "true"; + } + appendify(a, val, flags, width, precision); + } + + static void convertChar( + final Appendable a, + final Object arg, + final byte flags, + final int width, + final int precision) throws IOException { + final String val; + if (arg instanceof Character) { + val = ((Character) arg).toString(); + } else if ( arg instanceof Byte || + arg instanceof Short || + arg instanceof Integer ){ + final int codePoint = ((Number) arg).intValue(); + if (codePoint >= 0 && codePoint <= 0x10FFFF) { //<-- isValidCodePoint()? + val = new String(Character.toChars(codePoint)); + } else { + throw new IllegalFormatException("Invalid code point: " + arg); + } + } else { + throw new IllegalFormatException("Cannot do char conversion: " + arg); + } + appendify(a, val, flags, width, precision); + } + + // FIXME: this is broken for octal formats with negative values + static void convertLong( + final Appendable a, + final Long arg, + final byte flags, + final int width, + final int precision, + final int radix) throws IOException { + final String val; + final Long n = arg; + final long longValue = n.longValue(); + if (radix == 10 || longValue > -1) { + val = Long.toString(longValue, radix); + } else { + final long upper = 0xFFFFFFFFL&(longValue>>31); + final long lower = 0xFFFFFFFFL&(longValue); + val = Long.toString(upper, radix) + Long.toString(lower, radix); + } + appendify(a, val, flags, width, precision); + } + + static void convertInteger( + final Appendable a, + final Object arg, + final byte flags, + final int width, + final int precision, + final int radix) throws IOException { + final String val; + final Number n = (Number) arg; + final long longValue = n.longValue(); + final long modifier; + if (arg instanceof Integer) modifier = 0xFFFFFFFFL+1; else + if (arg instanceof Short) modifier = 0xFFFFL+1; else + if (arg instanceof Byte) modifier = 0xFFL+1; + else throw new IllegalFormatException( + "not an integer number: " + (arg != null ? arg.getClass() : null) + ); + if (radix != 10 && longValue < 0) { + val = Long.toString(longValue + modifier, radix); + } else { + val = Long.toString(longValue, radix); + } + appendify(a, val, flags, width, precision); + } + + // FIXME: I'm lazy, so hexidecimal exponential isn't implemented, sorry - bcg + static void convertFloat( + final Appendable a, + final Object arg, + final byte flags, + final int width, + final int precision, + final int radix) throws IOException { + final String val; + final Number n = (Number) arg; + if (arg instanceof Float) { + val = Float.toString(n.floatValue()); + } else if (arg instanceof Double) { + val = Double.toString(n.doubleValue()); + } else { + throw new IllegalFormatException( + "not a floating point number: " + (arg != null ? arg.getClass() : null) + ); + } + appendify(a, val, flags, width, precision); + } + + static void appendify( + final Appendable a, + final String val, + final byte flags, + final int width, + final int precision) throws IOException { + String result = val; + if (checkFlag(flags, FLAG_FORCE_UPPER_CASE)) { + result = result.toUpperCase(); + } + // TODO: implement other flags + // (+) always include sign + // (,) grouping separators + // (() negatives in parentheses + if (precision > 0) { + // FIXME: this behavior should be different for floating point numbers + final int difference = result.length() - precision; + if (difference > 0) { + result = result.substring(0, precision); + a.append(result); + return; + } + } + if (width > 0) { + final int difference = width - result.length(); + final boolean leftJustified = checkFlag(flags, FLAG_LEFT_JUSTIFIED); + if (!leftJustified && difference > 0) { + char fill = checkFlag(flags, FLAG_LEADING_ZERO_PADDED) ? '0' : ' '; + fill(a, difference, fill); + } + a.append(result); + if (leftJustified && difference > 0) { + fill(a, difference, ' '); + } + return; + } + a.append(result); + } + + private static void fill(Appendable a, int num, char c) throws IOException { + while (num > 0) { + a.append(c); + num--; + } + } + + /** Represents a single chunk of the format string, either a literal or one of + the specifiers documented in OpenJDK's javadoc for java.util.Formatter. + This struct is immutable so can be safely shared across threads. */ + private static final class FmtCmpnt { + + private final String _source; + private final byte _conversion; + private final int _argument_index; + private final int _width; + private final int _precision; + private final byte _flags; + + private FmtCmpnt(final String literal) { + this(literal, CONV_LITRL, 0, 0, 0, (byte)0); + } + private FmtCmpnt( + final String src, + final byte conversion, + final int argumentIndex, + final int width, + final int precision, + final byte flags) { + this._source = src; + this._conversion = conversion; + this._argument_index = argumentIndex; + this._width = width; + this._precision = precision; + this._flags = flags; + } + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("{ ") + .append("source = '").append(_source).append("', ") + .append("conversion = ").append(_conversion).append(", ") + .append("flags = ").append(Byte.toString(_flags, 2)).append(", ") + .append("arg_index = ").append(_argument_index).append(", ") + .append("width = ").append(_width).append(", ") + .append("precision = ").append(_precision).append(", ") + .append("}"); + return sb.toString(); + } + } + + /** + * Helper class for parsing a stream of characters into FmtCmpnt objects. + */ + private static final class FmtSpecBldr { + + private StringBuilder _source; + private byte _conversion; + private int _argument_index; + private int _width; + private int _precision; + private byte _flags; + + private FmtSpecBldr() { + this.init(); + } + + private final void init() { + _argument_index = + _width = + _precision = + _conversion = + _flags = 0; + _source = null; + } + + private final FmtCmpnt build() { + final FmtCmpnt result = new FmtCmpnt( + _source.toString(), + _conversion, + _argument_index, + _width, + _precision, + _flags + ); + init(); + return result; + } + + private final FmtCmpnt append(char c) { + + if (_source == null) { + _source = new StringBuilder(); + } + _source.append(c); + + // FIXME: none of these date formats are implemented, because lazy + // if a datetime is specified, after the conversion character a time + // format specifier is expected. This is the only case where a character + // is allowed after the conversion character. + if (_conversion == CONV_DTIME) switch (c) { + + // Hour of the day for the 24-hour clock, formatted as two digits with a + // leading zero as necessary i.e. 00 - 23. + case 'H': + + // Hour for the 12-hour clock, formatted as two digits with a leading + // zero as necessary, i.e. 01 - 12. + case 'I': + + // Hour of the day for the 24-hour clock, i.e. 0 - 23. + case 'k': + + // Hour for the 12-hour clock, i.e. 1 - 12. + case 'l': + + // Minute within the hour formatted as two digits with a leading zero + // as necessary, i.e. 00 - 59. + case 'M': + + // Seconds within the minute, formatted as two digits with a leading + // zero as necessary, i.e. 00 - 60 ("60" is a special value required to + // support leap seconds). + case 'S': + + // Millisecond within the second formatted as three digits with leading + // zeros as necessary, i.e. 000 - 999. + case 'L': + + // Nanosecond within the second, formatted as nine digits with leading + // zeros as necessary, i.e. 000000000 - 999999999. + case 'N': + + // Locale-specific morning or afternoon marker in lower case, + // e.g."am" or "pm". Use of the conversion prefix 'T' forces this + // output to upper case. + case 'p': + + // RFC 822 style numeric time zone offset from GMT, e.g. -0800. + case 'z': + + // A string representing the abbreviation for the time zone. The + // Formatter's locale will supersede the locale of the argument + // (if any). + case 'Z': + + // Seconds since the beginning of the epoch + // starting at 1 January 1970 00:00:00 UTC, + // i.e. Long.MIN_VALUE/1000 to Long.MAX_VALUE/1000. + case 's': + + // Milliseconds since the beginning of the epoch + // starting at 1 January 1970 00:00:00 UTC, + // i.e. Long.MIN_VALUE to Long.MAX_VALUE. + case 'Q': + + // ------------------------------------------------------------------ + // The following conversion characters are used for formatting dates: + // ------------------------------------------------------------------ + + // Locale-specific full month name, e.g. "January", "February". + case 'B': + + // Locale-specific abbreviated month name, e.g. "Jan", "Feb". + case 'b': + + // Same as 'b'. + case 'h': + + // Locale-specific full name of the day of the week, e.g. "Sunday" + case 'A': + + // Locale-specific short name of the day of the week, e.g. "Sun" + case 'a': + + // Four-digit year divided by 100, formatted as two digits with leading + // zero as necessary, i.e. 00 - 99 + case 'C': + + // Year, formatted as at least four digits with leading zeros + // as necessary, e.g. 0092 equals 92 CE for the Gregorian calendar. + case 'Y': + + // Last two digits of the year, formatted with leading zeros + // as necessary, i.e. 00 - 99. + case 'y': + + // Day of year, formatted as three digits with leading zeros + // as necessary, e.g. 001 - 366 for the Gregorian calendar. + case 'j': + + // Month, formatted as two digits with leading zeros as necessary, + // i.e. 01 - 13. + case 'm': + + // Day of month, formatted as two digits with leading zeros as + // necessary, i.e. 01 - 31 + case 'd': + + // Day of month, formatted as two digits, i.e. 1 - 31. + case 'e': + + // ------------------------------------------------------------------- + // The following conversion characters are used for formatting common + // date/time compositions. + // ------------------------------------------------------------------- + + // Time formatted for the 24-hour clock as "%tH:%tM" + case 'R': + + // Time formatted for the 24-hour clock as "%tH:%tM:%tS". + case 'T': + + // Time formatted for the 12-hour clock as "%tI:%tM:%tS %Tp". The location + // of the morning or afternoon marker ('%Tp') may be locale-dependent. + case 'r': + + // Date formatted as "%tm/%td/%ty". + case 'D': + + // ISO 8601 complete date formatted as "%tY-%tm-%td". + case 'F': + + // Date and time formatted as "%ta %tb %td %tT %tZ %tY", e.g. + // "Sun Jul 20 16:17:00 EDT 1969". + case 'c': + return seal(CONV_DTIME); + + default: + throw new IllegalFormatException("Illegal date/time modifier: " + c); + } + + // -- Flags and Switches ----------------------------------------------- + // these are the possible characters for flags, width, etc. if the input + // is not one of these characters, it needs to be a valid conversion char. + // because the possible flags can vary based on the type of conversion, + // it is easiest to just buffer the flags, argument index, etc. until a + // conversion character has been reached. The seal() method will then + // work out if the specified flags are valid for the given conversion. + switch (c) { + case '$': + case '<': + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + case '-': + case '+': + case '\'': + case ' ': + case '#': + case ',': + case '.': + case '(': + return null; + // -- End of Flags and Switches ---------------------------------------- + + // -- Conversion characters -------------------------------------------- + // If this point is reached, then the current character must be a valid + // conversion character. If it is not, it should fall through the rest + // of the switch statement below and throw an IllegalFormatException + + // string conversion + case 'S': + setFlagTrue(FLAG_FORCE_UPPER_CASE); + case 's': + return seal(CONV_STRNG); + + // newline conversion + case 'n': + return seal(CONV_NLINE); + + // percent conversion + case '%': + return seal(CONV_PRCNT); + + // decimal numeric conversion + case 'd': + return seal(CONV_DECML); + + // hexidecimal numeric conversion + case 'X': + setFlagTrue(FLAG_FORCE_UPPER_CASE); + case 'x': + return seal(CONV_HXDEC); + + // datetime conversion + case 'T': + setFlagTrue(FLAG_FORCE_UPPER_CASE); + case 't': + _conversion = CONV_DTIME; + return null; + + // boolean conversion + case 'B': + setFlagTrue(FLAG_FORCE_UPPER_CASE); + case 'b': + return seal(CONV_BOOLN); + + // hashcode conversion + case 'H': + setFlagTrue(FLAG_FORCE_UPPER_CASE); + case 'h': + return seal(CONV_HCODE); + + // character conversion + case 'C': + setFlagTrue(FLAG_FORCE_UPPER_CASE); + case 'c': + return seal(CONV_CHRCT); + + // octal numeric conversion + case 'o': + return seal(CONV_OCTAL); + + // computerized scientific conversion + case 'E': + setFlagTrue(FLAG_FORCE_UPPER_CASE); + case 'e': + return seal(CONV_CPSCI); + + // floating point conversion + case 'f': + return seal(CONV_FLOAT); + + // general scientific floating point conversion + case 'G': + setFlagTrue(FLAG_FORCE_UPPER_CASE); + case 'g': + return seal(CONV_GNSCI); + + // hexidecimal exponential floating point conversion + case 'A': + setFlagTrue(FLAG_FORCE_UPPER_CASE); + case 'a': + return seal(CONV_HXEXP); + // -- End of Conversion characters -------------------------------------- + + default: + throw new IllegalFormatException( + "Invalid character encountered while parsing specifier: " + c); + } + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("{ ") + .append("source = '").append(_source).append("', ") + .append("conversion = ").append(_conversion).append(", ") + .append("flags = ").append(Byte.toString(_flags, 2)).append(", ") + .append("arg_index = ").append(_argument_index).append(", ") + .append("width = ").append(_width).append(", ") + .append("precision = ").append(_precision).append(", ") + .append("}"); + return sb.toString(); + } + + private final FmtCmpnt seal(final byte conversion) { + + // throwing IllegalStateException instead of IllegalFormatException + // because this should only occur if there is a bug in the append() + // method. In that case I'd prefer to fail fast even if the user is + // explicitly trying to catch IllegalFormatException. + if (conversion < 0 || conversion > 0xE) { + throw new IllegalArgumentException(); + } + + this._conversion = conversion; + + // if the length is less than 2, it must mean that only the conversion + // character was specified. Since a conversion character by itself is a + // valid pattern, just build and return + if (_source.length() < 2) { + return build(); + } + + // --------------------------------------------------------------------- + // spec format: [argument_index$][flags][width][.precision] + // --------------------------------------------------------------------- + // the last character of the spec is the conversion character which has + // already been translated the appropriate byte by the append() method, + // so the last character gets chopped off before processing + final String spec = _source.substring(0, _source.length() - 1); + + // if argument index is supported, it should be followed by a '$' and be + // comprised only of digit characters, or it should be a single '<' char + final int dollarIndex = spec.indexOf('$'); + if (dollarIndex > -1) { + if (acceptsArgument(conversion)) { + if (spec.charAt(dollarIndex - 1) == '<') { + _argument_index = AIDX_PREV; + } else { + _argument_index = Integer.valueOf(spec.substring(0, dollarIndex)); + } + } else { + throw new IllegalFormatException( + "Formats that do not accept arguments cannot specify an index." + ); + } + } + if (dollarIndex == (spec.length() - 1)) { + return build(); + } + + // if precision is supported, look for the first period and assume that + // everything before is the width and everything after is the precision + final int dotIndex = spec.indexOf('.'); + if (dotIndex > -1) { + if (precisionSupported(conversion)) { + _precision = Integer.valueOf(spec.substring(dotIndex + 1)); + } else { + throw new IllegalFormatException( + "Precision is not supported for " + conversion + ); + } + } + + // Now loop over the remaining characters to get the width as well as any + // applicable flags. Note: 0 is a valid flag so must be handled carefully + final String remaining = spec.substring( + Math.max(dollarIndex, 0), dotIndex > -1 ? dotIndex : spec.length() + ); + int flagsEnd = -1; + for (int i = 0, n = remaining.length(); i < n && (flagsEnd == -1); i++) { + final char c = remaining.charAt(i); + switch (c) { + case '-': + ensureLeftJustifySupported(); + setFlagTrue(FLAG_LEFT_JUSTIFIED); + break; + case '#': + ensureNumeric(c); + setFlagTrue(FLAG_ALTERNATE_FORM); + break; + case '+': + ensureNumeric(c); + setFlagTrue(FLAG_ALWAYS_INCLUDES_SIGN); + break; + case ' ': + ensureNumeric(c); + setFlagTrue(FLAG_LEADING_SPACE_PADDED); + break; + case ',': + ensureNumeric(c); + setFlagTrue(FLAG_GROUPING_SEPARATORS); + break; + case '(': + ensureNumeric(c); + setFlagTrue(FLAG_NEGATIVES_IN_PARENS); + break; + case '0': + ensureNumeric(c); + setFlagTrue(FLAG_LEADING_ZERO_PADDED); + break; + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + flagsEnd = i; + _width = Integer.valueOf(remaining.substring(flagsEnd)); + return build(); + } + } + throw new IllegalStateException(); + } + private final void ensureLeftJustifySupported() { + if (!widthSupported(_conversion)) { + throw new IllegalFormatException( + "Conversion must support width if specifying left justified." + ); + } + } + private final void ensureNumeric(final char c) { + if (!isNumeric(_conversion)) { + throw new IllegalFormatException( + "flag " + c + " only supported on numeric specifiers." + ); + } + } + private final void setFlagTrue(final byte flag) { + _flags |= flag; + }/* + final void setFlagFalse(final byte flag) { + _flags &= ~flag; + }*/ + } +} diff --git a/sgx-jvm/avian/classpath/avian/Function.java b/sgx-jvm/avian/classpath/avian/Function.java new file mode 100644 index 0000000000..246a3ae512 --- /dev/null +++ b/sgx-jvm/avian/classpath/avian/Function.java @@ -0,0 +1,15 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package avian; + +public interface Function { + public B call(A argument) throws Exception; +} diff --git a/sgx-jvm/avian/classpath/avian/IncompatibleContinuationException.java b/sgx-jvm/avian/classpath/avian/IncompatibleContinuationException.java new file mode 100644 index 0000000000..15007c0fc0 --- /dev/null +++ b/sgx-jvm/avian/classpath/avian/IncompatibleContinuationException.java @@ -0,0 +1,21 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package avian; + +public class IncompatibleContinuationException extends Exception { + public IncompatibleContinuationException(String message) { + super(message); + } + + public IncompatibleContinuationException() { + super(); + } +} diff --git a/sgx-jvm/avian/classpath/avian/InnerClassReference.java b/sgx-jvm/avian/classpath/avian/InnerClassReference.java new file mode 100644 index 0000000000..614a4da93a --- /dev/null +++ b/sgx-jvm/avian/classpath/avian/InnerClassReference.java @@ -0,0 +1,18 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package avian; + +public class InnerClassReference { + public byte[] inner; + public byte[] outer; + public byte[] name; + public short flags; +} diff --git a/sgx-jvm/avian/classpath/avian/Iso88591.java b/sgx-jvm/avian/classpath/avian/Iso88591.java new file mode 100644 index 0000000000..dcdb7baf6a --- /dev/null +++ b/sgx-jvm/avian/classpath/avian/Iso88591.java @@ -0,0 +1,26 @@ + +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package avian; + +import java.io.ByteArrayOutputStream; + +public class Iso88591 { + + public static byte[] encode(char[] s16, int offset, int length) { + ByteArrayOutputStream buf = new ByteArrayOutputStream(); + for (int i = offset; i < offset+length; ++i) { + // ISO-88591-1/Latin-1 is the same as UTF-16 under 0x100 + buf.write(s16[i]); + } + return buf.toByteArray(); + } +} diff --git a/sgx-jvm/avian/classpath/avian/LegacyObjectInputStream.java b/sgx-jvm/avian/classpath/avian/LegacyObjectInputStream.java new file mode 100644 index 0000000000..8738048dd7 --- /dev/null +++ b/sgx-jvm/avian/classpath/avian/LegacyObjectInputStream.java @@ -0,0 +1,240 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package avian; + +import avian.VMClass; + +import java.util.HashMap; +import java.io.EOFException; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.PushbackReader; +import java.io.StreamCorruptedException; +import java.lang.reflect.Array; +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; + +public class LegacyObjectInputStream extends InputStream { + private final InputStream in; + private final PushbackReader r; + + public LegacyObjectInputStream(InputStream in) { + this.in = in; + this.r = new PushbackReader(new InputStreamReader(in)); + } + + public int read() throws IOException { + return in.read(); + } + + public int read(byte[] b, int offset, int length) throws IOException { + return in.read(b, offset, length); + } + + public void close() throws IOException { + in.close(); + } + + public Object readObject() throws IOException, ClassNotFoundException { + return readObject(new HashMap()); + } + + public boolean readBoolean() throws IOException { + read('z'); + return readLongToken() != 0; + } + + public byte readByte() throws IOException { + read('b'); + return (byte) readLongToken(); + } + + public char readChar() throws IOException { + read('c'); + return (char) readLongToken(); + } + + public short readShort() throws IOException { + read('s'); + return (short) readLongToken(); + } + + public int readInt() throws IOException { + read('i'); + return (int) readLongToken(); + } + + public long readLong() throws IOException { + read('j'); + return readLongToken(); + } + + public float readFloat() throws IOException { + read('f'); + return (float) readDoubleToken(); + } + + public double readDouble() throws IOException { + read('d'); + return readDoubleToken(); + } + + public void defaultReadObject() throws IOException { + throw new UnsupportedOperationException(); + } + + private void skipSpace() throws IOException { + int c; + while ((c = r.read()) != -1 && Character.isWhitespace((char) c)); + if (c != -1) { + r.unread(c); + } + } + + private void read(char v) throws IOException { + skipSpace(); + + int c = r.read(); + if (c != v) { + if (c == -1) { + throw new EOFException(); + } else { + throw new StreamCorruptedException(); + } + } + } + + private String readStringToken() throws IOException { + skipSpace(); + + StringBuilder sb = new StringBuilder(); + int c; + while ((c = r.read()) != -1 && ! Character.isWhitespace((char) c) && c != ')') { + sb.append((char) c); + } + if (c != -1) { + r.unread(c); + } + return sb.toString(); + } + + private long readLongToken() throws IOException { + return Long.parseLong(readStringToken()); + } + + private double readDoubleToken() throws IOException { + return Double.parseDouble(readStringToken()); + } + + private Object readObject(HashMap map) + throws IOException, ClassNotFoundException + { + skipSpace(); + switch (r.read()) { + case 'a': + return deserializeArray(map); + case 'l': + return deserializeObject(map); + case 'n': + return null; + case -1: + throw new EOFException(); + default: + throw new StreamCorruptedException(); + } + } + + private Object deserialize(HashMap map) + throws IOException, ClassNotFoundException + { + skipSpace(); + switch (r.read()) { + case 'a': + return deserializeArray(map); + case 'l': + return deserializeObject(map); + case 'r': + return map.get((int) readLongToken()); + case 'n': + return null; + case 'z': + return (readLongToken() != 0); + case 'b': + return (byte) readLongToken(); + case 'c': + return (char) readLongToken(); + case 's': + return (short) readLongToken(); + case 'i': + return (int) readLongToken(); + case 'j': + return readLongToken(); + case 'f': + return (float) readDoubleToken(); + case 'd': + return readDoubleToken(); + case -1: + throw new EOFException(); + default: + throw new StreamCorruptedException(); + } + } + + private Object deserializeArray(HashMap map) + throws IOException, ClassNotFoundException + { + read('('); + int id = (int) readLongToken(); + Class c = Class.forName(readStringToken()); + int length = (int) readLongToken(); + Class t = c.getComponentType(); + Object o = Array.newInstance(t, length); + + map.put(id, o); + + for (int i = 0; i < length; ++i) { + Array.set(o, i, deserialize(map)); + } + + read(')'); + + return o; + } + + private static native Object makeInstance(VMClass c); + + private Object deserializeObject(HashMap map) + throws IOException, ClassNotFoundException + { + read('('); + int id = (int) readLongToken(); + Class c = Class.forName(readStringToken()); + Object o = makeInstance(c.vmClass); + + map.put(id, o); + + for (Field f: c.getAllFields()) { + int modifiers = f.getModifiers(); + if ((modifiers & (Modifier.TRANSIENT | Modifier.STATIC)) == 0) { + try { + f.set(o, deserialize(map)); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + } + + read(')'); + + return o; + } +} diff --git a/sgx-jvm/avian/classpath/avian/LegacyObjectOutputStream.java b/sgx-jvm/avian/classpath/avian/LegacyObjectOutputStream.java new file mode 100644 index 0000000000..a55c18230e --- /dev/null +++ b/sgx-jvm/avian/classpath/avian/LegacyObjectOutputStream.java @@ -0,0 +1,211 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package avian; + +import java.util.IdentityHashMap; +import java.lang.reflect.Array; +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; +import java.io.IOException; +import java.io.OutputStream; +import java.io.PrintStream; +import java.io.Serializable; +import java.io.NotSerializableException; + +public class LegacyObjectOutputStream extends OutputStream { + private final PrintStream out; + + public LegacyObjectOutputStream(OutputStream out) { + this.out = new PrintStream(out); + } + + public void write(int c) throws IOException { + out.write(c); + } + + public void write(byte[] b, int offset, int length) throws IOException { + out.write(b, offset, length); + } + + public void flush() throws IOException { + out.flush(); + } + + public void close() throws IOException { + out.close(); + } + + public void writeObject(Object o) throws IOException { + writeObject(o, new IdentityHashMap(), new int[] {0}); + } + + public void writeBoolean(boolean v) { + out.print("z"); + out.print((v ? 1 : 0)); + } + + public void writeByte(byte v) { + out.print("b"); + out.print((int) v); + } + + public void writeChar(char v) { + out.print("c"); + out.print((int) v); + } + + public void writeShort(short v) { + out.print("s"); + out.print((int) v); + } + + public void writeInt(int v) { + out.print("i"); + out.print(v); + } + + public void writeLong(long v) { + out.print("j"); + out.print(v); + } + + public void writeFloat(float v) { + out.print("f"); + out.print(v); + } + + public void writeDouble(double v) { + out.print("d"); + out.print(v); + } + + public void defaultWriteObject() throws IOException { + throw new UnsupportedOperationException(); + } + + private void writeObject(Object o, IdentityHashMap map, + int[] nextId) + throws IOException + { + if (o == null) { + out.print("n"); + } else { + Integer id = map.get(o); + if (id == null) { + map.put(o, nextId[0]); + + Class c = o.getClass(); + if (c.isArray()) { + serializeArray(o, map, nextId); + } else if (Serializable.class.isAssignableFrom(c)) { + serializeObject(o, map, nextId); + } else { + throw new NotSerializableException(c.getName()); + } + } else { + out.print("r"); + out.print(id.intValue()); + } + } + } + + private void serializeArray(Object o, IdentityHashMap map, + int[] nextId) + throws IOException + { + Class c = o.getClass(); + Class t = c.getComponentType(); + int length = Array.getLength(o); + + out.print("a("); + out.print(nextId[0]++); + out.print(" "); + out.print(c.getName()); + out.print(" "); + out.print(length); + + for (int i = 0; i < length; ++i) { + out.print(" "); + Object v = Array.get(o, i); + if (t.equals(boolean.class)) { + writeBoolean((Boolean) v); + } else if (t.equals(byte.class)) { + writeByte((Byte) v); + } else if (t.equals(char.class)) { + writeChar((Character) v); + } else if (t.equals(short.class)) { + writeShort((Short) v); + } else if (t.equals(int.class)) { + writeInt((Integer) v); + } else if (t.equals(long.class)) { + writeLong((Long) v); + } else if (t.equals(float.class)) { + writeFloat((Float) v); + } else if (t.equals(double.class)) { + writeDouble((Double) v); + } else { + writeObject(v, map, nextId); + } + } + + out.print(")"); + } + + private void serializeObject(Object o, IdentityHashMap map, + int[] nextId) + throws IOException + { + Class c = o.getClass(); + + out.print("l("); + out.print(nextId[0]++); + out.print(" "); + out.print(c.getName()); + + for (Field f: c.getAllFields()) { + int modifiers = f.getModifiers(); + if ((modifiers & (Modifier.TRANSIENT | Modifier.STATIC)) == 0) { + out.print(" "); + Object v; + + try { + v = f.get(o); + } catch (Exception e) { + throw new RuntimeException(e); + } + + Class t = f.getType(); + if (t.equals(boolean.class)) { + writeBoolean((Boolean) v); + } else if (t.equals(byte.class)) { + writeByte((Byte) v); + } else if (t.equals(char.class)) { + writeChar((Character) v); + } else if (t.equals(short.class)) { + writeShort((Short) v); + } else if (t.equals(int.class)) { + writeInt((Integer) v); + } else if (t.equals(long.class)) { + writeLong((Long) v); + } else if (t.equals(float.class)) { + writeFloat((Float) v); + } else if (t.equals(double.class)) { + writeDouble((Double) v); + } else { + writeObject(v, map, nextId); + } + } + } + + out.print(")"); + } + +} diff --git a/sgx-jvm/avian/classpath/avian/Machine.java b/sgx-jvm/avian/classpath/avian/Machine.java new file mode 100644 index 0000000000..00c6ea2f15 --- /dev/null +++ b/sgx-jvm/avian/classpath/avian/Machine.java @@ -0,0 +1,67 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package avian; + +import sun.misc.Unsafe; +import java.lang.reflect.Field; + +public abstract class Machine { + + private static final Unsafe unsafe; + + static { + Unsafe u; + try { + Field f = Unsafe.class.getDeclaredField("theUnsafe"); + f.setAccessible(true); + u = (Unsafe)f.get(null); + } catch (Exception e) { + u = null; + } + unsafe = u; + } + + public static native void dumpHeap(String outputFile); + + public static Unsafe getUnsafe() { + return unsafe; + } + + /** + * Short version: Don't use this function -- it's evil. + * + * Long version: This is kind of a poor man's, cross-platform + * version of Microsoft's Structured Exception Handling. The idea + * is that you can call a native function with the specified + * argument such that any OS signals raised (e.g. SIGSEGV, SIGBUS, + * SIGFPE, EXC_ACCESS_VIOLATION, etc.) prior to the function + * returning are converted into the appropriate Java exception + * (e.g. NullPointerException, ArithmeticException, etc.) and thrown + * from this method. This may be useful in very specific + * circumstances, e.g. to work around a bug in a library that would + * otherwise crash your app. On the other hand, you'd be much + * better off just fixing the library if possible. + * + * Caveats: The specified function should return quickly without + * blocking, since it will block critical VM features such as + * garbage collection. The implementation is equivalent to using + * setjmp/longjmp to achieve a non-local return from the signal + * handler, meaning C++ destructors and other cleanup code might not + * be run if a signal is raised. It might melt your keyboard and + * burn your fingertips. Caveat lector. + * + * @param function a function pointer of type int64_t (*)(int64_t) + * @param argument the argument to pass to the function + * @return the return value of the function + */ + public static native long tryNative(long function, long argument); + +} diff --git a/sgx-jvm/avian/classpath/avian/MethodAddendum.java b/sgx-jvm/avian/classpath/avian/MethodAddendum.java new file mode 100644 index 0000000000..11f6b9ff15 --- /dev/null +++ b/sgx-jvm/avian/classpath/avian/MethodAddendum.java @@ -0,0 +1,17 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package avian; + +public class MethodAddendum extends Addendum { + public Object exceptionTable; + public Object annotationDefault; + public Object parameterAnnotationTable; +} diff --git a/sgx-jvm/avian/classpath/avian/Pair.java b/sgx-jvm/avian/classpath/avian/Pair.java new file mode 100644 index 0000000000..dff3313542 --- /dev/null +++ b/sgx-jvm/avian/classpath/avian/Pair.java @@ -0,0 +1,5 @@ +package avian; + +abstract class Pair { + // VM-visible fields in types.def +} diff --git a/sgx-jvm/avian/classpath/avian/PersistentSet.java b/sgx-jvm/avian/classpath/avian/PersistentSet.java new file mode 100644 index 0000000000..c257807ade --- /dev/null +++ b/sgx-jvm/avian/classpath/avian/PersistentSet.java @@ -0,0 +1,594 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package avian; + +import java.util.Comparator; + +public class PersistentSet implements Iterable { + private static final Node NullNode = new Node(null); + + static { + NullNode.left = NullNode; + NullNode.right = NullNode; + } + + private final Node root; + private final Comparator comparator; + private final int size; + + public PersistentSet() { + this(NullNode, new Comparator() { + public int compare(T a, T b) { + return ((Comparable) a).compareTo(b); + } + }, 0); + } + + public PersistentSet(Comparator comparator) { + this(NullNode, comparator, 0); + } + + private PersistentSet(Node root, Comparator comparator, int size) { + this.root = root; + this.comparator = comparator; + this.size = size; + } + + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("{"); + for (java.util.Iterator it = iterator(); it.hasNext();) { + sb.append(it.next()); + if (it.hasNext()) { + sb.append(","); + } + } + sb.append("}"); + return sb.toString(); + } + + public Comparator comparator() { + return comparator; + } + + public PersistentSet add(T value) { + return add(value, false); + } + + public int size() { + return size; + } + + public PersistentSet add(T value, boolean replaceExisting) { + Path p = find(value); + if (! p.fresh) { + if (replaceExisting) { + return p.replaceWith(value); + } else { + return this; + } + } + + return add(p); + } + + private PersistentSet add(Path p) { + if (! p.fresh) throw new IllegalArgumentException(); + + Node new_ = p.node; + Node newRoot = p.root.root; + Cell> ancestors = p.ancestors; + + // rebalance + new_.red = true; + while (ancestors != null && ancestors.value.red) { + if (ancestors.value == ancestors.next.value.left) { + if (ancestors.next.value.right.red) { + ancestors.value.red = false; + ancestors.next.value.right = new Node(ancestors.next.value.right); + ancestors.next.value.right.red = false; + ancestors.next.value.red = true; + new_ = ancestors.next.value; + ancestors = ancestors.next.next; + } else { + if (new_ == ancestors.value.right) { + new_ = ancestors.value; + ancestors = ancestors.next; + + Node n = leftRotate(new_); + if (ancestors.value.right == new_) { + ancestors.value.right = n; + } else { + ancestors.value.left = n; + } + ancestors = new Cell(n, ancestors); + } + ancestors.value.red = false; + ancestors.next.value.red = true; + + Node n = rightRotate(ancestors.next.value); + if (ancestors.next.next == null) { + newRoot = n; + } else if (ancestors.next.next.value.right == ancestors.next.value) { + ancestors.next.next.value.right = n; + } else { + ancestors.next.next.value.left = n; + } + // done + } + } else { + if (ancestors.next.value.left.red) { + ancestors.value.red = false; + ancestors.next.value.left = new Node(ancestors.next.value.left); + ancestors.next.value.left.red = false; + ancestors.next.value.red = true; + new_ = ancestors.next.value; + ancestors = ancestors.next.next; + } else { + if (new_ == ancestors.value.left) { + new_ = ancestors.value; + ancestors = ancestors.next; + + Node n = rightRotate(new_); + if (ancestors.value.right == new_) { + ancestors.value.right = n; + } else { + ancestors.value.left = n; + } + ancestors = new Cell(n, ancestors); + } + ancestors.value.red = false; + ancestors.next.value.red = true; + + Node n = leftRotate(ancestors.next.value); + if (ancestors.next.next == null) { + newRoot = n; + } else if (ancestors.next.next.value.right == ancestors.next.value) { + ancestors.next.next.value.right = n; + } else { + ancestors.next.next.value.left = n; + } + // done + } + } + } + + newRoot.red = false; + + return new PersistentSet(newRoot, comparator, size + 1); + } + + private static Node leftRotate(Node n) { + Node child = new Node(n.right); + n.right = child.left; + child.left = n; + return child; + } + + private static Node rightRotate(Node n) { + Node child = new Node(n.left); + n.left = child.right; + child.right = n; + return child; + } + + public PersistentSet remove(T value) { + Path p = find(value); + if (! p.fresh) { + return remove(p); + } + + return this; + } + + private PersistentSet remove(Path p) { + if (size == 1) { + if (p.node != root) { + throw new IllegalArgumentException(); + } + return new PersistentSet(NullNode, comparator, 0); + } + + Node new_ = p.node; + Node newRoot = p.root.root; + Cell> ancestors = p.ancestors; + + Node dead; + if (new_.left == NullNode || new_.right == NullNode) { + dead = new_; + } else { + Cell> path = successor(new_, ancestors); + dead = path.value; + ancestors = path.next; + } + + Node child; + if (dead.left != NullNode) { + child = new Node(dead.left); + } else if (dead.right != NullNode) { + child = new Node(dead.right); + } else { + child = NullNode; + } + + if (ancestors == null) { + child.red = false; + return new PersistentSet(child, comparator, 1); + } else if (dead == ancestors.value.left) { + ancestors.value.left = child; + } else { + ancestors.value.right = child; + } + + if (dead != new_) { + new_.value = dead.value; + } + + if (! dead.red) { + // rebalance + while (ancestors != null && ! child.red) { + if (child == ancestors.value.left) { + Node sibling = ancestors.value.right + = new Node(ancestors.value.right); + if (sibling.red) { + sibling.red = false; + ancestors.value.red = true; + + Node n = leftRotate(ancestors.value); + if (ancestors.next == null) { + newRoot = n; + } else if (ancestors.next.value.right == ancestors.value) { + ancestors.next.value.right = n; + } else { + ancestors.next.value.left = n; + } + ancestors.next = new Cell(n, ancestors.next); + + sibling = ancestors.value.right = new Node(ancestors.value.right); + } + + if (! (sibling.left.red || sibling.right.red)) { + sibling.red = true; + child = ancestors.value; + ancestors = ancestors.next; + } else { + if (! sibling.right.red) { + sibling.left = new Node(sibling.left); + sibling.left.red = false; + + sibling.red = true; + sibling = ancestors.value.right = rightRotate(sibling); + } + + sibling.red = ancestors.value.red; + ancestors.value.red = false; + + sibling.right = new Node(sibling.right); + sibling.right.red = false; + + Node n = leftRotate(ancestors.value); + if (ancestors.next == null) { + newRoot = n; + } else if (ancestors.next.value.right == ancestors.value) { + ancestors.next.value.right = n; + } else { + ancestors.next.value.left = n; + } + + child = newRoot; + ancestors = null; + } + } else { + Node sibling = ancestors.value.left + = new Node(ancestors.value.left); + if (sibling.red) { + sibling.red = false; + ancestors.value.red = true; + + Node n = rightRotate(ancestors.value); + if (ancestors.next == null) { + newRoot = n; + } else if (ancestors.next.value.left == ancestors.value) { + ancestors.next.value.left = n; + } else { + ancestors.next.value.right = n; + } + ancestors.next = new Cell(n, ancestors.next); + + sibling = ancestors.value.left = new Node(ancestors.value.left); + } + + if (! (sibling.right.red || sibling.left.red)) { + sibling.red = true; + child = ancestors.value; + ancestors = ancestors.next; + } else { + if (! sibling.left.red) { + sibling.right = new Node(sibling.right); + sibling.right.red = false; + + sibling.red = true; + sibling = ancestors.value.left = leftRotate(sibling); + } + + sibling.red = ancestors.value.red; + ancestors.value.red = false; + + sibling.left = new Node(sibling.left); + sibling.left.red = false; + + Node n = rightRotate(ancestors.value); + if (ancestors.next == null) { + newRoot = n; + } else if (ancestors.next.value.left == ancestors.value) { + ancestors.next.value.left = n; + } else { + ancestors.next.value.right = n; + } + + child = newRoot; + ancestors = null; + } + } + } + + child.red = false; + } + + return new PersistentSet(newRoot, comparator, size - 1); + } + + private static Cell> minimum(Node n, + Cell> ancestors) + { + while (n.left != NullNode) { + n.left = new Node(n.left); + ancestors = new Cell(n, ancestors); + n = n.left; + } + + return new Cell(n, ancestors); + } + + private static Cell> maximum(Node n, + Cell> ancestors) + { + while (n.right != NullNode) { + n.right = new Node(n.right); + ancestors = new Cell(n, ancestors); + n = n.right; + } + + return new Cell(n, ancestors); + } + + private static Cell> successor(Node n, + Cell> ancestors) + { + if (n.right != NullNode) { + n.right = new Node(n.right); + return minimum(n.right, new Cell(n, ancestors)); + } + + while (ancestors != null && n == ancestors.value.right) { + n = ancestors.value; + ancestors = ancestors.next; + } + + return ancestors; + } + + private static Cell> predecessor(Node n, + Cell> ancestors) + { + if (n.left != NullNode) { + n.left = new Node(n.left); + return maximum(n.left, new Cell(n, ancestors)); + } + + while (ancestors != null && n == ancestors.value.left) { + n = ancestors.value; + ancestors = ancestors.next; + } + + return ancestors; + } + + public Path find(T value) { + Node newRoot = new Node(root); + Cell> ancestors = null; + + Node old = root; + Node new_ = newRoot; + while (old != NullNode) { + ancestors = new Cell(new_, ancestors); + + int difference = comparator.compare(value, old.value); + if (difference < 0) { + old = old.left; + new_ = new_.left = new Node(old); + } else if (difference > 0) { + old = old.right; + new_ = new_.right = new Node(old); + } else { + return new Path(false, new_, + new PersistentSet(newRoot, comparator, size), + ancestors.next); + } + } + + new_.value = value; + return new Path(true, new_, + new PersistentSet(newRoot, comparator, size), + ancestors); + } + + public Path first() { + if (root == NullNode) return null; + + Node newRoot = new Node(root); + Cell> ancestors = null; + + Node old = root; + Node new_ = newRoot; + while (old.left != NullNode) { + ancestors = new Cell(new_, ancestors); + + old = old.left; + new_ = new_.left = new Node(old); + } + + return new Path(true, new_, + new PersistentSet(newRoot, comparator, size), + ancestors); + } + + public Path last() { + if (root == NullNode) return null; + + Node newRoot = new Node(root); + Cell> ancestors = null; + + Node old = root; + Node new_ = newRoot; + while (old.right != NullNode) { + ancestors = new Cell(new_, ancestors); + + old = old.right; + new_ = new_.right = new Node(old); + } + + return new Path(true, new_, + new PersistentSet(newRoot, comparator, size), + ancestors); + } + + public java.util.Iterator iterator() { + return new Iterator(first()); + } + + private Path successor(Path p) { + Cell> s = successor(p.node, p.ancestors); + if (s == null) { + return null; + } else { + return new Path(false, s.value, p.root, s.next); + } + } + + private Path predecessor(Path p) { + Cell> s = predecessor(p.node, p.ancestors); + if (s == null) { + return null; + } else { + return new Path(false, s.value, p.root, s.next); + } + } + + private static class Node { + public T value; + public Node left; + public Node right; + public boolean red; + + public Node(Node basis) { + if (basis != null) { + value = basis.value; + left = basis.left; + right = basis.right; + red = basis.red; + } + } + } + + public static class Path { + private final boolean fresh; + private final Node node; + private final PersistentSet root; + private final Cell> ancestors; + + public Path(boolean fresh, Node node, PersistentSet root, + Cell> ancestors) + { + this.fresh = fresh; + this.node = node; + this.root = root; + this.ancestors = ancestors; + } + + public T value() { + return node.value; + } + + public boolean fresh() { + return fresh; + } + + public PersistentSet root() { + return root; + } + + public Path successor() { + return root.successor(this); + } + + public Path predecessor() { + return root.predecessor(this); + } + + public PersistentSet remove() { + if (fresh) throw new IllegalStateException(); + + return root.remove(this); + } + + public PersistentSet add() { + if (! fresh) throw new IllegalStateException(); + + return root.add(this); + } + + public PersistentSet replaceWith(T value) { + if (fresh) throw new IllegalStateException(); + if (root.comparator.compare(node.value, value) != 0) + throw new IllegalArgumentException(); + + node.value = value; + return root; + } + } + + public class Iterator implements java.util.Iterator { + private PersistentSet.Path path; + + private Iterator(PersistentSet.Path path) { + this.path = path; + } + + private Iterator(Iterator start) { + path = start.path; + } + + public boolean hasNext() { + return path != null; + } + + public T next() { + PersistentSet.Path p = path; + path = path.successor(); + return p.value(); + } + + public void remove() { + throw new UnsupportedOperationException(); + } + } +} diff --git a/sgx-jvm/avian/classpath/avian/Singleton.java b/sgx-jvm/avian/classpath/avian/Singleton.java new file mode 100644 index 0000000000..c866169b6e --- /dev/null +++ b/sgx-jvm/avian/classpath/avian/Singleton.java @@ -0,0 +1,19 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package avian; + +public abstract class Singleton { + public static native int getInt(Object singleton, int offset); + public static native long getLong(Object singleton, int offset); + public static native Object getObject(Object singleton, int offset); + + // Fields in types.def +} diff --git a/sgx-jvm/avian/classpath/avian/Stream.java b/sgx-jvm/avian/classpath/avian/Stream.java new file mode 100644 index 0000000000..eb2859d432 --- /dev/null +++ b/sgx-jvm/avian/classpath/avian/Stream.java @@ -0,0 +1,80 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package avian; + +import java.io.InputStream; +import java.io.OutputStream; +import java.io.IOException; +import java.io.EOFException; + +public abstract class Stream { + public static void write1(OutputStream out, int v) throws IOException { + out.write(v & 0xFF); + } + + public static int read1(InputStream in) throws IOException { + return in.read(); + } + + public static void write2(OutputStream out, int v) throws IOException { + out.write((v >>> 8) & 0xFF); + out.write((v ) & 0xFF); + } + + public static int read2(InputStream in) throws IOException { + int b1 = in.read(); + int b2 = in.read(); + if (b2 == -1) throw new EOFException(); + return ((b1 << 8) | (b2 & 0xFF)); + } + + public static void write4(OutputStream out, int v) throws IOException { + out.write((v >>> 24) & 0xFF); + out.write((v >>> 16) & 0xFF); + out.write((v >>> 8) & 0xFF); + out.write((v ) & 0xFF); + } + + public static int read4(InputStream in) throws IOException { + int b1 = in.read(); + int b2 = in.read(); + int b3 = in.read(); + int b4 = in.read(); + if (b4 == -1) throw new EOFException(); + return ((b1 << 24) | (b2 << 16) | (b3 << 8) | (b4)); + } + + public static void write8(OutputStream out, long v) throws IOException { + write4(out, (int) (v >>> 32) & 0xFFFFFFFF); + write4(out, (int) (v ) & 0xFFFFFFFF); + } + + public static long read8(InputStream in) throws IOException { + long b1 = in.read(); + long b2 = in.read(); + long b3 = in.read(); + long b4 = in.read(); + long b5 = in.read(); + long b6 = in.read(); + long b7 = in.read(); + long b8 = in.read(); + if (b8 == -1) throw new EOFException(); + return ((b1 << 56) | (b2 << 48) | (b3 << 40) | (b4 << 32) | + (b5 << 24) | (b6 << 16) | (b7 << 8) | (b8)); + } + + public static void set4(byte[] array, int offset, int v) { + array[offset ] = (byte) ((v >>> 24) & 0xFF); + array[offset + 1] = (byte) ((v >>> 16) & 0xFF); + array[offset + 2] = (byte) ((v >>> 8) & 0xFF); + array[offset + 3] = (byte) ((v ) & 0xFF); + } +} diff --git a/sgx-jvm/avian/classpath/avian/SystemClassLoader.java b/sgx-jvm/avian/classpath/avian/SystemClassLoader.java new file mode 100644 index 0000000000..5dd2ee4352 --- /dev/null +++ b/sgx-jvm/avian/classpath/avian/SystemClassLoader.java @@ -0,0 +1,176 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package avian; + +import java.net.URL; +import java.net.MalformedURLException; +import java.io.IOException; +import java.util.Collection; +import java.util.Collections; +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.NoSuchElementException; + +public class SystemClassLoader extends ClassLoader { + public static native ClassLoader appLoader(); + + private native VMClass findVMClass(String name) + throws ClassNotFoundException; + + protected Class findClass(String name) throws ClassNotFoundException { + return getClass(findVMClass(name)); + } + + public static native Class getClass(VMClass vmClass); + + public static native VMClass vmClass(Class jClass); + + private native VMClass findLoadedVMClass(String name); + + protected Class reallyFindLoadedClass(String name){ + VMClass c = findLoadedVMClass(name); + return c == null ? null : getClass(c); + } + + protected Class loadClass(String name, boolean resolve) + throws ClassNotFoundException + { + Class c = findLoadedClass(name); + if (c == null) { + ClassLoader parent = getParent(); + if (parent != null) { + try { + c = parent.loadClass(name); + } catch (ClassNotFoundException ok) { } + } + + if (c == null) { + c = findClass(name); + } + } + + if (resolve) { + resolveClass(c); + } + + return c; + } + + private native String resourceURLPrefix(String name); + + protected URL findResource(String name) { + String prefix = resourceURLPrefix(name); + if (prefix != null) { + try { + return new URL(prefix + name); + } catch (MalformedURLException ignored) { } + } + return null; + } + + protected Package getPackage(String name) { + Package p = super.getPackage(name); + if (p == null) { + String source = getPackageSource(name); + if (source != null) { + // todo: load attributes from JAR manifest + definePackage(name, null, null, null, null, null, null, null); + } else { + definePackage(name, null, null, null, null, null, null, null); + } + } + + return super.getPackage(name); + } + + protected static native String getPackageSource(String name); + + // OpenJDK's java.lang.ClassLoader.getResource makes use of + // sun.misc.Launcher to load bootstrap resources, which is not + // appropriate for the Avian build, so we override it to ensure we + // get the behavior we want. This implementation is the same as + // that of Avian's java.lang.ClassLoader.getResource. + public URL getResource(String path) { + URL url = null; + ClassLoader parent = getParent(); + if (parent != null) { + url = parent.getResource(path); + } + + if (url == null) { + url = findResource(path); + } + + return url; + } + + // As above, we override this method to avoid inappropriate behavior + // in OpenJDK's java.lang.ClassLoader.getResources. + public Enumeration getResources(String name) throws IOException { + Collection urls = new ArrayList(5); + + ClassLoader parent = getParent(); + if (parent != null) { + for (Enumeration e = parent.getResources(name); + e.hasMoreElements();) + { + urls.add(e.nextElement()); + } + } + + Enumeration urls2 = findResources(name); + while (urls2.hasMoreElements()) { + urls.add(urls2.nextElement()); + } + + return Collections.enumeration(urls); + } + + private class ResourceEnumeration implements Enumeration { + private long[] finderElementPtrPtr; + private String name, urlPrefix; + + public ResourceEnumeration(String name) { + this.name = name; + finderElementPtrPtr = new long[1]; + urlPrefix = nextResourceURLPrefix(); + } + + private native String nextResourceURLPrefix(SystemClassLoader loader, + String name, long[] finderElementPtrPtr); + + private String nextResourceURLPrefix() { + return nextResourceURLPrefix(SystemClassLoader.this, name, + finderElementPtrPtr); + } + + public boolean hasMoreElements() { + return urlPrefix != null; + } + + public URL nextElement() { + if (urlPrefix == null) throw new NoSuchElementException(); + URL result; + try { + result = new URL(urlPrefix + name); + } catch (MalformedURLException ignored) { + result = null; + } + if (finderElementPtrPtr[0] == 0l) urlPrefix = null; + else urlPrefix = nextResourceURLPrefix(); + return result; + } + } + + protected Enumeration findResources(String name) { + return new ResourceEnumeration(name); + } +} diff --git a/sgx-jvm/avian/classpath/avian/Traces.java b/sgx-jvm/avian/classpath/avian/Traces.java new file mode 100644 index 0000000000..e9c106c7c9 --- /dev/null +++ b/sgx-jvm/avian/classpath/avian/Traces.java @@ -0,0 +1,71 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package avian; + +import java.net.InetSocketAddress; +import java.nio.ByteBuffer; +import java.nio.channels.ServerSocketChannel; +import java.nio.channels.SocketChannel; + +public class Traces { + private static final String Newline = System.getProperty("line.separator"); + + private static String traceAllThreads() { + StringBuilder buffer = new StringBuilder(); + + Thread[] threads = new Thread[Thread.activeCount()]; + + int count = Thread.enumerate(threads); + for (int i = 0; i < count; ++i) { + traceThread(threads[i], buffer); + } + + return buffer.toString(); + } + + private static String traceThread(Thread thread) { + StringBuilder buffer = new StringBuilder(); + + traceThread(thread, buffer); + + return buffer.toString(); + } + + private static void traceThread(Thread thread, StringBuilder buffer) { + buffer.append(thread).append(Newline); + for (StackTraceElement e: thread.getStackTrace()) { + buffer.append("\tat ").append(e).append(Newline); + } + } + + public static void startTraceListener(final String host, final int port) { + Thread t = new Thread(new Runnable() { + public void run() { + try { + ServerSocketChannel server = ServerSocketChannel.open(); + server.socket().bind(new InetSocketAddress(host, port)); + while (true) { + SocketChannel c = server.accept(); + try { + c.write(ByteBuffer.wrap(traceAllThreads().getBytes())); + } finally { + c.close(); + } + } + } catch (Exception e) { + e.printStackTrace(); + } + } + }); + t.setDaemon(true); + t.start(); + } +} diff --git a/sgx-jvm/avian/classpath/avian/Utf8.java b/sgx-jvm/avian/classpath/avian/Utf8.java new file mode 100644 index 0000000000..2c32fec9de --- /dev/null +++ b/sgx-jvm/avian/classpath/avian/Utf8.java @@ -0,0 +1,118 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package avian; + +import java.io.ByteArrayOutputStream; + +public class Utf8 { + public static boolean test(Object data) { + if (!(data instanceof byte[])) return false; + byte[] b = (byte[])data; + for (int i = 0; i < b.length; ++i) { + if (((int)b[i] & 0x080) != 0) return true; + } + return false; + } + + public static byte[] encode(char[] s16, int offset, int length) { + ByteArrayOutputStream buf = new ByteArrayOutputStream(); + for (int i = offset; i < offset+length; ++i) { + char c = s16[i]; + if (c == '\u0000') { // null char + buf.write(0); + buf.write(0); + } else if (c < 0x080) { // 1 byte char + buf.write(c); + } else if (c < 0x0800) { // 2 byte char + buf.write(0x0c0 | (c >>> 6)); + buf.write(0x080 | (c & 0x03f)); + } else { // 3 byte char + buf.write(0x0e0 | ((c >>> 12) & 0x0f)); + buf.write(0x080 | ((c >>> 6) & 0x03f)); + buf.write(0x080 | (c & 0x03f)); + } + } + return buf.toByteArray(); + } + + public static Object decode(byte[] s8, int offset, int length) { + Object buf = new byte[length]; + boolean isMultiByte = false; + int i=offset, j=0; + while (i < offset+length) { + int x = s8[i++]; + if ((x & 0x080) == 0x0) { // 1 byte char + if (x == 0) { // 2 byte null char + if (i == offset + length) { + return null; + } + ++ i; + } + cram(buf, j++, x); + } else if ((x & 0x0e0) == 0x0c0) { // 2 byte char + if (i == offset + length) { + return null; + } + + if (!isMultiByte) { + buf = widen(buf, j, length-1); + isMultiByte = true; + } + int y = s8[i++]; + cram(buf, j++, ((x & 0x1f) << 6) | (y & 0x3f)); + } else if ((x & 0x0f0) == 0x0e0) { // 3 byte char + if (i + 1 >= offset + length) { + return null; + } + + if (!isMultiByte) { + buf = widen(buf, j, length-2); + isMultiByte = true; + } + int y = s8[i++]; int z = s8[i++]; + cram(buf, j++, ((x & 0xf) << 12) | ((y & 0x3f) << 6) | (z & 0x3f)); + } + } + + return trim(buf, j); + } + + public static char[] decode16(byte[] s8, int offset, int length) { + Object decoded = decode(s8, offset, length); + if (decoded == null) { + return null; + } else if (decoded instanceof char[]) { + return (char[])decoded; + } else { + return (char[])widen(decoded, length, length); + } + } + + private static void cram(Object data, int index, int val) { + if (data instanceof byte[]) ((byte[])data)[index] = (byte)val; + else ((char[])data)[index] = (char)val; + } + + private static Object widen(Object data, int length, int capacity) { + byte[] src = (byte[])data; + char[] result = new char[capacity]; + for (int i = 0; i < length; ++i) result[i] = (char)((int)src[i] & 0x0ff); + return result; + } + + private static Object trim(Object data, int length) { + if (data instanceof byte[]) return data; + if (((char[])data).length == length) return data; + char[] result = new char[length]; + System.arraycopy(data, 0, result, 0, length); + return result; + } +} diff --git a/sgx-jvm/avian/classpath/avian/VMClass.java b/sgx-jvm/avian/classpath/avian/VMClass.java new file mode 100644 index 0000000000..8960670775 --- /dev/null +++ b/sgx-jvm/avian/classpath/avian/VMClass.java @@ -0,0 +1,42 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package avian; + +public class VMClass { + public short flags; + public short vmFlags; + public short fixedSize; + public byte arrayElementSize; + public byte arrayDimensions; + public VMClass arrayElementClass; + public int runtimeDataIndex; + public int[] objectMask; + public byte[] name; + public byte[] sourceFile; + public VMClass super_; + public Object[] interfaceTable; + public VMMethod[] virtualTable; + public VMField[] fieldTable; + /** + * Methods declared in this class, plus any abstract virtual methods + * inherited from implemented or extended interfaces. If addendum + * is non-null and addendum.declaredMethodCount is non-negative, + * then the first addendum.declaredMethodCount methods are declared + * methods, while the rest are abstract virtual methods. If + * addendum is null or addendum.declaredMethodCount is negative, all + * are declared methods. + */ + public VMMethod[] methodTable; + public ClassAddendum addendum; + public Singleton staticTable; + public ClassLoader loader; + public byte[] source; +} diff --git a/sgx-jvm/avian/classpath/avian/VMField.java b/sgx-jvm/avian/classpath/avian/VMField.java new file mode 100644 index 0000000000..2f2715d121 --- /dev/null +++ b/sgx-jvm/avian/classpath/avian/VMField.java @@ -0,0 +1,23 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package avian; + +public class VMField { + public byte vmFlags; + public byte code; + public short flags; + public short offset; + public int nativeID; + public byte[] name; + public byte[] spec; + public FieldAddendum addendum; + public VMClass class_; +} diff --git a/sgx-jvm/avian/classpath/avian/VMMethod.java b/sgx-jvm/avian/classpath/avian/VMMethod.java new file mode 100644 index 0000000000..53af6e9c80 --- /dev/null +++ b/sgx-jvm/avian/classpath/avian/VMMethod.java @@ -0,0 +1,31 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package avian; + +public class VMMethod { + public byte vmFlags; + public byte returnCode; + public byte parameterCount; + public byte parameterFootprint; + public short flags; + public short offset; + public int nativeID; + public int runtimeDataIndex; + public byte[] name; + public byte[] spec; + public MethodAddendum addendum; + public VMClass class_; + public Code code; + + public boolean hasAnnotations() { + return addendum != null && addendum.annotationTable != null; + } +} diff --git a/sgx-jvm/avian/classpath/avian/avianvmresource/Handler.java b/sgx-jvm/avian/classpath/avian/avianvmresource/Handler.java new file mode 100644 index 0000000000..2e25a6bafc --- /dev/null +++ b/sgx-jvm/avian/classpath/avian/avianvmresource/Handler.java @@ -0,0 +1,111 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package avian.avianvmresource; + +import java.net.URL; +import java.net.URLStreamHandler; +import java.net.URLConnection; +import java.io.IOException; +import java.io.FileNotFoundException; +import java.io.InputStream; + +public class Handler extends URLStreamHandler { + protected URLConnection openConnection(URL url) { + return new ResourceConnection(url); + } + + private static class ResourceConnection extends URLConnection { + public ResourceConnection(URL url) { + super(url); + } + + public int getContentLength() { + return ResourceInputStream.getContentLength(url.getFile()); + } + + public InputStream getInputStream() throws IOException { + return new ResourceInputStream(url.getFile()); + } + + public void connect() { + // ignore + } + } + + private static class ResourceInputStream extends InputStream { + private long peer; + private int position; + + public ResourceInputStream(String path) throws IOException { + peer = open(path); + if (peer == 0) { + throw new FileNotFoundException(path); + } + } + + private static native int getContentLength(String path); + + private static native long open(String path) throws IOException; + + private static native int read(long peer, int position) throws IOException; + + private static native int read(long peer, int position, + byte[] b, int offset, int length) + throws IOException; + + public static native void close(long peer) throws IOException; + + public static native int available(long peer, int position); + + public int available() { + return available(peer, position); + } + + public int read() throws IOException { + if (peer != 0) { + int c = read(peer, position); + if (c >= 0) { + ++ position; + } + return c; + } else { + throw new IOException(); + } + } + + public int read(byte[] b, int offset, int length) throws IOException { + if (peer != 0) { + if (b == null) { + throw new NullPointerException(); + } + + if (offset < 0 || offset + length > b.length) { + throw new ArrayIndexOutOfBoundsException(); + } + + int c = read(peer, position, b, offset, length); + if (c >= 0) { + position += c; + } + return c; + } else { + throw new IOException(); + } + } + + public void close() throws IOException { + if (peer != 0) { + close(peer); + peer = 0; + } + } + } +} diff --git a/sgx-jvm/avian/classpath/avian/file/Handler.java b/sgx-jvm/avian/classpath/avian/file/Handler.java new file mode 100644 index 0000000000..2ac476ff65 --- /dev/null +++ b/sgx-jvm/avian/classpath/avian/file/Handler.java @@ -0,0 +1,44 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package avian.file; + +import java.net.URL; +import java.net.URLStreamHandler; +import java.net.URLConnection; +import java.io.IOException; +import java.io.FileNotFoundException; +import java.io.File; +import java.io.FileInputStream; +import java.io.InputStream; + +public class Handler extends URLStreamHandler { + protected URLConnection openConnection(URL url) { + return new FileURLConnection(url); + } + + private static class FileURLConnection extends URLConnection { + public FileURLConnection(URL url) { + super(url); + } + + public int getContentLength() { + return (int) new File(url.getFile()).length(); + } + + public InputStream getInputStream() throws IOException { + return new FileInputStream(new File(url.getFile())); + } + + public void connect() { + // ignore + } + } +} diff --git a/sgx-jvm/avian/classpath/avian/http/Handler.java b/sgx-jvm/avian/classpath/avian/http/Handler.java new file mode 100644 index 0000000000..28f36d4194 --- /dev/null +++ b/sgx-jvm/avian/classpath/avian/http/Handler.java @@ -0,0 +1,120 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package avian.http; + +import java.io.BufferedInputStream; +import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.net.Socket; +import java.net.URL; +import java.net.URLConnection; +import java.net.URLStreamHandler; +import java.util.HashMap; +import java.util.Map; + +public class Handler extends URLStreamHandler +{ + public URLConnection openConnection(URL url) throws IOException + { + return new HttpURLConnection(url); + } + + class HttpURLConnection extends URLConnection + { + Socket socket; + private BufferedWriter writer; + private InputStream bin; + private Map header = new HashMap(); + private int status; + + protected HttpURLConnection(URL url) + { + super(url); + } + + @Override + public void connect() throws IOException + { + if(socket == null) + { + URLConnection con = null; + String host = url.getHost(); + int port =url.getPort(); + if(port < 0) port = 80; + socket = new Socket(host, port); + OutputStream out = socket.getOutputStream(); + writer = new BufferedWriter(new OutputStreamWriter(out)); + writer.write("GET " + url.getPath() + " HTTP/1.1"); + writer.write("\r\nHost: " + host); + writer.write("\r\n\r\n"); + writer.flush(); + bin = new BufferedInputStream(socket.getInputStream()); + readHeader(); +// System.out.println("Status: " + status); +// System.out.println("Headers: " + header); + } + } + + private void readHeader() throws IOException + { + byte[] buf = new byte[8192]; + int b = 0; + int index = 0; + while(b >= 0) + { + if(index >= 4 && buf[index-4] == '\r' && buf[index-3] == '\n' && buf[index-2] == '\r' && buf[index-1] == '\n') + { + break; + } + b = bin.read(); + buf[index] = (byte) b; + index++; + if(index >= buf.length) + { + throw new IOException("Header exceeded maximum size of 8k."); + } + } + BufferedReader reader = new BufferedReader(new InputStreamReader(new ByteArrayInputStream(buf, 0, index))); + String line = reader.readLine(); + int x = line.indexOf(' '); + status = Integer.parseInt(line.substring(x + 1 , line.indexOf(' ', x+1))); + while(line != null) + { + int i = line.indexOf(':'); + if(i > 0) + { + header.put(line.substring(0, i), line.substring(i + 1) .trim()); + } + line = reader.readLine(); + } + reader.close(); + } + + @Override + public InputStream getInputStream() throws IOException + { + connect(); + return bin; + } + + @Override + public OutputStream getOutputStream() throws IOException + { + throw new UnsupportedOperationException("Can' write to HTTP Connection"); + } + } +} diff --git a/sgx-jvm/avian/classpath/avian/jar/Handler.java b/sgx-jvm/avian/classpath/avian/jar/Handler.java new file mode 100644 index 0000000000..b4a24de288 --- /dev/null +++ b/sgx-jvm/avian/classpath/avian/jar/Handler.java @@ -0,0 +1,84 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package avian.jar; + +import java.net.URL; +import java.net.MalformedURLException; +import java.net.URLStreamHandler; +import java.net.JarURLConnection; +import java.net.URLConnection; +import java.io.IOException; +import java.io.FileNotFoundException; +import java.io.InputStream; +import java.util.jar.JarFile; +import java.util.jar.JarEntry; + +public class Handler extends URLStreamHandler { + protected URLConnection openConnection(URL url) { + return new MyJarURLConnection(url); + } + + protected void parseURL(URL url, String s, int start, int end) + throws MalformedURLException + { + // skip "jar:" + s = s.toString().substring(4); + int index = s.indexOf("!/"); + if (index < 0) { + throw new MalformedURLException(); + } + + URL file = new URL(s.substring(0, index)); + if (! "file".equals(file.getProtocol())) { + throw new RuntimeException + ("protocol " + file.getProtocol() + " not yet supported"); + } + + url.set("jar", null, -1, s, null); + } + + private static class MyJarURLConnection extends JarURLConnection { + private final JarFile file; + private final JarEntry entry; + + public MyJarURLConnection(URL url) { + super(url); + + String s = url.getFile(); + int index = s.indexOf("!/"); + + try { + this.file = new JarFile(new URL(s.substring(0, index)).getFile()); + this.entry = this.file.getJarEntry(s.substring(index + 2)); + } catch (MalformedURLException e) { + throw new RuntimeException(e); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + public JarFile getJarFile() throws IOException { + return file; + } + + public int getContentLength() { + return (int)entry.getSize(); + } + + public InputStream getInputStream() throws IOException { + return file.getInputStream(entry); + } + + public void connect() { + // ignore + } + } +} diff --git a/sgx-jvm/avian/classpath/dalvik/system/BaseDexClassLoader.java b/sgx-jvm/avian/classpath/dalvik/system/BaseDexClassLoader.java new file mode 100644 index 0000000000..27049cea21 --- /dev/null +++ b/sgx-jvm/avian/classpath/dalvik/system/BaseDexClassLoader.java @@ -0,0 +1,5 @@ +package dalvik.system; + +public class BaseDexClassLoader extends ClassLoader { + public native String getLdLibraryPath(); +} diff --git a/sgx-jvm/avian/classpath/java-io.cpp b/sgx-jvm/avian/classpath/java-io.cpp new file mode 100644 index 0000000000..2ca5ee04d1 --- /dev/null +++ b/sgx-jvm/avian/classpath/java-io.cpp @@ -0,0 +1,1015 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#include +#include +#include +#include +#include +#include + +#include "jni.h" +#include "jni-util.h" + +#ifdef PLATFORM_WINDOWS + +#define UNICODE + +#include +#include +#include +#include + +#define ACCESS _waccess +#define CLOSE _close +#define READ _read +#define WRITE _write +#define STAT _wstat +#define STRUCT_STAT struct _stat +#define MKDIR(path, mode) _wmkdir(path) +#define CHMOD(path, mode) _wchmod(path, mode) +#define REMOVE _wremove +#define RENAME _wrename +#define OPEN_MASK O_BINARY + +#define CHECK_X_OK R_OK + +#ifdef _MSC_VER +#define S_ISREG(x) ((x)&_S_IFREG) +#define S_ISDIR(x) ((x)&_S_IFDIR) +#define S_IRUSR _S_IREAD +#define S_IWUSR _S_IWRITE +#define W_OK 2 +#define R_OK 4 +#else +#define OPEN _wopen +#endif + +#define GET_CHARS GetStringChars +#define RELEASE_CHARS(path, chars) \ + ReleaseStringChars(path, reinterpret_cast(chars)) + +typedef wchar_t char_t; + +#if defined(WINAPI_FAMILY) +#if !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) + +#include "avian-interop.h" +#define SKIP_OPERATOR_NEW + +#endif +#endif + +#else // not PLATFORM_WINDOWS + +#include +#include +#include "sys/mman.h" + +#define ACCESS access +#define OPEN open +#define CLOSE close +#define READ read +#define WRITE write +#define STAT stat +#define STRUCT_STAT struct stat +#define MKDIR mkdir +#define CHMOD chmod +#define REMOVE remove +#define RENAME rename +#define OPEN_MASK 0 + +#define CHECK_X_OK X_OK + +#define GET_CHARS GetStringUTFChars +#define RELEASE_CHARS ReleaseStringUTFChars + +typedef char char_t; + +#endif // not PLATFORM_WINDOWS + +#ifndef WINAPI_FAMILY +#ifndef WINAPI_PARTITION_DESKTOP +#define WINAPI_PARTITION_DESKTOP 1 +#endif + +#ifndef WINAPI_FAMILY_PARTITION +#define WINAPI_FAMILY_PARTITION(x) (x) +#endif +#endif // WINAPI_FAMILY + +#if !defined(SKIP_OPERATOR_NEW) +inline void* operator new(size_t, void* p) throw() +{ + return p; +} +#endif + +typedef const char_t* string_t; + +namespace { + +#ifdef _MSC_VER +inline int OPEN(string_t path, int mask, int mode) +{ + int fd; + if (_wsopen_s(&fd, path, mask, _SH_DENYNO, mode) == 0) { + return fd; + } else { + return -1; + } +} +#endif + +inline bool exists(string_t path) +{ +#ifdef PLATFORM_WINDOWS + return GetFileAttributesW(path) != INVALID_FILE_ATTRIBUTES; +#else + STRUCT_STAT s; + return STAT(path, &s) == 0; +#endif +} + +inline int doOpen(JNIEnv* e, string_t path, int mask) +{ + int fd = OPEN(path, mask | OPEN_MASK, S_IRUSR | S_IWUSR); + if (fd == -1) { + if (errno == ENOENT) { + throwNewErrno(e, "java/io/FileNotFoundException"); + } else { + throwNewErrno(e, "java/io/IOException"); + } + } + return fd; +} + +inline void doClose(JNIEnv* e, jint fd) +{ + int r = CLOSE(fd); + if (r == -1) { + throwNewErrno(e, "java/io/IOException"); + } +} + +inline int doRead(JNIEnv* e, jint fd, jbyte* data, jint length) +{ + int r = READ(fd, data, length); + if (r > 0) { + return r; + } else if (r == 0) { + return -1; + } else { + throwNewErrno(e, "java/io/IOException"); + return 0; + } +} + +inline void doWrite(JNIEnv* e, jint fd, const jbyte* data, jint length) +{ + int r = WRITE(fd, data, length); + if (r != length) { + throwNewErrno(e, "java/io/IOException"); + } +} + +#ifdef PLATFORM_WINDOWS + +class Directory { + public: + Directory() : handle(0), findNext(false) + { + } + + virtual string_t next() + { + if (handle and handle != INVALID_HANDLE_VALUE) { + if (findNext) { + if (FindNextFileW(handle, &data)) { + return data.cFileName; + } + } else { + findNext = true; + return data.cFileName; + } + } + return 0; + } + + virtual void dispose() + { + if (handle and handle != INVALID_HANDLE_VALUE) { + FindClose(handle); + } + free(this); + } + + HANDLE handle; + WIN32_FIND_DATAW data; + bool findNext; +}; + +#else // not PLATFORM_WINDOWS + +#endif // not PLATFORM_WINDOWS + +} // namespace + +static inline string_t getChars(JNIEnv* e, jstring path) +{ + return reinterpret_cast(e->GET_CHARS(path, 0)); +} + +static inline void releaseChars(JNIEnv* e, jstring path, string_t chars) +{ + e->RELEASE_CHARS(path, chars); +} + +#ifndef SGX + +extern "C" JNIEXPORT jstring JNICALL + Java_java_io_File_toCanonicalPath(JNIEnv* /*e*/, jclass, jstring path) +{ + // todo + return path; +} + +extern "C" JNIEXPORT jstring JNICALL + Java_java_io_File_toAbsolutePath(JNIEnv* e UNUSED, jclass, jstring path) +{ +#ifdef PLATFORM_WINDOWS +#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) + string_t chars = getChars(e, path); + if (chars) { + const unsigned BufferSize = MAX_PATH; + char_t buffer[BufferSize]; + DWORD success = GetFullPathNameW(chars, BufferSize, buffer, 0); + releaseChars(e, path, chars); + + if (success) { + return e->NewString(reinterpret_cast(buffer), + wcslen(buffer)); + } + } + + return path; +#else + string_t chars = getChars(e, path); + if (chars) { + std::wstring partialPath = chars; + releaseChars(e, path, chars); + + std::wstring fullPath = AvianInterop::GetFullPath(partialPath); + + return e->NewString(reinterpret_cast(fullPath.c_str()), + fullPath.length()); + } + return path; +#endif +#else + jstring result = path; + string_t chars = getChars(e, path); + if (chars) { + if (chars[0] != '/') { + char* cwd = getcwd(NULL, 0); + if (cwd) { + unsigned size = strlen(cwd) + strlen(chars) + 2; + RUNTIME_ARRAY(char, buffer, size); + snprintf(RUNTIME_ARRAY_BODY(buffer), size, "%s/%s", cwd, chars); + result = e->NewStringUTF(RUNTIME_ARRAY_BODY(buffer)); + free(cwd); + } + } + releaseChars(e, path, chars); + } + return result; +#endif +} + +extern "C" JNIEXPORT jlong JNICALL + Java_java_io_File_length(JNIEnv* e, jclass, jstring path) +{ +#ifdef PLATFORM_WINDOWS + // Option: without opening file + // http://msdn.microsoft.com/en-us/library/windows/desktop/aa364946(v=vs.85).aspx + string_t chars = getChars(e, path); + if (chars) { + LARGE_INTEGER fileSize; +#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) + HANDLE file = CreateFileW( + chars, FILE_READ_DATA, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0); +#else + HANDLE file = CreateFile2( + chars, GENERIC_READ, FILE_SHARE_READ, OPEN_EXISTING, nullptr); +#endif + releaseChars(e, path, chars); + if (file == INVALID_HANDLE_VALUE) + return 0; +#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) + if (!GetFileSizeEx(file, &fileSize)) { + CloseHandle(file); + return 0; + } +#else + FILE_STANDARD_INFO info; + if (!GetFileInformationByHandleEx( + file, FileStandardInfo, &info, sizeof(info))) { + CloseHandle(file); + return 0; + } + fileSize = info.EndOfFile; +#endif + + CloseHandle(file); + return static_cast(fileSize.QuadPart); + } +#else + + string_t chars = getChars(e, path); + if (chars) { + STRUCT_STAT s; + int r = STAT(chars, &s); + releaseChars(e, path, chars); + if (r == 0) { + return s.st_size; + } + } + +#endif + + return 0; +} + +extern "C" JNIEXPORT void JNICALL + Java_java_io_File_mkdir(JNIEnv* e, jclass, jstring path) +{ + string_t chars = getChars(e, path); + if (chars) { + if (not exists(chars)) { + int r = ::MKDIR(chars, 0777); + if (r != 0) { + throwNewErrno(e, "java/io/IOException"); + } + } + releaseChars(e, path, chars); + } +} + +extern "C" JNIEXPORT jboolean JNICALL + Java_java_io_File_createNewFile(JNIEnv* e, jclass, jstring path) +{ + bool result = false; + string_t chars = getChars(e, path); + if (chars) { + if (not exists(chars)) { + int fd = OPEN(chars, O_CREAT | O_WRONLY | O_EXCL, 0666); + if (fd == -1) { + if (errno != EEXIST) { + throwNewErrno(e, "java/io/IOException"); + } + } else { + result = true; + doClose(e, fd); + } + } + releaseChars(e, path, chars); + } + return result; +} + +extern "C" JNIEXPORT void JNICALL +Java_java_io_File_delete(JNIEnv* e, jclass, jstring path) +{ + string_t chars = getChars(e, path); + int r; + if (chars) { +#ifdef PLATFORM_WINDOWS + if (GetFileAttributes(chars) & FILE_ATTRIBUTE_DIRECTORY) { + r = !RemoveDirectory(chars); + } else { + r = REMOVE(chars); + } +#else + r = REMOVE(chars); +#endif + if (r != 0) { + throwNewErrno(e, "java/io/IOException"); + } + releaseChars(e, path, chars); + } +} + +extern "C" JNIEXPORT jboolean JNICALL + Java_java_io_File_canRead(JNIEnv* e, jclass, jstring path) +{ + string_t chars = getChars(e, path); + if (chars) { + int r = ACCESS(chars, R_OK); + releaseChars(e, path, chars); + return (r == 0); + } + return false; +} + +extern "C" JNIEXPORT jboolean JNICALL + Java_java_io_File_canWrite(JNIEnv* e, jclass, jstring path) +{ + string_t chars = getChars(e, path); + if (chars) { + int r = ACCESS(chars, W_OK); + releaseChars(e, path, chars); + return (r == 0); + } + return false; +} + +extern "C" JNIEXPORT jboolean JNICALL + Java_java_io_File_canExecute(JNIEnv* e, jclass, jstring path) +{ + string_t chars = getChars(e, path); + if (chars) { + int r = ACCESS(chars, CHECK_X_OK); + releaseChars(e, path, chars); + return (r == 0); + } + return false; +} + +#ifndef PLATFORM_WINDOWS +extern "C" JNIEXPORT jboolean JNICALL + Java_java_io_File_setExecutable(JNIEnv* e, + jclass, + jstring path, + jboolean executable, + jboolean ownerOnly) +{ + string_t chars = getChars(e, path); + if (chars) { + jboolean v; + int mask; + if (ownerOnly) { + mask = S_IXUSR; + } else { + mask = S_IXUSR | S_IXGRP | S_IXOTH; + } + + STRUCT_STAT s; + int r = STAT(chars, &s); + if (r == 0) { + int mode = s.st_mode; + if (executable) { + mode |= mask; + } else { + mode &= ~mask; + } + if (CHMOD(chars, mode) != 0) { + v = false; + } else { + v = true; + } + } else { + v = false; + } + releaseChars(e, path, chars); + return v; + } + return false; +} + +#else // ifndef PLATFORM_WINDOWS + +extern "C" JNIEXPORT jboolean JNICALL + Java_java_io_File_setExecutable(JNIEnv*, + jclass, + jstring, + jboolean executable, + jboolean) +{ + return executable; +} + +#endif + +extern "C" JNIEXPORT jboolean JNICALL + Java_java_io_File_rename(JNIEnv* e, jclass, jstring old, jstring new_) +{ + string_t oldChars = getChars(e, old); + string_t newChars = getChars(e, new_); + if (oldChars) { + bool v; + if (newChars) { + v = RENAME(oldChars, newChars) == 0; + + releaseChars(e, new_, newChars); + } else { + v = false; + } + releaseChars(e, old, oldChars); + return v; + } else { + return false; + } +} + +extern "C" JNIEXPORT jboolean JNICALL + Java_java_io_File_isDirectory(JNIEnv* e, jclass, jstring path) +{ + string_t chars = getChars(e, path); + if (chars) { + STRUCT_STAT s; + int r = STAT(chars, &s); + bool v = (r == 0 and S_ISDIR(s.st_mode)); + releaseChars(e, path, chars); + return v; + } else { + return false; + } +} + +extern "C" JNIEXPORT jboolean JNICALL + Java_java_io_File_isFile(JNIEnv* e, jclass, jstring path) +{ + string_t chars = getChars(e, path); + if (chars) { + STRUCT_STAT s; + int r = STAT(chars, &s); + bool v = (r == 0 and S_ISREG(s.st_mode)); + releaseChars(e, path, chars); + return v; + } else { + return false; + } +} + +extern "C" JNIEXPORT jboolean JNICALL + Java_java_io_File_exists(JNIEnv* e, jclass, jstring path) +{ + string_t chars = getChars(e, path); + if (chars) { + bool v = exists(chars); + releaseChars(e, path, chars); + return v; + } else { + return false; + } +} + +extern "C" JNIEXPORT jlong JNICALL + Java_java_io_File_lastModified(JNIEnv* e, jclass, jstring path) +{ + string_t chars = getChars(e, path); + if (chars) { +#ifdef PLATFORM_WINDOWS +// Option: without opening file +// http://msdn.microsoft.com/en-us/library/windows/desktop/aa364946(v=vs.85).aspx +#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) + HANDLE hFile = CreateFileW( + chars, FILE_READ_DATA, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0); +#else + HANDLE hFile = CreateFile2( + chars, GENERIC_READ, FILE_SHARE_READ, OPEN_EXISTING, nullptr); +#endif + releaseChars(e, path, chars); + if (hFile == INVALID_HANDLE_VALUE) + return 0; + LARGE_INTEGER fileDate, filetimeToUnixEpochAdjustment; + filetimeToUnixEpochAdjustment.QuadPart = 11644473600000L * 10000L; +#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) + FILETIME fileLastWriteTime; + if (!GetFileTime(hFile, 0, 0, &fileLastWriteTime)) { + CloseHandle(hFile); + return 0; + } + fileDate.HighPart = fileLastWriteTime.dwHighDateTime; + fileDate.LowPart = fileLastWriteTime.dwLowDateTime; +#else + FILE_BASIC_INFO fileInfo; + if (!GetFileInformationByHandleEx( + hFile, FileBasicInfo, &fileInfo, sizeof(fileInfo))) { + CloseHandle(hFile); + return 0; + } + fileDate = fileInfo.ChangeTime; +#endif + CloseHandle(hFile); + fileDate.QuadPart -= filetimeToUnixEpochAdjustment.QuadPart; + return fileDate.QuadPart / 10000000L; +#else + struct stat fileStat; + int res = stat(chars, &fileStat); + releaseChars(e, path, chars); + + if (res == -1) { + return 0; + } +#ifdef __APPLE__ +#define MTIME st_mtimespec +#else +#define MTIME st_mtim +#endif + return (static_cast(fileStat.MTIME.tv_sec) * 1000) + + (static_cast(fileStat.MTIME.tv_nsec) / (1000 * 1000)); +#endif + } + + return 0; +} + +#ifdef PLATFORM_WINDOWS + +extern "C" JNIEXPORT jlong JNICALL + Java_java_io_File_openDir(JNIEnv* e, jclass, jstring path) +{ + string_t chars = getChars(e, path); + if (chars) { + unsigned length = wcslen(chars); + unsigned size = length * sizeof(char_t); + + RUNTIME_ARRAY(char_t, buffer, length + 3); + memcpy(RUNTIME_ARRAY_BODY(buffer), chars, size); + memcpy(RUNTIME_ARRAY_BODY(buffer) + length, L"\\*", 6); + + releaseChars(e, path, chars); + + Directory* d = new (malloc(sizeof(Directory))) Directory; +#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) + d->handle = FindFirstFileW(RUNTIME_ARRAY_BODY(buffer), &(d->data)); +#else + d->handle = FindFirstFileExW(RUNTIME_ARRAY_BODY(buffer), + FindExInfoStandard, + &(d->data), + FindExSearchNameMatch, + NULL, + 0); +#endif + if (d->handle == INVALID_HANDLE_VALUE) { + d->dispose(); + d = 0; + } + + return reinterpret_cast(d); + } else { + return 0; + } +} + +extern "C" JNIEXPORT jstring JNICALL + Java_java_io_File_readDir(JNIEnv* e, jclass, jlong handle) +{ + Directory* d = reinterpret_cast(handle); + + while (true) { + string_t s = d->next(); + if (s) { + if (wcscmp(s, L".") == 0 || wcscmp(s, L"..") == 0) { + // skip . or .. and try again + } else { + return e->NewString(reinterpret_cast(s), wcslen(s)); + } + } else { + return 0; + } + } +} + +extern "C" JNIEXPORT void JNICALL + Java_java_io_File_closeDir(JNIEnv*, jclass, jlong handle) +{ + reinterpret_cast(handle)->dispose(); +} + +#else // not PLATFORM_WINDOWS + +extern "C" JNIEXPORT jlong JNICALL + Java_java_io_File_openDir(JNIEnv* e, jclass, jstring path) +{ + string_t chars = getChars(e, path); + if (chars) { + jlong handle = reinterpret_cast(opendir(chars)); + releaseChars(e, path, chars); + return handle; + } else { + return 0; + } +} + +extern "C" JNIEXPORT jstring JNICALL + Java_java_io_File_readDir(JNIEnv* e, jclass, jlong handle) +{ + struct dirent* directoryEntry; + + if (handle != 0) { + while (true) { + directoryEntry = readdir(reinterpret_cast(handle)); + if (directoryEntry == NULL) { + return NULL; + } else if (strcmp(directoryEntry->d_name, ".") == 0 + || strcmp(directoryEntry->d_name, "..") == 0) { + // skip . or .. and try again + } else { + return e->NewStringUTF(directoryEntry->d_name); + } + } + } + return NULL; +} + +extern "C" JNIEXPORT void JNICALL + Java_java_io_File_closeDir(JNIEnv*, jclass, jlong handle) +{ + if (handle != 0) { + closedir(reinterpret_cast(handle)); + } +} + +#endif // not PLATFORM_WINDOWS + +extern "C" JNIEXPORT jint JNICALL + Java_java_io_FileInputStream_open(JNIEnv* e, jclass, jstring path) +{ + string_t chars = getChars(e, path); + if (chars) { + int fd = doOpen(e, chars, O_RDONLY); + releaseChars(e, path, chars); + return fd; + } else { + return -1; + } +} + +extern "C" JNIEXPORT jint JNICALL + Java_java_io_FileInputStream_read__I(JNIEnv* e, jclass, jint fd) +{ + jbyte data; + int r = doRead(e, fd, &data, 1); + if (r <= 0) { + return -1; + } else { + return data & 0xff; + } +} + +extern "C" JNIEXPORT jint JNICALL + Java_java_io_FileInputStream_read__I_3BII(JNIEnv* e, + jclass, + jint fd, + jbyteArray b, + jint offset, + jint length) +{ + jbyte* data = static_cast(malloc(length)); + if (data == 0) { + throwNew(e, "java/lang/OutOfMemoryError", 0); + return 0; + } + + int r = doRead(e, fd, data, length); + + e->SetByteArrayRegion(b, offset, length, data); + + free(data); + + return r; +} + +extern "C" JNIEXPORT void JNICALL + Java_java_io_FileInputStream_close(JNIEnv* e, jclass, jint fd) +{ + doClose(e, fd); +} + +extern "C" JNIEXPORT jint JNICALL + Java_java_io_FileOutputStream_open(JNIEnv* e, + jclass, + jstring path, + jboolean append) +{ + string_t chars = getChars(e, path); + if (chars) { + int fd = doOpen(e, + chars, + append ? (O_WRONLY | O_CREAT | O_APPEND) + : (O_WRONLY | O_CREAT | O_TRUNC)); + releaseChars(e, path, chars); + return fd; + } else { + return -1; + } +} + +#endif // !SGX + +extern "C" JNIEXPORT void JNICALL + Java_java_io_FileOutputStream_write__II(JNIEnv* e, jclass, jint fd, jint c) +{ + jbyte data = c; + doWrite(e, fd, &data, 1); +} + +extern "C" JNIEXPORT void JNICALL + Java_java_io_FileOutputStream_write__I_3BII(JNIEnv* e, + jclass, + jint fd, + jbyteArray b, + jint offset, + jint length) +{ + jbyte* data = static_cast(malloc(length)); + + if (data == 0) { + throwNew(e, "java/lang/OutOfMemoryError", 0); + return; + } + + e->GetByteArrayRegion(b, offset, length, data); + if (not e->ExceptionCheck()) { + doWrite(e, fd, data, length); + } + + free(data); +} + +extern "C" JNIEXPORT void JNICALL + Java_java_io_FileOutputStream_close(JNIEnv* e, jclass, jint fd) +{ + doClose(e, fd); +} + +#ifndef SGX + +extern "C" JNIEXPORT void JNICALL + Java_java_io_RandomAccessFile_open(JNIEnv* e, + jclass, + jstring path, + jboolean allowWrite, + jlongArray result) +{ + string_t chars = getChars(e, path); + if (chars) { + jlong peer = 0; + jlong length = 0; + int flags = (allowWrite ? O_RDWR | O_CREAT : O_RDONLY) | OPEN_MASK; +#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) +#if defined(PLATFORM_WINDOWS) + int fd = ::_wopen(chars, flags); +#else + int fd = ::open((const char*)chars, flags, 0666); +#endif + releaseChars(e, path, chars); + if (fd == -1) { + throwNewErrno(e, "java/io/IOException"); + return; + } + struct ::stat fileStats; + if (::fstat(fd, &fileStats) == -1) { + ::close(fd); + throwNewErrno(e, "java/io/IOException"); + return; + } + peer = fd; + length = fileStats.st_size; +#else + HANDLE hFile = CreateFile2( + chars, GENERIC_READ, FILE_SHARE_READ, OPEN_EXISTING, nullptr); + if (hFile == INVALID_HANDLE_VALUE) { + throwNewErrno(e, "java/io/IOException"); + return; + } + + FILE_STANDARD_INFO info; + if (!GetFileInformationByHandleEx( + hFile, FileStandardInfo, &info, sizeof(info))) { + CloseHandle(hFile); + throwNewErrno(e, "java/io/IOException"); + return; + } + + peer = (jlong)hFile; + length = info.EndOfFile.QuadPart; +#endif + + e->SetLongArrayRegion(result, 0, 1, &peer); + e->SetLongArrayRegion(result, 1, 1, &length); + } +} + +extern "C" JNIEXPORT jint JNICALL + Java_java_io_RandomAccessFile_readBytes(JNIEnv* e, + jclass, + jlong peer, + jlong position, + jbyteArray buffer, + int offset, + int length) +{ +#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) + int fd = (int)peer; + if (::lseek(fd, position, SEEK_SET) == -1) { + throwNewErrno(e, "java/io/IOException"); + return -1; + } + + uint8_t* dst + = reinterpret_cast(e->GetPrimitiveArrayCritical(buffer, 0)); + + int64_t bytesRead = ::read(fd, dst + offset, length); + e->ReleasePrimitiveArrayCritical(buffer, dst, 0); + + if (bytesRead == -1) { + throwNewErrno(e, "java/io/IOException"); + return -1; + } +#else + HANDLE hFile = (HANDLE)peer; + LARGE_INTEGER lPos; + lPos.QuadPart = position; + if (!SetFilePointerEx(hFile, lPos, nullptr, FILE_BEGIN)) { + throwNewErrno(e, "java/io/IOException"); + return -1; + } + + uint8_t* dst + = reinterpret_cast(e->GetPrimitiveArrayCritical(buffer, 0)); + + DWORD bytesRead = 0; + if (!ReadFile(hFile, dst + offset, length, &bytesRead, nullptr)) { + e->ReleasePrimitiveArrayCritical(buffer, dst, 0); + throwNewErrno(e, "java/io/IOException"); + return -1; + } + e->ReleasePrimitiveArrayCritical(buffer, dst, 0); +#endif + + return (jint)bytesRead; +} + +extern "C" JNIEXPORT jint JNICALL + Java_java_io_RandomAccessFile_writeBytes(JNIEnv* e, + jclass, + jlong peer, + jlong position, + jbyteArray buffer, + int offset, + int length) +{ +#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) + int fd = (int)peer; + if (::lseek(fd, position, SEEK_SET) == -1) { + throwNewErrno(e, "java/io/IOException"); + return -1; + } + + uint8_t* dst + = reinterpret_cast(e->GetPrimitiveArrayCritical(buffer, 0)); + + int64_t bytesWritten = ::write(fd, dst + offset, length); + e->ReleasePrimitiveArrayCritical(buffer, dst, 0); + + if (bytesWritten == -1) { + throwNewErrno(e, "java/io/IOException"); + return -1; + } +#else + HANDLE hFile = (HANDLE)peer; + LARGE_INTEGER lPos; + lPos.QuadPart = position; + if (!SetFilePointerEx(hFile, lPos, nullptr, FILE_BEGIN)) { + throwNewErrno(e, "java/io/IOException"); + return -1; + } + + uint8_t* dst + = reinterpret_cast(e->GetPrimitiveArrayCritical(buffer, 0)); + + DWORD bytesWritten = 0; + if (!WriteFile(hFile, dst + offset, length, &bytesWritten, nullptr)) { + e->ReleasePrimitiveArrayCritical(buffer, dst, 0); + throwNewErrno(e, "java/io/IOException"); + return -1; + } + e->ReleasePrimitiveArrayCritical(buffer, dst, 0); +#endif + + return (jint)bytesWritten; +} + +extern "C" JNIEXPORT void JNICALL + Java_java_io_RandomAccessFile_close(JNIEnv* /* e*/, jclass, jlong peer) +{ +#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) + int fd = (int)peer; + ::close(fd); +#else + HANDLE hFile = (HANDLE)peer; + CloseHandle(hFile); +#endif +} + +#endif // !SGX \ No newline at end of file diff --git a/sgx-jvm/avian/classpath/java-lang.cpp b/sgx-jvm/avian/classpath/java-lang.cpp new file mode 100644 index 0000000000..75f89088cd --- /dev/null +++ b/sgx-jvm/avian/classpath/java-lang.cpp @@ -0,0 +1,1253 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#include "stdlib.h" +#include "time.h" +#include "string.h" +#include "stdio.h" +#include "jni.h" +#include "jni-util.h" +#include "errno.h" +#include "fcntl.h" +#include "ctype.h" + +// Make sure M_* constants (in particular M_E) are exposed in math.h. +// This was a problem on the default mingw install on ubuntu precise +#undef __STRICT_ANSI__ +#include "math.h" + +#ifdef PLATFORM_WINDOWS + +#include "windows.h" +#include "winbase.h" +#include "io.h" +#include "tchar.h" +#include "float.h" +#include "sys/types.h" +#include "sys/timeb.h" +#define SO_PREFIX "" +#define SO_SUFFIX ".dll" + +#ifdef _MSC_VER +#define snprintf sprintf_s +#define isnan _isnan +#define isfinite _finite +#define strtof strtod +#endif + +#else // not PLATFORM_WINDOWS + +#define SO_PREFIX "lib" +#ifdef __APPLE__ +#define SO_SUFFIX ".dylib" +#include +#if !TARGET_IPHONE_SIMULATOR && !TARGET_OS_IPHONE +#include +#endif +#else +#define SO_SUFFIX ".so" +#endif +#include "unistd.h" +#include "limits.h" +#include "signal.h" +#include "sys/time.h" +#include "sys/types.h" +#ifndef __ANDROID__ +#include "sys/sysctl.h" +#endif +#include "sys/utsname.h" +#include "sys/wait.h" + +#endif // not PLATFORM_WINDOWS + +#ifndef WINAPI_FAMILY +#ifndef WINAPI_PARTITION_DESKTOP +#define WINAPI_PARTITION_DESKTOP 1 +#endif + +#ifndef WINAPI_FAMILY_PARTITION +#define WINAPI_FAMILY_PARTITION(x) (x) +#endif +#else +#if !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) + +#include "avian-interop.h" + +#endif +#endif // WINAPI_FAMILY + +#ifndef M_E +// in new C++-11 standard math.h doesn't have M_E, at least on MinGW, so define it manually +#define M_E 2.7182818284590452354 +#endif // M_E + +namespace { + +void add(JNIEnv* e, jobjectArray array, unsigned index, const char* format, ...) +{ + int size = 256; + while (true) { + va_list a; + va_start(a, format); + RUNTIME_ARRAY(char, buffer, size); + int r = vsnprintf(RUNTIME_ARRAY_BODY(buffer), size - 1, format, a); + va_end(a); + if (r >= 0 and r < size - 1) { + e->SetObjectArrayElement( + array, index++, e->NewStringUTF(RUNTIME_ARRAY_BODY(buffer))); + return; + } + + size *= 2; + } +} + +#ifdef PLATFORM_WINDOWS + +void add(JNIEnv* e, + jobjectArray array, + unsigned index, + const WCHAR* format, + ...) +{ + int size = 256; + while (true) { + va_list a; + va_start(a, format); + RUNTIME_ARRAY(WCHAR, buffer, size); + int r = _vsnwprintf(RUNTIME_ARRAY_BODY(buffer), size - 1, format, a); + va_end(a); + if (r >= 0 and r < size - 1) { + e->SetObjectArrayElement( + array, + index++, + e->NewString(reinterpret_cast(RUNTIME_ARRAY_BODY(buffer)), + r)); + return; + } + + size *= 2; + } +} + +#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) +char* getErrorStr(DWORD err) +{ + LPSTR errorStr = 0; + if (!FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER + | FORMAT_MESSAGE_FROM_SYSTEM + | FORMAT_MESSAGE_IGNORE_INSERTS, + 0, + err, + LANG_SYSTEM_DEFAULT, + (LPSTR)&errorStr, + 0, + 0)) { + char* errStr = (char*)malloc(9 * sizeof(char)); + snprintf(errStr, 9, "%d", (int)err); + return errStr; + } + char* errStr = strdup(errorStr); + LocalFree(errorStr); + return errStr; +} +#else +char* getErrorStr(DWORD err) +{ + LPSTR errorStr = (LPSTR)malloc(4096); // NOTE: something constant + if (!FormatMessageA( + FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, + 0, + err, + LANG_SYSTEM_DEFAULT, + errorStr, + 0, + 0)) { + free(errorStr); + + char* errStr = (char*)malloc(9 * sizeof(char)); + snprintf(errStr, 9, "%d", (int)err); + return errStr; + } + char* errStr = strdup(errorStr); + free(errorStr); + return errStr; +} +#endif + +#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) +void makePipe(JNIEnv* e, HANDLE p[2]) +{ + SECURITY_ATTRIBUTES sa; + sa.nLength = sizeof(sa); + sa.bInheritHandle = 1; + sa.lpSecurityDescriptor = 0; + + BOOL success = CreatePipe(p, p + 1, &sa, 0); + if (not success) { + throwNew(e, "java/io/IOException", getErrorStr(GetLastError())); + } +} +#endif + +int descriptor(JNIEnv* e, HANDLE h) +{ + int fd = _open_osfhandle(reinterpret_cast(h), 0); + if (fd == -1) { + throwNewErrno(e, "java/io/IOException"); + } + return fd; +} +#else +void makePipe(JNIEnv* e, int p[2]) +{ + if (pipe(p) != 0) { + throwNewErrno(e, "java/io/IOException"); + } +} + +void safeClose(int& fd) +{ + if (fd != -1) + close(fd); + fd = -1; +} + +void close(int p[2]) +{ + ::close(p[0]); + ::close(p[1]); +} + +void clean(JNIEnv* e, jobjectArray command, char** p) +{ + int i = 0; + for (char** x = p; *x; ++x, ++i) { + jstring element = (jstring)e->GetObjectArrayElement(command, i); + e->ReleaseStringUTFChars(element, *x); + } + free(p); +} +#endif +} + +class Locale { // represents an ISO two-char language/country pair + static const unsigned FIELDLEN = 2; + static const unsigned FIELDSIZE = FIELDLEN + 1; + + static const char* DEFAULT_LANGUAGE; + static const char* DEFAULT_REGION; + + char language[FIELDSIZE]; + char region[FIELDSIZE]; + + bool isLanguage(const char* language) + { + if (!language) + return false; + unsigned len = strlen(language); + if (len != FIELDLEN) + return false; + const char* p = language - 1; + while (islower(*++p)) + ; + if (*p != '\0') + return false; + return true; + } + + bool isRegion(const char* region) + { + if (!region) + return false; + unsigned len = strlen(region); + if (len != FIELDLEN) + return false; + const char* p = region - 1; + while (isupper(*++p)) + ; + if (*p != '\0') + return false; + return true; + } + + public: + Locale(const char* language = "") + { + Locale l(language, ""); + *this = l; + } + + Locale(const char* language, const char* region) + { + language = isLanguage(language) ? language : DEFAULT_LANGUAGE; + region = isRegion(region) ? region : DEFAULT_REGION; + memcpy(this->language, language, FIELDSIZE); + memcpy(this->region, region, FIELDSIZE); + } + + Locale& operator=(const Locale& l) + { + memcpy(language, l.language, FIELDSIZE); + memcpy(region, l.region, FIELDSIZE); + return *this; + } + + const char* getLanguage() + { + return reinterpret_cast(language); + } + const char* getRegion() + { + return reinterpret_cast(region); + } +}; +const char* Locale::DEFAULT_LANGUAGE = "en"; +const char* Locale::DEFAULT_REGION = ""; + +#ifdef PLATFORM_WINDOWS + +void appendN(char** dest, char ch, size_t length) +{ + for (size_t i = 0; i < length; i++) { + *((*dest)++) = ch; + } +} + +bool needsEscape(const char* src, size_t length) +{ + const char* end = src + length; + for (const char* ptr = src; ptr < end; ptr++) { + switch (*ptr) { + case ' ': + case '\t': + case '\n': + case '\v': + case '"': + return true; + } + } + + return false; +} + +void copyAndEscape(char** dest, const char* src, size_t length) +{ + char* destp = *dest; + const char* end = src + length; + + if (length != 0 && !needsEscape(src, length)) { + for (const char* ptr = src; ptr < end; ptr++) { + *(destp++) = *ptr; + } + } else { + *(destp++) = '"'; + + for (const char* ptr = src;; ptr++) { + unsigned numBackslashes = 0; + + while (ptr < end && *ptr == '\\') { + ptr++; + numBackslashes++; + } + + if (ptr == end) { + appendN(&destp, '\\', 2 * numBackslashes); + break; + } else if (*ptr == '"') { + appendN(&destp, '\\', 2 * numBackslashes + 1); + *(destp++) = *ptr; + } else { + appendN(&destp, '\\', numBackslashes); + *(destp++) = *ptr; + } + } + + *(destp++) = '"'; + } + + *dest = destp; +} + +extern "C" JNIEXPORT void JNICALL + Java_java_lang_Runtime_exec(JNIEnv* e, + jclass, + jobjectArray command, + jlongArray process) +{ +#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) + int size = 0; + for (int i = 0; i < e->GetArrayLength(command); ++i) { + jstring element = (jstring)e->GetObjectArrayElement(command, i); + if (element) { + // worst case, assuming every character is '"', and we escape all of them + size += 2 * e->GetStringUTFLength(element) + 3; + } else { + throwNew(e, + "java/lang/NullPointerException", + strdup("null string array element")); + } + } + + RUNTIME_ARRAY(char, line, size); + char* linep = RUNTIME_ARRAY_BODY(line); + for (int i = 0; i < e->GetArrayLength(command); ++i) { + if (i) + *(linep++) = _T(' '); + jstring element = (jstring)e->GetObjectArrayElement(command, i); + const char* s = e->GetStringUTFChars(element, 0); + + copyAndEscape(&linep, s, e->GetStringUTFLength(element)); + + e->ReleaseStringUTFChars(element, s); + } + *(linep++) = _T('\0'); + + HANDLE in[] = {0, 0}; + HANDLE out[] = {0, 0}; + HANDLE err[] = {0, 0}; + + makePipe(e, in); + SetHandleInformation(in[0], HANDLE_FLAG_INHERIT, 0); + jlong inDescriptor = static_cast(descriptor(e, in[0])); + if (e->ExceptionCheck()) + return; + e->SetLongArrayRegion(process, 2, 1, &inDescriptor); + makePipe(e, out); + SetHandleInformation(out[1], HANDLE_FLAG_INHERIT, 0); + jlong outDescriptor = static_cast(descriptor(e, out[1])); + if (e->ExceptionCheck()) + return; + e->SetLongArrayRegion(process, 3, 1, &outDescriptor); + makePipe(e, err); + SetHandleInformation(err[0], HANDLE_FLAG_INHERIT, 0); + jlong errDescriptor = static_cast(descriptor(e, err[0])); + if (e->ExceptionCheck()) + return; + e->SetLongArrayRegion(process, 4, 1, &errDescriptor); + + PROCESS_INFORMATION pi; + ZeroMemory(&pi, sizeof(pi)); + + STARTUPINFO si; + ZeroMemory(&si, sizeof(si)); + si.cb = sizeof(si); + si.dwFlags = STARTF_USESTDHANDLES; + si.hStdOutput = in[1]; + si.hStdInput = out[0]; + si.hStdError = err[1]; + + BOOL success = CreateProcess(0, + (LPSTR)RUNTIME_ARRAY_BODY(line), + 0, + 0, + 1, + CREATE_NO_WINDOW | CREATE_UNICODE_ENVIRONMENT, + 0, + 0, + &si, + &pi); + + CloseHandle(in[1]); + CloseHandle(out[0]); + CloseHandle(err[1]); + + if (not success) { + throwNew(e, "java/io/IOException", getErrorStr(GetLastError())); + return; + } + + jlong pid = reinterpret_cast(pi.hProcess); + e->SetLongArrayRegion(process, 0, 1, &pid); + jlong tid = reinterpret_cast(pi.hThread); + e->SetLongArrayRegion(process, 1, 1, &tid); +#else + throwNew(e, "java/io/Exception", strdup("Not supported on WinRT/WinPhone8")); +#endif +} + +extern "C" JNIEXPORT jint JNICALL + Java_java_lang_Runtime_waitFor(JNIEnv* e, jclass, jlong pid, jlong tid) +{ +#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) + DWORD exitCode; + WaitForSingleObject(reinterpret_cast(pid), INFINITE); + BOOL success = GetExitCodeProcess(reinterpret_cast(pid), &exitCode); + if (not success) { + throwNew(e, "java/lang/Exception", getErrorStr(GetLastError())); + } + + CloseHandle(reinterpret_cast(pid)); + CloseHandle(reinterpret_cast(tid)); + + return exitCode; +#else + throwNew(e, "java/io/Exception", strdup("Not supported on WinRT/WinPhone8")); + return -1; +#endif +} + +extern "C" JNIEXPORT void JNICALL + Java_java_lang_Runtime_kill(JNIEnv* e UNUSED, jclass, jlong pid) +{ +#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) + TerminateProcess(reinterpret_cast(pid), 1); +#else + throwNew(e, "java/io/Exception", strdup("Not supported on WinRT/WinPhone8")); +#endif +} + +Locale getLocale() +{ +#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) + const char* lang = ""; + const char* reg = ""; + unsigned langid = GetUserDefaultUILanguage(); + unsigned prilang = langid & 0x3ff; + unsigned sublang = langid >> 10; + + switch (prilang) { + case 0x004: { + lang = "zh"; + switch (sublang) { + case 0x01: + reg = "CN"; + break; + case 0x02: + reg = "TW"; + break; + case 0x03: + reg = "HK"; + break; + case 0x04: + reg = "SG"; + break; + } + } break; + case 0x006: + lang = "da"; + reg = "DK"; + break; + case 0x007: + lang = "de"; + reg = "DE"; + break; + case 0x009: { + lang = "en"; + switch (sublang) { + case 0x01: + reg = "US"; + break; + case 0x02: + reg = "GB"; + break; + case 0x03: + reg = "AU"; + break; + case 0x04: + reg = "CA"; + break; + case 0x05: + reg = "NZ"; + break; + case 0x06: + reg = "IE"; + break; + case 0x07: + reg = "ZA"; + break; + case 0x10: + reg = "IN"; + break; + } + } break; + case 0x00a: { + lang = "es"; + switch (sublang) { + case 0x01: + case 0x03: + reg = "ES"; + break; + case 0x02: + reg = "MX"; + break; + } + } break; + case 0x00c: { + lang = "fr"; + switch (sublang) { + case 0x01: + reg = "FR"; + break; + case 0x02: + reg = "BE"; + break; + case 0x03: + reg = "CA"; + break; + } + } break; + case 0x010: + lang = "it"; + reg = "IT"; + break; + case 0x011: + lang = "ja"; + reg = "JP"; + break; + case 0x012: + lang = "ko"; + reg = "KR"; + break; + case 0x013: { + lang = "nl"; + switch (sublang) { + case 0x01: + reg = "NL"; + break; + case 0x02: + reg = "BE"; + break; + } + } break; + case 0x014: + lang = "no"; + reg = "NO"; + break; + case 0x015: + lang = "pl"; + reg = "PL"; + break; + case 0x016: { + lang = "pt"; + switch (sublang) { + case 0x01: + reg = "BR"; + break; + case 0x02: + reg = "PT"; + break; + } + } break; + case 0x018: + lang = "ro"; + reg = "RO"; + break; + case 0x019: + lang = "ru"; + reg = "RU"; + break; + case 0x01d: + lang = "sv"; + reg = "SE"; + break; + default: + lang = "en"; + } + + return Locale(lang, reg); +#else + std::wstring culture = AvianInterop::GetCurrentUICulture(); + char* cultureName + = strdup(std::string(culture.begin(), culture.end()).c_str()); + char* delimiter = strchr(cultureName, '-'); + if (!delimiter) { + free(cultureName); + return Locale("en", "US"); + } + const char* lang = cultureName; + const char* reg = delimiter + 1; + *delimiter = 0; + Locale locale(lang, reg); + free(cultureName); + return locale; +#endif +} +#else +extern "C" JNIEXPORT void JNICALL + Java_java_lang_Runtime_exec(JNIEnv* e, + jclass, + jobjectArray command, + jlongArray process) +{ + char** argv = static_cast( + malloc((e->GetArrayLength(command) + 1) * sizeof(char*))); + int i; + for (i = 0; i < e->GetArrayLength(command); i++) { + jstring element = (jstring)e->GetObjectArrayElement(command, i); + char* s = const_cast(e->GetStringUTFChars(element, 0)); + argv[i] = s; + } + argv[i] = 0; + + int in[] = {-1, -1}; + int out[] = {-1, -1}; + int err[] = {-1, -1}; + int msg[] = {-1, -1}; + + makePipe(e, in); + if (e->ExceptionCheck()) + return; + jlong inDescriptor = static_cast(in[0]); + e->SetLongArrayRegion(process, 2, 1, &inDescriptor); + makePipe(e, out); + if (e->ExceptionCheck()) + return; + jlong outDescriptor = static_cast(out[1]); + e->SetLongArrayRegion(process, 3, 1, &outDescriptor); + makePipe(e, err); + if (e->ExceptionCheck()) + return; + jlong errDescriptor = static_cast(err[0]); + e->SetLongArrayRegion(process, 4, 1, &errDescriptor); + makePipe(e, msg); + if (e->ExceptionCheck()) + return; + if (fcntl(msg[1], F_SETFD, FD_CLOEXEC) != 0) { + throwNewErrno(e, "java/io/IOException"); + return; + } + +#ifdef __QNX__ + // fork(2) doesn't work in multithreaded QNX programs. See + // http://www.qnx.com/developers/docs/6.4.1/neutrino/getting_started/s1_procs.html + pid_t pid = vfork(); +#else + // We might be able to just use vfork on all UNIX-style systems, but + // the manual makes it sound dangerous due to the shared + // parent/child address space, so we use fork if we can. + pid_t pid = fork(); +#endif + switch (pid) { + case -1: // error + throwNewErrno(e, "java/io/IOException"); + return; + case 0: { // child + // Setup stdin, stdout and stderr + dup2(in[1], 1); + close(in); + dup2(out[0], 0); + close(out); + dup2(err[1], 2); + close(err); + close(msg[0]); + + execvp(argv[0], argv); + + // Error if here + int val = errno; + ssize_t rv UNUSED = write(msg[1], &val, sizeof(val)); + exit(127); + } break; + + default: { // parent + jlong JNIPid = static_cast(pid); + e->SetLongArrayRegion(process, 0, 1, &JNIPid); + + safeClose(in[1]); + safeClose(out[0]); + safeClose(err[1]); + safeClose(msg[1]); + + int val; + int r = read(msg[0], &val, sizeof(val)); + if (r == -1) { + throwNewErrno(e, "java/io/IOException"); + return; + } else if (r) { + errno = val; + throwNewErrno(e, "java/io/IOException"); + return; + } + } break; + } + + safeClose(msg[0]); + clean(e, command, argv); + + fcntl(in[0], F_SETFD, FD_CLOEXEC); + fcntl(out[1], F_SETFD, FD_CLOEXEC); + fcntl(err[0], F_SETFD, FD_CLOEXEC); +} + +extern "C" JNIEXPORT jint JNICALL + Java_java_lang_Runtime_waitFor(JNIEnv*, jclass, jlong pid, jlong) +{ + bool finished = false; + int status; + int exitCode; + while (!finished) { + waitpid(pid, &status, 0); + if (WIFEXITED(status)) { + finished = true; + exitCode = WEXITSTATUS(status); + } else if (WIFSIGNALED(status)) { + finished = true; + exitCode = -1; + } + } + + return exitCode; +} + +extern "C" JNIEXPORT void JNICALL + Java_java_lang_Runtime_kill(JNIEnv*, jclass, jlong pid) +{ + kill((pid_t)pid, SIGTERM); +} + +Locale getLocale() +{ + Locale fallback; + + const char* LANG = getenv("LANG"); + if (!LANG || strcmp(LANG, "C") == 0) + return fallback; + + int len = strlen(LANG); + char buf[len + 1]; // + 1 for the '\0' char + memcpy(buf, LANG, len + 1); + + char* tracer = buf; + const char* reg; + + while (*tracer && *tracer != '_') + ++tracer; + if (!*tracer) + return fallback; + *tracer = '\0'; + reg = ++tracer; + + while (*tracer && *tracer != '.') + ++tracer; + if (tracer == reg) + return fallback; + *tracer = '\0'; + + Locale locale(buf, reg); + return locale; +} +#endif + +extern "C" JNIEXPORT jobjectArray JNICALL + Java_java_lang_System_getNativeProperties(JNIEnv* e, jclass) +{ + jobjectArray array + = e->NewObjectArray(32, e->FindClass("java/lang/String"), 0); + + unsigned index = 0; + +#ifdef ARCH_x86_32 + e->SetObjectArrayElement(array, index++, e->NewStringUTF("os.arch=x86")); + +#elif defined ARCH_x86_64 + e->SetObjectArrayElement(array, index++, e->NewStringUTF("os.arch=x86_64")); + +#elif defined ARCH_arm + e->SetObjectArrayElement(array, index++, e->NewStringUTF("os.arch=arm")); + +#elif defined ARCH_arm64 + e->SetObjectArrayElement(array, index++, e->NewStringUTF("os.arch=arm64")); + +#else +#error "unknown architecture" + +#endif + +#ifdef PLATFORM_WINDOWS + e->SetObjectArrayElement( + array, index++, e->NewStringUTF("line.separator=\r\n")); + + e->SetObjectArrayElement( + array, index++, e->NewStringUTF("file.separator=\\")); + + e->SetObjectArrayElement(array, index++, e->NewStringUTF("path.separator=;")); + +#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) + e->SetObjectArrayElement(array, index++, e->NewStringUTF("os.name=Windows")); + +#elif WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_PHONE) + e->SetObjectArrayElement( + array, index++, e->NewStringUTF("os.name=Windows Phone")); + +#else + e->SetObjectArrayElement( + array, index++, e->NewStringUTF("os.name=Windows RT")); + +#endif + +#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) + { + OSVERSIONINFO OSversion; + OSversion.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + ::GetVersionEx(&OSversion); + + add(e, + array, + index++, + "os.version=%i.%i", + static_cast(OSversion.dwMajorVersion), + static_cast(OSversion.dwMinorVersion)); + } + +#else + // Currently there is no alternative on WinRT/WP8 + e->SetObjectArrayElement(array, index++, e->NewStringUTF("os.version=8.0")); + +#endif + +#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) + { + WCHAR buffer[MAX_PATH]; + GetTempPathW(MAX_PATH, buffer); + add(e, array, index++, L"java.io.tmpdir=%ls", buffer); + } + +#else + add(e, + array, + index++, + L"java.io.tmpdir=%ls", + AvianInterop::GetTemporaryFolder().c_str()); + +#endif + +#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) + { + WCHAR buffer[MAX_PATH]; + GetCurrentDirectoryW(MAX_PATH, buffer); + add(e, array, index++, L"user.dir=%ls", buffer); + } + +#else + add(e, + array, + index++, + L"user.dir=%ls", + AvianInterop::GetInstalledLocation().c_str()); + +#endif + +#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) +#ifdef _MSC_VER + { + WCHAR buffer[MAX_PATH]; + size_t needed; + if (_wgetenv_s(&needed, buffer, MAX_PATH, L"USERPROFILE") == 0) { + add(e, array, index++, L"user.home=%ls", buffer); + } + } + +#else + add(e, array, index++, L"user.home=%ls", _wgetenv(L"USERPROFILE")); + +#endif +#else + add(e, + array, + index++, + L"user.home=%ls", + AvianInterop::GetDocumentsLibraryLocation().c_str()); + +#endif + +#else // not Windows + e->SetObjectArrayElement( + array, index++, e->NewStringUTF("line.separator=\n")); + + e->SetObjectArrayElement(array, index++, e->NewStringUTF("file.separator=/")); + + e->SetObjectArrayElement(array, index++, e->NewStringUTF("path.separator=:")); + +#ifdef __APPLE__ + e->SetObjectArrayElement(array, index++, e->NewStringUTF("os.name=Mac OS X")); + +#elif defined __FreeBSD__ + e->SetObjectArrayElement(array, index++, e->NewStringUTF("os.name=FreeBSD")); + +#else + e->SetObjectArrayElement(array, index++, e->NewStringUTF("os.name=Linux")); + +#endif + { + struct utsname system_id; + uname(&system_id); + add(e, array, index++, "os.version=%s", system_id.release); + } + + e->SetObjectArrayElement( + array, index++, e->NewStringUTF("java.io.tmpdir=/tmp")); + + { + char buffer[PATH_MAX]; + add(e, array, index++, "user.dir=%s", getcwd(buffer, PATH_MAX)); + } + + add(e, array, index++, "user.home=%s", getenv("HOME")); + +#endif // not Windows + + { + Locale locale = getLocale(); + add(e, array, index++, "user.language=%s", locale.getLanguage()); + add(e, array, index++, "user.region=%s", locale.getRegion()); + } + + return array; +} + +// System.getEnvironment() implementation +// TODO: For Win32, replace usage of deprecated _environ and add Unicode +// support (neither of which is likely to be of great importance). +#ifdef AVIAN_IOS +namespace { +const char* environ[] = {0}; +} +#elif defined __APPLE__ +#include +#define environ (*_NSGetEnviron()) +#elif defined(WINAPI_FAMILY) \ + && !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) +// WinRT/WP8 does not provide alternative for environment variables +char* environ[] = {0}; +#else +extern char** environ; +#endif +extern "C" JNIEXPORT jobjectArray JNICALL + Java_java_lang_System_getEnvironment(JNIEnv* env, jclass) +{ + int length; + for (length = 0; environ[length] != 0; ++length) + ; + + jobjectArray stringArray = env->NewObjectArray( + length, env->FindClass("java/lang/String"), env->NewStringUTF("")); + + for (int i = 0; i < length; i++) { + jobject varString = env->NewStringUTF(environ[i]); + env->SetObjectArrayElement(stringArray, i, varString); + } + + return stringArray; +} + +extern "C" JNIEXPORT jlong JNICALL + Java_java_lang_System_currentTimeMillis(JNIEnv*, jclass) +{ +#ifdef PLATFORM_WINDOWS + // We used to use _ftime here, but that only gives us 1-second + // resolution on Windows 7. _ftime_s might work better, but MinGW + // doesn't have it as of this writing. So we use this mess instead: + FILETIME time; + GetSystemTimeAsFileTime(&time); + return (((static_cast(time.dwHighDateTime) << 32) | time.dwLowDateTime) + / 10000) - 11644473600000LL; +#else + timeval tv = {0, 0}; + gettimeofday(&tv, 0); + return (static_cast(tv.tv_sec) * 1000) + + (static_cast(tv.tv_usec) / 1000); +#endif +} + +extern "C" JNIEXPORT jstring JNICALL + Java_java_lang_System_doMapLibraryName(JNIEnv* e, jclass, jstring name) +{ + jstring r = 0; + const char* chars = e->GetStringUTFChars(name, 0); + if (chars) { + unsigned nameLength = strlen(chars); + unsigned size = sizeof(SO_PREFIX) + nameLength + sizeof(SO_SUFFIX); + RUNTIME_ARRAY(char, buffer, size); + snprintf(RUNTIME_ARRAY_BODY(buffer), size, SO_PREFIX "%s" SO_SUFFIX, chars); + r = e->NewStringUTF(RUNTIME_ARRAY_BODY(buffer)); + + e->ReleaseStringUTFChars(name, chars); + } + return r; +} + +extern "C" JNIEXPORT jboolean JNICALL + Java_java_lang_Double_isInfinite(JNIEnv*, jclass, jdouble val) +{ + return !isfinite(val); +} + +extern "C" JNIEXPORT jboolean JNICALL + Java_java_lang_Double_isNaN(JNIEnv*, jclass, jdouble val) +{ + return isnan(val); +} + +extern "C" JNIEXPORT jdouble JNICALL + Java_java_lang_Double_doubleFromString(JNIEnv* e, + jclass, + jstring s, + jintArray numDoublesRead) +{ + const char* chars = e->GetStringUTFChars(s, 0); + double d = 0.0; + jint numRead = 0; + + if (chars) { + char* lastRead; + d = strtod(chars, &lastRead); + if ((lastRead != chars) && ((chars + strlen(chars)) == lastRead)) { + numRead = 1; + } + e->ReleaseStringUTFChars(s, chars); + } + e->SetIntArrayRegion(numDoublesRead, 0, 1, &numRead); + return d; +} + +extern "C" JNIEXPORT jboolean JNICALL + Java_java_lang_Float_isInfinite(JNIEnv*, jclass, jfloat val) +{ + return !isfinite(val); +} + +extern "C" JNIEXPORT jboolean JNICALL + Java_java_lang_Float_isNaN(JNIEnv*, jclass, jfloat val) +{ + return isnan(val); +} + +extern "C" JNIEXPORT jfloat JNICALL + Java_java_lang_Float_floatFromString(JNIEnv* e, + jclass, + jstring s, + jintArray numFloatsRead) +{ + const char* chars = e->GetStringUTFChars(s, 0); + float f = 0.0; + jint numRead = 0; + + if (chars) { + char* lastRead; + f = strtof(chars, &lastRead); + if ((lastRead != chars) && ((chars + strlen(chars)) == lastRead)) { + numRead = 1; + } + e->ReleaseStringUTFChars(s, chars); + } + e->SetIntArrayRegion(numFloatsRead, 0, 1, &numRead); + return f; +} + +extern "C" JNIEXPORT jdouble JNICALL + Java_java_lang_Math_sin(JNIEnv*, jclass, jdouble val) +{ + return sin(val); +} + +extern "C" JNIEXPORT jdouble JNICALL + Java_java_lang_Math_cos(JNIEnv*, jclass, jdouble val) +{ + return cos(val); +} + +extern "C" JNIEXPORT jdouble JNICALL + Java_java_lang_Math_tan(JNIEnv*, jclass, jdouble val) +{ + return tan(val); +} + +extern "C" JNIEXPORT jdouble JNICALL + Java_java_lang_Math_asin(JNIEnv*, jclass, jdouble val) +{ + return asin(val); +} + +extern "C" JNIEXPORT jdouble JNICALL + Java_java_lang_Math_acos(JNIEnv*, jclass, jdouble val) +{ + return acos(val); +} + +extern "C" JNIEXPORT jdouble JNICALL + Java_java_lang_Math_atan(JNIEnv*, jclass, jdouble val) +{ + return atan(val); +} + +extern "C" JNIEXPORT jdouble JNICALL + Java_java_lang_Math_atan2(JNIEnv*, jclass, jdouble y, jdouble x) +{ + return atan2(y, x); +} + +extern "C" JNIEXPORT jdouble JNICALL + Java_java_lang_Math_sinh(JNIEnv*, jclass, jdouble val) +{ + return sinh(val); +} + +extern "C" JNIEXPORT jdouble JNICALL + Java_java_lang_Math_cosh(JNIEnv*, jclass, jdouble val) +{ + return cosh(val); +} + +extern "C" JNIEXPORT jdouble JNICALL + Java_java_lang_Math_tanh(JNIEnv*, jclass, jdouble val) +{ + return tanh(val); +} + +extern "C" JNIEXPORT jdouble JNICALL + Java_java_lang_Math_sqrt(JNIEnv*, jclass, jdouble val) +{ + return sqrt(val); +} + +extern "C" JNIEXPORT jdouble JNICALL + Java_java_lang_Math_pow(JNIEnv*, jclass, jdouble val, jdouble exp) +{ + return pow(val, exp); +} + +extern "C" JNIEXPORT jdouble JNICALL + Java_java_lang_Math_log(JNIEnv*, jclass, jdouble val) +{ + return log(val); +} + +extern "C" JNIEXPORT jdouble JNICALL + Java_java_lang_Math_floor(JNIEnv*, jclass, jdouble val) +{ + return floor(val); +} + +extern "C" JNIEXPORT jdouble JNICALL + Java_java_lang_Math_ceil(JNIEnv*, jclass, jdouble val) +{ + return ceil(val); +} + +extern "C" JNIEXPORT jdouble JNICALL + Java_java_lang_Math_exp(JNIEnv*, jclass, jdouble exp) +{ + return pow(M_E, exp); +} + +extern "C" JNIEXPORT jint JNICALL + Java_java_lang_Double_fillBufferWithDouble(JNIEnv* e, + jclass, + jdouble val, + jbyteArray buffer, + jint bufferSize) +{ + jboolean isCopy; + jbyte* buf = e->GetByteArrayElements(buffer, &isCopy); + jint count = snprintf(reinterpret_cast(buf), bufferSize, "%g", val); + e->ReleaseByteArrayElements(buffer, buf, 0); + return count; +} diff --git a/sgx-jvm/avian/classpath/java-net.cpp b/sgx-jvm/avian/classpath/java-net.cpp new file mode 100644 index 0000000000..cafb02238a --- /dev/null +++ b/sgx-jvm/avian/classpath/java-net.cpp @@ -0,0 +1,145 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#ifndef SGX + +#include "jni.h" +#include "avian/machine.h" +#include "sockets.h" +#include "jni-util.h" + +using namespace avian::classpath::sockets; + +extern "C" JNIEXPORT void JNICALL Java_java_net_Socket_init(JNIEnv* e, jclass) +{ + init(e); +} + +extern "C" JNIEXPORT SOCKET JNICALL + Java_java_net_Socket_create(JNIEnv* e, jclass) +{ + return create(e); +} + +extern "C" JNIEXPORT void JNICALL Java_java_net_Socket_connect(JNIEnv* e, + jclass, + jlong sock, + jlong addr, + jshort port) +{ + connect(e, static_cast(sock), addr, port); +} + +extern "C" JNIEXPORT void JNICALL Java_java_net_Socket_bind(JNIEnv* e, + jclass, + jlong sock, + jlong addr, + jshort port) +{ + bind(e, static_cast(sock), addr, port); +} + +extern "C" JNIEXPORT void JNICALL + Java_java_net_Socket_abort(JNIEnv* e, jclass, jlong sock) +{ + abort(e, static_cast(sock)); +} + +extern "C" JNIEXPORT void JNICALL + Java_java_net_Socket_close(JNIEnv* e, jclass, jlong sock) +{ + close(e, static_cast(sock)); +} + +extern "C" JNIEXPORT void JNICALL + Java_java_net_Socket_closeOutput(JNIEnv* e, jclass, jlong sock) +{ + close_output(e, static_cast(sock)); +} + +extern "C" JNIEXPORT void JNICALL + Java_java_net_Socket_closeInput(JNIEnv* e, jclass, jlong sock) +{ + close_input(e, static_cast(sock)); +} + +extern "C" JNIEXPORT void JNICALL + Avian_java_net_Socket_send(vm::Thread* t, vm::object, uintptr_t* arguments) +{ /* SOCKET s, object buffer_obj, int start_pos, int count */ + SOCKET& s = *(reinterpret_cast(&arguments[0])); + vm::GcByteArray* buffer_obj = vm::cast( + t, reinterpret_cast(arguments[2])); + int32_t& start_pos = *(reinterpret_cast(&arguments[3])); + int32_t& count = *(reinterpret_cast(&arguments[4])); + char* buffer = reinterpret_cast(&buffer_obj->body()[start_pos]); + avian::classpath::sockets::send((JNIEnv*)t, s, buffer, count); +} + +extern "C" JNIEXPORT int64_t JNICALL + Avian_java_net_Socket_recv(vm::Thread* t, vm::object, uintptr_t* arguments) +{ /* SOCKET s, object buffer_obj, int start_pos, int count */ + SOCKET& s = *(reinterpret_cast(&arguments[0])); + vm::GcByteArray* buffer_obj = vm::cast( + t, reinterpret_cast(arguments[2])); + int32_t& start_pos = *(reinterpret_cast(&arguments[3])); + int32_t& count = *(reinterpret_cast(&arguments[4])); + char* buffer = reinterpret_cast(&buffer_obj->body()[start_pos]); + return avian::classpath::sockets::recv((JNIEnv*)t, s, buffer, count); +} + +extern "C" JNIEXPORT jint JNICALL + Java_java_net_InetAddress_ipv4AddressForName(JNIEnv* e, + jclass, + jstring name) +{ + if(!name) { + throwNew(e, "java/lang/NullPointerException", 0); + return 0; + } + + const char* chars = e->GetStringUTFChars(name, 0); + if (chars) { +#ifdef PLATFORM_WINDOWS + hostent* host = gethostbyname(chars); + e->ReleaseStringUTFChars(name, chars); + if (host) { + return ntohl(reinterpret_cast(host->h_addr_list[0])->s_addr); + } else { + throwNew(e, "java/net/UnknownHostException", 0); + return 0; + } +#else + addrinfo hints; + memset(&hints, 0, sizeof(addrinfo)); + hints.ai_family = AF_INET; + hints.ai_socktype = SOCK_STREAM; + + addrinfo* result; + int r = getaddrinfo(chars, 0, &hints, &result); + e->ReleaseStringUTFChars(name, chars); + + if (r != 0) { + throwNew(e, "java/net/UnknownHostException", 0); + return 0; + } else { + int address = ntohl( + reinterpret_cast(result->ai_addr)->sin_addr.s_addr); + + freeaddrinfo(result); + return address; + } +#endif + } else { + throwNew(e, "java/lang/OutOfMemoryError", 0); + return 0; + } +} + +#endif // !SGX \ No newline at end of file diff --git a/sgx-jvm/avian/classpath/java-nio.cpp b/sgx-jvm/avian/classpath/java-nio.cpp new file mode 100644 index 0000000000..e04adc2d70 --- /dev/null +++ b/sgx-jvm/avian/classpath/java-nio.cpp @@ -0,0 +1,1102 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#ifndef SGX + +#include +#include +#include +#include + +#include "jni.h" +#include "jni-util.h" + +#ifdef PLATFORM_WINDOWS +#include +#include +#include +#ifdef _MSC_VER +#define snprintf sprintf_s +#else +#include +#endif +#else +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#endif + +#define java_nio_channels_SelectionKey_OP_READ 1L +#define java_nio_channels_SelectionKey_OP_WRITE 4L +#define java_nio_channels_SelectionKey_OP_CONNECT 8L +#define java_nio_channels_SelectionKey_OP_ACCEPT 16L + +#ifdef PLATFORM_WINDOWS +typedef int socklen_t; +#endif + +inline void* operator new(size_t, void* p) throw() +{ + return p; +} + +namespace { + +inline jbyteArray charsToArray(JNIEnv* e, const char* s) +{ + unsigned length = strlen(s); + jbyteArray a = e->NewByteArray(length + 1); + e->SetByteArrayRegion(a, 0, length + 1, reinterpret_cast(s)); + return a; +} + +inline void doClose(int socket) +{ +#ifdef PLATFORM_WINDOWS + closesocket(socket); +#else + close(socket); +#endif +} + +inline jbyteArray errorString(JNIEnv* e, int n) +{ +#ifdef _MSC_VER + const unsigned size = 128; + char buffer[size]; + strerror_s(buffer, size, n); + return charsToArray(e, buffer); +#else + return charsToArray(e, strerror(n)); +#endif +} + +inline jbyteArray socketErrorString(JNIEnv* e, int n) +{ +#ifdef PLATFORM_WINDOWS + const unsigned size = 64; + char buffer[size]; + snprintf(buffer, size, "wsa code: %d", n); + return charsToArray(e, buffer); +#else + return errorString(e, n); +#endif +} + +inline jbyteArray errorString(JNIEnv* e) +{ +#ifdef PLATFORM_WINDOWS + const unsigned size = 64; + char buffer[size]; + snprintf(buffer, size, "wsa code: %d", WSAGetLastError()); + return charsToArray(e, buffer); +#else + return errorString(e, errno); +#endif +} + +void throwIOException(JNIEnv* e, const char* s) +{ + throwNew(e, "java/io/IOException", s); +} + +void throwIOException(JNIEnv* e, jbyteArray a) +{ + size_t length = e->GetArrayLength(a); + uint8_t* buf = static_cast(allocate(e, length)); + if (buf) { + e->GetByteArrayRegion(a, 0, length, reinterpret_cast(buf)); + throwIOException(e, reinterpret_cast(buf)); + free(buf); + } else { + return; + } +} + +void throwIOException(JNIEnv* e) +{ + throwIOException(e, errorString(e)); +} + +void throwSocketException(JNIEnv* e, const char* s) +{ + throwNew(e, "java/net/SocketException", s); +} + +void throwSocketException(JNIEnv* e, jbyteArray a) +{ + size_t length = e->GetArrayLength(a); + uint8_t* buf = static_cast(allocate(e, length)); + if (buf) { + e->GetByteArrayRegion(a, 0, length, reinterpret_cast(buf)); + throwSocketException(e, reinterpret_cast(buf)); + free(buf); + } else { + return; + } +} + +void throwSocketException(JNIEnv* e) +{ + throwSocketException(e, errorString(e)); +} + +void init(sockaddr_in* address, jint host, jint port) +{ + memset(address, 0, sizeof(sockaddr_in)); + address->sin_family = AF_INET; + address->sin_port = htons(port); + address->sin_addr.s_addr = htonl(host); +} + +inline bool einProgress(int error) +{ +#ifdef PLATFORM_WINDOWS + return error == WSAEINPROGRESS or error == WSAEWOULDBLOCK; +#else + return error == EINPROGRESS; +#endif +} + +inline bool einProgress() +{ +#ifdef PLATFORM_WINDOWS + return WSAGetLastError() == WSAEINPROGRESS + or WSAGetLastError() == WSAEWOULDBLOCK; +#else + return errno == EINPROGRESS; +#endif +} + +inline bool eagain() +{ +#ifdef PLATFORM_WINDOWS + return WSAGetLastError() == WSAEINPROGRESS + or WSAGetLastError() == WSAEWOULDBLOCK; +#else + return errno == EAGAIN; +#endif +} + +bool setBlocking(JNIEnv* e, int d, bool blocking) +{ +#ifdef PLATFORM_WINDOWS + u_long a = (blocking ? 0 : 1); + int r = ioctlsocket(d, FIONBIO, &a); + if (r != 0) { + throwIOException(e); + return false; + } +#else + int r = fcntl(d, + F_SETFL, + (blocking ? (fcntl(d, F_GETFL) & (~O_NONBLOCK)) + : (fcntl(d, F_GETFL) | O_NONBLOCK))); + if (r < 0) { + throwIOException(e); + return false; + } +#endif + return true; +} + +bool setTcpNoDelay(JNIEnv* e, int d, bool on) +{ + int flag = on; + int r = setsockopt( + d, IPPROTO_TCP, TCP_NODELAY, reinterpret_cast(&flag), sizeof(int)); + if (r < 0) { + throwSocketException(e); + return false; + } + return true; +} + +void doBind(JNIEnv* e, int s, sockaddr_in* address) +{ + { + int opt = 1; + int r = ::setsockopt(s, + SOL_SOCKET, + SO_REUSEADDR, + reinterpret_cast(&opt), + sizeof(int)); + if (r != 0) { + throwIOException(e); + return; + } + } + +#ifdef SO_NOSIGPIPE + { + int opt = 1; + int r = ::setsockopt(s, + SOL_SOCKET, + SO_NOSIGPIPE, + reinterpret_cast(&opt), + sizeof(int)); + if (r != 0) { + throwIOException(e); + return; + } + } +#endif + + { + int r + = ::bind(s, reinterpret_cast(address), sizeof(sockaddr_in)); + if (r != 0) { + throwIOException(e); + return; + } + } +} + +void doListen(JNIEnv* e, int s) +{ + int r = ::listen(s, 100); + if (r != 0) { + throwIOException(e); + } +} + +void doFinishConnect(JNIEnv* e, int socket) +{ + int error; + socklen_t size = sizeof(int); + int r = getsockopt( + socket, SOL_SOCKET, SO_ERROR, reinterpret_cast(&error), &size); + + if (r != 0 or size != sizeof(int)) { + throwIOException(e); + } else if (error and not einProgress(error)) { + throwIOException(e, socketErrorString(e, error)); + } +} + +bool doConnect(JNIEnv* e, int s, sockaddr_in* address) +{ + int r + = ::connect(s, reinterpret_cast(address), sizeof(sockaddr_in)); + if (r == 0) { + return true; + } else if (not einProgress()) { + throwIOException(e); + return false; + } else { + return false; + } +} + +int doAccept(JNIEnv* e, int s) +{ + sockaddr address; + socklen_t length = sizeof(address); + int r = ::accept(s, &address, &length); + if (r >= 0) { + return r; + } else if (errno != EINTR) { + throwIOException(e); + } + return -1; +} + +int doRead(int fd, void* buffer, size_t count) +{ +#ifdef PLATFORM_WINDOWS + return recv(fd, static_cast(buffer), count, 0); +#else + return read(fd, buffer, count); +#endif +} + +int doRecv(int fd, void* buffer, size_t count, int32_t* host, int32_t* port) +{ + sockaddr address; + socklen_t length = sizeof(address); + int r = recvfrom(fd, static_cast(buffer), count, 0, &address, &length); + + if (r > 0) { + sockaddr_in a; + memcpy(&a, &address, length); + *host = ntohl(a.sin_addr.s_addr); + *port = ntohs(a.sin_port); + } else { + *host = 0; + *port = 0; + } + + return r; +} + +int doWrite(int fd, const void* buffer, size_t count) +{ +#ifdef PLATFORM_WINDOWS + return send(fd, static_cast(buffer), count, 0); +#else + return write(fd, buffer, count); +#endif +} + +int doSend(int fd, sockaddr_in* address, const void* buffer, size_t count) +{ + return sendto(fd, + static_cast(buffer), + count, + 0, + reinterpret_cast(address), + sizeof(sockaddr_in)); +} + +int makeSocket(JNIEnv* e, int type = SOCK_STREAM, int protocol = IPPROTO_TCP) +{ + int s = ::socket(AF_INET, type, protocol); + if (s < 0) { + throwIOException(e); + return s; + } + + return s; +} + +} // namespace + +extern "C" JNIEXPORT jint JNICALL + Java_java_nio_channels_ServerSocketChannel_natDoAccept(JNIEnv* e, + jclass, + jint socket) +{ + return ::doAccept(e, socket); +} + +extern "C" JNIEXPORT void JNICALL + Java_java_nio_channels_ServerSocketChannel_natDoListen(JNIEnv* e, + jclass, + jint socket, + jint host, + jint port) +{ + sockaddr_in address; + init(&address, host, port); + + ::doBind(e, socket, &address); + if (e->ExceptionCheck()) + return; + + ::doListen(e, socket); +} + +extern "C" JNIEXPORT void JNICALL + Java_java_nio_channels_SocketChannel_bind(JNIEnv* e, + jclass, + jint socket, + jint host, + jint port) +{ + sockaddr_in address; + init(&address, host, port); + + ::doBind(e, socket, &address); +} + +extern "C" JNIEXPORT void JNICALL + Java_java_nio_channels_DatagramChannel_bind(JNIEnv* e, + jclass c, + jint socket, + jint host, + jint port) +{ + Java_java_nio_channels_SocketChannel_bind(e, c, socket, host, port); +} + +extern "C" JNIEXPORT void JNICALL + Java_java_nio_channels_SocketChannel_configureBlocking(JNIEnv* e, + jclass, + jint socket, + jboolean blocking) +{ + setBlocking(e, socket, blocking); +} + +extern "C" JNIEXPORT void JNICALL + Java_java_nio_channels_DatagramChannel_configureBlocking(JNIEnv* e, + jclass c, + jint socket, + jboolean blocking) +{ + return Java_java_nio_channels_SocketChannel_configureBlocking( + e, c, socket, blocking); +} + +extern "C" JNIEXPORT void JNICALL + Java_java_nio_channels_SocketChannel_natSetTcpNoDelay(JNIEnv* e, + jclass, + jint socket, + jboolean on) +{ + setTcpNoDelay(e, socket, on); +} + +extern "C" JNIEXPORT jboolean JNICALL + Java_java_nio_channels_SocketChannel_natDoConnect(JNIEnv* e, + jclass, + jint socket, + jint host, + jint port) +{ + sockaddr_in address; + init(&address, host, port); + + return ::doConnect(e, socket, &address); +} + +extern "C" JNIEXPORT jint JNICALL + Java_java_nio_channels_SocketChannel_makeSocket(JNIEnv* e, jclass) +{ + return makeSocket(e); +} + +extern "C" JNIEXPORT jint JNICALL + Java_java_nio_channels_DatagramChannel_makeSocket(JNIEnv* e, jclass) +{ + return makeSocket(e, SOCK_DGRAM, IPPROTO_UDP); +} + +extern "C" JNIEXPORT jboolean JNICALL + Java_java_nio_channels_DatagramChannel_connect(JNIEnv* e, + jclass, + jint socket, + jint host, + jint port) +{ + sockaddr_in address; + init(&address, host, port); + + return ::doConnect(e, socket, &address); +} + +extern "C" JNIEXPORT void JNICALL + Java_java_nio_channels_SocketChannel_natFinishConnect(JNIEnv* e, + jclass, + jint socket) +{ + doFinishConnect(e, socket); +} + +extern "C" JNIEXPORT jint JNICALL + Java_java_nio_channels_SocketChannel_natRead(JNIEnv* e, + jclass, + jint socket, + jbyteArray buffer, + jint offset, + jint length, + jboolean blocking) +{ + int r; + if (blocking) { + uint8_t* buf = static_cast(allocate(e, length)); + if (buf) { + r = ::doRead(socket, buf, length); + if (r > 0) { + e->SetByteArrayRegion(buffer, offset, r, reinterpret_cast(buf)); + } + free(buf); + } else { + return 0; + } + } else { + jboolean isCopy; + uint8_t* buf + = static_cast(e->GetPrimitiveArrayCritical(buffer, &isCopy)); + + r = ::doRead(socket, buf + offset, length); + + e->ReleasePrimitiveArrayCritical(buffer, buf, 0); + } + + if (r < 0) { + if (eagain()) { + return 0; + } else { + throwIOException(e); + } + } else if (r == 0) { + return -1; + } + return r; +} + +extern "C" JNIEXPORT jint JNICALL + Java_java_nio_channels_DatagramChannel_receive(JNIEnv* e, + jclass, + jint socket, + jbyteArray buffer, + jint offset, + jint length, + jboolean blocking, + jintArray address) +{ + int r; + int32_t host; + int32_t port; + if (blocking) { + uint8_t* buf = static_cast(allocate(e, length)); + if (buf) { + r = ::doRecv(socket, buf, length, &host, &port); + if (r > 0) { + e->SetByteArrayRegion(buffer, offset, r, reinterpret_cast(buf)); + } + free(buf); + } else { + return 0; + } + } else { + jboolean isCopy; + uint8_t* buf + = static_cast(e->GetPrimitiveArrayCritical(buffer, &isCopy)); + + r = ::doRecv(socket, buf + offset, length, &host, &port); + + e->ReleasePrimitiveArrayCritical(buffer, buf, 0); + } + + if (r < 0) { + if (eagain()) { + return 0; + } else { + throwIOException(e); + } + } else if (r == 0) { + return -1; + } else { + jint jhost = host; + e->SetIntArrayRegion(address, 0, 1, &jhost); + jint jport = port; + e->SetIntArrayRegion(address, 1, 1, &jport); + } + + return r; +} + +extern "C" JNIEXPORT jint JNICALL + Java_java_nio_channels_SocketChannel_natWrite(JNIEnv* e, + jclass, + jint socket, + jbyteArray buffer, + jint offset, + jint length, + jboolean blocking) +{ + int r; + if (blocking) { + uint8_t* buf = static_cast(allocate(e, length)); + if (buf) { + e->GetByteArrayRegion( + buffer, offset, length, reinterpret_cast(buf)); + r = ::doWrite(socket, buf, length); + free(buf); + } else { + return 0; + } + } else { + jboolean isCopy; + uint8_t* buf + = static_cast(e->GetPrimitiveArrayCritical(buffer, &isCopy)); + + r = ::doWrite(socket, buf + offset, length); + + e->ReleasePrimitiveArrayCritical(buffer, buf, 0); + } + + if (r < 0) { + if (eagain()) { + return 0; + } else { + throwIOException(e); + } + } + return r; +} + +extern "C" JNIEXPORT jint JNICALL + Java_java_nio_channels_DatagramChannel_write(JNIEnv* e, + jclass c, + jint socket, + jbyteArray buffer, + jint offset, + jint length, + jboolean blocking) +{ + return Java_java_nio_channels_SocketChannel_natWrite( + e, c, socket, buffer, offset, length, blocking); +} + +extern "C" JNIEXPORT jint JNICALL + Java_java_nio_channels_DatagramChannel_send(JNIEnv* e, + jclass, + jint socket, + jint host, + jint port, + jbyteArray buffer, + jint offset, + jint length, + jboolean blocking) +{ + sockaddr_in address; + init(&address, host, port); + + int r; + if (blocking) { + uint8_t* buf = static_cast(allocate(e, length)); + if (buf) { + e->GetByteArrayRegion( + buffer, offset, length, reinterpret_cast(buf)); + r = ::doSend(socket, &address, buf, length); + free(buf); + } else { + return 0; + } + } else { + jboolean isCopy; + uint8_t* buf + = static_cast(e->GetPrimitiveArrayCritical(buffer, &isCopy)); + + r = ::doSend(socket, &address, buf + offset, length); + + e->ReleasePrimitiveArrayCritical(buffer, buf, 0); + } + + if (r < 0) { + if (eagain()) { + return 0; + } else { + throwIOException(e); + } + } + return r; +} + +extern "C" JNIEXPORT void JNICALL + Java_java_nio_channels_SocketChannel_natThrowWriteError(JNIEnv* e, + jclass, + jint socket) +{ + int error; + socklen_t size = sizeof(int); + int r = getsockopt( + socket, SOL_SOCKET, SO_ERROR, reinterpret_cast(&error), &size); + if (r != 0 or size != sizeof(int)) { + throwIOException(e); + } else if (error != 0) { + throwIOException(e, socketErrorString(e, error)); + } +} + +extern "C" JNIEXPORT void JNICALL + Java_java_nio_channels_SocketChannel_natCloseSocket(JNIEnv*, + jclass, + jint socket) +{ + doClose(socket); +} + +extern "C" JNIEXPORT void JNICALL + Java_java_nio_channels_DatagramChannel_close(JNIEnv*, jclass, jint socket) +{ + doClose(socket); +} + +namespace { + +class Pipe { + public: +#ifdef PLATFORM_WINDOWS + // The Windows socket API only accepts socket file descriptors, not + // pipe descriptors or others. Thus, to implement + // Selector.wakeup(), we make a socket connection via the loopback + // interface and use it as a pipe. + Pipe(JNIEnv* e) : connected_(false), listener_(-1), reader_(-1), writer_(-1) + { + sockaddr_in address; + address.sin_family = AF_INET; + address.sin_port = 0; + address.sin_addr.s_addr = inet_addr("127.0.0.1"); // INADDR_LOOPBACK; + + listener_ = makeSocket(e); + if (e->ExceptionCheck()) + return; + + setBlocking(e, listener_, false); + + ::doBind(e, listener_, &address); + if (e->ExceptionCheck()) + return; + + ::doListen(e, listener_); + if (e->ExceptionCheck()) + return; + + socklen_t length = sizeof(sockaddr_in); + int r = getsockname( + listener_, reinterpret_cast(&address), &length); + if (r) { + throwIOException(e); + return; + } + + writer_ = makeSocket(e); + if (e->ExceptionCheck()) + return; + + setBlocking(e, writer_, true); + connected_ = ::doConnect(e, writer_, &address); + } + + void dispose() + { + if (listener_ >= 0) + ::doClose(listener_); + if (reader_ >= 0) + ::doClose(reader_); + if (writer_ >= 0) + ::doClose(writer_); + } + + bool connected() + { + return connected_; + } + + void setConnected(bool v) + { + connected_ = v; + } + + int listener() + { + return listener_; + } + + void setListener(int v) + { + listener_ = v; + } + + int reader() + { + return reader_; + } + + void setReader(int v) + { + reader_ = v; + } + + int writer() + { + return writer_; + } + + private: + bool connected_; + int listener_; + int reader_; + int writer_; +#else + Pipe(JNIEnv* e) + { + if (::pipe(pipe) != 0) { + throwIOException(e); + return; + } + + if (setBlocking(e, pipe[0], false)) { + setBlocking(e, pipe[1], false); + } + + open_ = true; + } + + void dispose() + { + ::doClose(pipe[0]); + ::doClose(pipe[1]); + open_ = false; + } + + bool connected() + { + return open_; + } + + int reader() + { + return pipe[0]; + } + + int writer() + { + return pipe[1]; + } + + private: + int pipe[2]; + bool open_; +#endif +}; + +struct SelectorState { + fd_set read; + fd_set write; + fd_set except; + Pipe control; + SelectorState(JNIEnv* e) : control(e) + { + } +}; + +} // namespace + +extern "C" JNIEXPORT jlong JNICALL + Java_java_nio_channels_SocketSelector_natInit(JNIEnv* e, jclass) +{ + void* mem = malloc(sizeof(SelectorState)); + if (mem) { + SelectorState* s = new (mem) SelectorState(e); + if (e->ExceptionCheck()) + return 0; + + if (s) { + FD_ZERO(&(s->read)); + FD_ZERO(&(s->write)); + FD_ZERO(&(s->except)); + return reinterpret_cast(s); + } + } + throwNew(e, "java/lang/OutOfMemoryError", 0); + return 0; +} + +extern "C" JNIEXPORT void JNICALL + Java_java_nio_channels_SocketSelector_natWakeup(JNIEnv* e, + jclass, + jlong state) +{ + SelectorState* s = reinterpret_cast(state); + if (s->control.connected()) { + const char c = 1; + int r = ::doWrite(s->control.writer(), &c, 1); + if (r != 1) { + throwIOException(e); + } + } +} + +extern "C" JNIEXPORT void JNICALL + Java_java_nio_channels_SocketSelector_natClose(JNIEnv*, jclass, jlong state) +{ + SelectorState* s = reinterpret_cast(state); + s->control.dispose(); + free(s); +} + +extern "C" JNIEXPORT void JNICALL + Java_java_nio_channels_SocketSelector_natSelectClearAll(JNIEnv*, + jclass, + jint socket, + jlong state) +{ + SelectorState* s = reinterpret_cast(state); + FD_CLR(static_cast(socket), &(s->read)); + FD_CLR(static_cast(socket), &(s->write)); + FD_CLR(static_cast(socket), &(s->except)); +} + +extern "C" JNIEXPORT jint JNICALL + Java_java_nio_channels_SocketSelector_natSelectUpdateInterestSet( + JNIEnv*, + jclass, + jint socket, + jint interest, + jlong state, + jint max) +{ + SelectorState* s = reinterpret_cast(state); + if (interest & (java_nio_channels_SelectionKey_OP_READ + | java_nio_channels_SelectionKey_OP_ACCEPT)) { + FD_SET(static_cast(socket), &(s->read)); + if (max < socket) + max = socket; + } else { + FD_CLR(static_cast(socket), &(s->read)); + } + + if (interest & (java_nio_channels_SelectionKey_OP_WRITE + | java_nio_channels_SelectionKey_OP_CONNECT)) { + FD_SET(static_cast(socket), &(s->write)); + FD_SET(static_cast(socket), &(s->except)); + if (max < socket) + max = socket; + } else { + FD_CLR(static_cast(socket), &(s->write)); + } + return max; +} + +extern "C" JNIEXPORT jint JNICALL + Java_java_nio_channels_SocketSelector_natDoSocketSelect(JNIEnv* e, + jclass, + jlong state, + jint max, + jlong interval) +{ + SelectorState* s = reinterpret_cast(state); + if (s->control.reader() >= 0) { + int socket = s->control.reader(); + FD_SET(static_cast(socket), &(s->read)); + if (max < socket) + max = socket; + } + +#ifdef PLATFORM_WINDOWS + if (s->control.listener() >= 0) { + int socket = s->control.listener(); + FD_SET(static_cast(socket), &(s->read)); + if (max < socket) + max = socket; + } + + if (not s->control.connected()) { + int socket = s->control.writer(); + FD_SET(static_cast(socket), &(s->write)); + FD_SET(static_cast(socket), &(s->except)); + if (max < socket) + max = socket; + } +#endif + + timeval time; + if (interval > 0) { + time.tv_sec = interval / 1000; + time.tv_usec = (interval % 1000) * 1000; + } else if (interval < 0) { + time.tv_sec = 0; + time.tv_usec = 0; + } else { + time.tv_sec = 24 * 60 * 60 * 1000; + time.tv_usec = 0; + } + int r = ::select(max + 1, &(s->read), &(s->write), &(s->except), &time); + + if (r < 0) { + if (errno != EINTR) { + throwIOException(e); + return 0; + } + } + +#ifdef PLATFORM_WINDOWS + if (FD_ISSET(s->control.writer(), &(s->write)) + or FD_ISSET(s->control.writer(), &(s->except))) { + int socket = s->control.writer(); + FD_CLR(static_cast(socket), &(s->write)); + FD_CLR(static_cast(socket), &(s->except)); + + int error; + socklen_t size = sizeof(int); + int r = getsockopt( + socket, SOL_SOCKET, SO_ERROR, reinterpret_cast(&error), &size); + if (r != 0 or size != sizeof(int)) { + throwIOException(e); + } else if (error != 0) { + throwIOException(e, socketErrorString(e, error)); + } + s->control.setConnected(true); + } + + if (s->control.listener() >= 0 + and FD_ISSET(s->control.listener(), &(s->read))) { + FD_CLR(static_cast(s->control.listener()), &(s->read)); + + s->control.setReader(::doAccept(e, s->control.listener())); + s->control.setListener(-1); + } +#endif + + if (s->control.reader() >= 0 and FD_ISSET(s->control.reader(), &(s->read))) { + FD_CLR(static_cast(s->control.reader()), &(s->read)); + + char c; + int r = 1; + while (r == 1) { + r = ::doRead(s->control.reader(), &c, 1); + } + if (r < 0 and not eagain()) { + throwIOException(e); + } + } + + return r; +} + +extern "C" JNIEXPORT jint JNICALL + Java_java_nio_channels_SocketSelector_natUpdateReadySet(JNIEnv*, + jclass, + jint socket, + jint interest, + jlong state) +{ + SelectorState* s = reinterpret_cast(state); + jint ready = 0; + + if (FD_ISSET(socket, &(s->read))) { + if (interest & java_nio_channels_SelectionKey_OP_READ) { + ready |= java_nio_channels_SelectionKey_OP_READ; + } + + if (interest & java_nio_channels_SelectionKey_OP_ACCEPT) { + ready |= java_nio_channels_SelectionKey_OP_ACCEPT; + } + } + + if (FD_ISSET(socket, &(s->write)) or FD_ISSET(socket, &(s->except))) { + if (interest & java_nio_channels_SelectionKey_OP_WRITE) { + ready |= java_nio_channels_SelectionKey_OP_WRITE; + } + + if (interest & java_nio_channels_SelectionKey_OP_CONNECT) { + ready |= java_nio_channels_SelectionKey_OP_CONNECT; + } + } + + return ready; +} + +extern "C" JNIEXPORT jboolean JNICALL + Java_java_nio_ByteOrder_isNativeBigEndian(JNIEnv*, jclass) +{ + union { + uint32_t i; + char c[4]; + } u = {0x01020304}; + + if (u.c[0] == 1) + return JNI_TRUE; + return JNI_FALSE; +} + +#endif // !SGX \ No newline at end of file diff --git a/sgx-jvm/avian/classpath/java-util-zip.cpp b/sgx-jvm/avian/classpath/java-util-zip.cpp new file mode 100644 index 0000000000..0839d181e0 --- /dev/null +++ b/sgx-jvm/avian/classpath/java-util-zip.cpp @@ -0,0 +1,172 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#include "stdlib.h" +#include "string.h" +#include "avian/zlib-custom.h" + +#include "jni.h" +#include "jni-util.h" + +extern "C" JNIEXPORT jlong JNICALL + Java_java_util_zip_Inflater_make(JNIEnv* e, jclass, jboolean nowrap) +{ + z_stream* s = static_cast(malloc(sizeof(z_stream))); + if (s == 0) { + throwNew(e, "java/lang/OutOfMemoryError", 0); + return 0; + } + + memset(s, 0, sizeof(z_stream)); + + int r = inflateInit2(s, (nowrap ? -15 : 15)); + if (r != Z_OK) { + free(s); + throwNew(e, "java/lang/RuntimeException", zError(r)); + return 0; + } + + return reinterpret_cast(s); +} + +extern "C" JNIEXPORT void JNICALL + Java_java_util_zip_Inflater_dispose(JNIEnv*, jclass, jlong peer) +{ + z_stream* s = reinterpret_cast(peer); + inflateEnd(s); + free(s); +} + +extern "C" JNIEXPORT void JNICALL + Java_java_util_zip_Inflater_inflate(JNIEnv* e, + jclass, + jlong peer, + jbyteArray input, + jint inputOffset, + jint inputLength, + jbyteArray output, + jint outputOffset, + jint outputLength, + jintArray results) +{ + z_stream* s = reinterpret_cast(peer); + + jbyte* in = static_cast(malloc(inputLength)); + if (in == 0) { + throwNew(e, "java/lang/OutOfMemoryError", 0); + return; + } + + jbyte* out = static_cast(malloc(outputLength)); + if (out == 0) { + free(in); + throwNew(e, "java/lang/OutOfMemoryError", 0); + return; + } + + e->GetByteArrayRegion(input, inputOffset, inputLength, in); + + s->next_in = reinterpret_cast(in); + s->avail_in = inputLength; + s->next_out = reinterpret_cast(out); + s->avail_out = outputLength; + + int r = inflate(s, Z_SYNC_FLUSH); + jint resultArray[3] = {r, + static_cast(inputLength - s->avail_in), + static_cast(outputLength - s->avail_out)}; + + free(in); + + e->SetByteArrayRegion(output, outputOffset, resultArray[2], out); + free(out); + + e->SetIntArrayRegion(results, 0, 3, resultArray); +} + +extern "C" JNIEXPORT jlong JNICALL + Java_java_util_zip_Deflater_make(JNIEnv* e, + jclass, + jboolean nowrap, + jint level) +{ + z_stream* s = static_cast(malloc(sizeof(z_stream))); + if (s == 0) { + throwNew(e, "java/lang/OutOfMemoryError", 0); + return 0; + } + + memset(s, 0, sizeof(z_stream)); + + int r = deflateInit2(s, level, (nowrap ? -15 : 15)); + if (r != Z_OK) { + free(s); + throwNew(e, "java/lang/RuntimeException", zError(r)); + return 0; + } + + return reinterpret_cast(s); +} + +extern "C" JNIEXPORT void JNICALL + Java_java_util_zip_Deflater_dispose(JNIEnv*, jclass, jlong peer) +{ + z_stream* s = reinterpret_cast(peer); + deflateEnd(s); + free(s); +} + +extern "C" JNIEXPORT void JNICALL + Java_java_util_zip_Deflater_deflate(JNIEnv* e, + jclass, + jlong peer, + jbyteArray input, + jint inputOffset, + jint inputLength, + jbyteArray output, + jint outputOffset, + jint outputLength, + jboolean finish, + jintArray results) +{ + z_stream* s = reinterpret_cast(peer); + + jbyte* in = static_cast(malloc(inputLength)); + if (in == 0) { + throwNew(e, "java/lang/OutOfMemoryError", 0); + return; + } + + jbyte* out = static_cast(malloc(outputLength)); + if (out == 0) { + free(in); + throwNew(e, "java/lang/OutOfMemoryError", 0); + return; + } + + e->GetByteArrayRegion(input, inputOffset, inputLength, in); + + s->next_in = reinterpret_cast(in); + s->avail_in = inputLength; + s->next_out = reinterpret_cast(out); + s->avail_out = outputLength; + + int r = deflate(s, finish ? Z_FINISH : Z_NO_FLUSH); + jint resultArray[3] = {r, + static_cast(inputLength - s->avail_in), + static_cast(outputLength - s->avail_out)}; + + free(in); + + e->SetByteArrayRegion(output, outputOffset, resultArray[2], out); + free(out); + + e->SetIntArrayRegion(results, 0, 3, resultArray); +} diff --git a/sgx-jvm/avian/classpath/java-util.cpp b/sgx-jvm/avian/classpath/java-util.cpp new file mode 100644 index 0000000000..bb36df86f8 --- /dev/null +++ b/sgx-jvm/avian/classpath/java-util.cpp @@ -0,0 +1,58 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#include "time.h" +#include "jni.h" +#include "jni-util.h" + +namespace { + +#if (!defined PLATFORM_WINDOWS) || (defined _MSC_VER) + +void removeNewline(char* s) +{ + for (; s; ++s) { + if (*s == '\n') { + *s = 0; + break; + } + } +} + +#endif + +} // namespace + +extern "C" JNIEXPORT jstring JNICALL + Java_java_util_Date_toString(JNIEnv* e, jclass c UNUSED, jlong when) +{ + const unsigned BufferSize UNUSED = 27; + + time_t time = when / 1000; + +#ifdef PLATFORM_WINDOWS + e->MonitorEnter(c); +#ifdef _MSC_VER + char buffer[BufferSize]; + ctime_s(buffer, BufferSize, &time); + removeNewline(buffer); +#else + char* buffer = ctime(&time); +#endif + jstring r = e->NewStringUTF(buffer); + e->MonitorExit(c); + return r; +#else + char buffer[BufferSize]; + ctime_r(&time, buffer); + removeNewline(buffer); + return e->NewStringUTF(buffer); +#endif +} diff --git a/sgx-jvm/avian/classpath/java/io/BufferedInputStream.java b/sgx-jvm/avian/classpath/java/io/BufferedInputStream.java new file mode 100644 index 0000000000..25a7441304 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/io/BufferedInputStream.java @@ -0,0 +1,88 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ +package java.io; + +import java.io.IOException; +import java.io.InputStream; + +public class BufferedInputStream extends InputStream { + private final InputStream in; + private final byte[] buffer; + private int position; + private int limit; + + public BufferedInputStream(InputStream in, int size) { + this.in = in; + this.buffer = new byte[size]; + } + + public BufferedInputStream(InputStream in) { + this(in, 4096); + } + + private int fill() throws IOException { + position = 0; + limit = in.read(buffer); + + return limit; + } + + public int read() throws IOException { + if (position >= limit && fill() == -1) { + return -1; + } + + return buffer[position++] & 0xFF; + } + + public int read(byte[] b, int offset, int length) throws IOException { + int count = 0; + if (position >= limit && fill() == -1) { + return -1; + } + if (position < limit) { + int remaining = limit - position; + if (remaining > length) { + remaining = length; + } + + System.arraycopy(buffer, position, b, offset, remaining); + + count += remaining; + position += remaining; + offset += remaining; + length -= remaining; + } + while (length > 0 && in.available() > 0) + { + int c = in.read(b, offset, length); + if (c == -1) { + if (count == 0) { + count = -1; + } + break; + } else { + offset += c; + count += c; + length -= c; + } + } + return count; + } + + public int available() throws IOException { + return in.available() + (limit - position); + } + + public void close() throws IOException { + in.close(); + } +} + diff --git a/sgx-jvm/avian/classpath/java/io/BufferedOutputStream.java b/sgx-jvm/avian/classpath/java/io/BufferedOutputStream.java new file mode 100644 index 0000000000..165ebc2cca --- /dev/null +++ b/sgx-jvm/avian/classpath/java/io/BufferedOutputStream.java @@ -0,0 +1,61 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.io; + +public class BufferedOutputStream extends OutputStream { + private final OutputStream out; + private final byte[] buffer; + private int position; + + public BufferedOutputStream(OutputStream out, int size) { + this.out = out; + this.buffer = new byte[size]; + } + + public BufferedOutputStream(OutputStream out) { + this(out, 4096); + } + + private void drain() throws IOException { + if (position > 0) { + out.write(buffer, 0, position); + position = 0; + } + } + + public void write(int c) throws IOException { + if (position >= buffer.length) { + drain(); + } + + buffer[position++] = (byte) (c & 0xFF); + } + + public void write(byte[] b, int offset, int length) throws IOException { + if (length > buffer.length - position) { + drain(); + out.write(b, offset, length); + } else { + System.arraycopy(b, offset, buffer, position, length); + position += length; + } + } + + public void flush() throws IOException { + drain(); + out.flush(); + } + + public void close() throws IOException { + flush(); + out.close(); + } +} diff --git a/sgx-jvm/avian/classpath/java/io/BufferedReader.java b/sgx-jvm/avian/classpath/java/io/BufferedReader.java new file mode 100644 index 0000000000..8d5a69b884 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/io/BufferedReader.java @@ -0,0 +1,101 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.io; + +public class BufferedReader extends Reader { + private final Reader in; + private final char[] buffer; + private int position; + private int limit; + + public BufferedReader(Reader in, int bufferSize) { + this.in = in; + this.buffer = new char[bufferSize]; + } + + public BufferedReader(Reader in) { + this(in, 32); + } + + private void fill() throws IOException { + position = 0; + limit = in.read(buffer); + } + + public String readLine() throws IOException { + StringBuilder sb = new StringBuilder(); + while (true) { + if (position >= limit) { + fill(); + } + + if (position >= limit) { + return sb.length() == 0 ? null : sb.toString(); + } + + for (int i = position; i < limit; ++i) { + if(buffer[i] == '\r') { + sb.append(buffer, position, i - position); + position = i + 1; + if(i+1 < limit && buffer[i+1] == '\n') { + position = i + 2; + } + return sb.toString(); + } else if (buffer[i] == '\n') { + sb.append(buffer, position, i - position); + position = i + 1; + return sb.toString(); + } + } + sb.append(buffer, position, limit-position); + position = limit; + } + } + + public int read(char[] b, int offset, int length) throws IOException { + int count = 0; + + if (position >= limit && length < buffer.length) { + fill(); + } + + if (position < limit) { + int remaining = limit - position; + if (remaining > length) { + remaining = length; + } + + System.arraycopy(buffer, position, b, offset, remaining); + + count += remaining; + position += remaining; + offset += remaining; + length -= remaining; + } + + if (length > 0) { + int c = in.read(b, offset, length); + if (c == -1) { + if (count == 0) { + count = -1; + } + } else { + count += c; + } + } + + return count; + } + + public void close() throws IOException { + in.close(); + } +} diff --git a/sgx-jvm/avian/classpath/java/io/BufferedWriter.java b/sgx-jvm/avian/classpath/java/io/BufferedWriter.java new file mode 100644 index 0000000000..e1c4e71b18 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/io/BufferedWriter.java @@ -0,0 +1,53 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.io; + +public class BufferedWriter extends Writer { + private final Writer out; + private final char[] buffer; + private int position; + + public BufferedWriter(Writer out, int size) { + this.out = out; + this.buffer = new char[size]; + } + + public BufferedWriter(Writer out) { + this(out, 4096); + } + + private void drain() throws IOException { + if (position > 0) { + out.write(buffer, 0, position); + position = 0; + } + } + + public void write(char[] b, int offset, int length) throws IOException { + if (length > buffer.length - position) { + drain(); + out.write(b, offset, length); + } else { + System.arraycopy(b, offset, buffer, position, length); + position += length; + } + } + + public void flush() throws IOException { + drain(); + out.flush(); + } + + public void close() throws IOException { + flush(); + out.close(); + } +} diff --git a/sgx-jvm/avian/classpath/java/io/ByteArrayInputStream.java b/sgx-jvm/avian/classpath/java/io/ByteArrayInputStream.java new file mode 100644 index 0000000000..e5373b6a62 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/io/ByteArrayInputStream.java @@ -0,0 +1,55 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.io; + +public class ByteArrayInputStream extends InputStream { + private final byte[] array; + private int position; + private final int limit; + + public ByteArrayInputStream(byte[] array, int offset, int length) { + this.array = array; + position = offset; + this.limit = offset + length; + } + + public ByteArrayInputStream(byte[] array) { + this(array, 0, array.length); + } + + public int read() { + if (position < limit) { + return array[position++] & 0xff; + } else { + return -1; + } + } + + public int read(byte[] buffer, int offset, int bufferLength) { + if (bufferLength == 0) { + return 0; + } + if (position >= limit) { + return -1; + } + int remaining = limit-position; + if (remaining < bufferLength) { + bufferLength = remaining; + } + System.arraycopy(array, position, buffer, offset, bufferLength); + position += bufferLength; + return bufferLength; + } + + public int available() { + return limit - position; + } +} diff --git a/sgx-jvm/avian/classpath/java/io/ByteArrayOutputStream.java b/sgx-jvm/avian/classpath/java/io/ByteArrayOutputStream.java new file mode 100644 index 0000000000..96b0cd584e --- /dev/null +++ b/sgx-jvm/avian/classpath/java/io/ByteArrayOutputStream.java @@ -0,0 +1,148 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.io; + +public class ByteArrayOutputStream extends OutputStream { + private static final int BufferSize = 32; + + private Cell firstCell; + private Cell curCell; + private int length; + private byte[] buffer; + private int position; + + public ByteArrayOutputStream(int capacity) { } + + public ByteArrayOutputStream() { + this(0); + } + + public void reset() { + firstCell = null; + curCell = null; + length = 0; + buffer = null; + position = 0; + } + + public int size() { + return length; + } + + public void write(int c) { + if (buffer == null) { + buffer = new byte[BufferSize]; + } else if (position >= buffer.length) { + flushBuffer(); + buffer = new byte[BufferSize]; + } + + buffer[position++] = (byte) (c & 0xFF); + ++ length; + } + + private byte[] copy(byte[] b, int offset, int length) { + byte[] array = new byte[length]; + System.arraycopy(b, offset, array, 0, length); + return array; + } + + public void write(byte[] b, int offset, int length) { + if (b == null) { + throw new NullPointerException(); + } + + if (offset < 0 || offset + length > b.length) { + throw new ArrayIndexOutOfBoundsException(); + } + + if (length == 0) return; + + if (buffer != null && length <= buffer.length - position) { + System.arraycopy(b, offset, buffer, position, length); + position += length; + } else { + flushBuffer(); + chainCell( new Cell(copy(b, offset, length), 0, length) ); + } + + this.length += length; + } + + private void chainCell(Cell cell){ + if (curCell == null){ + firstCell = cell; + curCell = cell; + }else{ + curCell.next = cell; + curCell = cell; + } + } + + private void flushBuffer() { + if (position > 0) { + byte[] b = buffer; + int p = position; + buffer = null; + position = 0; + + chainCell( new Cell(b, 0, p) ); + } + } + + public byte[] toByteArray() { + flushBuffer(); + + byte[] array = new byte[length]; + int pos = 0; + for (Cell c = firstCell; c != null; c = c.next) { + System.arraycopy(c.array, c.offset, array, pos, c.length); + pos += c.length; + } + return array; + } + + public synchronized void writeTo(OutputStream out) throws IOException { + if (length==0) return; + + if (out == null){ + throw new NullPointerException(); + } + + flushBuffer(); + + for (Cell c = firstCell; c != null; c = c.next) { + out.write(c.array, c.offset, c.length); + } + } + + @Override + public String toString() { + return new String(toByteArray()); + } + + public String toString(String encoding) throws UnsupportedEncodingException { + return new String(toByteArray(), encoding); + } + + private static class Cell { + public byte[] array; + public int offset; + public int length; + public Cell next = null; + + public Cell(byte[] array, int offset, int length) { + this.array = array; + this.offset = offset; + this.length = length; + } + } +} diff --git a/sgx-jvm/avian/classpath/java/io/Closeable.java b/sgx-jvm/avian/classpath/java/io/Closeable.java new file mode 100644 index 0000000000..5a04d7db63 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/io/Closeable.java @@ -0,0 +1,16 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.io; + +public interface Closeable extends AutoCloseable { + void close() + throws IOException; +} diff --git a/sgx-jvm/avian/classpath/java/io/DataInput.java b/sgx-jvm/avian/classpath/java/io/DataInput.java new file mode 100644 index 0000000000..4c9c25cf54 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/io/DataInput.java @@ -0,0 +1,29 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.io; + +public interface DataInput { + boolean readBoolean() throws IOException; + byte readByte() throws IOException; + char readChar() throws IOException; + double readDouble() throws IOException; + float readFloat() throws IOException; + void readFully(byte[] b) throws IOException; + void readFully(byte[] b, int off, int len) throws IOException; + int readInt() throws IOException; + String readLine() throws IOException; + long readLong() throws IOException; + short readShort() throws IOException; + int readUnsignedByte() throws IOException; + int readUnsignedShort() throws IOException; + String readUTF() throws IOException; + int skipBytes(int n) throws IOException; +} diff --git a/sgx-jvm/avian/classpath/java/io/DataInputStream.java b/sgx-jvm/avian/classpath/java/io/DataInputStream.java new file mode 100644 index 0000000000..a80d93c5bc --- /dev/null +++ b/sgx-jvm/avian/classpath/java/io/DataInputStream.java @@ -0,0 +1,132 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.io; + +public class DataInputStream extends InputStream implements DataInput { + private InputStream in; + + public DataInputStream(InputStream in) { + this.in = in; + } + + public void close() throws IOException { + in.close(); + } + + public int read(byte[] buffer) throws IOException { + return in.read(buffer); + } + + public int read(byte[] buffer, int offset, int length) throws IOException { + return in.read(buffer, offset, length); + } + + public void readFully(byte[] b) throws IOException { + readFully(b, 0, b.length); + } + + public void readFully(byte[] b, int offset, int length) throws IOException { + while (length > 0) { + int count = read(b, offset, length); + if (count < 0) { + throw new EOFException("Reached EOF " + length + " bytes too early"); + } + offset += count; + length -= count; + } + } + + public int read() throws IOException { + return in.read(); + } + + private int read0() throws IOException { + int b = in.read(); + if (b < 0) { + throw new EOFException(); + } + return b; + } + + public boolean readBoolean() throws IOException { + return read0() != 0; + } + + public byte readByte() throws IOException { + return (byte)read0(); + } + + public short readShort() throws IOException { + return (short)((read0() << 8) | read0()); + } + + public int readInt() throws IOException { + return ((read0() << 24) | (read0() << 16) | (read0() << 8) | read0()); + } + + public float readFloat() throws IOException { + return Float.floatToIntBits(readInt()); + } + + public double readDouble() throws IOException { + return Double.doubleToLongBits(readLong()); + } + + public long readLong() throws IOException { + return ((readInt() & 0xffffffffl) << 32) | (readInt() & 0xffffffffl); + } + + public char readChar() throws IOException { + return (char)readShort(); + } + + public int readUnsignedByte() throws IOException { + return readByte() & 0xff; + } + + public int readUnsignedShort() throws IOException { + return readShort() & 0xffff; + } + + public String readUTF() throws IOException { + int length = readUnsignedShort(); + byte[] bytes = new byte[length]; + readFully(bytes); + return new String(bytes, "UTF-8"); + } + + @Deprecated + public String readLine() throws IOException { + int c = read(); + if (c < 0) { + return null; + } else if (c == '\n') { + return ""; + } + StringBuilder builder = new StringBuilder(); + for (;;) { + builder.append((char)c); + c = read(); + if (c < 0 || c == '\n') { + return builder.toString(); + } + } + } + + public int skipBytes(int n) throws IOException { + for (int count = 0; count < n; ++count) { + if (read() < 0) {; + return count; + } + } + return n; + } +} diff --git a/sgx-jvm/avian/classpath/java/io/DataOutput.java b/sgx-jvm/avian/classpath/java/io/DataOutput.java new file mode 100644 index 0000000000..9365e6cd73 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/io/DataOutput.java @@ -0,0 +1,28 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.io; + +public interface DataOutput { + void write(byte[] b) throws IOException; + void write(byte[] b, int off, int len) throws IOException; + void write(int b) throws IOException; + void writeBoolean(boolean v) throws IOException; + void writeByte(int v) throws IOException; + void writeBytes(String s) throws IOException; + void writeChar(int v) throws IOException; + void writeChars(String s) throws IOException; + void writeDouble(double v) throws IOException; + void writeFloat(float v) throws IOException; + void writeInt(int v) throws IOException; + void writeLong(long v) throws IOException; + void writeShort(int v) throws IOException; + void writeUTF(String s) throws IOException; +} diff --git a/sgx-jvm/avian/classpath/java/io/DataOutputStream.java b/sgx-jvm/avian/classpath/java/io/DataOutputStream.java new file mode 100644 index 0000000000..0bec001a5f --- /dev/null +++ b/sgx-jvm/avian/classpath/java/io/DataOutputStream.java @@ -0,0 +1,99 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.io; + +public class DataOutputStream extends OutputStream implements DataOutput { + private OutputStream out; + + public DataOutputStream(OutputStream out) { + this.out = out; + } + + public void close() throws IOException { + out.close(); + } + + public void flush() throws IOException { + out.flush(); + } + + public void write(byte[] buffer) throws IOException { + out.write(buffer); + } + + public void write(byte[] buffer, int offset, int length) throws IOException { + out.write(buffer, offset, length); + } + + public void write(int b) throws IOException { + out.write(b); + } + + public void writeBoolean(boolean b) throws IOException { + writeByte(b ? 1 : 0); + } + + public void writeByte(int b) throws IOException { + out.write(b); + } + + public void writeShort(int s) throws IOException { + write((byte)(s >> 8)); + write((byte)s); + } + + public void writeInt(int i) throws IOException { + write((byte)(i >> 24)); + write((byte)(i >> 16)); + write((byte)(i >> 8)); + write((byte)i); + } + + public void writeFloat(float f) throws IOException { + writeInt(Float.floatToIntBits(f)); + } + + public void writeDouble(double d) throws IOException { + writeLong(Double.doubleToLongBits(d)); + } + + public void writeLong(long l) throws IOException { + write((byte)(l >> 56)); + write((byte)(l >> 48)); + write((byte)(l >> 40)); + write((byte)(l >> 32)); + write((byte)(l >> 24)); + write((byte)(l >> 16)); + write((byte)(l >> 8)); + write((byte)l); + } + + public void writeChar(int ch) throws IOException { + write((byte)(ch >> 8)); + write((byte)ch); + } + + public void writeChars(String s) throws IOException { + for (char ch : s.toCharArray()) { + writeChar(ch & 0xffff); + } + } + + public void writeBytes(String s) throws IOException { + out.write(s.getBytes()); + } + + public void writeUTF(String s) throws IOException { + byte[] bytes = s.getBytes("UTF-8"); + writeShort((short)bytes.length); + out.write(bytes); + } +} diff --git a/sgx-jvm/avian/classpath/java/io/EOFException.java b/sgx-jvm/avian/classpath/java/io/EOFException.java new file mode 100644 index 0000000000..78a9e995a2 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/io/EOFException.java @@ -0,0 +1,21 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.io; + +public class EOFException extends IOException { + public EOFException(String message) { + super(message); + } + + public EOFException() { + this(null); + } +} diff --git a/sgx-jvm/avian/classpath/java/io/Externalizable.java b/sgx-jvm/avian/classpath/java/io/Externalizable.java new file mode 100644 index 0000000000..48351db912 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/io/Externalizable.java @@ -0,0 +1,16 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.io; + +public interface Externalizable { + public void readExternal(ObjectInput in); + public void writeExternal(ObjectOutput out); +} diff --git a/sgx-jvm/avian/classpath/java/io/File.java b/sgx-jvm/avian/classpath/java/io/File.java new file mode 100644 index 0000000000..732f2d050f --- /dev/null +++ b/sgx-jvm/avian/classpath/java/io/File.java @@ -0,0 +1,335 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.io; + +public class File implements Serializable { + private static final String FileSeparator + = System.getProperty("file.separator"); + + private static final boolean IsWindows + = System.getProperty("os.name").equals("Windows"); + + public static final String separator = FileSeparator; + + public static final char separatorChar = FileSeparator.charAt(0); + + private static final String PathSeparator + = System.getProperty("path.separator"); + + public static final String pathSeparator = PathSeparator; + + public static final char pathSeparatorChar = PathSeparator.charAt(0); + + // static { + // System.loadLibrary("natives"); + // } + + private final String path; + + public File(String path) { + if (path == null) throw new NullPointerException(); + this.path = normalize(path); + } + + public File(String parent, String child) { + this(parent + FileSeparator + child); + } + + public File(File parent, String child) { + this(parent.getPath() + FileSeparator + child); + } + + public static File createTempFile(String prefix, String suffix) + throws IOException + { + return createTempFile(prefix, suffix, null); + } + + public static File createTempFile(String prefix, String suffix, + File directory) + throws IOException + { + if(directory == null) { + directory = new File(System.getProperty("java.io.tmpdir")); + } + if(suffix == null) { + suffix = ".tmp"; + } + File ret; + long state = System.currentTimeMillis(); + + do { + ret = generateFile(directory, prefix, state, suffix); + state *= 7; + state += 3; + } while(ret == null); + ret.createNewFile(); + return ret; + } + + private static File generateFile(File directory, String prefix, long state, String suffix) { + File ret = new File(directory, prefix + state + suffix); + if(ret.exists()) { + return null; + } else { + return ret; + } + } + + private static String stripSeparators(String p) { + while (p.endsWith(FileSeparator)) { + p = p.substring(0, p.length() - 1); + } + return p; + } + + private static String normalize(String path) { + if(IsWindows + && path.length() > 2 + && path.charAt(0) == '/' + && path.charAt(2) == ':') + { + // remove a leading slash on Windows + path = path.substring(1); + } + return stripSeparators + ("\\".equals(FileSeparator) ? path.replace('/', '\\') : path); + } + + public static native boolean rename(String old, String new_); + + public boolean renameTo(File newName) { + return rename(path, newName.path); + } + + private static native boolean isDirectory(String path); + + public boolean isDirectory() { + return isDirectory(path); + } + + private static native boolean isFile(String path); + + public boolean isFile() { + return isFile(path); + } + + public boolean isAbsolute() { + return path.equals(toAbsolutePath(path)); + } + + private static native boolean canRead(String path); + + public boolean canRead() { + return canRead(path); + } + + private static native boolean canWrite(String path); + + public boolean canWrite() { + return canWrite(path); + } + + private static native boolean canExecute(String path); + + public boolean canExecute() { + return canExecute(path); + } + + private static native boolean setExecutable(String path, boolean executable, boolean ownerOnly); + + public boolean setExecutable(boolean executable) { + return setExecutable(executable, true); + } + + public boolean setExecutable(boolean executable, boolean ownerOnly) { + return setExecutable(path, executable, ownerOnly); + } + + public String getName() { + int index = path.lastIndexOf(FileSeparator); + if (index >= 0) { + return path.substring(index + 1); + } else { + return path; + } + } + + public String toString() { + return getPath(); + } + + public String getPath() { + return path; + } + + public String getParent() { + int index = path.lastIndexOf(FileSeparator); + if (index >= 0) { + return normalize(path.substring(0, index)); + } else { + return null; + } + } + + public File getParentFile() { + String s = getParent(); + return (s == null ? null : new File(s)); + } + + private static native String toCanonicalPath(String path); + + public String getCanonicalPath() { + return toCanonicalPath(path); + } + + public File getCanonicalFile() { + return new File(getCanonicalPath()); + } + + private static native String toAbsolutePath(String path); + + public String getAbsolutePath() { + return toAbsolutePath(path); + } + + public File getAbsoluteFile() { + return new File(getAbsolutePath()); + } + + private static native long length(String path); + + public long length() { + return length(path); + } + + private static native boolean exists(String path); + + public boolean exists() { + return exists(path); + } + + private static native void mkdir(String path) throws IOException; + + public boolean mkdir() { + try { + mkdir(path); + return true; + } catch (IOException e) { + return false; + } + } + + private static native boolean createNewFile(String path) throws IOException; + + public boolean createNewFile() throws IOException { + return createNewFile(path); + } + + public static native void delete(String path) throws IOException; + + public boolean delete() { + try { + delete(path); + return true; + } catch (IOException e) { + return false; + } + } + + public boolean mkdirs() { + File parent = getParentFile(); + if (parent != null) { + if (!parent.exists()) { + if (!parent.mkdirs()) { + return false; + } + } + } + return mkdir(); + } + + public File[] listFiles() { + return listFiles(null); + } + + public File[] listFiles(FilenameFilter filter) { + String[] list = list(filter); + if (list != null) { + File[] result = new File[list.length]; + for (int i = 0; i < list.length; ++i) { + result[i] = new File(this, list[i]); + } + return result; + } else { + return null; + } + } + + public String[] list() { + return list(null); + } + + public String[] list(FilenameFilter filter) { + long handle = 0; + try { + handle = openDir(path); + if (handle != 0) { + Pair list = null; + int count = 0; + for (String s = readDir(handle); s != null; s = readDir(handle)) { + if (filter == null || filter.accept(this, s)) { + list = new Pair(s, list); + ++ count; + } + } + + String[] result = new String[count]; + for (int i = count - 1; i >= 0; --i) { + result[i] = list.value; + list = list.next; + } + + return result; + } else { + return null; + } + } finally { + if (handle != 0) { + closeDir(handle); + } + } + } + + public long lastModified() { + return lastModified(path); + } + private static native long openDir(String path); + + private static native long lastModified(String path); + + private static native String readDir(long handle); + + private static native void closeDir(long handle); + + + + private static class Pair { + public final String value; + public final Pair next; + + public Pair(String value, Pair next) { + this.value = value; + this.next = next; + } + } + +} diff --git a/sgx-jvm/avian/classpath/java/io/FileDescriptor.java b/sgx-jvm/avian/classpath/java/io/FileDescriptor.java new file mode 100644 index 0000000000..0c7d5f7201 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/io/FileDescriptor.java @@ -0,0 +1,27 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.io; + +public class FileDescriptor { + public static final FileDescriptor in = new FileDescriptor(0); + public static final FileDescriptor out = new FileDescriptor(1); + public static final FileDescriptor err = new FileDescriptor(2); + + final int value; + + public FileDescriptor(int value) { + this.value = value; + } + + public FileDescriptor() { + this(-1); + } +} diff --git a/sgx-jvm/avian/classpath/java/io/FileInputStream.java b/sgx-jvm/avian/classpath/java/io/FileInputStream.java new file mode 100644 index 0000000000..e2e7fa6e48 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/io/FileInputStream.java @@ -0,0 +1,77 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.io; + +public class FileInputStream extends InputStream { + // static { + // System.loadLibrary("natives"); + // } + + private int fd; + private int remaining; + + public FileInputStream(FileDescriptor fd) { + this.fd = fd.value; + } + + public FileInputStream(String path) throws IOException { + fd = open(path); + remaining = (int) new File(path).length(); + } + + public FileInputStream(File file) throws IOException { + this(file.getPath()); + } + + public int available() throws IOException { + return remaining; + } + + private static native int open(String path) throws IOException; + + private static native int read(int fd) throws IOException; + + private static native int read(int fd, byte[] b, int offset, int length) + throws IOException; + + public static native void close(int fd) throws IOException; + + public int read() throws IOException { + int c = read(fd); + if (c >= 0 && remaining > 0) { + -- remaining; + } + return c; + } + + public int read(byte[] b, int offset, int length) throws IOException { + if (b == null) { + throw new NullPointerException(); + } + + if (offset < 0 || offset + length > b.length) { + throw new ArrayIndexOutOfBoundsException(); + } + + int c = read(fd, b, offset, length); + if (c > 0 && remaining > 0) { + remaining -= c; + } + return c; + } + + public void close() throws IOException { + if (fd != -1) { + close(fd); + fd = -1; + } + } +} diff --git a/sgx-jvm/avian/classpath/java/io/FileNotFoundException.java b/sgx-jvm/avian/classpath/java/io/FileNotFoundException.java new file mode 100644 index 0000000000..114595f470 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/io/FileNotFoundException.java @@ -0,0 +1,21 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.io; + +public class FileNotFoundException extends IOException { + public FileNotFoundException(String message) { + super(message); + } + + public FileNotFoundException() { + this(null); + } +} diff --git a/sgx-jvm/avian/classpath/java/io/FileOutputStream.java b/sgx-jvm/avian/classpath/java/io/FileOutputStream.java new file mode 100644 index 0000000000..8732004e72 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/io/FileOutputStream.java @@ -0,0 +1,68 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.io; + +public class FileOutputStream extends OutputStream { + // static { + // System.loadLibrary("natives"); + // } + + private int fd; + + public FileOutputStream(FileDescriptor fd) { + this.fd = fd.value; + } + + public FileOutputStream(String path) throws IOException { + this(path, false); + } + + public FileOutputStream(String path, boolean append) throws IOException { + fd = open(path, append); + } + + + public FileOutputStream(File file) throws IOException { + this(file.getPath()); + } + + private static native int open(String path, boolean append) throws IOException; + + private static native void write(int fd, int c) throws IOException; + + private static native void write(int fd, byte[] b, int offset, int length) + throws IOException; + + private static native void close(int fd) throws IOException; + + public void write(int c) throws IOException { + write(fd, c); + } + + public void write(byte[] b, int offset, int length) throws IOException { + if (b == null) { + throw new NullPointerException(); + } + + if (offset < 0 || offset + length > b.length) { + throw new ArrayIndexOutOfBoundsException(); + } + + write(fd, b, offset, length); + } + + public void close() throws IOException { + if (fd != -1) { + close(fd); + fd = -1; + } + } +} diff --git a/sgx-jvm/avian/classpath/java/io/FileReader.java b/sgx-jvm/avian/classpath/java/io/FileReader.java new file mode 100644 index 0000000000..fa484720ae --- /dev/null +++ b/sgx-jvm/avian/classpath/java/io/FileReader.java @@ -0,0 +1,39 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.io; + +public class FileReader extends Reader { + private final Reader in; + + public FileReader(FileInputStream in) { + this.in = new InputStreamReader(in); + } + + public FileReader(FileDescriptor fd) { + this(new FileInputStream(fd)); + } + + public FileReader(String path) throws IOException { + this(new FileInputStream(path)); + } + + public FileReader(File file) throws IOException { + this(new FileInputStream(file)); + } + + public int read(char[] b, int offset, int length) throws IOException { + return in.read(b, offset, length); + } + + public void close() throws IOException { + in.close(); + } +} diff --git a/sgx-jvm/avian/classpath/java/io/FileWriter.java b/sgx-jvm/avian/classpath/java/io/FileWriter.java new file mode 100644 index 0000000000..ca384b0af4 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/io/FileWriter.java @@ -0,0 +1,43 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.io; + +public class FileWriter extends Writer { + private final Writer out; + + private FileWriter(FileOutputStream out) { + this.out = new OutputStreamWriter(out); + } + + public FileWriter(FileDescriptor fd) { + this(new FileOutputStream(fd)); + } + + public FileWriter(String path) throws IOException { + this(new FileOutputStream(path)); + } + + public FileWriter(File file) throws IOException { + this(new FileOutputStream(file)); + } + + public void write(char[] b, int offset, int length) throws IOException { + out.write(b, offset, length); + } + + public void flush() throws IOException { + out.flush(); + } + + public void close() throws IOException { + out.close(); + } +} diff --git a/sgx-jvm/avian/classpath/java/io/FilenameFilter.java b/sgx-jvm/avian/classpath/java/io/FilenameFilter.java new file mode 100644 index 0000000000..8556e0ed8e --- /dev/null +++ b/sgx-jvm/avian/classpath/java/io/FilenameFilter.java @@ -0,0 +1,17 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.io; + +public interface FilenameFilter { + + boolean accept(File dir, String name); + +} diff --git a/sgx-jvm/avian/classpath/java/io/FilterInputStream.java b/sgx-jvm/avian/classpath/java/io/FilterInputStream.java new file mode 100644 index 0000000000..76119ebb24 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/io/FilterInputStream.java @@ -0,0 +1,35 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.io; + +public class FilterInputStream extends InputStream { + protected InputStream in; + + public FilterInputStream(InputStream in) { + this.in = in; + } + + public void close() throws IOException { + in.close(); + } + + public int read(byte[] b) throws IOException { + return in.read(b); + } + + public int read(byte[] b, int off, int len) throws IOException { + return in.read(b, off, len); + } + + public int read() throws IOException { + return in.read(); + } +} diff --git a/sgx-jvm/avian/classpath/java/io/FilterOutputStream.java b/sgx-jvm/avian/classpath/java/io/FilterOutputStream.java new file mode 100644 index 0000000000..ebab3b7cb2 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/io/FilterOutputStream.java @@ -0,0 +1,40 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.io; + +public class FilterOutputStream extends OutputStream { + protected OutputStream out; + + public FilterOutputStream(OutputStream out) { + this.out = out; + } + + public void close() throws IOException { + out.close(); + } + + public void flush() throws IOException { + out.flush(); + } + + public void write(byte[] b) throws IOException { + out.write(b); + } + + public void write(byte[] b, int off, int len) throws IOException { + out.write(b, off, len); + } + + public void write(int b) throws IOException { + out.write(b); + } + +} diff --git a/sgx-jvm/avian/classpath/java/io/FilterReader.java b/sgx-jvm/avian/classpath/java/io/FilterReader.java new file mode 100644 index 0000000000..13c8af3f98 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/io/FilterReader.java @@ -0,0 +1,51 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.io; + +public abstract class FilterReader extends Reader { + protected Reader in; + + protected FilterReader(Reader in) { + this.in = in; + } + + public int read() throws IOException { + return in.read(); + } + + public int read(char[] buffer, int offset, int length) throws IOException { + return in.read(buffer, offset, length); + } + + public boolean ready() throws IOException { + throw new UnsupportedOperationException(); + } + + public long skip(long n) throws IOException { + throw new UnsupportedOperationException(); + } + + public void close() throws IOException { + in.close(); + } + + public boolean markSupported() { + return in.markSupported(); + } + + public void mark(int readAheadLimit) throws IOException { + in.mark(readAheadLimit); + } + + public void reset() throws IOException { + in.reset(); + } +} diff --git a/sgx-jvm/avian/classpath/java/io/Flushable.java b/sgx-jvm/avian/classpath/java/io/Flushable.java new file mode 100644 index 0000000000..a3dd445c15 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/io/Flushable.java @@ -0,0 +1,16 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.io; + +public interface Flushable { + void flush() + throws IOException; +} diff --git a/sgx-jvm/avian/classpath/java/io/IOException.java b/sgx-jvm/avian/classpath/java/io/IOException.java new file mode 100644 index 0000000000..6dc9d189f1 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/io/IOException.java @@ -0,0 +1,29 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.io; + +public class IOException extends Exception { + public IOException(String message, Throwable cause) { + super(message, cause); + } + + public IOException(String message) { + this(message, null); + } + + public IOException(Throwable cause) { + this(null, cause); + } + + public IOException() { + this(null, null); + } +} diff --git a/sgx-jvm/avian/classpath/java/io/InputStream.java b/sgx-jvm/avian/classpath/java/io/InputStream.java new file mode 100644 index 0000000000..8bac129287 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/io/InputStream.java @@ -0,0 +1,67 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.io; + +public abstract class InputStream implements Closeable { + public abstract int read() throws IOException; + + public int read(byte[] buffer) throws IOException { + return read(buffer, 0, buffer.length); + } + + public int read(byte[] buffer, int offset, int length) throws IOException { + for (int i = 0; i < length; ++i) { + int c = read(); + if (c == -1) { + if (i == 0) { + return -1; + } else { + return i; + } + } else { + buffer[offset + i] = (byte) (c & 0xFF); + } + } + return length; + } + + public long skip(long count) throws IOException { + final long Max = 8 * 1024; + int size = (int) (count < Max ? count : Max); + byte[] buffer = new byte[size]; + long remaining = count; + int c; + while ((c = read(buffer, 0, (int) (size < remaining ? size : remaining))) + >= 0 + && remaining > 0) { + remaining -= c; + } + return count - remaining; + } + + public int available() throws IOException { + return 0; + } + + public void mark(int limit) { + // ignore + } + + public void reset() throws IOException { + throw new IOException("mark/reset not supported"); + } + + public boolean markSupported() { + return false; + } + + public void close() throws IOException { } +} diff --git a/sgx-jvm/avian/classpath/java/io/InputStreamReader.java b/sgx-jvm/avian/classpath/java/io/InputStreamReader.java new file mode 100644 index 0000000000..c7805a6f92 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/io/InputStreamReader.java @@ -0,0 +1,92 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.io; + +import avian.Utf8; + +public class InputStreamReader extends Reader { + private static final int MultibytePadding = 4; + + private final InputStream in; + + public InputStreamReader(InputStream in) { + this.in = in; + } + + public InputStreamReader(InputStream in, String encoding) + throws UnsupportedEncodingException + { + this(in); + + if (! encoding.equals("UTF-8")) { + throw new UnsupportedEncodingException(encoding); + } + } + + public int read(char[] b, int offset, int length) throws IOException { + if (length == 0) { + return 0; + } + + byte[] buffer = new byte[length + MultibytePadding]; + int bufferLength = length; + int bufferOffset = 0; + while (true) { + int c = in.read(buffer, bufferOffset, bufferLength); + + if (c <= 0) { + if (bufferOffset > 0) { + // if we've reached the end of the stream while trying to + // read a multibyte character, we still need to return any + // competely-decoded characters, plus \ufffd to indicate an + // unknown character + c = 1; + while (bufferOffset > 0) { + char[] buffer16 = Utf8.decode16(buffer, 0, bufferOffset); + + if (buffer16 != null) { + System.arraycopy(buffer16, 0, b, offset, buffer16.length); + + c = buffer16.length + 1; + break; + } else { + -- bufferOffset; + } + } + + b[offset + c - 1] = '\ufffd'; + } + + return c; + } + + bufferOffset += c; + + char[] buffer16 = Utf8.decode16(buffer, 0, bufferOffset); + + if (buffer16 != null) { + bufferOffset = 0; + + System.arraycopy(buffer16, 0, b, offset, buffer16.length); + + return buffer16.length; + } else { + // the buffer ended in an incomplete multibyte character, so + // we try to read a another byte at a time until it's complete + bufferLength = 1; + } + } + } + + public void close() throws IOException { + in.close(); + } +} diff --git a/sgx-jvm/avian/classpath/java/io/LineNumberReader.java b/sgx-jvm/avian/classpath/java/io/LineNumberReader.java new file mode 100644 index 0000000000..f8860f4987 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/io/LineNumberReader.java @@ -0,0 +1,41 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.io; + +public class LineNumberReader extends BufferedReader { + private int line; + + public LineNumberReader(Reader in, int bufferSize) { + super(in, bufferSize); + } + + public LineNumberReader(Reader in) { + super(in); + } + + public int getLineNumber() { + return line; + } + + public void setLineNumber(int v) { + line = v; + } + + public int read(char[] b, int offset, int length) throws IOException { + int c = super.read(b, offset, length); + for (int i = 0; i < c; ++i) { + if (b[i] == '\n') { + ++ line; + } + } + return c; + } +} diff --git a/sgx-jvm/avian/classpath/java/io/NotSerializableException.java b/sgx-jvm/avian/classpath/java/io/NotSerializableException.java new file mode 100644 index 0000000000..d34397817a --- /dev/null +++ b/sgx-jvm/avian/classpath/java/io/NotSerializableException.java @@ -0,0 +1,21 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.io; + +public class NotSerializableException extends ObjectStreamException { + public NotSerializableException(String message) { + super(message); + } + + public NotSerializableException() { + this(null); + } +} diff --git a/sgx-jvm/avian/classpath/java/io/ObjectInput.java b/sgx-jvm/avian/classpath/java/io/ObjectInput.java new file mode 100644 index 0000000000..640a4c16f6 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/io/ObjectInput.java @@ -0,0 +1,21 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.io; + +public interface ObjectInput { + public int available(); + public void close(); + public void read(); + public void read(byte[] b); + public void read(byte[] b, int off, int len); + public Object readObject(); + public long skip(long n); +} diff --git a/sgx-jvm/avian/classpath/java/io/ObjectInputStream.java b/sgx-jvm/avian/classpath/java/io/ObjectInputStream.java new file mode 100644 index 0000000000..66677141de --- /dev/null +++ b/sgx-jvm/avian/classpath/java/io/ObjectInputStream.java @@ -0,0 +1,443 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.io; + +import static java.io.ObjectOutputStream.STREAM_MAGIC; +import static java.io.ObjectOutputStream.STREAM_VERSION; +import static java.io.ObjectOutputStream.TC_NULL; +import static java.io.ObjectOutputStream.TC_REFERENCE; +import static java.io.ObjectOutputStream.TC_CLASSDESC; +import static java.io.ObjectOutputStream.TC_OBJECT; +import static java.io.ObjectOutputStream.TC_STRING; +import static java.io.ObjectOutputStream.TC_ARRAY; +import static java.io.ObjectOutputStream.TC_CLASS; +import static java.io.ObjectOutputStream.TC_BLOCKDATA; +import static java.io.ObjectOutputStream.TC_ENDBLOCKDATA; +import static java.io.ObjectOutputStream.TC_RESET; +import static java.io.ObjectOutputStream.TC_BLOCKDATALONG; +import static java.io.ObjectOutputStream.TC_EXCEPTION; +import static java.io.ObjectOutputStream.TC_LONGSTRING; +import static java.io.ObjectOutputStream.TC_PROXYCLASSDESC; +import static java.io.ObjectOutputStream.TC_ENUM; +import static java.io.ObjectOutputStream.SC_WRITE_METHOD; +import static java.io.ObjectOutputStream.SC_BLOCK_DATA; +import static java.io.ObjectOutputStream.SC_SERIALIZABLE; +import static java.io.ObjectOutputStream.SC_EXTERNALIZABLE; +import static java.io.ObjectOutputStream.SC_ENUM; +import static java.io.ObjectOutputStream.getReadOrWriteMethod; + +import avian.VMClass; + +import java.util.ArrayList; +import java.util.HashMap; +import java.lang.reflect.Array; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; + +public class ObjectInputStream extends InputStream implements DataInput { + private final static int HANDLE_OFFSET = 0x7e0000; + + private final InputStream in; + private final ArrayList references; + + public ObjectInputStream(InputStream in) throws IOException { + this.in = in; + short signature = (short)rawShort(); + if (signature != STREAM_MAGIC) { + throw new IOException("Unrecognized signature: 0x" + + Integer.toHexString(signature)); + } + int version = rawShort(); + if (version != STREAM_VERSION) { + throw new IOException("Unsupported version: " + version); + } + references = new ArrayList(); + } + + public int read() throws IOException { + return in.read(); + } + + private int rawByte() throws IOException { + int c = read(); + if (c < 0) { + throw new EOFException(); + } + return c; + } + + private int rawShort() throws IOException { + return (rawByte() << 8) | rawByte(); + } + + private int rawInt() throws IOException { + return (rawShort() << 16) | rawShort(); + } + + private long rawLong() throws IOException { + return ((rawInt() & 0xffffffffl) << 32) | rawInt(); + } + + private String rawString() throws IOException { + int length = rawShort(); + byte[] array = new byte[length]; + readFully(array); + return new String(array); + } + + public int read(byte[] b, int offset, int length) throws IOException { + return in.read(b, offset, length); + } + + public void readFully(byte[] b) throws IOException { + readFully(b, 0, b.length); + } + + public void readFully(byte[] b, int offset, int length) throws IOException { + while (length > 0) { + int count = read(b, offset, length); + if (count < 0) { + throw new EOFException("Reached EOF " + length + " bytes too early"); + } + offset += count; + length -= count; + } + } + + public String readLine() throws IOException { + int c = read(); + if (c < 0) { + return null; + } else if (c == '\n') { + return ""; + } + StringBuilder builder = new StringBuilder(); + for (;;) { + builder.append((char)c); + c = read(); + if (c < 0 || c == '\n') { + return builder.toString(); + } + } + } + + public void close() throws IOException { + in.close(); + } + + private int remainingBlockData; + + private int rawBlockDataByte() throws IOException { + while (remainingBlockData <= 0) { + int b = rawByte(); + if (b == TC_BLOCKDATA) { + remainingBlockData = rawByte(); + } else { + throw new UnsupportedOperationException("Unknown token: 0x" + + Integer.toHexString(b)); + } + } + --remainingBlockData; + return rawByte(); + } + + private int rawBlockDataShort() throws IOException { + return (rawBlockDataByte() << 8) | rawBlockDataByte(); + } + + private int rawBlockDataInt() throws IOException { + return (rawBlockDataShort() << 16) | rawBlockDataShort(); + } + + private long rawBlockDataLong() throws IOException { + return ((rawBlockDataInt() & 0xffffffffl) << 32) | rawBlockDataInt(); + } + + public boolean readBoolean() throws IOException { + return rawBlockDataByte() != 0; + } + + public byte readByte() throws IOException { + return (byte)rawBlockDataByte(); + } + + public char readChar() throws IOException { + return (char)rawBlockDataShort(); + } + + public short readShort() throws IOException { + return (short)rawBlockDataShort(); + } + + public int readInt() throws IOException { + return rawBlockDataInt(); + } + + public long readLong() throws IOException { + return rawBlockDataLong(); + } + + public float readFloat() throws IOException { + return Float.intBitsToFloat(rawBlockDataInt()); + } + + public double readDouble() throws IOException { + return Double.longBitsToDouble(rawBlockDataLong()); + } + + public int readUnsignedByte() throws IOException { + return rawBlockDataByte(); + } + + public int readUnsignedShort() throws IOException { + return rawBlockDataShort(); + } + + public String readUTF() throws IOException { + int length = rawBlockDataShort(); + if (remainingBlockData < length) { + throw new IOException("Short block data: " + + remainingBlockData + " < " + length); + } + byte[] bytes = new byte[length]; + readFully(bytes); + remainingBlockData -= length; + return new String(bytes, "UTF-8"); + } + + public int skipBytes(int count) throws IOException { + int i = 0; + while (i < count) { + if (read() < 0) { + return i; + } + ++i; + } + return count; + } + + private static Class charToPrimitiveType(int c) { + if (c == 'B') { + return Byte.TYPE; + } else if (c == 'C') { + return Character.TYPE; + } else if (c == 'D') { + return Double.TYPE; + } else if (c == 'F') { + return Float.TYPE; + } else if (c == 'I') { + return Integer.TYPE; + } else if (c == 'J') { + return Long.TYPE; + } else if (c == 'S') { + return Short.TYPE; + } else if (c == 'Z') { + return Boolean.TYPE; + } + throw new RuntimeException("Unhandled char: " + (char)c); + } + + private void expectToken(int token) throws IOException { + int c = rawByte(); + if (c != token) { + throw new UnsupportedOperationException("Unexpected token: 0x" + + Integer.toHexString(c)); + } + } + + private void field(Field field, Object o) + throws IOException, IllegalArgumentException, IllegalAccessException, + ClassNotFoundException + { + Class type = field.getType(); + if (!type.isPrimitive()) { + field.set(o, readObject()); + } else { + if (type == Byte.TYPE) { + field.setByte(o, (byte)rawByte()); + } else if (type == Character.TYPE) { + field.setChar(o, (char)rawShort()); + } else if (type == Double.TYPE) { + field.setDouble(o, Double.longBitsToDouble(rawLong())); + } else if (type == Float.TYPE) { + field.setFloat(o, Float.intBitsToFloat(rawInt())); + } else if (type == Integer.TYPE) { + field.setInt(o, rawInt()); + } else if (type == Long.TYPE) { + field.setLong(o, rawLong()); + } else if (type == Short.TYPE) { + field.setShort(o, (short)rawShort()); + } else if (type == Boolean.TYPE) { + field.setBoolean(o, rawByte() != 0); + } else { + throw new IOException("Unhandled type: " + type); + } + } + } + + public Object readObject() throws IOException, ClassNotFoundException { + int c = rawByte(); + if (c == TC_NULL) { + return null; + } + if (c == TC_STRING) { + int length = rawShort(); + byte[] bytes = new byte[length]; + readFully(bytes); + String s = new String(bytes, "UTF-8"); + references.add(s); + return s; + } + if (c == TC_REFERENCE) { + int handle = rawInt(); + return references.get(handle - HANDLE_OFFSET); + } + if (c != TC_OBJECT) { + throw new IOException("Unexpected token: 0x" + + Integer.toHexString(c)); + } + + // class desc + c = rawByte(); + ClassDesc classDesc; + if (c == TC_REFERENCE) { + int handle = rawInt() - HANDLE_OFFSET; + classDesc = (ClassDesc)references.get(handle); + } else if (c == TC_CLASSDESC) { + classDesc = classDesc(); + } else { + throw new UnsupportedOperationException("Unexpected token: 0x" + + Integer.toHexString(c)); + } + + try { + Object o = makeInstance(classDesc.clazz.vmClass); + references.add(o); + + do { + Object o1 = classDesc.clazz.cast(o); + boolean customized = (classDesc.flags & SC_WRITE_METHOD) != 0; + Method readMethod = customized ? + getReadOrWriteMethod(o, "readObject") : null; + if (readMethod == null) { + if (customized) { + throw new IOException("Could not find required readObject method " + + "in " + classDesc.clazz); + } + defaultReadObject(o, classDesc.fields); + } else { + current = o1; + currentFields = classDesc.fields; + readMethod.invoke(o, this); + current = null; + currentFields = null; + expectToken(TC_ENDBLOCKDATA); + } + } while ((classDesc = classDesc.superClassDesc) != null); + + return o; + } catch (IOException e) { + throw e; + } catch (Exception e) { + throw new IOException(e); + } + } + + private static class ClassDesc { + Class clazz; + int flags; + Field[] fields; + ClassDesc superClassDesc; + } + + private ClassDesc classDesc() throws ClassNotFoundException, IOException { + ClassDesc result = new ClassDesc(); + String className = rawString(); + ClassLoader loader = Thread.currentThread().getContextClassLoader(); + result.clazz = loader.loadClass(className); + long serialVersionUID = rawLong(); + try { + Field field = result.clazz.getField("serialVersionUID"); + long expected = field.getLong(null); + if (expected != serialVersionUID) { + throw new IOException("Incompatible serial version UID: 0x" + + Long.toHexString(serialVersionUID) + " != 0x" + + Long.toHexString(expected)); + } + } catch (Exception ignored) { } + references.add(result); + + result.flags = rawByte(); + if ((result.flags & ~(SC_SERIALIZABLE | SC_WRITE_METHOD)) != 0) { + throw new UnsupportedOperationException("Cannot handle flags: 0x" + + Integer.toHexString(result.flags)); + } + + int fieldCount = rawShort(); + result.fields = new Field[fieldCount]; + for (int i = 0; i < result.fields.length; i++) { + int typeChar = rawByte(); + String fieldName = rawString(); + try { + result.fields[i] = result.clazz.getDeclaredField(fieldName); + } catch (Exception e) { + throw new IOException(e); + } + Class type; + if (typeChar == '[' || typeChar == 'L') { + String typeName = (String)readObject(); + if (typeName.startsWith("L") && typeName.endsWith(";")) { + typeName = typeName.substring(1, typeName.length() - 1) + .replace('/', '.'); + } + type = loader.loadClass(typeName); + } else { + type = charToPrimitiveType(typeChar); + } + if (result.fields[i].getType() != type) { + throw new IOException("Unexpected type of field " + fieldName + + ": expected " + result.fields[i].getType() + " but got " + type); + } + } + expectToken(TC_ENDBLOCKDATA); + int c = rawByte(); + if (c == TC_CLASSDESC) { + result.superClassDesc = classDesc(); + } else if (c != TC_NULL) { + throw new UnsupportedOperationException("Unexpected token: 0x" + + Integer.toHexString(c)); + } + + return result; + } + + private Object current; + private Field[] currentFields; + + public void defaultReadObject() throws IOException { + defaultReadObject(current, currentFields); + } + + private void defaultReadObject(Object o, Field[] fields) throws IOException { + try { + for (Field field : fields) { + field(field, o); + } + } catch (IOException e) { + throw e; + } catch (Exception e) { + throw new IOException(e); + } + } + + private static native Object makeInstance(VMClass c); +} diff --git a/sgx-jvm/avian/classpath/java/io/ObjectOutput.java b/sgx-jvm/avian/classpath/java/io/ObjectOutput.java new file mode 100644 index 0000000000..a93eec2bc4 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/io/ObjectOutput.java @@ -0,0 +1,20 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.io; + +public interface ObjectOutput { + public void close(); + public void flush(); + public void write(byte[] b); + public void write(byte[] b, int off, int len); + public void write(int b); + public void writeObject(Object obj); +} diff --git a/sgx-jvm/avian/classpath/java/io/ObjectOutputStream.java b/sgx-jvm/avian/classpath/java/io/ObjectOutputStream.java new file mode 100644 index 0000000000..0ed12a2b76 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/io/ObjectOutputStream.java @@ -0,0 +1,337 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.io; + +import java.util.ArrayList; +import java.lang.reflect.Array; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; + +public class ObjectOutputStream extends OutputStream implements DataOutput { + final static short STREAM_MAGIC = (short)0xaced; + final static short STREAM_VERSION = 5; + final static byte TC_NULL = (byte)0x70; + final static byte TC_REFERENCE = (byte)0x71; + final static byte TC_CLASSDESC = (byte)0x72; + final static byte TC_OBJECT = (byte)0x73; + final static byte TC_STRING = (byte)0x74; + final static byte TC_ARRAY = (byte)0x75; + final static byte TC_CLASS = (byte)0x76; + final static byte TC_BLOCKDATA = (byte)0x77; + final static byte TC_ENDBLOCKDATA = (byte)0x78; + final static byte TC_RESET = (byte)0x79; + final static byte TC_BLOCKDATALONG = (byte)0x7a; + final static byte TC_EXCEPTION = (byte)0x7b; + final static byte TC_LONGSTRING = (byte)0x7c; + final static byte TC_PROXYCLASSDESC = (byte)0x7d; + final static byte TC_ENUM = (byte)0x7e; + final static byte SC_WRITE_METHOD = 0x01; //if SC_SERIALIZABLE + final static byte SC_BLOCK_DATA = 0x08; //if SC_EXTERNALIZABLE + final static byte SC_SERIALIZABLE = 0x02; + final static byte SC_EXTERNALIZABLE = 0x04; + final static byte SC_ENUM = 0x10; + + private final OutputStream out; + + public ObjectOutputStream(OutputStream out) throws IOException { + this.out = out; + rawShort(STREAM_MAGIC); + rawShort(STREAM_VERSION); + } + + public void write(int c) throws IOException { + out.write(c); + } + + public void write(byte[] b, int offset, int length) throws IOException { + out.write(b, offset, length); + } + + public void flush() throws IOException { + out.flush(); + } + + public void close() throws IOException { + out.close(); + } + + private void rawByte(int v) throws IOException { + out.write((byte)(v & 0xff)); + } + + private void rawShort(int v) throws IOException { + rawByte(v >> 8); + rawByte(v); + } + + private void rawInt(int v) throws IOException { + rawShort(v >> 16); + rawShort(v); + } + + private void rawLong(long v) throws IOException { + rawInt((int)(v >> 32)); + rawInt((int)(v & 0xffffffffl)); + } + + private void blockData(int... bytes) throws IOException { + blockData(bytes, null, null); + } + + private void blockData(int[] bytes, byte[] bytes2, char[] chars) throws IOException { + int count = (bytes == null ? 0 : bytes.length) + + (bytes2 == null ? 0 : bytes2.length) + + (chars == null ? 0 : chars.length * 2); + if (count < 0x100) { + rawByte(TC_BLOCKDATA); + rawByte(count); + } else { + rawByte(TC_BLOCKDATALONG); + rawInt(count); + } + if (bytes != null) { + for (int b : bytes) { + rawByte(b); + } + } + if (bytes2 != null) { + for (byte b : bytes2) { + rawByte(b & 0xff); + } + } + if (chars != null) { + for (char c : chars) { + rawShort((short)c); + } + } + } + + public void writeBoolean(boolean v) throws IOException { + blockData(v ? 1 : 0); + } + + public void writeByte(int v) throws IOException { + blockData(v); + } + + public void writeShort(int v) throws IOException { + blockData(v >> 8, v); + } + + public void writeChar(int v) throws IOException { + blockData(v >> 8, v); + } + + public void writeInt(int v) throws IOException { + blockData(v >> 24, v >> 16, v >> 8, v); + } + + public void writeLong(long v) throws IOException { + int u = (int)(v >> 32), l = (int)(v & 0xffffffff); + blockData(u >> 24, u >> 16, u >> 8, u, l >> 24, l >> 16, l >> 8, l); + } + + public void writeFloat(float v) throws IOException { + writeInt(Float.floatToIntBits(v)); + } + + public void writeDouble(double v) throws IOException { + writeLong(Double.doubleToLongBits(v)); + } + + public void writeBytes(String s) throws IOException { + blockData(null, s.getBytes(), null); + } + + public void writeChars(String s) throws IOException { + blockData(null, null, s.toCharArray()); + } + + public void writeUTF(String s) throws IOException { + byte[] bytes = s.getBytes(); + int length = bytes.length; + blockData(new int[] { length >> 8, length }, bytes, null); + } + + private int classHandle; + + private void string(String s) throws IOException { + int length = s.length(); + rawShort(length); + for (byte b : s.getBytes()) { + rawByte(b); + } + } + + private static char primitiveTypeChar(Class type) { + if (type == Byte.TYPE) { + return 'B'; + } else if (type == Character.TYPE) { + return 'C'; + } else if (type == Double.TYPE) { + return 'D'; + } else if (type == Float.TYPE) { + return 'F'; + } else if (type == Integer.TYPE) { + return 'I'; + } else if (type == Long.TYPE) { + return 'J'; + } else if (type == Short.TYPE) { + return 'S'; + } else if (type == Boolean.TYPE) { + return 'Z'; + } + throw new RuntimeException("Unhandled primitive type: " + type); + } + + private void classDesc(Class clazz, int scFlags) throws IOException { + rawByte(TC_CLASSDESC); + + // class name + string(clazz.getName()); + + // serial version UID + long serialVersionUID = 1l; + try { + Field field = clazz.getField("serialVersionUID"); + serialVersionUID = field.getLong(null); + } catch (Exception ignored) {} + rawLong(serialVersionUID); + + // handle + rawByte(SC_SERIALIZABLE | scFlags); + + Field[] fields = getFields(clazz); + rawShort(fields.length); + for (Field field : fields) { + Class fieldType = field.getType(); + if (fieldType.isPrimitive()) { + rawByte(primitiveTypeChar(fieldType)); + string(field.getName()); + } else { + rawByte(fieldType.isArray() ? '[' : 'L'); + string(field.getName()); + rawByte(TC_STRING); + string("L" + fieldType.getName().replace('.', '/') + ";"); + } + } + rawByte(TC_ENDBLOCKDATA); // TODO: write annotation + rawByte(TC_NULL); // super class desc + } + + private void field(Object o, Field field) throws IOException { + try { + field.setAccessible(true); + Class type = field.getType(); + if (!type.isPrimitive()) { + writeObject(field.get(o)); + } else if (type == Byte.TYPE) { + rawByte(field.getByte(o)); + } else if (type == Character.TYPE) { + char c = field.getChar(o); + rawShort((short)c); + } else if (type == Double.TYPE) { + double d = field.getDouble(o); + rawLong(Double.doubleToLongBits(d)); + } else if (type == Float.TYPE) { + float f = field.getFloat(o); + rawInt(Float.floatToIntBits(f)); + } else if (type == Integer.TYPE) { + int i = field.getInt(o); + rawInt(i); + } else if (type == Long.TYPE) { + long l = field.getLong(o); + rawLong(l); + } else if (type == Short.TYPE) { + short s = field.getShort(o); + rawShort(s); + } else if (type == Boolean.TYPE) { + boolean b = field.getBoolean(o); + rawByte(b ? 1 : 0); + } else { + throw new UnsupportedOperationException("Field '" + field.getName() + + "' has unsupported type: " + type); + } + } catch (IOException e) { + throw e; + } catch (Exception e) { + throw new IOException(e); + } + } + + private static Field[] getFields(Class clazz) { + ArrayList list = new ArrayList(); + Field[] fields = clazz.getDeclaredFields(); + for (Field field : fields) { + if (0 == (field.getModifiers() & + (Modifier.STATIC | Modifier.TRANSIENT))) { + list.add(field); + } + } + return list.toArray(new Field[list.size()]); + } + + public void writeObject(Object o) throws IOException { + if (o == null) { + rawByte(TC_NULL); + return; + } + if (o instanceof String) { + byte[] bytes = ((String)o).getBytes("UTF-8"); + rawByte(TC_STRING); + rawShort(bytes.length); + write(bytes); + return; + } + rawByte(TC_OBJECT); + Method writeObject = getReadOrWriteMethod(o, "writeObject"); + if (writeObject == null) { + classDesc(o.getClass(), 0); + defaultWriteObject(o); + } else try { + classDesc(o.getClass(), SC_WRITE_METHOD); + current = o; + writeObject.invoke(o, this); + current = null; + rawByte(TC_ENDBLOCKDATA); + } catch (Exception e) { + throw new IOException(e); + } + } + + static Method getReadOrWriteMethod(Object o, String methodName) { + try { + Method method = o.getClass().getDeclaredMethod(methodName, + new Class[] { methodName.startsWith("write") ? + ObjectOutputStream.class : ObjectInputStream.class }); + method.setAccessible(true); + int modifiers = method.getModifiers(); + if ((modifiers & Modifier.STATIC) == 0 || + (modifiers & Modifier.PRIVATE) != 0) { + return method; + } + } catch (NoSuchMethodException ignored) { } + return null; + } + + private Object current; + + public void defaultWriteObject() throws IOException { + defaultWriteObject(current); + } + + private void defaultWriteObject(Object o) throws IOException { + for (Field field : getFields(o.getClass())) { + field(o, field); + } + } +} diff --git a/sgx-jvm/avian/classpath/java/io/ObjectStreamException.java b/sgx-jvm/avian/classpath/java/io/ObjectStreamException.java new file mode 100644 index 0000000000..2e78ce6289 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/io/ObjectStreamException.java @@ -0,0 +1,21 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.io; + +public class ObjectStreamException extends IOException { + public ObjectStreamException(String message) { + super(message); + } + + public ObjectStreamException() { + this(null); + } +} diff --git a/sgx-jvm/avian/classpath/java/io/OutputStream.java b/sgx-jvm/avian/classpath/java/io/OutputStream.java new file mode 100644 index 0000000000..b81d0b71d0 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/io/OutputStream.java @@ -0,0 +1,29 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.io; + +public abstract class OutputStream implements Closeable, Flushable { + public abstract void write(int c) throws IOException; + + public void write(byte[] buffer) throws IOException { + write(buffer, 0, buffer.length); + } + + public void write(byte[] buffer, int offset, int length) throws IOException { + for (int i = 0; i < length; ++i) { + write(buffer[offset + i]); + } + } + + public void flush() throws IOException { } + + public void close() throws IOException { } +} diff --git a/sgx-jvm/avian/classpath/java/io/OutputStreamWriter.java b/sgx-jvm/avian/classpath/java/io/OutputStreamWriter.java new file mode 100644 index 0000000000..2a183d31d2 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/io/OutputStreamWriter.java @@ -0,0 +1,33 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.io; + +import avian.Utf8; + +public class OutputStreamWriter extends Writer { + private final OutputStream out; + + public OutputStreamWriter(OutputStream out) { + this.out = out; + } + + public void write(char[] b, int offset, int length) throws IOException { + out.write(Utf8.encode(b, offset, length)); + } + + public void flush() throws IOException { + out.flush(); + } + + public void close() throws IOException { + out.close(); + } +} diff --git a/sgx-jvm/avian/classpath/java/io/PrintStream.java b/sgx-jvm/avian/classpath/java/io/PrintStream.java new file mode 100644 index 0000000000..eda3feac64 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/io/PrintStream.java @@ -0,0 +1,170 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.io; + +public class PrintStream extends OutputStream { + private final OutputStream out; + private final boolean autoFlush; + + private static class Static { + private static final byte[] newline + = System.getProperty("line.separator").getBytes(); + } + + public PrintStream(OutputStream out, boolean autoFlush) { + this.out = out; + this.autoFlush = autoFlush; + } + + public PrintStream(OutputStream out, boolean autoFlush, String encoding) + throws UnsupportedEncodingException + { + this.out = out; + this.autoFlush = autoFlush; + + if (! (encoding.equals("UTF-8") || encoding.equals("ISO-8859-1"))) { + throw new UnsupportedEncodingException(encoding); + } + } + + public PrintStream(OutputStream out) { + this(out, false); + } + + public synchronized void print(String s) { + try { + out.write(s.getBytes()); + if (autoFlush) flush(); + } catch (IOException e) { } + } + + public void print(Object o) { + print(String.valueOf(o)); + } + + public void print(boolean v) { + print(String.valueOf(v)); + } + + public void print(char c) { + print(String.valueOf(c)); + } + + public void print(int v) { + print(String.valueOf(v)); + } + + public void print(long v) { + print(String.valueOf(v)); + } + + public void print(float v) { + print(String.valueOf(v)); + } + + public void print(double v) { + print(String.valueOf(v)); + } + + public void print(char[] s) { + print(String.valueOf(s)); + } + + public synchronized PrintStream printf(java.util.Locale locale, String format, Object... args) { + // should this be cached in an instance variable?? + final java.util.Formatter formatter = new java.util.Formatter(this); + formatter.format(locale, format, args); + return this; + } + + public synchronized PrintStream printf(String format, Object... args) { + final java.util.Formatter formatter = new java.util.Formatter(this); + formatter.format(format, args); + return this; + } + + public PrintStream format(String format, Object... args) { + return printf(format, args); + } + + public PrintStream format(java.util.Locale locale, String format, Object... args) { + return printf(locale, format, args); + } + + public synchronized void println(String s) { + try { + out.write(s.getBytes()); + out.write(Static.newline); + if (autoFlush) flush(); + } catch (IOException e) { } + } + + public synchronized void println() { + try { + out.write(Static.newline); + if (autoFlush) flush(); + } catch (IOException e) { } + } + + public void println(Object o) { + println(String.valueOf(o)); + } + + public void println(boolean v) { + println(String.valueOf(v)); + } + + public void println(char c) { + println(String.valueOf(c)); + } + + public void println(int v) { + println(String.valueOf(v)); + } + + public void println(long v) { + println(String.valueOf(v)); + } + + public void println(float v) { + println(String.valueOf(v)); + } + + public void println(double v) { + println(String.valueOf(v)); + } + + public void println(char[] s) { + println(String.valueOf(s)); + } + + public void write(int c) throws IOException { + out.write(c); + if (autoFlush && c == '\n') flush(); + } + + public void write(byte[] buffer, int offset, int length) throws IOException { + out.write(buffer, offset, length); + if (autoFlush) flush(); + } + + public void flush() { + try { + out.flush(); + } catch (IOException e) { } + } + + public void close() { + try { + out.close(); + } catch (IOException e) { } + } +} diff --git a/sgx-jvm/avian/classpath/java/io/PrintWriter.java b/sgx-jvm/avian/classpath/java/io/PrintWriter.java new file mode 100644 index 0000000000..604368d2b5 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/io/PrintWriter.java @@ -0,0 +1,90 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.io; + +public class PrintWriter extends Writer { + private static final char[] newline + = System.getProperty("line.separator").toCharArray(); + + private final Writer out; + private final boolean autoFlush; + + public PrintWriter(Writer out, boolean autoFlush) { + this.out = out; + this.autoFlush = autoFlush; + } + + public PrintWriter(Writer out) { + this(out, false); + } + + public PrintWriter(OutputStream out, boolean autoFlush) { + this(new OutputStreamWriter(out), autoFlush); + } + + public PrintWriter(OutputStream out) { + this(out, false); + } + + public synchronized void print(String s) { + try { + out.write(s.toCharArray()); + } catch (IOException e) { } + } + + public void print(Object o) { + print(o.toString()); + } + + public void print(char c) { + print(String.valueOf(c)); + } + + public synchronized void println(String s) { + try { + out.write(s.toCharArray()); + out.write(newline); + if (autoFlush) flush(); + } catch (IOException e) { } + } + + public synchronized void println() { + try { + out.write(newline); + if (autoFlush) flush(); + } catch (IOException e) { } + } + + public void println(Object o) { + println(o.toString()); + } + + public void println(char c) { + println(String.valueOf(c)); + } + + public void write(char[] buffer, int offset, int length) throws IOException { + out.write(buffer, offset, length); + if (autoFlush) flush(); + } + + public void flush() { + try { + out.flush(); + } catch (IOException e) { } + } + + public void close() { + try { + out.close(); + } catch (IOException e) { } + } +} diff --git a/sgx-jvm/avian/classpath/java/io/PushbackReader.java b/sgx-jvm/avian/classpath/java/io/PushbackReader.java new file mode 100644 index 0000000000..49acf98357 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/io/PushbackReader.java @@ -0,0 +1,74 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.io; + +public class PushbackReader extends Reader { + private final Reader in; + private char savedChar; + private boolean hasSavedChar; + + public PushbackReader(Reader in, int bufferSize) { + if (bufferSize > 1) { + throw new IllegalArgumentException(bufferSize + " > 1"); + } + this.in = in; + this.hasSavedChar = false; + } + + public PushbackReader(Reader in) { + this(in, 1); + } + + public int read(char[] b, int offset, int length) throws IOException { + int count = 0; + if (hasSavedChar && length > 0) { + length--; + b[offset++] = savedChar; + hasSavedChar = false; + count = 1; + } + if (length > 0) { + int c = in.read(b, offset, length); + if (c == -1) { + if (count == 0) { + count = -1; + } + } else { + count += c; + } + } + + return count; + } + + public void unread(char[] b, int offset, int length) throws IOException { + if (length != 1) { + throw new IOException("Can only push back 1 char, not " + length); + } else if (hasSavedChar) { + throw new IOException("Already have a saved char"); + } else { + hasSavedChar = true; + savedChar = b[offset]; + } + } + + public void unread(char[] b) throws IOException { + unread(b, 0, b.length); + } + + public void unread(int c) throws IOException { + unread(new char[] { (char) c }); + } + + public void close() throws IOException { + in.close(); + } +} diff --git a/sgx-jvm/avian/classpath/java/io/RandomAccessFile.java b/sgx-jvm/avian/classpath/java/io/RandomAccessFile.java new file mode 100644 index 0000000000..4739b9ea78 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/io/RandomAccessFile.java @@ -0,0 +1,282 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.io; + +import java.lang.IllegalArgumentException; +import java.nio.ByteBuffer; +import java.nio.channels.FileChannel; + +public class RandomAccessFile implements DataInput, Closeable { + + private long peer; + private File file; + private long position = 0; + private long length; + private boolean allowWrite; + + public RandomAccessFile(String name, String mode) + throws FileNotFoundException + { + this(new File(name), mode); + } + + public RandomAccessFile(File file, String mode) + throws FileNotFoundException + { + if (file == null) throw new NullPointerException(); + if (mode.equals("rw")) allowWrite = true; + else if (! mode.equals("r")) throw new IllegalArgumentException(); + this.file = file; + open(); + } + + private void open() throws FileNotFoundException { + long[] result = new long[2]; + open(file.getPath(), allowWrite, result); + peer = result[0]; + length = result[1]; + } + + private static native void open(String name, boolean allowWrite, long[] result) + throws FileNotFoundException; + + private void refresh() throws IOException { + if (file.length() != length) { + close(); + open(); + } + } + + public long length() throws IOException { + refresh(); + return length; + } + + public long getFilePointer() throws IOException { + return position; + } + + public void seek(long position) throws IOException { + if (position < 0 || (!allowWrite && position > length())) throw new IOException(); + + this.position = position; + } + + public int skipBytes(int count) throws IOException { + if (position + count > length()) throw new IOException(); + this.position = position + count; + return count; + } + + public int read(byte b[], int off, int len) throws IOException { + if(b == null) + throw new IllegalArgumentException(); + if (peer == 0) + throw new IOException(); + if(len == 0) + return 0; + if (position + len > this.length) + throw new EOFException(); + if (off < 0 || off + len > b.length) + throw new ArrayIndexOutOfBoundsException(); + int bytesRead = readBytes(peer, position, b, off, len); + position += bytesRead; + return bytesRead; + } + + public int read(byte b[]) throws IOException { + if(b == null) + throw new IllegalArgumentException(); + if (peer == 0) + throw new IOException(); + if(b.length == 0) + return 0; + if (position + b.length > this.length) + throw new EOFException(); + int bytesRead = readBytes(peer, position, b, 0, b.length); + position += bytesRead; + return bytesRead; + } + + public void readFully(byte b[], int off, int len) throws IOException { + if (b == null) + throw new IllegalArgumentException(); + if (peer == 0) + throw new IOException(); + if(len == 0) + return; + if (position + len > this.length) + throw new EOFException(); + if (off < 0 || off + len > b.length) + throw new ArrayIndexOutOfBoundsException(); + int n = 0; + do { + int count = readBytes(peer, position, b, off + n, len - n); + position += count; + if (count == 0) + throw new EOFException(); + n += count; + } while (n < len); + } + + public void readFully(byte b[]) throws IOException { + readFully(b, 0, b.length); + } + + private static native int readBytes(long peer, long position, byte[] buffer, + int offset, int length); + + public boolean readBoolean() throws IOException { + return readByte() != 0; + } + + public int read() throws IOException { + try { + return readByte() & 0xff; + } catch (final EOFException e) { + return -1; + } + } + + public byte readByte() throws IOException { + final byte[] buffer = new byte[1]; + readFully(buffer); + return buffer[0]; + } + + public short readShort() throws IOException { + final byte[] buffer = new byte[2]; + readFully(buffer); + return (short)((buffer[0] << 8) | buffer[1]); + } + + public int readInt() throws IOException { + byte[] buf = new byte[4]; + readFully(buf); + return ((buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3]); + } + + public float readFloat() throws IOException { + return Float.floatToIntBits(readInt()); + } + + public double readDouble() throws IOException { + return Double.doubleToLongBits(readLong()); + } + + public long readLong() throws IOException { + return ((readInt() & 0xffffffffl) << 32) | (readInt() & 0xffffffffl); + } + + public char readChar() throws IOException { + return (char)readShort(); + } + + public int readUnsignedByte() throws IOException { + return readByte() & 0xff; + } + + public int readUnsignedShort() throws IOException { + return readShort() & 0xffff; + } + + public String readUTF() throws IOException { + int length = readUnsignedShort(); + byte[] bytes = new byte[length]; + readFully(bytes); + return new String(bytes, "UTF-8"); + } + + @Deprecated + public String readLine() throws IOException { + int c = read(); + if (c < 0) { + return null; + } else if (c == '\n') { + return ""; + } + StringBuilder builder = new StringBuilder(); + for (;;) { + builder.append((char)c); + c = read(); + if (c < 0 || c == '\n') { + return builder.toString(); + } + } + } + + public void write(int b) throws IOException { + int count = writeBytes(peer, position, new byte[] { (byte)b }, 0, 1); + if (count > 0) position += count; + } + + private static native int writeBytes(long peer, long position, byte[] buffer, + int offset, int length); + + public void close() throws IOException { + if (peer != 0) { + close(peer); + peer = 0; + } + } + + private static native void close(long peer); + + public FileChannel getChannel() { + return new FileChannel() { + public void close() { + if (peer != 0) RandomAccessFile.close(peer); + } + + public boolean isOpen() { + return peer != 0; + } + + public int read(ByteBuffer dst, long position) throws IOException { + if (!dst.hasArray()) throw new IOException("Cannot handle " + dst.getClass()); + // TODO: this needs to be synchronized on the Buffer, no? + byte[] array = dst.array(); + return readBytes(peer, position, array, dst.position(), dst.remaining()); + } + + public int read(ByteBuffer dst) throws IOException { + int count = read(dst, position); + if (count > 0) position += count; + return count; + } + + public int write(ByteBuffer src, long position) throws IOException { + if (!src.hasArray()) throw new IOException("Cannot handle " + src.getClass()); + byte[] array = src.array(); + return writeBytes(peer, position, array, src.position(), src.remaining()); + } + + public int write(ByteBuffer src) throws IOException { + int count = write(src, position); + if (count > 0) position += count; + return count; + } + + public long position() throws IOException { + return getFilePointer(); + } + + public FileChannel position(long position) throws IOException { + seek(position); + return this; + } + + public long size() throws IOException { + return length(); + } + }; + } +} diff --git a/sgx-jvm/avian/classpath/java/io/Reader.java b/sgx-jvm/avian/classpath/java/io/Reader.java new file mode 100644 index 0000000000..bba2be4c13 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/io/Reader.java @@ -0,0 +1,58 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.io; + +import java.nio.CharBuffer; + +public abstract class Reader implements Closeable, Readable { + public int read(CharBuffer buffer) throws IOException { + int c = read(buffer.array(), + buffer.arrayOffset() + buffer.position(), + buffer.remaining()); + + if (c > 0) { + buffer.position(buffer.position() + c); + } + + return c; + } + + public int read() throws IOException { + char[] buffer = new char[1]; + int c = read(buffer); + if (c <= 0) { + return -1; + } else { + return (int) buffer[0]; + } + } + + public int read(char[] buffer) throws IOException { + return read(buffer, 0, buffer.length); + } + + public abstract int read(char[] buffer, int offset, int length) + throws IOException; + + public boolean markSupported() { + return false; + } + + public void mark(int readAheadLimit) throws IOException { + throw new IOException("mark not supported"); + } + + public void reset() throws IOException { + throw new IOException("reset not supported"); + } + + public abstract void close() throws IOException; +} diff --git a/sgx-jvm/avian/classpath/java/io/Serializable.java b/sgx-jvm/avian/classpath/java/io/Serializable.java new file mode 100644 index 0000000000..11978a051c --- /dev/null +++ b/sgx-jvm/avian/classpath/java/io/Serializable.java @@ -0,0 +1,13 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.io; + +public interface Serializable { } diff --git a/sgx-jvm/avian/classpath/java/io/StreamCorruptedException.java b/sgx-jvm/avian/classpath/java/io/StreamCorruptedException.java new file mode 100644 index 0000000000..06e56f9d62 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/io/StreamCorruptedException.java @@ -0,0 +1,21 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.io; + +public class StreamCorruptedException extends IOException { + public StreamCorruptedException(String message) { + super(message); + } + + public StreamCorruptedException() { + this(null); + } +} diff --git a/sgx-jvm/avian/classpath/java/io/StringReader.java b/sgx-jvm/avian/classpath/java/io/StringReader.java new file mode 100644 index 0000000000..f8f863c35e --- /dev/null +++ b/sgx-jvm/avian/classpath/java/io/StringReader.java @@ -0,0 +1,34 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.io; + +public class StringReader extends Reader { + private final String in; + private int position = 0; + + public StringReader(String in) { + this.in = in; + } + + public int read(char[] b, int offset, int length) throws IOException { + if (length > in.length() - position) { + length = in.length() - position; + if (length <= 0) { + return -1; + } + } + in.getChars(position, position+length, b, offset); + position += length; + return length; + } + + public void close() throws IOException { } +} diff --git a/sgx-jvm/avian/classpath/java/io/StringWriter.java b/sgx-jvm/avian/classpath/java/io/StringWriter.java new file mode 100644 index 0000000000..98d111f077 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/io/StringWriter.java @@ -0,0 +1,31 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.io; + +public class StringWriter extends Writer { + private final StringBuffer out = new StringBuffer(); + + public void write(char[] b, int offset, int length) throws IOException { + out.append(b, offset, length); + } + + public String toString() { + return out.toString(); + } + + public void flush() throws IOException { } + + public void close() throws IOException { } + + public StringBuffer getBuffer() { + return out; + } +} diff --git a/sgx-jvm/avian/classpath/java/io/UTFDataFormatException.java b/sgx-jvm/avian/classpath/java/io/UTFDataFormatException.java new file mode 100644 index 0000000000..7938bbf6b0 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/io/UTFDataFormatException.java @@ -0,0 +1,21 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.io; + +public class UTFDataFormatException extends IOException { + public UTFDataFormatException(String s) { + super(s); + } + + public UTFDataFormatException() { + super(); + } +} diff --git a/sgx-jvm/avian/classpath/java/io/UnsupportedEncodingException.java b/sgx-jvm/avian/classpath/java/io/UnsupportedEncodingException.java new file mode 100644 index 0000000000..80e8efeff3 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/io/UnsupportedEncodingException.java @@ -0,0 +1,21 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.io; + +public class UnsupportedEncodingException extends IOException { + public UnsupportedEncodingException(String message) { + super(message); + } + + public UnsupportedEncodingException() { + this(null); + } +} diff --git a/sgx-jvm/avian/classpath/java/io/Writer.java b/sgx-jvm/avian/classpath/java/io/Writer.java new file mode 100644 index 0000000000..60f0ccdeaf --- /dev/null +++ b/sgx-jvm/avian/classpath/java/io/Writer.java @@ -0,0 +1,63 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.io; + +public abstract class Writer implements Closeable, Flushable, Appendable { + public void write(int c) throws IOException { + char[] buffer = new char[] { (char) c }; + write(buffer); + } + + public void write(char[] buffer) throws IOException { + write(buffer, 0, buffer.length); + } + + public void write(String s) throws IOException { + write(s.toCharArray()); + } + + public void write(String s, int offset, int length) throws IOException { + char[] b = new char[length]; + s.getChars(offset, offset + length, b, 0); + write(b); + } + + public abstract void write(char[] buffer, int offset, int length) + throws IOException; + + public Appendable append(final char c) throws IOException { + write((int)c); + return this; + } + + public Appendable append(final CharSequence sequence) throws IOException { + return append(sequence, 0, sequence.length()); + } + + public Appendable append(CharSequence sequence, int start, int end) + throws IOException { + final int length = end - start; + if (sequence instanceof String) { + write((String)sequence, start, length); + } else { + final char[] charArray = new char[length]; + for (int i = start; i < end; i++) { + charArray[i] = sequence.charAt(i); + } + write(charArray, 0, length); + } + return this; + } + + public abstract void flush() throws IOException; + + public abstract void close() throws IOException; +} diff --git a/sgx-jvm/avian/classpath/java/lang/AbstractMethodError.java b/sgx-jvm/avian/classpath/java/lang/AbstractMethodError.java new file mode 100644 index 0000000000..185e10dee6 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/lang/AbstractMethodError.java @@ -0,0 +1,21 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.lang; + +public class AbstractMethodError extends IncompatibleClassChangeError { + public AbstractMethodError() { + super(); + } + + public AbstractMethodError(String message) { + super(message); + } +} diff --git a/sgx-jvm/avian/classpath/java/lang/Appendable.java b/sgx-jvm/avian/classpath/java/lang/Appendable.java new file mode 100644 index 0000000000..fc99187025 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/lang/Appendable.java @@ -0,0 +1,22 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.lang; + +import java.io.IOException; + +public interface Appendable { + public Appendable append(char c) throws IOException; + + public Appendable append(CharSequence sequence) throws IOException; + + public Appendable append(CharSequence sequence, int start, int end) + throws IOException; +} diff --git a/sgx-jvm/avian/classpath/java/lang/ArithmeticException.java b/sgx-jvm/avian/classpath/java/lang/ArithmeticException.java new file mode 100644 index 0000000000..0d7822dab0 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/lang/ArithmeticException.java @@ -0,0 +1,21 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.lang; + +public class ArithmeticException extends RuntimeException { + public ArithmeticException(String message) { + super(message); + } + + public ArithmeticException() { + this(null); + } +} diff --git a/sgx-jvm/avian/classpath/java/lang/ArrayIndexOutOfBoundsException.java b/sgx-jvm/avian/classpath/java/lang/ArrayIndexOutOfBoundsException.java new file mode 100644 index 0000000000..59913900fe --- /dev/null +++ b/sgx-jvm/avian/classpath/java/lang/ArrayIndexOutOfBoundsException.java @@ -0,0 +1,33 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.lang; + +public class ArrayIndexOutOfBoundsException extends IndexOutOfBoundsException { + public ArrayIndexOutOfBoundsException(String message, Throwable cause) { + super(message, cause); + } + + public ArrayIndexOutOfBoundsException(String message) { + this(message, null); + } + + public ArrayIndexOutOfBoundsException(Throwable cause) { + this(null, cause); + } + + public ArrayIndexOutOfBoundsException(int idx) { + this("Array index out of range: " + idx); + } + + public ArrayIndexOutOfBoundsException() { + this(null, null); + } +} diff --git a/sgx-jvm/avian/classpath/java/lang/ArrayStoreException.java b/sgx-jvm/avian/classpath/java/lang/ArrayStoreException.java new file mode 100644 index 0000000000..90ed0ddbd6 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/lang/ArrayStoreException.java @@ -0,0 +1,21 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.lang; + +public class ArrayStoreException extends RuntimeException { + public ArrayStoreException(String message) { + super(message, null); + } + + public ArrayStoreException() { + this(null); + } +} diff --git a/sgx-jvm/avian/classpath/java/lang/AssertionError.java b/sgx-jvm/avian/classpath/java/lang/AssertionError.java new file mode 100644 index 0000000000..16d650a26a --- /dev/null +++ b/sgx-jvm/avian/classpath/java/lang/AssertionError.java @@ -0,0 +1,45 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.lang; + +public class AssertionError extends Error { + public AssertionError() { + super("", null); + } + + public AssertionError(boolean detailMessage) { + super(""+detailMessage, null); + } + + public AssertionError(char detailMessage) { + super(""+detailMessage, null); + } + + public AssertionError(double detailMessage) { + super(""+detailMessage, null); + } + + public AssertionError(float detailMessage) { + super(""+detailMessage, null); + } + + public AssertionError(int detailMessage) { + super(""+detailMessage, null); + } + + public AssertionError(long detailMessage) { + super(""+detailMessage, null); + } + + public AssertionError(Object detailMessage) { + super(""+detailMessage, null); + } +} diff --git a/sgx-jvm/avian/classpath/java/lang/AutoCloseable.java b/sgx-jvm/avian/classpath/java/lang/AutoCloseable.java new file mode 100644 index 0000000000..0693dd45a5 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/lang/AutoCloseable.java @@ -0,0 +1,15 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.lang; + +public interface AutoCloseable { + void close() throws Exception; +} diff --git a/sgx-jvm/avian/classpath/java/lang/Boolean.java b/sgx-jvm/avian/classpath/java/lang/Boolean.java new file mode 100644 index 0000000000..44ebae2e09 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/lang/Boolean.java @@ -0,0 +1,69 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.lang; + +public final class Boolean implements Comparable { + public static final Class TYPE = avian.Classes.forCanonicalName("Z"); + + public static final Boolean FALSE = new Boolean(false); + public static final Boolean TRUE = new Boolean(true); + + private final boolean value; + + public Boolean(boolean value) { + this.value = value; + } + + public Boolean(String s) { + this.value = "true".equals(s); + } + + public static Boolean valueOf(boolean value) { + return (value ? Boolean.TRUE : Boolean.FALSE); + } + + public static Boolean valueOf(String s) { + Boolean.TRUE.booleanValue(); + return ("true".equals(s) ? Boolean.TRUE : Boolean.FALSE); + } + + public int compareTo(Boolean o) { + return (value ? (o.value ? 0 : 1) : (o.value ? -1 : 0)); + } + + public boolean equals(Object o) { + return o instanceof Boolean && ((Boolean) o).value == value; + } + + public int hashCode() { + return (value ? 1 : 0); + } + + public String toString() { + return toString(value); + } + + public static String toString(boolean v) { + return (v ? "true" : "false"); + } + + public boolean booleanValue() { + return value; + } + + public static boolean getBoolean(String name) { + return parseBoolean(System.getProperty(name)); + } + + public static boolean parseBoolean(String string) { + return string != null && string.equalsIgnoreCase("true"); + } +} diff --git a/sgx-jvm/avian/classpath/java/lang/Byte.java b/sgx-jvm/avian/classpath/java/lang/Byte.java new file mode 100644 index 0000000000..a28ec6a0f4 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/lang/Byte.java @@ -0,0 +1,80 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.lang; + +public final class Byte extends Number implements Comparable { + public static final Class TYPE = avian.Classes.forCanonicalName("B"); + + public static final byte MIN_VALUE = -128; + public static final byte MAX_VALUE = 127; + + private final byte value; + + public Byte(byte value) { + this.value = value; + } + + public static Byte valueOf(byte value) { + return new Byte(value); + } + + public boolean equals(Object o) { + return o instanceof Byte && ((Byte) o).value == value; + } + + public int hashCode() { + return value; + } + + public String toString() { + return toString(value); + } + + public int compareTo(Byte o) { + return value - o.value; + } + + public static String toString(byte v, int radix) { + return Long.toString(v, radix); + } + + public static String toString(byte v) { + return toString(v, 10); + } + + public static byte parseByte(String s) { + return (byte) Integer.parseInt(s); + } + + public byte byteValue() { + return value; + } + + public short shortValue() { + return value; + } + + public int intValue() { + return value; + } + + public long longValue() { + return value; + } + + public float floatValue() { + return (float) value; + } + + public double doubleValue() { + return (double) value; + } +} diff --git a/sgx-jvm/avian/classpath/java/lang/CharSequence.java b/sgx-jvm/avian/classpath/java/lang/CharSequence.java new file mode 100644 index 0000000000..bde0354155 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/lang/CharSequence.java @@ -0,0 +1,21 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.lang; + +public interface CharSequence { + public char charAt(int index); + + int length(); + + CharSequence subSequence(int start, int end); + + String toString(); +} diff --git a/sgx-jvm/avian/classpath/java/lang/Character.java b/sgx-jvm/avian/classpath/java/lang/Character.java new file mode 100644 index 0000000000..2a0882de85 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/lang/Character.java @@ -0,0 +1,258 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.lang; + +public final class Character implements Comparable { + public static final int MIN_RADIX = 2; + public static final int MAX_RADIX = 36; + + public static final Class TYPE = avian.Classes.forCanonicalName("C"); + + private final char value; + + public Character(char value) { + this.value = value; + } + + public static Character valueOf(char value) { + return new Character(value); + } + + public int compareTo(Character o) { + return value - o.value; + } + + public boolean equals(Object o) { + return o instanceof Character && ((Character) o).value == value; + } + + public int hashCode() { + return (int) value; + } + + public String toString() { + return toString(value); + } + + public static String toString(char v) { + return new String(new char[] { v }); + } + + public char charValue() { + return value; + } + + public static char toLowerCase(char c) { + if (c >= 'A' && c <= 'Z') { + return (char) ((c - 'A') + 'a'); + } else { + return c; + } + } + + public static int toLowerCase(int codePoint) { + if (isSupplementaryCodePoint(codePoint)) { + return codePoint; + } else { + return toLowerCase((char) codePoint); + } + } + + public static char toUpperCase(char c) { + if (c >= 'a' && c <= 'z') { + return (char) ((c - 'a') + 'A'); + } else { + return c; + } + } + + public static int toUpperCase(int codePoint) { + if (isSupplementaryCodePoint(codePoint)) { + return codePoint; + } else { + return toUpperCase((char) codePoint); + } + } + + public static boolean isDigit(char c) { + return c >= '0' && c <= '9'; + } + + public static boolean isDigit(int c) { + return c >= '0' && c <= '9'; + } + + public static int digit(char c, int radix) { + int digit = 0; + if ((c >= '0') && (c <= '9')) { + digit = c - '0'; + } else if ((c >= 'a') && (c <= 'z')) { + digit = c - 'a' + 10; + } else if ((c >= 'A') && (c <= 'Z')) { + digit = c - 'A' + 10; + } else { + return -1; + } + + if (digit < radix) { + return digit; + } else { + return -1; + } + } + + public static char forDigit(int digit, int radix) { + if (MIN_RADIX <= radix && radix <= MAX_RADIX) { + if (0 <= digit && digit < radix) { + return (char) (digit < 10 ? digit + '0' : digit + 'a' - 10); + } + } + return 0; + } + + public static boolean isLetter(int c) { + return canCastToChar(c) && isLetter((char) c); + } + + public static boolean isLetter(char c) { + return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'); + } + + public static boolean isLetterOrDigit(char c) { + return isDigit(c) || isLetter(c); + } + + public static boolean isLetterOrDigit(int c) { + return canCastToChar(c) && (isDigit((char) c) || isLetter((char) c)); + } + + public static boolean isLowerCase(int c) { + return canCastToChar(c) && isLowerCase((char) c); + } + + public static boolean isLowerCase(char c) { + return (c >= 'a' && c <= 'z'); + } + + public static boolean isUpperCase(char c) { + return (c >= 'A' && c <= 'Z'); + } + + public static boolean isUpperCase(int c) { + return canCastToChar(c) && isUpperCase((char) c); + } + + public static boolean isWhitespace(int c) { + return canCastToChar(c) && isWhitespace((char) c); + } + + public static boolean isWhitespace(char c) { + return c == ' ' || c == '\t' || c == '\n' || c == '\r'; + } + + public static boolean isSpaceChar(char c) { + return isWhitespace(c); + } + + public static boolean isHighSurrogate(char ch) { + return ch >= '\uD800' && ch <= '\uDBFF'; + } + + public static boolean isLowSurrogate(char ch) { + return ch >= '\uDC00' && ch <= '\uDFFF'; + } + + public static boolean isISOControl(char ch) { + return ch <= '\u001F' || (ch >= '\u007F' && ch <= '\u009F'); + } + + public static boolean isJavaIdentifierStart(char ch) { + return isLetter(ch) || ch == '$' || ch == '_'; + //TODO: add if (getType(ch)==LETTER_NUMBER) || getType(ch)==CURRENCY_SYMBOL + } + + public static boolean isJavaIdentifierStart(int c) { + return canCastToChar(c) && isJavaIdentifierStart((char) c); + } + + public static boolean isJavaIdentifierPart(char ch) { + return isJavaIdentifierStart(ch) || isDigit(ch); + //TODO:Check for numeric letters (such as a Roman numeral character),combining marks,non-spacing marks + //add isIdentifierIgnorable(ch) + } + + public static boolean isJavaIdentifierPart(int c) { + return canCastToChar(c) && isJavaIdentifierPart((char) c); + } + + public static int toCodePoint(char high, char low) { + return (((high & 0x3FF) << 10) | (low & 0x3FF)) + 0x10000; + } + + public static boolean isSupplementaryCodePoint(int codePoint) { + return codePoint >= 0x10000 && codePoint <= 0x10FFFF; + } + + private static boolean canCastToChar(int codePoint) { + return (codePoint >= 0 && codePoint <= 0xFFFF); + } + + public static char[] toChars(int codePoint) { + if (isSupplementaryCodePoint(codePoint)) { + int cpPrime = codePoint - 0x10000; + int high = 0xD800 | ((cpPrime >> 10) & 0x3FF); + int low = 0xDC00 | (cpPrime & 0x3FF); + return new char[] { (char) high, (char) low }; + } + return new char[] { (char) codePoint }; + } + + public static boolean isSurrogatePair(char high, char low) { + return isHighSurrogate(high) && isLowSurrogate(low); + } + + public static int codePointAt(CharSequence sequence, int offset) { + int length = sequence.length(); + if (offset < 0 || offset >= length) { + throw new IndexOutOfBoundsException(); + } + + char high = sequence.charAt(offset); + if (! isHighSurrogate(high) || offset >= length) { + return high; + } + char low = sequence.charAt(offset + 1); + if (! isLowSurrogate(low)) { + return high; + } + + return toCodePoint(high, low); + } + + public static int codePointCount(CharSequence sequence, int start, int end) { + int length = sequence.length(); + if (start < 0 || start > end || end >= length) { + throw new IndexOutOfBoundsException(); + } + + int count = 0; + for (int i = start; i < end; ++i) { + if (isHighSurrogate(sequence.charAt(i)) + && (i + 1) < end + && isLowSurrogate(sequence.charAt(i + 1))) + { + ++ i; + } + ++ count; + } + return count; + } +} diff --git a/sgx-jvm/avian/classpath/java/lang/Class.java b/sgx-jvm/avian/classpath/java/lang/Class.java new file mode 100644 index 0000000000..5cba3cd7e0 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/lang/Class.java @@ -0,0 +1,791 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.lang; + +import avian.VMClass; +import avian.ClassAddendum; +import avian.AnnotationInvocationHandler; +import avian.SystemClassLoader; +import avian.Classes; +import avian.InnerClassReference; + +import java.lang.reflect.Constructor; +import java.lang.reflect.GenericDeclaration; +import java.lang.reflect.Method; +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; +import java.lang.reflect.Type; +import java.lang.reflect.TypeVariable; +import java.lang.reflect.Proxy; +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.AnnotatedElement; +import java.lang.reflect.SignatureParser; +import java.lang.annotation.Annotation; +import java.io.InputStream; +import java.io.IOException; +import java.net.URL; +import java.util.Arrays; +import java.util.List; +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.Map; +import java.util.HashMap; +import java.security.ProtectionDomain; +import java.security.Permissions; +import java.security.AllPermission; + +public final class Class + implements Type, AnnotatedElement, GenericDeclaration +{ + private static final int PrimitiveFlag = 1 << 5; + private static final int EnumFlag = 1 << 14; + + public final VMClass vmClass; + + public Class(VMClass vmClass) { + this.vmClass = vmClass; + } + + public String toString() { + String res; + if (isInterface()) res = "interface "; + else if (isAnnotation()) res = "annotation "; + else res = "class "; + return res + getName(); + } + + private static byte[] replace(int a, int b, byte[] s, int offset, + int length) + { + byte[] array = new byte[length]; + for (int i = 0; i < length; ++i) { + byte c = s[i]; + array[i] = (byte) (c == a ? b : c); + } + return array; + } + + public String getName() { + return getName(vmClass); + } + + public static String getName(VMClass c) { + if (c.name == null) { + if ((c.vmFlags & PrimitiveFlag) != 0) { + if (c == Classes.primitiveClass('V')) { + c.name = "void\0".getBytes(); + } else if (c == Classes.primitiveClass('Z')) { + c.name = "boolean\0".getBytes(); + } else if (c == Classes.primitiveClass('B')) { + c.name = "byte\0".getBytes(); + } else if (c == Classes.primitiveClass('C')) { + c.name = "char\0".getBytes(); + } else if (c == Classes.primitiveClass('S')) { + c.name = "short\0".getBytes(); + } else if (c == Classes.primitiveClass('I')) { + c.name = "int\0".getBytes(); + } else if (c == Classes.primitiveClass('F')) { + c.name = "float\0".getBytes(); + } else if (c == Classes.primitiveClass('J')) { + c.name = "long\0".getBytes(); + } else if (c == Classes.primitiveClass('D')) { + c.name = "double\0".getBytes(); + } else { + throw new AssertionError(); + } + } else { + throw new AssertionError(); + } + } + + return Classes.makeString + (replace('/', '.', c.name, 0, c.name.length - 1), 0, c.name.length - 1); + } + + public String getCanonicalName() { + if ((vmClass.vmFlags & PrimitiveFlag) != 0) { + return getName(); + } else if (isArray()) { + return getComponentType().getCanonicalName() + "[]"; + } else { + return getName().replace('$', '.'); + } + } + + public String getSimpleName() { + if ((vmClass.vmFlags & PrimitiveFlag) != 0) { + return getName(); + } else if (isArray()) { + return getComponentType().getSimpleName() + "[]"; + } else { + String name = getCanonicalName(); + int index = name.lastIndexOf('.'); + if (index >= 0) { + return name.substring(index + 1); + } else { + return name; + } + } + } + + public T newInstance() + throws IllegalAccessException, InstantiationException + { + try { + return (T) getConstructor().newInstance(); + } catch (NoSuchMethodException e) { + throw new RuntimeException(e); + } catch (InvocationTargetException e) { + throw new RuntimeException(e); + } + } + + public static Class forName(String name) throws ClassNotFoundException { + return forName(name, true, Method.getCaller().class_.loader); + } + + public static Class forName(String name, boolean initialize, + ClassLoader loader) + throws ClassNotFoundException + { + return Classes.forName(name, initialize, loader); + } + + public Class getComponentType() { + if (isArray()) { + String n = getName(); + if ("[Z".equals(n)) { + return SystemClassLoader.getClass(Classes.primitiveClass('Z')); + } else if ("[B".equals(n)) { + return SystemClassLoader.getClass(Classes.primitiveClass('B')); + } else if ("[S".equals(n)) { + return SystemClassLoader.getClass(Classes.primitiveClass('S')); + } else if ("[C".equals(n)) { + return SystemClassLoader.getClass(Classes.primitiveClass('C')); + } else if ("[I".equals(n)) { + return SystemClassLoader.getClass(Classes.primitiveClass('I')); + } else if ("[F".equals(n)) { + return SystemClassLoader.getClass(Classes.primitiveClass('F')); + } else if ("[J".equals(n)) { + return SystemClassLoader.getClass(Classes.primitiveClass('J')); + } else if ("[D".equals(n)) { + return SystemClassLoader.getClass(Classes.primitiveClass('D')); + } + + if (vmClass.arrayElementClass == null) throw new AssertionError(); + return SystemClassLoader.getClass((VMClass) vmClass.arrayElementClass); + } else { + return null; + } + } + + public boolean isAssignableFrom(Class c) { + return Classes.isAssignableFrom(vmClass, c.vmClass); + } + + public Field getDeclaredField(String name) throws NoSuchFieldException { + int index = Classes.findField(vmClass, name); + if (index < 0) { + throw new NoSuchFieldException(name); + } else { + return new Field(vmClass.fieldTable[index]); + } + } + + public Field getField(String name) throws NoSuchFieldException { + for (VMClass c = vmClass; c != null; c = c.super_) { + int index = Classes.findField(c, name); + if (index >= 0) { + return new Field(vmClass.fieldTable[index]); + } + } + throw new NoSuchFieldException(name); + } + + public Method getDeclaredMethod(String name, Class ... parameterTypes) + throws NoSuchMethodException + { + if (name.startsWith("<")) { + throw new NoSuchMethodException(name); + } + int index = Classes.findMethod(vmClass, name, parameterTypes); + if (index < 0) { + throw new NoSuchMethodException(name); + } else { + return new Method(vmClass.methodTable[index]); + } + } + + public Method getMethod(String name, Class ... parameterTypes) + throws NoSuchMethodException + { + if (name.startsWith("<")) { + throw new NoSuchMethodException(name); + } + for (VMClass c = vmClass; c != null; c = c.super_) { + int index = Classes.findMethod(c, name, parameterTypes); + if (index >= 0) { + return new Method(c.methodTable[index]); + } + } + throw new NoSuchMethodException(name); + } + + public Constructor getConstructor(Class ... parameterTypes) + throws NoSuchMethodException + { + int index = Classes.findMethod(vmClass, "", parameterTypes); + if (index < 0) { + throw new NoSuchMethodException(); + } else { + return new Constructor(new Method(vmClass.methodTable[index])); + } + } + + public Constructor getDeclaredConstructor(Class ... parameterTypes) + throws NoSuchMethodException + { + Constructor c = null; + Constructor[] constructors = getDeclaredConstructors(); + + for (int i = 0; i < constructors.length; ++i) { + if (Classes.match(parameterTypes, constructors[i].getParameterTypes())) { + c = constructors[i]; + } + } + + if (c == null) { + throw new NoSuchMethodException(); + } else { + return c; + } + } + + private int countConstructors(boolean publicOnly) { + int count = 0; + if (vmClass.methodTable != null) { + for (int i = 0; i < vmClass.methodTable.length; ++i) { + if (((! publicOnly) + || ((vmClass.methodTable[i].flags & Modifier.PUBLIC)) + != 0) + && Method.getName(vmClass.methodTable[i]).equals("")) + { + ++ count; + } + } + } + return count; + } + + public Constructor[] getDeclaredConstructors() { + Constructor[] array = new Constructor[countConstructors(false)]; + if (vmClass.methodTable != null) { + Classes.link(vmClass); + + int index = 0; + for (int i = 0; i < vmClass.methodTable.length; ++i) { + if (Method.getName(vmClass.methodTable[i]).equals("")) { + array[index++] = new Constructor(new Method(vmClass.methodTable[i])); + } + } + } + + return array; + } + + public Constructor[] getConstructors() { + Constructor[] array = new Constructor[countConstructors(true)]; + if (vmClass.methodTable != null) { + Classes.link(vmClass); + + int index = 0; + for (int i = 0; i < vmClass.methodTable.length; ++i) { + if (((vmClass.methodTable[i].flags & Modifier.PUBLIC) != 0) + && Method.getName(vmClass.methodTable[i]).equals("")) + { + array[index++] = new Constructor(new Method(vmClass.methodTable[i])); + } + } + } + + return array; + } + + public Field[] getDeclaredFields() { + if (vmClass.fieldTable != null) { + Field[] array = new Field[vmClass.fieldTable.length]; + for (int i = 0; i < vmClass.fieldTable.length; ++i) { + array[i] = new Field(vmClass.fieldTable[i]); + } + return array; + } else { + return new Field[0]; + } + } + + private int countPublicFields() { + int count = 0; + if (vmClass.fieldTable != null) { + for (int i = 0; i < vmClass.fieldTable.length; ++i) { + if (((vmClass.fieldTable[i].flags & Modifier.PUBLIC)) != 0) { + ++ count; + } + } + } + return count; + } + + public Field[] getFields() { + Field[] array = new Field[countPublicFields()]; + if (vmClass.fieldTable != null) { + Classes.link(vmClass); + + int ai = 0; + for (int i = 0; i < vmClass.fieldTable.length; ++i) { + if (((vmClass.fieldTable[i].flags & Modifier.PUBLIC)) != 0) { + array[ai++] = new Field(vmClass.fieldTable[i]); + } + } + } + return array; + } + + private static void getAllFields(VMClass vmClass, ArrayList fields) { + if (vmClass.super_ != null) { + getAllFields(vmClass.super_, fields); + } + if (vmClass.fieldTable != null) { + Classes.link(vmClass); + + for (int i = 0; i < vmClass.fieldTable.length; ++i) { + fields.add(new Field(vmClass.fieldTable[i])); + } + } + } + + public Field[] getAllFields() { + ArrayList fields = new ArrayList(); + getAllFields(vmClass, fields); + return fields.toArray(new Field[fields.size()]); + } + + public Method[] getDeclaredMethods() { + return Classes.getMethods(vmClass, false); + } + + public Method[] getMethods() { + return Classes.getMethods(vmClass, true); + } + + public Class[] getInterfaces() { + ClassAddendum addendum = vmClass.addendum; + if (addendum != null) { + Object[] table = addendum.interfaceTable; + if (table != null) { + Class[] array = new Class[table.length]; + for (int i = 0; i < table.length; ++i) { + array[i] = SystemClassLoader.getClass((VMClass) table[i]); + } + return array; + } + } + return new Class[0]; + } + + public native Class getEnclosingClass(); + + public native Method getEnclosingMethod(); + + public native Constructor getEnclosingConstructor(); + + public T[] getEnumConstants() { + if (Enum.class.isAssignableFrom(this)) { + try { + return (T[]) getMethod("values").invoke(null); + } catch (Exception e) { + throw new Error(); + } + } else { + return null; + } + } + + public Class[] getDeclaredClasses() { + ClassAddendum addendum = vmClass.addendum; + if (addendum != null) { + InnerClassReference[] table = addendum.innerClassTable; + if (table != null) { + int count = 0; + for (int i = 0; i < table.length; ++i) { + InnerClassReference reference = table[i]; + if (reference.outer != null + && Arrays.equals(vmClass.name, reference.outer)) + { + ++ count; + } + } + + Class[] result = new Class[count]; + for (int i = 0; i < table.length; ++i) { + InnerClassReference reference = table[i]; + if (reference.outer != null + && Arrays.equals(vmClass.name, reference.outer)) + { + try { + result[--count] = getClassLoader().loadClass + (new String(reference.inner, 0, reference.inner.length - 1)); + } catch (ClassNotFoundException e) { + throw new Error(e); + } + } + } + + return result; + } + } + return new Class[0]; + } + + public Class getDeclaringClass() { + ClassAddendum addendum = vmClass.addendum; + if (addendum != null) { + InnerClassReference[] table = addendum.innerClassTable; + if (table != null) { + for (int i = 0; i < table.length; ++i) { + InnerClassReference reference = table[i]; + if (Arrays.equals(vmClass.name, reference.inner)) { + if (reference.outer != null) { + try { + return getClassLoader().loadClass + (new String(reference.outer, 0, reference.outer.length - 1)); + } catch (ClassNotFoundException e) { + throw new Error(e); + } + } else { + return null; + } + } + } + } + } + return null; + } + + public ClassLoader getClassLoader() { + return vmClass.loader; + } + + public int getModifiers() { + ClassAddendum addendum = vmClass.addendum; + if (addendum != null) { + InnerClassReference[] table = addendum.innerClassTable; + if (table != null) { + for (int i = 0; i < table.length; ++i) { + InnerClassReference reference = table[i]; + if (Arrays.equals(vmClass.name, reference.inner)) { + return reference.flags; + } + } + } + } + + return vmClass.flags; + } + + public boolean isInterface() { + return (vmClass.flags & Modifier.INTERFACE) != 0; + } + + public boolean isAnnotation() { + return (vmClass.flags & 0x2000) != 0; + } + + public Class getSuperclass() { + return (vmClass.super_ == null ? null : SystemClassLoader.getClass(vmClass.super_)); + } + + private enum ClassType { GLOBAL, MEMBER, LOCAL, ANONYMOUS } + + /** + * Determines the class type. + * + * There are four class types: global (no dollar sign), anonymous (only digits after the dollar sign), + * local (starts with digits after the dollar, ends in class name) and member (does not start with digits + * after the dollar sign). + * + * @return the class type + */ + private ClassType getClassType() { + final String name = getName(); + // Find the last dollar, as classes can be nested + int dollar = name.lastIndexOf('$'); + if (dollar < 0) return ClassType.GLOBAL; + + // Find the first non-digit after the dollar, if any + final char[] chars = name.toCharArray(); + int skipDigits; + for (skipDigits = dollar + 1; skipDigits < chars.length; skipDigits++) { + if (chars[skipDigits] < '0' || chars[skipDigits] > '9') break; + } + + if (skipDigits == chars.length) { + return ClassType.ANONYMOUS; + } else if (skipDigits == dollar + 1) { + return ClassType.MEMBER; + } else { + return ClassType.LOCAL; + } + } + + public boolean isAnonymousClass () { + return getClassType() == ClassType.ANONYMOUS; + } + + public boolean isLocalClass () { + return getClassType() == ClassType.LOCAL; + } + + public boolean isMemberClass () { + return getClassType() == ClassType.MEMBER; + } + + public boolean isArray() { + return vmClass.arrayDimensions != 0; + } + + public static boolean isInstance(VMClass c, Object o) { + return o != null && Classes.isAssignableFrom + (c, Classes.getVMClass(o)); + } + + public boolean isInstance(Object o) { + return isInstance(vmClass, o); + } + + public boolean isPrimitive() { + return (vmClass.vmFlags & PrimitiveFlag) != 0; + } + + public boolean isEnum() { + return getSuperclass() == Enum.class && (vmClass.flags & EnumFlag) != 0; + } + + public URL getResource(String path) { + if (path.startsWith("/")) { + path = path.substring(1); + } else { + String name = Classes.makeString + (vmClass.name, 0, vmClass.name.length - 1); + int index = name.lastIndexOf('/'); + if (index >= 0) { + path = name.substring(0, index) + "/" + path; + } + } + return getClassLoader().getResource(path); + } + + public InputStream getResourceAsStream(String path) { + URL url = getResource(path); + try { + return (url == null ? null : url.openStream()); + } catch (IOException e) { + return null; + } + } + + public boolean desiredAssertionStatus() { + return false; + } + + public Class asSubclass(Class c) { + if (! c.isAssignableFrom(this)) { + throw new ClassCastException(); + } + + return (Class) this; + } + + public T cast(Object o) { + return (T) o; + } + + public Package getPackage() { + if ((vmClass.vmFlags & PrimitiveFlag) != 0 || isArray()) { + return null; + } else { + String name = getCanonicalName(); + int index = name.lastIndexOf('.'); + if (index >= 0) { + return getClassLoader().getPackage(name.substring(0, index)); + } else { + return null; + } + } + } + + public boolean isAnnotationPresent + (Class class_) + { + return getAnnotation(class_) != null; + } + + private static Annotation getAnnotation(VMClass c, Object[] a) { + if (a[0] == null) { + a[0] = Proxy.newProxyInstance + (c.loader, new Class[] { (Class) a[1] }, + new AnnotationInvocationHandler(a)); + } + return (Annotation) a[0]; + } + + public T getAnnotation(Class class_) { + for (VMClass c = vmClass; c != null; c = c.super_) { + if (c.addendum != null && c.addendum.annotationTable != null) { + Classes.link(c, c.loader); + + Object[] table = (Object[]) c.addendum.annotationTable; + for (int i = 0; i < table.length; ++i) { + Object[] a = (Object[]) table[i]; + if (a[1] == class_) { + return (T) getAnnotation(c, a); + } + } + } + } + return null; + } + + public Annotation[] getDeclaredAnnotations() { + if (vmClass.addendum.annotationTable != null) { + Classes.link(vmClass); + + Object[] table = (Object[]) vmClass.addendum.annotationTable; + Annotation[] array = new Annotation[table.length]; + for (int i = 0; i < table.length; ++i) { + array[i] = getAnnotation(vmClass, (Object[]) table[i]); + } + return array; + } else { + return new Annotation[0]; + } + } + + private int countAnnotations() { + int count = 0; + for (VMClass c = vmClass; c != null; c = c.super_) { + if (c.addendum != null && c.addendum.annotationTable != null) { + count += ((Object[]) c.addendum.annotationTable).length; + } + } + return count; + } + + public Annotation[] getAnnotations() { + Annotation[] array = new Annotation[countAnnotations()]; + int i = 0; + for (VMClass c = vmClass; c != null; c = c.super_) { + if (c.addendum != null && c.addendum.annotationTable != null) { + Object[] table = (Object[]) c.addendum.annotationTable; + for (int j = 0; j < table.length; ++j) { + array[i++] = getAnnotation(vmClass, (Object[]) table[j]); + } + } + } + + return array; + } + + public ProtectionDomain getProtectionDomain() { + return Classes.getProtectionDomain(vmClass); + } + + public TypeVariable[] getTypeParameters() { + throw new UnsupportedOperationException("not yet implemented"); + } + + /** + * The first one is the superclass, the others are interfaces + **/ + private String[] getGenericTypeSignatures() { + String signature = Classes.toString((byte[]) vmClass.addendum.signature); + final char[] signChars = signature.toCharArray(); + + // Addendum format: + // LBaseClass;LIface1;LIface2;... + // We should split it + + int i = -1; + + // Passing the generic args + int angles = 0; + do { + i++; + if (signChars[i] == '<') angles ++; + else if (signChars[i] == '>') angles --; + } while (angles > 0); + if (signChars[i] == '>') i++; + + // Splitting types list + LinkedList typeSigns = new LinkedList(); + StringBuilder curTypeSign = new StringBuilder(); + for (; i < signChars.length; i++) { + // Counting braces + if (signChars[i] == '<') angles ++; + else if (signChars[i] == '>') angles --; + + // Appending character + curTypeSign.append(signChars[i]); + + // Splitting + if (angles == 0 && signChars[i] == ';') { + typeSigns.add(curTypeSign.toString()); + curTypeSign.setLength(0); + } + } + if (curTypeSign.length() > 0) typeSigns.add(curTypeSign.toString()); + + String[] res = new String[typeSigns.size()]; + return typeSigns.toArray(res); + } + + public Type[] getGenericInterfaces() { + if (vmClass.addendum == null || vmClass.addendum.signature == null) { + return getInterfaces(); + } + + String[] typeSigns = getGenericTypeSignatures(); + if (typeSigns.length < 1) { + throw new RuntimeException("Class signature doesn't contain any type"); + } + + // Parsing types + Type[] res = new Type[typeSigns.length - 1]; + for (int i = 0; i < typeSigns.length - 1; i++) { + res[i] = SignatureParser.parse(vmClass.loader, typeSigns[i + 1], this); + } + + return res; + } + + public Type getGenericSuperclass() { + if (vmClass.addendum == null || vmClass.addendum.signature == null) { + return getSuperclass(); + } + String[] typeSigns = getGenericTypeSignatures(); + if (typeSigns.length < 1) { + throw new RuntimeException("Class signature doesn't contain any type"); + } + + return SignatureParser.parse(vmClass.loader, typeSigns[0], this); + } + +} diff --git a/sgx-jvm/avian/classpath/java/lang/ClassCastException.java b/sgx-jvm/avian/classpath/java/lang/ClassCastException.java new file mode 100644 index 0000000000..c244f63ca7 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/lang/ClassCastException.java @@ -0,0 +1,21 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.lang; + +public class ClassCastException extends RuntimeException { + public ClassCastException(String message) { + super(message); + } + + public ClassCastException() { + super(); + } +} diff --git a/sgx-jvm/avian/classpath/java/lang/ClassLoader.java b/sgx-jvm/avian/classpath/java/lang/ClassLoader.java new file mode 100644 index 0000000000..85404fa924 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/lang/ClassLoader.java @@ -0,0 +1,213 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.lang; + +import java.io.InputStream; +import java.io.IOException; +import java.net.URL; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Enumeration; +import java.util.Map; +import java.util.HashMap; +import java.security.ProtectionDomain; + +public abstract class ClassLoader { + private final ClassLoader parent; + private Map packages; + + protected ClassLoader(ClassLoader parent) { + if (parent == null) { + this.parent = getSystemClassLoader(); + } else { + this.parent = parent; + } + } + + protected ClassLoader() { + this(getSystemClassLoader()); + } + + private Map packages() { + if (packages == null) { + packages = new HashMap(); + } + return packages; + } + + protected Package getPackage(String name) { + synchronized (this) { + return packages().get(name); + } + } + + protected Package[] getPackages() { + synchronized (this) { + return packages().values().toArray(new Package[packages().size()]); + } + } + + protected Package definePackage(String name, + String specificationTitle, + String specificationVersion, + String specificationVendor, + String implementationTitle, + String implementationVersion, + String implementationVendor, + URL sealBase) + { + Package p = new Package + (name, implementationTitle, implementationVersion, + implementationVendor, specificationTitle, specificationVersion, + specificationVendor, sealBase, this); + + synchronized (this) { + packages().put(name, p); + return p; + } + } + + public static ClassLoader getSystemClassLoader() { + return ClassLoader.class.getClassLoader(); + } + + protected Class defineClass(String name, byte[] b, int offset, int length) { + if (b == null) { + throw new NullPointerException(); + } + + if (offset < 0 || offset > length || offset + length > b.length) { + throw new IndexOutOfBoundsException(); + } + + return avian.SystemClassLoader.getClass + (avian.Classes.defineVMClass(this, b, offset, length)); + } + + protected Class defineClass(String name, byte[] b, int offset, int length, + ProtectionDomain domain) + { + return defineClass(name, b, offset, length); + } + + protected Class findClass(String name) throws ClassNotFoundException { + throw new ClassNotFoundException(); + } + + protected Class reallyFindLoadedClass(String name) { + return null; + } + + protected final Class findLoadedClass(String name) { + return reallyFindLoadedClass(name); + } + + public Class loadClass(String name) throws ClassNotFoundException { + return loadClass(name, false); + } + + protected Class loadClass(String name, boolean resolve) + throws ClassNotFoundException + { + Class c = findLoadedClass(name); + if (c == null) { + if (parent != null) { + try { + c = parent.loadClass(name); + } catch (ClassNotFoundException ok) { } + } + + if (c == null) { + c = findClass(name); + } + } + + if (resolve) { + resolveClass(c); + } + + return c; + } + + protected void resolveClass(Class c) { + avian.Classes.link(c.vmClass, this); + } + + public final ClassLoader getParent() { + return parent; + } + + protected URL findResource(String path) { + return null; + } + + protected Enumeration findResources(String name) throws IOException { + return Collections.enumeration(new ArrayList(0)); + } + + public URL getResource(String path) { + URL url = null; + if (parent != null) { + url = parent.getResource(path); + } + + if (url == null) { + url = findResource(path); + } + + return url; + } + + public InputStream getResourceAsStream(String path) { + URL url = getResource(path); + try { + return (url == null ? null : url.openStream()); + } catch (IOException e) { + return null; + } + } + + public static URL getSystemResource(String path) { + return getSystemClassLoader().getResource(path); + } + + public static InputStream getSystemResourceAsStream(String path) { + return getSystemClassLoader().getResourceAsStream(path); + } + + public static Enumeration getSystemResources(String name) throws IOException { + return getSystemClassLoader().getResources(name); + } + + public Enumeration getResources(String name) + throws IOException { + Collection resources = collectResources(name); + return Collections.enumeration(resources); + } + + private Collection collectResources(String name) { + Collection urls = parent != null ? parent.collectResources(name) : new ArrayList(5); + URL url = findResource(name); + if (url != null) { + urls.add(url); + } + return urls; + } + + protected String findLibrary(String name) { + return null; + } + + static native Class getCaller(); + + static native void load(String name, Class caller, boolean mapName); +} diff --git a/sgx-jvm/avian/classpath/java/lang/ClassNotFoundException.java b/sgx-jvm/avian/classpath/java/lang/ClassNotFoundException.java new file mode 100644 index 0000000000..9562f95d88 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/lang/ClassNotFoundException.java @@ -0,0 +1,33 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.lang; + +public class ClassNotFoundException extends Exception { + private final Throwable cause2; + + public ClassNotFoundException(String message, Throwable cause) { + super(message, cause); + cause2 = cause; + } + + public ClassNotFoundException(String message) { + this(message, null); + } + + public ClassNotFoundException() { + this(null, null); + } + + public Throwable getException() { + return cause2; + } + +} diff --git a/sgx-jvm/avian/classpath/java/lang/CloneNotSupportedException.java b/sgx-jvm/avian/classpath/java/lang/CloneNotSupportedException.java new file mode 100644 index 0000000000..b29f66a547 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/lang/CloneNotSupportedException.java @@ -0,0 +1,21 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.lang; + +public class CloneNotSupportedException extends Exception { + public CloneNotSupportedException(String message) { + super(message); + } + + public CloneNotSupportedException() { + super(); + } +} diff --git a/sgx-jvm/avian/classpath/java/lang/Cloneable.java b/sgx-jvm/avian/classpath/java/lang/Cloneable.java new file mode 100644 index 0000000000..84e202c12e --- /dev/null +++ b/sgx-jvm/avian/classpath/java/lang/Cloneable.java @@ -0,0 +1,13 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.lang; + +public interface Cloneable { } diff --git a/sgx-jvm/avian/classpath/java/lang/Comparable.java b/sgx-jvm/avian/classpath/java/lang/Comparable.java new file mode 100644 index 0000000000..fdf345bb08 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/lang/Comparable.java @@ -0,0 +1,15 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.lang; + +public interface Comparable { + public int compareTo(T o); +} diff --git a/sgx-jvm/avian/classpath/java/lang/Deprecated.java b/sgx-jvm/avian/classpath/java/lang/Deprecated.java new file mode 100644 index 0000000000..b7e833d254 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/lang/Deprecated.java @@ -0,0 +1,17 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.lang; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +@Retention(RetentionPolicy.RUNTIME) +public @interface Deprecated { } diff --git a/sgx-jvm/avian/classpath/java/lang/Double.java b/sgx-jvm/avian/classpath/java/lang/Double.java new file mode 100644 index 0000000000..ff224dd54e --- /dev/null +++ b/sgx-jvm/avian/classpath/java/lang/Double.java @@ -0,0 +1,119 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.lang; + +public final class Double extends Number { + public static final Class TYPE = avian.Classes.forCanonicalName("D"); + + public static final double NEGATIVE_INFINITY = -1.0 / 0.0; + public static final double POSITIVE_INFINITY = 1.0 / 0.0; + public static final double NaN = 0.0 / 0.0; + + public static final double MIN_VALUE = 2.22507385850720138309e-308; + public static final double MAX_VALUE = 1.79769313486231570815e+308; + + private final double value; + + public Double(String value) { + this.value = parseDouble(value); + } + + public Double(double value) { + this.value = value; + } + + public static Double valueOf(double value) { + return new Double(value); + } + + public static Double valueOf(String s) { + return new Double(s); + } + + public boolean equals(Object o) { + return o instanceof Double && ((Double) o).value == value; + } + + public int hashCode() { + long v = doubleToRawLongBits(value); + return (int) ((v >> 32) ^ (v & 0xFF)); + } + + public String toString() { + return toString(value); + } + + public static String toString(double v) { + byte[] buffer = new byte[20]; + int numChars = fillBufferWithDouble(v, buffer, 20); + return new String(buffer, 0, numChars, false); + } + + public byte byteValue() { + return (byte) value; + } + + public short shortValue() { + return (short) value; + } + + public int intValue() { + return (int) value; + } + + public long longValue() { + return (long) value; + } + + public float floatValue() { + return (float) value; + } + + public double doubleValue() { + return value; + } + + public boolean isInfinite() { + return isInfinite(value); + } + + public boolean isNaN() { + return isNaN(value); + } + + public static double parseDouble(String s) { + int[] numRead = new int[1]; + double d = doubleFromString(s, numRead); + if (numRead[0] == 1) { + return d; + } else { + throw new NumberFormatException(s); + } + } + + public static long doubleToLongBits(double value) { + if (isNaN(value)) return 0x7ff8000000000000L; + return doubleToRawLongBits(value); + } + + public static native int fillBufferWithDouble(double value, byte[] buffer, + int charCount); + + public static native long doubleToRawLongBits(double value); + + public static native double longBitsToDouble(long bits); + + public static native boolean isInfinite(double value); + + public static native boolean isNaN(double value); + + public static native double doubleFromString(String s, int[] numRead); +} diff --git a/sgx-jvm/avian/classpath/java/lang/Enum.java b/sgx-jvm/avian/classpath/java/lang/Enum.java new file mode 100644 index 0000000000..38ea903e5d --- /dev/null +++ b/sgx-jvm/avian/classpath/java/lang/Enum.java @@ -0,0 +1,72 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.lang; + +import java.lang.reflect.Method; + +public abstract class Enum> implements Comparable { + private final String name; + protected final int ordinal; + + public Enum(String name, int ordinal) { + this.name = name; + this.ordinal = ordinal; + } + + public int compareTo(E other) { + if (getDeclaringClass() != other.getDeclaringClass()) { + throw new ClassCastException(); + } + + return ordinal - other.ordinal; + } + + public static > T valueOf(Class enumType, String name) { + if (name == null) throw new NullPointerException("name"); + if (!enumType.isEnum()) + throw new IllegalArgumentException(enumType.getCanonicalName() + " is not an enum."); + + try { + Method method = enumType.getMethod("values"); + Enum values[] = (Enum[]) method.invoke(null); + for (Enum value: values) { + if (name.equals(value.name)) { + return (T) value; + } + } + } catch (Exception ex) { + // Cannot happen + throw new Error(ex); + } + + throw new IllegalArgumentException(enumType.getCanonicalName() + "." + name + " is not an enum constant."); + } + + public int ordinal() { + return ordinal; + } + + public final String name() { + return name; + } + + public String toString() { + return name; + } + + public Class getDeclaringClass() { + Class c = getClass(); + while (c.getSuperclass() != Enum.class) { + c = c.getSuperclass(); + } + return c; + } +} diff --git a/sgx-jvm/avian/classpath/java/lang/Error.java b/sgx-jvm/avian/classpath/java/lang/Error.java new file mode 100644 index 0000000000..8851c25979 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/lang/Error.java @@ -0,0 +1,29 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.lang; + +public class Error extends Throwable { + public Error(String message, Throwable cause) { + super(message, cause); + } + + public Error(String message) { + this(message, null); + } + + public Error(Throwable cause) { + this(null, cause); + } + + public Error() { + this(null, null); + } +} diff --git a/sgx-jvm/avian/classpath/java/lang/Exception.java b/sgx-jvm/avian/classpath/java/lang/Exception.java new file mode 100644 index 0000000000..09bec5b62d --- /dev/null +++ b/sgx-jvm/avian/classpath/java/lang/Exception.java @@ -0,0 +1,29 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.lang; + +public class Exception extends Throwable { + public Exception(String message, Throwable cause) { + super(message, cause); + } + + public Exception(String message) { + this(message, null); + } + + public Exception(Throwable cause) { + this(null, cause); + } + + public Exception() { + this(null, null); + } +} diff --git a/sgx-jvm/avian/classpath/java/lang/ExceptionInInitializerError.java b/sgx-jvm/avian/classpath/java/lang/ExceptionInInitializerError.java new file mode 100644 index 0000000000..4e56a2a1f6 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/lang/ExceptionInInitializerError.java @@ -0,0 +1,24 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.lang; + +public class ExceptionInInitializerError extends Error { + private final Throwable exception; + + public ExceptionInInitializerError(String message) { + super(message); + exception = null; + } + + public ExceptionInInitializerError() { + this(null); + } +} diff --git a/sgx-jvm/avian/classpath/java/lang/Float.java b/sgx-jvm/avian/classpath/java/lang/Float.java new file mode 100644 index 0000000000..3bebc1079c --- /dev/null +++ b/sgx-jvm/avian/classpath/java/lang/Float.java @@ -0,0 +1,121 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.lang; + +public final class Float extends Number { + public static final Class TYPE = avian.Classes.forCanonicalName("F"); + private static final int EXP_BIT_MASK = 0x7F800000; + private static final int SIGNIF_BIT_MASK = 0x007FFFFF; + + public static final float NEGATIVE_INFINITY = -1.0f / 0.0f; + public static final float POSITIVE_INFINITY = 1.0f / 0.0f; + public static final float NaN = 0.0f / 0.0f; + + public static final float MIN_VALUE = 1.17549435082228750797e-38f; + public static final float MAX_VALUE = 3.40282346638528859812e+38f; + + private final float value; + + public Float(String value) { + this.value = parseFloat(value); + } + + public Float(float value) { + this.value = value; + } + + public static Float valueOf(float value) { + return new Float(value); + } + + public static Float valueOf(String s) { + return new Float(s); + } + + public boolean equals(Object o) { + return o instanceof Float && ((Float) o).value == value; + } + + public int hashCode() { + return floatToRawIntBits(value); + } + + public String toString() { + return toString(value); + } + + public static String toString(float v) { + return Double.toString(v); + } + + public byte byteValue() { + return (byte) value; + } + + public short shortValue() { + return (short) value; + } + + public int intValue() { + return (int) value; + } + + public long longValue() { + return (long) value; + } + + public float floatValue() { + return value; + } + + public double doubleValue() { + return (double) value; + } + + public boolean isInfinite() { + return isInfinite(value); + } + + public boolean isNaN() { + return isNaN(value); + } + + public static float parseFloat(String s) { + int[] numRead = new int[1]; + float f = floatFromString(s, numRead); + if (numRead[0] == 1) { + return f; + } else { + throw new NumberFormatException(s); + } + } + + public static int floatToIntBits(float value) { + int result = floatToRawIntBits(value); + + // Check for NaN based on values of bit fields, maximum + // exponent and nonzero significand. + if (((result & EXP_BIT_MASK) == EXP_BIT_MASK) && (result & SIGNIF_BIT_MASK) != 0) { + result = 0x7fc00000; + } + return result; + } + + public static native int floatToRawIntBits(float value); + + public static native float intBitsToFloat(int bits); + + public static native boolean isInfinite(float value); + + public static native boolean isNaN(float value); + + public static native float floatFromString(String s, int[] numRead); +} diff --git a/sgx-jvm/avian/classpath/java/lang/IllegalAccessError.java b/sgx-jvm/avian/classpath/java/lang/IllegalAccessError.java new file mode 100644 index 0000000000..c53ba72f4d --- /dev/null +++ b/sgx-jvm/avian/classpath/java/lang/IllegalAccessError.java @@ -0,0 +1,26 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.lang; + +/** + * TODO : current Avian runtime doesn't check, need to be implemented. + * + */ +public class IllegalAccessError extends IncompatibleClassChangeError { + + public IllegalAccessError(String message) { + super(message); + } + + public IllegalAccessError() { + } + +} diff --git a/sgx-jvm/avian/classpath/java/lang/IllegalAccessException.java b/sgx-jvm/avian/classpath/java/lang/IllegalAccessException.java new file mode 100644 index 0000000000..e4205fb176 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/lang/IllegalAccessException.java @@ -0,0 +1,21 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.lang; + +public class IllegalAccessException extends Exception { + public IllegalAccessException(String message) { + super(message); + } + + public IllegalAccessException() { + super(); + } +} diff --git a/sgx-jvm/avian/classpath/java/lang/IllegalArgumentException.java b/sgx-jvm/avian/classpath/java/lang/IllegalArgumentException.java new file mode 100644 index 0000000000..124810a25c --- /dev/null +++ b/sgx-jvm/avian/classpath/java/lang/IllegalArgumentException.java @@ -0,0 +1,29 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.lang; + +public class IllegalArgumentException extends RuntimeException { + public IllegalArgumentException(String message, Throwable cause) { + super(message, cause); + } + + public IllegalArgumentException(String message) { + this(message, null); + } + + public IllegalArgumentException(Throwable cause) { + this(null, cause); + } + + public IllegalArgumentException() { + this(null, null); + } +} diff --git a/sgx-jvm/avian/classpath/java/lang/IllegalMonitorStateException.java b/sgx-jvm/avian/classpath/java/lang/IllegalMonitorStateException.java new file mode 100644 index 0000000000..31b65b587f --- /dev/null +++ b/sgx-jvm/avian/classpath/java/lang/IllegalMonitorStateException.java @@ -0,0 +1,21 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.lang; + +public class IllegalMonitorStateException extends RuntimeException { + public IllegalMonitorStateException(String message) { + super(message, null); + } + + public IllegalMonitorStateException() { + this(null); + } +} diff --git a/sgx-jvm/avian/classpath/java/lang/IllegalStateException.java b/sgx-jvm/avian/classpath/java/lang/IllegalStateException.java new file mode 100644 index 0000000000..5374f35e4c --- /dev/null +++ b/sgx-jvm/avian/classpath/java/lang/IllegalStateException.java @@ -0,0 +1,29 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.lang; + +public class IllegalStateException extends RuntimeException { + public IllegalStateException(String message, Throwable cause) { + super(message, cause); + } + + public IllegalStateException(String message) { + this(message, null); + } + + public IllegalStateException(Throwable cause) { + this(null, cause); + } + + public IllegalStateException() { + this(null, null); + } +} diff --git a/sgx-jvm/avian/classpath/java/lang/IllegalThreadStateException.java b/sgx-jvm/avian/classpath/java/lang/IllegalThreadStateException.java new file mode 100644 index 0000000000..3defa035d7 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/lang/IllegalThreadStateException.java @@ -0,0 +1,30 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.lang; + +public class IllegalThreadStateException extends IllegalArgumentException { + public IllegalThreadStateException(String message, Throwable cause) { + super(message, cause); + } + + public IllegalThreadStateException(String message) { + this(message, null); + } + + public IllegalThreadStateException(Throwable cause) { + this(null, cause); + } + + public IllegalThreadStateException() { + this(null, null); + } + +} diff --git a/sgx-jvm/avian/classpath/java/lang/IncompatibleClassChangeError.java b/sgx-jvm/avian/classpath/java/lang/IncompatibleClassChangeError.java new file mode 100644 index 0000000000..3af1db4c88 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/lang/IncompatibleClassChangeError.java @@ -0,0 +1,21 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.lang; + +public class IncompatibleClassChangeError extends LinkageError { + public IncompatibleClassChangeError(String message) { + super(message); + } + + public IncompatibleClassChangeError() { + super(); + } +} diff --git a/sgx-jvm/avian/classpath/java/lang/IndexOutOfBoundsException.java b/sgx-jvm/avian/classpath/java/lang/IndexOutOfBoundsException.java new file mode 100644 index 0000000000..35bbef659b --- /dev/null +++ b/sgx-jvm/avian/classpath/java/lang/IndexOutOfBoundsException.java @@ -0,0 +1,29 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.lang; + +public class IndexOutOfBoundsException extends RuntimeException { + public IndexOutOfBoundsException(String message, Throwable cause) { + super(message, cause); + } + + public IndexOutOfBoundsException(String message) { + this(message, null); + } + + public IndexOutOfBoundsException(Throwable cause) { + this(null, cause); + } + + public IndexOutOfBoundsException() { + this(null, null); + } +} diff --git a/sgx-jvm/avian/classpath/java/lang/InheritableThreadLocal.java b/sgx-jvm/avian/classpath/java/lang/InheritableThreadLocal.java new file mode 100644 index 0000000000..cf26eb07ad --- /dev/null +++ b/sgx-jvm/avian/classpath/java/lang/InheritableThreadLocal.java @@ -0,0 +1,19 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.lang; + +import java.util.Map; + +public class InheritableThreadLocal extends ThreadLocal { + protected T childValue(T parentValue) { + return parentValue; + } +} diff --git a/sgx-jvm/avian/classpath/java/lang/InstantiationError.java b/sgx-jvm/avian/classpath/java/lang/InstantiationError.java new file mode 100644 index 0000000000..d659bfdfbd --- /dev/null +++ b/sgx-jvm/avian/classpath/java/lang/InstantiationError.java @@ -0,0 +1,26 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.lang; + +/** + * TODO : current Avian runtime doesn't check, need to be implemented. + * + */ +public class InstantiationError extends IncompatibleClassChangeError { + + public InstantiationError(String message) { + super(message); + } + + public InstantiationError() { + } + +} diff --git a/sgx-jvm/avian/classpath/java/lang/InstantiationException.java b/sgx-jvm/avian/classpath/java/lang/InstantiationException.java new file mode 100644 index 0000000000..112484b9f4 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/lang/InstantiationException.java @@ -0,0 +1,21 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.lang; + +public class InstantiationException extends Exception { + public InstantiationException(String message) { + super(message); + } + + public InstantiationException() { + super(); + } +} diff --git a/sgx-jvm/avian/classpath/java/lang/Integer.java b/sgx-jvm/avian/classpath/java/lang/Integer.java new file mode 100644 index 0000000000..0dbf20ae21 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/lang/Integer.java @@ -0,0 +1,142 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.lang; + +public final class Integer extends Number implements Comparable { + public static final Class TYPE = avian.Classes.forCanonicalName("I"); + + public static final int MIN_VALUE = 0x80000000; + public static final int MAX_VALUE = 0x7FFFFFFF; + + private final int value; + + public Integer(int value) { + this.value = value; + } + + public Integer(String s) { + this.value = parseInt(s); + } + + public static Integer valueOf(int value) { + return new Integer(value); + } + + public static Integer valueOf(String value) { + return valueOf(parseInt(value)); + } + + public boolean equals(Object o) { + return o instanceof Integer && ((Integer) o).value == value; + } + + public int hashCode() { + return value; + } + + public int compareTo(Integer other) { + return value - other.value; + } + + public String toString() { + return toString(value); + } + + public static String toString(int v, int radix) { + return Long.toString(v, radix); + } + + public static String toString(int v) { + return toString(v, 10); + } + + public static String toHexString(int v) { + return Long.toString(((long) v) & 0xFFFFFFFFL, 16); + } + + public static String toOctalString(int v) { + return Long.toString(((long) v) & 0xFFFFFFFFL, 8); + } + + public static String toBinaryString(int v) { + return Long.toString(((long) v) & 0xFFFFFFFFL, 2); + } + + public byte byteValue() { + return (byte) value; + } + + public short shortValue() { + return (short) value; + } + + public int intValue() { + return value; + } + + public long longValue() { + return value; + } + + public float floatValue() { + return (float) value; + } + + public double doubleValue() { + return (double) value; + } + + public static int signum(int v) { + if (v == 0) return 0; + else if (v > 0) return 1; + else return -1; + } + + // See http://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetParallel + public static int bitCount(int v) { + v = v - ((v >> 1) & 0x55555555); + v = (v & 0x33333333) + ((v >> 2) & 0x33333333); + return ((v + (v >> 4) & 0xF0F0F0F) * 0x1010101) >> 24; + } + + public static int reverseBytes(int v) { + int byte3 = v >>> 24; + int byte2 = (v >>> 8) & 0xFF00; + int byte1 = (v << 8) & 0xFF00; + int byte0 = v << 24; + return (byte0 | byte1 | byte2 | byte3); + } + + public static int parseInt(String s) { + return parseInt(s, 10); + } + + public static int parseInt(String s, int radix) { + return (int) Long.parseLong(s, radix); + } + + public static Integer decode(String string) { + if (string.startsWith("-")) { + if (string.startsWith("-0") || string.startsWith("-#")) { + return new Integer(-decode(string.substring(1))); + } + } else if (string.startsWith("0")) { + char c = string.length() < 2 ? (char)-1 : string.charAt(1); + if (c == 'x' || c == 'X') { + return new Integer(parseInt(string.substring(2), 0x10)); + } + return new Integer(parseInt(string, 010)); + } else if (string.startsWith("#")) { + return new Integer(parseInt(string.substring(1), 0x10)); + } + return new Integer(parseInt(string, 10)); + } +} diff --git a/sgx-jvm/avian/classpath/java/lang/InternalError.java b/sgx-jvm/avian/classpath/java/lang/InternalError.java new file mode 100644 index 0000000000..69ac254db4 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/lang/InternalError.java @@ -0,0 +1,21 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.lang; + +public class InternalError extends VirtualMachineError { + public InternalError(String message) { + super(message); + } + + public InternalError() { + this(null); + } +} diff --git a/sgx-jvm/avian/classpath/java/lang/InterruptedException.java b/sgx-jvm/avian/classpath/java/lang/InterruptedException.java new file mode 100644 index 0000000000..9a4c0d8178 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/lang/InterruptedException.java @@ -0,0 +1,29 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.lang; + +public class InterruptedException extends Exception { + public InterruptedException(String message, Throwable cause) { + super(message, cause); + } + + public InterruptedException(String message) { + this(message, null); + } + + public InterruptedException(Throwable cause) { + this(null, cause); + } + + public InterruptedException() { + this(null, null); + } +} diff --git a/sgx-jvm/avian/classpath/java/lang/Iterable.java b/sgx-jvm/avian/classpath/java/lang/Iterable.java new file mode 100644 index 0000000000..4618e2ced7 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/lang/Iterable.java @@ -0,0 +1,17 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.lang; + +import java.util.Iterator; + +public interface Iterable { + public Iterator iterator(); +} diff --git a/sgx-jvm/avian/classpath/java/lang/LinkageError.java b/sgx-jvm/avian/classpath/java/lang/LinkageError.java new file mode 100644 index 0000000000..05313ffc1c --- /dev/null +++ b/sgx-jvm/avian/classpath/java/lang/LinkageError.java @@ -0,0 +1,21 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.lang; + +public class LinkageError extends Error { + public LinkageError(String message) { + super(message, null); + } + + public LinkageError() { + this(null); + } +} diff --git a/sgx-jvm/avian/classpath/java/lang/Long.java b/sgx-jvm/avian/classpath/java/lang/Long.java new file mode 100644 index 0000000000..dda7ed1ed6 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/lang/Long.java @@ -0,0 +1,174 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.lang; + +public final class Long extends Number implements Comparable { + public static final long MIN_VALUE = -9223372036854775808l; + public static final long MAX_VALUE = 9223372036854775807l; + + public static final Class TYPE = avian.Classes.forCanonicalName("J"); + + private final long value; + + public Long(long value) { + this.value = value; + } + + public Long(String s) { + this.value = parseLong(s); + } + + public static Long valueOf(String value) { + return new Long(value); + } + + public static Long valueOf(long value) { + return new Long(value); + } + + public int compareTo(Long o) { + return value > o.value ? 1 : (value < o.value ? -1 : 0); + } + + public boolean equals(Object o) { + return o instanceof Long && ((Long) o).value == value; + } + + public int hashCode() { + return (int) ((value >> 32) ^ (value & 0xFF)); + } + + public String toString() { + return String.valueOf(value); + } + + public static String toString(long v, int radix) { + if (radix < 1 || radix > 36) { + throw new IllegalArgumentException("radix " + radix + " not in [1,36]"); + } + + if (v == 0) { + return "0"; + } + + boolean negative = v < 0; + + int size = (negative ? 1 : 0); + for (long n = v; n != 0; n /= radix) ++size; + + char[] array = new char[size]; + + int i = size - 1; + for (long n = v; n != 0; n /= radix) { + long digit = n % radix; + if (negative) digit = -digit; + + if (digit >= 0 && digit <= 9) { + array[i] = (char) ('0' + digit); + } else { + array[i] = (char) ('a' + (digit - 10)); + } + --i; + } + + if (negative) { + array[i] = '-'; + } + + return new String(array, 0, size, false); + } + + public static String toString(long v) { + return toString(v, 10); + } + + public static String toHexString(long v) { + return toString(v, 16); + } + + public static String toOctalString(long v) { + return toString(v, 8); + } + + public static String toBinaryString(long v) { + return toString(v, 2); + } + + public byte byteValue() { + return (byte) value; + } + + public short shortValue() { + return (short) value; + } + + public int intValue() { + return (int) value; + } + + public long longValue() { + return value; + } + + public float floatValue() { + return (float) value; + } + + public double doubleValue() { + return (double) value; + } + + public static int signum(long v) { + if (v == 0) return 0; + else if (v > 0) return 1; + else return -1; + } + + private static long pow(long a, long b) { + long c = 1; + for (int i = 0; i < b; ++i) c *= a; + return c; + } + + public static long parseLong(String s) { + return parseLong(s, 10); + } + + public static long parseLong(String s, int radix) { + int i = 0; + long number = 0; + boolean negative = s.startsWith("-"); + int length = s.length(); + if (negative) { + i = 1; + -- length; + } + + long factor = pow(radix, length - 1); + for (; i < s.length(); ++i) { + char c = s.charAt(i); + int digit = Character.digit(c, radix); + if (digit >= 0) { + number += digit * factor; + factor /= radix; + } else { + throw new NumberFormatException("invalid character " + c + " code " + + (int) c); + } + } + + if (negative) { + number = -number; + } + + return number; + } +} diff --git a/sgx-jvm/avian/classpath/java/lang/Math.java b/sgx-jvm/avian/classpath/java/lang/Math.java new file mode 100644 index 0000000000..c1d1c0bdaf --- /dev/null +++ b/sgx-jvm/avian/classpath/java/lang/Math.java @@ -0,0 +1,124 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.lang; + +import java.util.Random; + +public final class Math { + public static final double E = 2.718281828459045; + public static final double PI = 3.141592653589793; + + private static class Static { + public static final Random random = new Random(); + } + + private Math() { } + + public static double max(double a, double b) { + return (a < b ? b : a); + } + + public static double min(double a, double b) { + return (a > b ? b : a); + } + + public static float max(float a, float b) { + return (a < b ? b : a); + } + + public static float min(float a, float b) { + return (a > b ? b : a); + } + + public static long max(long a, long b) { + return (a < b ? b : a); + } + + public static long min(long a, long b) { + return (a > b ? b : a); + } + + public static int max(int a, int b) { + return (a < b ? b : a); + } + + public static int min(int a, int b) { + return (a > b ? b : a); + } + + public static int abs(int v) { + return (v < 0 ? -v : v); + } + + public static long abs(long v) { + return (v < 0 ? -v : v); + } + + public static float abs(float v) { + return (v < 0 ? -v : v); + } + + public static double abs(double v) { + return (v < 0 ? -v : v); + } + + public static long round(double v) { + return (long) Math.floor(v + 0.5); + } + + public static int round(float v) { + return (int) Math.floor(v + 0.5); + } + + public static double signum(double d) { + return d > 0 ? +1.0 : d < 0 ? -1.0 : 0; + } + + public static float signum(float f) { + return f > 0 ? +1.0f : f < 0 ? -1.0f : 0; + } + + public static double random() { + return Static.random.nextDouble(); + } + + public static native double floor(double v); + + public static native double ceil(double v); + + public static native double exp(double v); + + public static native double log(double v); + + public static native double cos(double v); + + public static native double sin(double v); + + public static native double tan(double v); + + public static native double cosh(double v); + + public static native double sinh(double v); + + public static native double tanh(double v); + + public static native double acos(double v); + + public static native double asin(double v); + + public static native double atan(double v); + + public static native double atan2(double y, double x); + + public static native double sqrt(double v); + + public static native double pow(double v, double e); +} diff --git a/sgx-jvm/avian/classpath/java/lang/NegativeArraySizeException.java b/sgx-jvm/avian/classpath/java/lang/NegativeArraySizeException.java new file mode 100644 index 0000000000..a51048ad1b --- /dev/null +++ b/sgx-jvm/avian/classpath/java/lang/NegativeArraySizeException.java @@ -0,0 +1,21 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.lang; + +public class NegativeArraySizeException extends RuntimeException { + public NegativeArraySizeException(String message) { + super(message); + } + + public NegativeArraySizeException() { + super(); + } +} diff --git a/sgx-jvm/avian/classpath/java/lang/NoClassDefFoundError.java b/sgx-jvm/avian/classpath/java/lang/NoClassDefFoundError.java new file mode 100644 index 0000000000..1b01a3b150 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/lang/NoClassDefFoundError.java @@ -0,0 +1,21 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.lang; + +public class NoClassDefFoundError extends LinkageError { + public NoClassDefFoundError(String message) { + super(message); + } + + public NoClassDefFoundError() { + super(); + } +} diff --git a/sgx-jvm/avian/classpath/java/lang/NoSuchFieldError.java b/sgx-jvm/avian/classpath/java/lang/NoSuchFieldError.java new file mode 100644 index 0000000000..1fde5606c6 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/lang/NoSuchFieldError.java @@ -0,0 +1,21 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.lang; + +public class NoSuchFieldError extends IncompatibleClassChangeError { + public NoSuchFieldError(String message) { + super(message); + } + + public NoSuchFieldError() { + super(); + } +} diff --git a/sgx-jvm/avian/classpath/java/lang/NoSuchFieldException.java b/sgx-jvm/avian/classpath/java/lang/NoSuchFieldException.java new file mode 100644 index 0000000000..1323172b7b --- /dev/null +++ b/sgx-jvm/avian/classpath/java/lang/NoSuchFieldException.java @@ -0,0 +1,21 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.lang; + +public class NoSuchFieldException extends Exception { + public NoSuchFieldException(String message) { + super(message); + } + + public NoSuchFieldException() { + super(); + } +} diff --git a/sgx-jvm/avian/classpath/java/lang/NoSuchMethodError.java b/sgx-jvm/avian/classpath/java/lang/NoSuchMethodError.java new file mode 100644 index 0000000000..0bf772a3fb --- /dev/null +++ b/sgx-jvm/avian/classpath/java/lang/NoSuchMethodError.java @@ -0,0 +1,21 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.lang; + +public class NoSuchMethodError extends IncompatibleClassChangeError { + public NoSuchMethodError(String message) { + super(message); + } + + public NoSuchMethodError() { + super(); + } +} diff --git a/sgx-jvm/avian/classpath/java/lang/NoSuchMethodException.java b/sgx-jvm/avian/classpath/java/lang/NoSuchMethodException.java new file mode 100644 index 0000000000..63e1fb9ddc --- /dev/null +++ b/sgx-jvm/avian/classpath/java/lang/NoSuchMethodException.java @@ -0,0 +1,21 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.lang; + +public class NoSuchMethodException extends Exception { + public NoSuchMethodException(String message) { + super(message); + } + + public NoSuchMethodException() { + super(); + } +} diff --git a/sgx-jvm/avian/classpath/java/lang/NullPointerException.java b/sgx-jvm/avian/classpath/java/lang/NullPointerException.java new file mode 100644 index 0000000000..ba4c87c365 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/lang/NullPointerException.java @@ -0,0 +1,29 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.lang; + +public class NullPointerException extends RuntimeException { + public NullPointerException(String message, Throwable cause) { + super(message, cause); + } + + public NullPointerException(String message) { + this(message, null); + } + + public NullPointerException(Throwable cause) { + this(null, cause); + } + + public NullPointerException() { + this(null, null); + } +} diff --git a/sgx-jvm/avian/classpath/java/lang/Number.java b/sgx-jvm/avian/classpath/java/lang/Number.java new file mode 100644 index 0000000000..bbfff3a72e --- /dev/null +++ b/sgx-jvm/avian/classpath/java/lang/Number.java @@ -0,0 +1,22 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.lang; + +import java.io.Serializable; + +public abstract class Number implements Serializable { + public abstract byte byteValue(); + public abstract short shortValue(); + public abstract int intValue(); + public abstract long longValue(); + public abstract float floatValue(); + public abstract double doubleValue(); +} diff --git a/sgx-jvm/avian/classpath/java/lang/NumberFormatException.java b/sgx-jvm/avian/classpath/java/lang/NumberFormatException.java new file mode 100644 index 0000000000..9b38d55a09 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/lang/NumberFormatException.java @@ -0,0 +1,21 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.lang; + +public class NumberFormatException extends IllegalArgumentException { + public NumberFormatException(String message) { + super(message); + } + + public NumberFormatException() { + super(); + } +} diff --git a/sgx-jvm/avian/classpath/java/lang/Object.java b/sgx-jvm/avian/classpath/java/lang/Object.java new file mode 100644 index 0000000000..0ad1b78e82 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/lang/Object.java @@ -0,0 +1,58 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.lang; + +public class Object { + protected Object clone() throws CloneNotSupportedException { + if ((this instanceof Cloneable) || getClass().isArray()) { + return clone(this); + } else { + throw new CloneNotSupportedException(getClass().getName()); + } + } + + private static native Object clone(Object o); + + public boolean equals(Object o) { + return this == o; + } + + protected void finalize() throws Throwable { } + + public final Class getClass() { + return avian.SystemClassLoader.getClass(getVMClass(this)); + } + + private static native avian.VMClass getVMClass(Object o); + + public native int hashCode(); + + public native final void notify(); + + public native final void notifyAll(); + + public native String toString(); + + public final void wait() throws InterruptedException { + wait(0); + } + + public native final void wait(long milliseconds) throws InterruptedException; + + public final void wait(long milliseconds, int nanoseconds) + throws InterruptedException + { + if (nanoseconds != 0) { + ++ milliseconds; + } + wait(milliseconds); + } +} diff --git a/sgx-jvm/avian/classpath/java/lang/OutOfMemoryError.java b/sgx-jvm/avian/classpath/java/lang/OutOfMemoryError.java new file mode 100644 index 0000000000..3dc9830b3c --- /dev/null +++ b/sgx-jvm/avian/classpath/java/lang/OutOfMemoryError.java @@ -0,0 +1,21 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.lang; + +public class OutOfMemoryError extends VirtualMachineError { + public OutOfMemoryError(String message) { + super(message); + } + + public OutOfMemoryError() { + this(null); + } +} diff --git a/sgx-jvm/avian/classpath/java/lang/Override.java b/sgx-jvm/avian/classpath/java/lang/Override.java new file mode 100644 index 0000000000..78161ff9a8 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/lang/Override.java @@ -0,0 +1,15 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.lang; + +public @interface Override { + +} diff --git a/sgx-jvm/avian/classpath/java/lang/Package.java b/sgx-jvm/avian/classpath/java/lang/Package.java new file mode 100644 index 0000000000..f982d48caf --- /dev/null +++ b/sgx-jvm/avian/classpath/java/lang/Package.java @@ -0,0 +1,82 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.lang; + +import java.net.URL; + +public class Package { + private final String name; + private final String implementationTitle; + private final String implementationVendor; + private final String implementationVersion; + private final String specificationTitle; + private final String specificationVendor; + private final String specificationVersion; + private final URL sealed; + private final ClassLoader loader; + + Package(String name, + String implementationTitle, + String implementationVendor, + String implementationVersion, + String specificationTitle, + String specificationVendor, + String specificationVersion, + URL sealed, + ClassLoader loader) + { + this.name = name; + this.implementationTitle = implementationTitle; + this.implementationVendor = implementationVendor; + this.implementationVersion = implementationVersion; + this.specificationTitle = specificationTitle; + this.specificationVendor = specificationVendor; + this.specificationVersion = specificationVersion; + this.sealed = sealed; + this.loader = loader; + } + + public String getName() { + return name; + } + + public String getImplementationTitle() { + return implementationTitle; + } + + public String getImplementationVendor() { + return implementationVendor; + } + + public String getImplementationVersion() { + return implementationVersion; + } + + public String getSpecificationTitle() { + return specificationTitle; + } + + public String getSpecificationVendor() { + return specificationVendor; + } + + public String getSpecificationVersion() { + return specificationVersion; + } + + public boolean isSealed() { + return sealed != null; + } + + public boolean isSealed(URL url) { + return sealed.equals(url); + } +} diff --git a/sgx-jvm/avian/classpath/java/lang/Process.java b/sgx-jvm/avian/classpath/java/lang/Process.java new file mode 100644 index 0000000000..12f3f550c3 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/lang/Process.java @@ -0,0 +1,28 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.lang; + +import java.io.InputStream; +import java.io.OutputStream; + +public abstract class Process { + public abstract void destroy(); + + public abstract int exitValue(); + + public abstract InputStream getInputStream(); + + public abstract OutputStream getOutputStream(); + + public abstract InputStream getErrorStream(); + + public abstract int waitFor() throws InterruptedException; +} diff --git a/sgx-jvm/avian/classpath/java/lang/Readable.java b/sgx-jvm/avian/classpath/java/lang/Readable.java new file mode 100644 index 0000000000..f54e4d95ce --- /dev/null +++ b/sgx-jvm/avian/classpath/java/lang/Readable.java @@ -0,0 +1,18 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.lang; + +import java.nio.CharBuffer; +import java.io.IOException; + +public interface Readable { + int read(CharBuffer buffer) throws IOException; +} diff --git a/sgx-jvm/avian/classpath/java/lang/ReflectiveOperationException.java b/sgx-jvm/avian/classpath/java/lang/ReflectiveOperationException.java new file mode 100644 index 0000000000..add39584e0 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/lang/ReflectiveOperationException.java @@ -0,0 +1,13 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.lang; + +public class ReflectiveOperationException extends Exception { } diff --git a/sgx-jvm/avian/classpath/java/lang/Runnable.java b/sgx-jvm/avian/classpath/java/lang/Runnable.java new file mode 100644 index 0000000000..ef186d197c --- /dev/null +++ b/sgx-jvm/avian/classpath/java/lang/Runnable.java @@ -0,0 +1,15 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.lang; + +public interface Runnable { + public void run(); +} diff --git a/sgx-jvm/avian/classpath/java/lang/Runtime.java b/sgx-jvm/avian/classpath/java/lang/Runtime.java new file mode 100644 index 0000000000..e73d74b35b --- /dev/null +++ b/sgx-jvm/avian/classpath/java/lang/Runtime.java @@ -0,0 +1,185 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.lang; + +import java.io.IOException; +import java.io.InputStream; +import java.io.FileInputStream; +import java.io.OutputStream; +import java.io.FileOutputStream; +import java.io.FileDescriptor; +import java.util.StringTokenizer; + +public class Runtime { + private static final Runtime instance = new Runtime(); + + private Runtime() { } + + public static Runtime getRuntime() { + return instance; + } + + public void load(String path) { + if (path != null) { + ClassLoader.load(path, ClassLoader.getCaller(), false); + } else { + throw new NullPointerException(); + } + } + + public void loadLibrary(String path) { + if (path != null) { + ClassLoader.load(path, ClassLoader.getCaller(), true); + } else { + throw new NullPointerException(); + } + } + + public Process exec(String command) throws IOException { + StringTokenizer t = new StringTokenizer(command); + String[] cmd = new String[t.countTokens()]; + for (int i = 0; i < cmd.length; i++) + cmd[i] = t.nextToken(); + + return exec(cmd); + } + + public Process exec(final String[] command) throws IOException { + final MyProcess[] process = new MyProcess[1]; + final Throwable[] exception = new Throwable[1]; + + synchronized (process) { + Thread t = new Thread() { + public void run() { + synchronized (process) { + try { + long[] info = new long[5]; + exec(command, info); + process[0] = new MyProcess + (info[0], info[1], (int) info[2], (int) info[3], + (int) info[4]); + } catch (Throwable e) { + exception[0] = e; + } finally { + process.notifyAll(); + } + } + + MyProcess p = process[0]; + if (p != null) { + synchronized (p) { + try { + if (p.pid != 0) { + p.exitCode = Runtime.waitFor(p.pid, p.tid); + p.pid = 0; + p.tid = 0; + } + } finally { + p.notifyAll(); + } + } + } + } + }; + t.setDaemon(true); + t.start(); + + while (process[0] == null && exception[0] == null) { + try { + process.wait(); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + } + } + + if (exception[0] != null) { + if (exception[0] instanceof IOException) { + String message = "Failed to run \"" + command[0] + "\": " + exception[0].getMessage(); + throw new IOException(message); + } else { + throw new RuntimeException(exception[0]); + } + } + + return process[0]; + } + + public native void addShutdownHook(Thread t); + + private static native void exec(String[] command, long[] process) + throws IOException; + + private static native int waitFor(long pid, long tid); + + private static native void kill(long pid); + + public native void gc(); + + public native void exit(int code); + + public native long freeMemory(); + + public native long totalMemory(); + + public native long maxMemory(); + + private static class MyProcess extends Process { + private long pid; + private long tid; + private final int in; + private final int out; + private final int err; + private int exitCode; + + public MyProcess(long pid, long tid, int in, int out, int err) { + this.pid = pid; + this.tid = tid; + this.in = in; + this.out = out; + this.err = err; + } + + public void destroy() { + if (pid != 0) { + kill(pid); + } + } + + public InputStream getInputStream() { + return new FileInputStream(new FileDescriptor(in)); + } + + public OutputStream getOutputStream() { + return new FileOutputStream(new FileDescriptor(out)); + } + + public InputStream getErrorStream() { + return new FileInputStream(new FileDescriptor(err)); + } + + public synchronized int exitValue() { + if (pid != 0) { + throw new IllegalThreadStateException(); + } + + return exitCode; + } + + public synchronized int waitFor() throws InterruptedException { + while (pid != 0) { + wait(); + } + + return exitCode; + } + } +} diff --git a/sgx-jvm/avian/classpath/java/lang/RuntimeException.java b/sgx-jvm/avian/classpath/java/lang/RuntimeException.java new file mode 100644 index 0000000000..8eb8ecffb5 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/lang/RuntimeException.java @@ -0,0 +1,29 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.lang; + +public class RuntimeException extends Exception { + public RuntimeException(String message, Throwable cause) { + super(message, cause); + } + + public RuntimeException(String message) { + this(message, null); + } + + public RuntimeException(Throwable cause) { + this(null, cause); + } + + public RuntimeException() { + this(null, null); + } +} diff --git a/sgx-jvm/avian/classpath/java/lang/RuntimePermission.java b/sgx-jvm/avian/classpath/java/lang/RuntimePermission.java new file mode 100644 index 0000000000..b61e22eff9 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/lang/RuntimePermission.java @@ -0,0 +1,21 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.lang; + +import java.security.BasicPermission; + +public class RuntimePermission extends BasicPermission { + + public RuntimePermission(String name) { + super(name); + } + +} diff --git a/sgx-jvm/avian/classpath/java/lang/SecurityException.java b/sgx-jvm/avian/classpath/java/lang/SecurityException.java new file mode 100644 index 0000000000..af0fa9612f --- /dev/null +++ b/sgx-jvm/avian/classpath/java/lang/SecurityException.java @@ -0,0 +1,29 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.lang; + +public class SecurityException extends RuntimeException { + public SecurityException(String message, Throwable cause) { + super(message, cause); + } + + public SecurityException(String message) { + this(message, null); + } + + public SecurityException(Throwable cause) { + this(null, cause); + } + + public SecurityException() { + this(null, null); + } +} diff --git a/sgx-jvm/avian/classpath/java/lang/SecurityManager.java b/sgx-jvm/avian/classpath/java/lang/SecurityManager.java new file mode 100644 index 0000000000..29c6b65f74 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/lang/SecurityManager.java @@ -0,0 +1,30 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.lang; + +import java.security.AccessController; +import java.security.Permission; +import java.security.SecurityPermission; + +public class SecurityManager { + + public SecurityManager() { + } + + public void checkPermission(Permission perm) { + AccessController.checkPermission(perm); + } + + public void checkSecurityAccess(String target) { + checkPermission(new SecurityPermission(target)); + } + +} diff --git a/sgx-jvm/avian/classpath/java/lang/Short.java b/sgx-jvm/avian/classpath/java/lang/Short.java new file mode 100644 index 0000000000..409eae36c4 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/lang/Short.java @@ -0,0 +1,76 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.lang; + +public final class Short extends Number implements Comparable { + public static final Class TYPE = avian.Classes.forCanonicalName("S"); + + public static final short MIN_VALUE = -32768; + public static final short MAX_VALUE = 32767; + + private final short value; + + public Short(short value) { + this.value = value; + } + + public static Short valueOf(short value) { + return new Short(value); + } + + public int compareTo(Short o) { + return value - o.value; + } + + public boolean equals(Object o) { + return o instanceof Short && ((Short) o).value == value; + } + + public int hashCode() { + return value; + } + + public String toString() { + return toString(value); + } + + public static String toString(short v, int radix) { + return Long.toString(v, radix); + } + + public static String toString(short v) { + return toString(v, 10); + } + + public byte byteValue() { + return (byte) value; + } + + public short shortValue() { + return value; + } + + public int intValue() { + return value; + } + + public long longValue() { + return value; + } + + public float floatValue() { + return (float) value; + } + + public double doubleValue() { + return (double) value; + } +} diff --git a/sgx-jvm/avian/classpath/java/lang/StackOverflowError.java b/sgx-jvm/avian/classpath/java/lang/StackOverflowError.java new file mode 100644 index 0000000000..9bb536e681 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/lang/StackOverflowError.java @@ -0,0 +1,21 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.lang; + +public class StackOverflowError extends VirtualMachineError { + public StackOverflowError(String message) { + super(message); + } + + public StackOverflowError() { + this(null); + } +} diff --git a/sgx-jvm/avian/classpath/java/lang/StackTraceElement.java b/sgx-jvm/avian/classpath/java/lang/StackTraceElement.java new file mode 100644 index 0000000000..25b6e57afd --- /dev/null +++ b/sgx-jvm/avian/classpath/java/lang/StackTraceElement.java @@ -0,0 +1,77 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.lang; + +public class StackTraceElement { + private static int NativeLine = -1; + + private String class_; + private String method; + private String file; + private int line; + + public StackTraceElement(String class_, String method, String file, + int line) + { + this.class_ = class_; + this.method = method; + this.file = file; + this.line = line; + } + + public int hashCode() { + return class_.hashCode() ^ method.hashCode() ^ line; + } + + public boolean equals(Object o) { + if (o instanceof StackTraceElement) { + StackTraceElement e = (StackTraceElement) o; + return class_.equals(e.class_) + && method.equals(e.method) + && line == e.line; + } else { + return false; + } + } + + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append(class_).append(".").append(method); + + if (line == NativeLine) { + sb.append(" (native)"); + } else if (line >= 0) { + sb.append(" (line ").append(line).append(")"); + } + + return sb.toString(); + } + + public String getClassName() { + return class_; + } + + public String getMethodName() { + return method; + } + + public String getFileName() { + return file; + } + + public int getLineNumber() { + return line; + } + + public boolean isNativeMethod() { + return line == NativeLine; + } +} diff --git a/sgx-jvm/avian/classpath/java/lang/String.java b/sgx-jvm/avian/classpath/java/lang/String.java new file mode 100644 index 0000000000..be45b3c464 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/lang/String.java @@ -0,0 +1,698 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.lang; + +import java.io.Serializable; +import java.io.UnsupportedEncodingException; +import java.util.Comparator; +import java.util.Formatter; +import java.util.Locale; +import java.util.regex.Pattern; + +import avian.Iso88591; +import avian.Utf8; + +public final class String + implements Comparable, CharSequence, Serializable +{ + private static final String UTF_8_ENCODING = "UTF-8"; + private static final String ISO_8859_1_ENCODING = "ISO-8859-1"; + private static final String LATIN_1_ENCODING = "LATIN-1"; + private static final String DEFAULT_ENCODING = UTF_8_ENCODING; + + public static Comparator CASE_INSENSITIVE_ORDER + = new Comparator() { + @Override + public int compare(String a, String b) { + return a.compareToIgnoreCase(b); + } + }; + + private final Object data; + private final int offset; + private final int length; + private int hashCode; + + public String() { + this(new char[0], 0, 0); + } + + public String(char[] data, int offset, int length, boolean copy) { + this((Object) data, offset, length, copy); + } + + public String(char[] data, int offset, int length) { + this(data, offset, length, true); + } + + public String(char[] data) { + this(data, 0, data.length); + } + + public String(byte bytes[], int offset, int length, String charsetName) + throws UnsupportedEncodingException + { + this(bytes, offset, length); + if (! (charsetName.equalsIgnoreCase(UTF_8_ENCODING) + || charsetName.equalsIgnoreCase(ISO_8859_1_ENCODING))) + { + throw new UnsupportedEncodingException(charsetName); + } + } + + public String(byte[] data, int offset, int length, boolean copy) { + this((Object) data, offset, length, copy); + } + + public String(byte[] data, int offset, int length) { + this(data, offset, length, true); + } + + public String(byte[] data) { + this(data, 0, data.length); + } + + public String(String s) { + this(s.toCharArray()); + } + + public String(byte[] data, String charset) + throws UnsupportedEncodingException + { + this(data, 0, data.length, charset); + } + + public String(byte bytes[], int highByte, int offset, int length) { + if (offset < 0 ) + throw new StringIndexOutOfBoundsException(offset); + else if (offset + length > bytes.length) + throw new StringIndexOutOfBoundsException(offset + length); + else if (length < 0) + throw new StringIndexOutOfBoundsException(length); + + char[] c = new char[length]; + int mask = highByte << 8; + for (int i = 0; i < length; ++i) { + c[i] = (char) ((bytes[offset + i] & 0xFF) | mask); + } + + this.data = c; + this.offset = 0; + this.length = length; + } + + private String(Object data, int offset, int length, boolean copy) { + int l; + if (data instanceof char[]) { + l = ((char[]) data).length; + } else { + l = ((byte[]) data).length; + } + + if (offset < 0 ) + throw new StringIndexOutOfBoundsException(offset); + else if (offset + length > l) + throw new StringIndexOutOfBoundsException(offset + length); + else if (length < 0) + throw new StringIndexOutOfBoundsException(length); + + if(!copy && Utf8.test(data)) copy = true; + + if (copy) { + Object c; + if (data instanceof char[]) { + c = new char[length]; + System.arraycopy(data, offset, c, 0, length); + } else { + c = Utf8.decode((byte[])data, offset, length); + if(c instanceof char[]) length = ((char[])c).length; + if (c == null) { + throw new RuntimeException + ("unable to parse \"" + new String(data, offset, length, false) + + "\""); + } + } + + this.data = c; + this.offset = 0; + this.length = length; + } else { + this.data = data; + this.offset = offset; + this.length = length; + } + } + + @Override + public String toString() { + return this; + } + + @Override + public int length() { + return length; + } + + @Override + public int hashCode() { + if (hashCode == 0) { + int h = 0; + for (int i = 0; i < length; ++i) h = (h * 31) + charAt(i); + hashCode = h; + } + return hashCode; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } else if (o instanceof String) { + String s = (String) o; + return s.length == length && compareTo(s) == 0; + } else { + return false; + } + } + + public boolean equalsIgnoreCase(String s) { + if (this == s) { + return true; + } else { + return s != null && s.length == length && compareToIgnoreCase(s) == 0; + } + } + + @Override + public int compareTo(String s) { + if (this == s) return 0; + + int idx = 0; + int result; + + int end = (length < s.length ? length : s.length); + + while (idx < end) { + if ((result = charAt(idx) - s.charAt(idx)) != 0) { + return result; + } + idx++; + } + return length - s.length; + } + + public int compareToIgnoreCase(String s) { + if (this == s) return 0; + + int idx = 0; + int result; + + int end = (length < s.length ? length : s.length); + + while (idx < end) { + if ((result = + Character.toLowerCase(charAt(idx)) - + Character.toLowerCase(s.charAt(idx))) != 0) { + return result; + } + idx++; + } + return length - s.length; + } + + public String trim() { + int start = -1; + for (int i = 0; i < length; ++i) { + char c = charAt(i); + if (start == -1 && ! Character.isWhitespace(c)) { + start = i; + break; + } + } + + int end = -1; + for (int i = length - 1; i >= 0; --i) { + char c = charAt(i); + if (end == -1 && ! Character.isWhitespace(c)) { + end = i + 1; + break; + } + } + + if (start >= end) { + return ""; + } else { + return substring(start, end); + } + } + + public String toLowerCase() { + for (int j = 0; j < length; ++j) { + char ch = charAt(j); + if (Character.toLowerCase(ch) != ch) { + char[] b = new char[length]; + for (int i = 0; i < length; ++i) { + b[i] = Character.toLowerCase(charAt(i)); + } + return new String(b, 0, length, false); + } + } + return this; + } + + public String toUpperCase() { + for (int j = 0; j < length; ++j) { + char ch = charAt(j); + if (Character.toUpperCase(ch) != ch) { + char[] b = new char[length]; + for (int i = 0; i < length; ++i) { + b[i] = Character.toUpperCase(charAt(i)); + } + return new String(b, 0, length, false); + } + } + return this; + } + + public int indexOf(int c) { + return indexOf(c, 0); + } + + public int indexOf(int c, int start) { + for (int i = start; i < length; ++i) { + if (charAt(i) == c) { + return i; + } + } + + return -1; + } + + public int lastIndexOf(int ch) { + return lastIndexOf(ch, length-1); + } + + public int indexOf(String s) { + return indexOf(s, 0); + } + + public int indexOf(String s, int start) { + if (s.length == 0) return start; + + for (int i = start; i < length - s.length + 1; ++i) { + int j = 0; + for (; j < s.length; ++j) { + if (charAt(i + j) != s.charAt(j)) { + break; + } + } + if (j == s.length) { + return i; + } + } + + return -1; + } + + public int lastIndexOf(String s) { + return lastIndexOf(s, length - s.length); + } + + public int lastIndexOf(String s, int lastIndex) { + if (s.length == 0) return lastIndex; + + for (int i = Math.min(length - s.length, lastIndex); i >= 0; --i) { + int j = 0; + for (; j < s.length && i + j < length; ++j) { + if (charAt(i + j) != s.charAt(j)) { + break; + } + } + if (j == s.length) { + return i; + } + } + + return -1; + } + + public String replace(char oldChar, char newChar) { + if (data instanceof char[]) { + char[] buf = new char[length]; + for (int i=0; i < length; i++) { + if (charAt(i) == oldChar) { + buf[i] = newChar; + } else { + buf[i] = charAt(i); + } + } + return new String(buf, 0, length, false); + } else { + byte[] buf = new byte[length]; + byte[] orig = (byte[])data; + byte oldByte = (byte)oldChar; + byte newByte = (byte)newChar; + for (int i=0; i < length; i++) { + if (orig[i+offset] == oldByte) { + buf[i] = newByte; + } else { + buf[i] = orig[i+offset]; + } + } + return new String(buf, 0, length, false); + } + } + + public String substring(int start) { + return substring(start, length); + } + + public String substring(int start, int end) { + if (start < 0) + throw new StringIndexOutOfBoundsException(start); + else if (end > length) + throw new StringIndexOutOfBoundsException(end); + int newLen = end - start; + if (newLen < 0) + throw new StringIndexOutOfBoundsException(newLen); + + if (start == 0 && end == length) + return this; + else if (end - start == 0) + return ""; + else + return new String(data, offset + start, newLen, false); + } + + public boolean startsWith(String s) { + if (length >= s.length) { + return substring(0, s.length).compareTo(s) == 0; + } else { + return false; + } + } + + public boolean startsWith(String s, int start) { + if (length >= s.length + start) { + return substring(start, s.length).compareTo(s) == 0; + } else { + return false; + } + } + + public boolean endsWith(String s) { + if (length >= s.length) { + return substring(length - s.length).compareTo(s) == 0; + } else { + return false; + } + } + + public String concat(String s) { + if (s.length() == 0) { + return this; + } else { + return this + s; + } + } + + public void getBytes(int srcOffset, int srcLength, + byte[] dst, int dstOffset) + { + if (srcOffset < 0) + throw new StringIndexOutOfBoundsException(srcOffset); + else if (srcOffset + srcLength > length) + throw new StringIndexOutOfBoundsException(srcOffset + srcLength); + else if (srcLength < 0) + throw new StringIndexOutOfBoundsException(srcLength); + + if (data instanceof char[]) { + char[] src = (char[]) data; + for (int i = 0; i < srcLength; ++i) { + dst[i + dstOffset] = (byte) src[i + offset + srcOffset]; + } + } else { + byte[] src = (byte[]) data; + System.arraycopy(src, offset + srcOffset, dst, dstOffset, srcLength); + } + } + + public byte[] getBytes() { + try { + return getBytes(DEFAULT_ENCODING); + } catch (java.io.UnsupportedEncodingException ex) { + throw new RuntimeException( + "Default '" + DEFAULT_ENCODING + "' encoding not handled", ex); + } + } + + public byte[] getBytes(String format) + throws java.io.UnsupportedEncodingException + { + if(data instanceof byte[]) { + byte[] b = new byte[length]; + getBytes(0, length, b, 0); + return b; + } + String fmt = format.trim().toUpperCase(); + if (DEFAULT_ENCODING.equals(fmt)) { + return Utf8.encode((char[])data, offset, length); + } else if (ISO_8859_1_ENCODING.equals(fmt) || LATIN_1_ENCODING.equals(fmt)) { + return Iso88591.encode((char[])data, offset, length); + } else { + throw new java.io.UnsupportedEncodingException( + "Encoding " + format + " not supported"); + } + } + + public void getChars(int srcOffset, int srcEnd, + char[] dst, int dstOffset) + { + if (srcOffset < 0) + throw new StringIndexOutOfBoundsException(srcOffset); + else if (srcEnd > length) + throw new StringIndexOutOfBoundsException(srcEnd); + + int srcLength = srcEnd-srcOffset; + if (data instanceof char[]) { + char[] src = (char[]) data; + System.arraycopy(src, offset + srcOffset, dst, dstOffset, srcLength); + } else { + byte[] src = (byte[]) data; + for (int i = 0; i < srcLength; ++i) { + dst[i + dstOffset] = (char) src[i + offset + srcOffset]; + } + } + } + + public char[] toCharArray() { + char[] b = new char[length]; + getChars(0, length, b, 0); + return b; + } + + @Override + public char charAt(int index) { + if (index < 0 || index > length) { + throw new StringIndexOutOfBoundsException(index); + } + + if (data instanceof char[]) { + return ((char[]) data)[index + offset]; + } else { + return (char) ((byte[]) data)[index + offset]; + } + } + + public String[] split(String regex) { + return split(regex, 0); + } + + public String[] split(String regex, int limit) { + return Pattern.compile(regex).split(this, limit); + } + + @Override + public CharSequence subSequence(int start, int end) { + return substring(start, end); + } + + public boolean matches(String regex) { + return Pattern.matches(regex, this); + } + + public String replaceFirst(String regex, String replacement) { + return Pattern.compile(regex).matcher(this).replaceFirst(replacement); + } + + public String replaceAll(String regex, String replacement) { + return Pattern.compile(regex).matcher(this).replaceAll(replacement); + } + + public String replace(CharSequence target, CharSequence replace) { + if (target.length() == 0) { + return this.infuse(replace.toString()); + } + + String targetString = target.toString(); + String replaceString = replace.toString(); + + int targetSize = target.length(); + + StringBuilder returnValue = new StringBuilder(); + String unhandled = this; + + int index = -1; + while ((index = unhandled.indexOf(targetString)) != -1) { + returnValue.append(unhandled.substring(0, index)).append(replaceString); + unhandled = unhandled.substring(index + targetSize, + unhandled.length()); + } + + returnValue.append(unhandled); + return returnValue.toString(); + } + + private String infuse(String infuseWith) { + StringBuilder retVal = new StringBuilder(); + + String me = this; + for (int i = 0; i < me.length(); i++) { + retVal.append(infuseWith).append(me.substring(i, i + 1)); + } + + retVal.append(infuseWith); + return retVal.toString(); + } + + public native String intern(); + + public static String format(String fmt, Object... args) { + final Formatter formatter = new Formatter(); + final String result = formatter.format(fmt, args).toString(); + formatter.close(); + return result; + } + + public static String format(Locale l, String fmt, Object... args) { + final Formatter formatter = new Formatter(); + final String result = formatter.format(l, fmt, args).toString(); + formatter.close(); + return result; + } + + public static String valueOf(Object s) { + return s == null ? "null" : s.toString(); + } + + public static String valueOf(boolean v) { + return Boolean.toString(v); + } + + public static String valueOf(byte v) { + return Byte.toString(v); + } + + public static String valueOf(short v) { + return Short.toString(v); + } + + public static String valueOf(char v) { + return Character.toString(v); + } + + public static String valueOf(int v) { + return Integer.toString(v); + } + + public static String valueOf(long v) { + return Long.toString(v); + } + + public static String valueOf(float v) { + return Float.toString(v); + } + + public static String valueOf(double v) { + return Double.toString(v); + } + + public static String valueOf(char[] data, int offset, int length) { + return new String(data, offset, length); + } + + public static String valueOf(char[] data) { + return valueOf(data, 0, data.length); + } + + public int lastIndexOf(int ch, int lastIndex) { + if (lastIndex >= length) { + lastIndex = length - 1; + } + for (int i = lastIndex ; i >= 0; --i) { + if (charAt(i) == ch) { + return i; + } + } + + return -1; + } + + public boolean regionMatches(int thisOffset, String match, int matchOffset, + int length) + { + return regionMatches(false, thisOffset, match, matchOffset, length); + } + + public boolean regionMatches(boolean ignoreCase, int thisOffset, + String match, int matchOffset, int length) + { + String a = substring(thisOffset, thisOffset + length); + String b = match.substring(matchOffset, matchOffset + length); + if (ignoreCase) { + return a.equalsIgnoreCase(b); + } else { + return a.equals(b); + } + } + + public boolean isEmpty() { + return length == 0; + } + + public boolean contains(CharSequence match) { + return indexOf(match.toString()) != -1; + } + + public int codePointAt(int offset) { + return Character.codePointAt(this, offset); + } + + public int codePointCount(int start, int end) { + return Character.codePointCount(this, start, end); + } + + public String toUpperCase(Locale locale) { + if (locale == Locale.ENGLISH) { + return toUpperCase(); + } else { + throw new UnsupportedOperationException("toUpperCase("+locale+')'); + } + } + + public String toLowerCase(Locale locale) { + if (locale == Locale.ENGLISH) { + return toLowerCase(); + } else { + throw new UnsupportedOperationException("toLowerCase("+locale+')'); + } + } +} diff --git a/sgx-jvm/avian/classpath/java/lang/StringBuffer.java b/sgx-jvm/avian/classpath/java/lang/StringBuffer.java new file mode 100644 index 0000000000..66ff1051ae --- /dev/null +++ b/sgx-jvm/avian/classpath/java/lang/StringBuffer.java @@ -0,0 +1,159 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.lang; + +public class StringBuffer implements CharSequence { + private final StringBuilder sb; + + public StringBuffer(String s) { + sb = new StringBuilder(s); + } + + public StringBuffer(int capacity) { + sb = new StringBuilder(capacity); + } + + public StringBuffer() { + this(0); + } + + public synchronized StringBuffer append(String s) { + sb.append(s); + return this; + } + + public synchronized StringBuffer append(CharSequence s) { + sb.append(s); + return this; + } + + public synchronized StringBuffer append(StringBuffer s) { + sb.append(s); + return this; + } + + public synchronized StringBuffer append(Object o) { + sb.append(o); + return this; + } + + public synchronized StringBuffer append(char v) { + sb.append(v); + return this; + } + + public synchronized StringBuffer append(boolean v) { + sb.append(v); + return this; + } + + public synchronized StringBuffer append(int v) { + sb.append(v); + return this; + } + + public synchronized StringBuffer append(long v) { + sb.append(v); + return this; + } + + public synchronized StringBuffer append(float v) { + sb.append(v); + return this; + } + + public synchronized StringBuffer append(double v) { + sb.append(v); + return this; + } + + public synchronized StringBuffer append(char[] b, int offset, int length) { + sb.append(b, offset, length); + return this; + } + + public synchronized StringBuffer append(char[] b) { + sb.append(b, 0, b.length); + return this; + } + + public synchronized int indexOf(String s) { + return sb.indexOf(s); + } + + public synchronized int indexOf(String s, int fromIndex) { + return sb.indexOf(s, fromIndex); + } + + public synchronized StringBuffer insert(int i, String s) { + sb.insert(i, s); + return this; + } + + public synchronized StringBuffer insert(int i, char c) { + sb.insert(i, c); + return this; + } + + public synchronized StringBuffer insert(int i, int v) { + sb.insert(i, v); + return this; + } + + public synchronized StringBuffer delete(int start, int end) { + sb.delete(start, end); + return this; + } + + public synchronized StringBuffer deleteCharAt(int i) { + sb.deleteCharAt(i); + return this; + } + + public synchronized char charAt(int i) { + return sb.charAt(i); + } + + public synchronized int length() { + return sb.length(); + } + + public synchronized StringBuffer replace(int start, int end, String str) { + sb.replace(start, end, str); + return this; + } + + public synchronized void setLength(int v) { + sb.setLength(v); + } + + public synchronized void setCharAt(int index, char ch) { + sb.setCharAt(index, ch); + } + + public synchronized void getChars(int srcStart, int srcEnd, char[] dst, + int dstStart) + { + sb.getChars(srcStart, srcEnd, dst, dstStart); + } + + public synchronized String toString() { + return sb.toString(); + } + + public String substring(int start, int end) { + return sb.substring(start, end); + } + + public CharSequence subSequence(int start, int end) { + return sb.subSequence(start, end); + } +} diff --git a/sgx-jvm/avian/classpath/java/lang/StringBuilder.java b/sgx-jvm/avian/classpath/java/lang/StringBuilder.java new file mode 100644 index 0000000000..b5bf4b6725 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/lang/StringBuilder.java @@ -0,0 +1,384 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.lang; + +public class StringBuilder implements CharSequence, Appendable { + private static final int BufferSize = 32; + + private Cell chain; + private int length; + private char[] buffer; + private int position; + + public StringBuilder(String s) { + append(s); + } + + public StringBuilder(int capacity) { } + + public StringBuilder() { + this(0); + } + + private void flush() { + if (position > 0) { + chain = new Cell(new String(buffer, 0, position, false), chain); + buffer = null; + position = 0; + } + } + + public StringBuilder append(String s) { + if (s == null) { + return append("null"); + } else { + if (s.length() > 0) { + if (buffer != null && s.length() <= buffer.length - position) { + s.getChars(0, s.length(), buffer, position); + position += s.length(); + } else { + flush(); + chain = new Cell(s, chain); + } + length += s.length(); + } + return this; + } + } + + public StringBuilder append(StringBuffer sb) { + return append(sb.toString()); + } + + public StringBuilder append(CharSequence sequence) { + return append(sequence.toString()); + } + + public Appendable append(CharSequence sequence, int start, int end) { + return append(sequence.subSequence(start, end)); + } + + public StringBuilder append(char[] b, int offset, int length) { + return append(new String(b, offset, length)); + } + + public StringBuilder append(char[] b) { + return append(new String(b)); + } + + public StringBuilder append(Object o) { + return append(o == null ? "null" : o.toString()); + } + + public StringBuilder append(char v) { + if (buffer == null) { + buffer = new char[BufferSize]; + } else if (position >= buffer.length) { + flush(); + buffer = new char[BufferSize]; + } + + buffer[position++] = v; + ++ length; + + return this; + } + + public StringBuilder append(boolean v) { + return append(String.valueOf(v)); + } + + public StringBuilder append(int v) { + return append(String.valueOf(v)); + } + + public StringBuilder append(long v) { + return append(String.valueOf(v)); + } + + public StringBuilder append(float v) { + return append(String.valueOf(v)); + } + + public StringBuilder append(double v) { + return append(String.valueOf(v)); + } + + public char charAt(int i) { + if (i < 0 || i >= length) { + throw new IndexOutOfBoundsException(); + } + + flush(); + + int index = length; + for (Cell c = chain; c != null; c = c.next) { + int start = index - c.value.length(); + index = start; + + if (i >= start) { + return c.value.charAt(i - start); + } + } + + throw new RuntimeException(); + } + + public StringBuilder insert(int i, String s) { + if (i < 0 || i > length) { + throw new IndexOutOfBoundsException(); + } + + if (i == length) { + append(s); + } else { + flush(); + + int index = length; + for (Cell c = chain; c != null; c = c.next) { + int start = index - c.value.length(); + index = start; + + if (i >= start) { + if (i == start) { + c.next = new Cell(s, c.next); + } else { + String v = c.value; + c.value = v.substring(i - start, v.length()); + c.next = new Cell(s, new Cell(v.substring(0, i - start), c.next)); + } + break; + } + } + + length += s.length(); + } + + return this; + } + + public StringBuilder insert(int i, CharSequence s) { + return insert(i, s.toString()); + } + + public StringBuilder insert(int i, char c) { + return insert(i, new String(new char[] { c }, 0, 1, false)); + } + + public StringBuilder insert(int i, int v) { + return insert(i, String.valueOf(v)); + } + + public StringBuilder delete(int start, int end) { + if (start >= end) { + return this; + } + + if (start < 0 || end > length) { + throw new IndexOutOfBoundsException(); + } + + flush(); + + int index = length; + Cell p = null; + for (Cell c = chain; c != null; c = c.next) { + int e = index; + int s = index - c.value.length(); + index = s; + + if (end >= e) { + if (start <= s) { + if (p == null) { + chain = c.next; + } else { + p.next = c.next; + } + } else { + c.value = c.value.substring(0, start - s); + break; + } + } else { + if (start <= s) { + c.value = c.value.substring(end - s, e - s); + } else { + String v = c.value; + c.value = v.substring(end - s, e - s); + c.next = new Cell(v.substring(0, start - s), c.next); + break; + } + } + } + + length -= (end - start); + + return this; + } + + public StringBuilder deleteCharAt(int i) { + return delete(i, i + 1); + } + + public StringBuilder replace(int start, int end, String str) { + delete(start, end); + insert(start, str); + return this; + } + + public int indexOf(String s) { + return indexOf(s, 0); + } + + public int indexOf(String s, int start) { + int slength = s.length(); + if (slength == 0) return start; + + for (int i = start; i < length - slength + 1; ++i) { + int j = 0; + for (; j < slength; ++j) { + if (charAt(i + j) != s.charAt(j)) { + break; + } + } + if (j == slength) { + return i; + } + } + + return -1; + } + + public int lastIndexOf(String s) { + return lastIndexOf(s, length - s.length()); + } + + public int lastIndexOf(String s, int lastIndex) { + int slength = s.length(); + if (slength == 0) return lastIndex; + + for (int i = Math.min(length - slength, lastIndex); i >= 0; --i) { + int j = 0; + for (; j < slength && i + j < length; ++j) { + if (charAt(i + j) != s.charAt(j)) { + break; + } + } + if (j == slength) { + return i; + } + } + + return -1; + } + + public int length() { + return length; + } + + public void setLength(int v) { + if (v < 0) { + throw new IndexOutOfBoundsException(); + } + + if (v == 0) { + length = 0; + chain = null; + return; + } + + flush(); + + int index = length; + length = v; + for (Cell c = chain; c != null; c = c.next) { + int start = index - c.value.length(); + + if (v > start) { + if (v < index) { + c.value = c.value.substring(0, v - start); + } + break; + } + + chain = c.next; + index = start; + } + } + + public void getChars(int srcStart, int srcEnd, char[] dst, int dstStart) { + if (srcStart < 0 || srcEnd > length) { + throw new IndexOutOfBoundsException(); + } + + flush(); + + int index = length; + for (Cell c = chain; c != null; c = c.next) { + int start = index - c.value.length(); + int end = index; + index = start; + + if (start < srcStart) { + start = srcStart; + } + + if (end > srcEnd) { + end = srcEnd; + } + + if (start < end) { + c.value.getChars(start - index, end - index, + dst, dstStart + (start - srcStart)); + } + } + } + + public String toString() { + char[] array = new char[length]; + getChars(0, length, array, 0); + return new String(array, 0, length, false); + } + + private static class Cell { + public String value; + public Cell next; + + public Cell(String value, Cell next) { + this.value = value; + this.next = next; + } + } + + public String substring(int start) { + return substring(start, length); + } + + public String substring(int start, int end) { + int len = end-start; + char[] buf = new char[len]; + getChars(start, end, buf, 0); + return new String(buf, 0, len, false); + } + + public CharSequence subSequence(int start, int end) { + return substring(start, end); + } + + public void setCharAt(int index, char ch) { + if(index < 0 || index >= length) throw new IndexOutOfBoundsException(); + deleteCharAt(index); + insert(index, ch); + } + + public void ensureCapacity(int capacity) { + // ignore + } +} diff --git a/sgx-jvm/avian/classpath/java/lang/StringIndexOutOfBoundsException.java b/sgx-jvm/avian/classpath/java/lang/StringIndexOutOfBoundsException.java new file mode 100644 index 0000000000..b66d9ae43d --- /dev/null +++ b/sgx-jvm/avian/classpath/java/lang/StringIndexOutOfBoundsException.java @@ -0,0 +1,29 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.lang; + +/** + * Used by String to signal that a given index is either less than + * or greater than the allowed range. + */ +public class StringIndexOutOfBoundsException extends IndexOutOfBoundsException { + private static final long serialVersionUID = -6762910422159637258L; + + public StringIndexOutOfBoundsException(int index) { + super("String index out of range: "+index); + } + + public StringIndexOutOfBoundsException(String message) { + super(message); + } + + public StringIndexOutOfBoundsException() {} +} diff --git a/sgx-jvm/avian/classpath/java/lang/SuppressWarnings.java b/sgx-jvm/avian/classpath/java/lang/SuppressWarnings.java new file mode 100644 index 0000000000..fd73e8f4c7 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/lang/SuppressWarnings.java @@ -0,0 +1,16 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.lang; + + +public @interface SuppressWarnings { + String[] value(); +} diff --git a/sgx-jvm/avian/classpath/java/lang/System.java b/sgx-jvm/avian/classpath/java/lang/System.java new file mode 100644 index 0000000000..f6ceabad6b --- /dev/null +++ b/sgx-jvm/avian/classpath/java/lang/System.java @@ -0,0 +1,168 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.lang; + +import java.io.PrintStream; +import java.io.InputStream; +import java.io.BufferedInputStream; +import java.io.BufferedOutputStream; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.FileDescriptor; +import java.util.Map; +import java.util.Hashtable; +import java.util.Properties; + +public abstract class System { + private static class NanoTime { + public static final long BaseInMillis = currentTimeMillis(); + } + + private static class Static { + public static Properties properties = makeProperties(); + } + + private static Map environment; + + private static SecurityManager securityManager; + // static { + // loadLibrary("natives"); + // } + + public static final PrintStream out = new PrintStream + (new BufferedOutputStream(new FileOutputStream(FileDescriptor.out)), true); + + public static final PrintStream err = new PrintStream + (new BufferedOutputStream(new FileOutputStream(FileDescriptor.err)), true); + + public static final InputStream in + = new BufferedInputStream(new FileInputStream(FileDescriptor.in)); + + public static native void arraycopy(Object src, int srcOffset, Object dst, + int dstOffset, int length); + + public static String getProperty(String name) { + return (String) Static.properties.get(name); + } + + public static String getProperty(String name, String defaultValue) { + String result = getProperty(name); + if (result==null) { + return defaultValue; + } + return result; + } + + public static String setProperty(String name, String value) { + return (String) Static.properties.put(name, value); + } + + public static Properties getProperties() { + return Static.properties; + } + + private static Properties makeProperties() { + Properties properties = new Properties(); + + for (String p: getNativeProperties()) { + if (p == null) break; + int index = p.indexOf('='); + properties.put(p.substring(0, index), p.substring(index + 1)); + } + + for (String p: getVMProperties()) { + if (p == null) break; + int index = p.indexOf('='); + properties.put(p.substring(0, index), p.substring(index + 1)); + } + + return properties; + } + + private static native String[] getNativeProperties(); + + private static native String[] getVMProperties(); + + public static native long currentTimeMillis(); + + public static native int identityHashCode(Object o); + + public static long nanoTime() { + return (currentTimeMillis() - NanoTime.BaseInMillis) * 1000000; + } + + public static String mapLibraryName(String name) { + if (name != null) { + return doMapLibraryName(name); + } else { + throw new NullPointerException(); + } + } + + private static native String doMapLibraryName(String name); + + public static void load(String path) { + ClassLoader.load(path, ClassLoader.getCaller(), false); + } + + public static void loadLibrary(String name) { + ClassLoader.load(name, ClassLoader.getCaller(), true); + } + + public static void gc() { + Runtime.getRuntime().gc(); + } + + public static void exit(int code) { + Runtime.getRuntime().exit(code); + } + + public static SecurityManager getSecurityManager() { + return securityManager; + } + + public static void setSecurityManager(SecurityManager securityManager) { + System.securityManager = securityManager; + } + + public static String getenv(String name) throws NullPointerException, + SecurityException { + if (getSecurityManager() != null) { // is this allowed? + getSecurityManager(). + checkPermission(new RuntimePermission("getenv." + name)); + } + return getenv().get(name); + } + + public static Map getenv() throws SecurityException { + if (getSecurityManager() != null) { // is this allowed? + getSecurityManager().checkPermission(new RuntimePermission("getenv.*")); + } + + if (environment == null) { // build environment table + String[] vars = getEnvironment(); + environment = new Hashtable(vars.length); + for (String var : vars) { // parse name-value pairs + int equalsIndex = var.indexOf('='); + // null names and values are forbidden + if (equalsIndex != -1 && equalsIndex < var.length() - 1) { + environment.put(var.substring(0, equalsIndex), + var.substring(equalsIndex + 1)); + } + } + } + + return environment; + } + + /** Returns the native process environment. */ + private static native String[] getEnvironment(); +} diff --git a/sgx-jvm/avian/classpath/java/lang/Thread.java b/sgx-jvm/avian/classpath/java/lang/Thread.java new file mode 100644 index 0000000000..0dea70aae4 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/lang/Thread.java @@ -0,0 +1,311 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.lang; + +import java.util.Map; +import java.util.WeakHashMap; + +public class Thread implements Runnable { + // set and accessed from within LockSupport + protected volatile Object parkBlocker; + + private long peer; + private volatile boolean interrupted; + private volatile boolean unparked; + private boolean daemon; + private byte state; + private byte priority; + private final Runnable task; + private Map locals; + private Object sleepLock; + private ClassLoader classLoader; + private UncaughtExceptionHandler exceptionHandler; + private String name; + private ThreadGroup group; + + private static UncaughtExceptionHandler defaultExceptionHandler; + + public static final int MIN_PRIORITY = 1; + public static final int NORM_PRIORITY = 5; + public static final int MAX_PRIORITY = 10; + + public Thread(ThreadGroup group, Runnable task, String name, long stackSize) + { + this.group = (group == null ? Thread.currentThread().group : group); + this.task = task; + this.name = name; + + Thread current = currentThread(); + + Map map = current.locals; + if (map != null) { + for (Map.Entry e: map.entrySet()) { + if (e.getKey() instanceof InheritableThreadLocal) { + InheritableThreadLocal itl = (InheritableThreadLocal) e.getKey(); + locals().put(itl, itl.childValue(e.getValue())); + } + } + } + + classLoader = current.classLoader; + } + + public Thread(ThreadGroup group, Runnable task, String name) { + this(group, task, name, 0); + } + + public Thread(ThreadGroup group, String name) { + this(null, null, name); + } + + public Thread(Runnable task, String name) { + this(null, task, name); + } + + public Thread(Runnable task) { + this(null, task, "Thread["+task+"]"); + } + + public Thread(String name) { + this(null, null, name); + } + + public Thread() { + this((Runnable) null); + } + + public synchronized void start() { + if (peer != 0) { + throw new IllegalStateException("thread already started"); + } + + state = (byte) State.RUNNABLE.ordinal(); + + peer = doStart(); + if (peer == 0) { + state = (byte) State.NEW.ordinal(); + throw new RuntimeException("unable to start native thread"); + } + } + + private native long doStart(); + + private static void run(Thread t) throws Throwable { + try { + t.run(); + } catch (Throwable e) { + UncaughtExceptionHandler eh = t.exceptionHandler; + UncaughtExceptionHandler deh = defaultExceptionHandler; + if (eh != null) { + eh.uncaughtException(t, e); + } else if (deh != null) { + deh.uncaughtException(t, e); + } else { + throw e; + } + } finally { + synchronized (t) { + t.state = (byte) State.TERMINATED.ordinal(); + t.notifyAll(); + } + } + } + + public void run() { + if (task != null) { + task.run(); + } + } + + public ClassLoader getContextClassLoader() { + return classLoader; + } + + public void setContextClassLoader(ClassLoader v) { + classLoader = v; + } + + public Map locals() { + if (locals == null) { + locals = new WeakHashMap(); + } + return locals; + } + + public static native Thread currentThread(); + + public void interrupt() { + interrupt(peer); + } + + private static native boolean interrupt(long peer); + + public static boolean interrupted() { + return interrupted(currentThread().peer); + } + + private static native boolean interrupted(long peer); + + public boolean isInterrupted() { + return interrupted; + } + + public static void sleep(long milliseconds) throws InterruptedException { + if (milliseconds <= 0) { + milliseconds = 1; + } + + Thread t = currentThread(); + if (t.sleepLock == null) { + t.sleepLock = new Object(); + } + synchronized (t.sleepLock) { + t.sleepLock.wait(milliseconds); + } + } + + public static void sleep(long milliseconds, int nanoseconds) + throws InterruptedException + { + if (nanoseconds > 0) { + ++ milliseconds; + } + + sleep(milliseconds); + } + + public StackTraceElement[] getStackTrace() { + long p = peer; + if (p == 0) { + return new StackTraceElement[0]; + } + return Throwable.resolveTrace(getStackTrace(p)); + } + + private static native Object getStackTrace(long peer); + + public static native int activeCount(); + + public static native int enumerate(Thread[] array); + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public UncaughtExceptionHandler getUncaughtExceptionHandler() { + UncaughtExceptionHandler eh = exceptionHandler; + return (eh == null ? group : eh); + } + + public static UncaughtExceptionHandler getDefaultUncaughtExceptionHandler() { + return defaultExceptionHandler; + } + + public void setUncaughtExceptionHandler(UncaughtExceptionHandler h) { + exceptionHandler = h; + } + + public static void setDefaultUncaughtExceptionHandler + (UncaughtExceptionHandler h) + { + defaultExceptionHandler = h; + } + + public State getState() { + return State.values()[state]; + } + + public boolean isAlive() { + switch (getState()) { + case NEW: + case TERMINATED: + return false; + + default: + return true; + } + } + + public int getPriority() { + return priority; + } + + public void setPriority(int priority) { + if (priority < MIN_PRIORITY || priority > MAX_PRIORITY) { + throw new IllegalArgumentException(); + } + this.priority = (byte) priority; + } + + public boolean isDaemon() { + return daemon; + } + + public synchronized void setDaemon(boolean v) { + if (getState() != State.NEW) { + throw new IllegalStateException(); + } + + daemon = v; + } + + public static native void yield(); + + public synchronized void join() throws InterruptedException { + while (getState() != State.TERMINATED) { + wait(); + } + } + + public synchronized void join(long milliseconds) throws InterruptedException + { + long then = System.currentTimeMillis(); + long remaining = milliseconds; + while (remaining > 0 && getState() != State.TERMINATED) { + wait(remaining); + + remaining = milliseconds - (System.currentTimeMillis() - then); + } + } + + public void join(long milliseconds, int nanoseconds) + throws InterruptedException + { + if (nanoseconds > 0) { + ++ milliseconds; + } + + join(milliseconds); + } + + public ThreadGroup getThreadGroup() { + return group; + } + + public static native boolean holdsLock(Object o); + + public long getId() { + return peer; + } + + public interface UncaughtExceptionHandler { + public void uncaughtException(Thread t, Throwable e); + } + + public enum State { + NEW, RUNNABLE, BLOCKED, WAITING, TIMED_WAITING, TERMINATED + } + +} diff --git a/sgx-jvm/avian/classpath/java/lang/ThreadDeath.java b/sgx-jvm/avian/classpath/java/lang/ThreadDeath.java new file mode 100644 index 0000000000..31711ca64a --- /dev/null +++ b/sgx-jvm/avian/classpath/java/lang/ThreadDeath.java @@ -0,0 +1,15 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.lang; + +public class ThreadDeath extends Error { + public ThreadDeath() { } +} diff --git a/sgx-jvm/avian/classpath/java/lang/ThreadGroup.java b/sgx-jvm/avian/classpath/java/lang/ThreadGroup.java new file mode 100644 index 0000000000..0aef6ed6a4 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/lang/ThreadGroup.java @@ -0,0 +1,117 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.lang; + +import avian.Cell; + +public class ThreadGroup implements Thread.UncaughtExceptionHandler { + private final ThreadGroup parent; + private final String name; + private Cell subgroups; + + public ThreadGroup(ThreadGroup parent, String name) { + this.parent = parent; + this.name = name; + + synchronized (parent) { + parent.subgroups = new Cell(this, subgroups); + } + } + + public ThreadGroup(String name) { + this(Thread.currentThread().getThreadGroup(), name); + } + + public void uncaughtException(Thread t, Throwable e) { + if (parent != null) { + parent.uncaughtException(t, e); + } else { + Thread.UncaughtExceptionHandler deh + = Thread.getDefaultUncaughtExceptionHandler(); + if (deh != null) { + deh.uncaughtException(t, e); + } else if (! (e instanceof ThreadDeath)) { + e.printStackTrace(); + } + } + } + + public ThreadGroup getParent() { + return parent; + } + + public String getName() { + return name; + } + + public int activeCount() { + int allCount = Thread.activeCount(); + Thread[] all = new Thread[allCount]; + allCount = Thread.enumerate(all); + + int count = 0; + for (int i = 0; i < allCount; ++i) { + if (parentOf(all[i].getThreadGroup())) { + ++ count; + } + } + + return count; + } + + public int enumerate(Thread[] threads) { + return enumerate(threads, true); + } + + public int enumerate(Thread[] threads, boolean recurse) { + int allCount = Thread.activeCount(); + Thread[] all = new Thread[allCount]; + allCount = Thread.enumerate(all); + + int count = 0; + for (int i = 0; i < allCount && count < threads.length; ++i) { + Thread t = all[i]; + ThreadGroup g = t.getThreadGroup(); + if (g == this || (recurse && parentOf(g))) { + threads[count++] = t; + } + } + + return count; + } + + public boolean parentOf(ThreadGroup g) { + for (; g != null; g = g.parent) { + if (g == this) { + return true; + } + } + + return false; + } + + public int enumerate(ThreadGroup[] groups, boolean recurse) { + return enumerate(groups, recurse, 0); + } + + private int enumerate(ThreadGroup[] groups, boolean recurse, int count) { + for (Cell c = subgroups; c != null && count < groups.length; + c = c.next) + { + ThreadGroup g = c.value; + groups[count++] = g; + if (recurse) { + count = g.enumerate(groups, true, count); + } + } + return count; + } +} diff --git a/sgx-jvm/avian/classpath/java/lang/ThreadLocal.java b/sgx-jvm/avian/classpath/java/lang/ThreadLocal.java new file mode 100644 index 0000000000..b15112a742 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/lang/ThreadLocal.java @@ -0,0 +1,46 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.lang; + +import java.util.Map; + +public class ThreadLocal { + private static final Object Null = new Object(); + + protected T initialValue() { + return null; + } + + public T get() { + Map map = Thread.currentThread().locals(); + Object o = map.get(this); + if (o == null) { + o = initialValue(); + if (o == null) { + o = Null; + } + map.put(this, o); + } + if (o == Null) { + o = null; + } + return (T) o; + } + + public void set(T value) { + Map map = Thread.currentThread().locals(); + Object o = value; + if (o == null) { + o = Null; + } + map.put(this, o); + } +} diff --git a/sgx-jvm/avian/classpath/java/lang/Throwable.java b/sgx-jvm/avian/classpath/java/lang/Throwable.java new file mode 100644 index 0000000000..57c42290f1 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/lang/Throwable.java @@ -0,0 +1,129 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.lang; + +import java.io.PrintStream; +import java.io.PrintWriter; +import java.io.Serializable; + +public class Throwable implements Serializable { + private String message; + private Object trace; + private Throwable cause; + + public Throwable(String message, Throwable cause) { + this.message = message; + this.trace = trace(1); + this.cause = cause; + } + + public Throwable(String message) { + this(message, null); + } + + public Throwable(Throwable cause) { + this(null, cause); + } + + public Throwable() { + this(null, null); + } + + public Throwable getCause() { + return cause; + } + + public Throwable initCause(Throwable e) { + if (cause == null) { + cause = e; + return this; + } else { + throw new IllegalStateException(); + } + } + + public String getMessage() { + return message; + } + + public String getLocalizedMessage() { + return getMessage(); + } + + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append(getClass().getName()); + if (message != null) { + sb.append(": ").append(message); + } + return sb.toString(); + } + + private static native Object trace(int skipCount); + + static native StackTraceElement[] resolveTrace(Object trace); + + private StackTraceElement[] resolveTrace() { + if (! (trace instanceof StackTraceElement[])) { + trace = resolveTrace(trace); + } + return (StackTraceElement[]) trace; + } + + public StackTraceElement[] getStackTrace() { + return resolveTrace(); + } + + public void setStackTrace(StackTraceElement[] trace) { + this.trace = trace; + } + + public void printStackTrace(PrintStream out) { + StringBuilder sb = new StringBuilder(); + printStackTrace(sb, System.getProperty("line.separator")); + out.print(sb.toString()); + out.flush(); + } + + public void printStackTrace(PrintWriter out) { + StringBuilder sb = new StringBuilder(); + printStackTrace(sb, System.getProperty("line.separator")); + out.print(sb.toString()); + out.flush(); + } + + public void printStackTrace() { + printStackTrace(System.err); + } + + private void printStackTrace(StringBuilder sb, String nl) { + sb.append(toString()).append(nl); + + StackTraceElement[] trace = resolveTrace(); + for (int i = 0; i < trace.length; ++i) { + sb.append(" at ").append(trace[i].toString()).append(nl); + } + + Throwable printCause = getCause(); + if (printCause != null) { + sb.append("caused by: "); + printCause.printStackTrace(sb, nl); + } + } + + public Throwable fillInStackTrace() { + trace = trace(0); + return this; + } + + public void addSuppressed(Throwable exception) { + } +} diff --git a/sgx-jvm/avian/classpath/java/lang/TypeNotPresentException.java b/sgx-jvm/avian/classpath/java/lang/TypeNotPresentException.java new file mode 100644 index 0000000000..eb1f31ed73 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/lang/TypeNotPresentException.java @@ -0,0 +1,21 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.lang; + +public class TypeNotPresentException extends Exception { + public TypeNotPresentException(String message) { + super(message); + } + + public TypeNotPresentException() { + this(null); + } +} diff --git a/sgx-jvm/avian/classpath/java/lang/UnsatisfiedLinkError.java b/sgx-jvm/avian/classpath/java/lang/UnsatisfiedLinkError.java new file mode 100644 index 0000000000..9c94470345 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/lang/UnsatisfiedLinkError.java @@ -0,0 +1,21 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.lang; + +public class UnsatisfiedLinkError extends LinkageError { + public UnsatisfiedLinkError(String message) { + super(message); + } + + public UnsatisfiedLinkError() { + this(null); + } +} diff --git a/sgx-jvm/avian/classpath/java/lang/UnsupportedOperationException.java b/sgx-jvm/avian/classpath/java/lang/UnsupportedOperationException.java new file mode 100644 index 0000000000..4e5edb1cd4 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/lang/UnsupportedOperationException.java @@ -0,0 +1,29 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.lang; + +public class UnsupportedOperationException extends RuntimeException { + public UnsupportedOperationException(String message, Throwable cause) { + super(message, cause); + } + + public UnsupportedOperationException(String message) { + this(message, null); + } + + public UnsupportedOperationException(Throwable cause) { + this(null, cause); + } + + public UnsupportedOperationException() { + this(null, null); + } +} diff --git a/sgx-jvm/avian/classpath/java/lang/VirtualMachineError.java b/sgx-jvm/avian/classpath/java/lang/VirtualMachineError.java new file mode 100644 index 0000000000..3ad721dc22 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/lang/VirtualMachineError.java @@ -0,0 +1,21 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.lang; + +public class VirtualMachineError extends Error { + public VirtualMachineError(String message) { + super(message); + } + + public VirtualMachineError() { + this(null); + } +} diff --git a/sgx-jvm/avian/classpath/java/lang/Void.java b/sgx-jvm/avian/classpath/java/lang/Void.java new file mode 100644 index 0000000000..d721269f02 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/lang/Void.java @@ -0,0 +1,17 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.lang; + +public final class Void { + public static final Class TYPE = avian.Classes.forCanonicalName("V"); + + private Void() { } +} diff --git a/sgx-jvm/avian/classpath/java/lang/annotation/Annotation.java b/sgx-jvm/avian/classpath/java/lang/annotation/Annotation.java new file mode 100644 index 0000000000..238abeb47e --- /dev/null +++ b/sgx-jvm/avian/classpath/java/lang/annotation/Annotation.java @@ -0,0 +1,15 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.lang.annotation; + +public interface Annotation { + Class annotationType(); +} diff --git a/sgx-jvm/avian/classpath/java/lang/annotation/ElementType.java b/sgx-jvm/avian/classpath/java/lang/annotation/ElementType.java new file mode 100644 index 0000000000..36e62e08f6 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/lang/annotation/ElementType.java @@ -0,0 +1,22 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.lang.annotation; + +public enum ElementType { + ANNOTATION_TYPE, + CONSTRUCTOR, + FIELD, + LOCAL_VARIABLE, + METHOD, + PACKAGE, + PARAMETER, + TYPE +} diff --git a/sgx-jvm/avian/classpath/java/lang/annotation/Retention.java b/sgx-jvm/avian/classpath/java/lang/annotation/Retention.java new file mode 100644 index 0000000000..71db2d5f95 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/lang/annotation/Retention.java @@ -0,0 +1,16 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.lang.annotation; + +@Retention(RetentionPolicy.RUNTIME) +public @interface Retention { + public RetentionPolicy value(); +} diff --git a/sgx-jvm/avian/classpath/java/lang/annotation/RetentionPolicy.java b/sgx-jvm/avian/classpath/java/lang/annotation/RetentionPolicy.java new file mode 100644 index 0000000000..aa8f20f02a --- /dev/null +++ b/sgx-jvm/avian/classpath/java/lang/annotation/RetentionPolicy.java @@ -0,0 +1,15 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.lang.annotation; + +public enum RetentionPolicy { + CLASS, RUNTIME, SOURCE +} diff --git a/sgx-jvm/avian/classpath/java/lang/annotation/Target.java b/sgx-jvm/avian/classpath/java/lang/annotation/Target.java new file mode 100644 index 0000000000..d4dfb88f84 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/lang/annotation/Target.java @@ -0,0 +1,17 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.lang.annotation; + +@Retention(value=RetentionPolicy.RUNTIME) +@Target(value=ElementType.ANNOTATION_TYPE) +public @interface Target { + public ElementType[] value(); +} diff --git a/sgx-jvm/avian/classpath/java/lang/invoke/CallSite.java b/sgx-jvm/avian/classpath/java/lang/invoke/CallSite.java new file mode 100644 index 0000000000..806ac6e5ee --- /dev/null +++ b/sgx-jvm/avian/classpath/java/lang/invoke/CallSite.java @@ -0,0 +1,19 @@ +/* Copyright (c) 2008-2016, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.lang.invoke; + +public class CallSite { + private final MethodHandle target; + + CallSite(MethodHandle target) { + this.target = target; + } +} diff --git a/sgx-jvm/avian/classpath/java/lang/invoke/LambdaConversionException.java b/sgx-jvm/avian/classpath/java/lang/invoke/LambdaConversionException.java new file mode 100644 index 0000000000..bbc4aa131c --- /dev/null +++ b/sgx-jvm/avian/classpath/java/lang/invoke/LambdaConversionException.java @@ -0,0 +1,19 @@ +/* Copyright (c) 2008-2016, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.lang.invoke; + +public class LambdaConversionException extends java.lang.Exception { + public LambdaConversionException() { throw new RuntimeException(); } + public LambdaConversionException(String s) { throw new RuntimeException(); } + public LambdaConversionException(String s, Throwable th) { throw new RuntimeException(); } + public LambdaConversionException(Throwable th) { throw new RuntimeException(); } + public LambdaConversionException(String s, Throwable th, boolean b, boolean b2) { throw new RuntimeException(); } +} diff --git a/sgx-jvm/avian/classpath/java/lang/invoke/LambdaMetafactory.java b/sgx-jvm/avian/classpath/java/lang/invoke/LambdaMetafactory.java new file mode 100644 index 0000000000..4eb5cf771a --- /dev/null +++ b/sgx-jvm/avian/classpath/java/lang/invoke/LambdaMetafactory.java @@ -0,0 +1,410 @@ +/* Copyright (c) 2008-2016, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.lang.invoke; + +import static avian.Stream.write1; +import static avian.Stream.write2; +import static avian.Stream.write4; +import static avian.Stream.set4; +import static avian.Assembler.*; + +import java.lang.reflect.Proxy; +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Modifier; +import java.util.Arrays; +import java.util.List; +import java.util.ArrayList; +import java.io.ByteArrayOutputStream; +import java.io.IOException; + +import avian.Classes; +import avian.ConstantPool; +import avian.Assembler; +import avian.ConstantPool.PoolEntry; +import avian.SystemClassLoader; + +// To understand what this is all about, please read: +// +// http://cr.openjdk.java.net/~briangoetz/lambda/lambda-translation.html + +public class LambdaMetafactory { + private static int nextNumber = 0; + + public static final int FLAG_SERIALIZABLE = 1; + public static final int FLAG_MARKERS = 2; + public static final int FLAG_BRIDGES = 4; + + private static Class resolveReturnInterface(MethodType type) { + int index = 1; + byte[] s = type.spec; + + while (s[index] != ')') ++ index; + + if (s[++ index] != 'L') throw new AssertionError(); + + ++ index; + + int end = index + 1; + while (s[end] != ';') ++ end; + + Class c = SystemClassLoader.getClass + (Classes.loadVMClass(type.loader, s, index, end - index)); + + if (! c.isInterface()) throw new AssertionError(); + + return c; + } + + private static int indexOf(int c, byte[] array) { + int i = 0; + while (array[i] != c) ++i; + return i; + } + + private static String constructorSpec(MethodType type) { + return Classes.makeString(type.spec, 0, indexOf(')', type.spec) + 1) + "V"; + } + + private static byte[] makeFactoryCode(List pool, + String className, + String constructorSpec, + MethodType type) + throws IOException + { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + write2(out, type.footprint() + 2); // max stack + write2(out, type.footprint()); // max locals + write4(out, 0); // length (we'll set the real value later) + + write1(out, new_); + write2(out, ConstantPool.addClass(pool, className) + 1); + write1(out, dup); + + for (MethodType.Parameter p: type.parameters()) { + write1(out, p.load()); + write1(out, p.position()); + } + + write1(out, invokespecial); + write2(out, ConstantPool.addMethodRef + (pool, className, "", constructorSpec) + 1); + + write1(out, areturn); + + write2(out, 0); // exception handler table length + write2(out, 0); // attribute count + + byte[] result = out.toByteArray(); + set4(result, 4, result.length - 12); + + return result; + } + + private static byte[] makeConstructorCode(List pool, + String className, + MethodType type) + throws IOException + { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + write2(out, 3); // max stack + write2(out, type.footprint() + 1); // max locals + write4(out, 0); // length (we'll set the real value later) + + write1(out, aload_0); + write1(out, invokespecial); + write2(out, ConstantPool.addMethodRef + (pool, "java/lang/Object", "", "()V") + 1); + + for (MethodType.Parameter p: type.parameters()) { + write1(out, aload_0); + write1(out, p.load()); + write1(out, p.position() + 1); + write1(out, putfield); + write2(out, ConstantPool.addFieldRef + (pool, className, "field" + p.index(), p.spec()) + 1); + } + + write1(out, return_); + + write2(out, 0); // exception handler table length + write2(out, 0); // attribute count + + byte[] result = out.toByteArray(); + set4(result, 4, result.length - 12); + + return result; + } + + private static byte[] makeInvocationCode(List pool, + String className, + String constructorSpec, + MethodType fieldType, + MethodType localType, + MethodHandle implementation) + throws IOException + { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + write2(out, fieldType.footprint() + + localType.footprint() + 2); // max stack + write2(out, localType.footprint() + 1); // max locals + write4(out, 0); // length (we'll set the real value later) + + write1(out, aload_0); + + for (MethodType.Parameter p: fieldType.parameters()) { + write1(out, aload_0); + write1(out, getfield); + write2(out, ConstantPool.addFieldRef + (pool, className, "field" + p.index(), p.spec()) + 1); + } + + for (MethodType.Parameter p: localType.parameters()) { + write1(out, p.load()); + write1(out, p.position() + 1); + } + + switch (implementation.kind) { + case MethodHandle.REF_invokeStatic: + write1(out, invokestatic); + break; + + case MethodHandle.REF_invokeSpecial: + write1(out, invokespecial); + break; + + default: throw new AssertionError + ("todo: implement per http://docs.oracle.com/javase/specs/jvms/se8/html/jvms-5.html#jvms-5.4.3.5"); + } + + write2(out, ConstantPool.addMethodRef + (pool, + Classes.makeString(implementation.method.class_.name, 0, + implementation.method.class_.name.length - 1), + Classes.makeString(implementation.method.name, 0, + implementation.method.name.length - 1), + Classes.makeString(implementation.method.spec, 0, + implementation.method.spec.length - 1)) + 1); + + write1(out, implementation.type().result().return_()); + + write2(out, 0); // exception handler table length + write2(out, 0); // attribute count + + byte[] result = out.toByteArray(); + set4(result, 4, result.length - 12); + + return result; + } + + public static byte[] makeLambda(String invokedName, + String invokedType, + String methodType, + String implementationClass, + String implementationName, + String implementationSpec, + int implementationKind) + { + return makeLambda(invokedName, + new MethodType(invokedType), + new MethodType(methodType), + new MethodHandle(implementationClass, + implementationName, + implementationSpec, + implementationKind), + emptyInterfaceList); + } + + private static byte[] makeLambda(String invokedName, + MethodType invokedType, + MethodType methodType, + MethodHandle methodImplementation, + Class[] interfaces) + { + String className; + { int number; + synchronized (LambdaMetafactory.class) { + number = nextNumber++; + } + className = "Lambda-" + number; + } + + List pool = new ArrayList(); + + int[] interfaceIndexes = new int[interfaces.length + 1]; + interfaceIndexes[0] = ConstantPool.addClass(pool, invokedType.returnType().getName().replace('.', '/')); + for (int i = 0; i < interfaces.length; i++) { + String name = interfaces[i].getName().replace('.', '/'); + interfaceIndexes[i + 1] = ConstantPool.addClass(pool, name); + } + + List fieldTable = new ArrayList(); + + for (MethodType.Parameter p: invokedType.parameters()) { + fieldTable.add + (new FieldData(0, + ConstantPool.addUtf8(pool, "field" + p.index()), + ConstantPool.addUtf8(pool, p.spec()))); + } + + String constructorSpec = constructorSpec(invokedType); + + List methodTable = new ArrayList(); + + try { + methodTable.add + (new MethodData + (Modifier.PUBLIC | Modifier.STATIC, + ConstantPool.addUtf8(pool, "make"), + ConstantPool.addUtf8(pool, invokedType.toMethodDescriptorString()), + makeFactoryCode(pool, className, constructorSpec, invokedType))); + + methodTable.add + (new MethodData + (Modifier.PUBLIC, + ConstantPool.addUtf8(pool, ""), + ConstantPool.addUtf8(pool, constructorSpec), + makeConstructorCode(pool, className, invokedType))); + + methodTable.add + (new MethodData + (Modifier.PUBLIC, + ConstantPool.addUtf8(pool, invokedName), + ConstantPool.addUtf8(pool, methodType.toMethodDescriptorString()), + makeInvocationCode(pool, className, constructorSpec, invokedType, + methodType, methodImplementation))); + } catch (IOException e) { + AssertionError error = new AssertionError(); + error.initCause(e); + throw error; + } + + int nameIndex = ConstantPool.addClass(pool, className); + int superIndex = ConstantPool.addClass(pool, "java/lang/Object"); + + ByteArrayOutputStream out = new ByteArrayOutputStream(); + try { + Assembler.writeClass + (out, pool, nameIndex, superIndex, interfaceIndexes, + fieldTable.toArray(new FieldData[fieldTable.size()]), + methodTable.toArray(new MethodData[methodTable.size()])); + } catch (IOException e) { + AssertionError error = new AssertionError(); + error.initCause(e); + throw error; + } + + return out.toByteArray(); + } + + private static CallSite makeCallSite(MethodType invokedType, byte[] classData) throws AssertionError { + try { + return new CallSite + (new MethodHandle + (MethodHandle.REF_invokeStatic, invokedType.loader, Classes.toVMMethod + (avian.SystemClassLoader.getClass + (avian.Classes.defineVMClass + (invokedType.loader, classData, 0, classData.length)) + .getMethod("make", invokedType.parameterArray())))); + } catch (NoSuchMethodException e) { + AssertionError error = new AssertionError(); + error.initCause(e); + throw error; + } + } + + private static final Class[] emptyInterfaceList = new Class[] {}; + + public static CallSite metafactory(MethodHandles.Lookup caller, + String invokedName, + MethodType invokedType, + MethodType methodType, + MethodHandle methodImplementation, + MethodType instantiatedMethodType) + throws LambdaConversionException + { + byte[] classData = makeLambda(invokedName, invokedType, methodType, methodImplementation, emptyInterfaceList); + return makeCallSite(invokedType, classData); + } + + public static CallSite altMetafactory(MethodHandles.Lookup caller, + String invokedName, + MethodType invokedType, + Object... args) throws LambdaConversionException { + // See openjdk8/jdk/src/share/classes/java/lang/invoke/LambdaMetafactory.java + // Behaves as if the prototype is like this: + // + // CallSite altMetafactory( + // MethodHandles.Lookup caller, + // String invokedName, + // MethodType invokedType, + // MethodType methodType, + // MethodHandle methodImplementation, + // MethodType instantiatedMethodType, + // int flags, + // int markerInterfaceCount, // IF flags has MARKERS set + // Class... markerInterfaces, // IF flags has MARKERS set + // int bridgeCount, // IF flags has BRIDGES set + // MethodType... bridges // IF flags has BRIDGES set + // ) + MethodType methodType = (MethodType) args[0]; + MethodHandle methodImplementation = (MethodHandle) args[1]; + + int flags = (Integer) args[3]; + boolean serializable = (flags & FLAG_SERIALIZABLE) != 0; + + // Marker interfaces are added to a lambda when they're written like this: + // + // Runnable r = (Runnable & Serializable) () -> foo() + // + // The intersection type in the cast here indicates to the compiler what interfaces + // the generated lambda class should implement. Because a lambda has (by definition) + // one method only, it is meaningless for these interfaces to contain anything, thus + // they are only allowed to be empty marker interfaces. In practice the Serializable + // interface is handled specially and the use of markers is extremely rare. Adding + // support would be easy though. + if ((flags & FLAG_MARKERS) != 0) + throw new UnsupportedOperationException("Marker interfaces on lambdas are not supported on Avian yet. Sorry."); + + // In some cases there is a mismatch between what the JVM type system supports and + // what the Java language supports. In other cases the type of a lambda expression + // may not perfectly match the functional interface which represents it. Consider the + // following case: + // + // interface I { void foo(Integer i, String s1, Strings s2) } + // class Foo { static void m(Number i, Object... rest) {} } + // + // I lambda = Foo::m + // + // This is allowed by the Java language, even though the interface representing the + // lambda specifies three specific arguments and the method implementing the lambda + // uses varargs and a different type signature. Behind the scenes the compiler generates + // a "bridge" method that does the adaptation. + // + // You can learn more here: http://www.oracle.com/technetwork/java/jvmls2013heid-2013922.pdf + // and here: http://cr.openjdk.java.net/~briangoetz/lambda/lambda-translation.html + if ((flags & FLAG_BRIDGES) != 0) { + int bridgeCount = (Integer) args[4]; + if (bridgeCount > 0) + throw new UnsupportedOperationException("A lambda that requires bridge methods was used, this is not yet supported by Avian. Sorry."); + } + + // TODO: This is not necessary if the function type interface is already inheriting + // from Serializable. + Class[] interfaces = new Class[serializable ? 1 : 0]; + if (serializable) + interfaces[0] = java.io.Serializable.class; + + byte[] classData = makeLambda(invokedName, invokedType, methodType, methodImplementation, interfaces); + return makeCallSite(invokedType, classData); + } +} diff --git a/sgx-jvm/avian/classpath/java/lang/invoke/MethodHandle.java b/sgx-jvm/avian/classpath/java/lang/invoke/MethodHandle.java new file mode 100644 index 0000000000..bbb5cabdec --- /dev/null +++ b/sgx-jvm/avian/classpath/java/lang/invoke/MethodHandle.java @@ -0,0 +1,65 @@ +/* Copyright (c) 2008-2016, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.lang.invoke; + +import avian.Classes; +import avian.SystemClassLoader; + +public class MethodHandle { + static final int REF_invokeStatic = 6; + static final int REF_invokeSpecial = 7; + + final int kind; + private final ClassLoader loader; + final avian.VMMethod method; + private volatile MethodType type; + + MethodHandle(int kind, ClassLoader loader, avian.VMMethod method) { + this.kind = kind; + this.loader = loader; + this.method = method; + } + + MethodHandle(String class_, + String name, + String spec, + int kind) + { + this.kind = kind; + this.loader = SystemClassLoader.appLoader(); + try { + this.method = Classes.findMethod(this.loader, class_, name, spec); + } catch (ClassNotFoundException e) { + throw new RuntimeException(e); + } + } + + public String toString() { + StringBuilder sb = new StringBuilder(); + if (method.class_ != null) { + sb.append(Classes.makeString(method.class_.name, 0, + method.class_.name.length - 1)); + sb.append("."); + } + sb.append(Classes.makeString(method.name, 0, + method.name.length - 1)); + sb.append(Classes.makeString(method.spec, 0, + method.spec.length - 1)); + return sb.toString(); + } + + public MethodType type() { + if (type == null) { + type = new MethodType(loader, method.spec); + } + return type; + } +} diff --git a/sgx-jvm/avian/classpath/java/lang/invoke/MethodHandles.java b/sgx-jvm/avian/classpath/java/lang/invoke/MethodHandles.java new file mode 100644 index 0000000000..b4af275a5c --- /dev/null +++ b/sgx-jvm/avian/classpath/java/lang/invoke/MethodHandles.java @@ -0,0 +1,28 @@ +/* Copyright (c) 2008-2016, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.lang.invoke; + +public class MethodHandles { + public static class Lookup { + final avian.VMClass class_; + private final int modes; + + private Lookup(avian.VMClass class_, int modes) { + this.class_ = class_; + this.modes = modes; + } + + public String toString() { + return "lookup[" + avian.SystemClassLoader.getClass(class_) + ", " + + modes + "]"; + } + } +} diff --git a/sgx-jvm/avian/classpath/java/lang/invoke/MethodType.java b/sgx-jvm/avian/classpath/java/lang/invoke/MethodType.java new file mode 100644 index 0000000000..4ac62810f5 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/lang/invoke/MethodType.java @@ -0,0 +1,322 @@ +/* Copyright (c) 2008-2016, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.lang.invoke; + +import static avian.Assembler.*; + +import avian.Assembler; +import avian.Classes; +import avian.SystemClassLoader; +import avian.VMClass; + +import java.util.List; +import java.util.ArrayList; + +public final class MethodType implements java.io.Serializable { + private static final char[] Primitives = new char[] { + 'V', 'Z', 'B', 'C', 'S', 'I', 'F', 'J', 'D' + }; + + final ClassLoader loader; + final byte[] spec; + private volatile List parameters; + private volatile Result result; + private volatile int footprint; + + MethodType(ClassLoader loader, byte[] spec) { + this.loader = loader; + this.spec = spec; + } + + MethodType(String spec) { + this.loader = SystemClassLoader.appLoader(); + this.spec = new byte[spec.length() + 1]; + spec.getBytes(0, spec.length(), this.spec, 0); + } + + public String toMethodDescriptorString() { + return Classes.makeString(spec, 0, spec.length - 1); + } + + private static String spec(Class c) { + if (c.isPrimitive()) { + VMClass vmc = Classes.toVMClass(c); + for (char p: Primitives) { + if (vmc == Classes.primitiveClass(p)) { + return String.valueOf(p); + } + } + throw new AssertionError(); + } else if (c.isArray()) { + return "[" + spec(c.getComponentType()); + } else { + return "L" + c.getName().replace('.', '/') + ";"; + } + } + + private MethodType(Class rtype, + Class ... ptypes) + { + loader = rtype.getClassLoader(); + + StringBuilder sb = new StringBuilder(); + sb.append('('); + parameters = new ArrayList(ptypes.length); + int position = 0; + for (int i = 0; i < ptypes.length; ++i) { + String spec = spec(ptypes[i]); + sb.append(spec); + + Type type = type(spec); + + parameters.add(new Parameter(i, + position, + spec, + ptypes[i], + type.load)); + + position += type.size; + } + sb.append(')'); + + footprint = position; + + String spec = spec(rtype); + sb.append(spec); + + result = new Result(spec, rtype, type(spec).return_); + + this.spec = sb.toString().getBytes(); + } + + public static MethodType methodType(Class rtype, + Class ptype0, + Class ... ptypes) + { + Class[] array = new Class[ptypes.length + 1]; + array[0] = ptype0; + System.arraycopy(ptypes, 0, array, 1, ptypes.length); + return methodType(rtype, array); + } + + public static MethodType methodType(Class rtype, + Class ... ptypes) + { + return new MethodType(rtype, ptypes); + } + + public String toString() { + return Classes.makeString(spec, 0, spec.length - 1); + } + + public int footprint() { + parameters(); // ensure spec is parsed + + return footprint; + } + + public Class returnType() { + parameters(); // ensure spec is parsed + + return result.type; + } + + public Class[] parameterArray() { + parameters(); // ensure spec is parsed + + Class[] array = new Class[parameters.size()]; + for (int i = 0; i < parameters.size(); ++i) { + array[i] = parameters.get(i).type; + } + + return array; + } + + public Iterable parameters() { + if (parameters == null) { + List list = new ArrayList(); + int i; + int index = 0; + int position = 0; + for (i = 1; spec[i] != ')'; ++i) { + int start = i; + switch (spec[i]) { + case 'L': { + ++ i; + while (spec[i] != ';') ++ i; + } break; + + case '[': { + ++ i; + while (spec[i] == '[') ++ i; + + switch (spec[i]) { + case 'L': + ++ i; + while (spec[i] != ';') ++ i; + break; + + default: + break; + } + } break; + + case 'Z': + case 'B': + case 'S': + case 'C': + case 'I': + case 'F': + case 'J': + case 'D': + break; + + default: throw new AssertionError(); + } + + String paramSpec = Classes.makeString(spec, start, (i - start) + 1); + Type type = type(paramSpec); + + list.add(new Parameter + (index, + position, + paramSpec, + Classes.forCanonicalName(loader, paramSpec), + type.load)); + + ++ index; + position += type.size; + } + + footprint = position; + + ++ i; + + String paramSpec = Classes.makeString(spec, i, spec.length - i - 1); + Type type = type(paramSpec); + + result = new Result(paramSpec, + Classes.forCanonicalName(loader, paramSpec), + type.return_); + + parameters = list; + } + + return parameters; + } + + public Result result() { + parameters(); // ensure spec has been parsed + + return result; + } + + private static Type type(String spec) { + switch (spec.charAt(0)) { + case 'L': + case '[': + return Type.ObjectType; + + case 'Z': + case 'B': + case 'S': + case 'C': + case 'I': + return Type.IntegerType; + + case 'F': + return Type.FloatType; + + case 'J': + return Type.LongType; + + case 'D': + return Type.DoubleType; + + case 'V': + return Type.VoidType; + + default: throw new AssertionError(); + } + } + + private static enum Type { + ObjectType(aload, areturn, 1), + IntegerType(iload, ireturn, 1), + FloatType(fload, freturn, 1), + LongType(lload, lreturn, 2), + DoubleType(dload, dreturn, 2), + VoidType(-1, Assembler.return_, -1); + + public final int load; + public final int return_; + public final int size; + + private Type(int load, int return_, int size) { + this.load = load; + this.return_ = return_; + this.size = size; + } + } + + public static class Parameter { + private final int index; + private final int position; + private final String spec; + private final Class type; + private final int load; + + private Parameter(int index, + int position, + String spec, + Class type, + int load) + { + this.index = index; + this.position = position; + this.spec = spec; + this.type = type; + this.load = load; + } + + public int index() { + return index; + } + + public int position() { + return position; + } + + public String spec() { + return spec; + } + + public int load() { + return load; + } + } + + public static class Result { + private final String spec; + private final Class type; + private final int return_; + + public Result(String spec, Class type, int return_) { + this.spec = spec; + this.type = type; + this.return_ = return_; + } + + public int return_() { + return return_; // :) + } + } +} diff --git a/sgx-jvm/avian/classpath/java/lang/invoke/SerializedLambda.java b/sgx-jvm/avian/classpath/java/lang/invoke/SerializedLambda.java new file mode 100644 index 0000000000..749a11f049 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/lang/invoke/SerializedLambda.java @@ -0,0 +1,53 @@ +/* Copyright (c) 2008-2016, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.lang.invoke; + +public class SerializedLambda implements java.io.Serializable { + public Object getCapturedArg(int i) { + // todo + return null; + } + + public int getImplMethodKind() { + // todo + return 0; + } + + public String getImplClass() { + // todo + return null; + } + + public String getImplMethodName() { + // todo + return null; + } + + public String getImplMethodSignature() { + // todo + return null; + } + + public String getFunctionalInterfaceClass() { + // todo + return null; + } + + public String getFunctionalInterfaceMethodName() { + // todo + return null; + } + + public String getFunctionalInterfaceMethodSignature() { + // todo + return null; + } +} diff --git a/sgx-jvm/avian/classpath/java/lang/ref/PhantomReference.java b/sgx-jvm/avian/classpath/java/lang/ref/PhantomReference.java new file mode 100644 index 0000000000..3843154721 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/lang/ref/PhantomReference.java @@ -0,0 +1,25 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.lang.ref; + +public class PhantomReference extends Reference { + public PhantomReference(T target, ReferenceQueue queue) { + super(target, queue); + } + + public PhantomReference(T target) { + this(target, null); + } + + public T get() { + return null; + } +} diff --git a/sgx-jvm/avian/classpath/java/lang/ref/Reference.java b/sgx-jvm/avian/classpath/java/lang/ref/Reference.java new file mode 100644 index 0000000000..443e0c820c --- /dev/null +++ b/sgx-jvm/avian/classpath/java/lang/ref/Reference.java @@ -0,0 +1,50 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.lang.ref; + +public abstract class Reference { + private Object vmNext; + private T target; + private ReferenceQueue queue; + + Reference jNext; + + protected Reference(T target, ReferenceQueue queue) { + this.target = target; + this.queue = queue; + } + + protected Reference(T target) { + this(target, null); + } + + public T get() { + return target; + } + + public void clear() { + target = null; + } + + public boolean isEnqueued() { + return jNext != null; + } + + public boolean enqueue() { + if (queue != null) { + queue.add(this); + queue = null; + return true; + } else { + return false; + } + } +} diff --git a/sgx-jvm/avian/classpath/java/lang/ref/ReferenceQueue.java b/sgx-jvm/avian/classpath/java/lang/ref/ReferenceQueue.java new file mode 100644 index 0000000000..c5ccd6b320 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/lang/ref/ReferenceQueue.java @@ -0,0 +1,36 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.lang.ref; + +public class ReferenceQueue { + private Reference front; + + public Reference poll() { + Reference r = front; + if (front != null) { + if (front == front.jNext) { + front = null; + } else { + front = front.jNext; + } + } + return r; + } + + void add(Reference r) { + if (front == null) { + r.jNext = r; + } else { + r.jNext = front; + } + front = r; + } +} diff --git a/sgx-jvm/avian/classpath/java/lang/ref/SoftReference.java b/sgx-jvm/avian/classpath/java/lang/ref/SoftReference.java new file mode 100644 index 0000000000..412cf0204c --- /dev/null +++ b/sgx-jvm/avian/classpath/java/lang/ref/SoftReference.java @@ -0,0 +1,21 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.lang.ref; + +public class SoftReference extends Reference { + public SoftReference(T target, ReferenceQueue queue) { + super(target, queue); + } + + public SoftReference(T target) { + this(target, null); + } +} diff --git a/sgx-jvm/avian/classpath/java/lang/ref/WeakReference.java b/sgx-jvm/avian/classpath/java/lang/ref/WeakReference.java new file mode 100644 index 0000000000..4b6835c643 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/lang/ref/WeakReference.java @@ -0,0 +1,21 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.lang.ref; + +public class WeakReference extends Reference { + public WeakReference(T target, ReferenceQueue queue) { + super(target, queue); + } + + public WeakReference(T target) { + this(target, null); + } +} diff --git a/sgx-jvm/avian/classpath/java/lang/reflect/AccessibleObject.java b/sgx-jvm/avian/classpath/java/lang/reflect/AccessibleObject.java new file mode 100644 index 0000000000..9c8c0b57cd --- /dev/null +++ b/sgx-jvm/avian/classpath/java/lang/reflect/AccessibleObject.java @@ -0,0 +1,35 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.lang.reflect; + +import java.lang.annotation.Annotation; + +public abstract class AccessibleObject implements AnnotatedElement { + protected static final int Accessible = 1 << 0; + + // Access and property flags for Member descendants + protected static final int ACC_VARARGS = 0x0080; + protected static final int ACC_SYNTHETIC = 0x1000; + + public boolean isAnnotationPresent + (Class class_) + { + return getAnnotation(class_) != null; + } + + public abstract boolean isAccessible(); + + public abstract void setAccessible(boolean v); + + public static void setAccessible(AccessibleObject[] array, boolean v) { + for (AccessibleObject o: array) o.setAccessible(v); + } +} diff --git a/sgx-jvm/avian/classpath/java/lang/reflect/AnnotatedElement.java b/sgx-jvm/avian/classpath/java/lang/reflect/AnnotatedElement.java new file mode 100644 index 0000000000..d47b0c9fa3 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/lang/reflect/AnnotatedElement.java @@ -0,0 +1,23 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.lang.reflect; + +import java.lang.annotation.Annotation; + +public interface AnnotatedElement { + public boolean isAnnotationPresent(Class class_); + + public T getAnnotation(Class class_); + + public Annotation[] getAnnotations(); + + public Annotation[] getDeclaredAnnotations(); +} diff --git a/sgx-jvm/avian/classpath/java/lang/reflect/Array.java b/sgx-jvm/avian/classpath/java/lang/reflect/Array.java new file mode 100644 index 0000000000..09846019ba --- /dev/null +++ b/sgx-jvm/avian/classpath/java/lang/reflect/Array.java @@ -0,0 +1,130 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.lang.reflect; + +public final class Array { + private Array() { } + + public static Object get(Object array, int index) { + String className = array.getClass().getName(); + if (! className.startsWith("[")) { + throw new IllegalArgumentException(); + } + + switch (className.charAt(1)) { + case 'B': + return Byte.valueOf(((byte[]) array)[index]); + case 'C': + return Character.valueOf(((char[]) array)[index]); + case 'D': + return Double.valueOf(((double[]) array)[index]); + case 'F': + return Float.valueOf(((float[]) array)[index]); + case 'I': + return Integer.valueOf(((int[]) array)[index]); + case 'J': + return Long.valueOf(((long[]) array)[index]); + case 'S': + return Short.valueOf(((short[]) array)[index]); + case 'Z': + return Boolean.valueOf(((boolean[]) array)[index]); + case 'L': + case '[': + return ((Object[]) array)[index]; + + default: + throw new Error(); + } + } + + public static void set(Object array, int index, Object value) { + String className = array.getClass().getName(); + if (! className.startsWith("[")) { + throw new IllegalArgumentException(); + } + + switch (className.charAt(1)) { + case 'B': + ((byte[]) array)[index] = (Byte) value; + break; + case 'C': + ((char[]) array)[index] = (Character) value; + break; + case 'D': + ((double[]) array)[index] = (Double) value; + break; + case 'F': + ((float[]) array)[index] = (Float) value; + break; + case 'I': + ((int[]) array)[index] = (Integer) value; + break; + case 'J': + ((long[]) array)[index] = (Long) value; + break; + case 'S': + ((short[]) array)[index] = (Short) value; + break; + case 'Z': + ((boolean[]) array)[index] = (Boolean) value; + break; + case 'L': + case '[': + if (value == null + || array.getClass().getComponentType().isInstance(value)) + { + ((Object[]) array)[index] = value; + } else { + throw new IllegalArgumentException + ("need " + array.getClass().getComponentType() + + ", got " + value.getClass().getName()); + } + break; + + default: + throw new Error(); + } + } + + public static native int getLength(Object array); + + private static native Object makeObjectArray(Class elementType, int length); + + public static Object newInstance(Class elementType, int length) { + if (length < 0) { + throw new NegativeArraySizeException(); + } + + if (elementType.isPrimitive()) { + if (elementType.equals(boolean.class)) { + return new boolean[length]; + } else if (elementType.equals(byte.class)) { + return new byte[length]; + } else if (elementType.equals(char.class)) { + return new char[length]; + } else if (elementType.equals(short.class)) { + return new short[length]; + } else if (elementType.equals(int.class)) { + return new int[length]; + } else if (elementType.equals(long.class)) { + return new long[length]; + } else if (elementType.equals(float.class)) { + return new float[length]; + } else if (elementType.equals(double.class)) { + return new double[length]; + } else { + throw new IllegalArgumentException(); + } + } else { + return makeObjectArray(elementType, length); + } + } +} diff --git a/sgx-jvm/avian/classpath/java/lang/reflect/Constructor.java b/sgx-jvm/avian/classpath/java/lang/reflect/Constructor.java new file mode 100644 index 0000000000..ec7d306bbd --- /dev/null +++ b/sgx-jvm/avian/classpath/java/lang/reflect/Constructor.java @@ -0,0 +1,81 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.lang.reflect; + +import java.lang.annotation.Annotation; + +public class Constructor extends AccessibleObject implements Member { + private Method method; + + public Constructor(Method method) { + this.method = method; + } + + public boolean equals(Object o) { + return o instanceof Constructor + && ((Constructor) o).method.equals(method); + } + + public boolean isAccessible() { + return method.isAccessible(); + } + + public void setAccessible(boolean v) { + method.setAccessible(v); + } + + public Class getDeclaringClass() { + return method.getDeclaringClass(); + } + + public Class[] getParameterTypes() { + return method.getParameterTypes(); + } + + public int getModifiers() { + return method.getModifiers(); + } + + public boolean isSynthetic() { + return method.isSynthetic(); + } + + public String getName() { + return method.getName(); + } + + public T getAnnotation(Class class_) { + return method.getAnnotation(class_); + } + + public Annotation[] getAnnotations() { + return method.getAnnotations(); + } + + public Annotation[] getDeclaredAnnotations() { + return method.getDeclaredAnnotations(); + } + + private static native Object make(avian.VMClass c); + + public T newInstance(Object ... arguments) + throws InvocationTargetException, InstantiationException, + IllegalAccessException + { + T v = (T) make(method.getDeclaringClass().vmClass); + method.invoke(v, arguments); + return v; + } + + public Class[] getExceptionTypes() { + throw new UnsupportedOperationException("not yet implemented"); + } +} diff --git a/sgx-jvm/avian/classpath/java/lang/reflect/Field.java b/sgx-jvm/avian/classpath/java/lang/reflect/Field.java new file mode 100644 index 0000000000..91d3b68f5c --- /dev/null +++ b/sgx-jvm/avian/classpath/java/lang/reflect/Field.java @@ -0,0 +1,401 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.lang.reflect; + +import avian.VMField; +import avian.AnnotationInvocationHandler; +import avian.SystemClassLoader; +import avian.Classes; + +import java.lang.annotation.Annotation; + +public class Field extends AccessibleObject implements Member { + private static final int VoidField = 0; + private static final int ByteField = 1; + private static final int CharField = 2; + private static final int DoubleField = 3; + private static final int FloatField = 4; + private static final int IntField = 5; + private static final int LongField = 6; + private static final int ShortField = 7; + private static final int BooleanField = 8; + private static final int ObjectField = 9; + + private final VMField vmField; + private boolean accessible = true; + + public Field(VMField vmField) { + this.vmField = vmField; + } + + public boolean isAccessible() { + return accessible; + } + + public void setAccessible(boolean v) { + accessible = v; + } + + public Class getDeclaringClass() { + return SystemClassLoader.getClass(vmField.class_); + } + + public int getModifiers() { + return vmField.flags; + } + + public boolean isSynthetic() { + return (vmField.flags & ACC_SYNTHETIC) != 0; + } + + public String getName() { + return getName(vmField); + } + + public static String getName(VMField vmField) { + return Classes.makeString(vmField.name, 0, vmField.name.length - 1); + } + + public Class getType() { + return Classes.forCanonicalName + (vmField.class_.loader, + Classes.makeString(vmField.spec, 0, vmField.spec.length - 1)); + } + + public Type getGenericType() { + if (vmField.addendum == null || vmField.addendum.signature == null) { + return getType(); + } + String signature = Classes.toString((byte[]) vmField.addendum.signature); + return SignatureParser.parse(vmField.class_.loader, signature, getDeclaringClass()); + } + + public Object get(Object instance) throws IllegalAccessException { + Object target; + if ((vmField.flags & Modifier.STATIC) != 0) { + target = vmField.class_.staticTable; + } else if (Class.isInstance(vmField.class_, instance)) { + target = instance; + } else { + throw new IllegalArgumentException(); + } + + Classes.initialize(vmField.class_); + + switch (vmField.code) { + case ByteField: + return Byte.valueOf + ((byte) getPrimitive(target, vmField.code, vmField.offset)); + + case BooleanField: + return Boolean.valueOf + (getPrimitive(target, vmField.code, vmField.offset) != 0); + + case CharField: + return Character.valueOf + ((char) getPrimitive(target, vmField.code, vmField.offset)); + + case ShortField: + return Short.valueOf + ((short) getPrimitive(target, vmField.code, vmField.offset)); + + case IntField: + return Integer.valueOf + ((int) getPrimitive(target, vmField.code, vmField.offset)); + + case LongField: + return Long.valueOf + (getPrimitive(target, vmField.code, vmField.offset)); + + case FloatField: + return Float.valueOf + (Float.intBitsToFloat + ((int) getPrimitive(target, vmField.code, vmField.offset))); + + case DoubleField: + return Double.valueOf + (Double.longBitsToDouble + (getPrimitive(target, vmField.code, vmField.offset))); + + case ObjectField: + return getObject(target, vmField.offset); + + default: + throw new Error(); + } + } + + public boolean getBoolean(Object instance) throws IllegalAccessException { + return ((Boolean) get(instance)).booleanValue(); + } + + public byte getByte(Object instance) throws IllegalAccessException { + return ((Byte) get(instance)).byteValue(); + } + + public short getShort(Object instance) throws IllegalAccessException { + return ((Short) get(instance)).shortValue(); + } + + public char getChar(Object instance) throws IllegalAccessException { + return ((Character) get(instance)).charValue(); + } + + public int getInt(Object instance) throws IllegalAccessException { + return ((Integer) get(instance)).intValue(); + } + + public float getFloat(Object instance) throws IllegalAccessException { + return ((Float) get(instance)).floatValue(); + } + + public long getLong(Object instance) throws IllegalAccessException { + return ((Long) get(instance)).longValue(); + } + + public double getDouble(Object instance) throws IllegalAccessException { + return ((Double) get(instance)).doubleValue(); + } + + private boolean matchType(Object value) { + switch (vmField.code) { + case ByteField: + return value instanceof Byte; + + case BooleanField: + return value instanceof Boolean; + + case CharField: + return value instanceof Character; + + case ShortField: + return value instanceof Short; + + case IntField: + return value instanceof Integer; + + case LongField: + return value instanceof Long; + + case FloatField: + return value instanceof Float; + + case DoubleField: + return value instanceof Double; + + case ObjectField: + return value == null || getType().isInstance(value); + + default: + throw new Error(); + } + } + + public void set(Object instance, Object value) + throws IllegalAccessException + { + Object target; + if ((vmField.flags & Modifier.STATIC) != 0) { + target = vmField.class_.staticTable; + } else if (Class.isInstance(vmField.class_, instance)) { + target = instance; + } else { + throw new IllegalArgumentException(); + } + + if (! matchType(value)) { + throw new IllegalArgumentException(); + } + + Classes.initialize(vmField.class_); + + switch (vmField.code) { + case ByteField: + setPrimitive(target, vmField.code, vmField.offset, (Byte) value); + break; + + case BooleanField: + setPrimitive + (target, vmField.code, vmField.offset, ((Boolean) value) ? 1 : 0); + break; + + case CharField: + setPrimitive(target, vmField.code, vmField.offset, (Character) value); + break; + + case ShortField: + setPrimitive(target, vmField.code, vmField.offset, (Short) value); + break; + + case IntField: + setPrimitive(target, vmField.code, vmField.offset, (Integer) value); + break; + + case LongField: + setPrimitive(target, vmField.code, vmField.offset, (Long) value); + break; + + case FloatField: + setPrimitive(target, vmField.code, vmField.offset, + Float.floatToRawIntBits((Float) value)); + break; + + case DoubleField: + setPrimitive(target, vmField.code, vmField.offset, + Double.doubleToRawLongBits((Double) value)); + break; + + case ObjectField: + setObject(target, vmField.offset, value); + break; + + default: + throw new Error(); + } + } + + private void set(Object instance, long value) + throws IllegalAccessException + { + Object target; + if ((vmField.flags & Modifier.STATIC) != 0) { + target = vmField.class_.staticTable; + } else if (Class.isInstance(vmField.class_, instance)) { + target = instance; + } else { + throw new IllegalArgumentException(); + } + + Classes.initialize(vmField.class_); + + switch (vmField.code) { + case ByteField: + case BooleanField: + case CharField: + case ShortField: + case IntField: + case LongField: + case FloatField: + case DoubleField: + setPrimitive(target, vmField.code, vmField.offset, value); + break; + + default: + throw new IllegalArgumentException + ("needed " + getType() + ", got primitive type when setting " + + Class.getName(vmField.class_) + "." + getName()); + } + } + + public void setByte(Object instance, byte value) + throws IllegalAccessException + { + set(instance, value & 0xff); + } + + public void setBoolean(Object instance, boolean value) + throws IllegalAccessException + { + set(instance, value ? 1 : 0); + } + + public void setChar(Object instance, char value) + throws IllegalAccessException + { + set(instance, value & 0xffff); + } + + public void setShort(Object instance, short value) + throws IllegalAccessException + { + set(instance, value & 0xffff); + } + + public void setInt(Object instance, int value) + throws IllegalAccessException + { + set(instance, value & 0xffffffffl); + } + + public void setLong(Object instance, long value) + throws IllegalAccessException + { + set(instance, value); + } + + public void setFloat(Object instance, float value) + throws IllegalAccessException + { + set(instance, Float.floatToIntBits(value)); + } + + public void setDouble(Object instance, double value) + throws IllegalAccessException + { + set(instance, Double.doubleToLongBits(value)); + } + + private Annotation getAnnotation(Object[] a) { + if (a[0] == null) { + a[0] = Proxy.newProxyInstance + (vmField.class_.loader, new Class[] { (Class) a[1] }, + new AnnotationInvocationHandler(a)); + } + return (Annotation) a[0]; + } + + private boolean hasAnnotations() { + return vmField.addendum != null + && vmField.addendum.annotationTable != null; + } + + public T getAnnotation(Class class_) { + if (hasAnnotations()) { + Object[] table = (Object[]) vmField.addendum.annotationTable; + for (int i = 0; i < table.length; ++i) { + Object[] a = (Object[]) table[i]; + if (a[1] == class_) { + return (T) getAnnotation(a); + } + } + } + return null; + } + + public Annotation[] getAnnotations() { + if (hasAnnotations()) { + Object[] table = (Object[]) vmField.addendum.annotationTable; + Annotation[] array = new Annotation[table.length]; + for (int i = 0; i < table.length; ++i) { + array[i] = getAnnotation((Object[]) table[i]); + } + return array; + } else { + return new Annotation[0]; + } + } + + public Annotation[] getDeclaredAnnotations() { + return getAnnotations(); + } + + private static native long getPrimitive + (Object instance, int code, int offset); + + private static native Object getObject + (Object instance, int offset); + + private static native void setPrimitive + (Object instance, int code, int offset, long value); + + private static native void setObject + (Object instance, int offset, Object value); +} diff --git a/sgx-jvm/avian/classpath/java/lang/reflect/GenericDeclaration.java b/sgx-jvm/avian/classpath/java/lang/reflect/GenericDeclaration.java new file mode 100644 index 0000000000..d167aeb549 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/lang/reflect/GenericDeclaration.java @@ -0,0 +1,5 @@ +package java.lang.reflect; + +public interface GenericDeclaration { + TypeVariable[] getTypeParameters(); +} diff --git a/sgx-jvm/avian/classpath/java/lang/reflect/InvocationHandler.java b/sgx-jvm/avian/classpath/java/lang/reflect/InvocationHandler.java new file mode 100644 index 0000000000..02bd57f97c --- /dev/null +++ b/sgx-jvm/avian/classpath/java/lang/reflect/InvocationHandler.java @@ -0,0 +1,15 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.lang.reflect; + +public interface InvocationHandler { + public Object invoke(Object proxy, Method method, Object[] arguments) throws Throwable; +} diff --git a/sgx-jvm/avian/classpath/java/lang/reflect/InvocationTargetException.java b/sgx-jvm/avian/classpath/java/lang/reflect/InvocationTargetException.java new file mode 100644 index 0000000000..da6d11956f --- /dev/null +++ b/sgx-jvm/avian/classpath/java/lang/reflect/InvocationTargetException.java @@ -0,0 +1,31 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.lang.reflect; + +public class InvocationTargetException extends Exception { + private Throwable target; // for compatibility with OpenJDK + + public InvocationTargetException(Throwable targetException, String message) { + super(message, targetException); + } + + public InvocationTargetException(Throwable targetException) { + this(targetException, null); + } + + public InvocationTargetException() { + this(null, null); + } + + public Throwable getTargetException() { + return getCause(); + } +} diff --git a/sgx-jvm/avian/classpath/java/lang/reflect/Member.java b/sgx-jvm/avian/classpath/java/lang/reflect/Member.java new file mode 100644 index 0000000000..4081b12b35 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/lang/reflect/Member.java @@ -0,0 +1,24 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.lang.reflect; + +public interface Member { + public static final int PUBLIC = 0; + public static final int DECLARED = 1; + + public Class getDeclaringClass(); + + public int getModifiers(); + + public String getName(); + + public boolean isSynthetic(); +} diff --git a/sgx-jvm/avian/classpath/java/lang/reflect/Method.java b/sgx-jvm/avian/classpath/java/lang/reflect/Method.java new file mode 100644 index 0000000000..705fc8ec16 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/lang/reflect/Method.java @@ -0,0 +1,164 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.lang.reflect; + +import avian.VMMethod; +import avian.AnnotationInvocationHandler; +import avian.SystemClassLoader; +import avian.Classes; + +import java.lang.annotation.Annotation; + +public class Method extends AccessibleObject implements Member { + public final VMMethod vmMethod; + private boolean accessible; + + public Method(VMMethod vmMethod) { + this.vmMethod = vmMethod; + } + + public boolean equals(Object o) { + return o instanceof Method && ((Method) o).vmMethod == vmMethod; + } + + public boolean isAccessible() { + return accessible; + } + + public void setAccessible(boolean v) { + accessible = v; + } + + public static native VMMethod getCaller(); + + public Class getDeclaringClass() { + return SystemClassLoader.getClass(vmMethod.class_); + } + + public int getModifiers() { + return vmMethod.flags; + } + + public String getName() { + return getName(vmMethod); + } + + public static String getName(VMMethod vmMethod) { + return Classes.makeString(vmMethod.name, 0, vmMethod.name.length - 1); + } + + private String getSpec() { + return getSpec(vmMethod); + } + + public static String getSpec(VMMethod vmMethod) { + return Classes.makeString(vmMethod.spec, 0, vmMethod.spec.length - 1); + } + + public Class[] getParameterTypes() { + return Classes.getParameterTypes(vmMethod); + } + + public Object invoke(Object instance, Object ... arguments) + throws InvocationTargetException, IllegalAccessException + { + if ((vmMethod.flags & Modifier.STATIC) != 0 + || Class.isInstance(vmMethod.class_, instance)) + { + if ((vmMethod.flags & Modifier.STATIC) != 0) { + instance = null; + } + + if (arguments == null) { + if (vmMethod.parameterCount > 0) { + throw new NullPointerException(); + } + arguments = new Object[0]; + } + + if (arguments.length == vmMethod.parameterCount) { + Classes.initialize(vmMethod.class_); + + return invoke(vmMethod, instance, arguments); + } else { + throw new ArrayIndexOutOfBoundsException(); + } + } else { +// System.out.println +// (getDeclaringClass() + "." + getName() + " flags: " + vmMethod.flags + " vm flags: " + vmMethod.vmFlags + " return code: " + vmMethod.returnCode); + throw new IllegalArgumentException(); + } + } + + private static native Object invoke(VMMethod method, Object instance, + Object ... arguments) + throws InvocationTargetException, IllegalAccessException; + + public Class getReturnType() { + for (int i = 0; i < vmMethod.spec.length - 1; ++i) { + if (vmMethod.spec[i] == ')') { + return Classes.forCanonicalName + (vmMethod.class_.loader, + Classes.makeString + (vmMethod.spec, i + 1, vmMethod.spec.length - i - 2)); + } + } + throw new RuntimeException(); + } + + public T getAnnotation(Class class_) { + if (vmMethod.hasAnnotations()) { + Object[] table = (Object[]) vmMethod.addendum.annotationTable; + for (int i = 0; i < table.length; ++i) { + Object[] a = (Object[]) table[i]; + if (a[1] == class_) { + return (T) Classes.getAnnotation(vmMethod.class_.loader, a); + } + } + } + return null; + } + + public Annotation[] getAnnotations() { + if (vmMethod.hasAnnotations()) { + Object[] table = (Object[]) vmMethod.addendum.annotationTable; + Annotation[] array = new Annotation[table.length]; + for (int i = 0; i < table.length; ++i) { + array[i] = Classes.getAnnotation + (vmMethod.class_.loader, (Object[]) table[i]); + } + return array; + } else { + return new Annotation[0]; + } + } + + public Annotation[] getDeclaredAnnotations() { + return getAnnotations(); + } + + public boolean isVarArgs() { + return (getModifiers() & ACC_VARARGS) != 0; + } + + public boolean isSynthetic() { + return (getModifiers() & ACC_SYNTHETIC) != 0; + } + + public Object getDefaultValue() { + ClassLoader loader = getDeclaringClass().getClassLoader(); + return Classes.getAnnotationDefaultValue(loader, vmMethod.addendum); + } + + public Class[] getExceptionTypes() { + throw new UnsupportedOperationException("not yet implemented"); + } +} diff --git a/sgx-jvm/avian/classpath/java/lang/reflect/Modifier.java b/sgx-jvm/avian/classpath/java/lang/reflect/Modifier.java new file mode 100644 index 0000000000..1b32f6a1f6 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/lang/reflect/Modifier.java @@ -0,0 +1,40 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.lang.reflect; + +public final class Modifier { + public static final int PUBLIC = 1 << 0; + public static final int PRIVATE = 1 << 1; + public static final int PROTECTED = 1 << 2; + public static final int STATIC = 1 << 3; + public static final int FINAL = 1 << 4; + public static final int SUPER = 1 << 5; + public static final int SYNCHRONIZED = SUPER; + public static final int VOLATILE = 1 << 6; + public static final int TRANSIENT = 1 << 7; + public static final int NATIVE = 1 << 8; + public static final int INTERFACE = 1 << 9; + public static final int ABSTRACT = 1 << 10; + public static final int STRICT = 1 << 11; + + private Modifier() { } + + public static boolean isPublic (int v) { return (v & PUBLIC) != 0; } + public static boolean isPrivate (int v) { return (v & PRIVATE) != 0; } + public static boolean isProtected(int v) { return (v & PROTECTED) != 0; } + public static boolean isStatic (int v) { return (v & STATIC) != 0; } + public static boolean isFinal (int v) { return (v & FINAL) != 0; } + public static boolean isTransient(int v) { return (v & TRANSIENT) != 0; } + public static boolean isSuper (int v) { return (v & SUPER) != 0; } + public static boolean isNative (int v) { return (v & NATIVE) != 0; } + public static boolean isAbstract (int v) { return (v & ABSTRACT) != 0; } + public static boolean isInterface(int v) { return (v & INTERFACE) != 0; } +} diff --git a/sgx-jvm/avian/classpath/java/lang/reflect/ParameterizedType.java b/sgx-jvm/avian/classpath/java/lang/reflect/ParameterizedType.java new file mode 100644 index 0000000000..8a570f0c76 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/lang/reflect/ParameterizedType.java @@ -0,0 +1,17 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.lang.reflect; + +public interface ParameterizedType extends Type { + Type[] getActualTypeArguments(); + Type getOwnerType(); + Type getRawType(); +} diff --git a/sgx-jvm/avian/classpath/java/lang/reflect/Proxy.java b/sgx-jvm/avian/classpath/java/lang/reflect/Proxy.java new file mode 100644 index 0000000000..60bbedc7ec --- /dev/null +++ b/sgx-jvm/avian/classpath/java/lang/reflect/Proxy.java @@ -0,0 +1,430 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.lang.reflect; + +import static avian.Stream.write1; +import static avian.Stream.write2; +import static avian.Stream.write4; +import static avian.Stream.set4; +import static avian.Assembler.*; + +import avian.SystemClassLoader; +import avian.Classes; + +import avian.ConstantPool; +import avian.ConstantPool.PoolEntry; + +import avian.Assembler; +import avian.Assembler.FieldData; +import avian.Assembler.MethodData; + +import java.util.List; +import java.util.ArrayList; +import java.util.Map; +import java.util.HashMap; +import java.util.Set; +import java.util.HashSet; +import java.io.OutputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; + +public class Proxy { + private static int nextNumber; + + protected InvocationHandler h; + protected final static Map methodRefsMap = + new HashMap(); + protected final Method[] methodRefs; + + public Proxy() { + methodRefs = methodRefsMap.get(getClass()); + } + + public static Class getProxyClass(ClassLoader loader, + Class ... interfaces) + { + for (Class c: interfaces) { + if (! c.isInterface()) { + throw new IllegalArgumentException(); + } + } + + int number; + synchronized (Proxy.class) { + number = nextNumber++; + } + + try { + return makeClass(loader, interfaces, "Proxy-" + number); + } catch (IOException e) { + AssertionError error = new AssertionError(); + error.initCause(e); + throw error; + } + } + + public static boolean isProxyClass(Class c) { + return c.getName().startsWith("Proxy-"); + } + + public static InvocationHandler getInvocationHandler(Object proxy) { + return ((Proxy) proxy).h; + } + + private static byte[] makeInvokeCode(List pool, + String className, + byte[] spec, + int parameterCount, + int parameterFootprint, + int index) + throws IOException + { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + write2(out, 8); // max stack + write2(out, parameterFootprint); // max locals + write4(out, 0); // length (we'll set the real value later) + + write1(out, aload_0); + write1(out, getfield); + write2(out, ConstantPool.addFieldRef + (pool, "java/lang/reflect/Proxy", + "h", "Ljava/lang/reflect/InvocationHandler;") + 1); + + write1(out, aload_0); + + write1(out, aload_0); + write1(out, getfield); + write2(out, ConstantPool.addFieldRef + (pool, className, + "methodRefs", "[Ljava/lang/reflect/Method;") + 1); + write1(out, ldc_w); + write2(out, ConstantPool.addInteger(pool, index) + 1); + write1(out, aaload); + + write1(out, ldc_w); + write2(out, ConstantPool.addInteger(pool, parameterCount) + 1); + write1(out, anewarray); + write2(out, ConstantPool.addClass(pool, "java/lang/Object") + 1); + + int ai = 0; + int si; + for (si = 1; spec[si] != ')'; ++si) { + write1(out, dup); + + write1(out, ldc_w); + write2(out, ConstantPool.addInteger(pool, ai) + 1); + + switch (spec[si]) { + case 'L': + ++ si; + while (spec[si] != ';') ++si; + + write1(out, aload); + write1(out, ai + 1); + break; + + case '[': + ++ si; + while (spec[si] == '[') ++si; + switch (spec[si]) { + case 'L': + ++ si; + while (spec[si] != ';') ++si; + break; + + default: + break; + } + + write1(out, aload); + write1(out, ai + 1); + break; + + case 'Z': + write1(out, iload); + write1(out, ai + 1); + + write1(out, invokestatic); + write2(out, ConstantPool.addMethodRef + (pool, "java/lang/Boolean", + "valueOf", "(Z)Ljava/lang/Boolean;") + 1); + break; + + case 'B': + write1(out, iload); + write1(out, ai + 1); + + write1(out, invokestatic); + write2(out, ConstantPool.addMethodRef + (pool, "java/lang/Byte", + "valueOf", "(B)Ljava/lang/Byte;") + 1); + break; + + case 'S': + write1(out, iload); + write1(out, ai + 1); + + write1(out, invokestatic); + write2(out, ConstantPool.addMethodRef + (pool, "java/lang/Short", + "valueOf", "(S)Ljava/lang/Short;") + 1); + break; + + case 'C': + write1(out, iload); + write1(out, ai + 1); + + write1(out, invokestatic); + write2(out, ConstantPool.addMethodRef + (pool, "java/lang/Character", + "valueOf", "(C)Ljava/lang/Character;") + 1); + break; + + case 'I': + write1(out, iload); + write1(out, ai + 1); + + write1(out, invokestatic); + write2(out, ConstantPool.addMethodRef + (pool, "java/lang/Integer", + "valueOf", "(I)Ljava/lang/Integer;") + 1); + break; + + case 'F': + write1(out, fload); + write1(out, ai + 1); + + write1(out, invokestatic); + write2(out, ConstantPool.addMethodRef + (pool, "java/lang/Float", + "valueOf", "(F)Ljava/lang/Float;") + 1); + break; + + case 'J': + write1(out, lload); + write1(out, ai + 1); + + write1(out, invokestatic); + write2(out, ConstantPool.addMethodRef + (pool, "java/lang/Long", + "valueOf", "(J)Ljava/lang/Long;") + 1); + ++ ai; + break; + + case 'D': + write1(out, dload); + write1(out, ai + 1); + + write1(out, invokestatic); + write2(out, ConstantPool.addMethodRef + (pool, "java/lang/Double", + "valueOf", "(D)Ljava/lang/Double;") + 1); + ++ ai; + break; + + default: throw new IllegalArgumentException(); + } + + write1(out, aastore); + + ++ ai; + } + + write1(out, invokeinterface); + write2(out, ConstantPool.addMethodRef + (pool, "java/lang/reflect/InvocationHandler", + "invoke", + "(Ljava/lang/Object;" + + "Ljava/lang/reflect/Method;" + + "[Ljava/lang/Object;)" + + "Ljava/lang/Object;") + 1); + write2(out, 0); // this will be ignored by the VM + + switch (spec[si + 1]) { + case 'L': + case '[': + write1(out, areturn); + break; + + case 'Z': + write1(out, invokevirtual); + write2(out, ConstantPool.addMethodRef + (pool, "java/lang/Boolean", "booleanValue", "()Z") + 1); + write1(out, ireturn); + break; + + case 'B': + write1(out, invokevirtual); + write2(out, ConstantPool.addMethodRef + (pool, "java/lang/Byte", "byteValue", "()B") + 1); + write1(out, ireturn); + break; + + case 'C': + write1(out, invokevirtual); + write2(out, ConstantPool.addMethodRef + (pool, "java/lang/Character", "charValue", "()C") + 1); + write1(out, ireturn); + break; + + case 'S': + write1(out, invokevirtual); + write2(out, ConstantPool.addMethodRef + (pool, "java/lang/Short", "shortValue", "()S") + 1); + write1(out, ireturn); + break; + + case 'I': + write1(out, invokevirtual); + write2(out, ConstantPool.addMethodRef + (pool, "java/lang/Integer", "intValue", "()I") + 1); + write1(out, ireturn); + break; + + case 'F': + write1(out, invokevirtual); + write2(out, ConstantPool.addMethodRef + (pool, "java/lang/Float", "floatValue", "()F") + 1); + write1(out, freturn); + break; + + case 'J': + write1(out, invokevirtual); + write2(out, ConstantPool.addMethodRef + (pool, "java/lang/Long", "longValue", "()J") + 1); + write1(out, lreturn); + break; + + case 'D': + write1(out, invokevirtual); + write2(out, ConstantPool.addMethodRef + (pool, "java/lang/Double", "doubleValue", "()D") + 1); + write1(out, dreturn); + break; + + case 'V': + write1(out, pop); + write1(out, return_); + break; + + default: throw new IllegalArgumentException(); + } + + write2(out, 0); // exception handler table length + write2(out, 0); // attribute count + + byte[] result = out.toByteArray(); + set4(result, 4, result.length - 12); + + return result; + } + + private static byte[] makeConstructorCode(List pool) + throws IOException + { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + write2(out, 2); // max stack + write2(out, 2); // max locals + write4(out, 10); // length + + write1(out, aload_0); + write1(out, invokespecial); + write2(out, ConstantPool.addMethodRef + (pool, "java/lang/reflect/Proxy", + "", "()V") + 1); + + write1(out, aload_0); + write1(out, aload_1); + write1(out, putfield); + write2(out, ConstantPool.addFieldRef + (pool, "java/lang/reflect/Proxy", + "h", "Ljava/lang/reflect/InvocationHandler;") + 1); + write1(out, return_); + + write2(out, 0); // exception handler table length + write2(out, 0); // attribute count + + return out.toByteArray(); + } + + private static Class makeClass(ClassLoader loader, + Class[] interfaces, + String name) + throws IOException + { + List pool = new ArrayList(); + + int[] interfaceIndexes = new int[interfaces.length]; + for (int i = 0; i < interfaces.length; ++i) { + interfaceIndexes[i] = ConstantPool.addClass + (pool, interfaces[i].getName().replace('.', '/')); + } + + Set specs = new HashSet(); + List methodTable = new ArrayList(); + List refs = new ArrayList(); + for (Class c: interfaces) { + avian.VMMethod[] ivtable = SystemClassLoader.vmClass(c).virtualTable; + if (ivtable != null) { + for (avian.VMMethod m: ivtable) { + String spec = Classes.toString(m.name) + Classes.toString(m.spec); + if (specs.contains(spec)) { + continue; + } + methodTable.add(new MethodData + (Modifier.PUBLIC, + ConstantPool.addUtf8(pool, Classes.toString(m.name)), + ConstantPool.addUtf8(pool, Classes.toString(m.spec)), + makeInvokeCode(pool, name, m.spec, m.parameterCount, + m.parameterFootprint, methodTable.size()))); + refs.add(Classes.makeMethod(m)); + } + } + } + + methodTable.add(new MethodData + (Modifier.PUBLIC, + ConstantPool.addUtf8(pool, ""), + ConstantPool.addUtf8 + (pool, "(Ljava/lang/reflect/InvocationHandler;)V"), + makeConstructorCode(pool))); + + int nameIndex = ConstantPool.addClass(pool, name); + int superIndex = ConstantPool.addClass(pool, "java/lang/reflect/Proxy"); + + ByteArrayOutputStream out = new ByteArrayOutputStream(); + Assembler.writeClass + (out, pool, nameIndex, superIndex, interfaceIndexes, + new FieldData[0], + methodTable.toArray(new MethodData[methodTable.size()])); + + byte[] classData = out.toByteArray(); + Class result = avian.SystemClassLoader.getClass + (avian.Classes.defineVMClass(loader, classData, 0, classData.length)); + methodRefsMap.put(result, refs.toArray(new Method[refs.size()])); + return result; + } + + public static Object newProxyInstance(ClassLoader loader, + Class[] interfaces, + InvocationHandler handler) + { + try { + return Proxy.getProxyClass(loader, interfaces) + .getConstructor(new Class[] { InvocationHandler.class }) + .newInstance(new Object[] { handler }); + } catch (Exception e) { + AssertionError error = new AssertionError(); + error.initCause(e); + throw error; + } + } +} diff --git a/sgx-jvm/avian/classpath/java/lang/reflect/SignatureParser.java b/sgx-jvm/avian/classpath/java/lang/reflect/SignatureParser.java new file mode 100644 index 0000000000..b32f4fdc24 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/lang/reflect/SignatureParser.java @@ -0,0 +1,258 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.lang.reflect; + +import avian.Classes; + +import java.util.ArrayList; +import java.util.List; +import java.util.LinkedList; +import java.util.Map; +import java.util.HashMap; + +public class SignatureParser { + private final ClassLoader loader; + private final char[] array; + private final String signature; + private int offset; + private final Type type; + private final Map typeVariables; + + public static Type parse(ClassLoader loader, String signature, Class declaringClass) { + return new SignatureParser(loader, signature, collectTypeVariables(declaringClass)).type; + } + + private static Type parse(ClassLoader loader, String signature, Map typeVariables) { + return new SignatureParser(loader, signature, typeVariables).type; + } + + private SignatureParser(ClassLoader loader, String signature, Map typeVariables) { + this.loader = loader; + this.signature = signature; + array = signature.toCharArray(); + this.typeVariables = typeVariables; + type = parseType(); + if (offset != array.length) { + throw new IllegalArgumentException("Extra characters after " + offset + + ": " + signature); + } + } + + private Type parseType() { + char c = array[offset++]; + if (c == 'B') { + return Byte.TYPE; + } else if (c == 'C') { + return Character.TYPE; + } else if (c == 'D') { + return Double.TYPE; + } else if (c == 'F') { + return Float.TYPE; + } else if (c == 'I') { + return Integer.TYPE; + } else if (c == 'J') { + return Long.TYPE; + } else if (c == 'S') { + return Short.TYPE; + } else if (c == 'Z') { + return Boolean.TYPE; + } else if (c == 'T') { + int end = signature.indexOf(';', offset); + if (end < 0) { + throw new RuntimeException("No semicolon found while parsing signature"); + } + Type res = typeVariables.get(new String(array, offset, end - offset)); + offset = end + 1; + return res; + } else if (c != 'L') { + throw new IllegalArgumentException("Unexpected character: " + c + ", signature: " + new String(array, 0, array.length) + ", i = " + offset); + } + StringBuilder builder = new StringBuilder(); + Type ownerType = null; + for (;;) { + for (;;) { + c = array[offset++]; + if (c == ';' || c == '<') { + break; + } + builder.append(c == '/' ? '.' : c); + } + String rawTypeName = builder.toString(); + Class rawType; + try { + rawType = loader.loadClass(rawTypeName); + } catch (ClassNotFoundException e) { + throw new RuntimeException("Could not find class " + rawTypeName); + } + + int lastDollar = rawTypeName.lastIndexOf('$'); + if (lastDollar != -1 && ownerType == null) { + String ownerName = rawTypeName.substring(0, lastDollar); + try { + ownerType = loader.loadClass(ownerName); + } catch (ClassNotFoundException e) { + throw new RuntimeException("Could not find class " + ownerName); + } + } + + if (c == ';') { + return rawType; + } + List args = new ArrayList(); + while (array[offset] != '>') { + args.add(parseType()); + } + ++offset; + c = array[offset++]; + ParameterizedType type = makeType(args.toArray(new Type[args.size()]), ownerType, rawType); + if (c == ';') { + return type; + } + if (c != '.') { + throw new RuntimeException("TODO"); + } + ownerType = type; + builder.append("$"); + } + } + + private static String typeName(Type type) { + if (type instanceof Class) { + Class clazz = (Class) type; + return clazz.getName(); + } + return type.toString(); + } + + private static ParameterizedType makeType(final Type[] args, final Type owner, final Type raw) { + return new ParameterizedType() { + @Override + public Type getRawType() { + return raw; + } + + @Override + public Type getOwnerType() { + return owner; + } + + @Override + public Type[] getActualTypeArguments() { + return args; + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append(typeName(raw)); + builder.append('<'); + String sep = ""; + for (Type t : args) { + builder.append(sep).append(typeName(t)); + sep = ", "; + } + builder.append('>'); + return builder.toString(); + } + }; + } + + private static Map collectTypeVariables(Class clz) { + Map varsMap = new HashMap(); + LinkedList classList = new LinkedList(); + for (Class c = clz; c != null; c = c.getDeclaringClass()) { + classList.addFirst(c); + } + + for (Class cur : classList) { + final LinkedList varsList = new LinkedList(); + if (cur.vmClass.addendum != null && cur.vmClass.addendum.signature != null) { + String signature = Classes.toString((byte[]) cur.vmClass.addendum.signature); + final char[] signChars = signature.toCharArray(); + try { + int i = 0; + if (signChars[i] == '<') { + i++; + do { + final int colon = signature.indexOf(':', i); + if (colon < 0 || colon + 1 == signChars.length) { + throw new RuntimeException("Can't find ':' in the signature " + signature + " starting from " + i); + } + String typeVarName = new String(signChars, i, colon - i); + i = colon + 1; + + int start = i; + int angles = 0; + while (angles > 0 || signChars[i] != ';') { + if (signChars[i] == '<') angles ++; + else if (signChars[i] == '>') angles --; + i++; + } + String typeName = new String(signChars, start, i - start + 1); + final Type baseType = SignatureParser.parse(cur.vmClass.loader, typeName, varsMap); + + TypeVariableImpl tv = new TypeVariableImpl(typeVarName, baseType); + varsList.add(tv); + + i++; + } while (signChars[i] != '>'); + + } + } catch (IndexOutOfBoundsException e) { + throw new RuntimeException("Signature of " + cur + " is broken (" + signature + ") and can't be parsed", e); + } + } + for (TypeVariableImpl tv : varsList) { + tv.setVars(varsList); + varsMap.put(tv.getName(), tv); + } + cur = cur.getDeclaringClass(); + }; + return varsMap; + } + + private static class TypeVariableImpl implements TypeVariable { + private String name; + private Type baseType; + private TypeVariableImpl[] vars; + + public Type[] getBounds() { + return new Type[] { baseType }; + } + + public GenericDeclaration getGenericDeclaration() { + return new GenericDeclaration() { + public TypeVariable[] getTypeParameters() { + return vars; + } + }; + } + + public String getName() { + return name; + } + + TypeVariableImpl(String name, Type baseType) { + this.name = name; + this.baseType = baseType; + } + + void setVars(List vars) { + this.vars = new TypeVariableImpl[vars.size()]; + vars.toArray(this.vars); + } + + @Override + public String toString() { + return name; + } + } +} diff --git a/sgx-jvm/avian/classpath/java/lang/reflect/Type.java b/sgx-jvm/avian/classpath/java/lang/reflect/Type.java new file mode 100644 index 0000000000..c4deabf16e --- /dev/null +++ b/sgx-jvm/avian/classpath/java/lang/reflect/Type.java @@ -0,0 +1,13 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.lang.reflect; + +public interface Type { } diff --git a/sgx-jvm/avian/classpath/java/lang/reflect/TypeVariable.java b/sgx-jvm/avian/classpath/java/lang/reflect/TypeVariable.java new file mode 100644 index 0000000000..5d01787ada --- /dev/null +++ b/sgx-jvm/avian/classpath/java/lang/reflect/TypeVariable.java @@ -0,0 +1,7 @@ +package java.lang.reflect; + +public interface TypeVariable extends Type { + Type[] getBounds(); + D getGenericDeclaration(); + String getName(); +} diff --git a/sgx-jvm/avian/classpath/java/math/BigInteger.java b/sgx-jvm/avian/classpath/java/math/BigInteger.java new file mode 100644 index 0000000000..54df95b9e8 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/math/BigInteger.java @@ -0,0 +1,44 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.math; + +import java.io.Serializable; + +public class BigInteger implements Serializable { + + private int sign; + private int[] value; + + private BigInteger(int sign, long value) { + this.sign = sign; + int upperBits = (int) (value >>> 32); + if (upperBits == 0) + // Array with one element + this.value = new int[] { (int) value }; + else + // Array with two elements + this.value = new int[] { (int) value, upperBits }; + } + + public static final BigInteger ZERO = new BigInteger(0, 0); + public static final BigInteger ONE = new BigInteger(1, 1); + public static final BigInteger TEN = new BigInteger(1, 10); + + public static BigInteger valueOf(long num) { + int signum = Long.signum(num); + if (signum == 0) + return BigInteger.ZERO; + else if (signum > 0) + return new BigInteger(signum, num); + else + return new BigInteger(signum, -num); + } +} diff --git a/sgx-jvm/avian/classpath/java/math/MathContext.java b/sgx-jvm/avian/classpath/java/math/MathContext.java new file mode 100644 index 0000000000..8a8fe79607 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/math/MathContext.java @@ -0,0 +1,71 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.math; + +import java.io.Serializable; + +public final class MathContext implements Serializable { + + public static final MathContext DECIMAL32 = new MathContext( 7, RoundingMode.HALF_EVEN); + public static final MathContext DECIMAL64 = new MathContext(16, RoundingMode.HALF_EVEN); + public static final MathContext DECIMAL128 = new MathContext(34, RoundingMode.HALF_EVEN); + public static final MathContext UNLIMITED = new MathContext(0, RoundingMode.HALF_UP); + + private int precision; + private RoundingMode roundingMode; + + public MathContext(int precision, RoundingMode roundingMode) { + if (precision < 0) + throw new IllegalArgumentException(); + if (roundingMode == null) + throw new NullPointerException(); + this.precision = precision; + this.roundingMode = roundingMode; + } + + public MathContext(int precision) { + this(precision, RoundingMode.HALF_UP); + } + + public int getPrecision() { + return precision; + } + + public RoundingMode getRoundingMode() { + return roundingMode; + } + + @Override + public boolean equals(Object that) { + return + (that instanceof MathContext) && + (precision == ((MathContext) that).getPrecision()) && + (roundingMode == ((MathContext) that).getRoundingMode()); + } + + @Override + public int hashCode() { + return + roundingMode.ordinal() | + (precision << 4); + } + + private final static String precisionString = "precision="; + private final static String roundingModeString = " roundingMode="; + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(48); + sb.append(precisionString).append(precision); + sb.append(roundingModeString).append(roundingMode); + return sb.toString(); + } +} diff --git a/sgx-jvm/avian/classpath/java/math/RoundingMode.java b/sgx-jvm/avian/classpath/java/math/RoundingMode.java new file mode 100644 index 0000000000..4ea32d8e30 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/math/RoundingMode.java @@ -0,0 +1,36 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.math; + +public enum RoundingMode { + + UP (0), + DOWN (1), + CEILING (2), + FLOOR (3), + HALF_UP (4), + HALF_DOWN (5), + HALF_EVEN (6), + UNNECESSARY(7); + + RoundingMode(int rm) { + roundingMode = rm; + } + + private final int roundingMode; + + public static RoundingMode valueOf(int roundingMode) { + final RoundingMode[] values = values(); + if (roundingMode < 0 || roundingMode >= values.length) + throw new IllegalArgumentException(); + return values[roundingMode]; + } +} diff --git a/sgx-jvm/avian/classpath/java/net/BindException.java b/sgx-jvm/avian/classpath/java/net/BindException.java new file mode 100644 index 0000000000..18c6e08473 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/net/BindException.java @@ -0,0 +1,21 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.net; + +public class BindException extends SocketException { + public BindException(String message) { + super(message); + } + + public BindException() { + this(null); + } +} diff --git a/sgx-jvm/avian/classpath/java/net/DatagramSocket.java b/sgx-jvm/avian/classpath/java/net/DatagramSocket.java new file mode 100644 index 0000000000..911550a8aa --- /dev/null +++ b/sgx-jvm/avian/classpath/java/net/DatagramSocket.java @@ -0,0 +1,19 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.net; + +import java.io.IOException; + +public abstract class DatagramSocket { + public abstract SocketAddress getRemoteSocketAddress(); + + public abstract void bind(SocketAddress address) throws SocketException; +} diff --git a/sgx-jvm/avian/classpath/java/net/InetAddress.java b/sgx-jvm/avian/classpath/java/net/InetAddress.java new file mode 100644 index 0000000000..8ddecac67c --- /dev/null +++ b/sgx-jvm/avian/classpath/java/net/InetAddress.java @@ -0,0 +1,78 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.net; + +import java.io.IOException; + +public class InetAddress { + private final String name; + private final int ip; + + private InetAddress(String name) throws UnknownHostException { + this.name = name; + this.ip = ipv4AddressForName(name); + } + + public String getHostName() { + return name; + } + + public String getHostAddress() { + try { + return new InetAddress(name).toString(); + } catch (UnknownHostException e) { + return null; // Strange case + } + } + + public static InetAddress getByName(String name) throws UnknownHostException { + try { + Socket.init(); + return new InetAddress(name); + } catch (IOException e) { + UnknownHostException uhe = new UnknownHostException(name); + uhe.initCause(e); + throw uhe; + } + } + + public byte[] getAddress() { + byte[] res = new byte[4]; + res[0] = (byte) ( ip >>> 24); + res[1] = (byte) ((ip >>> 16) & 0xFF); + res[2] = (byte) ((ip >>> 8 ) & 0xFF); + res[3] = (byte) ((ip ) & 0xFF); + return res; + } + + @Override + public String toString() { + byte[] addr = getAddress(); + return (int)((addr[0] + 256) % 256) + "." + + (int)((addr[1] + 256) % 256) + "." + + (int)((addr[2] + 256) % 256) + "." + + (int)((addr[3] + 256) % 256); + } + + public int getRawAddress() { + return ip; + } + + static native int ipv4AddressForName(String name) throws UnknownHostException; + + public boolean equals(Object o) { + return o instanceof InetAddress && ((InetAddress) o).ip == ip; + } + + public int hashCode() { + return ip; + } +} diff --git a/sgx-jvm/avian/classpath/java/net/InetSocketAddress.java b/sgx-jvm/avian/classpath/java/net/InetSocketAddress.java new file mode 100644 index 0000000000..01d34a8734 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/net/InetSocketAddress.java @@ -0,0 +1,65 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.net; + +public class InetSocketAddress extends SocketAddress { + private final String host; + private final InetAddress address; + private final int port; + + public InetSocketAddress(String host, int port) { + InetAddress address; + try { + address = InetAddress.getByName(host); + host = address.getHostName(); + } catch (UnknownHostException e) { + address = null; + } + this.host = host; + this.address = address; + this.port = port; + } + + public InetSocketAddress(InetAddress address, int port) { + this.host = address.getHostName(); + this.address = address; + this.port = port; + } + + public InetAddress getAddress() { + return address; + } + + public String getHostName() { + return host; + } + + public int getPort() { + return port; + } + + public boolean equals(Object o) { + if (o instanceof InetSocketAddress) { + InetSocketAddress a = (InetSocketAddress) o; + return a.address.equals(address) && a.port == port; + } else { + return false; + } + } + + public int hashCode() { + return port ^ address.hashCode(); + } + + public String toString() { + return getHostName() + ":" + port; + } +} diff --git a/sgx-jvm/avian/classpath/java/net/JarURLConnection.java b/sgx-jvm/avian/classpath/java/net/JarURLConnection.java new file mode 100644 index 0000000000..bdfa5834fb --- /dev/null +++ b/sgx-jvm/avian/classpath/java/net/JarURLConnection.java @@ -0,0 +1,22 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.net; + +import java.io.IOException; +import java.util.jar.JarFile; + +public abstract class JarURLConnection extends URLConnection { + public JarURLConnection(URL url) { + super(url); + } + + public abstract JarFile getJarFile() throws IOException; +} diff --git a/sgx-jvm/avian/classpath/java/net/MalformedURLException.java b/sgx-jvm/avian/classpath/java/net/MalformedURLException.java new file mode 100644 index 0000000000..a635c7d457 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/net/MalformedURLException.java @@ -0,0 +1,21 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.net; + +public class MalformedURLException extends Exception { + public MalformedURLException(String message) { + super(message); + } + + public MalformedURLException() { + this(null); + } +} diff --git a/sgx-jvm/avian/classpath/java/net/ProtocolFamily.java b/sgx-jvm/avian/classpath/java/net/ProtocolFamily.java new file mode 100644 index 0000000000..7cbaaad567 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/net/ProtocolFamily.java @@ -0,0 +1,13 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.net; + +public interface ProtocolFamily { } diff --git a/sgx-jvm/avian/classpath/java/net/ServerSocket.java b/sgx-jvm/avian/classpath/java/net/ServerSocket.java new file mode 100644 index 0000000000..21836741ae --- /dev/null +++ b/sgx-jvm/avian/classpath/java/net/ServerSocket.java @@ -0,0 +1,17 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.net; + +import java.io.IOException; + +public abstract class ServerSocket { + public abstract void bind(SocketAddress address) throws IOException; +} diff --git a/sgx-jvm/avian/classpath/java/net/Socket.java b/sgx-jvm/avian/classpath/java/net/Socket.java new file mode 100644 index 0000000000..9a32b88f7c --- /dev/null +++ b/sgx-jvm/avian/classpath/java/net/Socket.java @@ -0,0 +1,201 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.net; + +import java.io.Closeable; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + +public class Socket implements Closeable, AutoCloseable { + + private static final int SD_RECEIVE = 0x00; + private static final int SD_SEND = 0x01; + private static final int SD_BOTH = 0x02; + + private static final int BUFFER_SIZE = 65535; + + /** + * This method is called from all routines that depend on winsock in windows, + * so it has public visibility + * @throws IOException + */ + public static native void init() throws IOException; + + /** + * Creates the native socket object + * @return Handle to the native object + * @throws IOException + */ + private static native /* SOCKET */long create() throws IOException; + + /** + * Connects the native socket object to an address:port + * @param sock Native socket handler + * @param addr Address to connect to + * @param port Port to connect to + * @throws IOException + */ + private static native void connect(/* SOCKET */long sock, long addr, short port) throws IOException; + private static native void bind(/* SOCKET */long sock, long addr, short port) throws IOException; + + private static native void send(/* SOCKET */long sock, byte[] buffer, int start_pos, int count) throws IOException; + private static native int recv(/* SOCKET */long sock, byte[] buffer, int start_pos, int count) throws IOException; + + private static native void abort(/* SOCKET */long sock); + private static native void close(/* SOCKET */long sock); + private static native void closeOutput(/* SOCKET */long sock); + private static native void closeInput(/* SOCKET */long sock); + + private class SocketInputStream extends InputStream { + + private boolean closed = false; + + @Override + public void close() throws IOException { + if (!closed) { + closeInput(sock); + closed = true; + } + super.close(); + } + + @Override + protected void finalize() throws Throwable { + close(); + super.finalize(); + } + + @Override + public int read() throws IOException { + byte[] buffer = new byte[1]; + int size = recv(sock, buffer, 0, 1); + if (size == 0) { + return -1; + } + return buffer[0]; + } + + @Override + public int read(byte[] buffer) throws IOException { + if(buffer.length == 0) return 0; //spec says return 0 if buffer length is zero. + int fullSize = buffer.length; + int size; + size = recv(sock, buffer, 0, Math.min(fullSize, Socket.BUFFER_SIZE)); + fullSize -= size; + //removed loop, because otherwise interactive protocols will not work. + if(size < 0) throw new IOException("Error while reading stream"); //as the manpage of recv says, a value below zero indicates an error. + if(size == 0) return -1; // if the stream is closed (size == 0), then return -1 to indicate end of stream. + return size; + } + } + + private class SocketOutputStream extends OutputStream { + + private boolean closed = false; + + @Override + public void close() throws IOException { + if (!closed) { + closeOutput(sock); + closed = true; + } + super.close(); + } + + @Override + protected void finalize() throws Throwable { + close(); + super.finalize(); + } + + @Override + public void write(int c) throws IOException { + byte[] res = new byte[1]; + res[0] = (byte)c; + send(sock, res, 0, 1); + } + + @Override + public void write(byte[] buffer) throws IOException { + int fullSize = buffer.length; + int index = 0; + int size; + do { + size = Math.min(fullSize, Socket.BUFFER_SIZE); + send(sock, buffer, index, size); + fullSize -= size; + index += size; + } while (fullSize != 0 && size != 0); + } + + } + + private long sock; + private SocketInputStream inputStream; + private SocketOutputStream outputStream; + + public Socket() throws IOException { + Socket.init(); + sock = create(); + inputStream = new SocketInputStream(); + outputStream = new SocketOutputStream(); + } + + public SocketInputStream getInputStream() { + return inputStream; + } + + public SocketOutputStream getOutputStream() { + return outputStream; + } + + public Socket(InetAddress address, int port) throws IOException { + this(); + connect(sock, address.getRawAddress(), (short)port); + } + + public Socket(String host, int port) throws UnknownHostException, IOException { + this(InetAddress.getByName(host), port); + } + + public void bind(SocketAddress bindpoint) throws IOException { + if (bindpoint instanceof InetSocketAddress) { + InetSocketAddress inetBindpoint = (InetSocketAddress)bindpoint; + bind(sock, inetBindpoint.getAddress().getRawAddress(), (short) inetBindpoint.getPort()); + } + } + + public void setTcpNoDelay(boolean on) throws SocketException {} + + @Override + public void close() throws IOException { + close(sock); + } + + public void shutdownInput() throws IOException { + inputStream.close(); + } + + public void shutdownOutput() throws IOException { + outputStream.close(); + } + + public SocketAddress getRemoteSocketAddress() { + throw new UnsupportedOperationException(); + } + + @Override + protected void finalize() throws Throwable { + close(); + super.finalize(); + } +} diff --git a/sgx-jvm/avian/classpath/java/net/SocketAddress.java b/sgx-jvm/avian/classpath/java/net/SocketAddress.java new file mode 100644 index 0000000000..c0d6cafe42 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/net/SocketAddress.java @@ -0,0 +1,13 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.net; + +public abstract class SocketAddress { } diff --git a/sgx-jvm/avian/classpath/java/net/SocketException.java b/sgx-jvm/avian/classpath/java/net/SocketException.java new file mode 100644 index 0000000000..6d3da998ea --- /dev/null +++ b/sgx-jvm/avian/classpath/java/net/SocketException.java @@ -0,0 +1,23 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.net; + +import java.io.IOException; + +public class SocketException extends IOException { + public SocketException(String message) { + super(message); + } + + public SocketException() { + this(null); + } +} diff --git a/sgx-jvm/avian/classpath/java/net/StandardProtocolFamily.java b/sgx-jvm/avian/classpath/java/net/StandardProtocolFamily.java new file mode 100644 index 0000000000..4a7f1e8a4e --- /dev/null +++ b/sgx-jvm/avian/classpath/java/net/StandardProtocolFamily.java @@ -0,0 +1,15 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.net; + +public enum StandardProtocolFamily implements ProtocolFamily { + INET; +} diff --git a/sgx-jvm/avian/classpath/java/net/URL.java b/sgx-jvm/avian/classpath/java/net/URL.java new file mode 100644 index 0000000000..86f244786f --- /dev/null +++ b/sgx-jvm/avian/classpath/java/net/URL.java @@ -0,0 +1,114 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.net; + +import java.io.IOException; +import java.io.InputStream; + +public final class URL { + private final URLStreamHandler handler; + private String protocol; + private String host; + private int port; + private String file; + private String path; + private String query; + private String ref; + + public URL(String s) throws MalformedURLException { + int colon = s.indexOf(':'); + int slash = s.indexOf('/'); + if (colon > 0 && (slash < 0 || colon < slash)) { + handler = findHandler(s.substring(0, colon)); + handler.parseURL(this, s, colon + 1, s.length()); + } else { + throw new MalformedURLException(s); + } + } + + public String toString() { + return handler.toExternalForm(this); + } + + public String getProtocol() { + return protocol; + } + + public String getHost() { + return host; + } + + public int getPort() { + return port; + } + + public String getFile() { + return file; + } + + public String getRef() { + return ref; + } + + public String getPath() { + return path; + } + + public String getQuery() { + return query; + } + + public URLConnection openConnection() throws IOException { + return handler.openConnection(this); + } + + public InputStream openStream() throws IOException { + return openConnection().getInputStream(); + } + + public Object getContent() throws IOException { + return openStream(); + } + + private static URLStreamHandler findHandler(String protocol) + throws MalformedURLException + { + if ("http".equals(protocol) || "https".equals(protocol)) { + return new avian.http.Handler(); + } else if ("avianvmresource".equals(protocol)) { + return new avian.avianvmresource.Handler(); + } else if ("file".equals(protocol)) { + return new avian.file.Handler(); + } else if ("jar".equals(protocol)) { + return new avian.jar.Handler(); + } else { + throw new MalformedURLException("unknown protocol: " + protocol); + } + } + + public void set(String protocol, String host, int port, String file, + String ref) + { + this.protocol = protocol; + this.host = host; + this.port = port; + this.file = file; + this.ref = ref; + + int q = file == null ? -1 : file.lastIndexOf('?'); + if (q != -1) { + this.query = file.substring(q + 1); + this.path = file.substring(0, q); + } else { + this.path = file; + } + } +} diff --git a/sgx-jvm/avian/classpath/java/net/URLClassLoader.java b/sgx-jvm/avian/classpath/java/net/URLClassLoader.java new file mode 100644 index 0000000000..2d210f13af --- /dev/null +++ b/sgx-jvm/avian/classpath/java/net/URLClassLoader.java @@ -0,0 +1,67 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.net; + +import java.io.File; + +import java.io.InputStream; +import java.io.IOException; +import java.io.ByteArrayOutputStream; + +public class URLClassLoader extends ClassLoader { + + private final File jarFile; + + public URLClassLoader(URL[] urls, ClassLoader parent) { + super(parent); + if(urls.length != 1) { + throw new UnsupportedOperationException(); + } + if(!urls[0].getProtocol().equals("file")) { + throw new UnsupportedOperationException(urls[0].getProtocol()); + } + this.jarFile = new File(urls[0].getFile()); + } + + + protected Class findClass(String name) throws ClassNotFoundException { + try { + InputStream stream = getResourceAsStream(name.replace(".", "/") + ".class"); + if(stream == null) { + throw new ClassNotFoundException("couldn't find class " + name); + } + byte[] buf = new byte[2048]; + ByteArrayOutputStream mem = new ByteArrayOutputStream(); + try { + int size; + while((size = stream.read(buf, 0, buf.length)) > 0) { + mem.write(buf, 0, size); + } + byte[] data = mem.toByteArray(); + return defineClass(name, data, 0, data.length); + } finally { + stream.close(); + } + } catch(IOException e) { + throw new ClassNotFoundException("couldn't find class " + name, e); + } + } + + public URL getResource(String path) { + try { + return new URL("jar:file:" + jarFile.getAbsolutePath() + "!/" + path); + } catch(MalformedURLException e) { + throw new RuntimeException(e); + } + } + + +} \ No newline at end of file diff --git a/sgx-jvm/avian/classpath/java/net/URLConnection.java b/sgx-jvm/avian/classpath/java/net/URLConnection.java new file mode 100644 index 0000000000..0a34889e42 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/net/URLConnection.java @@ -0,0 +1,64 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.net; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + +public abstract class URLConnection { + protected final URL url; + protected boolean doInput = true; + protected boolean doOutput = false; + protected boolean useCaches = true; + + protected URLConnection(URL url) { + this.url = url; + } + + public Object getContent() throws IOException { + return getInputStream(); + } + + public int getContentLength() { + return -1; + } + + public abstract void connect() throws IOException; + + public InputStream getInputStream() throws IOException { + throw new UnknownServiceException(); + } + + public OutputStream getOutputStream() throws IOException { + throw new UnknownServiceException(); + } + + public boolean getDoInput() { + return doInput; + } + + public boolean getDoOutput() { + return doOutput; + } + + public void setDoInput(boolean v) { + doInput = v; + } + + public void setDoOutput(boolean v) { + doInput = v; + } + + public void setUseCaches(boolean v) { + useCaches = v; + } +} diff --git a/sgx-jvm/avian/classpath/java/net/URLStreamHandler.java b/sgx-jvm/avian/classpath/java/net/URLStreamHandler.java new file mode 100644 index 0000000000..3699c73d18 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/net/URLStreamHandler.java @@ -0,0 +1,81 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.net; + +import java.io.IOException; + +public abstract class URLStreamHandler { + protected void parseURL(URL url, String s, int start, int end) + throws MalformedURLException + { + String protocol = s.substring(0, start - 1); + s = s.substring(start, end); + + String host = null; + int port = -1; + if (s.startsWith("//")) { + s = s.substring(2); + int colon = s.indexOf(':'); + int slash = s.indexOf('/'); + if (slash < 0) { + if (colon < 0) { + host = s; + } else { + host = s.substring(0, colon); + port = Integer.parseInt(s.substring(colon + 1)); + } + s = ""; + } else { + if (colon < 0 || colon > slash) { + host = s.substring(0, slash); + } else { + host = s.substring(0, colon); + port = Integer.parseInt(s.substring(colon + 1, slash)); + } + s = s.substring(slash); + } + } + + String file = null; + if (s.length() > 0) { + file = s; + } + + url.set(protocol, host, port, file, null); + } + + private static boolean equals(String a, String b) { + return (a == null && b == null) || (a != null && a.equals(b)); + } + + protected boolean equals(URL a, URL b) { + return equals(a.getHost(), b.getHost()) + && (a.getPort() == b.getPort()) + && equals(a.getFile(), b.getFile()); + } + + protected String toExternalForm(URL url) { + StringBuilder sb = new StringBuilder(); + sb.append(url.getProtocol()).append(":"); + if (url.getHost() != null) { + sb.append("//").append(url.getHost()); + if (url.getPort() >= 0) { + sb.append(":").append(url.getPort()); + } + } + if (url.getFile() != null) { + sb.append(url.getFile()); + } + return sb.toString(); + } + + protected abstract URLConnection openConnection(URL url) throws IOException; +} diff --git a/sgx-jvm/avian/classpath/java/net/UnknownHostException.java b/sgx-jvm/avian/classpath/java/net/UnknownHostException.java new file mode 100644 index 0000000000..4e4acd1ef3 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/net/UnknownHostException.java @@ -0,0 +1,21 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.net; + +import java.io.IOException; + +public class UnknownHostException extends IOException { + public UnknownHostException(String host) { + super(host); + } + + public UnknownHostException() { } +} diff --git a/sgx-jvm/avian/classpath/java/net/UnknownServiceException.java b/sgx-jvm/avian/classpath/java/net/UnknownServiceException.java new file mode 100644 index 0000000000..1c415de16e --- /dev/null +++ b/sgx-jvm/avian/classpath/java/net/UnknownServiceException.java @@ -0,0 +1,23 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.net; + +import java.io.IOException; + +public class UnknownServiceException extends IOException { + public UnknownServiceException(String message) { + super(message); + } + + public UnknownServiceException() { + this(null); + } +} diff --git a/sgx-jvm/avian/classpath/java/nio/ArrayByteBuffer.java b/sgx-jvm/avian/classpath/java/nio/ArrayByteBuffer.java new file mode 100644 index 0000000000..d0e41a2e0c --- /dev/null +++ b/sgx-jvm/avian/classpath/java/nio/ArrayByteBuffer.java @@ -0,0 +1,100 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.nio; + +class ArrayByteBuffer extends ByteBuffer { + private final byte[] array; + private final int arrayOffset; + + ArrayByteBuffer(byte[] array, int offset, int length, boolean readOnly) { + super(readOnly); + + this.array = array; + this.arrayOffset = offset; + this.capacity = length; + this.limit = length; + this.position = 0; + } + + public ByteBuffer asReadOnlyBuffer() { + ByteBuffer b = new ArrayByteBuffer(array, arrayOffset, capacity, true); + b.position(position()); + b.limit(limit()); + return b; + } + + public boolean hasArray() { + return true; + } + + public byte[] array() { + return array; + } + + public ByteBuffer slice() { + return new ArrayByteBuffer + (array, arrayOffset + position, remaining(), true); + } + + public int arrayOffset() { + return arrayOffset; + } + + protected void doPut(int position, byte val) { + array[arrayOffset + position] = val; + } + + public ByteBuffer put(ByteBuffer src) { + int length = src.remaining(); + checkPut(position, length, false); + src.get(array, arrayOffset + position, length); + position += length; + return this; + } + + public ByteBuffer put(byte[] src, int offset, int length) { + checkPut(position, length, false); + + System.arraycopy(src, offset, array, arrayOffset + position, length); + position += length; + + return this; + } + + public ByteBuffer get(byte[] dst, int offset, int length) { + checkGet(position, length, false); + + System.arraycopy(array, arrayOffset + position, dst, offset, length); + position += length; + + return this; + } + + protected byte doGet(int position) { + return array[arrayOffset+position]; + } + + public String toString() { + return "(ArrayByteBuffer with array: " + array + + " arrayOffset: " + arrayOffset + + " position: " + position + + " limit: " + limit + + " capacity: " + capacity + ")"; + } + + @Override + public ByteBuffer duplicate() { + ByteBuffer b = new ArrayByteBuffer(array, arrayOffset, capacity, isReadOnly()); + b.limit(this.limit()); + b.position(this.position()); + return b; + } +} diff --git a/sgx-jvm/avian/classpath/java/nio/ArrayCharBuffer.java b/sgx-jvm/avian/classpath/java/nio/ArrayCharBuffer.java new file mode 100644 index 0000000000..a4e93aa191 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/nio/ArrayCharBuffer.java @@ -0,0 +1,92 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.nio; + +class ArrayCharBuffer extends CharBuffer { + private final char[] array; + private final int arrayOffset; + + ArrayCharBuffer(char[] array, int offset, int length, boolean readOnly) { + super(readOnly); + + this.array = array; + this.arrayOffset = offset; + this.capacity = length; + this.limit = length; + this.position = 0; + } + + public CharBuffer asReadOnlyBuffer() { + CharBuffer b = new ArrayCharBuffer(array, arrayOffset, capacity, true); + b.position(position()); + b.limit(limit()); + return b; + } + + public boolean hasArray() { + return true; + } + + public char[] array() { + return array; + } + + public CharBuffer slice() { + return new ArrayCharBuffer + (array, arrayOffset + position, remaining(), true); + } + + public int arrayOffset() { + return arrayOffset; + } + + protected void doPut(int position, char val) { + array[arrayOffset + position] = val; + } + + public CharBuffer put(CharBuffer src) { + int length = src.remaining(); + checkPut(position, length, false); + src.get(array, arrayOffset + position, length); + position += length; + return this; + } + + public CharBuffer put(char[] src, int offset, int length) { + checkPut(position, length, false); + + System.arraycopy(src, offset, array, arrayOffset + position, length); + position += length; + + return this; + } + + public CharBuffer get(char[] dst, int offset, int length) { + checkGet(position, length, false); + + System.arraycopy(array, arrayOffset + position, dst, offset, length); + position += length; + + return this; + } + + protected char doGet(int position) { + return array[arrayOffset+position]; + } + + public String toString() { + return "(ArrayCharBuffer with array: " + array + + " arrayOffset: " + arrayOffset + + " position: " + position + + " limit: " + limit + + " capacity: " + capacity + ")"; + } +} diff --git a/sgx-jvm/avian/classpath/java/nio/Buffer.java b/sgx-jvm/avian/classpath/java/nio/Buffer.java new file mode 100644 index 0000000000..f03e178a2b --- /dev/null +++ b/sgx-jvm/avian/classpath/java/nio/Buffer.java @@ -0,0 +1,69 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.nio; + +public abstract class Buffer { + protected int capacity; + protected int position; + protected int limit; + protected boolean readonly; + + public final int limit() { + return limit; + } + + public final int remaining() { + return limit-position; + } + + public final int position() { + return position; + } + + public final int capacity() { + return capacity; + } + + public final Buffer limit(int newLimit) { + limit = newLimit; + return this; + } + + public final Buffer position(int newPosition) { + position = newPosition; + return this; + } + + public final boolean hasRemaining() { + return remaining() > 0; + } + + public final Buffer clear() { + position = 0; + limit = capacity; + return this; + } + + public final Buffer flip() { + limit = position; + position = 0; + return this; + } + + public final Buffer rewind() { + position = 0; + return this; + } + + public boolean isReadOnly() { + return readonly; + } +} diff --git a/sgx-jvm/avian/classpath/java/nio/BufferOverflowException.java b/sgx-jvm/avian/classpath/java/nio/BufferOverflowException.java new file mode 100644 index 0000000000..b1cb402ab2 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/nio/BufferOverflowException.java @@ -0,0 +1,14 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.nio; + +public class BufferOverflowException extends RuntimeException { +} diff --git a/sgx-jvm/avian/classpath/java/nio/BufferUnderflowException.java b/sgx-jvm/avian/classpath/java/nio/BufferUnderflowException.java new file mode 100644 index 0000000000..ec6afd7e75 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/nio/BufferUnderflowException.java @@ -0,0 +1,14 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.nio; + +public class BufferUnderflowException extends RuntimeException { +} diff --git a/sgx-jvm/avian/classpath/java/nio/ByteBuffer.java b/sgx-jvm/avian/classpath/java/nio/ByteBuffer.java new file mode 100644 index 0000000000..fddb06481b --- /dev/null +++ b/sgx-jvm/avian/classpath/java/nio/ByteBuffer.java @@ -0,0 +1,337 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.nio; + +public abstract class ByteBuffer + extends Buffer + implements Comparable +{ + + protected ByteBuffer(boolean readOnly) { + this.readonly = readOnly; + } + + public static ByteBuffer allocate(int capacity) { + return new ArrayByteBuffer(new byte[capacity], 0, capacity, false); + } + + public static ByteBuffer allocateDirect(int capacity) { + return FixedArrayByteBuffer.make(capacity); + } + + public static ByteBuffer wrap(byte[] array) { + return wrap(array, 0, array.length); + } + + public static ByteBuffer wrap(byte[] array, int offset, int length) { + return new ArrayByteBuffer(array, offset, length, false); + } + + public abstract ByteBuffer asReadOnlyBuffer(); + + public abstract ByteBuffer slice(); + + public abstract ByteBuffer duplicate(); + + protected abstract void doPut(int offset, byte val); + + public abstract ByteBuffer put(byte[] arr, int offset, int len); + + protected abstract byte doGet(int offset); + + public abstract ByteBuffer get(byte[] dst, int offset, int length); + + public boolean hasArray() { + return false; + } + + public ByteBuffer compact() { + int remaining = remaining(); + + if (position != 0) { + ByteBuffer b = slice(); + position = 0; + put(b); + } + + position = remaining; + limit(capacity()); + + return this; + } + + public ByteBuffer put(ByteBuffer src) { + if (src.hasArray()) { + checkPut(position, src.remaining(), false); + + put(src.array(), src.arrayOffset() + src.position, src.remaining()); + src.position(src.position() + src.remaining()); + + return this; + } else { + byte[] buffer = new byte[src.remaining()]; + src.get(buffer); + return put(buffer); + } + } + + public int compareTo(ByteBuffer o) { + int end = (remaining() < o.remaining() ? remaining() : o.remaining()); + + for (int i = 0; i < end; ++i) { + int d = get(position + i) - o.get(o.position + i); + if (d != 0) { + return d; + } + } + return remaining() - o.remaining(); + } + + public boolean equals(Object o) { + return o instanceof ByteBuffer && compareTo((ByteBuffer) o) == 0; + } + + public byte[] array() { + throw new UnsupportedOperationException(); + } + + public int arrayOffset() { + throw new UnsupportedOperationException(); + } + + public ByteBuffer put(int offset, byte val) { + checkPut(offset, 1, true); + doPut(offset, val); + return this; + } + + public ByteBuffer put(byte val) { + checkPut(position, 1, false); + doPut(position, val); + ++ position; + return this; + } + + public ByteBuffer put(byte[] arr) { + return put(arr, 0, arr.length); + } + + private void rawPutLong(int position, long val) { + doPut(position , (byte) ((val >> 56) & 0xff)); + doPut(position + 1, (byte) ((val >> 48) & 0xff)); + doPut(position + 2, (byte) ((val >> 40) & 0xff)); + doPut(position + 3, (byte) ((val >> 32) & 0xff)); + doPut(position + 4, (byte) ((val >> 24) & 0xff)); + doPut(position + 5, (byte) ((val >> 16) & 0xff)); + doPut(position + 6, (byte) ((val >> 8) & 0xff)); + doPut(position + 7, (byte) ((val ) & 0xff)); + } + + private void rawPutInt(int position, int val) { + doPut(position , (byte) ((val >> 24) & 0xff)); + doPut(position + 1, (byte) ((val >> 16) & 0xff)); + doPut(position + 2, (byte) ((val >> 8) & 0xff)); + doPut(position + 3, (byte) ((val ) & 0xff)); + } + + private void rawPutShort(int position, short val) { + doPut(position , (byte) ((val >> 8) & 0xff)); + doPut(position + 1, (byte) ((val ) & 0xff)); + } + + public ByteBuffer putDouble(int position, double val) { + return putLong(position, Double.doubleToRawLongBits(val)); + } + + public ByteBuffer putFloat(int position, float val) { + return putInt(position, Float.floatToRawIntBits(val)); + } + + public ByteBuffer putLong(int position, long val) { + checkPut(position, 8, true); + + rawPutLong(position, val); + + return this; + } + + public ByteBuffer putInt(int position, int val) { + checkPut(position, 4, true); + + rawPutInt(position, val); + + return this; + } + + public ByteBuffer putShort(int position, short val) { + checkPut(position, 2, true); + + rawPutShort(position, val); + + return this; + } + + public ByteBuffer putDouble(double val) { + return putLong(Double.doubleToRawLongBits(val)); + } + + public ByteBuffer putFloat(float val) { + return putInt(Float.floatToRawIntBits(val)); + } + + public ByteBuffer putLong(long val) { + checkPut(position, 8, false); + + rawPutLong(position, val); + position += 8; + return this; + } + + public ByteBuffer putInt(int val) { + checkPut(position, 4, false); + + rawPutInt(position, val); + position += 4; + return this; + } + + public ByteBuffer putShort(short val) { + checkPut(position, 2, false); + + rawPutShort(position, val); + position += 2; + return this; + } + + public byte get() { + checkGet(position, 1, false); + return doGet(position++); + } + + public byte get(int position) { + checkGet(position, 1, true); + return doGet(position); + } + + public ByteBuffer get(byte[] dst) { + return get(dst, 0, dst.length); + } + + public double getDouble(int position) { + return Double.longBitsToDouble(getLong(position)); + } + + public float getFloat(int position) { + return Float.intBitsToFloat(getInt(position)); + } + + public long getLong(int position) { + checkGet(position, 8, true); + + return rawGetLong(position); + } + + public int getInt(int position) { + checkGet(position, 4, true); + + return rawGetInt(position); + } + + public short getShort(int position) { + checkGet(position, 2, true); + + return rawGetShort(position); + } + + private long rawGetLong(int position) { + return (((long) (doGet(position ) & 0xFF)) << 56) + | (((long) (doGet(position + 1) & 0xFF)) << 48) + | (((long) (doGet(position + 2) & 0xFF)) << 40) + | (((long) (doGet(position + 3) & 0xFF)) << 32) + | (((long) (doGet(position + 4) & 0xFF)) << 24) + | (((long) (doGet(position + 5) & 0xFF)) << 16) + | (((long) (doGet(position + 6) & 0xFF)) << 8) + | (((long) (doGet(position + 7) & 0xFF)) ); + } + + private int rawGetInt(int position) { + return (((int) (doGet(position ) & 0xFF)) << 24) + | (((int) (doGet(position + 1) & 0xFF)) << 16) + | (((int) (doGet(position + 2) & 0xFF)) << 8) + | (((int) (doGet(position + 3) & 0xFF)) ); + } + + private short rawGetShort(int position) { + return (short) (( ((int) (doGet(position ) & 0xFF)) << 8) + | (((int) (doGet(position + 1) & 0xFF)) )); + } + + public double getDouble() { + return Double.longBitsToDouble(getLong()); + } + + public float getFloat() { + return Float.intBitsToFloat(getInt()); + } + + public long getLong() { + checkGet(position, 8, false); + + long r = rawGetLong(position); + position += 8; + return r; + } + + public int getInt() { + checkGet(position, 4, false); + + int r = rawGetInt(position); + position += 4; + return r; + } + + public short getShort() { + checkGet(position, 2, false); + + short r = rawGetShort(position); + position += 2; + return r; + } + + protected void checkPut(int position, int amount, boolean absolute) { + if (isReadOnly()) { + throw new ReadOnlyBufferException(); + } + + if (position < 0 || position+amount > limit) { + throw absolute + ? new IndexOutOfBoundsException() + : new BufferOverflowException(); + } + } + + protected void checkGet(int position, int amount, boolean absolute) { + if (amount > limit-position) { + throw absolute + ? new IndexOutOfBoundsException() + : new BufferUnderflowException(); + } + } + + public ByteBuffer order(ByteOrder order) { + if (order != ByteOrder.BIG_ENDIAN) throw new UnsupportedOperationException(); + return this; + } + + public ByteOrder order() { + return ByteOrder.BIG_ENDIAN; + } +} diff --git a/sgx-jvm/avian/classpath/java/nio/ByteOrder.java b/sgx-jvm/avian/classpath/java/nio/ByteOrder.java new file mode 100644 index 0000000000..6592bcd873 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/nio/ByteOrder.java @@ -0,0 +1,40 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.nio; + +public final class ByteOrder { + public static final ByteOrder BIG_ENDIAN = new ByteOrder("BIG_ENDIAN"); + public static final ByteOrder LITTLE_ENDIAN = new ByteOrder("LITTLE_ENDIAN"); + + private static final ByteOrder NATIVE; + private static native boolean isNativeBigEndian(); + + static { + if (isNativeBigEndian()) + NATIVE = BIG_ENDIAN; + else + NATIVE = LITTLE_ENDIAN; + } + + private String name; + + private ByteOrder(String name) { + this.name = name; + } + + public String toString() { + return name; + } + + public static ByteOrder nativeOrder() { + return NATIVE; + } +} diff --git a/sgx-jvm/avian/classpath/java/nio/CharBuffer.java b/sgx-jvm/avian/classpath/java/nio/CharBuffer.java new file mode 100644 index 0000000000..1d92de5980 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/nio/CharBuffer.java @@ -0,0 +1,154 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.nio; + +public abstract class CharBuffer + extends Buffer + implements Comparable +{ + private final boolean readOnly; + + protected CharBuffer(boolean readOnly) { + this.readOnly = readOnly; + } + + public static CharBuffer allocate(int capacity) { + return new ArrayCharBuffer(new char[capacity], 0, capacity, false); + } + + public static CharBuffer wrap(char[] array) { + return wrap(array, 0, array.length); + } + + public static CharBuffer wrap(char[] array, int offset, int length) { + return new ArrayCharBuffer(array, offset, length, false); + } + + public abstract CharBuffer asReadOnlyBuffer(); + + public abstract CharBuffer slice(); + + protected abstract void doPut(int offset, char value); + + public abstract CharBuffer put(char[] src, int offset, int length); + + protected abstract char doGet(int offset); + + public abstract CharBuffer get(char[] dst, int offset, int length); + + public boolean hasArray() { + return false; + } + + public CharBuffer compact() { + int remaining = remaining(); + + if (position != 0) { + CharBuffer b = slice(); + position = 0; + put(b); + } + + position = remaining; + limit(capacity()); + + return this; + } + + public CharBuffer put(CharBuffer src) { + if (src.hasArray()) { + checkPut(position, src.remaining(), false); + + put(src.array(), src.arrayOffset() + src.position, src.remaining()); + src.position(src.position() + src.remaining()); + + return this; + } else { + char[] buffer = new char[src.remaining()]; + src.get(buffer); + return put(buffer); + } + } + + public int compareTo(CharBuffer o) { + int end = (remaining() < o.remaining() ? remaining() : o.remaining()); + + for (int i = 0; i < end; ++i) { + int d = get(position + i) - o.get(o.position + i); + if (d != 0) { + return d; + } + } + return remaining() - o.remaining(); + } + + public boolean equals(Object o) { + return o instanceof CharBuffer && compareTo((CharBuffer) o) == 0; + } + + public char[] array() { + throw new UnsupportedOperationException(); + } + + public int arrayOffset() { + throw new UnsupportedOperationException(); + } + + public CharBuffer put(int offset, char val) { + checkPut(offset, 1, true); + doPut(offset, val); + return this; + } + + public CharBuffer put(char val) { + put(position, val); + ++ position; + return this; + } + + public CharBuffer put(char[] arr) { + return put(arr, 0, arr.length); + } + + public char get() { + checkGet(position, 1, false); + return doGet(position++); + } + + public char get(int position) { + checkGet(position, 1, true); + return doGet(position); + } + + public CharBuffer get(char[] dst) { + return get(dst, 0, dst.length); + } + + protected void checkPut(int position, int amount, boolean absolute) { + if (readOnly) { + throw new ReadOnlyBufferException(); + } + + if (position < 0 || position+amount > limit) { + throw absolute + ? new IndexOutOfBoundsException() + : new BufferOverflowException(); + } + } + + protected void checkGet(int position, int amount, boolean absolute) { + if (amount > limit-position) { + throw absolute + ? new IndexOutOfBoundsException() + : new BufferUnderflowException(); + } + } +} diff --git a/sgx-jvm/avian/classpath/java/nio/DirectByteBuffer.java b/sgx-jvm/avian/classpath/java/nio/DirectByteBuffer.java new file mode 100644 index 0000000000..ede7074a5b --- /dev/null +++ b/sgx-jvm/avian/classpath/java/nio/DirectByteBuffer.java @@ -0,0 +1,113 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.nio; + +import sun.misc.Unsafe; + +class DirectByteBuffer extends ByteBuffer { + private static final Unsafe unsafe = Unsafe.getUnsafe(); + private static final int baseOffset = unsafe.arrayBaseOffset(byte[].class); + + protected final long address; + + protected DirectByteBuffer(long address, int capacity, boolean readOnly) { + super(readOnly); + + this.address = address; + this.capacity = capacity; + this.limit = capacity; + this.position = 0; + } + + protected DirectByteBuffer(long address, int capacity) { + this(address, capacity, false); + } + + public ByteBuffer asReadOnlyBuffer() { + ByteBuffer b = new DirectByteBuffer(address, capacity, true); + b.position(position()); + b.limit(limit()); + return b; + } + + public ByteBuffer slice() { + return new DirectByteBuffer(address + position, remaining(), true); + } + + protected void doPut(int position, byte val) { + unsafe.putByte(address + position, val); + } + + public ByteBuffer put(ByteBuffer src) { + if (src instanceof DirectByteBuffer) { + checkPut(position, src.remaining(), false); + + DirectByteBuffer b = (DirectByteBuffer) src; + + unsafe.copyMemory + (b.address + b.position, address + position, b.remaining()); + + position += b.remaining(); + b.position += b.remaining(); + + return this; + } else { + return super.put(src); + } + } + + public ByteBuffer put(byte[] src, int offset, int length) { + if (offset < 0 || offset + length > src.length) { + throw new ArrayIndexOutOfBoundsException(); + } + + checkPut(position, length, false); + + unsafe.copyMemory + (src, baseOffset + offset, null, address + position, length); + + position += length; + + return this; + } + + public ByteBuffer get(byte[] dst, int offset, int length) { + if (offset < 0 || offset + length > dst.length) { + throw new ArrayIndexOutOfBoundsException(); + } + + checkGet(position, length, false); + + unsafe.copyMemory + (null, address + position, dst, baseOffset + offset, length); + + return this; + } + + protected byte doGet(int position) { + return unsafe.getByte(address + position); + } + + public String toString() { + return "(DirectByteBuffer with address: " + address + + " position: " + position + + " limit: " + limit + + " capacity: " + capacity + ")"; + } + + @Override + public ByteBuffer duplicate() { + ByteBuffer b = new DirectByteBuffer(address, capacity, isReadOnly()); + b.limit(this.limit()); + b.position(this.position()); + return b; + } +} diff --git a/sgx-jvm/avian/classpath/java/nio/FixedArrayByteBuffer.java b/sgx-jvm/avian/classpath/java/nio/FixedArrayByteBuffer.java new file mode 100644 index 0000000000..d433e321af --- /dev/null +++ b/sgx-jvm/avian/classpath/java/nio/FixedArrayByteBuffer.java @@ -0,0 +1,66 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.nio; + +class FixedArrayByteBuffer extends DirectByteBuffer { + private final byte[] array; + private final int arrayOffset; + + private FixedArrayByteBuffer(long address, + byte[] array, + int offset, + int capacity, + boolean readOnly) + { + super(address, capacity, readOnly); + + this.array = array; + this.arrayOffset = offset; + } + + public static FixedArrayByteBuffer make(int capacity) { + long[] address = new long[1]; + byte[] array = allocateFixed(capacity, address); + return new FixedArrayByteBuffer(address[0], array, 0, capacity, false); + } + + private static native byte[] allocateFixed(int capacity, long[] address); + + public ByteBuffer asReadOnlyBuffer() { + ByteBuffer b = new FixedArrayByteBuffer + (address, array, arrayOffset, capacity, true); + b.position(position()); + b.limit(limit()); + return b; + } + + public ByteBuffer slice() { + return new FixedArrayByteBuffer + (address + position, array, arrayOffset + position, remaining(), true); + } + + @Override + public ByteBuffer duplicate() { + ByteBuffer b = new FixedArrayByteBuffer(address, array, arrayOffset, capacity, isReadOnly()); + b.limit(this.limit()); + b.position(this.position()); + return b; + } + + public String toString() { + return "(FixedArrayByteBuffer with address: " + address + + " array: " + array + + " arrayOffset: " + arrayOffset + + " position: " + position + + " limit: " + limit + + " capacity: " + capacity + ")"; + } +} diff --git a/sgx-jvm/avian/classpath/java/nio/ReadOnlyBufferException.java b/sgx-jvm/avian/classpath/java/nio/ReadOnlyBufferException.java new file mode 100644 index 0000000000..62bcdd8ebb --- /dev/null +++ b/sgx-jvm/avian/classpath/java/nio/ReadOnlyBufferException.java @@ -0,0 +1,14 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.nio; + +public class ReadOnlyBufferException extends UnsupportedOperationException { +} diff --git a/sgx-jvm/avian/classpath/java/nio/channels/Channel.java b/sgx-jvm/avian/classpath/java/nio/channels/Channel.java new file mode 100644 index 0000000000..172e1d69e8 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/nio/channels/Channel.java @@ -0,0 +1,18 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.nio.channels; + +import java.io.IOException; + +public interface Channel { + public void close() throws IOException; + public boolean isOpen(); +} diff --git a/sgx-jvm/avian/classpath/java/nio/channels/Channels.java b/sgx-jvm/avian/classpath/java/nio/channels/Channels.java new file mode 100644 index 0000000000..9d0e377ea3 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/nio/channels/Channels.java @@ -0,0 +1,142 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.nio.channels; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.nio.ByteBuffer; + +public class Channels { + public static InputStream newInputStream(ReadableByteChannel channel) { + return new MyInputStream(channel); + } + + public static OutputStream newOutputStream(WritableByteChannel channel) { + return new MyOutputStream(channel); + } + + public static ReadableByteChannel newChannel(InputStream stream) { + return new InputStreamChannel(stream); + } + + public static WritableByteChannel newChannel(OutputStream stream) { + return new OutputStreamChannel(stream); + } + + private static class MyInputStream extends InputStream { + private final ReadableByteChannel channel; + + public MyInputStream(ReadableByteChannel channel) { + this.channel = channel; + } + + public int read() throws IOException { + byte[] buffer = new byte[1]; + int r = read(buffer); + if (r == -1) { + return -1; + } else { + return buffer[0] & 0xFF; + } + } + + public int read(byte[] buffer, int offset, int length) throws IOException { + return channel.read(ByteBuffer.wrap(buffer, offset, length)); + } + + public void close() throws IOException { + channel.close(); + } + } + + private static class MyOutputStream extends OutputStream { + private final WritableByteChannel channel; + + public MyOutputStream(WritableByteChannel channel) { + this.channel = channel; + } + + public void write(int v) throws IOException { + byte[] buffer = new byte[] { (byte) (v & 0xFF) }; + write(buffer); + } + + public void write(byte[] buffer, int offset, int length) + throws IOException + { + channel.write(ByteBuffer.wrap(buffer, offset, length)); + } + + public void close() throws IOException { + channel.close(); + } + } + + private static class InputStreamChannel implements ReadableByteChannel { + private InputStream stream; + + public InputStreamChannel(InputStream stream) { + this.stream = stream; + } + + public void close() throws IOException { + if (stream != null) { + stream.close(); + stream = null; + } + } + + public boolean isOpen() { + return stream != null; + } + + public int read(ByteBuffer b) throws IOException { + int c = stream.read + (b.array(), b.arrayOffset() + b.position(), b.remaining()); + + if (c > 0) { + b.position(b.position() + c); + } + + return c; + } + } + + private static class OutputStreamChannel implements WritableByteChannel { + private OutputStream stream; + + public OutputStreamChannel(OutputStream stream) { + this.stream = stream; + } + + public void close() throws IOException { + if (stream != null) { + stream.close(); + stream = null; + } + } + + public boolean isOpen() { + return stream != null; + } + + public int write(ByteBuffer b) throws IOException { + stream.write(b.array(), b.arrayOffset() + b.position(), b.remaining()); + + int c = b.remaining(); + + b.position(b.limit()); + + return c; + } + } +} diff --git a/sgx-jvm/avian/classpath/java/nio/channels/ClosedSelectorException.java b/sgx-jvm/avian/classpath/java/nio/channels/ClosedSelectorException.java new file mode 100644 index 0000000000..df85114f18 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/nio/channels/ClosedSelectorException.java @@ -0,0 +1,13 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.nio.channels; + +public class ClosedSelectorException extends IllegalStateException { } diff --git a/sgx-jvm/avian/classpath/java/nio/channels/DatagramChannel.java b/sgx-jvm/avian/classpath/java/nio/channels/DatagramChannel.java new file mode 100644 index 0000000000..f0a2b39a66 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/nio/channels/DatagramChannel.java @@ -0,0 +1,239 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.nio.channels; + +import java.io.IOException; +import java.nio.ByteBuffer; +import java.net.SocketAddress; +import java.net.InetSocketAddress; +import java.net.ProtocolFamily; +import java.net.Socket; +import java.net.SocketException; +import java.net.DatagramSocket; +import java.net.StandardProtocolFamily; + +// TODO: This class is both divergent from the Java standard and incomplete. +public class DatagramChannel extends SelectableChannel + implements ReadableByteChannel, WritableByteChannel +{ + public static final int InvalidSocket = -1; + + private int socket = makeSocket(); + private boolean blocking = true; + private boolean connected = false; + + public SelectableChannel configureBlocking(boolean v) throws IOException { + blocking = v; + configureBlocking(); + return this; + } + + private void configureBlocking() throws IOException { + if (socket != InvalidSocket) { + configureBlocking(socket, blocking); + } + } + + int socketFD() { + return socket; + } + + void handleReadyOps(int ops) { + // ignore + } + + public static DatagramChannel open(ProtocolFamily family) + throws IOException + { + if (family.equals(StandardProtocolFamily.INET)) { + Socket.init(); + + return new DatagramChannel(); + } else { + throw new UnsupportedOperationException(); + } + } + + public static DatagramChannel open() + throws IOException + { + return open(StandardProtocolFamily.INET); + } + + public DatagramSocket socket() { + return new Handle(); + } + + public DatagramChannel bind(SocketAddress address) throws IOException { + InetSocketAddress inetAddress; + try { + inetAddress = (InetSocketAddress) address; + } catch (ClassCastException e) { + throw new UnsupportedAddressTypeException(); + } + + if (inetAddress == null) { + bind(socket, 0, 0); + } else { + bind(socket, inetAddress.getAddress().getRawAddress(), + inetAddress.getPort()); + } + + return this; + } + + public DatagramChannel connect(SocketAddress address) throws IOException { + InetSocketAddress inetAddress; + try { + inetAddress = (InetSocketAddress) address; + } catch (ClassCastException e) { + throw new UnsupportedAddressTypeException(); + } + + connected = connect(socket, inetAddress.getAddress().getRawAddress(), + inetAddress.getPort()); + + return this; + } + + public int write(ByteBuffer b) throws IOException { + if (b.remaining() == 0) return 0; + + byte[] array = b.array(); + if (array == null) throw new NullPointerException(); + + int c = write + (socket, array, b.arrayOffset() + b.position(), b.remaining(), blocking); + + if (c > 0) { + b.position(b.position() + c); + } + + return c; + } + + public int read(ByteBuffer b) throws IOException { + int p = b.position(); + receive(b); + return b.position() - p; + } + + public SocketAddress receive(ByteBuffer b) throws IOException { + if (b.remaining() == 0) return null; + + byte[] array = b.array(); + if (array == null) throw new NullPointerException(); + + int[] address = new int[2]; + + int c = receive + (socket, array, b.arrayOffset() + b.position(), b.remaining(), blocking, + address); + + if (c > 0) { + b.position(b.position() + c); + + return new InetSocketAddress(ipv4ToString(address[0]), address[1]); + } else { + return null; + } + } + + public int send(ByteBuffer b, SocketAddress address) throws IOException { + if (b.remaining() == 0) return 0; + + InetSocketAddress inetAddress; + try { + inetAddress = (InetSocketAddress) address; + } catch (ClassCastException e) { + throw new UnsupportedAddressTypeException(); + } + + byte[] array = b.array(); + if (array == null) throw new NullPointerException(); + + int c = send + (socket, inetAddress.getAddress().getRawAddress(), + inetAddress.getPort(), array, b.arrayOffset() + b.position(), + b.remaining(), blocking); + + if (c > 0) { + b.position(b.position() + c); + } + + return c; + } + + private static String ipv4ToString(int address) { + StringBuilder sb = new StringBuilder(); + + sb.append( address >> 24 ).append('.') + .append((address >> 16) & 0xFF).append('.') + .append((address >> 8) & 0xFF).append('.') + .append( address & 0xFF); + + return sb.toString(); + } + + public class Handle extends DatagramSocket { + public SocketAddress getRemoteSocketAddress() { + throw new UnsupportedOperationException(); + } + + public void bind(SocketAddress address) throws SocketException { + try { + DatagramChannel.this.bind(address); + } catch (SocketException e) { + throw e; + } catch (IOException e) { + SocketException se = new SocketException(); + se.initCause(e); + throw se; + } + } + } + + public boolean isConnected() { return connected; } + + /** TODO: This is probably incomplete. */ + public DatagramChannel disconnect() throws IOException { + connect(socket, 0, 0); + connected = false; + return this; + } + + public void close() throws IOException { + if (isOpen()) { + super.close(); + close(socket); + } + } + + private static native int makeSocket(); + private static native void configureBlocking(int socket, boolean blocking) + throws IOException; + private static native void bind(int socket, int host, int port) + throws IOException; + private static native boolean connect(int socket, int host, int port) + throws IOException; + private static native int write(int socket, byte[] array, int offset, + int length, boolean blocking) + throws IOException; + private static native int send(int socket, int host, int port, + byte[] array, int offset, + int length, boolean blocking) + throws IOException; + private static native int receive(int socket, byte[] array, int offset, + int length, boolean blocking, + int[] address) + throws IOException; + private static native void close(int socket); +} diff --git a/sgx-jvm/avian/classpath/java/nio/channels/FileChannel.java b/sgx-jvm/avian/classpath/java/nio/channels/FileChannel.java new file mode 100644 index 0000000000..af8102317b --- /dev/null +++ b/sgx-jvm/avian/classpath/java/nio/channels/FileChannel.java @@ -0,0 +1,35 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.nio.channels; + +import java.io.IOException; +import java.nio.ByteBuffer; + +public abstract class FileChannel implements Channel { + + public static enum MapMode { + PRIVATE, READ_ONLY, READ_WRITE + }; + + public abstract int read(ByteBuffer dst) throws IOException; + + public abstract int read(ByteBuffer dst, long position) throws IOException; + + public abstract int write(ByteBuffer dst) throws IOException; + + public abstract int write(ByteBuffer dst, long position) throws IOException; + + public abstract long position() throws IOException; + + public abstract FileChannel position(long position) throws IOException; + + public abstract long size() throws IOException; +} diff --git a/sgx-jvm/avian/classpath/java/nio/channels/GatheringByteChannel.java b/sgx-jvm/avian/classpath/java/nio/channels/GatheringByteChannel.java new file mode 100644 index 0000000000..da461fcefe --- /dev/null +++ b/sgx-jvm/avian/classpath/java/nio/channels/GatheringByteChannel.java @@ -0,0 +1,20 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.nio.channels; + +import java.io.IOException; +import java.nio.ByteBuffer; + +public interface GatheringByteChannel extends WritableByteChannel { + public long write(ByteBuffer[] srcs) throws IOException; + public long write(ByteBuffer[] srcs, int offset, int length) + throws IOException; +} diff --git a/sgx-jvm/avian/classpath/java/nio/channels/ReadableByteChannel.java b/sgx-jvm/avian/classpath/java/nio/channels/ReadableByteChannel.java new file mode 100644 index 0000000000..d3891eabeb --- /dev/null +++ b/sgx-jvm/avian/classpath/java/nio/channels/ReadableByteChannel.java @@ -0,0 +1,18 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.nio.channels; + +import java.io.IOException; +import java.nio.ByteBuffer; + +public interface ReadableByteChannel extends Channel { + public int read(ByteBuffer b) throws IOException; +} diff --git a/sgx-jvm/avian/classpath/java/nio/channels/SelectableChannel.java b/sgx-jvm/avian/classpath/java/nio/channels/SelectableChannel.java new file mode 100644 index 0000000000..3e544f937e --- /dev/null +++ b/sgx-jvm/avian/classpath/java/nio/channels/SelectableChannel.java @@ -0,0 +1,43 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.nio.channels; + +import java.io.IOException; +import java.nio.ByteBuffer; + +public abstract class SelectableChannel implements Channel { + private SelectionKey key; + private boolean open = true; + + abstract int socketFD(); + + abstract void handleReadyOps(int ops); + + public abstract SelectableChannel configureBlocking(boolean v) + throws IOException; + + public SelectionKey register(Selector selector, int interestOps, + Object attachment) + { + key = new SelectionKey(this, selector, interestOps, attachment); + selector.add(key); + return key; + } + + public boolean isOpen() { + return open; + } + + public void close() throws IOException { + open = false; + key = null; + } +} diff --git a/sgx-jvm/avian/classpath/java/nio/channels/SelectionKey.java b/sgx-jvm/avian/classpath/java/nio/channels/SelectionKey.java new file mode 100644 index 0000000000..ca41b74d3a --- /dev/null +++ b/sgx-jvm/avian/classpath/java/nio/channels/SelectionKey.java @@ -0,0 +1,83 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.nio.channels; + +public class SelectionKey { + public static final int OP_READ = 1 << 0; + public static final int OP_WRITE = 1 << 2; + public static final int OP_CONNECT = 1 << 3; + public static final int OP_ACCEPT = 1 << 4; + + private final SelectableChannel channel; + private final Selector selector; + private int interestOps; + private int readyOps; + private final Object attachment; + + public SelectionKey(SelectableChannel channel, Selector selector, + int interestOps, Object attachment) + { + this.channel = channel; + this.selector = selector; + this.interestOps = interestOps; + this.attachment = attachment; + this.readyOps = 0; + } + + public int interestOps() { + return interestOps; + } + + public SelectionKey interestOps(int v) { + this.interestOps = v; + return this; + } + + public int readyOps() { + return readyOps; + } + + public void readyOps(int v) { + this.readyOps = v; + } + + public boolean isReadable() { + return (readyOps & OP_READ) != 0; + } + + public boolean isWritable() { + return (readyOps & OP_WRITE) != 0; + } + + public boolean isConnectable() { + return (readyOps & OP_CONNECT) != 0; + } + + public boolean isAcceptable() { + return (readyOps & OP_ACCEPT) != 0; + } + + public boolean isValid() { + return channel.isOpen() && selector.isOpen(); + } + + public SelectableChannel channel() { + return channel; + } + + public Selector selector() { + return selector; + } + + public Object attachment() { + return attachment; + } +} diff --git a/sgx-jvm/avian/classpath/java/nio/channels/Selector.java b/sgx-jvm/avian/classpath/java/nio/channels/Selector.java new file mode 100644 index 0000000000..ceb45031eb --- /dev/null +++ b/sgx-jvm/avian/classpath/java/nio/channels/Selector.java @@ -0,0 +1,52 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.nio.channels; + +import java.io.IOException; +import java.util.Set; +import java.util.HashSet; + +public abstract class Selector { + protected final Set keys = new HashSet(); + protected final Set selectedKeys = new HashSet(); + + public static Selector open() throws IOException { + return new SocketSelector(); + } + + public void add(SelectionKey key) { + keys.add(key); + } + + public void remove(SelectionKey key) { + keys.remove(key); + } + + public Set keys() { + return keys; + } + + public Set selectedKeys() { + return selectedKeys; + } + + public abstract boolean isOpen(); + + public abstract Selector wakeup(); + + public abstract int selectNow() throws IOException; + + public abstract int select(long interval) throws IOException; + + public abstract int select() throws IOException; + + public abstract void close(); +} diff --git a/sgx-jvm/avian/classpath/java/nio/channels/ServerSocketChannel.java b/sgx-jvm/avian/classpath/java/nio/channels/ServerSocketChannel.java new file mode 100644 index 0000000000..6f0d601a8b --- /dev/null +++ b/sgx-jvm/avian/classpath/java/nio/channels/ServerSocketChannel.java @@ -0,0 +1,93 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.nio.channels; + +import java.io.IOException; + +import java.net.InetSocketAddress; +import java.net.SocketAddress; +import java.net.ServerSocket; +import java.net.Socket; + +public class ServerSocketChannel extends SelectableChannel { + private final SocketChannel channel; + + private ServerSocketChannel() throws IOException { + channel = new SocketChannel(); + } + + public static ServerSocketChannel open() throws IOException { + Socket.init(); + + return new ServerSocketChannel(); + } + + public int socketFD() { + return channel.socketFD(); + } + + public void handleReadyOps(int ops) { + channel.handleReadyOps(ops); + } + + public SelectableChannel configureBlocking(boolean v) throws IOException { + return channel.configureBlocking(v); + } + + public void close() throws IOException { + channel.close(); + } + + public SocketChannel accept() throws IOException { + SocketChannel c = new SocketChannel(); + c.socket = doAccept(); + c.connected = true; + return c; + } + + public ServerSocket socket() { + return new Handle(); + } + + private int doAccept() throws IOException { + while (true) { + int s = natDoAccept(channel.socket); + if (s != -1) { + return s; + } + // todo: throw ClosedByInterruptException if this thread was + // interrupted during the accept call + } + } + + private void doListen(int socket, int host, int port) throws IOException { + Socket.init(); + + natDoListen(socket, host, port); + } + + public class Handle extends ServerSocket { + public void bind(SocketAddress address) + throws IOException + { + InetSocketAddress a; + try { + a = (InetSocketAddress) address; + } catch (ClassCastException e) { + throw new IllegalArgumentException(); + } + doListen(channel.socket, a.getAddress().getRawAddress(), a.getPort()); + } + } + + private static native int natDoAccept(int socket) throws IOException; + private static native void natDoListen(int socket, int host, int port) throws IOException; +} diff --git a/sgx-jvm/avian/classpath/java/nio/channels/SocketChannel.java b/sgx-jvm/avian/classpath/java/nio/channels/SocketChannel.java new file mode 100644 index 0000000000..f551eb1dc3 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/nio/channels/SocketChannel.java @@ -0,0 +1,214 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.nio.channels; + +import java.io.IOException; +import java.net.SocketException; +import java.net.SocketAddress; +import java.net.InetSocketAddress; +import java.net.Socket; +import java.nio.ByteBuffer; + +public class SocketChannel extends SelectableChannel + implements ReadableByteChannel, GatheringByteChannel +{ + public static final int InvalidSocket = -1; + + int socket = makeSocket(); + boolean connected = false; + boolean readyToConnect = false; + boolean blocking = true; + + public static SocketChannel open() throws IOException { + Socket.init(); + + return new SocketChannel(); + } + + public SelectableChannel configureBlocking(boolean v) throws IOException { + blocking = v; + if (socket != InvalidSocket) { + configureBlocking(socket, v); + } + return this; + } + + public boolean isBlocking() { + return blocking; + } + + public boolean isConnected() { + return connected; + } + + public Socket socket() { + try { + return new Handle(); + } catch (IOException e) { + return null; + } + } + + public boolean connect(SocketAddress address) throws IOException { + InetSocketAddress a; + try { + a = (InetSocketAddress) address; + } catch (ClassCastException e) { + throw new UnsupportedAddressTypeException(); + } + doConnect(socket, a.getAddress().getRawAddress(), a.getPort()); + configureBlocking(blocking); + return connected; + } + + public boolean finishConnect() throws IOException { + if (! connected) { + while (! readyToConnect) { + Selector selector = Selector.open(); + SelectionKey key = register(selector, SelectionKey.OP_CONNECT, null); + + if (blocking) { + selector.select(); + } else { + selector.selectNow(); + break; + } + } + + natFinishConnect(socket); + + connected = readyToConnect; + } + + return connected; + } + + public void close() throws IOException { + if (isOpen()) { + super.close(); + closeSocket(); + } + } + + private void doConnect(int socket, int host, int port) + throws IOException + { + connected = natDoConnect(socket, host, port); + } + + public int read(ByteBuffer b) throws IOException { + if (! isOpen()) return -1; + if (b.remaining() == 0) return 0; + + byte[] array = b.array(); + if (array == null) throw new NullPointerException(); + + int r = natRead(socket, array, b.arrayOffset() + b.position(), b.remaining(), blocking); + if (r > 0) { + b.position(b.position() + r); + } + return r; + } + + public int write(ByteBuffer b) throws IOException { + if (! connected) { + natThrowWriteError(socket); + } + if (b.remaining() == 0) return 0; + + byte[] array = b.array(); + if (array == null) throw new NullPointerException(); + + int w = natWrite(socket, array, b.arrayOffset() + b.position(), b.remaining(), blocking); + if (w > 0) { + b.position(b.position() + w); + } + return w; + } + + public long write(ByteBuffer[] srcs) throws IOException { + return write(srcs, 0, srcs.length); + } + + public long write(ByteBuffer[] srcs, int offset, int length) + throws IOException + { + long total = 0; + for (int i = offset; i < offset + length; ++i) { + total += write(srcs[i]); + if (srcs[i].hasRemaining()) { + return total; + } + } + return total; + } + + private void closeSocket() { + natCloseSocket(socket); + } + + int socketFD() { + return socket; + } + + void handleReadyOps(int ops) { + if ((ops & SelectionKey.OP_CONNECT) != 0) { + readyToConnect = true; + } + } + + public class Handle extends Socket { + public Handle() throws IOException { + super(); + } + + public void setTcpNoDelay(boolean on) throws SocketException { + natSetTcpNoDelay(socket, on); + } + + public void bind(SocketAddress address) + throws IOException + { + InetSocketAddress a; + try { + a = (InetSocketAddress) address; + } catch (ClassCastException e) { + throw new IllegalArgumentException(); + } + + if (a == null) { + SocketChannel.bind(socket, 0, 0); + } else { + SocketChannel.bind + (socket, a.getAddress().getRawAddress(), a.getPort()); + } + } + } + + private static native int makeSocket(); + private static native void configureBlocking(int socket, boolean blocking) + throws IOException; + + private static native void natSetTcpNoDelay(int socket, boolean on) + throws SocketException; + private static native void bind(int socket, int host, int port) + throws IOException; + private static native boolean natDoConnect(int socket, int host, int port) + throws IOException; + private static native void natFinishConnect(int socket) + throws IOException; + private static native int natRead(int socket, byte[] buffer, int offset, int length, boolean blocking) + throws IOException; + private static native int natWrite(int socket, byte[] buffer, int offset, int length, boolean blocking) + throws IOException; + private static native void natThrowWriteError(int socket) throws IOException; + private static native void natCloseSocket(int socket); +} diff --git a/sgx-jvm/avian/classpath/java/nio/channels/SocketSelector.java b/sgx-jvm/avian/classpath/java/nio/channels/SocketSelector.java new file mode 100644 index 0000000000..c17d2afbf2 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/nio/channels/SocketSelector.java @@ -0,0 +1,133 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.nio.channels; + +import java.io.IOException; +import java.util.Iterator; +import java.net.Socket; + +class SocketSelector extends Selector { + protected volatile long state; + protected final Object lock = new Object(); + protected boolean woken = false; + + public SocketSelector() throws IOException { + Socket.init(); + + state = natInit(); + } + + public boolean isOpen() { + return state != 0; + } + + public Selector wakeup() { + synchronized (lock) { + if (isOpen() && (! woken)) { + woken = true; + + natWakeup(state); + } + } + return this; + } + + private boolean clearWoken() { + synchronized (lock) { + if (woken) { + woken = false; + return true; + } else { + return false; + } + } + } + + public synchronized int selectNow() throws IOException { + return doSelect(-1); + } + + public synchronized int select() throws IOException { + return doSelect(0); + } + + public synchronized int select(long interval) throws IOException { + if (interval < 0) throw new IllegalArgumentException(); + + return doSelect(interval); + } + + public int doSelect(long interval) throws IOException { + if (! isOpen()) { + throw new ClosedSelectorException(); + } + + selectedKeys.clear(); + + if (clearWoken()) interval = -1; + + int max=0; + for (Iterator it = keys.iterator(); + it.hasNext();) + { + SelectionKey key = it.next(); + SelectableChannel c = key.channel(); + int socket = c.socketFD(); + if (c.isOpen()) { + key.readyOps(0); + max = natSelectUpdateInterestSet + (socket, key.interestOps(), state, max); + } else { + natSelectClearAll(socket, state); + it.remove(); + } + } + + int r = natDoSocketSelect(state, max, interval); + + if (r > 0) { + for (SelectionKey key : keys) { + SelectableChannel c = key.channel(); + int socket = c.socketFD(); + int ready = natUpdateReadySet(socket, key.interestOps(), state); + key.readyOps(ready); + if (ready != 0) { + c.handleReadyOps(ready); + selectedKeys.add(key); + } + } + } + clearWoken(); + + return selectedKeys.size(); + } + + public synchronized void close() { + synchronized (lock) { + if (isOpen()) { + natClose(state); + state = 0; + } + } + } + + private static native long natInit(); + private static native void natWakeup(long state); + private static native void natClose(long state); + private static native void natSelectClearAll(int socket, long state); + private static native int natSelectUpdateInterestSet(int socket, + int interest, + long state, + int max); + private static native int natDoSocketSelect(long state, int max, long interval) + throws IOException; + private static native int natUpdateReadySet(int socket, int interest, long state); +} diff --git a/sgx-jvm/avian/classpath/java/nio/channels/UnsupportedAddressTypeException.java b/sgx-jvm/avian/classpath/java/nio/channels/UnsupportedAddressTypeException.java new file mode 100644 index 0000000000..01362bcf6c --- /dev/null +++ b/sgx-jvm/avian/classpath/java/nio/channels/UnsupportedAddressTypeException.java @@ -0,0 +1,17 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.nio.channels; + +public class UnsupportedAddressTypeException extends IllegalArgumentException { + public UnsupportedAddressTypeException() { + super(null, null); + } +} diff --git a/sgx-jvm/avian/classpath/java/nio/channels/WritableByteChannel.java b/sgx-jvm/avian/classpath/java/nio/channels/WritableByteChannel.java new file mode 100644 index 0000000000..842f5dedad --- /dev/null +++ b/sgx-jvm/avian/classpath/java/nio/channels/WritableByteChannel.java @@ -0,0 +1,18 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.nio.channels; + +import java.io.IOException; +import java.nio.ByteBuffer; + +public interface WritableByteChannel extends Channel { + public int write(ByteBuffer b) throws IOException; +} diff --git a/sgx-jvm/avian/classpath/java/security/AccessControlException.java b/sgx-jvm/avian/classpath/java/security/AccessControlException.java new file mode 100644 index 0000000000..a0a93028a2 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/security/AccessControlException.java @@ -0,0 +1,28 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.security; + +public class AccessControlException extends SecurityException { + private final Permission permission; + + public AccessControlException(String message) { + this(message, null); + } + + public AccessControlException(String message, Permission permission) { + super(message); + this.permission = permission; + } + + public Permission getPermission() { + return permission; + } +} diff --git a/sgx-jvm/avian/classpath/java/security/AccessController.java b/sgx-jvm/avian/classpath/java/security/AccessController.java new file mode 100644 index 0000000000..e0fba259f8 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/security/AccessController.java @@ -0,0 +1,29 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.security; + +/** + * No real access control is implemented here. + * + * @author zsombor + * + */ +public class AccessController { + + public static T doPrivileged (PrivilegedAction action) { + return action.run(); + } + + public static void checkPermission(Permission perm) throws AccessControlException { + + } + +} diff --git a/sgx-jvm/avian/classpath/java/security/AllPermission.java b/sgx-jvm/avian/classpath/java/security/AllPermission.java new file mode 100644 index 0000000000..c39089f22c --- /dev/null +++ b/sgx-jvm/avian/classpath/java/security/AllPermission.java @@ -0,0 +1,19 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.security; + +public class AllPermission extends Permission { + public AllPermission() { + super(""); + } + + +} diff --git a/sgx-jvm/avian/classpath/java/security/BasicPermission.java b/sgx-jvm/avian/classpath/java/security/BasicPermission.java new file mode 100644 index 0000000000..74e734eb5c --- /dev/null +++ b/sgx-jvm/avian/classpath/java/security/BasicPermission.java @@ -0,0 +1,19 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.security; + +public class BasicPermission extends Permission { + + public BasicPermission(String name) { + super(name); + } + +} diff --git a/sgx-jvm/avian/classpath/java/security/CodeSource.java b/sgx-jvm/avian/classpath/java/security/CodeSource.java new file mode 100644 index 0000000000..b32723caf0 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/security/CodeSource.java @@ -0,0 +1,26 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.security; + +import java.net.URL; +import java.security.cert.Certificate; + +public class CodeSource { + private final URL url; + + public CodeSource(URL url, Certificate[] certificates) { + this.url = url; + } + + public URL getLocation() { + return url; + } +} diff --git a/sgx-jvm/avian/classpath/java/security/Permission.java b/sgx-jvm/avian/classpath/java/security/Permission.java new file mode 100644 index 0000000000..9f2ddeddef --- /dev/null +++ b/sgx-jvm/avian/classpath/java/security/Permission.java @@ -0,0 +1,33 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.security; + +public abstract class Permission { + + protected String name; + + public Permission(String name) { + this.name = name; + } + + public String getName() { + return name; + } + + @Override + public String toString() { + return this.getClass().getSimpleName() + '['+name+']'; + } + + public PermissionCollection newPermissionCollection() { + return null; + } +} diff --git a/sgx-jvm/avian/classpath/java/security/PermissionCollection.java b/sgx-jvm/avian/classpath/java/security/PermissionCollection.java new file mode 100644 index 0000000000..efdfc56a66 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/security/PermissionCollection.java @@ -0,0 +1,15 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.security; + +public abstract class PermissionCollection { + public abstract void add(Permission p); +} diff --git a/sgx-jvm/avian/classpath/java/security/Permissions.java b/sgx-jvm/avian/classpath/java/security/Permissions.java new file mode 100644 index 0000000000..919185cb7e --- /dev/null +++ b/sgx-jvm/avian/classpath/java/security/Permissions.java @@ -0,0 +1,41 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.security; + +import java.util.Map; +import java.util.HashMap; +import java.util.Set; +import java.util.HashSet; + +public class Permissions extends PermissionCollection { + private final Map collections = new HashMap(); + + public void add(Permission p) { + Class c = p.getClass(); + PermissionCollection pc = collections.get(c); + if (pc == null) { + pc = p.newPermissionCollection(); + if (pc == null) { + pc = new MyPermissionCollection(); + } + collections.put(c, pc); + } + pc.add(p); + } + + private static class MyPermissionCollection extends PermissionCollection { + private final Set permissions = new HashSet(); + + public void add(Permission p) { + permissions.add(p); + } + } +} diff --git a/sgx-jvm/avian/classpath/java/security/PrivilegedAction.java b/sgx-jvm/avian/classpath/java/security/PrivilegedAction.java new file mode 100644 index 0000000000..6e1a1f757b --- /dev/null +++ b/sgx-jvm/avian/classpath/java/security/PrivilegedAction.java @@ -0,0 +1,17 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.security; + +public interface PrivilegedAction { + + T run(); + +} diff --git a/sgx-jvm/avian/classpath/java/security/ProtectionDomain.java b/sgx-jvm/avian/classpath/java/security/ProtectionDomain.java new file mode 100644 index 0000000000..8186405853 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/security/ProtectionDomain.java @@ -0,0 +1,27 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.security; + +public class ProtectionDomain { + private final CodeSource codeSource; + private final PermissionCollection permissions; + + public ProtectionDomain(CodeSource codeSource, + PermissionCollection permissions) + { + this.codeSource = codeSource; + this.permissions = permissions; + } + + public CodeSource getCodeSource() { + return codeSource; + } +} diff --git a/sgx-jvm/avian/classpath/java/security/SecurityPermission.java b/sgx-jvm/avian/classpath/java/security/SecurityPermission.java new file mode 100644 index 0000000000..22a356a731 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/security/SecurityPermission.java @@ -0,0 +1,19 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.security; + +public class SecurityPermission extends BasicPermission { + + public SecurityPermission(String name) { + super(name); + } + +} diff --git a/sgx-jvm/avian/classpath/java/security/cert/Certificate.java b/sgx-jvm/avian/classpath/java/security/cert/Certificate.java new file mode 100644 index 0000000000..956aadc592 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/security/cert/Certificate.java @@ -0,0 +1,13 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.security.cert; + +public abstract class Certificate { } diff --git a/sgx-jvm/avian/classpath/java/text/DateFormatSymbols.java b/sgx-jvm/avian/classpath/java/text/DateFormatSymbols.java new file mode 100644 index 0000000000..a03becffe8 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/text/DateFormatSymbols.java @@ -0,0 +1,36 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.text; + +public class DateFormatSymbols { + private String[] ampm = new String[] { "AM", "PM" }; + private String[] shortWeekdays = new String[] { "Sun", "Mon", "Tue", + "Wed", "Thu", "Fri", "Sat" }; + private String[] shortMonths = new String[] { "Jan", "Feb", "Mar", "Apr", + "May", "Jun", "Jul", "Aug", + "Sep", "Oct", "Nov", "Dec" }; + + public String[] getAmPmStrings() { + return ampm; + } + + public void setAmPmStrings(String[] v) { + ampm = v; + } + + public String[] getShortWeekdays() { + return shortWeekdays; + } + + public String[] getShortMonths() { + return shortMonths; + } +} diff --git a/sgx-jvm/avian/classpath/java/text/FieldPosition.java b/sgx-jvm/avian/classpath/java/text/FieldPosition.java new file mode 100644 index 0000000000..d9ec4ebd7a --- /dev/null +++ b/sgx-jvm/avian/classpath/java/text/FieldPosition.java @@ -0,0 +1,15 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.text; + +public class FieldPosition { + public FieldPosition(int field) { } +} diff --git a/sgx-jvm/avian/classpath/java/text/Format.java b/sgx-jvm/avian/classpath/java/text/Format.java new file mode 100644 index 0000000000..b99649540c --- /dev/null +++ b/sgx-jvm/avian/classpath/java/text/Format.java @@ -0,0 +1,20 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.text; + +public abstract class Format { + public final String format(Object o) { + return format(o, new StringBuffer(), new FieldPosition(0)).toString(); + } + + public abstract StringBuffer format(Object o, StringBuffer target, + FieldPosition p); +} diff --git a/sgx-jvm/avian/classpath/java/text/MessageFormat.java b/sgx-jvm/avian/classpath/java/text/MessageFormat.java new file mode 100644 index 0000000000..4ff224546d --- /dev/null +++ b/sgx-jvm/avian/classpath/java/text/MessageFormat.java @@ -0,0 +1,103 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.text; + +import java.util.Locale; + +/** + * A minimalist Java message formatter. + * The string is a sequence of letters, copied verbatim unless the letter + * is "{" or "'". If the letter is a "{", this begins a parameter, which + * is a base-10 number. {0} will be replaced by the first argument to + * format, {1} is the second argument, and so on. + * If the letter is a single tick ("'"), then all characters + * until the mathcing tick are outputted verbatim(this is useful for escaping + * the { character). + *

Examples

+ * + * + * + * + * + * + *
formatArgsResult
There are {0} grapessixThere are six grapes
{2} + {1} = {0}5 2 33 + 2 = 5
{0} and {0} and {0}againagain and again and again
Joe''s age is {0}, not '{0}'30Joe's age is 30, not {0}
+ */ +public class MessageFormat extends Format { + private String pattern; + private final Locale locale; + + public MessageFormat(String pattern, Locale locale) { + this.pattern = pattern; + this.locale = locale; + } + + public MessageFormat(String pattern) { + this(pattern, Locale.getDefault()); + } + + public StringBuffer format(Object args[], StringBuffer target, FieldPosition pos) { + int i=0; + int len=pattern.length(); + + while (i < len) { + char ch = pattern.charAt(i); + if (ch == '{') { + // Param should be a number + int num=0; + while (i < (len-1)) { + i++; + ch = pattern.charAt(i); + if ((ch >= '0') && (ch <= '9')) { + num = num * 10 + (ch - '0'); + } else if (ch == '}') { + target.append((args[num] == null) ? "null" : args[num].toString()); + break; + } else { + throw new IllegalArgumentException("Character within {} isn't digit: " + ch); + } + } + } else if (ch == '\'') { + // Char is a literal string + i++; + ch = pattern.charAt(i); + if (ch == '\'') { + target.append('\''); + } else { + while (ch != '\'') { + target.append(ch); + i++; + ch = pattern.charAt(i); + } + } + } else { + target.append(ch); + } + i++; + } + return target; + } + + public static String format(String message, Object... args) { + return new MessageFormat(message).format(args, new StringBuffer(), new FieldPosition(0)).toString(); + } + + public StringBuffer format(Object args, StringBuffer target, FieldPosition p) { + return format((Object[]) args, target, p); + } + + public void applyPattern(String pattern) { + this.pattern = pattern; + } + + public String toPattern() { + return pattern; + } +} diff --git a/sgx-jvm/avian/classpath/java/text/ParseException.java b/sgx-jvm/avian/classpath/java/text/ParseException.java new file mode 100644 index 0000000000..ba9d74a801 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/text/ParseException.java @@ -0,0 +1,24 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.text; + +public class ParseException extends Exception { + private int errorOffset; + + public ParseException(String message, int errorOffset) { + super(message); + this.errorOffset = errorOffset; + } + + public int getErrorOffset() { + return errorOffset; + } +} diff --git a/sgx-jvm/avian/classpath/java/text/ParsePosition.java b/sgx-jvm/avian/classpath/java/text/ParsePosition.java new file mode 100644 index 0000000000..93a730abcd --- /dev/null +++ b/sgx-jvm/avian/classpath/java/text/ParsePosition.java @@ -0,0 +1,39 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.text; + +public class ParsePosition { + private int index, errorIndex = -1; + + public ParsePosition(int index) { + this.index = index; + } + + public int getErrorIndex() { + return errorIndex; + } + + public int getIndex() { + return index; + } + + public void setErrorIndex(int i) { + errorIndex = i; + } + + public void setIndex(int i) { + index = i; + } + + public String toString() { + return "index: " + index + "(error index: " + errorIndex + ")"; + } +} diff --git a/sgx-jvm/avian/classpath/java/text/SimpleDateFormat.java b/sgx-jvm/avian/classpath/java/text/SimpleDateFormat.java new file mode 100644 index 0000000000..483ac707e9 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/text/SimpleDateFormat.java @@ -0,0 +1,105 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.text; + +import java.util.Calendar; +import java.util.Date; +import java.util.TimeZone; + +public class SimpleDateFormat { + private String pattern; + + public SimpleDateFormat(String pattern) { + this.pattern = pattern; + if (! "yyyy-MM-dd'T'HH:mm:ss".equals(pattern)) { + throw new UnsupportedOperationException("Unsupported pattern: " + pattern); + } + } + + public void setTimeZone(TimeZone tz) { + if(!tz.getDisplayName().equals("GMT")) { + throw new UnsupportedOperationException(); + } + } + + public StringBuffer format(Date date, StringBuffer buffer, FieldPosition position) { + Calendar calendar = Calendar.getInstance(); + calendar.setTime(date); + pad(buffer, calendar.get(Calendar.YEAR), 4); + buffer.append('-'); + pad(buffer, calendar.get(Calendar.MONTH) + 1, 2); + buffer.append('-'); + pad(buffer, calendar.get(Calendar.DAY_OF_MONTH), 2); + buffer.append("T"); + pad(buffer, calendar.get(Calendar.HOUR_OF_DAY), 2); + buffer.append(':'); + pad(buffer, calendar.get(Calendar.MINUTE), 2); + buffer.append(':'); + pad(buffer, calendar.get(Calendar.SECOND), 2); + return buffer; + } + + public Date parse(String text) { + return parse(text, new ParsePosition(0)); + } + + public Date parse(String text, ParsePosition position) { + int index = position.getIndex(); + try { + Calendar calendar = Calendar.getInstance(); + index = parseField(text, index, 4, calendar, Calendar.YEAR, 0); + index = expectPrefix(text, index, "-"); + index = parseField(text, index, 2, calendar, Calendar.MONTH, -1); + index = expectPrefix(text, index, "-"); + index = parseField(text, index, 2, calendar, Calendar.DAY_OF_MONTH, 0); + index = expectPrefix(text, index, "T"); + index = parseField(text, index, 2, calendar, Calendar.HOUR_OF_DAY, 0); + index = expectPrefix(text, index, ":"); + index = parseField(text, index, 2, calendar, Calendar.MINUTE, 0); + index = expectPrefix(text, index, ":"); + index = parseField(text, index, 2, calendar, Calendar.SECOND, 0); + position.setIndex(index); + return calendar.getTime(); + } catch (ParseException e) { + position.setErrorIndex(index); + return null; + } + } + + private static void pad(StringBuffer buffer, int value, int digits) { + int i = value == 0 ? 1 : value; + while (i > 0) { + i /= 10; + --digits; + } + while (digits-- > 0) { + buffer.append('0'); + } + buffer.append(value); + } + + private static int parseField(String text, int offset, int length, Calendar calendar, int field, int adjustment) throws ParseException { + if (text.length() < offset + length) throw new ParseException("Short date: " + text, offset); + try { + int value = Integer.parseInt(text.substring(offset, offset + length), 10); + calendar.set(field, value + adjustment); + } catch (NumberFormatException e) { + throw new ParseException("Not a number: " + text, offset); + } + return offset + length; + } + + private static int expectPrefix(String text, int offset, String prefix) throws ParseException { + if (text.length() <= offset) throw new ParseException("Short date: " + text, offset); + if (! text.substring(offset).startsWith(prefix)) throw new ParseException("Parse error: " + text, offset); + return offset + prefix.length(); + } +} diff --git a/sgx-jvm/avian/classpath/java/util/AbstractCollection.java b/sgx-jvm/avian/classpath/java/util/AbstractCollection.java new file mode 100644 index 0000000000..d6b6dda81f --- /dev/null +++ b/sgx-jvm/avian/classpath/java/util/AbstractCollection.java @@ -0,0 +1,108 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.util; + +/** + * @author zsombor + * + */ +public abstract class AbstractCollection implements Collection { + public boolean add(T element) { + throw new UnsupportedOperationException("adding to " + + this.getClass().getName()); + } + + public boolean addAll(Collection collection) { + boolean result = false; + for (T obj : collection) { + result |= add(obj); + } + return result; + } + + public void clear() { + throw new UnsupportedOperationException("clear() in " + + this.getClass().getName()); + } + + public boolean contains(Object element) { + if (element != null) { + for (Iterator iter = iterator(); iter.hasNext();) { + if (element.equals(iter.next())) { + return true; + } + } + } else { + for (Iterator iter = iterator(); iter.hasNext();) { + if (iter.next()==null) { + return true; + } + } + + } + return false; + } + + public boolean containsAll(Collection c) { + if (c == null) { + throw new NullPointerException("Collection is null"); + } + + Iterator it = c.iterator(); + while (it.hasNext()) { + if (! contains(it.next())) { + return false; + } + } + + return true; + } + + public boolean isEmpty() { + return size() == 0; + } + + public boolean remove(Object element) { + throw new UnsupportedOperationException("remove(T) in " + + this.getClass().getName()); + } + + public boolean removeAll(Collection c) { + if (c == null) { + throw new NullPointerException("Collection is null"); + } + + boolean changed = false; + + Iterator it = c.iterator(); + while (it.hasNext()) { + changed = remove(it.next()) || changed; + } + + return changed; + } + + public abstract int size(); + + public Object[] toArray() { + return toArray(new Object[size()]); + } + + public S[] toArray(S[] array) { + return avian.Data.toArray(this, array); + } + + public abstract Iterator iterator(); + + public String toString() { + return avian.Data.toString(this); + } +} diff --git a/sgx-jvm/avian/classpath/java/util/AbstractDeque.java b/sgx-jvm/avian/classpath/java/util/AbstractDeque.java new file mode 100644 index 0000000000..f88858bb2e --- /dev/null +++ b/sgx-jvm/avian/classpath/java/util/AbstractDeque.java @@ -0,0 +1,90 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.util; + +public abstract class AbstractDeque extends AbstractQueue + implements Deque { + + @Override + public void push(T e) { + addFirst(e); + } + + @Override + public void addLast(T element) { + if (! offerLast(element)) { + throw new IllegalStateException(); + } + } + + @Override + public void addFirst(T element) { + if (! offerFirst(element)) { + throw new IllegalStateException(); + } + } + + @Override + public boolean offer(T element) { + return offerLast(element); + } + + @Override + public T poll() { + return pollFirst(); + } + + @Override + public T pop() { + return removeFirst(); + } + + @Override + public T removeFirst() { + return remove(); + } + + @Override + public boolean remove(Object element) { + return removeFirstOccurrence(element); + } + + @Override + public T removeLast() { + T result = pollLast(); + if (result == null) { + throw new NoSuchElementException(); + } else { + return result; + } + } + + @Override + public T getFirst() { + return element(); + } + + @Override + public T getLast() { + T result = peekLast(); + + if (result == null) { + throw new NoSuchElementException(); + } + + return result; + } + + @Override + public T peek() { + return peekFirst(); + } +} diff --git a/sgx-jvm/avian/classpath/java/util/AbstractList.java b/sgx-jvm/avian/classpath/java/util/AbstractList.java new file mode 100644 index 0000000000..5ad69eaabc --- /dev/null +++ b/sgx-jvm/avian/classpath/java/util/AbstractList.java @@ -0,0 +1,67 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.util; + +public abstract class AbstractList extends AbstractCollection + implements List +{ + protected int modCount; + + public boolean add(T o) { + add(size(), o); + return true; + } + + public boolean addAll(Collection c) { + return addAll(size(), c); + } + + public boolean addAll(int startIndex, Collection c) { + if (c == null) { + throw new NullPointerException("Collection is null"); + } + + int index = startIndex; + boolean changed = false; + + Iterator it = c.iterator(); + while (it.hasNext()) { + add(index++, it.next()); + changed = true; + } + + return changed; + } + + public Iterator iterator() { + return listIterator(); + } + + public ListIterator listIterator() { + return new Collections.ArrayListIterator(this); + } + + public int indexOf(Object o) { + int i = 0; + for (T v: this) { + if (o == null) { + if (v == null) { + return i; + } + } else if (o.equals(v)) { + return i; + } + + ++ i; + } + return -1; + } +} diff --git a/sgx-jvm/avian/classpath/java/util/AbstractMap.java b/sgx-jvm/avian/classpath/java/util/AbstractMap.java new file mode 100644 index 0000000000..88cd22636d --- /dev/null +++ b/sgx-jvm/avian/classpath/java/util/AbstractMap.java @@ -0,0 +1,13 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.util; + +public abstract class AbstractMap extends Object implements Map { } diff --git a/sgx-jvm/avian/classpath/java/util/AbstractQueue.java b/sgx-jvm/avian/classpath/java/util/AbstractQueue.java new file mode 100644 index 0000000000..e407672c76 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/util/AbstractQueue.java @@ -0,0 +1,67 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.util; + +public abstract class AbstractQueue extends AbstractCollection implements Queue { + + protected AbstractQueue() { + super(); + } + + @Override + public boolean add(T element) { + if (offer(element)) { + return true; + } else { + throw new IllegalStateException(); + } + } + + @Override + public boolean addAll(Collection collection) { + if (collection == null) { + throw new NullPointerException(); + } + + for (T element : collection) { + add(element); + } + + return true; + } + + @Override + public void clear() { + while (size() > 0) { + poll(); + } + } + + @Override + public T element() { + T result = peek(); + if (result == null) { + throw new NoSuchElementException(); + } else { + return result; + } + } + + @Override + public T remove() { + T result = poll(); + if (result == null) { + throw new NoSuchElementException(); + } else { + return result; + } + } +} diff --git a/sgx-jvm/avian/classpath/java/util/AbstractSequentialList.java b/sgx-jvm/avian/classpath/java/util/AbstractSequentialList.java new file mode 100644 index 0000000000..3f359ec502 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/util/AbstractSequentialList.java @@ -0,0 +1,15 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.util; + +public abstract class AbstractSequentialList extends AbstractList + implements List +{ } diff --git a/sgx-jvm/avian/classpath/java/util/AbstractSet.java b/sgx-jvm/avian/classpath/java/util/AbstractSet.java new file mode 100644 index 0000000000..29b3a95a82 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/util/AbstractSet.java @@ -0,0 +1,14 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.util; + +public abstract class AbstractSet extends AbstractCollection implements Set { +} diff --git a/sgx-jvm/avian/classpath/java/util/ArrayDeque.java b/sgx-jvm/avian/classpath/java/util/ArrayDeque.java new file mode 100644 index 0000000000..8801806064 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/util/ArrayDeque.java @@ -0,0 +1,364 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.util; + +public class ArrayDeque extends AbstractDeque + implements Deque { + private Object[] dataArray; + // both indexes are inclusive, except when size == 0 + private int startIndex; + private int endIndex; + private int size; + private int modCount; + + public ArrayDeque() { + this(16); + } + + public ArrayDeque(int intialSize) { + dataArray = new Object[intialSize]; + modCount = 0; + clear(); + } + + public ArrayDeque(Collection c) { + this(c.size()); + + addAll(c); + } + + private void copyInto(Object[] array) { + if (startIndex <= endIndex) { + // only one copy needed + System.arraycopy(dataArray, startIndex, array, 0, size); + } else { + int firstCopyCount = dataArray.length - startIndex; + System.arraycopy(dataArray, startIndex, array, 0, firstCopyCount); + System.arraycopy(dataArray, 0, array, firstCopyCount, endIndex + 1); + } + } + + private void ensureCapacity(int newSize) { + if (dataArray.length < newSize) { + Object[] newArray = new Object[dataArray.length * 2]; + copyInto(newArray); + + dataArray = newArray; + startIndex = 0; + endIndex = size - 1; + } + } + + @Override + public boolean offerFirst(T e) { + ensureCapacity(size() + 1); + modCount++; + + if (size > 0) { + // we don't need to move the head index for the first one + startIndex--; + if (startIndex < 0) { // wrapping to the end of the array + startIndex = dataArray.length - 1; + } + } + size++; + dataArray[startIndex] = e; + + return true; + } + + @Override + public boolean offerLast(T e) { + ensureCapacity(size() + 1); + modCount++; + + if (size > 0) { + // we don't need to move the tail index for the first one + endIndex = (endIndex + 1) % dataArray.length; + } + size++; + dataArray[endIndex] = e; + + return true; + } + + @Override + public T pollFirst() { + modCount++; + + if (size == 0) { + return null; + } + + @SuppressWarnings("unchecked") + T result = (T)dataArray[startIndex]; + size--; + if (size == 0) { + startIndex = endIndex = 0; + } else { + startIndex = (startIndex + 1) % dataArray.length; + } + + return result; + } + + @Override + public T pollLast() { + modCount++; + + if (size == 0) { + return null; + } + + @SuppressWarnings("unchecked") + T result = (T)dataArray[endIndex]; + size--; + if (size == 0) { + startIndex = endIndex = 0; + } else { + endIndex--; + if (endIndex < 0) { + endIndex = dataArray.length - 1; + } + } + + return result; + } + + @Override + public T peekFirst() { + if (size == 0) { + return null; + } else { + @SuppressWarnings("unchecked") + T result = (T)dataArray[startIndex]; + return result; + } + } + + @Override + public T peekLast() { + if (size == 0) { + return null; + } else { + @SuppressWarnings("unchecked") + T result = (T)dataArray[endIndex]; + return result; + } + } + + @Override + public boolean addAll(Collection c) { + if (c == null || c.isEmpty()) { + return false; + } + + ensureCapacity(size() + c.size()); + + Iterator it = c.iterator(); + while (it.hasNext()) { + add(it.next()); + } + + return true; + } + + @Override + public boolean removeAll(Collection c) { + boolean removed = false; + Iterator it = c.iterator(); + while (it.hasNext()) { + removed = remove(it.next()) || removed; + } + + return removed; + } + + private boolean remove(Object o, boolean first) { + modCount++; + + Iterator it; + if (first) { + it = iterator(); + } else { + it = descendingIterator(); + } + while (it.hasNext()) { + T next = it.next(); + if (next == null) { + if (o == null) { + it.remove(); + return true; + } + } else if (next.equals(o)) { + it.remove(); + return true; + } + } + + return false; + } + + @Override + public boolean removeFirstOccurrence(Object o) { + return remove(o, true); + } + + @Override + public boolean removeLastOccurrence(Object o) { + return remove(o, false); + } + + @Override + public void clear() { + size = 0; + startIndex = endIndex = 0; + modCount++; + } + + @Override + public int size() { + return size; + } + + @Override + public boolean contains(Object element) { + Iterator it = iterator(); + while (it.hasNext()) { + T next = it.next(); + if (next == null) { + if (element == null) { + return true; + } + } else if (next.equals(element)) { + return true; + } + } + + return false; + } + + @Override + public boolean containsAll(Collection c) { + Iterator it = c.iterator(); + while (it.hasNext()) { + if (! contains(it.next())) { + return false; + } + } + + return true; + } + + @Override + public Object[] toArray() { + Object[] result = new Object[size]; + copyInto(result); + + return result; + } + + @Override + public S[] toArray(S[] array) { + return avian.Data.toArray(this, array); + } + + public Iterator iterator() { + return new GenericIterator() { + @Override + protected int getArrayIndex() { + int result = (currentIndex + startIndex) % dataArray.length; + return result; + } + }; + } + + public Iterator descendingIterator() { + return new GenericIterator() { + @Override + protected int getArrayIndex() { + int result = (endIndex - currentIndex) % dataArray.length; + return result; + } + }; + } + + private abstract class GenericIterator implements Iterator { + protected int expectedModCount = modCount; + protected int currentIndex = 0; + + protected abstract int getArrayIndex(); + + @Override + public T next() { + if (modCount != expectedModCount) { + throw new ConcurrentModificationException(); + } else if (currentIndex == size) { + throw new NoSuchElementException(); + } + + @SuppressWarnings("unchecked") + T result = (T)dataArray[getArrayIndex()]; + currentIndex++; + + return result; + } + + @Override + public boolean hasNext() { + return currentIndex < size; + } + + @Override + public void remove() { + currentIndex--; + + int removalIndex = getArrayIndex(); + if (removalIndex == startIndex) { + // avoid array copy + pollFirst(); + expectedModCount = modCount; + } else if (removalIndex == endIndex) { + // avoid array copy + pollLast(); + expectedModCount = modCount; + } else { // array must be copied + Object[] newArray = new Object[dataArray.length]; + if (startIndex <= endIndex) { + int firstCopyCount = removalIndex - startIndex; + System.arraycopy(dataArray, startIndex, + newArray, 0, firstCopyCount); + System.arraycopy(dataArray, removalIndex + 1, + newArray, firstCopyCount, size - firstCopyCount); + } else if (removalIndex > startIndex) { + int firstCopyCount = removalIndex - startIndex; + System.arraycopy(dataArray, startIndex, + newArray, 0, firstCopyCount); + System.arraycopy(dataArray, startIndex + firstCopyCount + 1, + newArray, firstCopyCount, dataArray.length - removalIndex - 1); + System.arraycopy(dataArray, 0, newArray, size - removalIndex, endIndex + 1); + } else { + int firstCopyCount = dataArray.length - startIndex; + System.arraycopy(dataArray, startIndex, + newArray, 0, firstCopyCount); + System.arraycopy(dataArray, 0, + newArray, firstCopyCount, removalIndex); + System.arraycopy(dataArray, removalIndex + 1, + newArray, firstCopyCount + removalIndex, endIndex - removalIndex); + } + + dataArray = newArray; + startIndex = 0; + endIndex = --size - 1; + } + } + } +} diff --git a/sgx-jvm/avian/classpath/java/util/ArrayList.java b/sgx-jvm/avian/classpath/java/util/ArrayList.java new file mode 100644 index 0000000000..325fa1591f --- /dev/null +++ b/sgx-jvm/avian/classpath/java/util/ArrayList.java @@ -0,0 +1,209 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.util; + +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; + +public class ArrayList extends AbstractList implements java.io.Serializable, RandomAccess { + private static final int MinimumCapacity = 16; + + private Object[] array; + private int size; + + public ArrayList(int capacity) { + resize(capacity); + } + + public ArrayList() { + this(0); + } + + public ArrayList(Collection source) { + this(source.size()); + addAll(source); + } + + private void grow(int newSize) { + if (array == null || newSize > array.length) { + resize(Math.max(newSize, array == null + ? MinimumCapacity : array.length * 2)); + } + } + + private void shrink(int newSize) { + if (array.length / 2 >= MinimumCapacity && newSize <= array.length / 3) { + resize(array.length / 2); + } + } + + private void resize(int capacity) { + Object[] newArray = null; + if (capacity != 0) { + if (array != null && array.length == capacity) { + return; + } + + newArray = new Object[capacity]; + if (array != null) { + System.arraycopy(array, 0, newArray, 0, size); + } + } + array = newArray; + } + + private static boolean equal(Object a, Object b) { + return (a == null && b == null) || (a != null && a.equals(b)); + } + + public int size() { + return size; + } + + public void ensureCapacity(int capacity) { + grow(capacity); + } + + public boolean contains(Object element) { + for (int i = 0; i < size; ++i) { + if (equal(element, array[i])) { + return true; + } + } + return false; + } + + public void add(int index, T element) { + int newSize = Math.max(size+1, index+1); + grow(newSize); + size = newSize; + System.arraycopy(array, index, array, index+1, size-index-1); + array[index] = element; + } + + public boolean add(T element) { + add(size, element); + return true; + } + + public boolean addAll(Collection collection) { + for (T t: collection) add(t); + return true; + } + + public int indexOf(Object element) { + for (int i = 0; i < size; ++i) { + if (equal(element, array[i])) { + return i; + } + } + return -1; + } + + public int lastIndexOf(Object element) { + for (int i = size - 1; i >= 0; --i) { + if (equal(element, array[i])) { + return i; + } + } + return -1; + } + + public T get(int index) { + if (index >= 0 && index < size) { + return (T) array[index]; + } else { + throw new IndexOutOfBoundsException(index + " not in [0, " + size + ")"); + } + } + + public T set(int index, T element) { + if (index >= 0 && index < size) { + Object oldValue = array[index]; + array[index] = element; + return (T) oldValue; + } else { + throw new IndexOutOfBoundsException(index + " not in [0, " + size + ")"); + } + } + + public T remove(int index) { + T v = get(index); + + int newSize = size - 1; + + if (index == newSize) { + array[index] = null; + } else { + System.arraycopy(array, index + 1, array, index, newSize - index); + } + + shrink(newSize); + size = newSize; + + return v; + } + + public boolean remove(Object element) { + for (int i = 0; i < size; ++i) { + if (equal(element, array[i])) { + remove(i); + return true; + } + } + return false; + } + + public boolean isEmpty() { + return size() == 0; + } + + public void clear() { + array = null; + size = 0; + } + + public Iterator iterator() { + return listIterator(); + } + + public ListIterator listIterator(int index) { + return new Collections.ArrayListIterator(this, index); + } + + public ListIterator listIterator() { + return listIterator(0); + } + + public String toString() { + return avian.Data.toString(this); + } + + private void writeObject(ObjectOutputStream out) throws IOException { + out.defaultWriteObject(); + out.writeInt(array.length); + for (T o : this) { + out.writeObject(o); + } + } + + private void readObject(ObjectInputStream in) + throws ClassNotFoundException, IOException + { + in.defaultReadObject(); + int capacity = in.readInt(); + grow(capacity); + for (int i = 0; i < size; i++) { + array[i] = in.readObject(); + } + } +} diff --git a/sgx-jvm/avian/classpath/java/util/Arrays.java b/sgx-jvm/avian/classpath/java/util/Arrays.java new file mode 100644 index 0000000000..0c2de7dba2 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/util/Arrays.java @@ -0,0 +1,689 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.util; + +import java.lang.reflect.Array; + +public class Arrays { + private Arrays() { } + + public static String toString(Object[] a) { + return asList(a).toString(); + } + + public static String toString(boolean[] a) { + if (a == null) { + return "null"; + } else { + StringBuilder sb = new StringBuilder(); + sb.append("["); + for (int i = 0; i < a.length; ++i) { + sb.append(String.valueOf(a[i])); + if (i + 1 != a.length) { + sb.append(", "); + } + } + sb.append("]"); + return sb.toString(); + } + } + + public static String toString(byte[] a) { + if (a == null) { + return "null"; + } else { + StringBuilder sb = new StringBuilder(); + sb.append("["); + for (int i = 0; i < a.length; ++i) { + sb.append(String.valueOf(a[i])); + if (i + 1 != a.length) { + sb.append(", "); + } + } + sb.append("]"); + return sb.toString(); + } + } + + public static String toString(short[] a) { + if (a == null) { + return "null"; + } else { + StringBuilder sb = new StringBuilder(); + sb.append("["); + for (int i = 0; i < a.length; ++i) { + sb.append(String.valueOf(a[i])); + if (i + 1 != a.length) { + sb.append(", "); + } + } + sb.append("]"); + return sb.toString(); + } + } + + public static String toString(int[] a) { + if (a == null) { + return "null"; + } else { + StringBuilder sb = new StringBuilder(); + sb.append("["); + for (int i = 0; i < a.length; ++i) { + sb.append(String.valueOf(a[i])); + if (i + 1 != a.length) { + sb.append(", "); + } + } + sb.append("]"); + return sb.toString(); + } + } + + public static String toString(long[] a) { + if (a == null) { + return "null"; + } else { + StringBuilder sb = new StringBuilder(); + sb.append("["); + for (int i = 0; i < a.length; ++i) { + sb.append(String.valueOf(a[i])); + if (i + 1 != a.length) { + sb.append(", "); + } + } + sb.append("]"); + return sb.toString(); + } + } + + public static String toString(float[] a) { + if (a == null) { + return "null"; + } else { + StringBuilder sb = new StringBuilder(); + sb.append("["); + for (int i = 0; i < a.length; ++i) { + sb.append(String.valueOf(a[i])); + if (i + 1 != a.length) { + sb.append(", "); + } + } + sb.append("]"); + return sb.toString(); + } + } + + public static String toString(double[] a) { + if (a == null) { + return "null"; + } else { + StringBuilder sb = new StringBuilder(); + sb.append("["); + for (int i = 0; i < a.length; ++i) { + sb.append(String.valueOf(a[i])); + if (i + 1 != a.length) { + sb.append(", "); + } + } + sb.append("]"); + return sb.toString(); + } + } + + private static boolean equal(Object a, Object b) { + return (a == null && b == null) || (a != null && a.equals(b)); + } + + public static void sort(Object[] array) { + sort(array, new Comparator() { + @Override + public int compare(Object a, Object b) { + return ((Comparable) a).compareTo(b); + } + }); + } + + private final static int SORT_SIZE_THRESHOLD = 16; + + public static void sort(T[] array, Comparator comparator) { + introSort(array, comparator, 0, array.length, array.length); + insertionSort(array, comparator); + } + + private static void introSort(T[] array, + Comparator comparator, int begin, int end, int limit) + { + while (end - begin > SORT_SIZE_THRESHOLD) { + if (limit == 0) { + heapSort(array, comparator, begin, end); + return; + } + limit >>= 1; + + // median of three + T a = array[begin]; + T b = array[begin + (end - begin) / 2 + 1]; + T c = array[end - 1]; + T median; + if (comparator.compare(a, b) < 0) { + median = comparator.compare(b, c) < 0 ? + b : (comparator.compare(a, c) < 0 ? c : a); + } else { + median = comparator.compare(b, c) > 0 ? + b : (comparator.compare(a, c) > 0 ? c : a); + } + + // partition + int pivot, i = begin, j = end; + for (;;) { + while (comparator.compare(array[i], median) < 0) { + ++i; + } + --j; + while (comparator.compare(median, array[j]) < 0) { + --j; + } + if (i >= j) { + pivot = i; + break; + } + T swap = array[i]; + array[i] = array[j]; + array[j] = swap; + ++i; + } + + introSort(array, comparator, pivot, end, limit); + end = pivot; + } + } + + private static void heapSort(T[] array, Comparator comparator, + int begin, int end) + { + int count = end - begin; + for (int i = count / 2 - 1; i >= 0; --i) { + siftDown(array, comparator, i, count, begin); + } + for (int i = count - 1; i > 0; --i) { + // swap begin and begin + i + T swap = array[begin + i]; + array[begin + i] = array[begin]; + array[begin] = swap; + + siftDown(array, comparator, 0, i, begin); + } + } + + private static void siftDown(T[] array, Comparator comparator, + int i, int count, int offset) + { + T value = array[offset + i]; + while (i < count / 2) { + int child = 2 * i + 1; + if (child + 1 < count && + comparator.compare(array[child], array[child + 1]) < 0) { + ++child; + } + if (comparator.compare(value, array[child]) >= 0) { + break; + } + array[offset + i] = array[offset + child]; + i = child; + } + array[offset + i] = value; + } + + private static void insertionSort(T[] array, + Comparator comparator) + { + for (int j = 1; j < array.length; ++j) { + T t = array[j]; + int i = j - 1; + while (i >= 0 && comparator.compare(array[i], t) > 0) { + array[i + 1] = array[i]; + i = i - 1; + } + array[i + 1] = t; + } + } + + public static int hashCode(Object[] array) { + if(array == null) { + return 9023; + } + + int hc = 823347; + for(Object o : array) { + hc += o != null ? o.hashCode() : 54267; + hc *= 3; + } + return hc; + } + + public static boolean equals(Object[] a, Object[] b) { + if(a == b) { + return true; + } + if(a == null || b == null) { + return false; + } + if(a.length != b.length) { + return false; + } + for(int i = 0; i < a.length; i++) { + if(!equal(a[i], b[i])) { + return false; + } + } + return true; + } + + public static boolean equals(byte[] a, byte[] b) { + if(a == b) { + return true; + } + if(a == null || b == null) { + return false; + } + if(a.length != b.length) { + return false; + } + for(int i = 0; i < a.length; i++) { + if(a[i] != b[i]) { + return false; + } + } + return true; + } + + public static boolean equals(int[] a, int[] b) { + if(a == b) { + return true; + } + if(a == null || b == null) { + return false; + } + if(a.length != b.length) { + return false; + } + for(int i = 0; i < a.length; i++) { + if(a[i] != b[i]) { + return false; + } + } + return true; + } + + public static boolean equals(long[] a, long[] b) { + if(a == b) { + return true; + } + if(a == null || b == null) { + return false; + } + if(a.length != b.length) { + return false; + } + for(int i = 0; i < a.length; i++) { + if(a[i] != b[i]) { + return false; + } + } + return true; + } + + public static boolean equals(short[] a, short[] b) { + if(a == b) { + return true; + } + if(a == null || b == null) { + return false; + } + if(a.length != b.length) { + return false; + } + for(int i = 0; i < a.length; i++) { + if(a[i] != b[i]) { + return false; + } + } + return true; + } + + public static boolean equals(char[] a, char[] b) { + if(a == b) { + return true; + } + if(a == null || b == null) { + return false; + } + if(a.length != b.length) { + return false; + } + for(int i = 0; i < a.length; i++) { + if(a[i] != b[i]) { + return false; + } + } + return true; + } + + public static boolean equals(float[] a, float[] b) { + if(a == b) { + return true; + } + if(a == null || b == null) { + return false; + } + if(a.length != b.length) { + return false; + } + for(int i = 0; i < a.length; i++) { + if(a[i] != b[i]) { + return false; + } + } + return true; + } + + public static boolean equals(double[] a, double[] b) { + if(a == b) { + return true; + } + if(a == null || b == null) { + return false; + } + if(a.length != b.length) { + return false; + } + for(int i = 0; i < a.length; i++) { + if(a[i] != b[i]) { + return false; + } + } + return true; + } + + public static boolean deepEquals(Object[] a, Object[] b) { + if(a == b) { + return true; + } + if(a == null || b == null) { + return false; + } + if(a.length != b.length) { + return false; + } + for(int i = 0; i < a.length; i++) { + if(!Objects.deepEquals(a[i], b[i])) { + return false; + } + } + return true; + } + + public static List asList(final T ... array) { + return new AbstractList() { + @Override + public int size() { + return array.length; + } + + @Override + public void add(int index, T element) { + throw new UnsupportedOperationException(); + } + + @Override + public int indexOf(Object element) { + for (int i = 0; i < array.length; ++i) { + if (equal(element, array[i])) { + return i; + } + } + return -1; + } + + @Override + public int lastIndexOf(Object element) { + for (int i = array.length - 1; i >= 0; --i) { + if (equal(element, array[i])) { + return i; + } + } + return -1; + } + + @Override + public T get(int index) { + return array[index]; + } + + @Override + public T set(int index, T value) { + throw new UnsupportedOperationException(); + } + + @Override + public T remove(int index) { + throw new UnsupportedOperationException(); + } + + @Override + public ListIterator listIterator(int index) { + return new Collections.ArrayListIterator(this, index); + } + }; + } + + private static void checkRange(int len, int start, int stop) { + if (start < 0) { + throw new ArrayIndexOutOfBoundsException(start); + } + if (stop > len) { + throw new ArrayIndexOutOfBoundsException(stop); + } + if (start > stop) { + throw new IllegalArgumentException("start(" + start + ") > stop(" + stop + ")"); + } + } + + public static void fill(int[] array, int value) { + for (int i=0;i void fill(T[] array, T value) { + for (int i=0;i void fill(T[] array, int start, int stop, T value) { + checkRange(array.length, start, stop); + for (int i=start;i newLength ? newLength : array.length; + System.arraycopy(array, 0, result, 0, length); + return result; + } + + public static byte[] copyOf(byte[] array, int newLength) { + byte[] result = new byte[newLength]; + int length = array.length > newLength ? newLength : array.length; + System.arraycopy(array, 0, result, 0, length); + return result; + } + + public static char[] copyOf(char[] array, int newLength) { + char[] result = new char[newLength]; + int length = array.length > newLength ? newLength : array.length; + System.arraycopy(array, 0, result, 0, length); + return result; + } + + public static double[] copyOf(double[] array, int newLength) { + double[] result = new double[newLength]; + int length = array.length > newLength ? newLength : array.length; + System.arraycopy(array, 0, result, 0, length); + return result; + } + + public static float[] copyOf(float[] array, int newLength) { + float[] result = new float[newLength]; + int length = array.length > newLength ? newLength : array.length; + System.arraycopy(array, 0, result, 0, length); + return result; + } + + public static int[] copyOf(int[] array, int newLength) { + int[] result = new int[newLength]; + int length = array.length > newLength ? newLength : array.length; + System.arraycopy(array, 0, result, 0, length); + return result; + } + + public static long[] copyOf(long[] array, int newLength) { + long[] result = new long[newLength]; + int length = array.length > newLength ? newLength : array.length; + System.arraycopy(array, 0, result, 0, length); + return result; + } + + public static short[] copyOf(short[] array, int newLength) { + short[] result = new short[newLength]; + int length = array.length > newLength ? newLength : array.length; + System.arraycopy(array, 0, result, 0, length); + return result; + } + + public static T[] copyOf(T[] array, int newLength) { + Class clazz = array.getClass().getComponentType(); + T[] result = (T[])Array.newInstance(clazz, newLength); + int length = array.length > newLength ? newLength : array.length; + System.arraycopy(array, 0, result, 0, length); + return result; + } + + public static T[] copyOf(U[] array, int newLength, + Class newType) + { + T[] result = (T[])Array.newInstance(newType.getComponentType(), newLength); + int length = array.length > newLength ? newLength : array.length; + System.arraycopy(array, 0, result, 0, length); + return result; + } +} diff --git a/sgx-jvm/avian/classpath/java/util/BitSet.java b/sgx-jvm/avian/classpath/java/util/BitSet.java new file mode 100644 index 0000000000..c76016a5f0 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/util/BitSet.java @@ -0,0 +1,267 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.util; + +import java.io.Serializable; + +/** + * @author zsombor + * + */ +public class BitSet implements Serializable, Cloneable { + + final static int BITS_PER_LONG = 64; + final static int BITS_PER_LONG_SHIFT = 6; + final static long MASK = 0xFFFFFFFFFFFFFFFFL; + + private long[] bits; + + private static int longPosition(int index) { + return index >> BITS_PER_LONG_SHIFT; + } + + private static long bitPosition(int index) { + return 1L << (index % BITS_PER_LONG); + } + + private static long getTrueMask(int fromIndex, int toIndex) { + int currentRange = toIndex - fromIndex; + return (MASK >>> (BITS_PER_LONG - currentRange)) << (fromIndex % BITS_PER_LONG); + } + + public BitSet(int bitLength) { + if (bitLength % BITS_PER_LONG == 0) { + enlarge(longPosition(bitLength)); + } else { + enlarge(longPosition(bitLength) + 1); + } + } + + public BitSet() { + enlarge(1); + } + + public void and(BitSet otherBits) { + int min = Math.min(bits.length, otherBits.bits.length); + for (int i = 0; i < min; i++) { + bits[i] &= otherBits.bits[i]; + } + for (int i = min; i < bits.length; i++) { + bits[i] = 0; + } + } + + public void andNot(BitSet otherBits) { + int max = Math.max(bits.length, otherBits.bits.length); + enlarge(max); + int min = Math.min(bits.length, otherBits.bits.length); + for (int i = 0; i < min; i++) { + bits[i] &= ~otherBits.bits[i]; + } + } + + public void or(BitSet otherBits) { + int max = Math.max(bits.length, otherBits.bits.length); + enlarge(max); + int min = Math.min(bits.length, otherBits.bits.length); + for (int i = 0; i < min; i++) { + bits[i] |= otherBits.bits[i]; + } + } + + public void xor(BitSet otherBits) { + int max = Math.max(bits.length, otherBits.bits.length); + enlarge(max); + int min = Math.min(bits.length, otherBits.bits.length); + for (int i = 0; i < min; i++) { + bits[i] ^= otherBits.bits[i]; + } + } + + private void enlarge(int newPartition) { + if (bits == null || bits.length < (newPartition + 1)) { + long[] newBits = new long[newPartition + 1]; + if (bits != null) { + System.arraycopy(bits, 0, newBits, 0, bits.length); + } + bits = newBits; + } + } + + public boolean get(int index) { + int pos = longPosition(index); + if (pos < bits.length) { + return (bits[pos] & bitPosition(index)) != 0; + } + return false; + } + + public void flip(int index) { + flip(index, index+1); + } + + public void flip(int fromIndex, int toIndex) { + if (fromIndex > toIndex || fromIndex < 0 || toIndex < 0) { + throw new IndexOutOfBoundsException(); + } else if (fromIndex != toIndex) { + MaskInfoIterator iter = new MaskInfoIterator(fromIndex, toIndex); + enlarge(iter.getLastPartition()); + while (iter.hasNext()) { + MaskInfo info = iter.next(); + bits[info.partitionIndex] ^= info.mask; + } + } + } + + public void set(int index) { + int pos = longPosition(index); + enlarge(pos); + bits[pos] |= bitPosition(index); + } + + public void set(int start, int end) { + MaskInfoIterator iter = new MaskInfoIterator(start, end); + enlarge(iter.getLastPartition()); + while (iter.hasNext()) { + MaskInfo info = iter.next(); + bits[info.partitionIndex] |= info.mask; + } + } + + public void clear(int index) { + int pos = longPosition(index); + if (pos < bits.length) { + bits[pos] &= (MASK ^ bitPosition(index)); + } + } + + public void clear(int start, int end) { + MaskInfoIterator iter = new MaskInfoIterator(start, end); + while (iter.hasNext()) { + MaskInfo info = iter.next(); + bits[info.partitionIndex] &= (MASK ^ info.mask); + } + } + + public boolean isEmpty() { + for (int i = 0; i < bits.length; i++) { + if (bits[i] != 0) { + return false; + } + } + return true; + } + + public boolean intersects(BitSet otherBits) { + int max = Math.max(bits.length, otherBits.bits.length); + for (int i = 0; i < max; i++) { + if ((bits[i] & otherBits.bits[i]) != 0) { + return true; + } + } + return false; + } + + public int length() { + return bits.length << BITS_PER_LONG_SHIFT; + } + + public int nextSetBit(int fromIndex) { + return nextBit(fromIndex, false); + } + + private int nextBit(int fromIndex, boolean bitClear) { + int pos = longPosition(fromIndex); + if (pos >= bits.length) { + return -1; + } + int current = fromIndex; + do { + long currValue = bits[pos]; + if (currValue == 0) { + pos++; + current = pos << BITS_PER_LONG_SHIFT; + } else { + do { + long bitPos = bitPosition(current); + if (((currValue & bitPos) != 0) ^ bitClear) { + return current; + } else { + current++; + } + } while (current % BITS_PER_LONG != 0); + } + pos++; + } while (pos < bits.length); + + return -1; + } + + public int nextClearBit(int fromIndex) { + return nextBit(fromIndex, true); + } + + public int cardinality() { + int numSetBits = 0; + for (int i = nextSetBit(0); i >= 0; i = nextSetBit(i+1)) { + ++numSetBits; + } + + return numSetBits; + } + + private static class MaskInfoIterator implements Iterator { + private int basePartition; + private int numPartitionsToTraverse; + private int currentPartitionOffset; + private int toIndex; + private int currentFirstIndex; + + public MaskInfoIterator(int fromIndex, int toIndex) { + this.basePartition = longPosition(fromIndex); + this.numPartitionsToTraverse = longPosition(toIndex - 1) - basePartition + 1; + this.currentPartitionOffset = 0; + this.toIndex = toIndex; + this.currentFirstIndex = fromIndex; + } + + public MaskInfo next() { + int currentToIndex = Math.min(toIndex, (basePartition + currentPartitionOffset + 1) * BITS_PER_LONG); + long mask = getTrueMask(currentFirstIndex, currentToIndex); + MaskInfo info = new MaskInfo(mask, basePartition + currentPartitionOffset); + currentFirstIndex = currentToIndex; + currentPartitionOffset++; + return info; + } + + public boolean hasNext() { + return currentPartitionOffset < numPartitionsToTraverse; + } + + public void remove() { + throw new UnsupportedOperationException(); + } + + public int getLastPartition() { + return basePartition + numPartitionsToTraverse - 1; + } + } + + private static class MaskInfo { + public long mask; + public int partitionIndex; + + public MaskInfo(long mask, int partitionIndex) { + this.mask = mask; + this.partitionIndex = partitionIndex; + } + } +} diff --git a/sgx-jvm/avian/classpath/java/util/Calendar.java b/sgx-jvm/avian/classpath/java/util/Calendar.java new file mode 100644 index 0000000000..448f0f1bef --- /dev/null +++ b/sgx-jvm/avian/classpath/java/util/Calendar.java @@ -0,0 +1,188 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.util; + +public abstract class Calendar { + public static final int AM = 0; + public static final int AM_PM = 9; + public static final int DAY_OF_MONTH = 5; + public static final int DAY_OF_WEEK = 7; + public static final int HOUR = 10; + public static final int HOUR_OF_DAY = 11; + public static final int MINUTE = 12; + public static final int MONTH = 2; + public static final int PM = 1; + public static final int SECOND = 13; + public static final int YEAR = 1; + + public static final int FIELD_COUNT = 17; + + protected long time; + protected boolean isTimeSet; + protected int[] fields = new int[FIELD_COUNT]; + protected boolean areFieldsSet; + protected boolean[] isSet = new boolean[FIELD_COUNT]; + + protected Calendar() { } + + public static Calendar getInstance() { + return new MyCalendar(System.currentTimeMillis()); + } + + public int get(int field) { + return fields[field]; + } + + public void set(int field, int value) { + fields[field] = value; + } + + public void set(int year, int month, int date) { + set(YEAR, year); + set(MONTH, month); + set(DAY_OF_MONTH, date); + } + + public void setTime(Date date) { + time = date.getTime(); + } + + public Date getTime() { + return new Date(time); + } + + public abstract void roll(int field, boolean up); + public abstract void add(int field, int amount); + + public void roll(int field, int amount) { + boolean up = amount >= 0; + if (! up) { + amount = - amount; + } + for (int i = 0; i < amount; ++i) { + roll(field, up); + } + } + + public abstract int getMinimum(int field); + + public abstract int getMaximum(int field); + + public abstract int getActualMinimum(int field); + + public abstract int getActualMaximum(int field); + + private static class MyCalendar extends Calendar { + private static final long MILLIS_PER_DAY = 86400000; + private static final int MILLIS_PER_HOUR = 3600000; + private static final int MILLIS_PER_MINUTE = 60000; + private static final int MILLIS_PER_SECOND = 1000; + + private static final int EPOCH_YEAR = 1970; + private static final int EPOCH_LEAP_YEAR = 1968; + private static final int DAYS_TO_EPOCH = 731; + + private static final int[][] DAYS_IN_MONTH = new int[][] { + { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }, + { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 } + }; + + public MyCalendar(long time) { + this.time = time; + this.isTimeSet = true; + parseIntoFields(time); + } + + public void setTime(Date date) { + super.setTime(date); + parseIntoFields(this.time); + } + + public Date getTime() { + long days = fields[DAY_OF_MONTH] - 1; + long years = fields[YEAR] - EPOCH_LEAP_YEAR; + days += years * 365 + years / 4 + 1 - DAYS_TO_EPOCH; + for (int month = 0; month < fields[MONTH]; month++) { + days += DAYS_IN_MONTH[0][month]; + } + if (fields[MONTH] < 2 && isLeapYear(fields[YEAR])) { + days--; + } + long time = MILLIS_PER_DAY * days + + MILLIS_PER_HOUR * fields[HOUR_OF_DAY] + + MILLIS_PER_MINUTE * fields[MINUTE] + + MILLIS_PER_SECOND * fields[SECOND]; + return new Date(time); + } + + private static boolean isLeapYear(int year) { + return (year%4 == 0) && (year%100 != 0) || (year%400 == 0); + } + + private void parseIntoFields(long timeInMillis) { + long days = timeInMillis / MILLIS_PER_DAY; + /* convert days since Jan 1, 1970 to days since Jan 1, 1968 */ + days += DAYS_TO_EPOCH; + long years = 4 * days / 1461; /* days/365.25 = 4*days/(4*365.25) */ + int year = (int)(EPOCH_LEAP_YEAR + years); + days -= 365 * years + years / 4; + if (!isLeapYear(year)) days--; + + int month=0; + int leapIndex = isLeapYear(year) ? 1 : 0; + while (days >= DAYS_IN_MONTH[leapIndex][month]) { + days -= DAYS_IN_MONTH[leapIndex][month++]; + } + days++; + + int remainder = (int)(timeInMillis % MILLIS_PER_DAY); + int hour = remainder / MILLIS_PER_HOUR; + remainder = remainder % MILLIS_PER_HOUR; + int minute = remainder / MILLIS_PER_MINUTE; + remainder = remainder % MILLIS_PER_MINUTE; + int second = remainder / MILLIS_PER_SECOND; + fields[YEAR] = year; + fields[MONTH] = month; + fields[DAY_OF_MONTH] = (int)days; + fields[HOUR_OF_DAY] = hour; + fields[MINUTE] = minute; + fields[SECOND] = second; + } + + public void roll(int field, boolean up) { + // todo + } + + public void add(int fild, int amount) { + // todo + } + + public int getMinimum(int field) { + // todo + return 0; + } + + public int getMaximum(int field) { + // todo + return 0; + } + + public int getActualMinimum(int field) { + // todo + return 0; + } + + public int getActualMaximum(int field) { + // todo + return 0; + } + } +} diff --git a/sgx-jvm/avian/classpath/java/util/Collection.java b/sgx-jvm/avian/classpath/java/util/Collection.java new file mode 100644 index 0000000000..9f0b740961 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/util/Collection.java @@ -0,0 +1,35 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.util; + +public interface Collection extends Iterable { + public int size(); + + public boolean isEmpty(); + + public boolean contains(Object element); + + public boolean containsAll(Collection c); + + public boolean add(T element); + + public boolean addAll(Collection collection); + + public boolean remove(Object element); + + public boolean removeAll(Collection c); + + public Object[] toArray(); + + public S[] toArray(S[] array); + + public void clear(); +} diff --git a/sgx-jvm/avian/classpath/java/util/Collections.java b/sgx-jvm/avian/classpath/java/util/Collections.java new file mode 100644 index 0000000000..9a6f998503 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/util/Collections.java @@ -0,0 +1,816 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.util; + +import avian.Data; + +public class Collections { + + private Collections() { } + + public static void shuffle(List list, Random random) { + Object[] array = Data.toArray(list, new Object[list.size()]); + for (int i = 0; i < array.length; ++i) { + int j = random.nextInt(array.length); + Object tmp = array[i]; + array[i] = array[j]; + array[j] = tmp; + } + + list.clear(); + for (int i = 0; i < array.length; ++i) { + list.add(array[i]); + } + } + + public static void shuffle(List list) { + shuffle(list, new Random()); + } + + public static void sort(List list) { + sort(list, new Comparator() { + public int compare(Object a, Object b) { + return ((Comparable) a).compareTo(b); + } + }); + } + + private final static int SORT_SIZE_THRESHOLD = 16; + + public static void sort(List list, Comparator comparator) { + int size = list.size(); + introSort(list, comparator, 0, size, size); + insertionSort(list, comparator); + } + + private static void introSort(List list, + Comparator comparator, int begin, int end, int limit) + { + while (end - begin > SORT_SIZE_THRESHOLD) { + if (limit == 0) { + heapSort(list, comparator, begin, end); + return; + } + limit >>= 1; + + // median of three + T a = list.get(begin); + T b = list.get(begin + (end - begin) / 2 + 1); + T c = list.get(end - 1); + T median; + if (comparator.compare(a, b) < 0) { + median = comparator.compare(b, c) < 0 ? + b : (comparator.compare(a, c) < 0 ? c : a); + } else { + median = comparator.compare(b, c) > 0 ? + b : (comparator.compare(a, c) > 0 ? c : a); + } + + // partition + int pivot, i = begin, j = end; + for (;;) { + while (comparator.compare(list.get(i), median) < 0) { + ++i; + } + --j; + while (comparator.compare(median, list.get(j)) < 0) { + --j; + } + if (i >= j) { + pivot = i; + break; + } + T swap = list.get(i); + list.set(i, list.get(j)); + list.set(j, swap); + ++i; + } + + introSort(list, comparator, pivot, end, limit); + end = pivot; + } + } + + private static void heapSort(List list, Comparator comparator, + int begin, int end) + { + int count = end - begin; + for (int i = count / 2 - 1; i >= 0; --i) { + siftDown(list, comparator, i, count, begin); + } + for (int i = count - 1; i > 0; --i) { + // swap begin and begin + i + T swap = list.get(begin + i); + list.set(begin + i, list.get(begin)); + list.set(begin, swap); + + siftDown(list, comparator, 0, i, begin); + } + } + + private static void siftDown(List list, Comparator comparator, + int i, int count, int offset) + { + T value = list.get(offset + i); + while (i < count / 2) { + int child = 2 * i + 1; + if (child + 1 < count && + comparator.compare(list.get(child), list.get(child + 1)) < 0) { + ++child; + } + if (comparator.compare(value, list.get(child)) >= 0) { + break; + } + list.set(offset + i, list.get(offset + child)); + i = child; + } + list.set(offset + i, value); + } + + private static void insertionSort(List list, + Comparator comparator) + { + int size = list.size(); + for (int j = 1; j < size; ++j) { + T t = list.get(j); + int i = j - 1; + while (i >= 0 && comparator.compare(list.get(i), t) > 0) { + list.set(i + 1, list.get(i)); + --i; + } + list.set(i + 1, t); + } + } + + public static int binarySearch(List list, T needle) { + int left = -1, right = list.size(); + while (left + 1 < right) { + int middle = (left + right) >> 1; + int result = ((Comparable)needle).compareTo(list.get(middle)); + if (result < 0) { + right = middle; + } else if (result > 0) { + left = middle; + } else { + return middle; + } + } + return -1 - right; + } + + public static void reverse(List list) { + int ascending = 0, descending = list.size() - 1; + while (ascending < descending) { + T tmp = list.get(ascending); + list.set(ascending++, list.get(descending)); + list.set(descending--, tmp); + } + } + + public static final List EMPTY_LIST + = new UnmodifiableList(new ArrayList(0)); + + public static final List emptyList() { + return EMPTY_LIST; + } + + public static final Map emptyMap() { + return (Map) new UnmodifiableMap( + new HashMap(0)); + } + + public static final Set emptySet() { + return (Set) new UnmodifiableSet( + new HashSet(0)); + } + + public static Enumeration enumeration(Collection c) { + return new IteratorEnumeration (c.iterator()); + } + + public static Comparator reverseOrder(Comparator cmp) { + return new ReverseComparator(cmp); + } + + static class IteratorEnumeration implements Enumeration { + private final Iterator it; + + public IteratorEnumeration(Iterator it) { + this.it = it; + } + + public T nextElement() { + return it.next(); + } + + public boolean hasMoreElements() { + return it.hasNext(); + } + } + + static class SynchronizedCollection implements Collection { + protected final Object lock; + protected final Collection collection; + + public SynchronizedCollection(Object lock, Collection collection) { + this.lock = lock; + this.collection = collection; + } + + public int size() { + synchronized (lock) { return collection.size(); } + } + + public boolean isEmpty() { + return size() == 0; + } + + public boolean contains(Object e) { + synchronized (lock) { return collection.contains(e); } + } + + public boolean add(T e) { + synchronized (lock) { return collection.add(e); } + } + + public boolean addAll(Collection collection) { + synchronized (lock) { return this.collection.addAll(collection); } + } + + public boolean remove(Object e) { + synchronized (lock) { return collection.remove((T)e); } + } + + public Object[] toArray() { + return toArray(new Object[size()]); + } + + public T[] toArray(T[] array) { + synchronized (lock) { return collection.toArray(array); } + } + + public void clear() { + synchronized (lock) { collection.clear(); } + } + + public Iterator iterator() { + return new SynchronizedIterator(lock, collection.iterator()); + } + + public boolean containsAll(Collection c) { + synchronized (lock) { return collection.containsAll(c); } + } + + public boolean removeAll(Collection c) { + synchronized (lock) { return collection.removeAll(c); } + } + } + + static class SynchronizedMap implements Map { + protected final Object lock; + protected final Map map; + + SynchronizedMap(Map map) { + this.map = map; + this.lock = this; + } + + SynchronizedMap(Object lock, Map map) { + this.lock = lock; + this.map = map; + } + + public void clear() { + synchronized (lock) { map.clear(); } + } + public boolean containsKey(Object key) { + synchronized (lock) { return map.containsKey(key); } + } + public boolean containsValue(Object value) { + synchronized (lock) { return map.containsValue(value); } + } + public Set> entrySet() { + synchronized (lock) { return new SynchronizedSet>(lock, map.entrySet()); } + } + public V get(Object key) { + synchronized (lock) { return map.get(key); } + } + public boolean isEmpty() { + synchronized (lock) { return map.isEmpty(); } + } + public Set keySet() { + synchronized (lock) { return new SynchronizedSet(lock, map.keySet()); } + } + public V put(K key, V value) { + synchronized (lock) { return map.put(key, value); } + } + public void putAll(Map elts) { + synchronized (lock) { map.putAll(elts); } + } + public V remove(Object key) { + synchronized (lock) { return map.remove(key); } + } + public int size() { + synchronized (lock) { return map.size(); } + } + public Collection values() { + synchronized (lock) { return new SynchronizedCollection(lock, map.values()); } + } + } + + public static Map synchronizedMap(Map map) { + return new SynchronizedMap (map); + } + + static class SynchronizedSet + extends SynchronizedCollection + implements Set + { + public SynchronizedSet(Object lock, Set set) { + super(lock, set); + } + } + + public static Set synchronizedSet(Set set) { + return new SynchronizedSet (set, set); + } + + static class SynchronizedList + extends SynchronizedCollection + implements List + { + private final List list; + + public SynchronizedList(List list) { + super(list, list); + + this.list = list; + } + + @Override + public T get(int index) { + synchronized (lock) { + return list.get(index); + } + } + + @Override + public T set(int index, T value) { + synchronized (lock) { + return list.set(index, value); + } + } + + @Override + public T remove(int index) { + synchronized (lock) { + return list.remove(index); + } + } + + @Override + public void add(int index, T element) { + synchronized (lock) { + list.add(index, element); + } + } + + @Override + public boolean addAll(int startIndex, Collection c) { + synchronized (lock) { + return list.addAll(startIndex, c); + } + } + + @Override + public int indexOf(Object value) { + synchronized (lock) { + return list.indexOf(value); + } + } + + @Override + public int lastIndexOf(Object value) { + synchronized (lock) { + return list.lastIndexOf(value); + } + } + + @Override + public ListIterator listIterator(int index) { + // as described in the javadocs, user should be synchronized on list before calling + return list.listIterator(index); + } + + @Override + public ListIterator listIterator() { + // as described in the javadocs, user should be synchronized on list before calling + return list.listIterator(); + } + } + + static class RandomAccessSynchronizedList + extends SynchronizedList + implements RandomAccess + { + public RandomAccessSynchronizedList(List list) { + super(list); + } + } + + public static List synchronizedList(List list) { + List result; + if (list instanceof RandomAccess) { + result = new RandomAccessSynchronizedList(list); + } else { + result = new SynchronizedList(list); + } + + return result; + } + + static class SynchronizedIterator implements Iterator { + private final Object lock; + private final Iterator it; + + public SynchronizedIterator(Object lock, Iterator it) { + this.lock = lock; + this.it = it; + } + + public T next() { + synchronized (lock) { return it.next(); } + } + + public boolean hasNext() { + synchronized (lock) { return it.hasNext(); } + } + + public void remove() { + synchronized (lock) { it.remove(); } + } + } + + static class ArrayListIterator implements ListIterator { + private final List list; + private int toRemove = -1; + private int index; + + public ArrayListIterator(List list) { + this(list, 0); + } + + public ArrayListIterator(List list, int index) { + this.list = list; + this.index = index - 1; + } + + public boolean hasPrevious() { + return index >= 0; + } + + public T previous() { + if (hasPrevious()) { + toRemove = index; + return list.get(index--); + } else { + throw new NoSuchElementException(); + } + } + + public T next() { + if (hasNext()) { + toRemove = ++index; + return list.get(index); + } else { + throw new NoSuchElementException(); + } + } + + public boolean hasNext() { + return index + 1 < list.size(); + } + + public void remove() { + if (toRemove != -1) { + list.remove(toRemove); + index = toRemove - 1; + toRemove = -1; + } else { + throw new IllegalStateException(); + } + } + } + + public static List unmodifiableList(List list) { + return new UnmodifiableList(list); + } + + static class UnmodifiableList implements List { + + private List inner; + + UnmodifiableList(List l) { + this.inner = l; + } + + public T get(int index) { + return inner.get(index); + } + + public T set(int index, T value) { + throw new UnsupportedOperationException(); + } + + public T remove(int index) { + throw new UnsupportedOperationException(); + } + + public boolean remove(Object o) { + throw new UnsupportedOperationException(); + } + + public boolean add(T element) { + throw new UnsupportedOperationException(); + } + + public void add(int index, T element) { + throw new UnsupportedOperationException(); + } + + public Iterator iterator() { + return new UnmodifiableIterator(inner.iterator()); + } + + public int indexOf(Object value) { + return inner.indexOf(value); + } + + public int lastIndexOf(Object value) { + return inner.lastIndexOf(value); + } + + public boolean isEmpty() { + return inner.isEmpty(); + } + + public ListIterator listIterator(int index) { + return new UnmodifiableListIterator(inner.listIterator(index)); + } + + public ListIterator listIterator() { + return new UnmodifiableListIterator(inner.listIterator()); + } + + public int size() { + return inner.size(); + } + + public boolean contains(Object element) { + return inner.contains(element); + } + + public boolean addAll(Collection collection) { + throw new UnsupportedOperationException(); + } + + public Object[] toArray() { + return inner.toArray(); + } + + public S[] toArray(S[] array) { + return inner.toArray(array); + } + + public void clear() { + throw new UnsupportedOperationException(); + } + + public boolean removeAll(Collection c) { + throw new UnsupportedOperationException(); + } + + public boolean addAll(int startIndex, Collection c) { + throw new UnsupportedOperationException(); + } + + public boolean containsAll(Collection c) { + return inner.containsAll(c); + } + } + + public static Map unmodifiableMap(Map m) { + return new UnmodifiableMap(m); + } + + static class UnmodifiableMap implements Map { + private Map inner; + + UnmodifiableMap(Map m) { + this.inner = m; + } + + public void clear() { + throw new UnsupportedOperationException(); + } + + public boolean containsKey(Object key) { + return inner.containsKey(key); + } + + public boolean containsValue(Object value) { + return inner.containsValue(value); + } + + public Set> entrySet() { + return unmodifiableSet(inner.entrySet()); + } + + public V get(Object key) { + return inner.get(key); + } + + public boolean isEmpty() { + return inner.isEmpty(); + } + + public Set keySet() { + return unmodifiableSet(inner.keySet()); + } + + public V put(K key, V value) { + throw new UnsupportedOperationException(); + } + + public void putAll(Map t) { + throw new UnsupportedOperationException(); + } + + public V remove(Object key) { + throw new UnsupportedOperationException(); + } + + public int size() { + return inner.size(); + } + + public Collection values() { + return unmodifiableCollection(inner.values()); + } + } + + static class UnmodifiableIterator implements Iterator { + private final Iterator inner; + + UnmodifiableIterator(Iterator inner) { + this.inner = inner; + } + + @Override + public T next() { + return inner.next(); + } + + @Override + public boolean hasNext() { + return inner.hasNext(); + } + + @Override + public void remove() { + throw new UnsupportedOperationException(); + } + } + + + static class UnmodifiableListIterator extends UnmodifiableIterator + implements ListIterator { + private final ListIterator innerListIterator; + + UnmodifiableListIterator(ListIterator listIterator) { + super(listIterator); + + this.innerListIterator = listIterator; + } + + @Override + public boolean hasPrevious() { + return innerListIterator.hasPrevious(); + } + + @Override + public T previous() { + return innerListIterator.previous(); + } + } + + static class UnmodifiableCollection implements Collection { + private final Collection inner; + + UnmodifiableCollection(Collection inner) { + this.inner = inner; + } + + @Override + public Iterator iterator() { + return new UnmodifiableIterator(inner.iterator()); + } + + @Override + public int size() { + return inner.size(); + } + + @Override + public boolean isEmpty() { + return inner.isEmpty(); + } + + @Override + public boolean contains(Object element) { + return inner.contains(element); + } + + @Override + public boolean containsAll(Collection c) { + return inner.containsAll(c); + } + + @Override + public boolean add(T element) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean addAll(Collection collection) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean remove(Object element) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean removeAll(Collection c) { + throw new UnsupportedOperationException(); + } + + @Override + public Object[] toArray() { + return inner.toArray(); + } + + @Override + public S[] toArray(S[] array) { + return inner.toArray(array); + } + + @Override + public void clear() { + throw new UnsupportedOperationException(); + } + } + + public static UnmodifiableCollection unmodifiableCollection(Collection collection) { + return new UnmodifiableCollection(collection); + } + + static class UnmodifiableSet extends UnmodifiableCollection + implements Set { + UnmodifiableSet(Set inner) { + super(inner); + } + } + + public static Set unmodifiableSet(Set hs) { + return new UnmodifiableSet(hs); + } + + private static final class ReverseComparator implements Comparator { + + Comparator cmp; + + public ReverseComparator(Comparator cmp) { + this.cmp = cmp; + } + + public int compare(T o1, T o2) { + return - cmp.compare(o1, o2); + } + } + + public static List singletonList(T o) { + ArrayList list = new ArrayList(1); + list.add(o); + return new UnmodifiableList(list); + } +} diff --git a/sgx-jvm/avian/classpath/java/util/Comparator.java b/sgx-jvm/avian/classpath/java/util/Comparator.java new file mode 100644 index 0000000000..6d861ea393 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/util/Comparator.java @@ -0,0 +1,15 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.util; + +public interface Comparator { + public int compare(T o1, T o2); +} diff --git a/sgx-jvm/avian/classpath/java/util/ConcurrentModificationException.java b/sgx-jvm/avian/classpath/java/util/ConcurrentModificationException.java new file mode 100644 index 0000000000..f828ac169e --- /dev/null +++ b/sgx-jvm/avian/classpath/java/util/ConcurrentModificationException.java @@ -0,0 +1,47 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.util; + +/** + * @author zsombor + * + */ +public class ConcurrentModificationException extends RuntimeException { + + /** + * @param message + * @param cause + */ + public ConcurrentModificationException(String message, Throwable cause) { + super(message, cause); + } + + /** + * @param message + */ + public ConcurrentModificationException(String message) { + super(message); + } + + /** + * @param cause + */ + public ConcurrentModificationException(Throwable cause) { + super(cause); + } + + /** + * + */ + public ConcurrentModificationException() { + } + +} diff --git a/sgx-jvm/avian/classpath/java/util/Date.java b/sgx-jvm/avian/classpath/java/util/Date.java new file mode 100644 index 0000000000..2681c84bf5 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/util/Date.java @@ -0,0 +1,33 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.util; + +public class Date { + public final long when; + + public Date() { + when = System.currentTimeMillis(); + } + + public Date(long when) { + this.when = when; + } + + public long getTime() { + return when; + } + + public String toString() { + return toString(when); + } + + private static native String toString(long when); +} diff --git a/sgx-jvm/avian/classpath/java/util/Deque.java b/sgx-jvm/avian/classpath/java/util/Deque.java new file mode 100644 index 0000000000..8586090f42 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/util/Deque.java @@ -0,0 +1,31 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.util; + +public interface Deque extends Queue { + public boolean offerFirst(T e); + public void push(T e); + public void addFirst(T element); + public boolean offerLast(T e); + public void addLast(T element); + public T peekFirst(); + public T getFirst(); + public T peekLast(); + public T getLast(); + public T pollFirst(); + public T removeFirst(); + public T pop(); + public T pollLast(); + public T removeLast(); + public Iterator descendingIterator(); + public boolean removeLastOccurrence(Object o); + public boolean removeFirstOccurrence(Object o); +} diff --git a/sgx-jvm/avian/classpath/java/util/EmptyStackException.java b/sgx-jvm/avian/classpath/java/util/EmptyStackException.java new file mode 100644 index 0000000000..2e5a406987 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/util/EmptyStackException.java @@ -0,0 +1,13 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.util; + +public class EmptyStackException extends RuntimeException {} diff --git a/sgx-jvm/avian/classpath/java/util/EnumSet.java b/sgx-jvm/avian/classpath/java/util/EnumSet.java new file mode 100644 index 0000000000..7b40b56405 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/util/EnumSet.java @@ -0,0 +1,155 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.util; + +public class EnumSet> extends AbstractSet { + + private BitSet bitset; + private Class elementType; + + private EnumSet(int size, Class type) { + bitset = new BitSet(size); + elementType = type; + } + + @Override + public boolean add(T element) { + int index = element.ordinal(); + boolean contains = bitset.get(index); + if (!contains) { + bitset.set(index); + } + + return !contains; + } + + @Override + public boolean remove(Object toRemove) { + T element = tryToCast(toRemove); + + int index = element.ordinal(); + boolean contains = bitset.get(index); + if (contains) { + bitset.clear(index); + } + + return contains; + } + + @Override + public boolean contains(Object toCheck) { + T element = tryToCast(toCheck); + int index = element.ordinal(); + return bitset.get(index); + } + + @Override + public int size() { + return bitset.cardinality(); + } + + @Override + public Iterator iterator() { + return new EnumSetIterator(); + } + + public static >EnumSet allOf(Class elementType) { + EnumSet enumSet = createEmptyEnumSet(elementType); + enumSet.bitset.set(0, elementType.getEnumConstants().length); + + return enumSet; + } + + public static >EnumSet noneOf(Class elementType) { + return createEmptyEnumSet(elementType); + } + + public static >EnumSet of(T first, T ... rest) { + EnumSet enumSet = createEmptyEnumSet(first.getDeclaringClass()); + enumSet.add(first); + addAllElementsToSet(Arrays.asList(rest), enumSet); + + return enumSet; + } + + public static >EnumSet complementOf(EnumSet s) { + EnumSet enumSet = copyOf(s); + enumSet.bitset.flip(0, s.elementType.getEnumConstants().length); + + return enumSet; + } + + public static >EnumSet copyOf(EnumSet s) { + EnumSet enumSet = createEmptyEnumSet(s.elementType); + enumSet.bitset.or(s.bitset); + + return enumSet; + } + + private static >EnumSet createEmptyEnumSet(Class elementType) { + T[] constants = elementType.getEnumConstants(); + EnumSet enumSet = new EnumSet(constants.length, elementType); + + return enumSet; + } + + private static > void addAllElementsToSet(Iterable elements, EnumSet enumSet) { + for (T element : elements) { + enumSet.add(element); + } + } + + @SuppressWarnings("unchecked") + private T tryToCast(Object object) throws ClassCastException { + //We want the class cast exception if we can't convert. + return (T) object; + } + + private class EnumSetIterator implements Iterator { + private int currentIndex = 0; + private boolean removeAllowed = false; + + public T next() { + if (!hasNext()) { + throw new NoSuchElementException("EnumSet has no more elements"); + } + + int indexOfNextValue = nextIndex(); + T element = elementType.getEnumConstants()[indexOfNextValue]; + currentIndex = indexOfNextValue + 1; + removeAllowed = true; + + return element; + } + + public boolean hasNext() { + int indexOfNextValue = nextIndex(); + if (indexOfNextValue >= 0) { + return true; + } else { + return false; + } + } + + public void remove() { + if (!removeAllowed) { + throw new IllegalStateException("Cannot remove from this iterator in this state"); + } + + bitset.clear(currentIndex - 1); + removeAllowed = false; + } + + private int nextIndex() { + return bitset.nextSetBit(currentIndex); + } + } +} diff --git a/sgx-jvm/avian/classpath/java/util/Enumeration.java b/sgx-jvm/avian/classpath/java/util/Enumeration.java new file mode 100644 index 0000000000..70e50b6d59 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/util/Enumeration.java @@ -0,0 +1,17 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.util; + +public interface Enumeration { + public T nextElement(); + + public boolean hasMoreElements(); +} diff --git a/sgx-jvm/avian/classpath/java/util/EventListener.java b/sgx-jvm/avian/classpath/java/util/EventListener.java new file mode 100644 index 0000000000..3b27d4a709 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/util/EventListener.java @@ -0,0 +1,15 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.util; + +public interface EventListener { + +} diff --git a/sgx-jvm/avian/classpath/java/util/EventObject.java b/sgx-jvm/avian/classpath/java/util/EventObject.java new file mode 100644 index 0000000000..25be1f5df2 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/util/EventObject.java @@ -0,0 +1,23 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.util; + +public class EventObject { + protected Object source; + + public EventObject(Object source) { + this.source = source; + } + + public Object getSource() { + return source; + } +} diff --git a/sgx-jvm/avian/classpath/java/util/Formatter.java b/sgx-jvm/avian/classpath/java/util/Formatter.java new file mode 100644 index 0000000000..12d5919e82 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/util/Formatter.java @@ -0,0 +1,158 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.util; + +import java.io.Closeable; +import java.io.File; +import java.io.FileWriter; +import java.io.Flushable; +import java.io.IOException; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.io.PrintStream; +import java.io.Writer; + +import avian.FormatString; + +public class Formatter implements Closeable, Flushable, AutoCloseable { + + private final Appendable _out; + + private final Locale _locale; + + private IOException lastException; + + private boolean _closed; + + private void ensureNotClosed() { + if (this._closed) { + throw new IllegalStateException(); + } + } + + public Formatter() { + this((Appendable) null, (Locale) null); + } + + public Formatter(final Appendable a) { + this(a, null); + } + + public Formatter(final Appendable a, final Locale l) { + if (a == null) { + this._out = new StringBuilder(); + } else { + this._out = a; + } + if (l == null) { + this._locale = Locale.getDefault(); + } else { + this._locale = l; + } + } + + public Formatter(File file) throws IOException { + this(file, null); + } + + public Formatter(File file, Locale l) throws IOException { + this(new FileWriter(file), l); + } + + public Formatter(Locale l) { + this((Appendable) null, l); + } + + public Formatter(OutputStream os) { + this(os, null); + } + + public Formatter(OutputStream os, Locale l) { + this(new OutputStreamWriter(os), l); + } + + public Formatter(PrintStream ps) { + this(new OutputStreamWriter(ps)); + } + + public Formatter(String fileName) throws IOException { + this(fileName, (Locale) null); + } + + public Formatter(String fileName, Locale l) throws IOException { + this(new File(fileName), l); + } + + public void close() { + if (this._closed) { + return; + } + final Appendable out = out(); + if (out instanceof Closeable) { + final Closeable closeable = (Closeable) out; + try { + closeable.close(); + } catch (IOException e) { + throw new RuntimeException("An error occurred while closing.", e); + } + this._closed = true; + } + } + + public void flush() { + ensureNotClosed(); + final Appendable out = out(); + if (out instanceof Flushable) { + final Flushable flushable = (Flushable) out; + try { + flushable.flush(); + } catch (IOException e) { + throw new RuntimeException("An error occurred while flushing.", e); + } + } + } + + public Formatter format(Locale l, final String format, final Object...args) { + ensureNotClosed(); + try { + final FormatString formatString = FormatString.compile(format); + this._out.append(formatString.format(args)); + } catch (IOException e) { + this.lastException = e; + } + return this; + } + + public Formatter format(String format, Object... args) { + ensureNotClosed(); + return this.format(null, format, args); + } + + public IOException ioException() { + return lastException; + } + + public Locale locale() { + ensureNotClosed(); + return this._locale; + } + + public Appendable out() { + ensureNotClosed(); + return this._out; + } + + public String toString() { + ensureNotClosed(); + return this._out.toString(); + } + +} diff --git a/sgx-jvm/avian/classpath/java/util/HashMap.java b/sgx-jvm/avian/classpath/java/util/HashMap.java new file mode 100644 index 0000000000..c86f1dde4a --- /dev/null +++ b/sgx-jvm/avian/classpath/java/util/HashMap.java @@ -0,0 +1,385 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.util; + +import avian.Data; + +public class HashMap implements Map { + private static final int MinimumCapacity = 16; + + private int size; + private Cell[] array; + private final Helper helper; + + public HashMap(int capacity, Helper helper) { + if (capacity > 0) { + array = new Cell[Data.nextPowerOfTwo(capacity)]; + } + this.helper = helper; + } + + public HashMap(int capacity) { + this(capacity, new MyHelper()); + } + + public HashMap() { + this(0); + } + + public HashMap(Map map) { + this(map.size()); + for (Map.Entry entry : map.entrySet()) { + put(entry.getKey(), entry.getValue()); + } + } + + public String toString() { + return avian.Data.toString(this); + } + + public boolean isEmpty() { + return size() == 0; + } + + public int size() { + return size; + } + + private void grow() { + if (array == null || size >= array.length * 2) { + resize(array == null ? MinimumCapacity : array.length * 2); + } + } + + private void shrink() { + if (array.length / 2 >= MinimumCapacity && size <= array.length / 3) { + resize(array.length / 2); + } + } + + private void resize(int capacity) { + Cell[] newArray = null; + if (capacity != 0) { + capacity = Data.nextPowerOfTwo(capacity); + if (array != null && array.length == capacity) { + return; + } + + newArray = new Cell[capacity]; + if (array != null) { + for (int i = 0; i < array.length; ++i) { + Cell next; + for (Cell c = array[i]; c != null; c = next) { + next = c.next(); + int index = c.hashCode() & (capacity - 1); + c.setNext(newArray[index]); + newArray[index] = c; + } + } + } + } + array = newArray; + } + + protected Cell find(Object key) { + if (array != null) { + int index = helper.hash(key) & (array.length - 1); + for (Cell c = array[index]; c != null; c = c.next()) { + if (helper.equal(key, c.getKey())) { + return c; + } + } + } + + return null; + } + + private void insert(Cell cell) { + ++ size; + + grow(); + + int index = cell.hashCode() & (array.length - 1); + cell.setNext(array[index]); + array[index] = cell; + } + + public void remove(Cell cell) { + int index = cell.hashCode() & (array.length - 1); + Cell p = null; + for (Cell c = array[index]; c != null; c = c.next()) { + if (c == cell) { + if (p == null) { + array[index] = c.next(); + } else { + p.setNext(c.next()); + } + -- size; + break; + } + } + + shrink(); + } + + private Cell putCell(K key, V value) { + Cell c = find(key); + if (c == null) { + insert(helper.make(key, value, null)); + } else { + c.setValue(value); + } + return c; + } + + public boolean containsKey(Object key) { + return find(key) != null; + } + + public boolean containsValue(Object value) { + if (array != null) { + for (int i = 0; i < array.length; ++i) { + for (Cell c = array[i]; c != null; c = c.next()) { + if (helper.equal(value, c.getValue())) { + return true; + } + } + } + } + + return false; + } + + public V get(Object key) { + Cell c = find(key); + return (c == null ? null : c.getValue()); + } + + public Cell removeCell(Object key) { + Cell old = null; + if (array != null) { + int index = helper.hash(key) & (array.length - 1); + Cell p = null; + for (Cell c = array[index]; c != null; c = c.next()) { + if (helper.equal(key, c.getKey())) { + old = c; + if (p == null) { + array[index] = c.next(); + } else { + p.setNext(c.next()); + } + -- size; + break; + } + p = c; + } + + shrink(); + } + return old; + } + + public V put(K key, V value) { + Cell c = find(key); + if (c == null) { + insert(helper.make(key, value, null)); + return null; + } else { + V old = c.getValue(); + c.setValue(value); + return old; + } + } + + public void putAll(Map elts) { + for (Map.Entry entry : elts.entrySet()) { + put(entry.getKey(), entry.getValue()); + } + } + + public V remove(Object key) { + Cell c = removeCell((K)key); + return (c == null ? null : c.getValue()); + } + + public void clear() { + array = null; + size = 0; + } + + public Set> entrySet() { + return new Data.EntrySet(new MyEntryMap()); + } + + public Set keySet() { + return new Data.KeySet(new MyEntryMap()); + } + + public Collection values() { + return new Data.Values(new MyEntryMap()); + } + + Iterator> iterator() { + return new MyIterator(); + } + + private class MyEntryMap implements Data.EntryMap { + public int size() { + return HashMap.this.size(); + } + + public Entry find(Object key) { + return HashMap.this.find(key); + } + + public Entry remove(Object key) { + return removeCell(key); + } + + public void clear() { + HashMap.this.clear(); + } + + public Iterator> iterator() { + return HashMap.this.iterator(); + } + } + + interface Cell extends Entry { + public HashMap.Cell next(); + + public void setNext(HashMap.Cell next); + } + + interface Helper { + public Cell make(K key, V value, Cell next); + + public int hash(K key); + + public boolean equal(K a, K b); + } + + private static class MyCell implements Cell { + public final K key; + public V value; + public Cell next; + public int hashCode; + + public MyCell(K key, V value, Cell next, int hashCode) { + this.key = key; + this.value = value; + this.next = next; + this.hashCode = hashCode; + } + + public K getKey() { + return key; + } + + public V getValue() { + return value; + } + + public V setValue(V value) { + V old = this.value; + this.value = value; + return old; + } + + public HashMap.Cell next() { + return next; + } + + public void setNext(HashMap.Cell next) { + this.next = next; + } + + public int hashCode() { + return hashCode; + } + } + + static class MyHelper implements Helper { + public Cell make(K key, V value, Cell next) { + return new MyCell(key, value, next, hash(key)); + } + + public int hash(K a) { + return (a == null ? 0 : a.hashCode()); + } + + public boolean equal(K a, K b) { + return (a == null && b == null) || (a != null && a.equals(b)); + } + } + + private class MyIterator implements Iterator> { + private int currentIndex = -1; + private int nextIndex = -1; + private Cell previousCell; + private Cell currentCell; + private Cell nextCell; + + public MyIterator() { + hasNext(); + } + + public Entry next() { + if (hasNext()) { + if (currentCell != null) { + if (currentCell.next() != null) { + previousCell = currentCell; + } else { + previousCell = null; + } + } + + currentCell = nextCell; + currentIndex = nextIndex; + + nextCell = nextCell.next(); + + return currentCell; + } else { + throw new NoSuchElementException(); + } + } + + public boolean hasNext() { + if (array != null) { + while (nextCell == null && ++ nextIndex < array.length) { + if (array[nextIndex] != null) { + nextCell = array[nextIndex]; + return true; + } + } + } + return nextCell != null; + } + + public void remove() { + if (currentCell != null) { + if (previousCell == null) { + array[currentIndex] = currentCell.next(); + } else { + previousCell.setNext(currentCell.next()); + if (previousCell.next() == null) { + previousCell = null; + } + } + currentCell = null; + -- size; + } else { + throw new IllegalStateException(); + } + } + } +} diff --git a/sgx-jvm/avian/classpath/java/util/HashSet.java b/sgx-jvm/avian/classpath/java/util/HashSet.java new file mode 100644 index 0000000000..3c70cda172 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/util/HashSet.java @@ -0,0 +1,88 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.util; + +public class HashSet extends AbstractSet implements Set { + private static final Object Value = new Object(); + + private final HashMap map; + + public HashSet(Collection c) { + map = new HashMap(c.size()); + addAll(c); + } + + public HashSet(int capacity) { + map = new HashMap(capacity); + } + + public HashSet() { + this(0); + } + + public int size() { + return map.size(); + } + + public boolean isEmpty() { + return map.isEmpty(); + } + + public boolean contains(Object element) { + return map.containsKey(element); + } + + public boolean add(T element) { + return map.put(element, Value) != Value; + } + + public boolean addAll(Collection collection) { + boolean change = false; + for (T t: collection) if (add(t)) change = true; + return change; + } + + public boolean remove(Object element) { + return map.remove(element) != Value; + } + + public void clear() { + map.clear(); + } + + public Iterator iterator() { + return new MyIterator(map.iterator()); + } + + public String toString() { + return avian.Data.toString(this); + } + + private static class MyIterator implements Iterator { + private final Iterator> it; + + public MyIterator(Iterator> it) { + this.it = it; + } + + public T next() { + return it.next().getKey(); + } + + public boolean hasNext() { + return it.hasNext(); + } + + public void remove() { + it.remove(); + } + } +} diff --git a/sgx-jvm/avian/classpath/java/util/Hashtable.java b/sgx-jvm/avian/classpath/java/util/Hashtable.java new file mode 100644 index 0000000000..4f277a1d18 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/util/Hashtable.java @@ -0,0 +1,91 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.util; + +public class Hashtable implements Map { + private final HashMap map; + + public Hashtable(int capacity) { + map = new HashMap(capacity); + } + + public Hashtable() { + this(0); + } + + public Hashtable(Map m) { + this(m.size()); + for (Entry entry : m.entrySet()) { + put(entry.getKey(), entry.getValue()); + } + } + + public synchronized String toString() { + return map.toString(); + } + + public synchronized boolean isEmpty() { + return map.isEmpty(); + } + + public synchronized int size() { + return map.size(); + } + + public synchronized boolean containsKey(Object key) { + return map.containsKey(key); + } + + public synchronized boolean containsValue(Object value) { + return map.containsValue(value); + } + + public synchronized V get(Object key) { + return map.get(key); + } + + public synchronized V put(K key, V value) { + return map.put(key, value); + } + + public synchronized void putAll(Map elts) { + map.putAll(elts); + } + + public synchronized V remove(Object key) { + return map.remove(key); + } + + public synchronized void clear() { + map.clear(); + } + + public Enumeration keys() { + return new Collections.IteratorEnumeration(keySet().iterator()); + } + + public Enumeration elements() { + return new Collections.IteratorEnumeration(values().iterator()); + } + + public Set> entrySet() { + return new Collections.SynchronizedSet(this, map.entrySet()); + } + + public Set keySet() { + return new Collections.SynchronizedSet(this, map.keySet()); + } + + public Collection values() { + return new Collections.SynchronizedCollection(this, map.values()); + } + +} diff --git a/sgx-jvm/avian/classpath/java/util/IdentityHashMap.java b/sgx-jvm/avian/classpath/java/util/IdentityHashMap.java new file mode 100644 index 0000000000..42fb4a5a6a --- /dev/null +++ b/sgx-jvm/avian/classpath/java/util/IdentityHashMap.java @@ -0,0 +1,83 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.util; + +public class IdentityHashMap implements Map { + private final HashMap map; + + public IdentityHashMap(int capacity) { + map = new HashMap(capacity, new MyHelper()); + } + + public IdentityHashMap() { + this(0); + } + + public boolean isEmpty() { + return map.isEmpty(); + } + + public int size() { + return map.size(); + } + + public boolean containsKey(Object key) { + return map.containsKey(key); + } + + public boolean containsValue(Object value) { + return map.containsValue(value); + } + + public V get(Object key) { + return map.get(key); + } + + public V put(K key, V value) { + return map.put(key, value); + } + + public void putAll(Map elts) { + map.putAll(elts); + } + + public V remove(Object key) { + return map.remove(key); + } + + public void clear() { + map.clear(); + } + + public Set> entrySet() { + return map.entrySet(); + } + + public Set keySet() { + return map.keySet(); + } + + public Collection values() { + return map.values(); + } + + private static class MyHelper + extends HashMap.MyHelper + { + public int hash(K a) { + return (a == null ? 0 : System.identityHashCode(a)); + } + + public boolean equal(K a, K b) { + return a == b; + } + } +} diff --git a/sgx-jvm/avian/classpath/java/util/IllegalFormatException.java b/sgx-jvm/avian/classpath/java/util/IllegalFormatException.java new file mode 100644 index 0000000000..d9f24f4564 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/util/IllegalFormatException.java @@ -0,0 +1,31 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.util; + +public class IllegalFormatException extends IllegalArgumentException { + + public IllegalFormatException() { + super(); + } + + public IllegalFormatException(String message, Throwable cause) { + super(message, cause); + } + + public IllegalFormatException(String message) { + super(message); + } + + public IllegalFormatException(Throwable cause) { + super(cause); + } + +} diff --git a/sgx-jvm/avian/classpath/java/util/Iterator.java b/sgx-jvm/avian/classpath/java/util/Iterator.java new file mode 100644 index 0000000000..cae013f04c --- /dev/null +++ b/sgx-jvm/avian/classpath/java/util/Iterator.java @@ -0,0 +1,19 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.util; + +public interface Iterator { + public T next(); + + public boolean hasNext(); + + public void remove(); +} diff --git a/sgx-jvm/avian/classpath/java/util/LinkedHashMap.java b/sgx-jvm/avian/classpath/java/util/LinkedHashMap.java new file mode 100644 index 0000000000..2b9bcce890 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/util/LinkedHashMap.java @@ -0,0 +1,267 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.util; + +public class LinkedHashMap extends HashMap { + private static class LinkedKey { + private final K key; + private LinkedKey previous, next; + + public LinkedKey(K key) { + this.key = key; + } + + public boolean equals(Object other) { + LinkedKey o = (LinkedKey) other; + return key.equals(o.key); + } + + public int hashCode() { + return key.hashCode(); + } + } + + private LinkedKey first, last; + private HashMap> lookup; + + public LinkedHashMap(int capacity) { + super(capacity); + lookup = new HashMap>(); + } + + public LinkedHashMap() { + this(0); + } + + public LinkedHashMap(Map map) { + this(map.size()); + putAll(map); + } + + public V put(K key, V value) { + if (!super.containsKey(key)) { + LinkedKey k = new LinkedKey(key); + if (first == null) { + first = k; + } else { + last.next = k; + k.previous = last; + } + last = k; + lookup.put(key, k); + } + return super.put(key, value); + } + + public V remove(Object key) { + LinkedKey linked = lookup.get(key); + if (linked == null) { + return null; + } + if (linked.previous == null) { + first = linked.next; + } else { + linked.previous.next = linked.next; + } + if (linked.next == null) { + last = linked.previous; + } else { + linked.next.previous = linked.previous; + } + return super.remove(key); + } + + public void clear() { + first = last = null; + super.clear(); + } + + public Set> entrySet() { + return new EntrySet(); + } + + public Set keySet() { + return new KeySet(); + } + + public Collection values() { + return new Values(); + } + + Iterator> iterator() { + return new MyIterator(); + } + + private class EntrySet extends AbstractSet> { + public int size() { + return LinkedHashMap.this.size(); + } + + public boolean isEmpty() { + return LinkedHashMap.this.isEmpty(); + } + + public boolean contains(Object o) { + return (o instanceof Entry) + && containsKey(((Entry)o).getKey()); + } + + public boolean add(Entry e) { + return put(e.getKey(), e.getValue()) != null; + } + + public boolean remove(Object o) { + return (o instanceof Entry) && remove((Entry)o); + } + + public boolean remove(Entry e) { + return LinkedHashMap.this.remove(e.getKey()) != null; + } + + public Object[] toArray() { + return toArray(new Object[size()]); + } + + public T[] toArray(T[] array) { + return avian.Data.toArray(this, array); + } + + public void clear() { + LinkedHashMap.this.clear(); + } + + public Iterator> iterator() { + return new MyIterator(); + } + } + + private class KeySet extends AbstractSet { + public int size() { + return LinkedHashMap.this.size(); + } + + public boolean isEmpty() { + return LinkedHashMap.this.isEmpty(); + } + + public boolean contains(Object key) { + return containsKey(key); + } + + public boolean add(K key) { + return put(key, null) != null; + } + + public boolean remove(Object key) { + return LinkedHashMap.this.remove(key) != null; + } + + public Object[] toArray() { + return toArray(new Object[size()]); + } + + public T[] toArray(T[] array) { + return avian.Data.toArray(this, array); + } + + public void clear() { + LinkedHashMap.this.clear(); + } + + public Iterator iterator() { + return new avian.Data.KeyIterator(new MyIterator()); + } + } + + private class Values implements Collection { + public int size() { + return LinkedHashMap.this.size(); + } + + public boolean isEmpty() { + return LinkedHashMap.this.isEmpty(); + } + + public boolean contains(Object value) { + return containsValue(value); + } + + public boolean containsAll(Collection c) { + if (c == null) { + throw new NullPointerException("collection is null"); + } + + Iterator it = c.iterator(); + while (it.hasNext()) { + if (! contains(it.next())) { + return false; + } + } + + return true; + } + + public boolean add(V value) { + throw new UnsupportedOperationException(); + } + + public boolean addAll(Collection collection) { + throw new UnsupportedOperationException(); + } + + public boolean remove(Object value) { + throw new UnsupportedOperationException(); + } + + public boolean removeAll(Collection c) { + throw new UnsupportedOperationException(); + } + + public Object[] toArray() { + return toArray(new Object[size()]); + } + + public T[] toArray(T[] array) { + return avian.Data.toArray(this, array); + } + + public void clear() { + LinkedHashMap.this.clear(); + } + + public Iterator iterator() { + return new avian.Data.ValueIterator(new MyIterator()); + } + } + + private class MyIterator implements Iterator> { + private LinkedKey current = first; + + public Entry next() { + if (!hasNext()) { + throw new NoSuchElementException(); + } + Entry result = find(current.key); + current = current.next; + return result; + } + + public boolean hasNext() { + return current != null; + } + + public void remove() { + LinkedHashMap.this.remove(current == null ? + last.key : current.previous.key); + } + } +} + diff --git a/sgx-jvm/avian/classpath/java/util/LinkedHashSet.java b/sgx-jvm/avian/classpath/java/util/LinkedHashSet.java new file mode 100644 index 0000000000..b508b1d5d5 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/util/LinkedHashSet.java @@ -0,0 +1,89 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.util; + +public class LinkedHashSet extends AbstractSet implements Set { + private static final Object Value = new Object(); + + private final LinkedHashMap map; + + public LinkedHashSet(Collection c) { + map = new LinkedHashMap(c.size()); + addAll(c); + } + + public LinkedHashSet(int capacity) { + map = new LinkedHashMap(capacity); + } + + public LinkedHashSet() { + this(0); + } + + public int size() { + return map.size(); + } + + public boolean isEmpty() { + return map.isEmpty(); + } + + public boolean contains(Object element) { + return map.containsKey(element); + } + + public boolean add(T element) { + return map.put(element, Value) != Value; + } + + public boolean addAll(Collection collection) { + boolean change = false; + for (T t: collection) if (add(t)) change = true; + return change; + } + + public boolean remove(Object element) { + return map.remove(element) != Value; + } + + public void clear() { + map.clear(); + } + + public Iterator iterator() { + return new MyIterator(map.iterator()); + } + + public String toString() { + return avian.Data.toString(this); + } + + private static class MyIterator implements Iterator { + private final Iterator> it; + + public MyIterator(Iterator> it) { + this.it = it; + } + + public T next() { + return it.next().getKey(); + } + + public boolean hasNext() { + return it.hasNext(); + } + + public void remove() { + it.remove(); + } + } +} + diff --git a/sgx-jvm/avian/classpath/java/util/LinkedList.java b/sgx-jvm/avian/classpath/java/util/LinkedList.java new file mode 100644 index 0000000000..6896b1eb4e --- /dev/null +++ b/sgx-jvm/avian/classpath/java/util/LinkedList.java @@ -0,0 +1,463 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.util; + +public class LinkedList extends AbstractSequentialList implements Deque { + private Cell front; + private Cell rear; + private int size; + + public LinkedList(Collection c) { + addAll(c); + } + + public LinkedList() { } + + private Cell find(int index) { + int i = 0; + for (Cell c = front; c != null; c = c.next) { + if (i == index) { + return c; + } + ++ i; + } + throw new IndexOutOfBoundsException(index + " not in [0, " + size + ")"); + } + + private static boolean equal(Object a, Object b) { + return (a == null && b == null) || (a != null && a.equals(b)); + } + + private void addFirst(Cell c) { + ++ size; + + if (front == null) { + front = rear = c; + } else { + c.next = front; + front.prev = c; + front = c; + } + } + + private void addLast(Cell c) { + ++ size; + + if (front == null) { + front = rear = c; + } else { + c.prev = rear; + rear.next = c; + rear = c; + } + } + + private Cell find(Object element) { + for (Cell c = front; c != null; c = c.next) { + if (equal(c.value, element)) { + return c; + } + } + return null; + } + + private void remove(Cell c) { + -- size; + + if (c.prev == null) { + front = c.next; + } else { + c.prev.next = c.next; + } + + if (c.next == null) { + rear = c.prev; + } else { + c.next.prev = c.prev; + } + } + + @Override + public int size() { + return size; + } + + @Override + public boolean contains(Object element) { + return find(element) != null; + } + + @Override + public int indexOf(Object element) { + int i = 0; + for (Cell c = front; c != null; c = c.next) { + if (equal(c.value, element)) { + return i; + } + ++ i; + } + return -1; + } + + @Override + public int lastIndexOf(Object element) { + int i = size; + for (Cell c = rear; c != null; c = c.prev) { + -- i; + if (equal(c.value, element)) { + return i; + } + } + return -1; + } + + @Override + public boolean offer(T element) { + return add(element); + } + + @Override + public boolean add(T element) { + addLast(element); + return true; + } + + @Override + public boolean addAll(Collection collection) { + for (T t: collection) add(t); + return true; + } + + @Override + public void add(int index, T element) { + if (index == 0) { + addFirst(element); + } else { + Cell cell = find(index); + Cell newCell = new Cell(element, cell.prev, cell); + cell.prev.next = newCell; + } + } + + @Override + public boolean offerFirst(T e) { + addFirst(e); + + return true; + } + + @Override + public void push(T e) { + addFirst(e); + } + + @Override + public void addFirst(T element) { + addFirst(new Cell(element, null, null)); + } + + @Override + public boolean offerLast(T e) { + addLast(e); + + return true; + } + + @Override + public void addLast(T element) { + addLast(new Cell(element, null, null)); + } + + public T get(int index) { + return find(index).value; + } + + @Override + public T set(int index, T value) { + Cell c = find(index); + T old = c.value; + c.value = value; + return old; + } + + @Override + public T peek() { + return peekFirst(); + } + + @Override + public T peekFirst() { + if (front != null) { + return front.value; + } else { + return null; + } + } + + @Override + public T getFirst() { + if (front != null) { + return front.value; + } else { + throw new NoSuchElementException(); + } + } + + @Override + public T peekLast() { + if (rear != null) { + return rear.value; + } else { + return null; + } + } + + @Override + public T getLast() { + if (rear != null) { + return rear.value; + } else { + throw new NoSuchElementException(); + } + } + + @Override + public T remove(int index) { + Cell c = find(index); + remove(c); + return c.value; + } + + @Override + public boolean isEmpty() { + return size() == 0; + } + + @Override + public T poll() { + return pollFirst(); + } + + @Override + public T pollFirst() { + if (front != null) { + T v = front.value; + remove(front); + return v; + } else { + return null; + } + } + + @Override + public T removeFirst() { + T result = pollFirst(); + + if (result == null) { + throw new NoSuchElementException(); + } else { + return result; + } + } + + @Override + public T pop() { + return removeFirst(); + } + + @Override + public T remove() { + return removeFirst(); + } + + @Override + public T pollLast() { + if (rear != null) { + T v = rear.value; + remove(rear); + return v; + } else { + throw new NoSuchElementException(); + } + } + + @Override + public T removeLast() { + T result = pollLast(); + + if (result == null) { + throw new NoSuchElementException(); + } else { + return result; + } + } + + @Override + public boolean remove(Object element) { + Cell c = find(element); + if (c == null) { + return false; + } else { + remove(c); + return true; + } + } + + @Override + public void clear() { + front = rear = null; + size = 0; + } + + @Override + public Iterator iterator() { + return listIterator(); + } + + @Override + public ListIterator listIterator() { + return listIterator(0); + } + + @Override + public ListIterator listIterator(int index) { + MyIterator it = new MyIterator(); + for (int i = 0; i < index; ++i) { + it.next(); + } + return it; + } + + @Override + public Iterator descendingIterator() { + final ListIterator li = listIterator(size()); + + return new Iterator() { + @Override + public T next() { + return li.previous(); + } + + @Override + public boolean hasNext() { + return li.hasPrevious(); + } + + @Override + public void remove() { + li.remove(); + } + }; + } + + @Override + public String toString() { + return avian.Data.toString(this); + } + + @Override + public T element() { + T result = peek(); + if (result == null) { + throw new NoSuchElementException(); + } else { + return result; + } + } + + @Override + public boolean removeFirstOccurrence(Object o) { + int index = indexOf(o); + if (index > 0) { + remove(index); + + return true; + } else { + return false; + } + } + + @Override + public boolean removeLastOccurrence(Object o) { + int lastIndex = lastIndexOf(o); + if (lastIndex > 0) { + remove(lastIndex); + + return true; + } else { + return false; + } + } + + private static class Cell { + public T value; + public Cell prev; + public Cell next; + + public Cell(T value, Cell prev, Cell next) { + this.value = value; + this.prev = prev; + this.next = next; + } + } + + private class MyIterator implements ListIterator { + private Cell toRemove; + private Cell current; + + public T previous() { + if (hasPrevious()) { + T v = current.value; + toRemove = current; + current = current.prev; + return v; + } else { + throw new NoSuchElementException(); + } + } + + public T next() { + if (hasNext()) { + if (current == null) { + current = front; + } else { + current = current.next; + } + toRemove = current; + return current.value; + } else { + throw new NoSuchElementException(); + } + } + + public boolean hasNext() { + if (current == null) { + return front != null; + } else { + return current.next != null; + } + } + + public boolean hasPrevious() { + return current != null; + } + + public void remove() { + if (toRemove != null) { + current = toRemove.prev; + LinkedList.this.remove(toRemove); + toRemove = null; + } else { + throw new IllegalStateException(); + } + } + } +} diff --git a/sgx-jvm/avian/classpath/java/util/List.java b/sgx-jvm/avian/classpath/java/util/List.java new file mode 100644 index 0000000000..a263f811bd --- /dev/null +++ b/sgx-jvm/avian/classpath/java/util/List.java @@ -0,0 +1,35 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.util; + +public interface List extends Collection { + public T get(int index); + + public T set(int index, T value); + + public T remove(int index); + + public boolean add(T element); + + public void add(int index, T element); + + public boolean addAll(int startIndex, Collection c); + + public int indexOf(Object value); + + public int lastIndexOf(Object value); + + public boolean isEmpty(); + + public ListIterator listIterator(int index); + + public ListIterator listIterator(); +} diff --git a/sgx-jvm/avian/classpath/java/util/ListIterator.java b/sgx-jvm/avian/classpath/java/util/ListIterator.java new file mode 100644 index 0000000000..8259cb50aa --- /dev/null +++ b/sgx-jvm/avian/classpath/java/util/ListIterator.java @@ -0,0 +1,16 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.util; + +public interface ListIterator extends Iterator { + public boolean hasPrevious(); + public E previous(); +} diff --git a/sgx-jvm/avian/classpath/java/util/Locale.java b/sgx-jvm/avian/classpath/java/util/Locale.java new file mode 100644 index 0000000000..c0ffeebff7 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/util/Locale.java @@ -0,0 +1,64 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.util; + +public class Locale { + private static final Locale DEFAULT; + public static final Locale ENGLISH = new Locale("en", ""); + + private final String language; + private final String country; + private final String variant; + + static { + DEFAULT = new Locale(System.getProperty("user.language"), + System.getProperty("user.region")); + } + + public Locale(String language, String country, String variant) { + this.language = language; + this.country = country; + this.variant = variant; + } + + public Locale(String language, String country) { + this(language, country, ""); + } + + public Locale(String language) { + this(language, ""); + } + + public String getLanguage() { + return language; + } + + public String getCountry() { + return country; + } + + public String getVariant() { + return variant; + } + + public static Locale getDefault() { + return DEFAULT; + } + + public final String toString() { + boolean hasLanguage = language != ""; + boolean hasCountry = country != ""; + boolean hasVariant = variant != ""; + + if (!hasLanguage && !hasCountry) return ""; + return language + (hasCountry || hasVariant ? '_' + country : "") + (hasVariant ? '_' + variant : ""); + } +} diff --git a/sgx-jvm/avian/classpath/java/util/Map.java b/sgx-jvm/avian/classpath/java/util/Map.java new file mode 100644 index 0000000000..f91b765544 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/util/Map.java @@ -0,0 +1,49 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.util; + +public interface Map { + public boolean isEmpty(); + + public int size(); + + public boolean containsKey(Object obj); + + public boolean containsValue(Object obj); + + public V get(Object key); + + public V put(K key, V value); + + public void putAll(Map elts); + + public V remove(Object key); + + public void clear(); + + public Set> entrySet(); + + public Set keySet(); + + public Collection values(); + + public boolean equals(Object other); + + public int hashCode(); + + public interface Entry { + public K getKey(); + + public V getValue(); + + public V setValue(V value); + } +} diff --git a/sgx-jvm/avian/classpath/java/util/MissingResourceException.java b/sgx-jvm/avian/classpath/java/util/MissingResourceException.java new file mode 100644 index 0000000000..df2f02bfee --- /dev/null +++ b/sgx-jvm/avian/classpath/java/util/MissingResourceException.java @@ -0,0 +1,30 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.util; + +public class MissingResourceException extends RuntimeException { + private final String class_; + private final String key; + + public MissingResourceException(String message, String class_, String key) { + super(message); + this.class_ = class_; + this.key = key; + } + + public String getClassName() { + return class_; + } + + public String getKey() { + return key; + } +} diff --git a/sgx-jvm/avian/classpath/java/util/NavigableMap.java b/sgx-jvm/avian/classpath/java/util/NavigableMap.java new file mode 100644 index 0000000000..05136159c6 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/util/NavigableMap.java @@ -0,0 +1,6 @@ +package java.util; + +public interface NavigableMap extends SortedMap { + Map.Entry firstEntry(); + Map.Entry lastEntry(); +} diff --git a/sgx-jvm/avian/classpath/java/util/NoSuchElementException.java b/sgx-jvm/avian/classpath/java/util/NoSuchElementException.java new file mode 100644 index 0000000000..86c6dba6e7 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/util/NoSuchElementException.java @@ -0,0 +1,21 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.util; + +public class NoSuchElementException extends RuntimeException { + public NoSuchElementException(String message) { + super(message); + } + + public NoSuchElementException() { + super(); + } +} diff --git a/sgx-jvm/avian/classpath/java/util/Objects.java b/sgx-jvm/avian/classpath/java/util/Objects.java new file mode 100644 index 0000000000..ca59ce1922 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/util/Objects.java @@ -0,0 +1,92 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.util; + +public final class Objects { + private Objects() { + throw new AssertionError("Instantiating java.long.Objetcs is not allowed!"); + } + + public static int compare(final T x, final T y, final Comparator comparator) { + if (x == y) + return 0; + else + return comparator.compare(x, y); + } + + public static boolean deepEquals(final Object x, final Object y) { + if (x == y) + return true; + if (x == null || y == null) + return false; + if (x.getClass().isArray()) { + if(x instanceof Object[] && y instanceof Object[]) + return Arrays.deepEquals((Object[])x, (Object[])y); + if(x instanceof byte[] && y instanceof byte[]) + return Arrays.equals((byte[]) x, (byte[]) y); + if(x instanceof int[] && y instanceof int[]) + return Arrays.equals((int[]) x, (int[]) y); + if(x instanceof long[] && y instanceof long[]) + return Arrays.equals((long[]) x, (long[]) y); + if(x instanceof short[] && y instanceof short[]) + return Arrays.equals((short[]) x, (short[]) y); + if(x instanceof char[] && y instanceof char[]) + return Arrays.equals((char[]) x, (char[]) y); + if(x instanceof float[] && y instanceof float[]) + return Arrays.equals((float[]) x, (float[]) y); + if(x instanceof double[] && y instanceof double[]) + return Arrays.equals((double[]) x, (double[]) y); + } + return x.equals(y); + } + + public static boolean equals(final Object x, final Object y) { + if (x == y) + return true; + if (x != null) + return x.equals(y); + return false; + } + + public static int hash(final Object... values) { + return Arrays.hashCode(values); + } + + public static int hashCode(final Object value) { + if (value == null) + return 0; + return value.hashCode(); + } + + public static T requireNonNull(final T value) { + if (value == null) + throw new NullPointerException(); + else + return value; + } + + public static T requireNonNull(final T value, String message) { + if (value == null) + throw new NullPointerException(message); + else + return value; + } + + public static String toString(final Object value) { + return String.valueOf(value); + } + + public static String toString(final Object value, final String defaultValue) { + if (value == null) + return defaultValue; + return value.toString(); + } +} diff --git a/sgx-jvm/avian/classpath/java/util/Observable.java b/sgx-jvm/avian/classpath/java/util/Observable.java new file mode 100644 index 0000000000..5b2d6dfc17 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/util/Observable.java @@ -0,0 +1,73 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.util; + +public class Observable { + + private List observers = new ArrayList(); + private boolean changed = false; + + public void addObserver(Observer o) { + if(o == null) { + throw new NullPointerException(); + } + synchronized(this) { + if(!observers.contains(o)) { + observers.add(o); + } + } + } + + public synchronized int countObservers() { + return observers.size(); + } + + public void deleteObserver(Observer o) { + if(o == null) { + throw new NullPointerException(); + } + synchronized(this) { + observers.remove(o); + } + } + + public void notifyObservers() { + notifyObservers(null); + } + + public synchronized void notifyObservers(Object value) { + Observer[] obsArray = null; + synchronized(this) { + if(hasChanged()) { + clearChanged(); + obsArray = observers.toArray(new Observer[observers.size()]); + } + } + if(obsArray != null) { + for(Observer obs : obsArray) { + obs.update(this, value); + } + } + } + + public boolean hasChanged() { + return changed; + } + + protected void setChanged() { + changed = true; + } + + protected void clearChanged() { + changed = false; + } + +} \ No newline at end of file diff --git a/sgx-jvm/avian/classpath/java/util/Observer.java b/sgx-jvm/avian/classpath/java/util/Observer.java new file mode 100644 index 0000000000..f77b916219 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/util/Observer.java @@ -0,0 +1,15 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.util; + +public interface Observer { + public void update(Observable o, Object arg); +} \ No newline at end of file diff --git a/sgx-jvm/avian/classpath/java/util/Properties.java b/sgx-jvm/avian/classpath/java/util/Properties.java new file mode 100644 index 0000000000..b7905b484d --- /dev/null +++ b/sgx-jvm/avian/classpath/java/util/Properties.java @@ -0,0 +1,213 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.util; + +import java.io.InputStream; +import java.io.OutputStream; +import java.io.PrintStream; +import java.io.IOException; +import java.io.Reader; + +public class Properties extends Hashtable { + public void load(InputStream in) throws IOException { + new InputStreamParser(in).parse(this); + } + + public void load(Reader reader) throws IOException { + new ReaderParser(reader).parse(this); + } + + public void store(OutputStream out, String comment) throws IOException { + PrintStream os = new PrintStream(out); + os.println("# " + comment); + for (Iterator it = entrySet().iterator(); + it.hasNext();) { + Map.Entry entry = (Map.Entry)it.next(); + os.print(entry.getKey()); + os.print('='); + os.println(entry.getValue()); + } + os.flush(); + } + + public String getProperty(String key) { + return (String)get(key); + } + + public String getProperty(String key, String defaultValue) { + String value = (String) get(key); + if (value == null) { + return defaultValue; + } + return value; + } + + public Object setProperty(String key, String value) { + return put(key, value); + } + + public Enumeration propertyNames() { + return keys(); + } + + public Set stringPropertyNames() { + return new HashSet(keySet()); + } + + private abstract static class Parser { + private StringBuilder key = null; + private StringBuilder value = null; + private StringBuilder current = null; + + private void append(int c) { + if (current == null) { + if (key == null) { + current = key = new StringBuilder(); + } else { + current = value = new StringBuilder(); + } + } + + current.append((char) c); + } + + private void finishLine(Map map) { + if (key != null) { + map.put(key.toString(), + (value == null ? "" : value.toString().trim())); + } + + key = value = current = null; + } + + abstract int readCharacter() throws IOException; + + char readUtf16() throws IOException { + char c = 0; + for (int i = 0; i < 4; ++i) { + int digit = Character.digit((char)readCharacter(), 16); + if (digit == -1) throw new IOException("Invalid Unicode escape encountered."); + c <<= 4; + c |= digit; + } + return c; + } + + void parse(Map map) + throws IOException + { + boolean escaped = false; + + int c; + while ((c = readCharacter()) != -1) { + if (c == '\\') { + if (escaped) { + escaped = false; + append(c); + } else { + escaped = true; + } + } else { + switch (c) { + case '#': + case '!': + if (key == null) { + while ((c = readCharacter()) != -1 && c != '\n'); + } else { + append(c); + } + break; + + case ' ': + case '\r': + case '\t': + if (escaped || (current != null && value == current)) { + append(c); + } else if (key == current) { + current = null; + } + break; + + case ':': + case '=': + if (escaped || (current != null && value == current)) { + append(c); + } else { + if (key == null) { + key = new StringBuilder(); + } + current = null; + } + break; + + case '\n': + if (escaped) { + append(c); + } else { + finishLine(map); + } + break; + case 'n': + if (escaped) { + append('\n'); + } else { + append(c); + } + break; + + case 'u': + if (escaped) { + append(readUtf16()); + } else { + append(c); + } break; + + default: + append(c); + break; + } + + escaped = false; + } + } + + finishLine(map); + } + } + + static class InputStreamParser extends Parser { + InputStream in; + + + public InputStreamParser(InputStream in) { + this.in = in; + } + + @Override + int readCharacter() throws IOException { + return in.read(); + } + } + + static class ReaderParser extends Parser { + Reader in; + + public ReaderParser(Reader in) { + this.in = in; + } + + @Override + int readCharacter() throws IOException { + return in.read(); + } + } + +} diff --git a/sgx-jvm/avian/classpath/java/util/PropertyResourceBundle.java b/sgx-jvm/avian/classpath/java/util/PropertyResourceBundle.java new file mode 100644 index 0000000000..d9dbff2101 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/util/PropertyResourceBundle.java @@ -0,0 +1,30 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.util; + +import java.io.InputStream; +import java.io.IOException; + +public class PropertyResourceBundle extends ResourceBundle { + private final Properties map = new Properties(); + + public PropertyResourceBundle(InputStream in) throws IOException { + map.load(in); + } + + public Object handleGetObject(String key) { + return map.get(key); + } + + public Enumeration getKeys() { + return map.keys(); + } +} diff --git a/sgx-jvm/avian/classpath/java/util/Queue.java b/sgx-jvm/avian/classpath/java/util/Queue.java new file mode 100644 index 0000000000..d0f6578817 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/util/Queue.java @@ -0,0 +1,20 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.util; + +public interface Queue extends Collection, Iterable { + public boolean add(T element); + public T element(); + public boolean offer(T element); + public T peek(); + public T poll(); + public T remove(); +} diff --git a/sgx-jvm/avian/classpath/java/util/Random.java b/sgx-jvm/avian/classpath/java/util/Random.java new file mode 100644 index 0000000000..9d244c5e0c --- /dev/null +++ b/sgx-jvm/avian/classpath/java/util/Random.java @@ -0,0 +1,87 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.util; + +public class Random { + private static final long Mask = 0x5DEECE66DL; + + private static final long InitialSeed = 123456789987654321L; + + private static long nextSeed = InitialSeed; + + private long seed; + + public Random(long seed) { + setSeed(seed); + } + + public Random() { + synchronized (Random.class) { + setSeed(nextSeed ^ System.currentTimeMillis()); + nextSeed *= 123456789987654321L; + if (nextSeed == 0) { + nextSeed = InitialSeed; + } + } + } + + public void setSeed(long seed) { + this.seed = (seed ^ Mask) & ((1L << 48) - 1); + } + + protected int next(int bits) { + seed = ((seed * Mask) + 0xBL) & ((1L << 48) - 1); + return (int) (seed >>> (48 - bits)); + } + + public int nextInt(int limit) { + if (limit <= 0) { + throw new IllegalArgumentException(); + } + + if ((limit & -limit) == limit) { + // limit is a power of two + return (int) ((limit * (long) next(31)) >> 31); + } + + int bits; + int value; + do { + bits = next(31); + value = bits % limit; + } while (bits - value + (limit - 1) < 0); + + return value; + } + + public int nextInt() { + return next(32); + } + + public void nextBytes(byte[] bytes) { + final int length = bytes.length; + for (int i = 0; i < length;) { + int r = nextInt(); + for (int j = Math.min(length - i, 4); j > 0; --j) { + bytes[i++] = (byte) r; + r >>= 8; + } + } + } + + public long nextLong() { + return ((long) next(32) << 32) + next(32); + } + + public double nextDouble() { + return (((long) next(26) << 27) + next(27)) / (double) (1L << 53); + } +} diff --git a/sgx-jvm/avian/classpath/java/util/RandomAccess.java b/sgx-jvm/avian/classpath/java/util/RandomAccess.java new file mode 100644 index 0000000000..17afe39dba --- /dev/null +++ b/sgx-jvm/avian/classpath/java/util/RandomAccess.java @@ -0,0 +1,16 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.util; + +public interface RandomAccess { + /* nothing added here, this interface just indicates a + * structure is efficient to access via index's directly.*/ +} diff --git a/sgx-jvm/avian/classpath/java/util/ResourceBundle.java b/sgx-jvm/avian/classpath/java/util/ResourceBundle.java new file mode 100644 index 0000000000..ccab80f876 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/util/ResourceBundle.java @@ -0,0 +1,122 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.util; + +import java.lang.reflect.Method; +import java.io.InputStream; +import java.io.IOException; + +public abstract class ResourceBundle { + protected String name; + protected ResourceBundle parent; + + private static String replace(char a, char b, String s) { + char[] array = new char[s.length()]; + for (int i = 0; i < array.length; ++i) { + char c = s.charAt(i); + array[i] = (c == a ? b : c); + } + return new String(array, 0, array.length, false); + } + + private static ResourceBundle findProperties(String name, ClassLoader loader, + ResourceBundle parent) + throws IOException + { + InputStream in = loader.getResourceAsStream + (replace('.', '/', name) + ".properties"); + if (in != null) { + try { + ResourceBundle r = new PropertyResourceBundle(in); + r.name = name; + r.parent = parent; + return r; + } finally { + in.close(); + } + } else { + return null; + } + } + + private static ResourceBundle find(String name, ClassLoader loader, + ResourceBundle parent) + throws Exception + { + try { + Class c = Class.forName(name, true, loader); + if (c.isAssignableFrom(ResourceBundle.class)) { + return (ResourceBundle) c.getConstructor().newInstance(); + } + } catch (ClassNotFoundException ok) { + } catch (NoSuchMethodException ok) { } + + return findProperties(name, loader, parent); + } + + public static ResourceBundle getBundle(String name, Locale locale, + ClassLoader loader) + { + try { + ResourceBundle b = find(name, loader, null); + + if (locale.getLanguage() != null) { + name = name + "_" + locale.getLanguage(); + ResourceBundle b2 = find(name, loader, b); + if (b2 != null) b = b2; + + if (locale.getCountry() != null) { + name = name + "_" + locale.getCountry(); + b2 = find(name, loader, b); + if (b2 != null) b = b2; + + if (locale.getVariant() != null) { + name = name + "_" + locale.getVariant(); + b2 = find(name, loader, b); + if (b2 != null) b = b2; + } + } + } + return b; + } catch (Exception e) { + RuntimeException re = new MissingResourceException(name, name, null); + re.initCause(e); + throw re; + } + } + + public static ResourceBundle getBundle(String name, Locale locale) { + return getBundle(name, locale, Method.getCaller().class_.loader); + } + + public static ResourceBundle getBundle(String name) { + return getBundle + (name, Locale.getDefault(), Method.getCaller().class_.loader); + } + + public Object getObject(String key) { + for (ResourceBundle b = this; b != null; b = b.parent) { + Object value = b.handleGetObject(key); + if (value != null) { + return value; + } + } + throw new MissingResourceException(key, name, key); + } + + public String getString(String key) { + return (String) getObject(key); + } + + protected abstract Object handleGetObject(String key); + + public abstract Enumeration getKeys(); +} diff --git a/sgx-jvm/avian/classpath/java/util/Set.java b/sgx-jvm/avian/classpath/java/util/Set.java new file mode 100644 index 0000000000..1dc124d0e1 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/util/Set.java @@ -0,0 +1,13 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.util; + +public interface Set extends Collection { } diff --git a/sgx-jvm/avian/classpath/java/util/SortedMap.java b/sgx-jvm/avian/classpath/java/util/SortedMap.java new file mode 100644 index 0000000000..d7abb282ba --- /dev/null +++ b/sgx-jvm/avian/classpath/java/util/SortedMap.java @@ -0,0 +1,15 @@ +package java.util; + +public interface SortedMap extends Map { + public Comparator comparator(); + + public K firstKey(); + + public K lastKey(); + + public SortedMap headMap(K toKey); + + public SortedMap tailMap(K fromKey); + + public SortedMap subMap(K fromKey, K toKey); +} diff --git a/sgx-jvm/avian/classpath/java/util/SortedSet.java b/sgx-jvm/avian/classpath/java/util/SortedSet.java new file mode 100644 index 0000000000..26ddf8159c --- /dev/null +++ b/sgx-jvm/avian/classpath/java/util/SortedSet.java @@ -0,0 +1,20 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.util; + +public interface SortedSet extends Collection, Iterable, Set { + public Comparator comparator(); + public T first(); + public SortedSet headSet(T toElement); + public T last(); + public SortedSet subSet(T fromElement, T toElement); + public SortedSet tailSet(T fromElement); +} diff --git a/sgx-jvm/avian/classpath/java/util/Stack.java b/sgx-jvm/avian/classpath/java/util/Stack.java new file mode 100644 index 0000000000..9d7def967c --- /dev/null +++ b/sgx-jvm/avian/classpath/java/util/Stack.java @@ -0,0 +1,30 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.util; + +public class Stack extends Vector { + public boolean empty() { + return size() == 0; + } + + public T peek() { + return get(size() - 1); + } + + public T pop() { + return remove(size() - 1); + } + + public T push(T element) { + add(element); + return element; + } +} diff --git a/sgx-jvm/avian/classpath/java/util/StringTokenizer.java b/sgx-jvm/avian/classpath/java/util/StringTokenizer.java new file mode 100644 index 0000000000..e2127fce20 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/util/StringTokenizer.java @@ -0,0 +1,108 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.util; + +public class StringTokenizer implements Enumeration { + private final String in; + private String delimiters; + private final boolean includeDelimiters; + private int position; + + public StringTokenizer(String in, String delimiters, + boolean includeDelimiters) + { + this.in = in; + this.delimiters = delimiters; + this.includeDelimiters = includeDelimiters; + } + + public StringTokenizer(String in, String delimiters) { + this(in, delimiters, false); + } + + public StringTokenizer(String in) { + this(in, " \t\r\n\f"); + } + + private boolean isDelimiter(char c) { + return delimiters.indexOf(c) >= 0; + } + + public int countTokens() { + int count = 0; + boolean sawNonDelimiter = false; + for (int i = position; i < in.length(); ++i) { + if (isDelimiter(in.charAt(i))) { + if (sawNonDelimiter) { + sawNonDelimiter = false; + ++ count; + } + + if (includeDelimiters) { + ++ count; + } + } else { + sawNonDelimiter = true; + } + } + + if (sawNonDelimiter) { + ++ count; + } + + return count; + } + + public boolean hasMoreTokens() { + for (int i = position; i < in.length(); ++i) { + if (isDelimiter(in.charAt(i))) { + if (includeDelimiters) { + return true; + } + } else { + position = i; + return true; + } + } + return false; + } + + public String nextToken() { + for (int i = position; i < in.length(); ++i) { + if (isDelimiter(in.charAt(i))) { + if (includeDelimiters) { + return in.substring(i, i + 1); + } + } else { + position = i; + while (position < in.length() && ! isDelimiter(in.charAt(position))) { + ++ position; + } + return in.substring(i, position); + } + } + throw new NoSuchElementException(); + } + + public String nextToken(String delimiters) { + this.delimiters = delimiters; + return nextToken(); + } + + public boolean hasMoreElements() { + return hasMoreTokens(); + } + + public Object nextElement() { + return nextToken(); + } + +} diff --git a/sgx-jvm/avian/classpath/java/util/TimeZone.java b/sgx-jvm/avian/classpath/java/util/TimeZone.java new file mode 100644 index 0000000000..ec933e7649 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/util/TimeZone.java @@ -0,0 +1,35 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.util; + +public class TimeZone { + + // for now, we only support GMT + private static final TimeZone GMT = new TimeZone("GMT"); + + private final String name; + + private TimeZone(String name) { + this.name = name; + } + + public static TimeZone getTimeZone(String id) { + // technically the Java spec says that this method + // returns GMT if it can't understand the "id" parameter + // sigh. + return GMT; + } + + public String getDisplayName() { + return name; + } + +} diff --git a/sgx-jvm/avian/classpath/java/util/TreeMap.java b/sgx-jvm/avian/classpath/java/util/TreeMap.java new file mode 100644 index 0000000000..9b8792d9d6 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/util/TreeMap.java @@ -0,0 +1,304 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.util; + +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; + +public class TreeMap implements NavigableMap { + private final Comparator comparator; + private transient TreeSet> set; + + public TreeMap(Comparator comparator) { + this.comparator = comparator; + initializeSet(); + } + + private void initializeSet() { + final Comparator comparator = this.comparator != null ? + this.comparator : new Comparator() { + public int compare(K a, K b) { + return ((Comparable) a).compareTo(b); + } + }; + set = new TreeSet(new Comparator>() { + public int compare(MyEntry a, MyEntry b) { + return comparator.compare(a.key, b.key); + } + }); + } + + public TreeMap() { + this(null); + } + + public String toString() { + return avian.Data.toString(this); + } + + @Override + public Comparator comparator() { + return comparator; + } + + @Override + public Map.Entry firstEntry() { + return set.first(); + } + + @Override + public Map.Entry lastEntry() { + return set.last(); + } + + @Override + public K firstKey() { + return set.first().key; + } + + @Override + public K lastKey() { + return set.last().key; + } + + @Override + public SortedMap headMap(K toKey) { + // TODO - this should be implemented, the trick is making the returned SortedMap backed by this TreeSet + throw new UnsupportedOperationException(); + } + + @Override + public SortedMap tailMap(K fromKey) { + // TODO - this should be implemented, the trick is making the returned SortedMap backed by this TreeSet + throw new UnsupportedOperationException(); + } + + @Override + public SortedMap subMap(K fromKey, K toKey) { + // TODO - this should be implemented, the trick is making the returned SortedMap backed by this TreeSet + throw new UnsupportedOperationException(); + } + + public V get(Object key) { + MyEntry e = set.find(new MyEntry(key, null)); + return e == null ? null : e.value; + } + + public V put(K key, V value) { + MyEntry e = set.addAndReplace(new MyEntry(key, value)); + return e == null ? null : e.value; + } + + public void putAll(Map elts) { + for (Map.Entry entry : elts.entrySet()) { + put(entry.getKey(), entry.getValue()); + } + } + + public V remove(Object key) { + MyEntry e = set.removeAndReturn(new MyEntry(key, null)); + return e == null ? null : e.value; + } + + public void clear() { + set.clear(); + } + + public int size() { + return set.size(); + } + + public boolean isEmpty() { + return size() == 0; + } + + public boolean containsKey(Object key) { + return set.contains(new MyEntry(key, null)); + } + + private boolean equal(Object a, Object b) { + return a == null ? b == null : a.equals(b); + } + + public boolean containsValue(Object value) { + for (V v: values()) { + if (equal(v, value)) { + return true; + } + } + return false; + } + + public Set> entrySet() { + return (Set>) (Set) set; + } + + public Set keySet() { + return new KeySet(); + } + + public Collection values() { + return new Values(); + } + + private static class MyEntry implements Entry { + public final K key; + public V value; + + public MyEntry(K key, V value) { + this.key = key; + this.value = value; + } + + public K getKey() { + return key; + } + + public V getValue() { + return value; + } + + public V setValue(V value) { + V old = this.value; + this.value = value; + return old; + } + + } + + private class KeySet extends AbstractSet { + public int size() { + return TreeMap.this.size(); + } + + public boolean isEmpty() { + return TreeMap.this.isEmpty(); + } + + public boolean contains(Object key) { + return containsKey(key); + } + + public boolean add(K key) { + return set.addAndReplace(new MyEntry(key, null)) != null; + } + + public boolean addAll(Collection collection) { + boolean change = false; + for (K k: collection) if (add(k)) change = true; + return change; + } + + public boolean remove(Object key) { + return set.removeAndReturn(new MyEntry(key, null)) != null; + } + + public Object[] toArray() { + return toArray(new Object[size()]); + } + + public T[] toArray(T[] array) { + return avian.Data.toArray(this, array); + } + + public void clear() { + TreeMap.this.clear(); + } + + public Iterator iterator() { + return new avian.Data.KeyIterator(set.iterator()); + } + } + + private class Values implements Collection { + public int size() { + return TreeMap.this.size(); + } + + public boolean isEmpty() { + return TreeMap.this.isEmpty(); + } + + public boolean contains(Object value) { + return containsValue(value); + } + + public boolean containsAll(Collection c) { + if (c == null) { + throw new NullPointerException("collection is null"); + } + + Iterator it = c.iterator(); + while (it.hasNext()) { + if (! contains(it.next())) { + return false; + } + } + + return true; + } + + public boolean add(V value) { + throw new UnsupportedOperationException(); + } + + public boolean addAll(Collection collection) { + throw new UnsupportedOperationException(); + } + + public boolean remove(Object value) { + throw new UnsupportedOperationException(); + } + + public boolean removeAll(Collection c) { + throw new UnsupportedOperationException(); + } + + public Object[] toArray() { + return toArray(new Object[size()]); + } + + public T[] toArray(T[] array) { + return avian.Data.toArray(this, array); + } + + public void clear() { + TreeMap.this.clear(); + } + + public Iterator iterator() { + return new avian.Data.ValueIterator(set.iterator()); + } + } + + public final static long serialVersionUID = 0x0cc1f63e2d256ae6l; + + private void writeObject(ObjectOutputStream out) throws IOException { + out.defaultWriteObject(); + out.writeInt(size()); + for (Entry entry : entrySet()) { + out.writeObject(entry.getKey()); + out.writeObject(entry.getValue()); + } + } + + private void readObject(ObjectInputStream in) throws IOException { + in.defaultReadObject(); + initializeSet(); + int size = in.readInt(); + for (int i = 0; i < size; i++) try { + put((K) in.readObject(), (V) in.readObject()); + } catch (ClassNotFoundException e) { + throw new IOException(e); + } + } +} diff --git a/sgx-jvm/avian/classpath/java/util/TreeSet.java b/sgx-jvm/avian/classpath/java/util/TreeSet.java new file mode 100644 index 0000000000..ccb03e3b6e --- /dev/null +++ b/sgx-jvm/avian/classpath/java/util/TreeSet.java @@ -0,0 +1,214 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.util; + +import avian.PersistentSet; +import avian.Cell; + +public class TreeSet extends AbstractSet implements Collection { + private PersistentSet> set; + + public TreeSet(final Comparator comparator) { + set = new PersistentSet(new Comparator>() { + public int compare(Cell a, Cell b) { + return comparator.compare(a.value, b.value); + } + }); + } + + public TreeSet() { + this(new Comparator() { + public int compare(T a, T b) { + return ((Comparable) a).compareTo(b); + } + }); + } + + public TreeSet(Collection collection) { + this(); + + for (T item: collection) { + add(item); + } + } + + public T first() { + if (isEmpty()) throw new NoSuchElementException(); + + return set.first().value().value; + } + + public T last() { + if (isEmpty()) throw new NoSuchElementException(); + + return set.last().value().value; + } + + public Iterator iterator() { + return new MyIterator(set.first()); + } + + public Iterator descendingIterator() { + return new MyIterator(set.last(), true); + } + + public String toString() { + return avian.Data.toString(this); + } + + public boolean add(T value) { + PersistentSet.Path> p = set.find(new Cell(value, null)); + if (p.fresh()) { + set = p.add(); + return true; + } + return false; + } + + T addAndReplace(T value) { + PersistentSet.Path> p = set.find(new Cell(value, null)); + if (p.fresh()) { + set = p.add(); + return null; + } else { + T old = p.value().value; + set = p.replaceWith(new Cell(value, null)); + return old; + } + } + + T find(T value) { + PersistentSet.Path> p = set.find(new Cell(value, null)); + return p.fresh() ? null : p.value().value; + } + + T removeAndReturn(T value) { + Cell cell = removeCell(value); + return cell == null ? null : cell.value; + } + + private Cell removeCell(Object value) { + PersistentSet.Path> p = set.find(new Cell(value, null)); + if (p.fresh()) { + return null; + } else { + Cell old = p.value(); + + if (p.value().next != null) { + set = p.replaceWith(p.value().next); + } else { + set = p.remove(); + } + + return old; + } + } + + public boolean remove(Object value) { + return removeCell(value) != null; + } + + public int size() { + return set.size(); + } + + public boolean isEmpty() { + return set.size() == 0; + } + + public boolean contains(Object value) { + return !set.find(new Cell(value, null)).fresh(); + } + + public void clear() { + set = new PersistentSet(set.comparator()); + } + + private class MyIterator implements java.util.Iterator { + private PersistentSet.Path> path; + private PersistentSet.Path> nextPath; + private Cell cell; + private Cell prevCell; + private Cell prevPrevCell; + private boolean canRemove = false; + private final boolean reversed; + + private MyIterator(PersistentSet.Path> path) { + this(path, false); + } + + private MyIterator(PersistentSet.Path> path, boolean reversed) { + this.path = path; + this.reversed = reversed; + if (path != null) { + cell = path.value(); + nextPath = nextPath(); + } + } + + private MyIterator(MyIterator start) { + path = start.path; + nextPath = start.nextPath; + cell = start.cell; + prevCell = start.prevCell; + prevPrevCell = start.prevPrevCell; + canRemove = start.canRemove; + reversed = start.reversed; + } + + public boolean hasNext() { + return cell != null || nextPath != null; + } + + public T next() { + if (cell == null) { + path = nextPath; + nextPath = nextPath(); + cell = path.value(); + } + prevPrevCell = prevCell; + prevCell = cell; + cell = cell.next; + canRemove = true; + return prevCell.value; + } + + private PersistentSet.Path nextPath() { + return reversed ? path.predecessor() : path.successor(); + } + + public void remove() { + if (! canRemove) throw new IllegalStateException(); + + if (prevPrevCell != null && prevPrevCell.next == prevCell) { + // cell to remove is not the first in the list. + prevPrevCell.next = prevCell.next; + prevCell = prevPrevCell; + } else if (prevCell.next == cell && cell != null) { + // cell to remove is the first in the list, but not the last. + set = (PersistentSet) path.replaceWith(cell); + prevCell = null; + } else { + // cell is alone in the list. + set = (PersistentSet) path.remove(); + path = nextPath; + if (path != null) { + prevCell = null; + cell = path.value(); + path = (PersistentSet.Path) set.find((Cell) cell); + nextPath = nextPath(); + } + } + + canRemove = false; + } + } +} diff --git a/sgx-jvm/avian/classpath/java/util/UUID.java b/sgx-jvm/avian/classpath/java/util/UUID.java new file mode 100644 index 0000000000..4c5be5ccac --- /dev/null +++ b/sgx-jvm/avian/classpath/java/util/UUID.java @@ -0,0 +1,55 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.util; + +public class UUID { + private final byte[] data; + + private UUID(byte[] data) { + this.data = data; + } + + public static UUID randomUUID() { + byte[] array = new byte[16]; + + new Random().nextBytes(array); + + array[6] &= 0x0f; + array[6] |= 0x40; + array[8] &= 0x3f; + array[8] |= 0x80; + + return new UUID(array); + } + + public String toString() { + StringBuilder sb = new StringBuilder(); + toHex(sb, data, 0, 4); sb.append('-'); + toHex(sb, data, 4, 2); sb.append('-'); + toHex(sb, data, 6, 2); sb.append('-'); + toHex(sb, data, 8, 2); sb.append('-'); + toHex(sb, data, 10, 6); + return sb.toString(); + } + + private static char toHex(int i) { + return (char) (i < 10 ? i + '0' : (i - 10) + 'A'); + } + + private static void toHex(StringBuilder sb, byte[] array, int offset, + int length) + { + for (int i = offset; i < offset + length; ++i) { + sb.append(toHex((array[i] >> 4) & 0xf)); + sb.append(toHex((array[i] ) & 0xf)); + } + } +} diff --git a/sgx-jvm/avian/classpath/java/util/Vector.java b/sgx-jvm/avian/classpath/java/util/Vector.java new file mode 100644 index 0000000000..3b8a9d831a --- /dev/null +++ b/sgx-jvm/avian/classpath/java/util/Vector.java @@ -0,0 +1,137 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.util; + +public class Vector extends AbstractList implements java.io.Serializable, Cloneable, RandomAccess { + private final ArrayList list; + + public Vector(int capacity) { + list = new ArrayList(capacity); + } + + public Vector() { + this(0); + } + + public Vector(Collection source) { + list = new ArrayList(source); + } + + public synchronized int size() { + return list.size(); + } + + public synchronized boolean contains(Object element) { + return list.contains(element); + } + + public synchronized void add(int index, T element) { + list.add(index, element); + } + + public void insertElementAt(T element, int index) { + add(index, element); + } + + public synchronized boolean add(T element) { + return list.add(element); + } + + public synchronized boolean addAll(Collection collection) { + return list.addAll(collection); + } + + public void addElement(T element) { + add(element); + } + + public synchronized T get(int index) { + return list.get(index); + } + + public synchronized T set(int index, T value) { + return list.set(index, value); + } + + public void setElementAt(T value, int index) { + set(index, value); + } + + public T elementAt(int index) { + return get(index); + } + + public synchronized T remove(int index) { + return list.remove(index); + } + + public synchronized boolean isEmpty() { + return list.isEmpty(); + } + + public void removeElementAt(int index) { + remove(index); + } + + public synchronized void removeAllElements() { + list.clear(); + } + + public synchronized boolean remove(Object element) { + return list.remove(element); + } + + public boolean removeElement(T element) { + return remove(element); + } + + public synchronized void clear() { + list.clear(); + } + + public synchronized int indexOf(Object element) { + return list.indexOf(element); + } + + public synchronized int lastIndexOf(Object element) { + return list.lastIndexOf(element); + } + + public synchronized void copyInto(Object[] array) { + for (int i = 0; i < size(); ++i) { + array[i] = list.get(i); + } + } + + public Iterator iterator() { + return listIterator(); + } + + public ListIterator listIterator(int index) { + return new Collections.ArrayListIterator(this, index); + } + + public ListIterator listIterator() { + return listIterator(0); + } + + public Enumeration elements() { + return new Collections.IteratorEnumeration(iterator()); + } + + public synchronized Object clone() { + Vector copy = new Vector(size()); + for (T t : this) { + copy.add(t); + } + return copy; + } +} diff --git a/sgx-jvm/avian/classpath/java/util/WeakHashMap.java b/sgx-jvm/avian/classpath/java/util/WeakHashMap.java new file mode 100644 index 0000000000..6cdd19f53c --- /dev/null +++ b/sgx-jvm/avian/classpath/java/util/WeakHashMap.java @@ -0,0 +1,143 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.util; + +import java.lang.ref.ReferenceQueue; +import java.lang.ref.Reference; +import java.lang.ref.WeakReference; + +public class WeakHashMap implements Map { + private final HashMap map; + private final ReferenceQueue queue; + + public WeakHashMap(int capacity) { + map = new HashMap(capacity, new MyHelper()); + queue = new ReferenceQueue(); + } + + public WeakHashMap() { + this(0); + } + + private void poll() { + for (MyCell c = (MyCell) queue.poll(); + c != null; + c = (MyCell) queue.poll()) + { + map.remove(c); + } + } + + public boolean isEmpty() { + return map.isEmpty(); + } + + public int size() { + return map.size(); + } + + public boolean containsKey(Object key) { + poll(); + return map.containsKey(key); + } + + public boolean containsValue(Object value) { + poll(); + return map.containsValue(value); + } + + public V get(Object key) { + poll(); + return map.get(key); + } + + public V put(K key, V value) { + poll(); + return map.put(key, value); + } + + public void putAll(Map elts) { + map.putAll(elts); + } + + public V remove(Object key) { + poll(); + return map.remove(key); + } + + public void clear() { + map.clear(); + } + + public Set> entrySet() { + return map.entrySet(); + } + + public Set keySet() { + return map.keySet(); + } + + public Collection values() { + return map.values(); + } + + private static class MyCell + extends WeakReference + implements HashMap.Cell + { + public V value; + public HashMap.Cell next; + public int hashCode; + + public MyCell(K key, ReferenceQueue queue, V value, + HashMap.Cell next, int hashCode) + { + super(key, queue); + this.value = value; + this.next = next; + this.hashCode = hashCode; + } + + public K getKey() { + return get(); + } + + public V getValue() { + return value; + } + + public V setValue(V value) { + V old = this.value; + this.value = value; + return old; + } + + public HashMap.Cell next() { + return next; + } + + public void setNext(HashMap.Cell next) { + this.next = next; + } + + public int hashCode() { + return hashCode; + } + } + + private class MyHelper + extends HashMap.MyHelper + { + public HashMap.Cell make(K key, V value, HashMap.Cell next) { + return new MyCell(key, queue, value, next, hash(key)); + } + } +} diff --git a/sgx-jvm/avian/classpath/java/util/concurrent/BlockingDeque.java b/sgx-jvm/avian/classpath/java/util/concurrent/BlockingDeque.java new file mode 100644 index 0000000000..156d6d469c --- /dev/null +++ b/sgx-jvm/avian/classpath/java/util/concurrent/BlockingDeque.java @@ -0,0 +1,23 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.util.concurrent; + +import java.util.Deque; + +public interface BlockingDeque extends Deque, BlockingQueue { + public T takeFirst() throws InterruptedException; + + public T takeLast() throws InterruptedException; + + public T pollFirst(long timeout, TimeUnit unit) throws InterruptedException; + + public T pollLast(long timeout, TimeUnit unit) throws InterruptedException; +} diff --git a/sgx-jvm/avian/classpath/java/util/concurrent/BlockingQueue.java b/sgx-jvm/avian/classpath/java/util/concurrent/BlockingQueue.java new file mode 100644 index 0000000000..e5a2479f59 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/util/concurrent/BlockingQueue.java @@ -0,0 +1,30 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.util.concurrent; + +import java.util.Collection; +import java.util.Queue; + +public interface BlockingQueue extends Queue { + public void put(T e) throws InterruptedException; + + public boolean offer(T e, long timeout, TimeUnit unit) throws InterruptedException; + + public T take() throws InterruptedException; + + public T poll(long timeout, TimeUnit unit) throws InterruptedException; + + public int remainingCapacity(); + + public int drainTo(Collection c); + + public int drainTo(Collection c, int maxElements); +} diff --git a/sgx-jvm/avian/classpath/java/util/concurrent/Callable.java b/sgx-jvm/avian/classpath/java/util/concurrent/Callable.java new file mode 100644 index 0000000000..8ffca41fec --- /dev/null +++ b/sgx-jvm/avian/classpath/java/util/concurrent/Callable.java @@ -0,0 +1,15 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.util.concurrent; + +public interface Callable { + public T call() throws Exception; +} diff --git a/sgx-jvm/avian/classpath/java/util/concurrent/CancellationException.java b/sgx-jvm/avian/classpath/java/util/concurrent/CancellationException.java new file mode 100644 index 0000000000..866ab4a7a3 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/util/concurrent/CancellationException.java @@ -0,0 +1,23 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.util.concurrent; + +public class CancellationException extends IllegalStateException { + private static final long serialVersionUID = -9202173006928992231L; + + public CancellationException() { + super(); + } + + public CancellationException(String message) { + super(message); + } +} diff --git a/sgx-jvm/avian/classpath/java/util/concurrent/CompletionService.java b/sgx-jvm/avian/classpath/java/util/concurrent/CompletionService.java new file mode 100644 index 0000000000..1c671c7590 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/util/concurrent/CompletionService.java @@ -0,0 +1,23 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.util.concurrent; + +public interface CompletionService { + public Future submit(Callable task); + + public Future submit(Runnable task, T result); + + public Future take() throws InterruptedException; + + public Future poll(); + + public Future poll(long timeout, TimeUnit unit) throws InterruptedException; +} diff --git a/sgx-jvm/avian/classpath/java/util/concurrent/ConcurrentHashMap.java b/sgx-jvm/avian/classpath/java/util/concurrent/ConcurrentHashMap.java new file mode 100644 index 0000000000..abb0713525 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/util/concurrent/ConcurrentHashMap.java @@ -0,0 +1,438 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.util.concurrent; + +import avian.Data; +import avian.PersistentSet; +import avian.PersistentSet.Path; + +import sun.misc.Unsafe; +import java.util.AbstractMap; +import java.util.Map; +import java.util.Set; +import java.util.Collection; +import java.util.Iterator; +import java.util.NoSuchElementException; + +public class ConcurrentHashMap + extends AbstractMap + implements ConcurrentMap +{ + private static final Unsafe unsafe = Unsafe.getUnsafe(); + private static final long Content; + private static final Content Empty = new Content(new PersistentSet(), 0); + + static { + try { + Content = unsafe.objectFieldOffset + (ConcurrentHashMap.class.getDeclaredField("content")); + } catch (NoSuchFieldException e) { + throw new Error(e); + } + } + + private volatile Content content; + + public ConcurrentHashMap() { + content = Empty; + } + + public ConcurrentHashMap(int initialCapacity) { + this(); + } + + public ConcurrentHashMap(int initialCapacity, float loadFactor) { + this(); + } + + public ConcurrentHashMap(int initialCapacity, float loadFactor, int concurrencyLevel) { + this(); + } + + public boolean isEmpty() { + return content.size == 0; + } + + public int size() { + return content.size; + } + + public boolean containsKey(Object key) { + return find(key) != null; + } + + public boolean containsValue(Object value) { + for (V v: values()) { + if (value.equals(v)) { + return true; + } + } + return false; + } + + public V get(Object key) { + Cell cell = find(key); + return cell == null ? null : cell.value; + } + + private Cell find(Object key) { + Content c = content; + + Path>> path = c.set.find(new Node(key.hashCode())); + for (Cell cell = path.value().value; + cell != null; + cell = cell.next) + { + if (key.equals(cell.key)) { + return cell; + } + } + return null; + } + + public V putIfAbsent(K key, V value) { + Cell cell = put(key, value, PutCondition.IfAbsent, null); + return cell == null ? null : cell.value; + } + + public boolean remove(K key, V value) { + Cell cell = remove(key, RemoveCondition.IfEqual, value); + return cell != null && cell.value.equals(value); + } + + public V replace(K key, V value) { + Cell cell = put(key, value, PutCondition.IfPresent, null); + return cell == null ? null : cell.value; + } + + public boolean replace(K key, V oldValue, V newValue) { + Cell cell = put(key, newValue, PutCondition.IfEqual, oldValue); + return cell != null && cell.value.equals(oldValue); + } + + public V put(K key, V value) { + Cell cell = put(key, value, PutCondition.Always, null); + return cell == null ? null : cell.value; + } + + public V remove(Object key) { + Cell cell = remove(key, RemoveCondition.Always, null); + return cell == null ? null : cell.value; + } + + private enum PutCondition { + Always() { + public boolean addIfAbsent() { return true; } + public boolean addIfPresent(V a, V b) { return true; } + }, IfAbsent() { + public boolean addIfAbsent() { return true; } + public boolean addIfPresent(V a, V b) { return false; } + }, IfPresent() { + public boolean addIfAbsent() { return false; } + public boolean addIfPresent(V a, V b) { return true; } + }, IfEqual() { + public boolean addIfAbsent() { return false; } + public boolean addIfPresent(V a, V b) { return a.equals(b); } + }; + + public boolean addIfAbsent() { throw new AssertionError(); } + public boolean addIfPresent(V a, V b) { throw new AssertionError(); } + } + + private enum RemoveCondition { + Always() { + public boolean remove(V a, V b) { return true; } + }, IfEqual() { + public boolean remove(V a, V b) { return a.equals(b); } + }; + + public boolean remove(V a, V b) { throw new AssertionError(); } + } + + private Cell put(K key, V value, PutCondition condition, V oldValue) { + Node> node = new Node(key.hashCode()); + + loop: while (true) { + node.value = null; + Content content = this.content; + Path>> path = content.set.find(node); + for (Cell cell = path.value().value; + cell != null; + cell = cell.next) + { + if (key.equals(cell.key)) { + if (! condition.addIfPresent(cell.value, oldValue)) { + return cell; + } + + Cell start = null; + Cell last = null; + for (Cell cell2 = path.value().value; + true; + cell2 = cell2.next) + { + Cell c; + c = cell2.clone(); + + if (last == null) { + last = start = c; + } else { + last.next = c; + last = c; + } + + if (cell2 == cell) { + c.value = value; + break; + } + } + + node.value = start; + if (unsafe.compareAndSwapObject + (this, Content, content, new Content + (path.replaceWith(node), content.size))) + { + return cell; + } else { + continue loop; + } + } + } + + // no mapping found -- add a new one if appropriate + if (! condition.addIfAbsent()) { + return null; + } + + node.value = new Cell(key, value, null); + if (unsafe.compareAndSwapObject + (this, Content, content, new Content + (path.fresh() ? path.add() : path.replaceWith(node), + content.size + 1))) + { + return null; + } + } + } + + public void putAll(Map map) { + for (Map.Entry e: map.entrySet()) { + put(e.getKey(), e.getValue()); + } + } + + private Cell remove(Object key, RemoveCondition condition, + V oldValue) + { + Node> node = new Node(key.hashCode()); + + loop: while (true) { + node.value = null; + Content content = this.content; + Path>> path = content.set.find(node); + for (Cell cell = path.value().value; + cell != null; + cell = cell.next) + { + if (key.equals(cell.key)) { + if (! condition.remove(cell.value, oldValue)) { + return cell; + } + + Cell start = null; + Cell last = null; + for (Cell cell2 = path.value().value; + cell2 != cell; + cell2 = cell2.next) + { + Cell c = cell2.clone(); + if (last == null) { + last = start = c; + } else { + last.next = c; + last = c; + } + } + + if (last == null) { + start = last = cell.next; + } else { + last.next = cell.next; + } + + node.value = start; + if (unsafe.compareAndSwapObject + (this, Content, content, new Content + (start == null ? path.remove() : path.replaceWith(node), + content.size - 1))) + { + return cell; + } else { + continue loop; + } + } + } + + return null; + } + } + + public void clear() { + content = Empty; + } + + public Set> entrySet() { + return new Data.EntrySet(new MyEntryMap()); + } + + public Set keySet() { + return new Data.KeySet(new MyEntryMap()); + } + + public Collection values() { + return new Data.Values(new MyEntryMap()); + } + + private class MyEntryMap implements Data.EntryMap { + public int size() { + return ConcurrentHashMap.this.size(); + } + + public Map.Entry find(Object key) { + return new MyEntry(ConcurrentHashMap.this.find(key)); + } + + public Map.Entry remove(Object key) { + return new MyEntry + (ConcurrentHashMap.this.remove(key, RemoveCondition.Always, null)); + } + + public void clear() { + ConcurrentHashMap.this.clear(); + } + + public Iterator> iterator() { + return new MyIterator(content); + } + } + + private static class Content { + private final PersistentSet>> set; + private final int size; + + public Content(PersistentSet>> set, + int size) + { + this.set = set; + this.size = size; + } + } + + private static class Cell implements Cloneable { + public final K key; + public V value; + public Cell next; + + public Cell(K key, V value, Cell next) { + this.key = key; + this.value = value; + this.next = next; + } + + public Cell clone() { + try { + return (Cell) super.clone(); + } catch (CloneNotSupportedException e) { + throw new AssertionError(); + } + } + } + + private static class Node implements Comparable> { + public final int key; + public T value; + + public Node(int key) { + this.key = key; + } + + public int compareTo(Node n) { + return key - n.key; + } + } + + private class MyEntry implements Map.Entry { + private final K key; + private V value; + + public MyEntry(Cell cell) { + key = cell.key; + value = cell.value; + } + + public K getKey() { + return key; + } + + public V getValue() { + return value; + } + + public V setValue(V value) { + V v = value; + this.value = value; + put(key, value); + return v; + } + } + + private class MyIterator implements Iterator> { + private final Content content; + private final Iterator>> iterator; + private Cell currentCell; + private Cell nextCell; + + public MyIterator(Content content) { + this.content = content; + this.iterator = content.set.iterator(); + hasNext(); + } + + public Map.Entry next() { + if (hasNext()) { + currentCell = nextCell; + + nextCell = nextCell.next; + + return new MyEntry(currentCell); + } else { + throw new NoSuchElementException(); + } + } + + public boolean hasNext() { + if (nextCell == null && iterator.hasNext()) { + nextCell = iterator.next().value; + } + return nextCell != null; + } + + public void remove() { + if (currentCell != null) { + ConcurrentHashMap.this.remove + (currentCell.key, RemoveCondition.Always, null); + currentCell = null; + } else { + throw new IllegalStateException(); + } + } + } +} diff --git a/sgx-jvm/avian/classpath/java/util/concurrent/ConcurrentLinkedQueue.java b/sgx-jvm/avian/classpath/java/util/concurrent/ConcurrentLinkedQueue.java new file mode 100644 index 0000000000..21c64cff2c --- /dev/null +++ b/sgx-jvm/avian/classpath/java/util/concurrent/ConcurrentLinkedQueue.java @@ -0,0 +1,171 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.util.concurrent; + +import java.util.AbstractQueue; +import java.util.Collection; +import java.util.Iterator; + +import avian.Atomic; + +public class ConcurrentLinkedQueue extends AbstractQueue { + private static final long QueueHead; + private static final long QueueTail; + private static final long NodeNext; + + static { + try { + QueueHead = Atomic.getOffset + (ConcurrentLinkedQueue.class.getField("head")); + + QueueTail = Atomic.getOffset + (ConcurrentLinkedQueue.class.getField("tail")); + + NodeNext = Atomic.getOffset + (Node.class.getField("next")); + } catch (NoSuchFieldException e) { + throw new RuntimeException(e); + } + } + + private volatile Node head = new Node(null, null); + private volatile Node tail = head; + + @Override + public void clear() { + // TODO - can we safely make this O(1)? + while (poll() != null) { } + } + + @Override + public boolean offer(T element) { + add(element); + + return true; + } + + @Override + public boolean add(T value) { + Node n = new Node(value, null); + while (true) { + Node t = tail; + Node next = tail.next; + if (t == tail) { + if (next != null) { + Atomic.compareAndSwapObject(this, QueueTail, t, next); + } else if (Atomic.compareAndSwapObject(tail, NodeNext, null, n)) { + Atomic.compareAndSwapObject(this, QueueTail, t, n); + break; + } + } + } + + return true; + } + + @Override + public T peek() { + return poll(false); + } + + @Override + public T poll() { + return poll(true); + } + + private T poll(boolean remove) { + while (true) { + Node h = head; + Node t = tail; + Node next = head.next; + + if (h == head) { + if (h == t) { + if (next != null) { + Atomic.compareAndSwapObject(this, QueueTail, t, next); + } else { + return null; + } + } else { + T value = next.value; + if ((! remove) + || Atomic.compareAndSwapObject(this, QueueHead, h, next)) + { + return value; + } + } + } + } + } + + private static class Node { + public volatile T value; + public volatile Node next; + + public Node(T value, Node next) { + this.value = value; + this.next = next; + } + } + + @Override + public int size() { + // TODO - implement + throw new UnsupportedOperationException(); + } + + @Override + public boolean isEmpty() { + return size() == 0; + } + + @Override + public boolean contains(Object element) { + // TODO - implement + throw new UnsupportedOperationException(); + } + + @Override + public boolean containsAll(Collection c) { + // TODO - implement + throw new UnsupportedOperationException(); + } + + @Override + public boolean remove(Object element) { + // TODO - implement + throw new UnsupportedOperationException(); + } + + @Override + public boolean removeAll(Collection c) { + // TODO - implement + throw new UnsupportedOperationException(); + } + + @Override + public Object[] toArray() { + // TODO - implement + throw new UnsupportedOperationException(); + } + + @Override + public S[] toArray(S[] array) { + // TODO - implement + throw new UnsupportedOperationException(); + } + + @Override + public Iterator iterator() { + // TODO - implement + throw new UnsupportedOperationException(); + } +} diff --git a/sgx-jvm/avian/classpath/java/util/concurrent/ConcurrentMap.java b/sgx-jvm/avian/classpath/java/util/concurrent/ConcurrentMap.java new file mode 100644 index 0000000000..9328320eaa --- /dev/null +++ b/sgx-jvm/avian/classpath/java/util/concurrent/ConcurrentMap.java @@ -0,0 +1,23 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.util.concurrent; + +import java.util.Map; + +public interface ConcurrentMap extends Map { + public V putIfAbsent(K key, V value); + + public boolean remove(K key, V value); + + public V replace(K key, V value); + + public boolean replace(K key, V oldValue, V newValue); +} diff --git a/sgx-jvm/avian/classpath/java/util/concurrent/Delayed.java b/sgx-jvm/avian/classpath/java/util/concurrent/Delayed.java new file mode 100644 index 0000000000..0c7368ee62 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/util/concurrent/Delayed.java @@ -0,0 +1,15 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.util.concurrent; + +public interface Delayed extends Comparable { + public long getDelay(TimeUnit unit); +} diff --git a/sgx-jvm/avian/classpath/java/util/concurrent/ExecutionException.java b/sgx-jvm/avian/classpath/java/util/concurrent/ExecutionException.java new file mode 100644 index 0000000000..7f6560b26e --- /dev/null +++ b/sgx-jvm/avian/classpath/java/util/concurrent/ExecutionException.java @@ -0,0 +1,31 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.util.concurrent; + +public class ExecutionException extends Exception { + private static final long serialVersionUID = 7830266012832686185L; + + protected ExecutionException() { + super(); + } + + protected ExecutionException(String message) { + super(message); + } + + public ExecutionException(String message, Throwable cause) { + super(message, cause); + } + + public ExecutionException(Throwable cause) { + super(cause); + } +} diff --git a/sgx-jvm/avian/classpath/java/util/concurrent/Executor.java b/sgx-jvm/avian/classpath/java/util/concurrent/Executor.java new file mode 100644 index 0000000000..cd9f5d4b27 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/util/concurrent/Executor.java @@ -0,0 +1,15 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.util.concurrent; + +public interface Executor { + public void execute(Runnable task); +} diff --git a/sgx-jvm/avian/classpath/java/util/concurrent/ExecutorCompletionService.java b/sgx-jvm/avian/classpath/java/util/concurrent/ExecutorCompletionService.java new file mode 100644 index 0000000000..f08ef9960d --- /dev/null +++ b/sgx-jvm/avian/classpath/java/util/concurrent/ExecutorCompletionService.java @@ -0,0 +1,73 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.util.concurrent; + +public class ExecutorCompletionService implements CompletionService { + private final Executor executor; + private final BlockingQueue> completionQueue; + + public ExecutorCompletionService(Executor executor) { + this(executor, new LinkedBlockingQueue>()); + } + + public ExecutorCompletionService(Executor executor, BlockingQueue> completionQueue) { + this.executor = executor; + this.completionQueue = completionQueue; + } + + @Override + public Future submit(Callable task) { + ECSFuture f = new ECSFuture(task); + + executor.execute(f); + + return f; + } + + @Override + public Future submit(Runnable task, T result) { + ECSFuture f = new ECSFuture(task, result); + + executor.execute(f); + + return f; + } + + @Override + public Future take() throws InterruptedException { + return completionQueue.take(); + } + + @Override + public Future poll() { + return completionQueue.poll(); + } + + @Override + public Future poll(long timeout, TimeUnit unit) throws InterruptedException { + return completionQueue.poll(timeout, unit); + } + + private class ECSFuture extends FutureTask implements Future { + private ECSFuture(Runnable r, T result) { + super(r, result); + } + + private ECSFuture(Callable callable) { + super(callable); + } + + @Override + protected void done() { + completionQueue.add(this); + } + } +} diff --git a/sgx-jvm/avian/classpath/java/util/concurrent/ExecutorService.java b/sgx-jvm/avian/classpath/java/util/concurrent/ExecutorService.java new file mode 100644 index 0000000000..15556bff4c --- /dev/null +++ b/sgx-jvm/avian/classpath/java/util/concurrent/ExecutorService.java @@ -0,0 +1,41 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.util.concurrent; +import java.util.List; +import java.util.Collection; + +public interface ExecutorService extends Executor { + public void shutdown(); + + public List shutdownNow(); + + public boolean isShutdown(); + + public boolean isTerminated(); + + public boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException; + + public Future submit(Callable task); + + public Future submit(Runnable task, T result); + + public Future submit(Runnable task); + + public List> invokeAll(Collection> tasks) throws InterruptedException; + + public List> invokeAll(Collection> tasks, + long timeout, TimeUnit unit) throws InterruptedException; + + public T invokeAny(Collection> tasks) throws InterruptedException, ExecutionException; + + public T invokeAny(Collection> tasks, + long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException; +} diff --git a/sgx-jvm/avian/classpath/java/util/concurrent/Executors.java b/sgx-jvm/avian/classpath/java/util/concurrent/Executors.java new file mode 100644 index 0000000000..96496b5c99 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/util/concurrent/Executors.java @@ -0,0 +1,24 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.util.concurrent; + +public class Executors { + public static Callable callable(final Runnable task, final T result) { + return new Callable() { + @Override + public T call() throws Exception { + task.run(); + + return result; + } + }; + } +} diff --git a/sgx-jvm/avian/classpath/java/util/concurrent/Future.java b/sgx-jvm/avian/classpath/java/util/concurrent/Future.java new file mode 100644 index 0000000000..93c219b81c --- /dev/null +++ b/sgx-jvm/avian/classpath/java/util/concurrent/Future.java @@ -0,0 +1,25 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.util.concurrent; + +public interface Future { + public boolean cancel(boolean mayInterruptIfRunning); + + public boolean isCancelled(); + + public boolean isDone(); + + public V get() throws InterruptedException, ExecutionException; + + public V get(long timeout, TimeUnit unit) throws InterruptedException, + ExecutionException, + TimeoutException; +} diff --git a/sgx-jvm/avian/classpath/java/util/concurrent/FutureTask.java b/sgx-jvm/avian/classpath/java/util/concurrent/FutureTask.java new file mode 100644 index 0000000000..967d2c8a1d --- /dev/null +++ b/sgx-jvm/avian/classpath/java/util/concurrent/FutureTask.java @@ -0,0 +1,169 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.util.concurrent; + +import java.util.concurrent.atomic.AtomicReference; + +public class FutureTask implements RunnableFuture { + private enum State { New, Canceling, Canceled, Running, Done }; + + private final AtomicReference currentState; + private final Callable callable; + private final Object notifyLock; + private volatile Thread runningThread; + private volatile T result; + private volatile Throwable failure; + + public FutureTask(final Runnable r, final T result) { + this(new Callable() { + @Override + public T call() { + r.run(); + + return result; + } + }); + } + + public FutureTask(Callable callable) { + currentState = new AtomicReference(State.New); + this.callable = callable; + notifyLock = new Object(); + runningThread = null; + result = null; + failure = null; + } + + @Override + public void run() { + if (currentState.compareAndSet(State.New, State.Running)) { + runningThread = Thread.currentThread(); + try { + result = callable.call(); + } catch (Throwable t) { + failure = t; + } finally { + if (currentState.compareAndSet(State.Running, State.Done) || + currentState.get() == State.Canceled) { + /* in either of these conditions we either were not canceled + * or we already were interrupted. The thread may or MAY NOT + * be in an interrupted status depending on when it was + * interrupted and what the callable did with the state. + */ + } else { + /* Should be in canceling state, so block forever till we are + * interrupted. If state already transitioned into canceled + * and thus thread is in interrupted status, the exception should + * throw immediately on the sleep call. + */ + try { + Thread.sleep(Long.MAX_VALUE); + } catch (InterruptedException e) { + // expected + } + } + + Thread.interrupted(); // reset interrupted status if set + handleDone(); + runningThread = null; // must be last operation + } + } + } + + private void handleDone() { + done(); + + synchronized (notifyLock) { + notifyLock.notifyAll(); + } + } + + protected void done() { + // default implementation does nothing, designed to be overridden + } + + @Override + public boolean cancel(boolean mayInterruptIfRunning) { + if (currentState.compareAndSet(State.New, State.Canceled)) { + handleDone(); + + return true; + } else if (mayInterruptIfRunning && + currentState.compareAndSet(State.Running, State.Canceling)) { + // handleDone will be called from running thread + try { + Thread runningThread = this.runningThread; + if (runningThread != null) { + runningThread.interrupt(); + + return true; + } + } finally { + // we can not set to canceled until interrupt status has been set + currentState.set(State.Canceled); + } + } + + return false; + } + + @Override + public boolean isCancelled() { + return currentState.get() == State.Canceled; + } + + @Override + public boolean isDone() { + return currentState.get() == State.Done || isCancelled(); + } + + @Override + public T get() throws InterruptedException, ExecutionException { + try { + return get(Long.MAX_VALUE, TimeUnit.MILLISECONDS); + } catch (TimeoutException e) { + // not possible + throw new RuntimeException(e); + } + } + + @Override + public T get(long timeout, TimeUnit unit) throws InterruptedException, + ExecutionException, + TimeoutException { + long timeoutInMillis = unit.toMillis(timeout); + long startTime = 0; + if (timeoutInMillis < Long.MAX_VALUE) { + startTime = System.currentTimeMillis(); + } + long remainingTime; + synchronized (notifyLock) { + remainingTime = timeoutInMillis; + while (! isDone() && remainingTime > 0) { + notifyLock.wait(remainingTime); + + if (timeoutInMillis < Long.MAX_VALUE) { + remainingTime = timeoutInMillis - (System.currentTimeMillis() - startTime); + } + } + } + + if (remainingTime <= 0) { + throw new TimeoutException(); + } else if (currentState.get() == State.Canceled) { + throw new CancellationException(); + } else if (failure != null) { + throw new ExecutionException(failure); + } else { + return result; + } + } +} diff --git a/sgx-jvm/avian/classpath/java/util/concurrent/LinkedBlockingQueue.java b/sgx-jvm/avian/classpath/java/util/concurrent/LinkedBlockingQueue.java new file mode 100644 index 0000000000..49be16ccb6 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/util/concurrent/LinkedBlockingQueue.java @@ -0,0 +1,302 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.util.concurrent; + +import java.util.AbstractQueue; +import java.util.Collection; +import java.util.Iterator; +import java.util.LinkedList; + +public class LinkedBlockingQueue extends AbstractQueue + implements BlockingQueue { + private final Object collectionLock; + private final LinkedList storage; + private final int capacity; + + public LinkedBlockingQueue() { + this(Integer.MAX_VALUE); + } + + public LinkedBlockingQueue(int capacity) { + collectionLock = new Object(); + this.capacity = capacity; + storage = new LinkedList(); + } + + // should be synchronized on collectionLock before calling + private void handleRemove() { + collectionLock.notifyAll(); + } + + // should be synchronized on collectionLock before calling + private void handleAdd() { + collectionLock.notifyAll(); + } + + // should be synchronized on collectionLock before calling + private void blockTillNotFull() throws InterruptedException { + blockTillNotFull(Long.MAX_VALUE); + } + + // should be synchronized on collectionLock before calling + private void blockTillNotFull(long maxWaitInMillis) throws InterruptedException { + if (capacity > storage.size()) { + return; + } + + long startTime = 0; + if (maxWaitInMillis != Long.MAX_VALUE) { + startTime = System.currentTimeMillis(); + } + long remainingWait = maxWaitInMillis; + while (remainingWait > 0) { + collectionLock.wait(remainingWait); + + if (capacity > storage.size()) { + return; + } else if (maxWaitInMillis != Long.MAX_VALUE) { + remainingWait = maxWaitInMillis - (System.currentTimeMillis() - startTime); + } + } + } + + // should be synchronized on collectionLock before calling + private void blockTillNotEmpty() throws InterruptedException { + blockTillNotEmpty(Long.MAX_VALUE); + } + + // should be synchronized on collectionLock before calling + private void blockTillNotEmpty(long maxWaitInMillis) throws InterruptedException { + if (! storage.isEmpty()) { + return; + } + + long startTime = 0; + if (maxWaitInMillis != Long.MAX_VALUE) { + startTime = System.currentTimeMillis(); + } + long remainingWait = maxWaitInMillis; + while (remainingWait > 0) { + collectionLock.wait(remainingWait); + + if (! storage.isEmpty()) { + return; + } else if (maxWaitInMillis != Long.MAX_VALUE) { + remainingWait = maxWaitInMillis - (System.currentTimeMillis() - startTime); + } + } + } + + @Override + public boolean offer(T element) { + synchronized (collectionLock) { + if (capacity > storage.size()) { + storage.addLast(element); + + handleAdd(); + + return true; + } else { + return false; + } + } + } + + @Override + public boolean offer(T e, long timeout, TimeUnit unit) throws InterruptedException { + long timeoutInMillis = unit.toMillis(timeout); + synchronized (collectionLock) { + // block till we can add or have reached timeout + blockTillNotFull(timeoutInMillis); + + return offer(e); + } + } + + @Override + public void put(T e) throws InterruptedException { + synchronized (collectionLock) { + // block till we have space + blockTillNotFull(); + + storage.add(e); + handleAdd(); + } + } + + @Override + public boolean addAll(Collection c) { + synchronized (collectionLock) { + if (storage.size() + c.size() > capacity) { + throw new IllegalStateException("Not enough space"); + } + + if (c.isEmpty()) { + return false; + } else { + storage.addAll(c); + + return true; + } + } + } + + @Override + public T peek() { + synchronized (collectionLock) { + if (storage.isEmpty()) { + return null; + } else { + return storage.getFirst(); + } + } + } + + // should be synchronized on collectionLock before calling + private T removeFirst() { + T result = storage.removeFirst(); + handleRemove(); + + return result; + } + + @Override + public T poll() { + synchronized (collectionLock) { + if (storage.isEmpty()) { + return null; + } else { + return removeFirst(); + } + } + } + + @Override + public T poll(long timeout, TimeUnit unit) throws InterruptedException { + long timeoutInMillis = unit.toMillis(timeout); + synchronized (collectionLock) { + // block till we available or timeout + blockTillNotEmpty(timeoutInMillis); + + return poll(); + } + } + + @Override + public T take() throws InterruptedException { + synchronized (collectionLock) { + // block till we available + blockTillNotEmpty(); + + return removeFirst(); + } + } + + @Override + public int drainTo(Collection c) { + return drainTo(c, Integer.MAX_VALUE); + } + + @Override + public int drainTo(Collection c, int maxElements) { + int remainingElements = maxElements; + synchronized (collectionLock) { + while (remainingElements > 0 && ! storage.isEmpty()) { + c.add(storage.removeFirst()); + remainingElements--; + } + + if (remainingElements != maxElements) { + handleRemove(); + } + + return maxElements - remainingElements; + } + } + + @Override + public int remainingCapacity() { + synchronized (collectionLock) { + return capacity - storage.size(); + } + } + + @Override + public int size() { + synchronized (collectionLock) { + return storage.size(); + } + } + + @Override + public boolean contains(Object element) { + synchronized (collectionLock) { + return storage.contains(element); + } + } + + @Override + public boolean containsAll(Collection c) { + synchronized (collectionLock) { + return storage.containsAll(c); + } + } + + @Override + public boolean remove(Object element) { + synchronized (collectionLock) { + if (storage.remove(element)) { + handleRemove(); + return true; + } else { + return false; + } + } + } + + @Override + public boolean removeAll(Collection c) { + synchronized (collectionLock) { + if (storage.removeAll(c)) { + handleRemove(); + return true; + } else { + return false; + } + } + } + + @Override + public void clear() { + synchronized (collectionLock) { + storage.clear(); + } + } + + @Override + public Object[] toArray() { + synchronized (collectionLock) { + return storage.toArray(); + } + } + + @Override + public S[] toArray(S[] array) { + synchronized (collectionLock) { + return storage.toArray(array); + } + } + + @Override + public Iterator iterator() { + throw new UnsupportedOperationException("Not implemented yet"); + } +} diff --git a/sgx-jvm/avian/classpath/java/util/concurrent/RejectedExecutionException.java b/sgx-jvm/avian/classpath/java/util/concurrent/RejectedExecutionException.java new file mode 100644 index 0000000000..e3230c1cd1 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/util/concurrent/RejectedExecutionException.java @@ -0,0 +1,31 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.util.concurrent; + +public class RejectedExecutionException extends RuntimeException { + private static final long serialVersionUID = -375805702767069545L; + + public RejectedExecutionException() { + super(); + } + + public RejectedExecutionException(String message) { + super(message); + } + + public RejectedExecutionException(String message, Throwable cause) { + super(message, cause); + } + + public RejectedExecutionException(Throwable cause) { + super(cause); + } +} diff --git a/sgx-jvm/avian/classpath/java/util/concurrent/RunnableFuture.java b/sgx-jvm/avian/classpath/java/util/concurrent/RunnableFuture.java new file mode 100644 index 0000000000..7b8b38cad6 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/util/concurrent/RunnableFuture.java @@ -0,0 +1,15 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.util.concurrent; + +public interface RunnableFuture extends Runnable, Future { + // nothing added to interface +} diff --git a/sgx-jvm/avian/classpath/java/util/concurrent/ScheduledExecutorService.java b/sgx-jvm/avian/classpath/java/util/concurrent/ScheduledExecutorService.java new file mode 100644 index 0000000000..d0cba8caed --- /dev/null +++ b/sgx-jvm/avian/classpath/java/util/concurrent/ScheduledExecutorService.java @@ -0,0 +1,29 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.util.concurrent; + +public interface ScheduledExecutorService extends ExecutorService { + public ScheduledFuture schedule(Runnable command, + long delay, TimeUnit unit); + + public ScheduledFuture schedule(Callable callable, + long delay, TimeUnit unit); + + public ScheduledFuture scheduleAtFixedRate(Runnable command, + long initialDelay, + long period, + TimeUnit unit); + + public ScheduledFuture scheduleWithFixedDelay(Runnable command, + long initialDelay, + long delay, + TimeUnit unit); +} diff --git a/sgx-jvm/avian/classpath/java/util/concurrent/ScheduledFuture.java b/sgx-jvm/avian/classpath/java/util/concurrent/ScheduledFuture.java new file mode 100644 index 0000000000..eb9ab4da01 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/util/concurrent/ScheduledFuture.java @@ -0,0 +1,15 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.util.concurrent; + +public interface ScheduledFuture extends Delayed, Future { + +} diff --git a/sgx-jvm/avian/classpath/java/util/concurrent/ThreadFactory.java b/sgx-jvm/avian/classpath/java/util/concurrent/ThreadFactory.java new file mode 100644 index 0000000000..ed7def9977 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/util/concurrent/ThreadFactory.java @@ -0,0 +1,15 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.util.concurrent; + +public interface ThreadFactory { + public Thread newThread(Runnable r); +} diff --git a/sgx-jvm/avian/classpath/java/util/concurrent/TimeUnit.java b/sgx-jvm/avian/classpath/java/util/concurrent/TimeUnit.java new file mode 100644 index 0000000000..3503d672b9 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/util/concurrent/TimeUnit.java @@ -0,0 +1,416 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.util.concurrent; + +public enum TimeUnit { + NANOSECONDS { + @Override + public long toNanos(long d) { + return d; + } + + @Override + public long toMicros(long d) { + return d / NANOSECONDS_PER_MICROSECOND; + } + + @Override + public long toMillis(long d) { + return d / NANOSECONDS_PER_MILLISECOND; + } + + @Override + public long toSeconds(long d) { + return d / NANOSECONDS_PER_SECOND; + } + + @Override + public long toMinutes(long d) { + return d / NANOSECONDS_PER_MINUTE; + } + + @Override + public long toHours(long d) { + return d / NANOSECONDS_PER_HOUR; + } + + @Override + public long toDays(long d) { + return d / NANOSECONDS_PER_DAY; + } + + @Override + public long convert(long d, TimeUnit u) { + return u.toNanos(d); + } + + @Override + int excessNanos(long d, long m) { + return (int) (d - (m * NANOSECONDS_PER_MILLISECOND)); + } + }, + MICROSECONDS { + @Override + public long toNanos(long d) { + return scale(d, NANOSECONDS_PER_MICROSECOND); + } + + @Override + public long toMicros(long d) { + return d; + } + + @Override + public long toMillis(long d) { + return d / MICROSECONDS_PER_MILLISECOND; + } + + @Override + public long toSeconds(long d) { + return d / MICROSECONDS_PER_SECOND; + } + + @Override + public long toMinutes(long d) { + return d / MICROSECONDS_PER_MINUTE; + } + + @Override + public long toHours(long d) { + return d / MICROSECONDS_PER_HOUR; + } + + @Override + public long toDays(long d) { + return d / MICROSECONDS_PER_DAY; + } + + @Override + public long convert(long d, TimeUnit u) { + return u.toMicros(d); + } + + @Override + int excessNanos(long d, long m) { + return (int) ((d * NANOSECONDS_PER_MICROSECOND) - (m * NANOSECONDS_PER_MILLISECOND)); + } + }, + MILLISECONDS { + @Override + public long toNanos(long d) { + return scale(d, NANOSECONDS_PER_MILLISECOND); + } + + @Override + public long toMicros(long d) { + return scale(d, MICROSECONDS_PER_MILLISECOND); + } + + @Override + public long toMillis(long d) { + return d; + } + + @Override + public long toSeconds(long d) { + return d / MILLISECONDS_PER_SECOND; + } + + @Override + public long toMinutes(long d) { + return d / MILLISECONDS_PER_MINUTE; + } + + @Override + public long toHours(long d) { + return d / MILLISECONDS_PER_HOUR; + } + + @Override + public long toDays(long d) { + return d / MILLISECONDS_PER_DAY; + } + + @Override + public long convert(long d, TimeUnit u) { + return u.toMillis(d); + } + + @Override + int excessNanos(long d, long m) { + return 0; + } + }, + SECONDS { + @Override + public long toNanos(long d) { + return scale(d, NANOSECONDS_PER_SECOND); + } + + @Override + public long toMicros(long d) { + return scale(d, MICROSECONDS_PER_SECOND); + } + + @Override + public long toMillis(long d) { + return scale(d, MILLISECONDS_PER_SECOND); + } + + @Override + public long toSeconds(long d) { + return d; + } + + @Override + public long toMinutes(long d) { + return d / SECONDS_PER_MINUTE; + } + + @Override + public long toHours(long d) { + return d / SECONDS_PER_HOUR; + } + + @Override + public long toDays(long d) { + return d / SECONDS_PER_DAY; + } + + @Override + public long convert(long d, TimeUnit u) { + return u.toSeconds(d); + } + + @Override + int excessNanos(long d, long m) { + return 0; + } + }, + MINUTES { + @Override + public long toNanos(long d) { + return scale(d, NANOSECONDS_PER_MINUTE); + } + + @Override + public long toMicros(long d) { + return scale(d, MICROSECONDS_PER_MINUTE); + } + + @Override + public long toMillis(long d) { + return scale(d, MILLISECONDS_PER_MINUTE); + } + + @Override + public long toSeconds(long d) { + return scale(d, SECONDS_PER_MINUTE); + } + + @Override + public long toMinutes(long d) { + return d; + } + + @Override + public long toHours(long d) { + return d / MINUETS_PER_HOUR; + } + + @Override + public long toDays(long d) { + return d / MINUETS_PER_DAY; + } + + @Override + public long convert(long d, TimeUnit u) { + return u.toMinutes(d); + } + + @Override + int excessNanos(long d, long m) { + return 0; + } + }, + HOURS { + @Override + public long toNanos(long d) { + return scale(d, NANOSECONDS_PER_HOUR); + } + + @Override + public long toMicros(long d) { + return scale(d, MICROSECONDS_PER_HOUR); + } + + @Override + public long toMillis(long d) { + return scale(d, MILLISECONDS_PER_HOUR); + } + + @Override + public long toSeconds(long d) { + return scale(d, SECONDS_PER_HOUR); + } + + @Override + public long toMinutes(long d) { + return scale(d, MINUETS_PER_HOUR); + } + + @Override + public long toHours(long d) { + return d; + } + + @Override + public long toDays(long d) { + return d / HOURS_PER_DAY; + } + + @Override + public long convert(long d, TimeUnit u) { + return u.toHours(d); + } + + @Override + int excessNanos(long d, long m) { + return 0; + } + }, + DAYS { + @Override + public long toNanos(long d) { + return scale(d, NANOSECONDS_PER_DAY); + } + + @Override + public long toMicros(long d) { + return scale(d, MICROSECONDS_PER_DAY); + } + + @Override + public long toMillis(long d) { + return scale(d, MILLISECONDS_PER_DAY); + } + + @Override + public long toSeconds(long d) { + return scale(d, SECONDS_PER_DAY); + } + + @Override + public long toMinutes(long d) { + return scale(d, MINUETS_PER_DAY); + } + + @Override + public long toHours(long d) { + return scale(d, HOURS_PER_DAY); + } + + @Override + public long toDays(long d) { + return d; + } + + @Override + public long convert(long d, TimeUnit u) { + return u.toDays(d); + } + + @Override + int excessNanos(long d, long m) { + return 0; + } + }; + + private static final long NANOSECONDS_PER_MICROSECOND = 1000L; + private static final long MICROSECONDS_PER_MILLISECOND = 1000L; + private static final long MILLISECONDS_PER_SECOND = 1000L; + private static final long SECONDS_PER_MINUTE = 60; + private static final long MINUETS_PER_HOUR = 60; + private static final long HOURS_PER_DAY = 24; + + private static final long NANOSECONDS_PER_MILLISECOND = NANOSECONDS_PER_MICROSECOND * MICROSECONDS_PER_MILLISECOND; + private static final long NANOSECONDS_PER_SECOND = NANOSECONDS_PER_MILLISECOND * MILLISECONDS_PER_SECOND; + private static final long NANOSECONDS_PER_MINUTE = NANOSECONDS_PER_SECOND * SECONDS_PER_MINUTE; + private static final long NANOSECONDS_PER_HOUR = NANOSECONDS_PER_MINUTE * MINUETS_PER_HOUR; + private static final long NANOSECONDS_PER_DAY = NANOSECONDS_PER_HOUR * HOURS_PER_DAY; + + private static final long MICROSECONDS_PER_SECOND = MICROSECONDS_PER_MILLISECOND * MILLISECONDS_PER_SECOND; + private static final long MICROSECONDS_PER_MINUTE = MICROSECONDS_PER_SECOND * SECONDS_PER_MINUTE; + private static final long MICROSECONDS_PER_HOUR = MICROSECONDS_PER_MINUTE * MINUETS_PER_HOUR; + private static final long MICROSECONDS_PER_DAY = MICROSECONDS_PER_HOUR * HOURS_PER_DAY; + + private static final long MILLISECONDS_PER_MINUTE = MILLISECONDS_PER_SECOND * SECONDS_PER_MINUTE; + private static final long MILLISECONDS_PER_HOUR = MILLISECONDS_PER_MINUTE * MINUETS_PER_HOUR; + private static final long MILLISECONDS_PER_DAY = MILLISECONDS_PER_HOUR * HOURS_PER_DAY; + + private static final long SECONDS_PER_HOUR = SECONDS_PER_MINUTE * MINUETS_PER_HOUR; + private static final long SECONDS_PER_DAY = SECONDS_PER_HOUR * HOURS_PER_DAY; + + private static final long MINUETS_PER_DAY = MINUETS_PER_HOUR * HOURS_PER_DAY; + + private static long scale(long value, long conversion) { + long result = value * conversion; + if (value > 0 && result < value) { + return Long.MAX_VALUE; + } else if (value < 0 && result > value) { + return Long.MIN_VALUE; + } else { + return result; + } + } + + public abstract long convert(long sourceDuration, TimeUnit sourceUnit); + + public abstract long toNanos(long duration); + + public abstract long toMicros(long duration); + + public abstract long toMillis(long duration); + + public abstract long toSeconds(long duration); + + public abstract long toMinutes(long duration); + + public abstract long toHours(long duration); + + public abstract long toDays(long duration); + + abstract int excessNanos(long d, long m); + + public void timedWait(Object obj, long timeout) throws InterruptedException { + if (timeout > 0) { + long ms = toMillis(timeout); + int ns = excessNanos(timeout, ms); + obj.wait(ms, ns); + } + } + + public void timedJoin(Thread thread, long timeout) throws InterruptedException { + if (timeout > 0) { + long ms = toMillis(timeout); + int ns = excessNanos(timeout, ms); + thread.join(ms, ns); + } + } + + public void sleep(long timeout) throws InterruptedException { + if (timeout > 0) { + long ms = toMillis(timeout); + int ns = excessNanos(timeout, ms); + Thread.sleep(ms, ns); + } + } +} diff --git a/sgx-jvm/avian/classpath/java/util/concurrent/TimeoutException.java b/sgx-jvm/avian/classpath/java/util/concurrent/TimeoutException.java new file mode 100644 index 0000000000..fcb62e5c8e --- /dev/null +++ b/sgx-jvm/avian/classpath/java/util/concurrent/TimeoutException.java @@ -0,0 +1,23 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.util.concurrent; + +public class TimeoutException extends Exception { + private static final long serialVersionUID = 1900926677490660714L; + + public TimeoutException() { + super(); + } + + public TimeoutException(String message) { + super(message); + } +} diff --git a/sgx-jvm/avian/classpath/java/util/concurrent/atomic/AtomicBoolean.java b/sgx-jvm/avian/classpath/java/util/concurrent/atomic/AtomicBoolean.java new file mode 100644 index 0000000000..fc7253f3fa --- /dev/null +++ b/sgx-jvm/avian/classpath/java/util/concurrent/atomic/AtomicBoolean.java @@ -0,0 +1,67 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.util.concurrent.atomic; + +public class AtomicBoolean implements java.io.Serializable { + private static final long serialVersionUID = 4654671469794556979L; + + private static final int FALSE_VALUE = 0; + private static final int TRUE_VALUE = 1; + + private final AtomicInteger value; + + public AtomicBoolean() { + this(false); + } + + public AtomicBoolean(boolean initialValue) { + value = new AtomicInteger(intValue(initialValue)); + } + + private static int intValue(boolean value) { + return value ? TRUE_VALUE : FALSE_VALUE; + } + + private static boolean booleanValue(int value) { + return value == TRUE_VALUE; + } + + public boolean get() { + return booleanValue(value.get()); + } + + public boolean compareAndSet(boolean expect, boolean update) { + return value.compareAndSet(intValue(expect), intValue(update)); + } + + public boolean weakCompareAndSet(boolean expect, boolean update) { + return value.weakCompareAndSet(intValue(expect), intValue(update)); + } + + public void set(boolean newValue) { + value.set(intValue(newValue)); + } + + public void lazySet(boolean newValue) { + value.lazySet(intValue(newValue)); + } + + public boolean getAndSet(boolean newValue) { + int intResult = value.getAndSet(intValue(newValue)); + + return booleanValue(intResult); + } + + @Override + public String toString() { + return Boolean.toString(get()); + } +} diff --git a/sgx-jvm/avian/classpath/java/util/concurrent/atomic/AtomicInteger.java b/sgx-jvm/avian/classpath/java/util/concurrent/atomic/AtomicInteger.java new file mode 100644 index 0000000000..34621f4eff --- /dev/null +++ b/sgx-jvm/avian/classpath/java/util/concurrent/atomic/AtomicInteger.java @@ -0,0 +1,136 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.util.concurrent.atomic; + +import java.lang.reflect.Field; + +import sun.misc.Unsafe; + +public class AtomicInteger extends Number implements java.io.Serializable { + private static final long serialVersionUID = 6214790243416807050L; + + private static final Unsafe unsafe = Unsafe.getUnsafe(); + private static final long valueOffset; + + static { + try { + Field f = AtomicInteger.class.getDeclaredField("value"); + valueOffset = unsafe.objectFieldOffset(f); + } catch (NoSuchFieldException e) { + throw new Error(e); + } + } + + private volatile int value; + + public AtomicInteger() { + this(0); + } + + public AtomicInteger(int initialValue) { + this.value = initialValue; + } + + public int get() { + return value; + } + + public void set(int newValue) { + this.value = newValue; + } + + public void lazySet(int newValue) { + unsafe.putOrderedInt(this, valueOffset, newValue); + } + + public boolean compareAndSet(int expect, int update) { + return unsafe.compareAndSwapInt(this, valueOffset, expect, update); + } + + public boolean weakCompareAndSet(int expect, int update) { + return unsafe.compareAndSwapInt(this, valueOffset, expect, update); + } + + public int getAndSet(int newValue) { + while (true) { + int current = value; + if (compareAndSet(current, newValue)) { + return current; + } + } + } + + public int getAndAdd(int delta) { + while (true) { + int current = value; + int next = current + delta; + if (compareAndSet(current, next)) { + return current; + } + } + } + + public int getAndIncrement() { + return getAndAdd(1); + } + + public int getAndDecrement() { + return getAndAdd(-1); + } + + public int addAndGet(int delta) { + while (true) { + int current = value; + int next = current + delta; + if (compareAndSet(current, next)) { + return next; + } + } + } + + public int incrementAndGet() { + return addAndGet(1); + } + + public int decrementAndGet() { + return addAndGet(-1); + } + + @Override + public byte byteValue() { + return (byte)value; + } + + @Override + public short shortValue() { + return (short)value; + } + + @Override + public int intValue() { + return value; + } + + @Override + public long longValue() { + return value; + } + + @Override + public float floatValue() { + return value; + } + + @Override + public double doubleValue() { + return value; + } +} diff --git a/sgx-jvm/avian/classpath/java/util/concurrent/atomic/AtomicLong.java b/sgx-jvm/avian/classpath/java/util/concurrent/atomic/AtomicLong.java new file mode 100644 index 0000000000..849ea91b7b --- /dev/null +++ b/sgx-jvm/avian/classpath/java/util/concurrent/atomic/AtomicLong.java @@ -0,0 +1,136 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.util.concurrent.atomic; + +import java.lang.reflect.Field; + +import sun.misc.Unsafe; + +public class AtomicLong extends Number implements java.io.Serializable { + private static final long serialVersionUID = 1927816293512124184L; + + private static final Unsafe unsafe = Unsafe.getUnsafe(); + private static final long valueOffset; + + static { + try { + Field f = AtomicLong.class.getDeclaredField("value"); + valueOffset = unsafe.objectFieldOffset(f); + } catch (NoSuchFieldException e) { + throw new Error(e); + } + } + + private volatile long value; + + public AtomicLong() { + this(0); + } + + public AtomicLong(long initialValue) { + this.value = initialValue; + } + + public long get() { + return value; + } + + public void set(long newValue) { + this.value = newValue; + } + + public void lazySet(long newValue) { + unsafe.putOrderedLong(this, valueOffset, newValue); + } + + public boolean compareAndSet(long expect, long update) { + return unsafe.compareAndSwapLong(this, valueOffset, expect, update); + } + + public boolean weakCompareAndSet(long expect, long update) { + return unsafe.compareAndSwapLong(this, valueOffset, expect, update); + } + + public long getAndSet(long newValue) { + while (true) { + long current = value; + if (compareAndSet(current, newValue)) { + return current; + } + } + } + + public long getAndAdd(long delta) { + while (true) { + long current = value; + long next = current + delta; + if (compareAndSet(current, next)) { + return current; + } + } + } + + public long getAndIncrement() { + return getAndAdd(1); + } + + public long getAndDecrement() { + return getAndAdd(-1); + } + + public long addAndGet(long delta) { + while (true) { + long current = value; + long next = current + delta; + if (compareAndSet(current, next)) { + return next; + } + } + } + + public long incrementAndGet() { + return addAndGet(1); + } + + public long decrementAndGet() { + return addAndGet(-1); + } + + @Override + public byte byteValue() { + return (byte)value; + } + + @Override + public short shortValue() { + return (short)value; + } + + @Override + public int intValue() { + return (int)value; + } + + @Override + public long longValue() { + return value; + } + + @Override + public float floatValue() { + return value; + } + + @Override + public double doubleValue() { + return value; + } +} diff --git a/sgx-jvm/avian/classpath/java/util/concurrent/atomic/AtomicReference.java b/sgx-jvm/avian/classpath/java/util/concurrent/atomic/AtomicReference.java new file mode 100644 index 0000000000..80361d407e --- /dev/null +++ b/sgx-jvm/avian/classpath/java/util/concurrent/atomic/AtomicReference.java @@ -0,0 +1,75 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.util.concurrent.atomic; + +import java.lang.reflect.Field; + +import sun.misc.Unsafe; + +public class AtomicReference implements java.io.Serializable { + private static final long serialVersionUID = -1848883965231344442L; + + private static final Unsafe unsafe = Unsafe.getUnsafe(); + private static final long valueOffset; + + static { + try { + Field f = AtomicReference.class.getDeclaredField("value"); + valueOffset = unsafe.objectFieldOffset(f); + } catch (NoSuchFieldException e) { + throw new Error(e); + } + } + + private volatile T value; + + public AtomicReference() { + this(null); + } + + public AtomicReference(T initialValue) { + this.value = initialValue; + } + + public T get() { + return value; + } + + public void set(T newValue) { + value = newValue; + } + + public void lazySet(T newValue) { + unsafe.putOrderedObject(this, valueOffset, newValue); + } + + public boolean compareAndSet(T expect, T update) { + return unsafe.compareAndSwapObject(this, valueOffset, expect, update); + } + + public boolean weakCompareAndSet(T expect, T update) { + return unsafe.compareAndSwapObject(this, valueOffset, expect, update); + } + + public final T getAndSet(T newValue) { + while (true) { + T current = value; + if (compareAndSet(current, newValue)) { + return current; + } + } + } + + @Override + public String toString() { + return String.valueOf(value); + } +} diff --git a/sgx-jvm/avian/classpath/java/util/concurrent/atomic/AtomicReferenceArray.java b/sgx-jvm/avian/classpath/java/util/concurrent/atomic/AtomicReferenceArray.java new file mode 100644 index 0000000000..96f6f47586 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/util/concurrent/atomic/AtomicReferenceArray.java @@ -0,0 +1,69 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.util.concurrent.atomic; + +import java.util.Arrays; + +import sun.misc.Unsafe; + +public class AtomicReferenceArray { + private static final Unsafe unsafe = Unsafe.getUnsafe(); + private static final long arrayOffset = unsafe.arrayBaseOffset(Object.class); + private static final long arrayScale = unsafe.arrayIndexScale(Object.class); + + private final Object[] array; + + public AtomicReferenceArray(int length) { + array = new Object[length]; + } + + public T get(int index) { + return (T) unsafe.getObjectVolatile + (array, arrayOffset + (index * arrayScale)); + } + + public void set(int index, T newValue) { + unsafe.putObjectVolatile + (array, arrayOffset + (index * arrayScale), newValue); + } + + public void lazySet(int index, T newValue) { + unsafe.putOrderedObject + (array, arrayOffset + (index * arrayScale), newValue); + } + + public boolean compareAndSet(int index, T expect, T update) { + return unsafe.compareAndSwapObject + (array, arrayOffset + (index * arrayScale), expect, update); + } + + public boolean weakCompareAndSet(int index, T expect, T update) { + return compareAndSet(index, expect, update); + } + + public final T getAndSet(int index, T newValue) { + while (true) { + T current = get(index); + if (compareAndSet(index, current, newValue)) { + return current; + } + } + } + + public int length() { + return array.length; + } + + @Override + public String toString() { + return Arrays.toString(array); + } +} diff --git a/sgx-jvm/avian/classpath/java/util/concurrent/locks/Condition.java b/sgx-jvm/avian/classpath/java/util/concurrent/locks/Condition.java new file mode 100644 index 0000000000..75c835f006 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/util/concurrent/locks/Condition.java @@ -0,0 +1,24 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.util.concurrent.locks; + +import java.util.Date; +import java.util.concurrent.TimeUnit; + +public interface Condition { + public void await(); + public boolean await(long time, TimeUnit unit); + public long awaitNanos(long nanosTimeout); + public void awaitUninterruptibly(); + public boolean awaitUntil(Date deadline); + public void signal(); + public void signalAll(); +} diff --git a/sgx-jvm/avian/classpath/java/util/concurrent/locks/Lock.java b/sgx-jvm/avian/classpath/java/util/concurrent/locks/Lock.java new file mode 100644 index 0000000000..2d21f97822 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/util/concurrent/locks/Lock.java @@ -0,0 +1,22 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.util.concurrent.locks; + +import java.util.concurrent.TimeUnit; + +public interface Lock { + public void lock(); + public void lockInterruptibly() throws InterruptedException; + public Condition newCondition(); + public boolean tryLock(); + public boolean tryLock(long time, TimeUnit unit) throws InterruptedException; + public void unlock(); +} diff --git a/sgx-jvm/avian/classpath/java/util/concurrent/locks/LockSupport.java b/sgx-jvm/avian/classpath/java/util/concurrent/locks/LockSupport.java new file mode 100644 index 0000000000..7276b75afd --- /dev/null +++ b/sgx-jvm/avian/classpath/java/util/concurrent/locks/LockSupport.java @@ -0,0 +1,85 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.util.concurrent.locks; + +import sun.misc.Unsafe; + +public class LockSupport { + private LockSupport() { + // can't construct + } + + private static final Unsafe unsafe; + private static final long parkBlockerOffset; + + static { + unsafe = Unsafe.getUnsafe(); + try { + parkBlockerOffset = unsafe.objectFieldOffset(Thread.class.getDeclaredField("parkBlocker")); + } catch (Exception ex) { + throw new Error(ex); + } + } + + public static void unpark(Thread thread) { + if (thread != null) { + unsafe.unpark(thread); + } + } + + public static void park(Object blocker) { + doParkNanos(blocker, 0L); + } + + public static void parkNanos(Object blocker, long nanos) { + if (nanos <= 0) { + return; + } + + doParkNanos(blocker, nanos); + } + + private static void doParkNanos(Object blocker, long nanos) { + Thread t = Thread.currentThread(); + unsafe.putObject(t, parkBlockerOffset, blocker); + unsafe.park(false, nanos); + unsafe.putObject(t, parkBlockerOffset, null); + } + + public static void parkUntil(Object blocker, long deadline) { + Thread t = Thread.currentThread(); + unsafe.putObject(t, parkBlockerOffset, blocker); + unsafe.park(true, deadline); + unsafe.putObject(t, parkBlockerOffset, null); + } + + public static Object getBlocker(Thread t) { + if (t == null) { + throw new NullPointerException(); + } + + return unsafe.getObjectVolatile(t, parkBlockerOffset); + } + + public static void park() { + unsafe.park(false, 0L); + } + + public static void parkNanos(long nanos) { + if (nanos > 0) { + unsafe.park(false, nanos); + } + } + + public static void parkUntil(long deadline) { + unsafe.park(true, deadline); + } +} diff --git a/sgx-jvm/avian/classpath/java/util/concurrent/locks/ReadWriteLock.java b/sgx-jvm/avian/classpath/java/util/concurrent/locks/ReadWriteLock.java new file mode 100644 index 0000000000..b0c1b5cae7 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/util/concurrent/locks/ReadWriteLock.java @@ -0,0 +1,16 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.util.concurrent.locks; + +public interface ReadWriteLock { + public Lock readLock(); + public Lock writeLock(); +} diff --git a/sgx-jvm/avian/classpath/java/util/jar/Attributes.java b/sgx-jvm/avian/classpath/java/util/jar/Attributes.java new file mode 100644 index 0000000000..6f4ee6cf2d --- /dev/null +++ b/sgx-jvm/avian/classpath/java/util/jar/Attributes.java @@ -0,0 +1,27 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.util.jar; + +public class Attributes { + public static class Name { + private final String name; + + private static final int MAX_NAME_LENGTH = 70; + + public Name(String s) { + int len = s.length(); + if (len == 0 || len > MAX_NAME_LENGTH) + throw new IllegalArgumentException(); + + name = s; + } + } +} diff --git a/sgx-jvm/avian/classpath/java/util/jar/JarEntry.java b/sgx-jvm/avian/classpath/java/util/jar/JarEntry.java new file mode 100644 index 0000000000..6cee2310a5 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/util/jar/JarEntry.java @@ -0,0 +1,19 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.util.jar; + +import java.util.zip.ZipEntry; + +public abstract class JarEntry extends ZipEntry { + public JarEntry(){ + super(null); + } +} diff --git a/sgx-jvm/avian/classpath/java/util/jar/JarFile.java b/sgx-jvm/avian/classpath/java/util/jar/JarFile.java new file mode 100644 index 0000000000..08adc3d9c8 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/util/jar/JarFile.java @@ -0,0 +1,81 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.util.jar; + +import java.io.File; +import java.io.IOException; +import java.util.Enumeration; +import java.util.zip.ZipFile; +import java.util.zip.ZipEntry; + +public class JarFile extends ZipFile { + public JarFile(String name) throws IOException { + super(name); + } + + public JarFile(File file) throws IOException { + super(file); + } + + public Enumeration entries() { + return (Enumeration) makeEnumeration(JarEntryFactory.Instance); + } + + public JarEntry getJarEntry(String name) { + return (JarEntry) getEntry(JarEntryFactory.Instance, name); + } + + private static class MyJarEntry extends JarEntry implements MyEntry { + public final Window window; + public final int pointer; + + public MyJarEntry(Window window, int pointer) { + this.window = window; + this.pointer = pointer; + } + + public String getName() { + try { + return entryName(window, pointer); + } catch (IOException e) { + return null; + } + } + + public long getCompressedSize() { + try { + return compressedSize(window, pointer); + } catch (IOException e) { + return 0; + } + } + + public long getSize() { + try { + return uncompressedSize(window, pointer); + } catch (IOException e) { + return 0; + } + } + + public int pointer() { + return pointer; + } + } + + private static class JarEntryFactory implements EntryFactory { + public static final JarEntryFactory Instance = new JarEntryFactory(); + + public ZipEntry makeEntry(Window window, int pointer) { + return new MyJarEntry(window, pointer); + } + } +} diff --git a/sgx-jvm/avian/classpath/java/util/logging/Handler.java b/sgx-jvm/avian/classpath/java/util/logging/Handler.java new file mode 100644 index 0000000000..2e2fc41cb6 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/util/logging/Handler.java @@ -0,0 +1,16 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.util.logging; + +public class Handler { + public void publish(LogRecord r) { + } +} diff --git a/sgx-jvm/avian/classpath/java/util/logging/Level.java b/sgx-jvm/avian/classpath/java/util/logging/Level.java new file mode 100644 index 0000000000..e301ab7a32 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/util/logging/Level.java @@ -0,0 +1,40 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.util.logging; + +public class Level { + public static final Level FINEST = new Level("FINEST", 300); + public static final Level FINER = new Level("FINER", 400); + public static final Level FINE = new Level("FINE", 500); + public static final Level INFO = new Level("INFO", 800); + public static final Level WARNING = new Level("WARNING", 900); + public static final Level SEVERE = new Level("SEVERE", 1000); + + private final int value; + private final String name; + + private Level(String name, int value) { + this.name = name; + this.value = value; + } + + public int intValue() { + return value; + } + + public String getName() { + return name; + } + + public String toString() { + return name; + } +} diff --git a/sgx-jvm/avian/classpath/java/util/logging/LogRecord.java b/sgx-jvm/avian/classpath/java/util/logging/LogRecord.java new file mode 100644 index 0000000000..23d4d536bc --- /dev/null +++ b/sgx-jvm/avian/classpath/java/util/logging/LogRecord.java @@ -0,0 +1,48 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.util.logging; + +public class LogRecord { + private final String loggerName; + private final String message; + private final Throwable thrown; + private final Level level; + private final String methodName; + + LogRecord(String loggerName, String methodName, Level level, String message, + Throwable thrown) { + this.loggerName = loggerName; + this.message = message; + this.thrown = thrown; + this.level = level; + this.methodName = methodName; + } + + public String getLoggerName() { + return loggerName; + } + + public String getMessage() { + return message; + } + + public Throwable getThrown() { + return thrown; + } + + public Level getLevel() { + return level; + } + + public String getSourceMethodName() { + return methodName; + } +} diff --git a/sgx-jvm/avian/classpath/java/util/logging/Logger.java b/sgx-jvm/avian/classpath/java/util/logging/Logger.java new file mode 100644 index 0000000000..ad710ae7ce --- /dev/null +++ b/sgx-jvm/avian/classpath/java/util/logging/Logger.java @@ -0,0 +1,232 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.util.logging; + +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.List; + +public class Logger { + private final String name; + private Level levelValue = null; + private static final ArrayList handlers; + private static Logger rootLogger; + private Logger parent; + + static { + rootLogger = new Logger(""); + rootLogger.setLevel(Level.INFO); + handlers = new ArrayList(); + handlers.add(new DefaultHandler()); + } + + public static Logger getLogger(String name) { + if (name.equals("")) return rootLogger; + Logger logger = new Logger(name); + logger.parent = rootLogger; + return logger; + } + + private Logger(String name) { + this.name = name; + } + + public Handler[] getHandlers() { + return handlers.toArray(new Handler[handlers.size()]); + } + + public void addHandler(Handler handler) { + handlers.add(handler); + } + + public void removeHandler(Handler handler) { + handlers.remove(handler); + } + + public Logger getParent() { + return parent; + } + + public void fine(String message) { + log(Level.FINE, Method.getCaller(), message, null); + } + + public void finer(String message) { + log(Level.FINER, Method.getCaller(), message, null); + } + + public void finest(String message) { + log(Level.FINEST, Method.getCaller(), message, null); + } + + public void info(String message) { + log(Level.INFO, Method.getCaller(), message, null); + } + + public void warning(String message) { + log(Level.WARNING, Method.getCaller(), message, null); + } + + public void severe(String message) { + log(Level.SEVERE, Method.getCaller(), message, null); + } + + public void log(Level level, String message) { + log(level, Method.getCaller(), message, null); + } + + public void log(Level level, String message, Throwable exception) { + log(level, Method.getCaller(), message, exception); + } + + public void log(Level level, String message, Object param) { + log(level, Method.getCaller(), replaceParameters(message, param), null); + } + + private static String replaceParameters(String message, Object... params) { + StringBuilder builder = new StringBuilder(); + int offset = 0; + for (int i = 0; i < params.length; ++i) { + int curly = message.indexOf("{}", offset); + if (curly < 0) { + break; + } + if (curly > offset) { + builder.append(message, offset, curly); + } + offset = curly + 2; + builder.append(params[i]); + } + if (message.length() > offset) { + builder.append(message, offset, message.length()); + } + return builder.toString(); + } + + public void logp(Level level, String sourceClass, String sourceMethod, String msg) { + if (!isLoggable(level)) { + return; + } + publish(new LogRecord(name, sourceMethod, level, msg, null)); + } + + public void logp(Level level, String sourceClass, String sourceMethod, + String msg, Throwable thrown) { + if (!isLoggable(level)) { + return; + } + publish(new LogRecord(name, sourceMethod, level, msg, thrown)); + } + + public Level getLevel() { + return levelValue; + } + + private Level getEffectiveLevel() { + Logger logger = this; + + while (logger.levelValue == null) { + logger = logger.getParent(); + } + return logger.getLevel(); + } + + private void log(Level level, avian.VMMethod caller, String message, + Throwable exception) { + + if (level.intValue() < getEffectiveLevel().intValue()) { + return; + } + LogRecord r = new LogRecord + (name, caller == null ? "" : Method.getName(caller), level, + message, exception); + publish(r); + } + + private void publish(LogRecord logRecord) { + for (Handler h : handlers) { + h.publish(logRecord); + } + } + + public void setLevel(Level level) { + levelValue = level; + } + + public boolean isLoggable(Level level) { + return level.intValue() >= getEffectiveLevel().intValue(); + } + + private static class DefaultHandler extends Handler { + private static final int NAME_WIDTH = 14; + private static final int METHOD_WIDTH = 15; + private static final int LEVEL_WIDTH = 8; + private final String newline; + + public DefaultHandler() { + newline = System.getProperty("line.separator"); + } + + public Object clone() { return this; } + public void close() { } + public void flush() { } + + private void maybeLogThrown(StringBuilder sb, Throwable t) { + if (t != null) { + sb.append("\nCaused by: "); + sb.append(t.getClass().getName()); + sb.append(": "); + sb.append(t.getMessage()); + sb.append(newline); + + for (StackTraceElement elt : t.getStackTrace()) { + sb.append('\t'); + sb.append(elt.getClassName()); + sb.append('.'); + sb.append(elt.getMethodName()); + sb.append("(line"); + sb.append(':'); + int lineNumber = elt.getLineNumber(); + if (lineNumber == -2) { + sb.append("unknown"); + } else if (lineNumber == -1) { + sb.append("native"); + } else { + sb.append(lineNumber); + } + sb.append(')'); + sb.append(newline); + } + maybeLogThrown(sb, t.getCause()); + } + } + + private void indent(StringBuilder sb, int amount) { + do { + sb.append(' '); + } while (--amount > 0); + } + + public void publish(LogRecord r) { + StringBuilder sb = new StringBuilder(); + sb.append(r.getLoggerName()); + indent(sb, NAME_WIDTH - r.getLoggerName().length()); + sb.append(r.getSourceMethodName()); + indent(sb, METHOD_WIDTH - r.getSourceMethodName().length()); + sb.append(r.getLevel().getName()); + indent(sb, LEVEL_WIDTH - r.getLevel().getName().length()); + sb.append(r.getMessage()); + maybeLogThrown(sb, r.getThrown()); + System.out.println(sb.toString()); + } + } + +} diff --git a/sgx-jvm/avian/classpath/java/util/regex/CharacterMatcher.java b/sgx-jvm/avian/classpath/java/util/regex/CharacterMatcher.java new file mode 100644 index 0000000000..0df1a947c6 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/util/regex/CharacterMatcher.java @@ -0,0 +1,332 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.util.regex; + +/** + * A class to match classes of characters. + *

+ * This class is intended to be the working horse behind character classes + * such as {@code [a-z]}. + *

+ * @author Johannes Schindelin + */ +class CharacterMatcher { + private boolean[] map; + private boolean inversePattern; + + public static CharacterMatcher parse(String description) { + return parse(description.toCharArray()); + } + + public static CharacterMatcher parse(char[] description) { + Parser parser = new Parser(description); + CharacterMatcher result = parser.parseClass(); + if (parser.getEndOffset() != description.length) { + throw new RuntimeException("Short character class @" + + parser.getEndOffset() + ": " + new String(description)); + } + return result; + } + + public boolean matches(char c) { + int index = c; + return (map.length > index && map[index]) ^ inversePattern; + } + + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("["); + if (inversePattern) { + builder.append("^"); + } + for (int i = 0; i < map.length; ++ i) { + if (!map[i]) { + continue; + } + builder.append(i >= ' ' && i <= 0x7f ? + "" + (char)i : ("\\x" + Integer.toHexString(i))); + int j = i + 1; + while (j < map.length && map[j]) { + ++ j; + } + -- j; + if (j > i) { + if (j > i + 1) { + builder.append('-'); + } + builder.append(j >= ' ' && j <= 0x7f ? + "" + (char)j : ("\\x" + Integer.toHexString(j))); + i = j; + } + } + builder.append("]"); + return builder.toString(); + } + + private static String specialClass(int c) { + if ('d' == c) { + return "[0-9]"; + } + if ('D' == c) { + return "[^0-9]"; + } + if ('s' == c) { + return "[ \\t\\n\\x0B\\f\\r]"; + } + if ('S' == c) { + return "[^ \\t\\n\\x0B\\f\\r]"; + } + if ('w' == c) { + return "[a-zA-Z_0-9]"; + } + if ('W' == c) { + return "[^a-zA-Z_0-9]"; + } + return null; + } + + private CharacterMatcher(boolean[] map, boolean inversePattern) { + this.map = map; + this.inversePattern = inversePattern; + } + + private void setMatch(int c) { + ensureCapacity(c + 1); + map[c] = true; + } + + private void ensureCapacity(int length) { + if (map.length >= length) { + return; + } + int size = map.length; + if (size < 32) { + size = 32; + } + while (size < length) { + size <<= 1; + } + map = java.util.Arrays.copyOf(map, size); + } + + private void merge(CharacterMatcher other) { + boolean inversePattern = this.inversePattern || other.inversePattern; + if ((map.length < other.map.length) ^ inversePattern) { + map = java.util.Arrays.copyOf(map, other.map.length); + } + for (int i = 0; i < map.length; ++ i) { + map[i] = (matches((char)i) || other.matches((char)i)) ^ inversePattern; + } + this.inversePattern = inversePattern; + } + + private void intersect(CharacterMatcher other) { + boolean inversePattern = this.inversePattern && other.inversePattern; + if ((map.length > other.map.length) ^ inversePattern) { + map = java.util.Arrays.copyOf(map, other.map.length); + } + for (int i = 0; i < map.length; ++ i) { + map[i] = (matches((char)i) && other.matches((char)i)) ^ inversePattern; + } + this.inversePattern = inversePattern; + } + + static class Parser { + private final char[] description; + private int offset; + + public Parser(char[] description) { + this.description = description; + } + + public int getEndOffset() { + return offset; + } + + /** + * Parses an escaped character. + * + * @param start the offset after the backslash + * @return the escaped character, or -1 if no character was recognized + */ + public int parseEscapedCharacter(int start) { + offset = start; + return parseEscapedCharacter(); + } + + private int parseEscapedCharacter() { + if (offset == description.length) { + throw new IllegalArgumentException("Short escaped character"); + } + char c = description[offset++]; + if (c == '0') { + int len = digits(offset, 3, 8); + if (len == 3 && description[offset] > '3') { + --len; + } + c = (char)Integer.parseInt(new String(description, offset, len), 8); + offset += len; + return c; + } + if (c == 'x' || c == 'u') { + int len = digits(offset, 4, 16); + c = (char)Integer.parseInt(new String(description, offset, len), 16); + offset += len; + return c; + } + switch (c) { + case 'a': + return 0x0007; + case 'e': + return 0x001B; + case 'f': + return 0x000C; + case 'n': + return 0x000A; + case 'r': + return 0x000D; + case 't': + return 0x0009; + case '\\': + case '.': + case '*': + case '+': + case '?': + case '|': + case '[': + case ']': + case '{': + case '}': + case '(': + case ')': + case '^': + case '$': + return c; + } + return -1; + } + + public int digits(int offset, int maxLength, int base) { + for (int i = 0; ; ++i) { + if (i == maxLength || offset + i >= description.length) { + return i; + } + int value = description[offset + i] - '0'; + if (value < 0) { + return i; + } + if (base > 10 && value >= 10) { + value += 10 - (value >= 'a' - '0' ? 'a' - '0' : 'A' - '0'); + } + if (value >= base) { + return i; + } + } + } + + public CharacterMatcher parseClass(int start) { + offset = start; + return parseClass(); + } + + public CharacterMatcher parseClass() { + if (description[offset] != '[') { + if (description[offset] == '\\') { + String range = specialClass(description[++ offset]); + if (range != null) { + ++ offset; + return CharacterMatcher.parse(range); + } + } + return null; + } + CharacterMatcher matcher = new CharacterMatcher(new boolean[0], + description[++ offset] == '^'); + if (matcher.inversePattern) { + ++ offset; + } + + int previous = -1; + boolean firstCharacter = true; + for (;;) { + if (offset >= description.length) { + unsupported("short regex"); + } + char c = description[offset++]; + if (c == '-' && !firstCharacter && description[offset] != ']') { + if (previous < 0) { + unsupported("invalid range"); + } + int rangeEnd = description[offset]; + if ('\\' == rangeEnd) { + rangeEnd = parseEscapedCharacter(); + if (rangeEnd < 0) { + unsupported("invalid range"); + } + } + matcher.ensureCapacity(rangeEnd + 1); + for (int j = previous + 1; j <= rangeEnd; j++) { + matcher.map[j] = true; + } + } else if (c == '\\') { + int saved = offset; + previous = parseEscapedCharacter(); + if (previous < 0) { + offset = saved - 1; + CharacterMatcher clazz = parseClass(); + if (clazz == null) { + unsupported("escape"); + } + matcher.merge(clazz); + } else { + matcher.setMatch(previous); + } + } else if (c == '[') { + Parser parser = new Parser(description); + CharacterMatcher other = parser.parseClass(offset - 1); + if (other == null) { + unsupported("invalid merge"); + } + matcher.merge(other); + offset = parser.getEndOffset(); + previous = -1; + } else if (c == '&') { + if (offset + 2 > description.length || description[offset] != '&' + || description[offset + 1] != '[') { + unsupported("operation"); + } + Parser parser = new Parser(description); + CharacterMatcher other = parser.parseClass(offset + 1); + if (other == null) { + unsupported("invalid intersection"); + } + matcher.intersect(other); + offset = parser.getEndOffset(); + previous = -1; + } else if (c == ']') { + break; + } else { + previous = c; + matcher.setMatch(previous); + } + firstCharacter = false; + } + + return matcher; + } + + private void unsupported(String msg) throws UnsupportedOperationException { + throw new UnsupportedOperationException("Unsupported " + msg + " @" + + offset + ": " + + new String(description, 0, description.length)); + } + } +} diff --git a/sgx-jvm/avian/classpath/java/util/regex/Compiler.java b/sgx-jvm/avian/classpath/java/util/regex/Compiler.java new file mode 100644 index 0000000000..4e495a5f80 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/util/regex/Compiler.java @@ -0,0 +1,533 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.util.regex; + +import java.util.ArrayList; +import java.util.Stack; + +/** + * Compiles regular expressions into {@link PikeVM}s. + * + * @author Johannes Schindelin + */ +class Compiler implements PikeVMOpcodes { + private final static CharacterMatcher regularCharacter = + CharacterMatcher.parse("[^\\\\.*+?|\\[\\]{}()^$]"); + + private static class Output { + private int[] program; + private int offset; + private int groupCount = -1; + private int findPreambleSize; + private ArrayList classes; + private ArrayList lookarounds; + + public Output(Expression expr) { + // try-run to determine the code size + expr.writeCode(this); + program = new int[offset]; + offset = 0; + groupCount = -1; + classes = new ArrayList(); + lookarounds = new ArrayList(); + // write it out! + expr.writeCode(this); + } + + public void add(int opcode) { + if (program != null) { + program[offset] = opcode; + } + offset++; + } + + public int markJump() { + return offset++; + } + + public void setJump(int mark) { + if (program != null) { + program[mark] = offset; + } + } + + public void markFindPreambleEnd() { + findPreambleSize = offset; + } + + public PikeVM toVM() { + CharacterMatcher[] classes = new CharacterMatcher[this.classes.size()]; + this.classes.toArray(classes); + PikeVM[] lookarounds = new PikeVM[this.lookarounds.size()]; + this.lookarounds.toArray(lookarounds); + return new PikeVM(program, findPreambleSize, groupCount, classes, + lookarounds); + } + + public int addClass(CharacterMatcher characterClass) { + if (program == null) { + return -1; + } + int result = classes.size(); + classes.add(characterClass); + return result; + } + + public int addLookaround(PikeVM lookaround) { + if (program == null) { + return -1; + } + int result = lookarounds.size(); + lookarounds.add(lookaround); + return result; + } + } + + private abstract class Expression { + protected abstract void writeCode(Output output); + } + + private class CharacterRange extends Expression { + private final CharacterMatcher characterClass; + + public CharacterRange(CharacterMatcher characterClass) { + this.characterClass = characterClass; + } + + protected void writeCode(Output output) { + output.add(CHARACTER_CLASS); + output.add(output.addClass(characterClass)); + } + + public String toString() { + return characterClass.toString(); + } + } + + private class Repeat extends Expression { + private Expression expr; + private int minCount, maxCount; + private boolean greedy; + + public Repeat(Expression expr, int minCount, int maxCount, boolean greedy) { + if (minCount < 0) { + throw new RuntimeException("Unexpected min count: " + minCount); + } + if (maxCount != -1) { + if (maxCount == 0) { + throw new RuntimeException("Unexpected max count: " + maxCount); + } + if (minCount > maxCount) { + throw new RuntimeException("Unexpected range: " + minCount + ", " + maxCount); + } + } + this.expr = expr; + this.minCount = minCount; + this.maxCount = maxCount; + this.greedy = greedy; + } + + protected void writeCode(Output output) { + int start = output.offset; + int splitJmp = greedy ? SPLIT_JMP : SPLIT; + int split = greedy ? SPLIT : SPLIT_JMP; + for (int i = 1; i < minCount; ++ i) { + expr.writeCode(output); + } + if (maxCount == -1) { + if (minCount > 0) { + int jump = output.offset; + expr.writeCode(output); + output.add(splitJmp); + output.add(jump); + } else { + output.add(split); + int jump = output.markJump(); + expr.writeCode(output); + output.add(splitJmp); + output.add(start + 2); + output.setJump(jump); + } + } else { + if (minCount > 0) { + expr.writeCode(output); + } + if (maxCount > minCount) { + int[] jumps = new int[maxCount - minCount]; + for (int i = 0; i < jumps.length; ++ i) { + output.add(split); + jumps[i] = output.markJump(); + expr.writeCode(output); + } + for (int jump : jumps) { + output.setJump(jump); + } + } + } + } + + public String toString() { + String qualifier = greedy ? "" : "?"; + if (minCount == 0 && maxCount < 2) { + return expr.toString() + (minCount < 0 ? "*" : "?") + qualifier; + } + if (minCount == 1 && maxCount < 0) { + return expr.toString() + "+" + qualifier; + } + return expr.toString() + "{" + minCount + "," + + (maxCount < 0 ? "" : "" + maxCount) + "}" + qualifier; + } + } + + private class Group extends Expression { + private final boolean capturing; + + private ArrayList list = new ArrayList(); + private ArrayList alternatives; + + public Group(boolean capturing, ArrayList initialList) { + this.capturing = capturing; + if (initialList != null) { + list.addAll(initialList); + } + } + + public void push(Expression expr) { + list.add(expr); + } + + public void push(final int c) { + push(new Expression() { + public void writeCode(Output output) { + output.add(c); + } + + public String toString() { + if (c >= 0) { + return "" + (char)c; + } + switch (c) { + case DOT: + return "."; + case WORD_BOUNDARY: + return "\\b"; + case NON_WORD_BOUNDARY: + return "\\B"; + case LINE_START: + return "^"; + case LINE_END: + return "$"; + default: + throw new RuntimeException("Unhandled opcode: " + c); + } + } + }); + } + + public void startAlternative() { + if (alternatives == null) { + alternatives = new ArrayList(); + } + alternatives.add(new Group(false, list)); + list.clear(); + } + + public Expression pop() { + Expression result = list.remove(list.size() - 1); + return result; + } + + protected void writeCode(Output output) { + int groupIndex = -1; + if (capturing) { + groupIndex = ++ output.groupCount; + output.add(SAVE_OFFSET); + output.add(2 * groupIndex); + } + int[] jumps = null; + if (alternatives != null) { + jumps = new int[alternatives.size()]; + int i = 0; + for (Group alternative : alternatives) { + output.add(SPLIT); + int jump = output.markJump(); + alternative.writeCode(output); + output.add(JMP); + jumps[i++] = output.markJump(); + output.setJump(jump); + } + } + for (Expression expr : list) { + expr.writeCode(output); + } + if (jumps != null) { + for (int jump : jumps) { + output.setJump(jump); + } + } + if (capturing) { + output.add(SAVE_OFFSET); + output.add(2 * groupIndex + 1); + } + } + + public String toString() { + StringBuilder builder = new StringBuilder(); + if (alternatives != null || list.size() > 1) { + builder.append('('); + if (!capturing) { + builder.append("?:"); + } + } + if (alternatives != null) { + for (Group alternative : alternatives) { + builder.append(alternative).append('|'); + } + } + for (Expression expr : list) { + builder.append(expr); + } + if (alternatives != null || list.size() > 1) { + builder.append(')'); + } + return builder.toString(); + } + } + + private class Lookaround extends Expression { + private final Group group = new Group(false, null); + private final boolean forward, negative; + + public Lookaround(boolean forward, boolean negative) { + this.forward = forward; + this.negative = negative; + } + + @Override + protected void writeCode(Output output) { + PikeVM vm = new Output(group).toVM(); + if (!forward) { + vm.reverse(); + } + output.add(forward ? + (negative ? NEGATIVE_LOOKAHEAD : LOOKAHEAD) : + (negative ? NEGATIVE_LOOKAHEAD : LOOKBEHIND)); + output.add(output.addLookaround(vm)); + } + + public String toString() { + String inner = group.toString(); + if (inner.startsWith("(?:")) { + inner = inner.substring(3); + } else { + inner += ")"; + } + return "(?=" + inner; + } + } + + private class Group0 extends Expression { + private final Group group; + + public Group0() { + group = new Group(true, null); + } + + public void writeCode(Output output) { + // find() preamble + int start = output.offset; + output.add(SPLIT_JMP); + output.add(start + 5); + output.add(DOTALL); + output.add(SPLIT); + output.add(start + 2); + output.markFindPreambleEnd(); + group.writeCode(output); + } + + public String toString() { + String inner = group.toString(); + return inner.startsWith("(?:") && inner.endsWith(")") ? + inner.substring(1, inner.length() - 1) : inner; + } + } + + private Group0 root; + private Stack groups; + + public Compiler() { + root = new Group0(); + groups = new Stack(); + groups.add(root.group); + } + + public Pattern compile(String regex) { + char[] array = regex.toCharArray(); + CharacterMatcher.Parser characterClassParser = + new CharacterMatcher.Parser(array); + for (int index = 0; index < array.length; ++ index) { + char c = array[index]; + Group current = groups.peek(); + if (regularCharacter.matches(c)) { + current.push(c); + continue; + } + switch (c) { + case '.': + current.push(DOT); + continue; + case '\\': + int unescaped = characterClassParser.parseEscapedCharacter(index + 1); + if (unescaped >= 0) { + index = characterClassParser.getEndOffset() - 1; + current.push((char)unescaped); + continue; + } + CharacterMatcher characterClass = characterClassParser.parseClass(index); + if (characterClass != null) { + index = characterClassParser.getEndOffset() - 1; + current.push(new CharacterRange(characterClass)); + continue; + } + switch (array[index + 1]) { + case 'b': + index++; + current.push(WORD_BOUNDARY); + continue; + case 'B': + index++; + current.push(NON_WORD_BOUNDARY); + continue; + } + throw new RuntimeException("Parse error @" + index + ": " + regex); + case '?': + case '*': + case '+': { + boolean greedy = true; + if (index + 1 < array.length && array[index + 1] == '?') { + greedy = false; + ++ index; + } + current.push(new Repeat(current.pop(), + c == '+' ? 1 : 0, c == '?' ? 1 : -1, greedy)); + continue; + } + case '{': { + ++ index; + int length = characterClassParser.digits(index, 8, 10); + int min = Integer.parseInt(regex.substring(index, index + length)); + int max = min; + index += length - 1; + c = index + 1 < array.length ? array[index + 1] : 0; + if (c == ',') { + ++ index; + length = characterClassParser.digits(index + 1, 8, 10); + max = length == 0 ? -1 : + Integer.parseInt(regex.substring(index + 1, index + 1 + length)); + index += length; + c = index + 1< array.length ? array[index + 1] : 0; + } + if (c != '}') { + throw new RuntimeException("Invalid quantifier @" + index + ": " + + regex); + } + ++ index; + boolean greedy = true; + if (index + 1 < array.length && array[index + 1] == '?') { + ++ index; + greedy = false; + } + current.push(new Repeat(current.pop(), min, max, greedy)); + continue; + } + case '(': { + boolean capturing = true; + if (index + 1 < array.length && array[index + 1] == '?') { + index += 2; + if (index >= array.length) { + throw new RuntimeException("Short pattern @" + index + ": " + + regex); + } + c = array[index]; + boolean lookAhead = true; + if (c == '<') { + if (++ index >= array.length) { + throw new RuntimeException("Short pattern @" + index + ": " + + regex); + } + lookAhead = false; + c = array[index]; + if (c != '=' && c != '!') { + throw new IllegalArgumentException("Named groups not supported @" + + index + ": " + regex); + } + } + switch (c) { + case ':': + capturing = false; + break; + case '!': + case '=': { + capturing = false; + Lookaround lookaround = new Lookaround(lookAhead, c == '!'); + current.push(lookaround); + groups.push(lookaround.group); + continue; + } + default: + throw new UnsupportedOperationException("Not yet supported: " + + regex.substring(index)); + } + } + current.push(groups.push(new Group(capturing, null))); + continue; + } + case ')': + if (groups.size() < 2) { + throw new RuntimeException("Invalid group close @" + index + ": " + + regex); + } + groups.pop(); + continue; + case '[': { + CharacterMatcher matcher = characterClassParser.parseClass(index); + if (matcher == null) { + throw new RuntimeException("Invalid range @" + index + ": " + regex); + } + current.push(new CharacterRange(matcher)); + index = characterClassParser.getEndOffset() - 1; + continue; + } + case '|': + current.startAlternative(); + continue; + case '^': + current.push(LINE_START); + continue; + case '$': + current.push(LINE_END); + continue; + default: + throw new RuntimeException("Parse error @" + index + ": " + regex); + } + } + if (groups.size() != 1) { + throw new IllegalArgumentException("Unclosed groups: (" + + (groups.size() - 1) + "): " + regex); + } + PikeVM vm = new Output(root).toVM(); + String plain = vm.isPlainString(); + if (plain != null) { + return new TrivialPattern(regex, plain, 0); + } + return new RegexPattern(regex, 0, vm); + } +} diff --git a/sgx-jvm/avian/classpath/java/util/regex/Matcher.java b/sgx-jvm/avian/classpath/java/util/regex/Matcher.java new file mode 100644 index 0000000000..a192942e02 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/util/regex/Matcher.java @@ -0,0 +1,119 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.util.regex; + +/** + * This is a work in progress. + * + * @author zsombor and others + */ +public abstract class Matcher { + protected CharSequence input; + protected int start; + protected int end; + + public Matcher(CharSequence input) { + reset(input); + } + + public abstract boolean matches(); + + public boolean find() { + return find(end); + } + + public abstract boolean find(int start); + + public Matcher reset() { + return reset(input); + } + + public Matcher reset(CharSequence input) { + this.input = input; + start = 0; + end = 0; + return this; + } + + public String replaceAll(String replacement) { + return replace(replacement, Integer.MAX_VALUE); + } + + public String replaceFirst(String replacement) { + return replace(replacement, 1); + } + + protected String replace(String replacement, int limit) { + reset(); + + StringBuilder sb = null; + int index = 0; + int count = 0; + while (count < limit && index < input.length()) { + if (find(index)) { + if (sb == null) { + sb = new StringBuilder(); + } + if (start > index) { + sb.append(input.subSequence(index, start)); + } + sb.append(replacement); + index = end; + ++ count; + } else if (index == 0) { + return input.toString(); + } else { + break; + } + } + if (index < input.length()) { + sb.append(input.subSequence(index, input.length())); + } + return sb.toString(); + } + + public int start() { + return start; + } + + public int end() { + return end; + } + + public String group() { + return input.subSequence(start, end).toString(); + } + + public int start(int group) { + if (group == 0) { + return start(); + } + throw new UnsupportedOperationException(); + } + + public int end(int group) { + if (group == 0) { + return end(); + } + throw new UnsupportedOperationException(); + } + + public String group(int group) { + if (group == 0) { + return group(); + } + throw new UnsupportedOperationException(); + } + + public int groupCount() { + return 0; + } +} diff --git a/sgx-jvm/avian/classpath/java/util/regex/Pattern.java b/sgx-jvm/avian/classpath/java/util/regex/Pattern.java new file mode 100644 index 0000000000..299de7ab8e --- /dev/null +++ b/sgx-jvm/avian/classpath/java/util/regex/Pattern.java @@ -0,0 +1,89 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.util.regex; + +import java.util.ArrayList; +import java.util.List; + +/** + * This is a work in progress. + * + * @author zsombor and others + * + */ +public abstract class Pattern implements PikeVMOpcodes { + + public static final int UNIX_LINES = 1; + public static final int CASE_INSENSITIVE = 2; + public static final int COMMENTS = 4; + public static final int MULTILINE = 8; + public static final int LITERAL = 16; + public static final int DOTALL = 32; + public static final int UNICODE_CASE = 64; + public static final int CANON_EQ = 128; + + private final int patternFlags; + private final String pattern; + + protected Pattern(String pattern, int flags) { + this.pattern = pattern; + this.patternFlags = flags; + } + + public static Pattern compile(String regex) { + return compile(regex, 0); + } + + public static Pattern compile(String regex, int flags) { + if (flags != 0) { + throw new UnsupportedOperationException("TODO"); + } + return new Compiler().compile(regex); + } + + public int flags() { + return patternFlags; + } + + public abstract Matcher matcher(CharSequence input); + + public static boolean matches(String regex, CharSequence input) { + return Pattern.compile(regex).matcher(input).matches(); + } + + public String pattern() { + return pattern; + } + + public String[] split(CharSequence input) { + return split(input, 0); + } + + public String[] split(CharSequence input, int limit) { + if (limit <= 0) { + limit = Integer.MAX_VALUE; + } + Matcher matcher = matcher(input); + List result = new ArrayList(); + int offset = 0; + for (;;) { + if (result.size() >= limit || !matcher.find()) { + break; + } + result.add(input.subSequence(offset, matcher.start()).toString()); + offset = matcher.end(); + } + if (offset == 0 || offset < input.length()) { + result.add(input.subSequence(offset, input.length()).toString()); + } + return result.toArray(new String[result.size()]); + } +} diff --git a/sgx-jvm/avian/classpath/java/util/regex/PikeVM.java b/sgx-jvm/avian/classpath/java/util/regex/PikeVM.java new file mode 100644 index 0000000000..b364aecaa6 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/util/regex/PikeVM.java @@ -0,0 +1,629 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.util.regex; + +/** + * A minimal implementation of a regular expression engine. + * + * @author Johannes Schindelin + */ +class PikeVM implements PikeVMOpcodes { + private final int[] program; + private final int groupCount; + private final int offsetsCount; + /* + * For find(), we do not want to anchor the match at the start offset. Our + * compiler allows this by prefixing the code with an implicit '(?:.*?)'. For + * regular matches() calls, we want to skip that code and start at {@code + * findPrefixLength} instead. + */ + private final int findPrefixLength; + private final CharacterMatcher[] classes; + private final PikeVM[] lookarounds; + private final static CharacterMatcher wordCharacter = + CharacterMatcher.parse("\\w"); + private final static CharacterMatcher lineTerminator = + CharacterMatcher.parse("[\n\r\u0085\u2028\u2029]"); + private boolean multiLine; + + public interface Result { + void set(int[] start, int[] end); + } + + protected PikeVM(int[] program, int findPrefixLength, int groupCount, + CharacterMatcher[] classes, PikeVM[] lookarounds) + { + this.program = program; + this.findPrefixLength = findPrefixLength; + this.groupCount = groupCount; + offsetsCount = 2 * groupCount + 2; + this.classes = classes; + this.lookarounds = lookarounds; + } + + /** + * The current thread states. + *

+ * The threads are identified by their program counter. The rationale: as all + * threads are executed in lock-step, i.e. for the same character in the + * string to be matched, it does not make sense for two threads to be at the + * same program counter -- they would both do exactly the same for the rest of + * the execution. + *

+ *

+ * For efficiency, the threads are kept in a linked list that actually lives + * in an array indexed by the program counter, pointing to the next thread's + * program counter, in the order of high to low priority. + *

+ *

+ * Program counters which have no thread associated thread are marked as -1. + * The program counter associated with the least-priority thread (the last one + * in the linked list) is marked as -2 to be able to tell it apart from + * unscheduled threads. + *

+ *

+ * We actually never need to have an explicit value for the priority, the + * ordering is sufficient: whenever a new thread is to be scheduled and it is + * found to be scheduled already, it was already scheduled by a + * higher-priority thread. + *

+ */ + private class ThreadQueue { + private int head, tail; + // next[pc] is 1 + the next thread's pc + private int[] next; + // offsets[pc][2 * group] is 1 + start offset + private int[][] offsets; + + public ThreadQueue() { + head = tail = -1; + next = new int[program.length + 1]; + offsets = new int[program.length + 1][]; + } + + public ThreadQueue(int startPC) { + head = tail = startPC; + next = new int[program.length + 1]; + offsets = new int[program.length + 1][]; + offsets[head] = new int[offsetsCount]; + } + + public int queueOneImmediately(ThreadQueue into) { + for (;;) { + if (head < 0) { + return -1; + } + boolean wasQueued = queueNext(head, head, into); + int pc = head; + if (head == tail) { + head = tail = -1; + } else { + head = next[pc] - 1; + next[pc] = 0; + } + offsets[pc] = null; + if (wasQueued) { + into.tail = pc; + return pc; + } + } + } + + /** + * Schedules the instruction at {@code nextPC} to be executed immediately. + *

+ * For non-matching steps (SPLIT, SAVE_STATE, etc) we need to schedule the + * corresponding program counter(s) to be handled right after this opcode, + * before advancing to the next character. + *

+ *

+ * To achieve this, we insert the program counter to-be-scheduled in the + * linked thread list at the current position, but only if it has not been + * scheduled yet: if it has, a higher-priority thread already reached that + * state. + *

+ *

+ * In contrast to {@link #queueNext(int, int, ThreadQueue)}, this method + * works on the current step's thread list. + *

+ * + * @param currentPC + * the current program counter + * @param nextPC + * the program counter to schedule + * @param copyThreadState + * whether to spawn off a new thread + * @return whether the step was queued (i.e. no thread was queued for the + * same {@code nextPC} already) + */ + public boolean queueImmediately(int currentPC, int nextPC, + boolean copyThreadState) { + if (isScheduled(nextPC)) { + return false; + } + int[] offsets = this.offsets[currentPC]; + if (copyThreadState) { + offsets = java.util.Arrays.copyOf(offsets, offsetsCount); + } + if (currentPC == tail) { + tail = nextPC; + } else { + next[nextPC] = next[currentPC]; + } + this.offsets[nextPC] = offsets; + next[currentPC] = nextPC + 1; + return true; + } + + /** + * Schedules the instruction at {@code nextPC} to be executed in the next + * step. + *

+ * This method advances the current thread to the next program counter, to + * be executed after reading the next character. + *

+ * + * @param currentPC + * the current program counter + * @param nextPC + * the program counter to schedule + * @param next + * the thread state of the next step + * @return whether the step was queued (i.e. no thread was queued for the + * same {@code nextPC} already) + */ + private boolean queueNext(int currentPC, int nextPC, ThreadQueue next) { + if (next.tail < 0) { + next.head = nextPC; + } else if (next.isScheduled(nextPC)) { + return false; + } else { + next.next[next.tail] = nextPC + 1; + } + next.offsets[nextPC] = offsets[currentPC]; + next.tail = nextPC; + return true; + } + + public void saveOffset(int pc, int index, int offset) { + offsets[pc][index] = offset + 1; + } + + public void setResult(Result result) { + // copy offsets + int[] offsets = this.offsets[program.length]; + int[] groupStart = new int[groupCount + 1]; + int[] groupEnd = new int[groupCount + 1]; + for (int j = 0; j <= groupCount; ++j) { + groupStart[j] = offsets[2 * j] - 1; + groupEnd[j] = offsets[2 * j + 1] - 1; + } + result.set(groupStart, groupEnd); + } + + private void mustStartMatchAt(int start) { + int previous = -1; + for (int pc = head; pc >= 0; ) { + int nextPC = next[pc] - 1; + if (start + 1 == offsets[pc][0]) { + previous = pc; + } else { + next[pc] = 0; + offsets[pc] = null; + if (pc == tail) { + head = tail = -1; + } else if (previous < 0) { + head = nextPC; + } else { + next[previous] = 1 + nextPC; + } + } + pc = nextPC; + } + } + + private int startOffset(int pc) { + return offsets[pc][0] - 1; + } + + public boolean isEmpty() { + return head < 0; + } + + public boolean isScheduled(int pc) { + return pc == tail || next[pc] > 0; + } + + public int next(int pc) { + return pc < 0 ? head : next[pc] - 1; + } + + public void clean() { + for (int pc = head; pc >= 0; ) { + int nextPC = next[pc] - 1; + next[pc] = 0; + offsets[pc] = null; + pc = nextPC; + } + head = tail = -1; + } + } + + /** + * Executes the Pike VM defined by the program. + *

+ * The idea is to execute threads in parallel, at each step executing them + * from the highest priority thread to the lowest one. In contrast to most + * regular expression engines, the Thompson/Pike one gets away with linear + * complexity because the string is matched from left to right, at each step + * executing a number of threads bounded by the length of the program: if two + * threads would execute at the same instruction pointer of the program, we + * need only consider the higher-priority one. + *

+ *

+ * This implementation is based on the description of Russ Cox. + *

+ * + * @param characters + * the {@link String} to match + * @param start + * the start offset where to match + * @param length + * the end offset + * @param anchorStart + * whether the match must start at {@code start} + * @param anchorEnd + * whether the match must start at {@code end} + * @param result + * the {@link Matcher} to store the groups' offsets in, if successful + * @return whether a match was found + */ + public boolean matches(char[] characters, int start, int end, + boolean anchorStart, boolean anchorEnd, Result result) + { + ThreadQueue current = new ThreadQueue(); + ThreadQueue next = new ThreadQueue(); + + // initialize the first thread + int startPC = anchorStart ? findPrefixLength : 0; + ThreadQueue queued = new ThreadQueue(startPC); + + boolean foundMatch = false; + int step = end > start ? +1 : -1; + for (int i = start; i != end + step; i += step) { + if (queued.isEmpty()) { + // no threads left + return foundMatch; + } + + char c = i != end ? characters[i] : 0; + int pc = -1; + for (;;) { + pc = current.next(pc); + if (pc < 0) { + pc = queued.queueOneImmediately(current); + } + if (pc < 0) { + break; + } + + // pc == program.length is a match! + if (pc == program.length) { + if (anchorEnd && i != end) { + continue; + } + if (result == null) { + // only interested in a match, no need to go on + return true; + } + current.setResult(result); + + // now that we found a match, even higher-priority matches must match + // at the same start offset + if (!anchorStart) { + next.mustStartMatchAt(current.startOffset(pc)); + } + foundMatch = true; + break; + } + + int opcode = program[pc]; + switch (opcode) { + case DOT: + if (c != '\0' && c != '\r' && c != '\n') { + current.queueNext(pc, pc + 1, next); + } + break; + case DOTALL: + current.queueNext(pc, pc + 1, next); + break; + case WORD_BOUNDARY: + case NON_WORD_BOUNDARY: { + int i2 = i - step; + int c2 = i2 < 0 || i2 >= characters.length ? -1 : characters[i2]; + switch (opcode) { + case WORD_BOUNDARY: + if ((c2 < 0 || !wordCharacter.matches((char)c2))) { + if (wordCharacter.matches(c)) { + current.queueImmediately(pc, pc + 1, false); + } + } else if (i >= 0 && i < characters.length && + !wordCharacter.matches(c)) { + current.queueImmediately(pc, pc + 1, false); + } + break; + case NON_WORD_BOUNDARY: + if ((c2 < 0 || !wordCharacter.matches((char)c2))) { + if (i >= 0 && i < characters.length && + !wordCharacter.matches(c)) { + current.queueImmediately(pc, pc + 1, false); + } + } else if (wordCharacter.matches(c)) { + current.queueImmediately(pc, pc + 1, false); + } + break; + } + break; + } + case LINE_START: + if (i == 0 || (multiLine && + lineTerminator.matches(characters[i - 1]))) { + current.queueImmediately(pc, pc + 1, false); + } + break; + case LINE_END: + if (i == characters.length || (multiLine && + lineTerminator.matches(c))) { + current.queueImmediately(pc, pc + 1, false); + } + break; + case CHARACTER_CLASS: + if (classes[program[pc + 1]].matches(c)) { + current.queueNext(pc, pc + 2, next); + } + break; + case LOOKAHEAD: + if (lookarounds[program[pc + 1]].matches(characters, + i, characters.length, true, false, null)) { + current.queueImmediately(pc, pc + 2, false); + } + break; + case LOOKBEHIND: + if (lookarounds[program[pc + 1]].matches(characters, + i - 1, -1, true, false, null)) { + current.queueImmediately(pc, pc + 2, false); + } + break; + case NEGATIVE_LOOKAHEAD: + if (!lookarounds[program[pc + 1]].matches(characters, + i, characters.length, true, false, null)) { + current.queueImmediately(pc, pc + 2, false); + } + break; + case NEGATIVE_LOOKBEHIND: + if (!lookarounds[program[pc + 1]].matches(characters, + i - 1, -1, true, false, null)) { + current.queueImmediately(pc, pc + 2, false); + } + break; + /* immediate opcodes, i.e. thread continues within the same step */ + case SAVE_OFFSET: + if (result != null) { + int index = program[pc + 1]; + current.saveOffset(pc, index, i); + } + current.queueImmediately(pc, pc + 2, false); + break; + case SPLIT: + current.queueImmediately(pc, program[pc + 1], true); + current.queueImmediately(pc, pc + 2, false); + break; + case SPLIT_JMP: + current.queueImmediately(pc, pc + 2, true); + current.queueImmediately(pc, program[pc + 1], false); + break; + case JMP: + current.queueImmediately(pc, program[pc + 1], false); + break; + default: + if (program[pc] >= 0 && program[pc] <= 0xffff) { + if (c == (char)program[pc]) { + current.queueNext(pc, pc + 1, next); + } + break; + } + throw new RuntimeException("Invalid opcode: " + opcode + + " at pc " + pc); + } + } + // clean linked thread list (and states) + current.clean(); + + // prepare for next step + ThreadQueue swap = queued; + queued = next; + next = swap; + } + return foundMatch; + } + + /** + * Determines whether this machine recognizes a pattern without special + * operators. + *

+ * In case that the regular expression is actually a plain string without any + * special operators, we can avoid using a full-blown Pike VM and instead fall + * back to using the much faster {@link TrivialPattern}. + *

+ * + * @return the string to match, or null if the machine recognizes a + * non-trivial pattern + */ + public String isPlainString() { + // we expect the machine to start with the find preamble and SAVE_OFFSET 0 + // end with SAVE_OFFSET 1 + int start = findPrefixLength; + if (start + 1 < program.length && + program[start] == SAVE_OFFSET && program[start + 1] == 0) { + start += 2; + } + int end = program.length; + if (end > start + 1 && + program[end - 2] == SAVE_OFFSET && program[end - 1] == 1) { + end -= 2; + } + for (int i = start; i < end; ++ i) { + if (program[i] < 0) { + return null; + } + } + char[] array = new char[end - start]; + for (int i = start; i < end; ++ i) { + array[i - start] = (char)program[i]; + } + return new String(array); + } + + private static int length(int opcode) { + return opcode <= SINGLE_ARG_START && opcode >= SINGLE_ARG_END ? 2 : 1; + } + + private static boolean isJump(int opcode) { + return opcode <= SPLIT && opcode >= JMP; + } + + /** + * Reverses the program (effectively matching the reverse pattern). + *

+ * It is a well-known fact that any regular expression can be reordered + * trivially into an equivalent regular expression to be applied in backward + * direction (coming in real handy for look-behind expressions). + *

+ *

+ * Example: instead of matching the sequence "aaaabb" with the pattern "a+b+", + * we can match the reverse sequence "bbaaaa" with the pattern "b+a+". + *

+ *

+ * One caveat: while the reverse pattern is equivalent in the sense that it + * matches if, and only if, the original pattern matches the forward + * direction, the same is not true for submatches. Consider the input "a" and + * the pattern "(a?)a?": when matching in forward direction the captured group + * is "a", while the backward direction will yield the empty string. For that + * reason, Java dictates that capturing groups in look-behind patterns are + * ignored. + *

+ */ + public void reverse() { + reverse(findPrefixLength, program.length); + } + + /** + * Reverses a specific part of the program (to match in reverse direction). + *

+ * This is the work-horse of {@link #reverse()}. + *

+ *

+ * To visualize the process of reversing a program, let's look at it as a + * directed graph (each jump is represented by an "X + * ", non-jumping steps are represented by a "o"s, arrows show the + * direction of the flow, SPLITs spawn two arrows): + * + *

+   * o -> X -> X -> o -> X    o -> o
+   * ^    |     \         \___^____^
+   *  \__/       \____________|
+   * 
+ * + * The concept of reversing the program is easiest explained as following: if + * we insert auxiliary nodes "Y" for jump targets, the graph looks + * like this instead: + * + *
+   * Y -> o -> X -> X -> o -> X    Y -> o -> Y -> o
+   * ^         |     \         \___^_________^
+   *  \_______/       \____________|
+   * 
+ * + * It is now obvious that reversing the program is equivalent to reversing all + * arrows, simply deleting all Xs and substituting each Y + * with a jump. Note that the reverse program will have the same number of + * JMP, but they will not be associated with the same arrows!: + * + *
+   * X <- o <- o    X <- o <- X <- o
+   * |    ^    ^____|________/
+   *  \__/ \_______/
+   * 
+ * + *

+ * @param start + * start reversing the program with this instruction + * @param end + * stop reversing at this instruction (this must be either an index + * aligned exactly with an instruction, or exactly + * {@code program.length}. + */ + private void reverse(int start, int end) { + // Pass 1: build the list of jump targets + int[] newJumps = new int[end + 1]; + boolean[] brokenArrows = new boolean[end + 1]; + for (int pc = start; pc < end; pc += length(program[pc])) { + if (isJump(program[pc])) { + int target = program[pc + 1]; + newJumps[pc + 1] = newJumps[target]; + newJumps[target] = pc + 1; + if (program[pc] == JMP) { + brokenArrows[pc + 2] = true; + } + } + } + + // Pass 2: determine mapped program counters + int[] mapping = new int[end]; + for (int pc = start, mappedPC = end; mappedPC > 0 + && pc < end; pc += length(program[pc])) { + for (int jump = newJumps[pc]; jump > 0; jump = newJumps[jump]) { + mappedPC -= 2; + } + if (!isJump(program[pc])) { + mappedPC -= length(program[pc]); + } + mapping[pc] = mappedPC; + } + + // Pass 3: write the new program + int[] reverse = new int[end]; + for (int pc = start, mappedPC = end; mappedPC > 0; + pc += length(program[pc])) { + boolean brokenArrow = brokenArrows[pc]; + for (int jump = newJumps[pc]; jump > 0; jump = newJumps[jump]) { + reverse[--mappedPC] = mapping[jump - 1]; + if (brokenArrow) { + reverse[--mappedPC] = JMP; + brokenArrow = false; + } else { + reverse[--mappedPC] = + program[jump - 1] == SPLIT_JMP ? SPLIT_JMP : SPLIT; + } + } + if (pc == end) { + break; + } + if (!isJump(program[pc])) { + for (int i = length(program[pc]); i-- > 0; ) { + reverse[--mappedPC] = program[pc + i]; + } + } + } + System.arraycopy(reverse, start, program, start, end - start); + } +} diff --git a/sgx-jvm/avian/classpath/java/util/regex/PikeVMOpcodes.java b/sgx-jvm/avian/classpath/java/util/regex/PikeVMOpcodes.java new file mode 100644 index 0000000000..7558bf2736 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/util/regex/PikeVMOpcodes.java @@ -0,0 +1,45 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.util.regex; + +/** + * Opcodes for the Pike VM. + *

+ * See {@link PikeVM}. + *

+ * + * @author Johannes Schindelin + */ +interface PikeVMOpcodes { + final static int DOT = -1; + final static int DOTALL = -2; + + final static int WORD_BOUNDARY = -10; + final static int NON_WORD_BOUNDARY = -11; + final static int LINE_START = -12; + final static int LINE_END = -13; + + final static int CHARACTER_CLASS = -20; + + final static int LOOKAHEAD = -30; + final static int LOOKBEHIND = -31; + final static int NEGATIVE_LOOKAHEAD = -32; + final static int NEGATIVE_LOOKBEHIND = -33; + + final static int SAVE_OFFSET = -40; + + final static int SPLIT = -50; + final static int SPLIT_JMP = -51; // this split prefers to jump + final static int JMP = -52; + + final static int SINGLE_ARG_START = CHARACTER_CLASS; + final static int SINGLE_ARG_END = JMP; +} diff --git a/sgx-jvm/avian/classpath/java/util/regex/RegexMatcher.java b/sgx-jvm/avian/classpath/java/util/regex/RegexMatcher.java new file mode 100644 index 0000000000..acd4f9fa7f --- /dev/null +++ b/sgx-jvm/avian/classpath/java/util/regex/RegexMatcher.java @@ -0,0 +1,80 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.util.regex; + +/** + * A minimal implementation of a regular expression matcher. + * + * @author Johannes Schindelin + */ +public class RegexMatcher extends Matcher { + private final PikeVM vm; + private char[] array; + int[] groupStart, groupEnd; + + RegexMatcher(PikeVM vm, CharSequence string) { + super(string); + this.vm = vm; + } + + private final PikeVM.Result adapter = new PikeVM.Result() { + public void set(int[] start, int[] end) { + RegexMatcher.this.start = start[0]; + RegexMatcher.this.end = end[0]; + RegexMatcher.this.groupStart = start; + RegexMatcher.this.groupEnd = end; + } + }; + + public Matcher reset() { + start = end = -1; + return this; + } + + public Matcher reset(CharSequence input) { + this.input = input; + array = input.toString().toCharArray(); + return reset(); + } + + public boolean matches() { + return vm.matches(array, 0, array.length, true, true, adapter); + } + + public boolean find() { + return find(end + (start == end ? 1 : 0)); + } + + public boolean find(int offset) { + return vm.matches(array, offset, array.length, false, false, adapter); + } + + public int start(int group) { + return groupStart[group]; + } + + public int end(int group) { + return groupEnd[group]; + } + + public String group(int group) { + int offset = start(group); + if (offset < 0) { + return null; + } + int length = end(group) - offset; + return new String(array, offset, length); + } + + public int groupCount() { + return groupStart.length - 1; + } +} diff --git a/sgx-jvm/avian/classpath/java/util/regex/RegexPattern.java b/sgx-jvm/avian/classpath/java/util/regex/RegexPattern.java new file mode 100644 index 0000000000..cd7dcc582e --- /dev/null +++ b/sgx-jvm/avian/classpath/java/util/regex/RegexPattern.java @@ -0,0 +1,57 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.util.regex; + +/** + * A minimal implementation of a regular expression engine. + *

+ * Intended as a permissively-licensed drop-in replacement for Oracle JDK's + * regular expression engine, this class uses the Pike VM implemented in + * {@link PikeVM} to match regular expressions. + *

+ *

+ * The Pike VM not only has a nicer runtime performance than Oracle JDK's + * backtracking approach -- O(n*m) instead of O(2^m) where + * n is the length of the regular expression pattern (after normalizing + * {<n>} quantifiers) and m the length of the text to match against + * the pattern -- but also supports arbitrary-sized look-behinds. + *

+ *

+ * The current implementation supports all regular expression constructs + * supported by Oracle JDK's regular expression engine except for the following + * ones: + *

    + *
  • control characters: \cX
  • + *
  • extended character classes: \p{...}
  • + *
  • extended boundary matchers: \A,\G,\Z,\z
  • + *
  • possessive quantifiers: X?+
  • + *
  • back references: \<n>, \k<name>
  • + *
  • long escape: \Q, \E
  • + *
  • named groups: (?<name>X)
  • + *
  • flags: (?idmsuxU)
  • + *
  • independent, non-capturing group: (?>X)
  • + *
+ *

+ * + * @author Johannes Schindelin + */ +public class RegexPattern extends Pattern { + private PikeVM vm; + + public RegexMatcher matcher(CharSequence string) { + return new RegexMatcher(vm, string); + } + + RegexPattern(String regex, int flags, PikeVM vm) { + super(regex, flags); + this.vm = vm; + } +} diff --git a/sgx-jvm/avian/classpath/java/util/regex/TrivialMatcher.java b/sgx-jvm/avian/classpath/java/util/regex/TrivialMatcher.java new file mode 100644 index 0000000000..ed4360bf8c --- /dev/null +++ b/sgx-jvm/avian/classpath/java/util/regex/TrivialMatcher.java @@ -0,0 +1,48 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.util.regex; + +/** + * This is a work in progress. + * + * @author zsombor and others + */ +class TrivialMatcher extends Matcher { + private final String pattern; + + TrivialMatcher(String pattern, CharSequence input) { + super(input); + this.pattern = pattern; + } + + public boolean matches() { + if (pattern.equals(input.toString())) { + start = 0; + end = input.length(); + return true; + } else { + return false; + } + } + + public boolean find(int start) { + String p = pattern; + int i = TrivialPattern.indexOf(input, p, start); + if (i >= 0) { + this.start = i; + this.end = i + p.length(); + return true; + } else { + return false; + } + } +} + diff --git a/sgx-jvm/avian/classpath/java/util/regex/TrivialPattern.java b/sgx-jvm/avian/classpath/java/util/regex/TrivialPattern.java new file mode 100644 index 0000000000..5929375238 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/util/regex/TrivialPattern.java @@ -0,0 +1,112 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.util.regex; + +import java.util.Iterator; +import java.util.List; +import java.util.LinkedList; + +/** + * This is a work in progress. + * + * @author zsombor and others + * + */ +public class TrivialPattern extends Pattern { + + private final String unescaped; + + TrivialPattern(String pattern, String unescaped, int flags) { + super(pattern, flags); + this.unescaped = unescaped; + } + + public Matcher matcher(CharSequence input) { + return new TrivialMatcher(unescaped, input); + } + + public String[] split(CharSequence input, int limit) { + boolean strip; + if (limit < 0) { + strip = false; + limit = Integer.MAX_VALUE; + } else if (limit == 0) { + strip = true; + limit = Integer.MAX_VALUE; + } else { + strip = false; + } + + List list = new LinkedList(); + int index = 0; + int trailing = 0; + int patternLength = unescaped.length(); + while (index < input.length() && list.size() < limit - 1) { + int i; + if (patternLength == 0) { + if (list.size() == 0) { + i = 0; + } else { + i = index + 1; + } + } else { + i = indexOf(input, unescaped, index); + } + + if (i >= 0) { + if (patternLength != 0 && i == index) { + ++ trailing; + } else { + trailing = 0; + } + + list.add(input.subSequence(index, i)); + index = i + patternLength; + } else { + break; + } + } + + if (strip && index > 0 && index == input.length()) { + ++ trailing; + } else { + trailing = 0; + } + list.add(input.subSequence(index, input.length())); + + String[] result = new String[list.size() - trailing]; + int i = 0; + for (Iterator it = list.iterator(); + it.hasNext() && i < result.length; ++ i) + { + result[i] = it.next().toString(); + } + return result; + } + + static int indexOf(CharSequence haystack, CharSequence needle, int start) { + if (needle.length() == 0) return start; + + for (int i = start; i < haystack.length() - needle.length() + 1; ++i) { + int j = 0; + for (; j < needle.length(); ++j) { + if (haystack.charAt(i + j) != needle.charAt(j)) { + break; + } + } + if (j == needle.length()) { + return i; + } + } + + return -1; + } +} diff --git a/sgx-jvm/avian/classpath/java/util/zip/CRC32.java b/sgx-jvm/avian/classpath/java/util/zip/CRC32.java new file mode 100644 index 0000000000..cd587a4c71 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/util/zip/CRC32.java @@ -0,0 +1,69 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.util.zip; + +public class CRC32 { + private static final int Polynomial = 0x04C11DB7; + private static final int Width = 32; + private static final int Top = 1 << (Width - 1); + private static final int InitialRemainder = 0xFFFFFFFF; + private static final long ResultXor = 0xFFFFFFFFL; + + private static final int[] table = new int[256]; + + static { + for (int dividend = 0; dividend < 256; ++ dividend) { + int remainder = dividend << (Width - 8); + for (int bit = 8; bit > 0; --bit) { + remainder = ((remainder & Top) != 0) + ? (remainder << 1) ^ Polynomial + : (remainder << 1); + } + table[dividend] = remainder; + } + } + + private int remainder = InitialRemainder; + + public void reset() { + remainder = InitialRemainder; + } + + public void update(int b) { + remainder = table[reflect(b, 8) ^ (remainder >>> (Width - 8))] + ^ (remainder << 8); + } + + public void update(byte[] array, int offset, int length) { + for (int i = 0; i < length; ++i) { + update(array[offset + i] & 0xFF); + } + } + + public void update(byte[] array) { + update(array, 0, array.length); + } + + public long getValue() { + return (reflect(remainder, Width) ^ ResultXor) & 0xFFFFFFFFL; + } + + private static int reflect(int x, int n) { + int reflection = 0; + for (int i = 0; i < n; ++i) { + if ((x & 1) != 0) { + reflection |= (1 << ((n - 1) - i)); + } + x = (x >>> 1); + } + return reflection; + } +} diff --git a/sgx-jvm/avian/classpath/java/util/zip/DataFormatException.java b/sgx-jvm/avian/classpath/java/util/zip/DataFormatException.java new file mode 100644 index 0000000000..c5a7adbb22 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/util/zip/DataFormatException.java @@ -0,0 +1,21 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.util.zip; + +public class DataFormatException extends Exception { + public DataFormatException(String s) { + super(s); + } + + public DataFormatException() { + super(); + } +} diff --git a/sgx-jvm/avian/classpath/java/util/zip/Deflater.java b/sgx-jvm/avian/classpath/java/util/zip/Deflater.java new file mode 100644 index 0000000000..7a86294f77 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/util/zip/Deflater.java @@ -0,0 +1,162 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.util.zip; + +public class Deflater { + private static final int DEFAULT_LEVEL = 6; // default compression level (6 is default for gzip) + private static final int Z_OK = 0; + private static final int Z_STREAM_END = 1; + private static final int Z_NEED_DICT = 2; + +// static { +// System.loadLibrary("natives"); +// } + + private long peer; + private byte[] input; + private int offset; + private int length; + private boolean needDictionary; + private boolean finished; + private final boolean nowrap; + private boolean finish; + + public Deflater(int level, boolean nowrap) { + this.nowrap = nowrap; + peer = make(nowrap, level); + } + + public Deflater(int level) { + this(level, false); + } + + public Deflater() { + this(DEFAULT_LEVEL); + } + + private void check() { + if (peer == 0) { + throw new IllegalStateException(); + } + } + + private static native long make(boolean nowrap, int level); + + public boolean finished() { + return finished; + } + + public boolean needsDictionary() { + return needDictionary; + } + + public boolean needsInput() { + return getRemaining() == 0; + } + + public int getRemaining() { + return length; + } + + public void setLevel(int level) throws IllegalArgumentException { + if (level < 0 || level > 9) { + throw new IllegalArgumentException("Valid compression levels are 0-9"); + } + + dispose(peer); + peer = make(nowrap, level); + } + + public void setInput(byte[] input) { + setInput(input, 0, input.length); + } + + public void setInput(byte[] input, int offset, int length) { + this.input = input; + this.offset = offset; + this.length = length; + } + + public void reset() { + dispose(); + peer = make(nowrap, DEFAULT_LEVEL); + input = null; + offset = length = 0; + finish = false; + needDictionary = finished = false; + } + + public int deflate(byte[] output) { + return deflate(output, 0, output.length); + } + + public int deflate(byte[] output, int offset, int length) { + final int zlibResult = 0; + final int inputCount = 1; + final int outputCount = 2; + + if (peer == 0) { + throw new IllegalStateException(); + } + + if (input == null || output == null) { + throw new NullPointerException(); + } + + int[] results = new int[3]; + deflate(peer, + input, this.offset, this.length, + output, offset, length, finish, results); + + if (results[zlibResult] < 0) { + throw new AssertionError(); + } + + switch (results[zlibResult]) { + case Z_NEED_DICT: + needDictionary = true; + break; + + case Z_STREAM_END: + finished = true; + break; + } + + this.offset += results[inputCount]; + this.length -= results[inputCount]; + + return results[outputCount]; + } + + public void finish() { + finish = true; + } + + private static native void deflate + (long peer, + byte[] input, int inputOffset, int inputLength, + byte[] output, int outputOffset, int outputLength, + boolean finish, + int[] results); + + public void end() { + dispose(); + } + + public void dispose() { + if (peer != 0) { + dispose(peer); + peer = 0; + } + } + + private static native void dispose(long peer); +} diff --git a/sgx-jvm/avian/classpath/java/util/zip/DeflaterOutputStream.java b/sgx-jvm/avian/classpath/java/util/zip/DeflaterOutputStream.java new file mode 100644 index 0000000000..dc6320fcbb --- /dev/null +++ b/sgx-jvm/avian/classpath/java/util/zip/DeflaterOutputStream.java @@ -0,0 +1,81 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.util.zip; + +import java.io.OutputStream; +import java.io.FilterOutputStream; +import java.io.IOException; + +public class DeflaterOutputStream extends FilterOutputStream { + protected final Deflater deflater; + protected final byte[] buffer; + + public DeflaterOutputStream(OutputStream out, Deflater deflater, int bufferSize) + { + super(out); + this.deflater = deflater; + this.buffer = new byte[bufferSize]; + } + + public DeflaterOutputStream(OutputStream out, Deflater deflater) { + this(out, deflater, 4 * 1024); + } + + public DeflaterOutputStream(OutputStream out) { + this(out, new Deflater()); + } + + public void write(int b) throws IOException { + byte[] buffer = new byte[1]; + buffer[0] = (byte)(b & 0xff); + write(buffer, 0, 1); + } + + public void write(byte[] b) throws IOException { + write(b, 0, b.length); + } + + public void write(byte[] b, int offset, int length) throws IOException { + // error condition checking + if (deflater.finished()) { + throw new IOException("Already at end of stream"); + } else if (offset < 0) { + throw new IndexOutOfBoundsException("Offset can't be less than zero"); + } else if (length < 0) { + throw new IndexOutOfBoundsException("Length can't be less than zero"); + } else if (b.length - (offset + length) < 0) { + throw new IndexOutOfBoundsException("Offset + Length is larger than the input byte array"); + } else if (length == 0) { + return; + } + + deflater.setInput(b, offset, length); + while (deflater.getRemaining() > 0) { + deflate(); + } + } + + private void deflate() throws IOException { + int len = deflater.deflate(buffer, 0, buffer.length); + if (len > 0) { + out.write(buffer, 0, len); + } + } + + public void close() throws IOException { + deflater.finish(); + while (! deflater.finished()) { + deflate(); + } + out.close(); + deflater.dispose(); + } +} diff --git a/sgx-jvm/avian/classpath/java/util/zip/Inflater.java b/sgx-jvm/avian/classpath/java/util/zip/Inflater.java new file mode 100644 index 0000000000..2c0b7e0466 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/util/zip/Inflater.java @@ -0,0 +1,142 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.util.zip; + +public class Inflater { + private static final int Z_OK = 0; + private static final int Z_STREAM_END = 1; + private static final int Z_NEED_DICT = 2; + +// static { +// System.loadLibrary("natives"); +// } + + private long peer; + private byte[] input; + private int offset; + private int length; + private boolean needDictionary; + private boolean finished; + private final boolean nowrap; + + public Inflater(boolean nowrap) { + this.nowrap = nowrap; + peer = make(nowrap); + } + + public Inflater() { + this(false); + } + + private void check() { + if (peer == 0) { + throw new IllegalStateException(); + } + } + + private static native long make(boolean nowrap); + + public boolean finished() { + return finished; + } + + public boolean needsDictionary() { + return needDictionary; + } + + public boolean needsInput() { + return getRemaining() == 0; + } + + public int getRemaining() { + return length; + } + + public void setInput(byte[] input) { + setInput(input, 0, input.length); + } + + public void setInput(byte[] input, int offset, int length) { + this.input = input; + this.offset = offset; + this.length = length; + } + + public void reset() { + dispose(); + peer = make(nowrap); + input = null; + offset = length = 0; + needDictionary = finished = false; + } + + public int inflate(byte[] output) throws DataFormatException { + return inflate(output, 0, output.length); + } + + public int inflate(byte[] output, int offset, int length) + throws DataFormatException + { + final int zlibResult = 0; + final int inputCount = 1; + final int outputCount = 2; + + if (peer == 0) { + throw new IllegalStateException(); + } + + if (input == null || output == null) { + throw new NullPointerException(); + } + + int[] results = new int[3]; + inflate(peer, input, this.offset, this.length, + output, offset, length, results); + + if (results[zlibResult] < 0) { + throw new DataFormatException(); + } + + switch (results[zlibResult]) { + case Z_NEED_DICT: + needDictionary = true; + break; + + case Z_STREAM_END: + finished = true; + break; + } + + this.offset += results[inputCount]; + this.length -= results[inputCount]; + + return results[outputCount]; + } + + private static native void inflate + (long peer, + byte[] input, int inputOffset, int inputLength, + byte[] output, int outputOffset, int outputLength, + int[] results); + + public void end() { + dispose(); + } + + public void dispose() { + if (peer != 0) { + dispose(peer); + peer = 0; + } + } + + private static native void dispose(long peer); +} diff --git a/sgx-jvm/avian/classpath/java/util/zip/InflaterInputStream.java b/sgx-jvm/avian/classpath/java/util/zip/InflaterInputStream.java new file mode 100644 index 0000000000..fcefaec87b --- /dev/null +++ b/sgx-jvm/avian/classpath/java/util/zip/InflaterInputStream.java @@ -0,0 +1,81 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.util.zip; + +import java.io.InputStream; +import java.io.IOException; +import java.io.EOFException; + +public class InflaterInputStream extends InputStream { + private final InputStream in; + private final Inflater inflater; + private final byte[] buffer; + + public InflaterInputStream(InputStream in, Inflater inflater, int bufferSize) + { + this.in = in; + this.inflater = inflater; + this.buffer = new byte[bufferSize]; + } + + public InflaterInputStream(InputStream in, Inflater inflater) { + this(in, inflater, 4 * 1024); + } + + public InflaterInputStream(InputStream in) { + this(in, new Inflater()); + } + + public int read() throws IOException { + byte[] buffer = new byte[1]; + int c = read(buffer); + return (c < 0 ? c : (buffer[0] & 0xFF)); + } + + public int read(byte[] b, int offset, int length) throws IOException { + if (inflater.finished()) { + return -1; + } + + while (true) { + if (inflater.needsInput()) { + int count = in.read(buffer); + if (count > 0) { + inflater.setInput(buffer, 0, count); + } else { + throw new EOFException(); + } + } + + try { + int count = inflater.inflate(b, offset, length); + if (count > 0) { + return count; + } else if (inflater.needsDictionary()) { + throw new IOException("missing dictionary"); + } else if (inflater.finished()) { + return -1; + } + } catch (DataFormatException e) { + throw new IOException(e); + } + } + } + + public int available() throws IOException { + return inflater.finished() ? 0 : 1; + } + + public void close() throws IOException { + in.close(); + inflater.dispose(); + } +} diff --git a/sgx-jvm/avian/classpath/java/util/zip/ZipEntry.java b/sgx-jvm/avian/classpath/java/util/zip/ZipEntry.java new file mode 100644 index 0000000000..482f9d0347 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/util/zip/ZipEntry.java @@ -0,0 +1,210 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.util.zip; + +/** + * Class ZipEntry: + * + * Class to store and retrieve information for entries in a zip file + * Contains variables for all standard zip format field as well as + * setter and accessor methods + * + * "name" is used to store the string name of the entrys + * "reqVersion" stores a byte encoded minimum required version to open the zip + * "compressionMethod" stores the method used to compress the zip + * "modTimeDate" stores an MSDOS time field "millisTime" stores time in long format + * "crc" stores crc data for the zip entry + * "compSize" and "uncompSize" store compressed and uncompressed sizes + * "offset" stores data regarding the offset from the start of the zip file + * + * @author Christopher Jordan + * @author David Chau + * @author Aaron Davis + * @author Riley Moses + */ + +import java.util.Calendar; +import java.util.Date; + + +public class ZipEntry { + String name; + short reqVersion = -1; + short compressionMethod = -1; + int modTimeDate = -1; + long millisTime = -1; + int crc = -1; + long compSize = 0; + long uncompSize = 0; + int offset = -1; + + public ZipEntry(String name) { + this.name = name; + setTime(System.currentTimeMillis()); + } + + //Method to return name of the file + public String getName() { + return name; + } + + //Method to check if file is a directory + public boolean isDirectory() { + return getName().endsWith("/"); + } + + /** + * Method setRequiredVersion: + * + * Method to set the minimum version required to open the zip file + * Valid values for the compression method are the numbers 1.0 to 10.0 + * + * @author Christopher Jordan + */ + private boolean setRequiredVersion(float versionFloat){ + //Check for valid version numbers + if (versionFloat < 1 || versionFloat > 100){ + return false; + } + + //Convert to short value for storage + versionFloat = versionFloat * 10; + short versionShort = (short)versionFloat; + + //Set value of version + reqVersion = versionShort; + return true; + } + + //Method to set the compression method for the file + //Valid methods are "stored" = 0 or "deflated" = 8 + public void setMethod(short compMethod){ + if (compMethod == 0 || compMethod == 8){ + this.compressionMethod = compMethod; + } + } + + public int getMethod(){ + return this.compressionMethod; + } + + //Methods to set and get the crc for the entry + public void setCrc(int crc){ + if (crc < 0 || crc > 0xffffffff){ + return; + } + else + this.crc = crc; + } + + public int getCrc(){ + return this.crc; + } + + //Methods to set and get the time and date + public void setTime(long currentTime){ + modTimeDate = computeDOSDateTime(currentTime); + millisTime = currentTime; + } + + public long getTime(){ + return millisTime; + } + + /** + * Method computeDOSDateTime(): + * + * Takes the time from a long and converts to a Calendar object + * + * Time is stored in the MSDOS format 5 bits for hour, 6 bits for min, 5 bits for seconds + * Hours are in military time and must be adjusted to time zone + * Seconds are divided by two before storing and must be multiplied by two to retrieve + * + * Date is stored in the MSDOS format 7 bit for year, 4 bit for month, 5 bits for day of month + * Year is the number of years since 1980 per, the month is stored starting at 0 + * for January. Day of month is stored with nature numbering + * + * Bit masks and shifting are used to build the time and date bytes + * + * @author Christopher Jordan + * @author Aaron Davis + **/ + private static int computeDOSDateTime(long currentTime){ + final int DAY_OF_MONTH = 5; + final int HOUR_OF_DAY = 11; + final int MINUTE = 12; + final int MONTH = 2; + final int SECOND = 13; + final int YEAR = 1; + + //Create calendar object, then set time to value passed in + Calendar modCalendar = Calendar.getInstance(); + modCalendar.setTime(new Date(currentTime)); + + //Hour + int timeBits = modCalendar.get(HOUR_OF_DAY); + timeBits = timeBits - 6; + timeBits = timeBits << 6; + + //Minutes + int minBits = 0x3f & (modCalendar.get(MINUTE));; + timeBits = timeBits ^ minBits; + timeBits = timeBits << 5; + + //Seconds + int secBits = 0x1f & (modCalendar.get(SECOND)); + secBits = secBits >> 1; //Divide by 2 + timeBits = timeBits ^ secBits; + + //Year + int dateBits = (modCalendar.get(YEAR) -1980); + dateBits = dateBits << 4; + + //Month + int month = 0xf & ((modCalendar.get(MONTH)) + 1); + dateBits = dateBits ^ month; + dateBits = dateBits << 5; + + //Day of month + int dayBits = 0x1f & modCalendar.get(DAY_OF_MONTH); + dateBits = dateBits ^ dayBits; + + //Store Date + int storeDate = ((dateBits << 16) ^ (timeBits)); + return storeDate; + } + + //Methods to set and get the uncompressed size of the entry + public void setSize(int size){ + if (size < 0){ + return; + } + else + uncompSize = size; + } + + public long getSize() { + return uncompSize; + } + + //Methods to set and get the compressed size of the entry + public void setCompressedSize(long size){ + if (size < 0){ + return; + } + else + compSize = size; + } + + public long getCompressedSize() { + return compSize; + } +} diff --git a/sgx-jvm/avian/classpath/java/util/zip/ZipFile.java b/sgx-jvm/avian/classpath/java/util/zip/ZipFile.java new file mode 100644 index 0000000000..17159ea7da --- /dev/null +++ b/sgx-jvm/avian/classpath/java/util/zip/ZipFile.java @@ -0,0 +1,389 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.util.zip; + +import java.io.File; +import java.io.RandomAccessFile; +import java.io.InputStream; +import java.io.IOException; +import java.util.Enumeration; +import java.util.Iterator; +import java.util.Map; +import java.util.HashMap; + +public class ZipFile { + private final RandomAccessFile file; + private final Window window; + private final Map index = new HashMap(); + + public ZipFile(String name) throws IOException { + file = new RandomAccessFile(name, "r"); + window = new Window(file, 4096); + + int fileLength = (int) file.length(); + int pointer = fileLength - 22; + byte[] magic = new byte[] { 0x50, 0x4B, 0x05, 0x06 }; + while (pointer > 0) { + if (equal(window.data, window.seek(pointer, magic.length), + magic, 0, magic.length)) + { + pointer = directoryOffset(window, pointer); + + magic = new byte[] { 0x50, 0x4B, 0x01, 0x02 }; + while (pointer < fileLength) { + if (equal(window.data, window.seek(pointer, magic.length), + magic, 0, magic.length)) + { + index.put(entryName(window, pointer), pointer); + pointer = entryEnd(window, pointer); + } else { + pointer = fileLength; + } + } + pointer = 0; + } else { + -- pointer; + } + } + } + + public ZipFile(File file) throws IOException { + this(file.getAbsolutePath()); + } + + public int size() { + return index.size(); + } + + protected Enumeration makeEnumeration + (EntryFactory factory) + { + return new MyEnumeration(factory, window, index.values().iterator()); + } + + public Enumeration entries() { + return makeEnumeration(ZipEntryFactory.Instance); + } + + protected ZipEntry getEntry(EntryFactory factory, String name) { + while (name.startsWith("/")) { + name = name.substring(1); + } + Integer pointer = index.get(name); + return (pointer == null ? null : factory.makeEntry(window, pointer)); + } + + public ZipEntry getEntry(String name) { + return getEntry(ZipEntryFactory.Instance, name); + } + + public InputStream getInputStream(ZipEntry entry) throws IOException { + final int pointer = ((MyEntry) entry).pointer(); + int method = compressionMethod(window, pointer); + int size = compressedSize(window, pointer); + InputStream in = new MyInputStream(file, fileData(window, pointer), size); + + final int Stored = 0; + final int Deflated = 8; + + switch (method) { + case Stored: + return in; + + case Deflated: + return new InflaterInputStream(in, new Inflater(true)) { + int remaining = uncompressedSize(window, pointer); + + public int read() throws IOException { + byte[] buffer = new byte[1]; + int c = read(buffer); + return (c < 0 ? c : (buffer[0] & 0xFF)); + } + + public int read(byte[] buffer) throws IOException { + return read(buffer, 0, buffer.length); + } + + public int read(byte[] buffer, int offset, int length) + throws IOException + { + int c = super.read(buffer, offset, length); + if (c > 0) { + remaining -= c; + } + return c; + } + + public int available() { + return remaining; + } + }; + + default: + throw new IOException(); + } + } + + private static boolean equal(byte[] a, int aOffset, byte[] b, int bOffset, + int size) + { + for (int i = 0; i < size; ++i) { + if (a[aOffset + i] != b[bOffset + i]) return false; + } + return true; + } + + private static int get2(Window w, int p) throws IOException { + int offset = w.seek(p, 2); + return + ((w.data[offset + 1] & 0xFF) << 8) | + ((w.data[offset ] & 0xFF) ); + } + + private static int get4(Window w, int p) throws IOException { + int offset = w.seek(p, 4); + return + ((w.data[offset + 3] & 0xFF) << 24) | + ((w.data[offset + 2] & 0xFF) << 16) | + ((w.data[offset + 1] & 0xFF) << 8) | + ((w.data[offset ] & 0xFF) ); + } + + private static int directoryOffset(Window w, int p) throws IOException { + return get4(w, p + 16); + } + + private static int entryNameLength(Window w, int p) throws IOException { + return get2(w, p + 28); + } + + protected static String entryName(Window w, int p) throws IOException { + int length = entryNameLength(w, p); + return new String(w.data, w.seek(p + 46, length), length); + } + + private static int compressionMethod(Window w, int p) throws IOException { + return get2(w, p + 10); + } + + protected static int compressedSize(Window w, int p) throws IOException { + return get4(w, p + 20); + } + + protected static int uncompressedSize(Window w, int p) throws IOException { + return get4(w, p + 24); + } + + private static int fileNameLength(Window w, int p) throws IOException { + return get2(w, p + 28); + } + + private static int extraFieldLength(Window w, int p) throws IOException { + return get2(w, p + 30); + } + + private static int commentFieldLength(Window w, int p) throws IOException { + return get2(w, p + 32); + } + + private static int entryEnd(Window w, int p) throws IOException { + final int HeaderSize = 46; + return p + HeaderSize + + fileNameLength(w, p) + + extraFieldLength(w, p) + + commentFieldLength(w, p); + } + + private static int fileData(Window w, int p) throws IOException { + int localHeader = localHeader(w, p); + final int LocalHeaderSize = 30; + return localHeader + + LocalHeaderSize + + localFileNameLength(w, localHeader) + + localExtraFieldLength(w, localHeader); + } + + private static int localHeader(Window w, int p) throws IOException { + return get4(w, p + 42); + } + + private static int localFileNameLength(Window w, int p) throws IOException { + return get2(w, p + 26); + } + + private static int localExtraFieldLength(Window w, int p) + throws IOException + { + return get2(w, p + 28); + } + + public void close() throws IOException { + file.close(); + } + + protected static class Window { + private final RandomAccessFile file; + public final byte[] data; + public int start; + public int length; + + public Window(RandomAccessFile file, int size) { + this.file = file; + data = new byte[size]; + } + + public int seek(int start, int length) throws IOException { + int fileLength = (int) file.length(); + + if (length > data.length) { + throw new IllegalArgumentException + ("length " + length + " greater than buffer length " + data.length); + } + + if (start < 0) { + throw new IllegalArgumentException("negative start " + start); + } + + if (start + length > fileLength) { + throw new IllegalArgumentException + ("end " + (start + length) + " greater than file length " + + fileLength); + } + + if (start < this.start || start + length > this.start + this.length) { + this.length = Math.min(data.length, fileLength); + this.start = start - ((this.length - length) / 2); + if (this.start < 0) { + this.start = 0; + } else if (this.start + this.length > fileLength) { + this.start = fileLength - this.length; + } + file.seek(this.start); + file.readFully(data, 0, this.length); + } + + return start - this.start; + } + } + + protected interface MyEntry { + public int pointer(); + } + + private static class MyZipEntry extends ZipEntry implements MyEntry { + public final Window window; + public final int pointer; + + public MyZipEntry(Window window, int pointer) { + super(null); + this.window = window; + this.pointer = pointer; + } + + public String getName() { + try { + return entryName(window, pointer); + } catch (IOException e) { + return null; + } + } + + public long getCompressedSize() { + try { + return compressedSize(window, pointer); + } catch (IOException e) { + return 0; + } + } + + public long getSize() { + try { + return uncompressedSize(window, pointer); + } catch (IOException e) { + return 0; + } + } + + public int pointer() { + return pointer; + } + } + + protected interface EntryFactory { + public ZipEntry makeEntry(Window window, int pointer); + } + + private static class ZipEntryFactory implements EntryFactory { + public static final ZipEntryFactory Instance = new ZipEntryFactory(); + + public ZipEntry makeEntry(Window window, int pointer) { + return new MyZipEntry(window, pointer); + } + } + + private static class MyEnumeration implements Enumeration { + private final EntryFactory factory; + private final Window window; + private final Iterator iterator; + + public MyEnumeration(EntryFactory factory, Window window, + Iterator iterator) + { + this.factory = factory; + this.window = window; + this.iterator = iterator; + } + + public boolean hasMoreElements() { + return iterator.hasNext(); + } + + public ZipEntry nextElement() { + return factory.makeEntry(window, iterator.next()); + } + } + + private static class MyInputStream extends InputStream { + private RandomAccessFile file; + private int offset; + private int length; + + public MyInputStream(RandomAccessFile file, int start, int length) { + this.file = file; + this.offset = start; + this.length = length; + } + + public int read() throws IOException { + byte[] b = new byte[1]; + int c = read(b); + return (c == -1 ? -1 : b[0] & 0xFF); + } + + public int read(byte[] b, int offset, int length) throws IOException { + if (this.length == 0) return -1; + + if (length > this.length) length = this.length; + + file.seek(this.offset); + file.readFully(b, offset, length); + + this.offset += length; + this.length -= length; + + return length; + } + + public void close() throws IOException { + file = null; + } + } +} diff --git a/sgx-jvm/avian/classpath/java/util/zip/ZipOutputStream.java b/sgx-jvm/avian/classpath/java/util/zip/ZipOutputStream.java new file mode 100644 index 0000000000..e5b929ac72 --- /dev/null +++ b/sgx-jvm/avian/classpath/java/util/zip/ZipOutputStream.java @@ -0,0 +1,246 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.util.zip; + +import java.io.IOException; +import java.io.OutputStream; +import java.io.UnsupportedEncodingException; +import java.util.ArrayList; +import java.util.List; +import java.util.zip.CRC32; +import java.util.zip.DeflaterOutputStream; +import java.util.zip.Deflater; + + +/** + * An as simple as possible implementation of ZipOutputStream + * Compression method defaults to DEFLATE + * All hardcoded defaults match the defaults for openJDK, + * including PKZip version, bit flags set, compression level, etc + * + * @author David Chau + * @author Aaron Davis + * @author Christopher Jordan + * @author Riley Moses + * + */ +public class ZipOutputStream extends DeflaterOutputStream { + private static final int SIGNATURE = 0x04034b50; + private static final short VERSION = 0x0014; + private static final short BITFLAG = 0x0008; + private static final short METHOD = 0x0008; + private static final int CENTRAL_FILE_HEADER = 0x02014b50; + private static final int DATA_DESCRIPTER_HEADER = 0x08074b50; + private static final int END_OF_CENTRAL_DIRECTORY_SIG = 0x06054b50; + private static final int DEFAULT_LEVEL = 6; + + private static final int INPUT_BUFFER_SIZE = 1024; + + private List entries; + private CRC32 crc = new CRC32(); + private ZipEntry currentEntry; // holder for current entry + private int bytesWritten; // a counter for total bytes written + private int sizeOfCentralDirectory; // a counter for central dir size + + // these are used for the function write(int b) to provide a speed increase + private byte[] inputBuffer = new byte[INPUT_BUFFER_SIZE]; + private int bufferIndex; + + + public ZipOutputStream(OutputStream outStream) { + super(outStream, new Deflater(DEFAULT_LEVEL, true)); + bytesWritten = 0; + sizeOfCentralDirectory = 0; + entries = new ArrayList(); + } + + public void putNextEntry(ZipEntry e) throws IOException { + e.offset = bytesWritten; + currentEntry = e; + entries.add(e); + writeLocalHeader(e); + } + + public void closeEntry() throws IOException { + // write remainder of buffer if partially full + if (bufferIndex != 0) { + write(inputBuffer, 0, bufferIndex); + bufferIndex = 0; + } + + finish(); + + currentEntry.crc = (int) crc.getValue(); + crc.reset(); + writeDataDescriptor(currentEntry); + } + + @Override + public void write(byte[] b, int offset, int length) throws IOException { + if (offset < 0 || length < 0 || b.length - (offset + length) < 0) + throw new IndexOutOfBoundsException(); + + currentEntry.uncompSize += length; + crc.update(b, offset, length); + currentEntry.crc = (int) crc.getValue(); + + deflater.setInput(b, offset, length); + while (deflater.getRemaining() > 0) + deflate(); + } + + @Override + public void write(int b) throws IOException { + inputBuffer[bufferIndex] = (byte)(b & 0xff); + bufferIndex += 1; + if (bufferIndex == 1024) { + write(inputBuffer, 0, bufferIndex); + bufferIndex = 0; + } + } + + private void deflate() throws IOException { + int len = deflater.deflate(buffer, 0, buffer.length); + currentEntry.compSize += len; + bytesWritten += len; + if (len > 0) + out.write(buffer, 0, len); + } + + private void writeLocalHeader(ZipEntry e) throws IOException { + byte[] tmpBuffer = new byte[30]; + + addFourBytes(SIGNATURE, 0, tmpBuffer); // local header signature + addTwoBytes(VERSION, 4, tmpBuffer); // version used + addTwoBytes(BITFLAG, 6, tmpBuffer); // flags + addTwoBytes(METHOD, 8, tmpBuffer); // compression method + addFourBytes(e.modTimeDate, 10, tmpBuffer); // last mod date and time + addFourBytes(0, 14, tmpBuffer); // CRC is 0 for local header + + // with default flag settings (bit 3 set) the compressed and uncompressed size + // is written here as 0 and written correctly in the data descripter + addFourBytes(0, 18, tmpBuffer); // compressed size + addFourBytes(0, 22, tmpBuffer); // uncompressed size + addTwoBytes(e.name.length(), 26, tmpBuffer); // length of file name + + // extra field length, in this implementation extra field in not used + addTwoBytes(0, 28, tmpBuffer); + + out.write(tmpBuffer, 0, 30); + + // write file name, return the number of bytes written + int len = writeUTF8(e.getName()); + + bytesWritten += 30 + len; + } + + private void writeDataDescriptor(ZipEntry currentEntry) throws IOException { + byte[] tmpBuffer = new byte[16]; + + addFourBytes(DATA_DESCRIPTER_HEADER, 0, tmpBuffer); // data descripter header + addFourBytes(currentEntry.crc, 4, tmpBuffer); // crc value + addFourBytes((int)currentEntry.compSize, 8, tmpBuffer); // compressed size + addFourBytes((int)currentEntry.uncompSize, 12, tmpBuffer);// uncompressed size + out.write(tmpBuffer, 0, 16); + bytesWritten += 16; + } + + private void writeCentralDirectoryHeader(ZipEntry e) throws IOException { + byte[] tmpBuffer = new byte[46]; + + addFourBytes(CENTRAL_FILE_HEADER, 0, tmpBuffer); // central directory header signature + addTwoBytes(VERSION, 4, tmpBuffer); // version made by + addTwoBytes(VERSION, 6, tmpBuffer); // version needed + addTwoBytes(BITFLAG, 8, tmpBuffer); // flags + addTwoBytes(METHOD, 10, tmpBuffer); // compression method + + addFourBytes(e.modTimeDate, 12, tmpBuffer); // last mod date and time + addFourBytes(e.crc, 16, tmpBuffer); // crc + addFourBytes((int)e.compSize, 20, tmpBuffer); // compressed size + addFourBytes((int)e.uncompSize, 24, tmpBuffer); // uncompressed size + + addTwoBytes(e.getName().length(), 28, tmpBuffer); // file name length + + // the following 5 fields are all 0 for a simple default compression + addTwoBytes(0, 30, tmpBuffer); // extra field length (not used) + addTwoBytes(0, 32, tmpBuffer); // comment length (not used) + addTwoBytes(0, 34, tmpBuffer); // disk number start + addTwoBytes(0, 36, tmpBuffer); // internal file attribute + addFourBytes(0, 38, tmpBuffer); // external file attribute + + addFourBytes((int) e.offset, 42, tmpBuffer); // relative offset of local header + + out.write(tmpBuffer, 0, 46); + + int len = writeUTF8(e.getName()); + + bytesWritten += 46 + len; + sizeOfCentralDirectory += 46 + len; + } + + private void writeEndofCentralDirectory(int offset) throws IOException { + byte[] tmpBuffer = new byte[22]; + + short numEntries = (short) entries.size(); + addFourBytes(END_OF_CENTRAL_DIRECTORY_SIG, 0, tmpBuffer); // end of central directory signature + addTwoBytes(0, 4, tmpBuffer); // disk number + addTwoBytes(0, 6, tmpBuffer); // disk number where central dir starts + addTwoBytes(numEntries, 8, tmpBuffer); // number of entries on this disk + addTwoBytes(numEntries, 10, tmpBuffer); // number of entries in central dir + addFourBytes(sizeOfCentralDirectory, 12, tmpBuffer); // length of central directory + addFourBytes(offset, 16, tmpBuffer); // offset of central directory + addTwoBytes(0, 20, tmpBuffer); // length of added comments (not used) + out.write(tmpBuffer, 0, 22); + bytesWritten += 22; + } + + @Override + public void close() throws IOException { + int centralDirOffset = bytesWritten; + for (ZipEntry e : entries) + writeCentralDirectoryHeader(e); + writeEndofCentralDirectory(centralDirOffset); + deflater.dispose(); + out.close(); + } + + @Override + public void flush() throws IOException { + out.write(inputBuffer, 0, inputBuffer.length); + inputBuffer = new byte[INPUT_BUFFER_SIZE]; + } + + private void finish() throws IOException { + deflater.finish(); + while (!deflater.finished()) { + deflate(); + } + deflater.reset(); + } + + private void addTwoBytes(int bytes, int offset, byte[] buffer) throws IOException { + buffer[offset] = (byte) (bytes & 0xff); + buffer[offset + 1] = (byte) ((bytes >> 8) & 0xff); + } + + private void addFourBytes(int bytes, int offset, byte[] buffer) throws IOException { + buffer[offset] = (byte) (bytes & 0xff); + buffer[offset + 1] = (byte) ((bytes >> 8) & 0xff); + buffer[offset + 2] = (byte) ((bytes >> 16) & 0xff); + buffer[offset + 3] = (byte) ((bytes >> 24) & 0xff); + } + + private int writeUTF8(String text) throws IOException { + byte[] bytes = text.getBytes("UTF-8"); + out.write(bytes, 0, bytes.length); + return bytes.length; + } +} \ No newline at end of file diff --git a/sgx-jvm/avian/classpath/jni-util.h b/sgx-jvm/avian/classpath/jni-util.h new file mode 100644 index 0000000000..f77a4104eb --- /dev/null +++ b/sgx-jvm/avian/classpath/jni-util.h @@ -0,0 +1,127 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#ifndef JNI_UTIL +#define JNI_UTIL + +#include "stdio.h" +#include "stdlib.h" +#include "string.h" + +#include + +#undef JNIEXPORT + +#ifdef UNUSED +#undef UNUSED +#endif + +#if (defined __MINGW32__) || (defined _MSC_VER) +#define PLATFORM_WINDOWS +#define PATH_SEPARATOR ';' +#define JNIEXPORT __declspec(dllexport) +#else // not (defined __MINGW32__) || (defined _MSC_VER) +#define PLATFORM_POSIX +#define PATH_SEPARATOR ':' +#define JNIEXPORT __attribute__((visibility("default"))) __attribute__((used)) +#endif // not (defined __MINGW32__) || (defined _MSC_VER) + +#ifdef _MSC_VER + +#define UNUSED + +typedef char int8_t; +typedef unsigned char uint8_t; +typedef short int16_t; +typedef unsigned short uint16_t; +typedef int int32_t; +typedef unsigned int uint32_t; +typedef __int64 int64_t; +typedef unsigned __int64 uint64_t; + +#define INT32_MAX 2147483647 + +#define not! +#define or || +#define and && +#define xor ^ + +#ifdef _M_IX86 +#define ARCH_x86_32 +#elif defined _M_X64 +#define ARCH_x86_64 +#endif + +#else // not _MSC_VER + +#define UNUSED __attribute__((unused)) + +#include "stdint.h" +#include "errno.h" + +#ifdef __i386__ +#define ARCH_x86_32 +#elif defined __x86_64__ +#define ARCH_x86_64 +#elif defined __arm__ +#define ARCH_arm +#elif defined __aarch64__ +#define ARCH_arm64 +#endif + +#endif // not _MSC_VER + +inline void throwNew(JNIEnv* e, const char* class_, const char* message, ...) +{ + jclass c = e->FindClass(class_); + if (c) { + if (message) { + static const unsigned BufferSize = 256; + char buffer[BufferSize]; + + va_list list; + va_start(list, message); +#ifdef _MSC_VER + vsnprintf_s(buffer, BufferSize - 1, _TRUNCATE, message, list); +#else + vsnprintf(buffer, BufferSize - 1, message, list); +#endif + va_end(list); + + e->ThrowNew(c, buffer); + } else { + e->ThrowNew(c, 0); + } + e->DeleteLocalRef(c); + } +} + +inline void throwNewErrno(JNIEnv* e, const char* class_) +{ +#ifdef _MSC_VER + const unsigned size = 128; + char buffer[size]; + strerror_s(buffer, size, errno); + throwNew(e, class_, buffer); +#else + throwNew(e, class_, strerror(errno)); +#endif +} + +inline void* allocate(JNIEnv* e, unsigned size) +{ + void* p = malloc(size); + if (p == 0) { + throwNew(e, "java/lang/OutOfMemoryError", 0); + } + return p; +} + +#endif // JNI_UTIL diff --git a/sgx-jvm/avian/classpath/libcore/reflect/AnnotationAccess.java b/sgx-jvm/avian/classpath/libcore/reflect/AnnotationAccess.java new file mode 100644 index 0000000000..750fe9cadf --- /dev/null +++ b/sgx-jvm/avian/classpath/libcore/reflect/AnnotationAccess.java @@ -0,0 +1,8 @@ +package libcore.reflect; + +import java.lang.reflect.AccessibleObject; + +public class AnnotationAccess { + public static native AccessibleObject getEnclosingMethodOrConstructor + (Class c); +} diff --git a/sgx-jvm/avian/classpath/sockets.cpp b/sgx-jvm/avian/classpath/sockets.cpp new file mode 100644 index 0000000000..ddffc18576 --- /dev/null +++ b/sgx-jvm/avian/classpath/sockets.cpp @@ -0,0 +1,205 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +/* + * This file implements a simple cross-platform JNI sockets API + * It is used from different classes of the default Avian classpath + */ + +#ifndef SGX + +#include "sockets.h" + +namespace avian { +namespace classpath { +namespace sockets { + +int last_socket_error() +{ +#ifdef PLATFORM_WINDOWS + int error = WSAGetLastError(); +#else + int error = errno; +#endif + return error; +} + +void init(JNIEnv* ONLY_ON_WINDOWS(e)) +{ +#ifdef PLATFORM_WINDOWS + static bool wsaInitialized = false; + if (not wsaInitialized) { + WSADATA data; + int r = WSAStartup(MAKEWORD(2, 2), &data); + if (r or LOBYTE(data.wVersion) != 2 or HIBYTE(data.wVersion) != 2) { + throwNew(e, "java/io/IOException", "WSAStartup failed"); + } else { + wsaInitialized = true; + } + } +#endif +} + +SOCKET create(JNIEnv* e) +{ + SOCKET sock; + if (INVALID_SOCKET == (sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP))) { + char buf[255]; + sprintf( + buf, "Can't create a socket. System error: %d", last_socket_error()); + throwNew(e, "java/io/IOException", buf); + return 0; // This doesn't matter cause we have risen an exception + } + return sock; +} + +void connect(JNIEnv* e, SOCKET sock, long addr, short port) +{ + sockaddr_in adr; + adr.sin_family = AF_INET; +#ifdef PLATFORM_WINDOWS + adr.sin_addr.S_un.S_addr = htonl(addr); +#else + adr.sin_addr.s_addr = htonl(addr); +#endif + adr.sin_port = htons(port); + + if (SOCKET_ERROR == ::connect(sock, (sockaddr*)&adr, sizeof(adr))) { + char buf[255]; + sprintf( + buf, "Can't connect a socket. System error: %d", last_socket_error()); + throwNew(e, "java/io/IOException", buf); + return; + } +} + +void bind(JNIEnv* e, SOCKET sock, long addr, short port) +{ + sockaddr_in adr; + adr.sin_family = AF_INET; +#ifdef PLATFORM_WINDOWS + adr.sin_addr.S_un.S_addr = htonl(addr); +#else + adr.sin_addr.s_addr = htonl(addr); +#endif + adr.sin_port = htons(port); + + if (SOCKET_ERROR == ::bind(sock, (sockaddr*)&adr, sizeof(adr))) { + char buf[255]; + sprintf(buf, "Can't bind a socket. System error: %d", last_socket_error()); + throwNew(e, "java/io/IOException", buf); + return; + } +} + +SOCKET accept(JNIEnv* e, SOCKET sock, long* client_addr, short* client_port) +{ + sockaddr_in adr; + SOCKET client_socket = ::accept(sock, (sockaddr*)&adr, NULL); + if (INVALID_SOCKET == client_socket) { + char buf[255]; + sprintf(buf, + "Can't accept the incoming connection. System error: %d", + last_socket_error()); + throwNew(e, "java/io/IOException", buf); + return INVALID_SOCKET; + } + + if (client_addr != NULL) { +#ifdef PLATFORM_WINDOWS + *client_addr = ntohl(adr.sin_addr.S_un.S_addr); +#else + *client_addr = ntohl(adr.sin_addr.s_addr); +#endif + } + + if (client_port != NULL) { + *client_port = ntohs(adr.sin_port); + } + + return client_socket; +} + +void send(JNIEnv* e, SOCKET sock, const char* buff_ptr, int buff_size) +{ + if (SOCKET_ERROR == ::send(sock, buff_ptr, buff_size, 0)) { + char buf[255]; + sprintf(buf, + "Can't send data through the socket. System error: %d", + last_socket_error()); + throwNew(e, "java/io/IOException", buf); + return; + } +} + +int recv(JNIEnv* e, SOCKET sock, char* buff_ptr, int buff_size) +{ + int length = ::recv(sock, buff_ptr, buff_size, 0); + if (SOCKET_ERROR == length) { + char buf[255]; + sprintf(buf, + "Can't receive data through the socket. System error: %d", + last_socket_error()); + throwNew(e, "java/io/IOException", buf); + return 0; // This doesn't matter cause we have risen an exception + } + return length; +} + +void abort(JNIEnv* e, SOCKET sock) +{ + if (SOCKET_ERROR == ::closesocket(sock)) { + char buf[255]; + sprintf( + buf, "Can't close the socket. System error: %d", last_socket_error()); + throwNew(e, "java/io/IOException", buf); + } +} + +void close(JNIEnv* e, SOCKET sock) +{ + if (SOCKET_ERROR == ::shutdown(sock, SD_BOTH)) { + int errcode = last_socket_error(); + if (errcode != ENOTCONN) { + char buf[255]; + sprintf(buf, "Can't shutdown the socket. System error: %d", errcode); + throwNew(e, "java/io/IOException", buf); + } + } +} + +void close_input(JNIEnv* e, SOCKET sock) +{ + if (SOCKET_ERROR == ::shutdown(sock, SD_RECEIVE)) { + int errcode = last_socket_error(); + if (errcode != ENOTCONN) { + char buf[255]; + sprintf(buf, "Can't shutdown the socket. System error: %d", errcode); + throwNew(e, "java/io/IOException", buf); + } + } +} + +void close_output(JNIEnv* e, SOCKET sock) +{ + if (SOCKET_ERROR == ::shutdown(sock, SD_SEND)) { + int errcode = last_socket_error(); + if (errcode != ENOTCONN) { + char buf[255]; + sprintf(buf, "Can't shutdown the socket. System error: %d", errcode); + throwNew(e, "java/io/IOException", buf); + } + } +} +} +} +} + +#endif \ No newline at end of file diff --git a/sgx-jvm/avian/classpath/sockets.h b/sgx-jvm/avian/classpath/sockets.h new file mode 100644 index 0000000000..31a45f2ce5 --- /dev/null +++ b/sgx-jvm/avian/classpath/sockets.h @@ -0,0 +1,74 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +/* + * This file represents a simple cross-platform JNI sockets API + * It is used from different classes of the default Avian classpath + */ + +#ifndef SOCKETS_H_ +#define SOCKETS_H_ + +#include "jni.h" +#include "jni-util.h" +#include "avian/common.h" + +#ifdef PLATFORM_WINDOWS +#include + +#define ONLY_ON_WINDOWS(x) x + +#ifndef ENOTCONN +#define ENOTCONN WSAENOTCONN +#endif +#else +#include +#include +#include +#include + +#define ONLY_ON_WINDOWS(x) +#define SOCKET int +#define INVALID_SOCKET -1 +#define SOCKET_ERROR -1 +#define closesocket(x) close(x) + +#define SD_RECEIVE SHUT_RD +#define SD_SEND SHUT_WR +#define SD_BOTH SHUT_RDWR + +#endif + +namespace avian { +namespace classpath { +namespace sockets { + +// Library initialization +void init(JNIEnv* ONLY_ON_WINDOWS(e)); + +// Socket initialization +SOCKET create(JNIEnv* e); +void connect(JNIEnv* e, SOCKET sock, long addr, short port); +void bind(JNIEnv* e, SOCKET sock, long addr, short port); +SOCKET accept(JNIEnv* e, SOCKET sock, long* client_addr, short* client_port); + +// I/O +void send(JNIEnv* e, SOCKET sock, const char* buff_ptr, int buff_size); +int recv(JNIEnv* e, SOCKET sock, char* buff_ptr, int buff_size); + +// Socket closing +void abort(JNIEnv* e, SOCKET sock); +void close(JNIEnv* e, SOCKET sock); +void close_input(JNIEnv* e, SOCKET sock); +void close_output(JNIEnv* e, SOCKET sock); +} +} +} +#endif /* SOCKETS_H_ */ diff --git a/sgx-jvm/avian/classpath/sun/misc/Cleaner.java b/sgx-jvm/avian/classpath/sun/misc/Cleaner.java new file mode 100644 index 0000000000..eaeea86f72 --- /dev/null +++ b/sgx-jvm/avian/classpath/sun/misc/Cleaner.java @@ -0,0 +1,13 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package sun.misc; + +public class Cleaner { } diff --git a/sgx-jvm/avian/classpath/sun/misc/Unsafe.java b/sgx-jvm/avian/classpath/sun/misc/Unsafe.java new file mode 100644 index 0000000000..a8fdedc227 --- /dev/null +++ b/sgx-jvm/avian/classpath/sun/misc/Unsafe.java @@ -0,0 +1,153 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package sun.misc; + +import java.lang.reflect.Field; + +public final class Unsafe { + private void Unsafe() { } + + private static final Unsafe theUnsafe = new Unsafe(); + + public static Unsafe getUnsafe() { + return theUnsafe; + } + + public native long allocateMemory(long bytes); + + public native void setMemory + (Object base, long offset, long count, byte value); + + public native void freeMemory(long address); + + public native byte getByte(long address); + + public native void putByte(long address, byte x); + + public native short getShort(long address); + + public native void putShort(long address, short x); + + public native char getChar(long address); + + public native void putChar(long address, char x); + + public native int getInt(long address); + + public native void putInt(long address, int x); + + public native long getLong(long address); + + public native void putLong(long address, long x); + + public native float getFloat(long address); + + public native void putFloat(long address, float x); + + public native double getDouble(long address); + + public native void putDouble(long address, double x); + + public native boolean getBooleanVolatile(Object o, long offset); + + public native void putBooleanVolatile(Object o, long offset, boolean x); + + public native byte getByteVolatile(Object o, long offset); + + public native void putByteVolatile(Object o, long offset, byte x); + + public native short getShortVolatile(Object o, long offset); + + public native void putShortVolatile(Object o, long offset, short x); + + public native char getCharVolatile(Object o, long offset); + + public native void putCharVolatile(Object o, long offset, char x); + + public native int getIntVolatile(Object o, long offset); + + public native void putIntVolatile(Object o, long offset, int x); + + public native float getFloatVolatile(Object o, long offset); + + public native void putFloatVolatile(Object o, long offset, float x); + + public native double getDoubleVolatile(Object o, long offset); + + public native void putDoubleVolatile(Object o, long offset, double x); + + public native long getLongVolatile(Object o, long offset); + + public native void putLongVolatile(Object o, long offset, long x); + + public long getLong(Object o, long offset) { + return getLongVolatile(o, offset); + } + + public void putLong(Object o, long offset, long x) { + putLongVolatile(o, offset, x); + } + + public double getDouble(Object o, long offset) { + return getDoubleVolatile(o, offset); + } + + public void putDouble(Object o, long offset, double x) { + putDoubleVolatile(o, offset, x); + } + + public native void putOrderedLong(Object o, long offset, long x); + + public native void putOrderedInt(Object o, long offset, int x); + + public native Object getObject(Object o, long offset); + + public native void putObject(Object o, long offset, Object x); + + public native void putObjectVolatile(Object o, long offset, Object x); + + public native void putOrderedObject(Object o, long offset, Object x); + + public native Object getObjectVolatile(Object o, long offset); + + public native long getAddress(long address); + + public native void putAddress(long address, long x); + + public native int arrayBaseOffset(Class arrayClass); + + public native int arrayIndexScale(Class arrayClass); + + public native long objectFieldOffset(Field field); + + public native void park(boolean absolute, long time); + + public native void unpark(Object target); + + public native void copyMemory(Object srcBase, long srcOffset, + Object destBase, long destOffset, + long count); + + public native boolean compareAndSwapInt(Object o, long offset, int old, + int new_); + + public native boolean compareAndSwapLong(Object o, long offset, + long old, long new_); + + public native boolean compareAndSwapObject(Object o, long offset, Object old, + Object new_); + + public void copyMemory(long src, long dst, long count) { + copyMemory(null, src, null, dst, count); + } + + public native void throwException(Throwable t); +} diff --git a/sgx-jvm/avian/classpath/sun/reflect/ConstantPool.java b/sgx-jvm/avian/classpath/sun/reflect/ConstantPool.java new file mode 100644 index 0000000000..ad29977933 --- /dev/null +++ b/sgx-jvm/avian/classpath/sun/reflect/ConstantPool.java @@ -0,0 +1,13 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package sun.reflect; + +public class ConstantPool { } diff --git a/sgx-jvm/avian/cmake/Platform.cmake b/sgx-jvm/avian/cmake/Platform.cmake new file mode 100644 index 0000000000..20116488a7 --- /dev/null +++ b/sgx-jvm/avian/cmake/Platform.cmake @@ -0,0 +1,18 @@ +IF (APPLE) + INCLUDE_DIRECTORIES ( /Developer/Headers/FlatCarbon ) + FIND_LIBRARY(CORE_FOUNDATION_LIBRARY CoreFoundation) + + MARK_AS_ADVANCED (CORE_FOUNDATION_LIBRARY) + + SET(PLATFORM_LIBS ${CORE_FOUNDATION_LIBRARY}) +ENDIF() + +IF (MSVC) + SET(PLATFORM_CXX_FLAGS "/Wall") +ELSE() + SET(PLATFORM_CXX_FLAGS "-Wall -Werror -fno-exceptions -std=c++0x") + SET(PLATFORM_LIBS ${PLATFORM_LIBS} pthread dl) +ENDIF() + +find_package(ZLIB REQUIRED) +include_directories(${ZLIB_INCLUDE_DIRS}) diff --git a/sgx-jvm/avian/docker/Dockerfile b/sgx-jvm/avian/docker/Dockerfile new file mode 100644 index 0000000000..f4aaa75032 --- /dev/null +++ b/sgx-jvm/avian/docker/Dockerfile @@ -0,0 +1,83 @@ +FROM debian:jessie +MAINTAINER Joshua Warner, joshuawarner32@gmail.com + +RUN echo 'deb http://http.debian.net/debian jessie-backports main' >> /etc/apt/sources.list && \ + echo 'deb-src http://http.debian.net/debian jessie-backports main' >> /etc/apt/sources.list && \ + dpkg --add-architecture i386 && \ + apt-get update && \ + mkdir /var/src/ + +# Install base dependencies and build tools, general debugging tools +RUN apt-get install -y \ + build-essential \ + g++-4.9 \ + zlib1g-dev \ + openjdk-8-jdk \ + locales \ + --no-install-recommends && \ + apt-get clean all + +# Fix utf-8 default locale - we'd otherwise have trouble with the Strings and Misc tests +RUN dpkg-reconfigure locales && \ + locale-gen C.UTF-8 && \ + /usr/sbin/update-locale LANG=C.UTF-8 + +ENV LC_ALL C.UTF-8 + +# Set JAVA_HOME for avian's benefit +ENV JAVA_HOME /usr/lib/jvm/java-8-openjdk-amd64 + +# Add i386 libraries +RUN apt-get install -y \ + libc6-dev-i386 && \ + apt-get download \ + zlib1g-dev:i386 && \ + dpkg -x *.deb / && \ + rm *.deb && \ + apt-get clean all + +# Install cross-compile toolchain and emulator for testing +RUN apt-get install -y \ + mingw-w64 \ + wget \ + unzip \ + --no-install-recommends && \ + apt-get clean all + +# Download win32 and win64 adjacent to avian +RUN cd /var/src/ && \ + wget https://github.com/ReadyTalk/win32/archive/master.zip -O win32.zip && \ + unzip win32.zip && \ + rm win32.zip && \ + mv win32-* win32 && \ + wget https://github.com/ReadyTalk/win64/archive/master.zip -O win64.zip && \ + unzip win64.zip && \ + rm win64.zip && \ + mv win64-* win64 + +# Add openjdk-src stuff +RUN apt-get install -y \ + libcups2-dev \ + libgconf2-dev && \ + mkdir /var/src/openjdk/ && \ + cd /var/src/openjdk/ && \ + apt-get source openjdk-8 && \ + apt-get clean all && \ + find /var/src/openjdk && \ + rm /var/src/openjdk/*.gz /var/src/openjdk/*.dsc && \ + cd /var/src/openjdk/ && \ + tar -xf /var/src/openjdk/openjdk*/jdk.tar.xz && \ + mv /var/src/openjdk/jdk-*/src /var/src/openjdk-src && \ + rm -rf /var/src/openjdk && \ + apt-get clean all + +# Download/extract lzma source +RUN mkdir /var/src/lzma && \ + cd /var/src/lzma && \ + apt-get install -y p7zip && \ + wget http://www.7-zip.org/a/lzma1507.7z -O lzma.7z && \ + p7zip -d lzma.7z + +# Avian build location +VOLUME /var/src/avian +WORKDIR /var/src/avian diff --git a/sgx-jvm/avian/docker/arm/Dockerfile b/sgx-jvm/avian/docker/arm/Dockerfile new file mode 100644 index 0000000000..69278214e2 --- /dev/null +++ b/sgx-jvm/avian/docker/arm/Dockerfile @@ -0,0 +1,69 @@ +FROM joshuawarner32/avian-build +MAINTAINER Joshua Warner, joshuawarner32@gmail.com + +RUN dpkg --add-architecture armel && \ + apt-get update && \ + mkdir -p /opt/arm && \ + apt-get download libc6-dev:armel \ + linux-headers-3.13-1-all-armel:armel \ + linux-libc-dev:armel \ + libc6:armel \ + zlib1g-dev:armel \ + zlib1g:armel && \ + for x in *.deb; do \ + dpkg -x $x /opt/arm; \ + done && \ + rm *.deb && \ + apt-get install -y \ + wget \ + libgmp-dev \ + libmpfr-dev \ + libmpc-dev \ + libisl-dev && \ + apt-get clean all && \ + for x in $(find /opt/arm -type l); do \ + r=$(readlink "$x" | sed 's,^/,/opt/arm/,g'); \ + rm "$x"; \ + ln -s "$r" "$x"; \ + done + +RUN mkdir -p /var/src + +# Build & install binutils +RUN wget ftp://sourceware.org/pub/binutils/snapshots/binutils-2.23.91.tar.bz2 -O /var/src/binutils.tar.bz2 && \ + cd /var/src/ && tar -xjf binutils.tar.bz2 && rm binutils.tar.bz2 && \ + cd /var/src/binutils* && \ + mkdir build && \ + cd build && \ + ../configure \ + --target=arm-linux-gnueabi \ + --prefix=/opt/arm \ + --disable-multilib \ + --program-prefix=arm-linux-gnueabi- \ + --with-sysroot=/opt/arm \ + --with-headers=/opt/arm/usr/include && \ + make && \ + make install && \ + cd /var/src && \ + rm -rf * + +# build & install gcc +RUN wget http://www.netgull.com/gcc/releases/gcc-4.8.2/gcc-4.8.2.tar.bz2 -O /var/src/gcc.tar.bz2 && \ + cd /var/src/ && tar -xjf gcc.tar.bz2 && rm gcc.tar.bz2 && \ + cd /var/src/gcc* && \ + mkdir build && \ + cd build && \ + ../configure \ + --target=arm-linux-gnueabi \ + --enable-languages=c,c++ \ + --prefix=/opt/arm \ + --disable-multilib \ + --program-prefix=arm-linux-gnueabi- \ + --with-sysroot=/opt/arm \ + --with-headers=/opt/arm/usr/include && \ + make && \ + make install && \ + cd /var/src && \ + rm -rf * + +ENV PATH $PATH:/opt/arm/bin diff --git a/sgx-jvm/avian/docker/arm64/Dockerfile b/sgx-jvm/avian/docker/arm64/Dockerfile new file mode 100644 index 0000000000..c39413a31e --- /dev/null +++ b/sgx-jvm/avian/docker/arm64/Dockerfile @@ -0,0 +1,71 @@ +FROM joshuawarner32/avian-build +MAINTAINER Joshua Warner, joshuawarner32@gmail.com + +RUN dpkg --add-architecture arm64 && \ + apt-get update && \ + mkdir -p /opt/arm64 && \ + apt-get download libc6-dev:arm64 \ + linux-headers-3.16.0-4-all-arm64:arm64 \ + linux-libc-dev:arm64 \ + libc6:arm64 \ + zlib1g-dev:arm64 \ + zlib1g:arm64 && \ + for x in *.deb; do \ + dpkg -x $x /opt/arm64; \ + done && \ + rm *.deb && \ + apt-get install -y \ + wget \ + libgmp-dev \ + libmpfr-dev \ + libmpc-dev \ + libisl-dev && \ + apt-get clean all && \ + for x in $(find /opt/arm64 -type l); do \ + r=$(readlink "$x" | sed 's,^/,/opt/arm64/,g'); \ + rm "$x"; \ + ln -s "$r" "$x"; \ + done + +RUN mkdir -p /var/src + +# Build & install binutils +RUN wget ftp://sourceware.org/pub/binutils/snapshots/binutils-2.23.91.tar.bz2 -O /var/src/binutils.tar.bz2 && \ + cd /var/src/ && tar -xjf binutils.tar.bz2 && rm binutils.tar.bz2 && \ + cd /var/src/binutils* && \ + mkdir build && \ + cd build && \ + ../configure \ + --target=aarch64-linux-gnu \ + --prefix=/opt/arm64 \ + --disable-multilib \ + --program-prefix=aarch64-linux-gnu- \ + --with-sysroot=/opt/arm64 \ + --with-headers=/opt/arm64/usr/include \ + --disable-werror && \ + make && \ + make install && \ + cd /var/src && \ + rm -rf * + +# build & install gcc +RUN wget http://www.netgull.com/gcc/releases/gcc-4.8.2/gcc-4.8.2.tar.bz2 -O /var/src/gcc.tar.bz2 && \ + cd /var/src/ && tar -xjf gcc.tar.bz2 && rm gcc.tar.bz2 && \ + cd /var/src/gcc* && \ + mkdir build && \ + cd build && \ + ../configure \ + --target=aarch64-linux-gnu \ + --enable-languages=c,c++ \ + --prefix=/opt/arm64 \ + --disable-multilib \ + --program-prefix=aarch64-linux-gnu- \ + --with-sysroot=/opt/arm64 \ + --with-headers=/opt/arm64/usr/include \ + --disable-werror && \ + make && \ + make install && \ + cd /var/src && \ + rm -rf * + +ENV PATH $PATH:/opt/arm64/bin diff --git a/sgx-jvm/avian/docker/build.sh b/sgx-jvm/avian/docker/build.sh new file mode 100755 index 0000000000..ef61007dce --- /dev/null +++ b/sgx-jvm/avian/docker/build.sh @@ -0,0 +1,41 @@ +#!/bin/sh + +if test $# -eq 0; then + echo "Usage: $0 [--container ] -- " + echo "Ex: $0 make test" + echo "Ex: $0 ./test/ci.sh" + echo "Ex: $0 --container joshuawarner32/avian-build-windows -- make platform=windows" + exit 1 +fi + +THE_USER="-u $(id -u "${USER}")" + +while test $# -gt 1 ; do + key="$1" + case $key in + -c|--container) + shift + CONTAINER="$1" + shift + ;; + -r|--root) + shift + THE_USER= + ;; + --) + shift + break + ;; + *) + break + ;; + esac +done + +if test -z $CONTAINER; then + CONTAINER=joshuawarner32/avian-build +fi + +DIR=$(cd $(dirname "$0") && cd .. && pwd) + +docker run --rm -i -t -v "${DIR}":/var/src/avian ${THE_USER} "${CONTAINER}" "${@}" diff --git a/sgx-jvm/avian/gradle.properties b/sgx-jvm/avian/gradle.properties new file mode 100644 index 0000000000..fbcdf372fe --- /dev/null +++ b/sgx-jvm/avian/gradle.properties @@ -0,0 +1,4 @@ +org.gradle.daemon=true + +group=com.readytalk.avian +version=1.3.0-SNAPSHOT \ No newline at end of file diff --git a/sgx-jvm/avian/gradle/wrapper/gradle-wrapper.jar b/sgx-jvm/avian/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000000..b761216703 Binary files /dev/null and b/sgx-jvm/avian/gradle/wrapper/gradle-wrapper.jar differ diff --git a/sgx-jvm/avian/gradle/wrapper/gradle-wrapper.properties b/sgx-jvm/avian/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000000..2ce5f17a6f --- /dev/null +++ b/sgx-jvm/avian/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Fri Jan 02 11:31:32 MST 2015 +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=http\://services.gradle.org/distributions/gradle-2.0-bin.zip diff --git a/sgx-jvm/avian/gradlew b/sgx-jvm/avian/gradlew new file mode 100755 index 0000000000..91a7e269e1 --- /dev/null +++ b/sgx-jvm/avian/gradlew @@ -0,0 +1,164 @@ +#!/usr/bin/env bash + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS="" + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn ( ) { + echo "$*" +} + +die ( ) { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; +esac + +# For Cygwin, ensure paths are in UNIX format before anything is touched. +if $cygwin ; then + [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"` +fi + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >&- +APP_HOME="`pwd -P`" +cd "$SAVED" >&- + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin, switch paths to Windows format before running java +if $cygwin ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=$((i+1)) + done + case $i in + (0) set -- ;; + (1) set -- "$args0" ;; + (2) set -- "$args0" "$args1" ;; + (3) set -- "$args0" "$args1" "$args2" ;; + (4) set -- "$args0" "$args1" "$args2" "$args3" ;; + (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules +function splitJvmOpts() { + JVM_OPTS=("$@") +} +eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS +JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" + +exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" diff --git a/sgx-jvm/avian/gradlew.bat b/sgx-jvm/avian/gradlew.bat new file mode 100644 index 0000000000..aec99730b4 --- /dev/null +++ b/sgx-jvm/avian/gradlew.bat @@ -0,0 +1,90 @@ +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS= + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto init + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto init + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:init +@rem Get command-line arguments, handling Windowz variants + +if not "%OS%" == "Windows_NT" goto win9xME_args +if "%@eval[2+2]" == "4" goto 4NT_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* +goto execute + +:4NT_args +@rem Get arguments from the 4NT Shell from JP Software +set CMD_LINE_ARGS=%$ + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/sgx-jvm/avian/include/avian/codegen/architecture.h b/sgx-jvm/avian/include/avian/codegen/architecture.h new file mode 100644 index 0000000000..7bdad3eeab --- /dev/null +++ b/sgx-jvm/avian/include/avian/codegen/architecture.h @@ -0,0 +1,164 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#ifndef AVIAN_CODEGEN_ARCHITECTURE_H +#define AVIAN_CODEGEN_ARCHITECTURE_H + +#include "ir.h" +#include "registers.h" + +namespace vm { +class Zone; +} + +namespace avian { + +namespace util { +class Alloc; +} + +namespace codegen { + +class Assembler; + +class OperandMask { + public: + uint8_t typeMask; + RegisterMask lowRegisterMask; + RegisterMask highRegisterMask; + + OperandMask(uint8_t typeMask, + RegisterMask lowRegisterMask, + RegisterMask highRegisterMask) + : typeMask(typeMask), + lowRegisterMask(lowRegisterMask), + highRegisterMask(highRegisterMask) + { + } + + OperandMask() : typeMask(~0), lowRegisterMask(AnyRegisterMask), highRegisterMask(AnyRegisterMask) + { + } + + void setLowHighRegisterMasks(RegisterMask lowRegisterMask, RegisterMask highRegisterMask) { + this->lowRegisterMask = lowRegisterMask; + this->highRegisterMask = highRegisterMask; + } +}; + +class Architecture { + public: + virtual unsigned floatRegisterSize() = 0; + + virtual const RegisterFile* registerFile() = 0; + + virtual Register scratch() = 0; + virtual Register stack() = 0; + virtual Register thread() = 0; + virtual Register returnLow() = 0; + virtual Register returnHigh() = 0; + virtual Register virtualCallTarget() = 0; + virtual Register virtualCallIndex() = 0; + + virtual ir::TargetInfo targetInfo() = 0; + + virtual bool bigEndian() = 0; + + virtual uintptr_t maximumImmediateJump() = 0; + + virtual bool alwaysCondensed(lir::BinaryOperation op) = 0; + virtual bool alwaysCondensed(lir::TernaryOperation op) = 0; + + virtual bool reserved(Register register_) = 0; + + virtual unsigned frameFootprint(unsigned footprint) = 0; + virtual unsigned argumentFootprint(unsigned footprint) = 0; + virtual bool argumentAlignment() = 0; + virtual bool argumentRegisterAlignment() = 0; + virtual unsigned argumentRegisterCount() = 0; + virtual Register argumentRegister(unsigned index) = 0; + + virtual bool hasLinkRegister() = 0; + + virtual unsigned stackAlignmentInWords() = 0; + + virtual bool matchCall(void* returnAddress, void* target) = 0; + + virtual void updateCall(lir::UnaryOperation op, + void* returnAddress, + void* newTarget) = 0; + + virtual void setConstant(void* dst, uint64_t constant) = 0; + + virtual unsigned alignFrameSize(unsigned sizeInWords) = 0; + + virtual void nextFrame(void* start, + unsigned size, + unsigned footprint, + void* link, + bool mostRecent, + int targetParameterFootprint, + void** ip, + void** stack) = 0; + virtual void* frameIp(void* stack) = 0; + virtual unsigned frameHeaderSize() = 0; + virtual unsigned frameReturnAddressSize() = 0; + virtual unsigned frameFooterSize() = 0; + virtual int returnAddressOffset() = 0; + virtual int framePointerOffset() = 0; + + virtual void plan(lir::UnaryOperation op, + unsigned aSize, + OperandMask& aMask, + bool* thunk) = 0; + + virtual void planSource(lir::BinaryOperation op, + unsigned aSize, + OperandMask& aMask, + unsigned bSize, + bool* thunk) = 0; + + virtual void planDestination(lir::BinaryOperation op, + unsigned aSize, + const OperandMask& aMask, + unsigned bSize, + OperandMask& bMask) = 0; + + virtual void planMove(unsigned size, + OperandMask& src, + OperandMask& tmp, + const OperandMask& dst) = 0; + + virtual void planSource(lir::TernaryOperation op, + unsigned aSize, + OperandMask& aMask, + unsigned bSize, + OperandMask& bMask, + unsigned cSize, + bool* thunk) = 0; + + virtual void planDestination(lir::TernaryOperation op, + unsigned aSize, + const OperandMask& aMask, + unsigned bSize, + const OperandMask& bMask, + unsigned cSize, + OperandMask& cMask) = 0; + + virtual Assembler* makeAssembler(util::Alloc*, vm::Zone*) = 0; + + virtual void acquire() = 0; + virtual void release() = 0; +}; + +} // namespace codegen +} // namespace avian + +#endif // AVIAN_CODEGEN_ARCHITECTURE_H diff --git a/sgx-jvm/avian/include/avian/codegen/assembler.h b/sgx-jvm/avian/include/avian/codegen/assembler.h new file mode 100644 index 0000000000..ab6a990a4c --- /dev/null +++ b/sgx-jvm/avian/include/avian/codegen/assembler.h @@ -0,0 +1,116 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#ifndef AVIAN_CODEGEN_ASSEMBLER_H +#define AVIAN_CODEGEN_ASSEMBLER_H + +#include +#include "avian/zone.h" + +#include +#include +#include + +namespace avian { +namespace codegen { + +class Architecture; + +class OperandInfo { + public: + const unsigned size; + const lir::Operand::Type type; + lir::Operand* const operand; + + inline OperandInfo(unsigned size, + lir::Operand::Type type, + lir::Operand* operand) + : size(size), type(type), operand(operand) + { + } +}; + +#ifdef AVIAN_TAILS +const bool TailCalls = true; +#else +const bool TailCalls = false; +#endif + +#ifdef AVIAN_USE_FRAME_POINTER +const bool UseFramePointer = true; +#else +const bool UseFramePointer = false; +#endif + +class Assembler { + public: + class Client { + public: + virtual Register acquireTemporary(RegisterMask mask = AnyRegisterMask) = 0; + virtual void releaseTemporary(Register r) = 0; + + virtual void save(Register r) = 0; + }; + + class Block { + public: + virtual unsigned resolve(unsigned start, Block* next) = 0; + }; + + virtual void setClient(Client* client) = 0; + + virtual Architecture* arch() = 0; + + virtual void checkStackOverflow(uintptr_t handler, + unsigned stackLimitOffsetFromThread) = 0; + virtual void saveFrame(unsigned stackOffset, unsigned ipOffset) = 0; + virtual void pushFrame(unsigned argumentCount, ...) = 0; + virtual void allocateFrame(unsigned footprint) = 0; + virtual void adjustFrame(unsigned difference) = 0; + virtual void popFrame(unsigned footprint) = 0; + virtual void popFrameForTailCall(unsigned footprint, + int offset, + Register returnAddressSurrogate, + Register framePointerSurrogate) = 0; + virtual void popFrameAndPopArgumentsAndReturn(unsigned frameFootprint, + unsigned argumentFootprint) = 0; + virtual void popFrameAndUpdateStackAndReturn(unsigned frameFootprint, + unsigned stackOffsetFromThread) + = 0; + + virtual void apply(lir::Operation op) = 0; + virtual void apply(lir::UnaryOperation op, OperandInfo a) = 0; + virtual void apply(lir::BinaryOperation op, OperandInfo a, OperandInfo b) = 0; + virtual void apply(lir::TernaryOperation op, + OperandInfo a, + OperandInfo b, + OperandInfo c) = 0; + + virtual void setDestination(uint8_t* dst) = 0; + + virtual void write() = 0; + + virtual Promise* offset(bool forTrace = false) = 0; + + virtual Block* endBlock(bool startNew) = 0; + + virtual void endEvent() = 0; + + virtual unsigned length() = 0; + + virtual unsigned footerSize() = 0; + + virtual void dispose() = 0; +}; + +} // namespace codegen +} // namespace avian + +#endif // AVIAN_CODEGEN_ASSEMBLER_H diff --git a/sgx-jvm/avian/include/avian/codegen/compiler.h b/sgx-jvm/avian/include/avian/codegen/compiler.h new file mode 100644 index 0000000000..03c03ed855 --- /dev/null +++ b/sgx-jvm/avian/include/avian/codegen/compiler.h @@ -0,0 +1,199 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#ifndef AVIAN_CODEGEN_COMPILER_H +#define AVIAN_CODEGEN_COMPILER_H + +#include +#include +#include "avian/zone.h" +#include "assembler.h" +#include "ir.h" + +namespace avian { +namespace codegen { + +class TraceHandler { + public: + virtual void handleTrace(Promise* address, unsigned argumentIndex) = 0; +}; + +template +class Args { + public: + ir::Value* values[N]; + + template + Args(Ts... ts) +#ifndef _MSC_VER + : values{ts...} +#endif + { +#ifdef _MSC_VER + setArrayElements(values, ts...); +#endif + } + + operator util::Slice() + { + return util::Slice(&values[0], N); + } +}; + +inline Args<0> args() +{ + return Args<0>(); +} + +inline Args<1> args(ir::Value* first) +{ + return Args<1>{first}; +} + +template +inline Args<1 + util::ArgumentCount::Result> args(ir::Value* first, + Ts... rest) +{ + return Args<1 + util::ArgumentCount::Result>{first, rest...}; +} + +class Compiler { + public: + class Client { + public: + virtual intptr_t getThunk(lir::UnaryOperation op, unsigned size) = 0; + virtual intptr_t getThunk(lir::BinaryOperation op, + unsigned size, + unsigned resultSize) = 0; + virtual intptr_t getThunk(lir::TernaryOperation op, + unsigned size, + unsigned resultSize, + bool* threadParameter) = 0; + }; + + static const unsigned Aligned = 1 << 0; + static const unsigned NoReturn = 1 << 1; + static const unsigned TailJump = 1 << 2; + static const unsigned LongJumpOrCall = 1 << 3; + + class State { + }; + + virtual State* saveState() = 0; + virtual void restoreState(State* state) = 0; + + virtual void init(unsigned logicalCodeSize, + unsigned parameterFootprint, + unsigned localFootprint, + unsigned alignedFrameSize) = 0; + + virtual void extendLogicalCode(unsigned more) = 0; + + virtual void visitLogicalIp(unsigned logicalIp) = 0; + virtual void startLogicalIp(unsigned logicalIp) = 0; + + virtual Promise* machineIp(unsigned logicalIp) = 0; + + virtual Promise* poolAppend(intptr_t value) = 0; + virtual Promise* poolAppendPromise(Promise* value) = 0; + + virtual ir::Value* constant(int64_t value, ir::Type type) = 0; + virtual ir::Value* promiseConstant(Promise* value, ir::Type type) = 0; + virtual ir::Value* address(ir::Type type, Promise* address) = 0; + virtual ir::Value* memory(ir::Value* base, + ir::Type type, + int displacement = 0, + ir::Value* index = 0) = 0; + + virtual ir::Value* threadRegister() = 0; + + virtual void push(ir::Type type, ir::Value* value) = 0; + virtual void save(ir::Type type, ir::Value* value) = 0; + virtual ir::Value* pop(ir::Type type) = 0; + virtual void pushed(ir::Type type) = 0; + virtual void popped(unsigned footprint) = 0; + virtual unsigned topOfStack() = 0; + virtual ir::Value* peek(unsigned footprint, unsigned index) = 0; + + virtual ir::Value* nativeCall(ir::Value* address, + unsigned flags, + TraceHandler* traceHandler, + ir::Type resultType, + util::Slice arguments) = 0; + + virtual ir::Value* stackCall(ir::Value* address, + unsigned flags, + TraceHandler* traceHandler, + ir::Type resultType, + util::Slice arguments) = 0; + + virtual void return_(ir::Value* value) = 0; + virtual void return_() = 0; + + virtual void initLocal(unsigned index, ir::Type type) = 0; + virtual void initLocalsFromLogicalIp(unsigned logicalIp) = 0; + virtual void storeLocal(ir::Value* src, unsigned index) = 0; + virtual ir::Value* loadLocal(ir::Type type, unsigned index) = 0; + virtual void saveLocals() = 0; + + virtual void checkBounds(ir::Value* object, + unsigned lengthOffset, + ir::Value* index, + intptr_t handler) = 0; + + virtual ir::Value* truncateThenExtend(ir::ExtendMode extendMode, + ir::Type extendType, + ir::Type truncateType, + ir::Value* src) = 0; + + virtual ir::Value* truncate(ir::Type type, ir::Value* src) = 0; + + virtual void store(ir::Value* src, ir::Value* dst) = 0; + virtual ir::Value* load(ir::ExtendMode extendMode, + ir::Value* src, + ir::Type dstType) = 0; + + virtual void condJump(lir::TernaryOperation op, + ir::Value* a, + ir::Value* b, + ir::Value* address) = 0; + + virtual void jmp(ir::Value* address) = 0; + virtual void exit(ir::Value* address) = 0; + + virtual ir::Value* binaryOp(lir::TernaryOperation op, + ir::Type type, + ir::Value* a, + ir::Value* b) = 0; + virtual ir::Value* unaryOp(lir::BinaryOperation op, ir::Value* a) = 0; + virtual void nullaryOp(lir::Operation op) = 0; + + virtual ir::Value* f2f(ir::Type resType, ir::Value* a) = 0; + virtual ir::Value* f2i(ir::Type resType, ir::Value* a) = 0; + virtual ir::Value* i2f(ir::Type resType, ir::Value* a) = 0; + + virtual void compile(uintptr_t stackOverflowHandler, + unsigned stackLimitOffset) = 0; + virtual unsigned resolve(uint8_t* dst) = 0; + virtual unsigned poolSize() = 0; + virtual void write() = 0; + + virtual void dispose() = 0; +}; + +Compiler* makeCompiler(vm::System* system, + Assembler* assembler, + vm::Zone* zone, + Compiler::Client* client); + +} // namespace codegen +} // namespace avian + +#endif // AVIAN_CODEGEN_COMPILER_H diff --git a/sgx-jvm/avian/include/avian/codegen/ir.h b/sgx-jvm/avian/include/avian/codegen/ir.h new file mode 100644 index 0000000000..ae0f2663aa --- /dev/null +++ b/sgx-jvm/avian/include/avian/codegen/ir.h @@ -0,0 +1,152 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#ifndef AVIAN_CODEGEN_IR_H +#define AVIAN_CODEGEN_IR_H + +namespace avian { +namespace codegen { +namespace ir { + +class TargetInfo { + public: + unsigned pointerSize; + + explicit TargetInfo(unsigned pointerSize) : pointerSize(pointerSize) + { + } +}; + +class Type { + public: + enum Flavor { + // A GC-visiible reference + Object, + + // GC-invisible types + Integer, + Float, + Address, + + // Represents the lack of a return value + // TODO: remove when possible + Void, + }; + + typedef int16_t TypeDesc; + +#define TY_DESC(flavor, size) ((flavor & 0xff) | ((size & 0xff) << 8)) + // TODO: once we upgrade to c++11, these should become plain constants (rather + // than function calls). + // The constructor will need to be declared 'constexpr'. + static inline Type void_() + { + return TY_DESC(Void, 0); + } + static inline Type object() + { + return TY_DESC(Object, -1); + } + static inline Type iptr() + { + return TY_DESC(Integer, -1); + } + static inline Type i1() + { + return TY_DESC(Integer, 1); + } + static inline Type i2() + { + return TY_DESC(Integer, 2); + } + static inline Type i4() + { + return TY_DESC(Integer, 4); + } + static inline Type i8() + { + return TY_DESC(Integer, 8); + } + static inline Type f4() + { + return TY_DESC(Float, 4); + } + static inline Type f8() + { + return TY_DESC(Float, 8); + } + static inline Type addr() + { + return TY_DESC(Address, -1); + } +#undef TY_DESC + + private: + TypeDesc desc; + + friend class Types; + + // TODO: once we move to c++11, declare this 'constexpr', to allow + // compile-time constants of this type. + /* constexpr */ Type(TypeDesc desc) : desc(desc) + { + } + + public: + inline Flavor flavor() const + { + return (Flavor)(desc & 0xff); + } + + // If the size isn't known without inspecting the TargetInfo, returns -1. + // Otherwise, matches size(TargetInfo). + inline int rawSize() const + { + return desc >> 8; + } + + inline unsigned size(const TargetInfo& t) const + { + int s = rawSize(); + if (s < 0) { + return t.pointerSize; + } + return (unsigned)s; + } + + inline bool operator==(const Type& other) const + { + return desc == other.desc; + } + + inline bool operator!=(const Type& other) const + { + return !(*this == other); + } +}; + +enum class ExtendMode { Signed, Unsigned }; + +enum class CallingConvention { Native, Avian }; + +class Value { + public: + ir::Type type; + + Value(ir::Type type) : type(type) + { + } +}; + +} // namespace ir +} // namespace codegen +} // namespace avian + +#endif // AVIAN_CODEGEN_IR_H diff --git a/sgx-jvm/avian/include/avian/codegen/lir-ops.inc.cpp b/sgx-jvm/avian/include/avian/codegen/lir-ops.inc.cpp new file mode 100644 index 0000000000..cf038c6647 --- /dev/null +++ b/sgx-jvm/avian/include/avian/codegen/lir-ops.inc.cpp @@ -0,0 +1,62 @@ +LIR_OP_0(Return) +LIR_OP_0(LoadBarrier) +LIR_OP_0(StoreStoreBarrier) +LIR_OP_0(StoreLoadBarrier) +LIR_OP_0(Trap) + +LIR_OP_1(Call) +LIR_OP_1(LongCall) +LIR_OP_1(AlignedLongCall) +LIR_OP_1(AlignedCall) +LIR_OP_1(Jump) +LIR_OP_1(LongJump) +LIR_OP_1(AlignedLongJump) +LIR_OP_1(AlignedJump) + +LIR_OP_2(Move) +LIR_OP_2(MoveLow) +LIR_OP_2(MoveHigh) +LIR_OP_2(MoveZ) +LIR_OP_2(Negate) +LIR_OP_2(FloatNegate) +LIR_OP_2(Float2Float) +LIR_OP_2(Float2Int) +LIR_OP_2(Int2Float) +LIR_OP_2(FloatSquareRoot) +LIR_OP_2(FloatAbsolute) +LIR_OP_2(Absolute) + +LIR_OP_3(Add) +LIR_OP_3(Subtract) +LIR_OP_3(Multiply) +LIR_OP_3(Divide) +LIR_OP_3(Remainder) +LIR_OP_3(ShiftLeft) +LIR_OP_3(ShiftRight) +LIR_OP_3(UnsignedShiftRight) +LIR_OP_3(And) +LIR_OP_3(Or) +LIR_OP_3(Xor) +LIR_OP_3(FloatAdd) +LIR_OP_3(FloatSubtract) +LIR_OP_3(FloatMultiply) +LIR_OP_3(FloatDivide) +LIR_OP_3(FloatRemainder) +LIR_OP_3(FloatMax) +LIR_OP_3(FloatMin) +LIR_OP_3(JumpIfLess) +LIR_OP_3(JumpIfGreater) +LIR_OP_3(JumpIfLessOrEqual) +LIR_OP_3(JumpIfGreaterOrEqual) +LIR_OP_3(JumpIfEqual) +LIR_OP_3(JumpIfNotEqual) +LIR_OP_3(JumpIfFloatEqual) +LIR_OP_3(JumpIfFloatNotEqual) +LIR_OP_3(JumpIfFloatLess) +LIR_OP_3(JumpIfFloatGreater) +LIR_OP_3(JumpIfFloatLessOrEqual) +LIR_OP_3(JumpIfFloatGreaterOrEqual) +LIR_OP_3(JumpIfFloatLessOrUnordered) +LIR_OP_3(JumpIfFloatGreaterOrUnordered) +LIR_OP_3(JumpIfFloatLessOrEqualOrUnordered) +LIR_OP_3(JumpIfFloatGreaterOrEqualOrUnordered) diff --git a/sgx-jvm/avian/include/avian/codegen/lir.h b/sgx-jvm/avian/include/avian/codegen/lir.h new file mode 100644 index 0000000000..444a661e81 --- /dev/null +++ b/sgx-jvm/avian/include/avian/codegen/lir.h @@ -0,0 +1,184 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#ifndef AVIAN_CODEGEN_LIR_H +#define AVIAN_CODEGEN_LIR_H + +#include + +namespace avian { +namespace codegen { +class Promise; + +namespace lir { +enum Operation { +#define LIR_OP_0(x) x, +#define LIR_OP_1(x) +#define LIR_OP_2(x) +#define LIR_OP_3(x) +#include "lir-ops.inc.cpp" +#undef LIR_OP_0 +#undef LIR_OP_1 +#undef LIR_OP_2 +#undef LIR_OP_3 +}; + +const unsigned OperationCount = Trap + 1; + +enum UnaryOperation { +#define LIR_OP_0(x) +#define LIR_OP_1(x) x, +#define LIR_OP_2(x) +#define LIR_OP_3(x) +#include "lir-ops.inc.cpp" +#undef LIR_OP_0 +#undef LIR_OP_1 +#undef LIR_OP_2 +#undef LIR_OP_3 + NoUnaryOperation = -1 +}; + +const unsigned UnaryOperationCount = AlignedJump + 1; + +enum BinaryOperation { +#define LIR_OP_0(x) +#define LIR_OP_1(x) +#define LIR_OP_2(x) x, +#define LIR_OP_3(x) +#include "lir-ops.inc.cpp" +#undef LIR_OP_0 +#undef LIR_OP_1 +#undef LIR_OP_2 +#undef LIR_OP_3 + NoBinaryOperation = -1 +}; + +const unsigned BinaryOperationCount = Absolute + 1; + +enum TernaryOperation { +#define LIR_OP_0(x) +#define LIR_OP_1(x) +#define LIR_OP_2(x) +#define LIR_OP_3(x) x, +#include "lir-ops.inc.cpp" +#undef LIR_OP_0 +#undef LIR_OP_1 +#undef LIR_OP_2 +#undef LIR_OP_3 + NoTernaryOperation = -1 +}; + +const unsigned TernaryOperationCount = JumpIfFloatGreaterOrEqualOrUnordered + 1; + +const unsigned NonBranchTernaryOperationCount = FloatMin + 1; +const unsigned BranchOperationCount = JumpIfFloatGreaterOrEqualOrUnordered + - FloatMin; + +enum ValueType { ValueGeneral, ValueFloat }; + +inline bool isBranch(lir::TernaryOperation op) +{ + return op > FloatMin; +} + +inline bool isFloatBranch(lir::TernaryOperation op) +{ + return op > JumpIfNotEqual; +} + +inline bool isGeneralBranch(lir::TernaryOperation op) +{ + return isBranch(op) && !isFloatBranch(op); +} + +inline bool isGeneralBinaryOp(lir::TernaryOperation op) +{ + return op < FloatAdd; +} + +inline bool isFloatBinaryOp(lir::TernaryOperation op) +{ + return op >= FloatAdd && op <= FloatMin; +} + +inline bool isGeneralUnaryOp(lir::BinaryOperation op) +{ + return op == Negate || op == Absolute; +} + +inline bool isFloatUnaryOp(lir::BinaryOperation op) +{ + return op == FloatNegate || op == FloatSquareRoot || op == FloatAbsolute; +} + +class Operand { +public: + + enum class Type { + Constant, + Address, + RegisterPair, + Memory + }; + + const static unsigned TypeCount = (unsigned)Type::Memory + 1; + + const static unsigned ConstantMask = 1 << (unsigned)Type::Constant; + const static unsigned AddressMask = 1 << (unsigned)Type::Address; + const static unsigned RegisterPairMask = 1 << (unsigned)Type::RegisterPair; + const static unsigned MemoryMask = 1 << (unsigned)Type::Memory; +}; + +class Constant : public Operand { + public: + Constant(Promise* value) : value(value) + { + } + + Promise* value; +}; + +class Address : public Operand { + public: + Address(Promise* address) : address(address) + { + } + + Promise* address; +}; + +class RegisterPair : public Operand { + public: + RegisterPair(Register low, Register high = NoRegister) : low(low), high(high) + { + } + + Register low; + Register high; +}; + +class Memory : public Operand { + public: + Memory(Register base, int offset, Register index = NoRegister, unsigned scale = 1) + : base(base), offset(offset), index(index), scale(scale) + { + } + + Register base; + int offset; + Register index; + unsigned scale; +}; + +} // namespace lir +} // namespace codegen +} // namespace avian + +#endif // AVIAN_CODEGEN_LIR_H diff --git a/sgx-jvm/avian/include/avian/codegen/promise.h b/sgx-jvm/avian/include/avian/codegen/promise.h new file mode 100644 index 0000000000..8bca0dd528 --- /dev/null +++ b/sgx-jvm/avian/include/avian/codegen/promise.h @@ -0,0 +1,185 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#ifndef AVIAN_CODEGEN_PROMISE_H +#define AVIAN_CODEGEN_PROMISE_H + +#include +#include +#include + +namespace avian { +namespace codegen { + +class Promise { + public: + class Listener { + public: + virtual bool resolve(int64_t value, void** location) = 0; + + Listener* next; + }; + + virtual int64_t value() = 0; + virtual bool resolved() = 0; + virtual Listener* listen(unsigned) + { + return 0; + } +}; + +class ResolvedPromise : public Promise { + public: + ResolvedPromise(int64_t value) : value_(value) + { + } + + virtual int64_t value() + { + return value_; + } + + virtual bool resolved() + { + return true; + } + + int64_t value_; +}; + +class ShiftMaskPromise : public Promise { + public: + ShiftMaskPromise(Promise* base, unsigned shift, int64_t mask) + : base(base), shift(shift), mask(mask) + { + } + + virtual int64_t value() + { + return (base->value() >> shift) & mask; + } + + virtual bool resolved() + { + return base->resolved(); + } + + Promise* base; + unsigned shift; + int64_t mask; +}; + +class CombinedPromise : public Promise { + public: + CombinedPromise(Promise* low, Promise* high) : low(low), high(high) + { + } + + virtual int64_t value() + { + return low->value() | (high->value() << 32); + } + + virtual bool resolved() + { + return low->resolved() and high->resolved(); + } + + Promise* low; + Promise* high; +}; + +class OffsetPromise : public Promise { + public: + OffsetPromise(Promise* base, int64_t offset) : base(base), offset(offset) + { + } + + virtual int64_t value() + { + return base->value() + offset; + } + + virtual bool resolved() + { + return base->resolved(); + } + + Promise* base; + int64_t offset; +}; + +class ListenPromise : public Promise { + public: + ListenPromise(vm::System* s, util::AllocOnly* allocator) + : s(s), allocator(allocator), listener(0) + { + } + + virtual int64_t value() + { + abort(s); + } + + virtual bool resolved() + { + return false; + } + + virtual Listener* listen(unsigned sizeInBytes) + { + Listener* l = static_cast(allocator->allocate(sizeInBytes)); + l->next = listener; + listener = l; + return l; + } + + vm::System* s; + util::AllocOnly* allocator; + Listener* listener; + Promise* promise; +}; + +class DelayedPromise : public ListenPromise { + public: + DelayedPromise(vm::System* s, + util::AllocOnly* allocator, + Promise* basis, + DelayedPromise* next) + : ListenPromise(s, allocator), basis(basis), next(next) + { + } + + virtual int64_t value() + { + abort(s); + } + + virtual bool resolved() + { + return false; + } + + virtual Listener* listen(unsigned sizeInBytes) + { + Listener* l = static_cast(allocator->allocate(sizeInBytes)); + l->next = listener; + listener = l; + return l; + } + + Promise* basis; + DelayedPromise* next; +}; + +} // namespace codegen +} // namespace avian + +#endif // AVIAN_CODEGEN_PROMISE_H diff --git a/sgx-jvm/avian/include/avian/codegen/registers.h b/sgx-jvm/avian/include/avian/codegen/registers.h new file mode 100644 index 0000000000..25420db668 --- /dev/null +++ b/sgx-jvm/avian/include/avian/codegen/registers.h @@ -0,0 +1,212 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#ifndef AVIAN_CODEGEN_REGISTERS_H +#define AVIAN_CODEGEN_REGISTERS_H + +#include "avian/common.h" + +namespace avian { +namespace codegen { + +class RegisterMask; + +class Register { +private: + int8_t _index; +public: + explicit constexpr Register(int8_t _index) : _index(_index) {} + constexpr Register() : _index(-1) {} + + constexpr bool operator == (Register o) const { + return _index == o._index; + } + + constexpr bool operator != (Register o) const { + return !(*this == o); + } + + constexpr RegisterMask operator | (Register o) const; + + constexpr bool operator < (Register o) const { + return _index < o._index; + } + + constexpr bool operator > (Register o) const { + return _index > o._index; + } + + constexpr bool operator <= (Register o) const { + return _index <= o._index; + } + + constexpr bool operator >= (Register o) const { + return _index >= o._index; + } + + constexpr int index() const { + return _index; + } +}; + +constexpr Register NoRegister; + +class RegisterMask { +private: + uint64_t mask; + + static constexpr unsigned maskStart(uint64_t mask, unsigned offset = 64) { + return mask == 0 ? (offset & 63) : maskStart(mask << 1, offset - 1); + } + + static constexpr unsigned maskLimit(uint64_t mask, unsigned offset = 0) { + return mask == 0 ? offset : maskLimit(mask >> 1, offset + 1); + } +public: + constexpr RegisterMask(uint64_t mask) : mask(mask) {} + constexpr RegisterMask() : mask(0) {} + constexpr RegisterMask(Register reg) : mask(static_cast(1) << reg.index()) {} + + constexpr unsigned begin() const { + return maskStart(mask); + } + + constexpr unsigned end() const { + return maskLimit(mask); + } + + constexpr RegisterMask operator &(RegisterMask o) const { + return RegisterMask(mask & o.mask); + } + + RegisterMask operator &=(RegisterMask o) { + mask &= o.mask; + return *this; + } + + constexpr RegisterMask operator |(RegisterMask o) const { + return RegisterMask(mask | o.mask); + } + + constexpr bool contains(Register reg) const { + return (mask & (static_cast(1) << reg.index())) != 0; + } + + constexpr bool containsExactly(Register reg) const { + return mask == (mask & (static_cast(1) << reg.index())); + } + + constexpr RegisterMask excluding(Register reg) const { + return RegisterMask(mask & ~(static_cast(1) << reg.index())); + } + + constexpr RegisterMask including(Register reg) const { + return RegisterMask(mask | (static_cast(1) << reg.index())); + } + + constexpr explicit operator uint64_t() const { + return mask; + } + + constexpr explicit operator bool() const { + return mask != 0; + } +}; + +constexpr RegisterMask AnyRegisterMask(~static_cast(0)); +constexpr RegisterMask NoneRegisterMask(0); + +constexpr RegisterMask Register::operator | (Register o) const { + return RegisterMask(*this) | o; +} + +class RegisterIterator; + +class BoundedRegisterMask : public RegisterMask { + public: + uint8_t start; + uint8_t limit; + + BoundedRegisterMask(RegisterMask mask) + : RegisterMask(mask), start(mask.begin()), limit(mask.end()) + { + } + + RegisterIterator begin() const; + + RegisterIterator end() const; +}; + +class RegisterIterator { + public: + int index; + int direction; + int limit; + const RegisterMask mask; + + RegisterIterator(int index, int direction, int limit, RegisterMask mask) + : index(index), direction(direction), limit(limit), mask(mask) + { + } + + bool operator !=(const RegisterIterator& o) const { + return index != o.index; + } + + Register operator *() { + return Register(index); + } + + void operator ++ () { + if(index != limit) { + index += direction; + } + while(index != limit && !mask.contains(Register(index))) { + index += direction; + } + } +}; + +inline RegisterIterator BoundedRegisterMask::begin() const { + // We use reverse iteration... for some reason. + return RegisterIterator(limit - 1, -1, start - 1, *this); +} + +inline RegisterIterator BoundedRegisterMask::end() const { + // We use reverse iteration... for some reason. + return RegisterIterator(start - 1, -1, start - 1, *this); +} + +inline RegisterIterator begin(BoundedRegisterMask mask) { + return mask.begin(); +} + +inline RegisterIterator end(BoundedRegisterMask mask) { + return mask.end(); +} + +class RegisterFile { + public: + BoundedRegisterMask allRegisters; + BoundedRegisterMask generalRegisters; + BoundedRegisterMask floatRegisters; + + RegisterFile(RegisterMask generalRegisterMask, RegisterMask floatRegisterMask) + : allRegisters(generalRegisterMask | floatRegisterMask), + generalRegisters(generalRegisterMask), + floatRegisters(floatRegisterMask) + { + } +}; + +} // namespace codegen +} // namespace avian + +#endif // AVIAN_CODEGEN_REGISTERS_H diff --git a/sgx-jvm/avian/include/avian/codegen/runtime.h b/sgx-jvm/avian/include/avian/codegen/runtime.h new file mode 100644 index 0000000000..527d68a525 --- /dev/null +++ b/sgx-jvm/avian/include/avian/codegen/runtime.h @@ -0,0 +1,54 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#ifndef AVIAN_CODEGEN_RUNTIME_H +#define AVIAN_CODEGEN_RUNTIME_H + +namespace avian { +namespace codegen { +namespace runtime { + +int64_t compareDoublesG(uint64_t bi, uint64_t ai); +int64_t compareDoublesL(uint64_t bi, uint64_t ai); +int64_t compareFloatsG(uint32_t bi, uint32_t ai); +int64_t compareFloatsL(uint32_t bi, uint32_t ai); +int64_t compareLongs(uint64_t b, uint64_t a); +uint64_t addDouble(uint64_t b, uint64_t a); +uint64_t subtractDouble(uint64_t b, uint64_t a); +uint64_t multiplyDouble(uint64_t b, uint64_t a); +uint64_t divideDouble(uint64_t b, uint64_t a); +uint64_t moduloDouble(uint64_t b, uint64_t a); +uint64_t negateDouble(uint64_t a); +uint64_t squareRootDouble(uint64_t a); +uint64_t doubleToFloat(int64_t a); +int64_t doubleToInt(int64_t a); +int64_t doubleToLong(int64_t a); +uint64_t addFloat(uint32_t b, uint32_t a); +uint64_t subtractFloat(uint32_t b, uint32_t a); +uint64_t multiplyFloat(uint32_t b, uint32_t a); +uint64_t divideFloat(uint32_t b, uint32_t a); +uint64_t moduloFloat(uint32_t b, uint32_t a); +uint64_t negateFloat(uint32_t a); +uint64_t absoluteFloat(uint32_t a); +int64_t absoluteLong(int64_t a); +int64_t absoluteInt(int32_t a); +uint64_t floatToDouble(int32_t a); +int64_t floatToInt(int32_t a); +int64_t floatToLong(int32_t a); +uint64_t intToDouble(int32_t a); +uint64_t intToFloat(int32_t a); +uint64_t longToDouble(int64_t a); +uint64_t longToFloat(int64_t a); + +} // namespace runtime +} // namespace codegen +} // namespace avian + +#endif // AVIAN_CODEGEN_RUNTIME_H diff --git a/sgx-jvm/avian/include/avian/codegen/targets.h b/sgx-jvm/avian/include/avian/codegen/targets.h new file mode 100644 index 0000000000..d297c86bab --- /dev/null +++ b/sgx-jvm/avian/include/avian/codegen/targets.h @@ -0,0 +1,32 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#ifndef AVIAN_CODEGEN_TARGETS_H +#define AVIAN_CODEGEN_TARGETS_H + +namespace vm { +class System; +} + +namespace avian { +namespace codegen { + +class Architecture; + +Architecture* makeArchitectureNative(vm::System* system, + bool useNativeFeatures); + +Architecture* makeArchitectureX86(vm::System* system, bool useNativeFeatures); +Architecture* makeArchitectureArm(vm::System* system, bool useNativeFeatures); + +} // namespace codegen +} // namespace avian + +#endif // AVIAN_CODEGEN_TARGETS_H diff --git a/sgx-jvm/avian/include/avian/heap/heap.h b/sgx-jvm/avian/include/avian/heap/heap.h new file mode 100644 index 0000000000..5448fa3222 --- /dev/null +++ b/sgx-jvm/avian/include/avian/heap/heap.h @@ -0,0 +1,88 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#ifndef HEAP_H +#define HEAP_H + +#include +#include + +namespace vm { + +// an object must survive TenureThreshold + 2 garbage collections +// before being copied to gen2 (must be at least 1): +const unsigned TenureThreshold = 3; + +const unsigned FixieTenureThreshold = TenureThreshold + 2; + +class Heap : public avian::util::Allocator { + public: + enum CollectionType { MinorCollection, MajorCollection }; + + enum Status { Null, Reachable, Unreachable, Tenured }; + + class Visitor { + public: + virtual void visit(void*) = 0; + }; + + class Walker { + public: + virtual bool visit(unsigned) = 0; + }; + + class Client { + public: + virtual void collect(void* context, CollectionType type) = 0; + virtual void visitRoots(Visitor*) = 0; + virtual bool isFixed(void*) = 0; + virtual unsigned sizeInWords(void*) = 0; + virtual unsigned copiedSizeInWords(void*) = 0; + virtual void copy(void*, void*) = 0; + virtual void walk(void*, Walker*) = 0; + }; + + virtual void setClient(Client* client) = 0; + virtual void setImmortalHeap(uintptr_t* start, unsigned sizeInWords) = 0; + virtual unsigned remaining() = 0; + virtual unsigned limit() = 0; + virtual bool limitExceeded(int pendingAllocation = 0) = 0; + virtual void collect(CollectionType type, + unsigned footprint, + int pendingAllocation) = 0; + virtual unsigned fixedFootprint(unsigned sizeInWords, bool objectMask) = 0; + virtual void* allocateFixed(avian::util::Alloc* allocator, + unsigned sizeInWords, + bool objectMask) = 0; + virtual void* allocateImmortalFixed(avian::util::Alloc* allocator, + unsigned sizeInWords, + bool objectMask) = 0; + virtual void mark(void* p, unsigned offset, unsigned count) = 0; + virtual void pad(void* p) = 0; + virtual void* follow(void* p) = 0; + + template + T* follow(T* p) + { + return static_cast(follow(static_cast(p))); + } + + virtual void postVisit() = 0; + virtual Status status(void* p) = 0; + virtual CollectionType collectionType() = 0; + virtual void disposeFixies() = 0; + virtual void dispose() = 0; +}; + +Heap* makeHeap(System* system, unsigned limit); + +} // namespace vm + +#endif // HEAP_H diff --git a/sgx-jvm/avian/include/avian/system/memory.h b/sgx-jvm/avian/include/avian/system/memory.h new file mode 100644 index 0000000000..4b4de4dd7b --- /dev/null +++ b/sgx-jvm/avian/include/avian/system/memory.h @@ -0,0 +1,49 @@ + /* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#ifndef AVIAN_SYSTEM_MEMORY_H +#define AVIAN_SYSTEM_MEMORY_H + +#include + +#include + +namespace avian { +namespace system { + +class Memory { + public: + enum Permissions { + Read = 1 << 0, + Write = 1 << 1, + Execute = 1 << 2, + + // Utility munged constants + ReadWrite = Read | Write, + ReadExecute = Read | Execute, + ReadWriteExecute = Read | Write | Execute + }; + + static const size_t PageSize; + + // Allocate a contiguous range of pages. + static util::Slice allocate(size_t sizeInBytes, Permissions perms = ReadWrite); + + // Free a contiguous range of pages. + static void free(util::Slice pages); + + // TODO: In the future: + // static void setPermissions(util::Slice pages, Permissions perms); +}; + +} // namespace system +} // namespace avian + +#endif diff --git a/sgx-jvm/avian/include/avian/system/signal.h b/sgx-jvm/avian/include/avian/system/signal.h new file mode 100644 index 0000000000..a5711e7da7 --- /dev/null +++ b/sgx-jvm/avian/include/avian/system/signal.h @@ -0,0 +1,81 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#ifndef AVIAN_SYSTEM_SIGNAL_H +#define AVIAN_SYSTEM_SIGNAL_H + +#include + +namespace avian { +namespace system { + +// Crash the process. +// On posix, the just calls abort. On windows, we dereference a null pointer in +// order to trigger the crash dump logic. +NO_RETURN void crash(); + +// Registrar for unix-like "signals" (implemented with structured exceptions on +// windows). +// TODO: remove dependence on generated code having a well-known "thread" +// register. Use a thread-local variable instead. +class SignalRegistrar { + public: + class Handler { + public: + // This function receives state information about the paused thread. + // Returns whether to resume execution after the failure point. + virtual bool handleSignal(void** ip, + void** frame, + void** stack, + void** thread) = 0; + }; + + enum Signal { + // "Segmentation fault" exceptions (mostly null pointer dereference, but + // generally access to any non-mapped memory) + SegFault, + DivideByZero, + }; + + SignalRegistrar(); + ~SignalRegistrar(); + + // Register a handler for the given signal. + // After this method call, anytime the given signal is raised, it will be + // handled by the given handler. + // Returns true upon success, false upon failure + bool registerHandler(Signal signal, Handler* handler); + + // Unregister a handler for the given signal. + // After this method call, the given signal will no longer be handled (or, + // rather, it go back to being handled by whatever was registered to handle it + // before us). + // Returns true upon success, false upon failure + bool unregisterHandler(Signal signal); + + // Set the directory that a crash dump will be written to should an unhandled + // exception be thrown. + // Note: this only currently does anything on windows. + // TODO: move this out of this class, into a separate "CrashDumper" class or + // somesuch. + void setCrashDumpDirectory(const char* crashDumpDirectory); + + // This is internal, implementation-specific data. It's declared in the + // specific implementation. + struct Data; + + private: + Data* data; +}; + +} // namespace system +} // namespace avian + +#endif diff --git a/sgx-jvm/avian/include/avian/system/system.h b/sgx-jvm/avian/include/avian/system/system.h new file mode 100644 index 0000000000..e2c4ff5022 --- /dev/null +++ b/sgx-jvm/avian/include/avian/system/system.h @@ -0,0 +1,183 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#ifndef SYSTEM_H +#define SYSTEM_H + +#include "avian/common.h" +#include +#include + +namespace vm { + +class System : public avian::util::Aborter { + public: + typedef intptr_t Status; + + enum FileType { TypeUnknown, TypeDoesNotExist, TypeFile, TypeDirectory }; + + class Thread { + public: + virtual void interrupt() = 0; + virtual bool getAndClearInterrupted() = 0; + virtual void join() = 0; + virtual void dispose() = 0; + }; + + class ThreadVisitor { + public: + virtual void visit(void* ip, void* stack, void* link) = 0; + }; + + class Runnable { + public: + virtual void attach(Thread*) = 0; + virtual void run() = 0; + virtual bool interrupted() = 0; + virtual void setInterrupted(bool v) = 0; + }; + + class Mutex { + public: + virtual void acquire() = 0; + virtual void release() = 0; + virtual void dispose() = 0; + }; + + class Monitor { + public: + virtual bool tryAcquire(Thread* context) = 0; + virtual void acquire(Thread* context) = 0; + virtual void release(Thread* context) = 0; + virtual void wait(Thread* context, int64_t time) = 0; + virtual bool waitAndClearInterrupted(Thread* context, int64_t time) = 0; + virtual void notify(Thread* context) = 0; + virtual void notifyAll(Thread* context) = 0; + virtual Thread* owner() = 0; + virtual void dispose() = 0; + }; + + class Local { + public: + virtual void* get() = 0; + virtual void set(void* p) = 0; + virtual void dispose() = 0; + }; + + class Region { + public: + virtual const uint8_t* start() = 0; + virtual size_t length() = 0; + virtual void dispose() = 0; + }; + + class Directory { + public: + virtual const char* next() = 0; + virtual void dispose() = 0; + }; + + class Library { + public: + virtual void* resolve(const char* symbol) = 0; + virtual const char* name() = 0; + virtual Library* next() = 0; + virtual void setNext(Library* lib) = 0; + virtual void disposeAll() = 0; + }; + + class MonitorResource { + public: + MonitorResource(System::Thread* t, System::Monitor* m) : t(t), m(m) + { + m->acquire(t); + } + + ~MonitorResource() + { + m->release(t); + } + + private: + System::Thread* t; + System::Monitor* m; + }; + + virtual bool success(Status) = 0; + virtual void* tryAllocate(size_t sizeInBytes) = 0; + virtual void free(const void* p) = 0; + virtual Status attach(Runnable*) = 0; + virtual Status start(Runnable*) = 0; + virtual Status make(Mutex**) = 0; + virtual Status make(Monitor**) = 0; + virtual Status make(Local**) = 0; + + virtual Status visit(Thread* thread, Thread* target, ThreadVisitor* visitor) + = 0; + + virtual Status map(Region**, const char* name) = 0; + virtual FileType stat(const char* name, size_t* length) = 0; + virtual Status open(Directory**, const char* name) = 0; + virtual const char* libraryPrefix() = 0; + virtual const char* librarySuffix() = 0; + virtual Status load(Library**, const char* name) = 0; + virtual char pathSeparator() = 0; + virtual char fileSeparator() = 0; + virtual const char* toAbsolutePath(avian::util::AllocOnly* allocator, + const char* name) = 0; + virtual int64_t now() = 0; + virtual void yield() = 0; + virtual void exit(int code) = 0; + virtual void dispose() = 0; +}; + +inline void* allocate(System* s, size_t size) +{ + void* p = s->tryAllocate(size); + if (p == 0) + s->abort(); + return p; +} + +#define ACQUIRE_MONITOR(t, m) \ + System::MonitorResource MAKE_NAME(monitorResource_)(t, m) + +inline avian::util::Aborter* getAborter(System* s) +{ + return s; +} + +inline void NO_RETURN sysAbort(System* s) +{ + abort(s); +} + +// #ifdef NDEBUG + +// # define assertT(a, b) +// # define vm_assert(a, b) + +// #else // not NDEBUG + +// inline void +// assertT(System* s, bool v) +// { +// expect(s, v); +// } + +// # define vm_assert(a, b) vm::assertT(a, b) + +// #endif // not NDEBUG + +AVIAN_EXPORT System* makeSystem(bool reentrant = false); + +} // namespace vm + +#endif // SYSTEM_H diff --git a/sgx-jvm/avian/include/avian/tools/object-writer/tools.h b/sgx-jvm/avian/include/avian/tools/object-writer/tools.h new file mode 100644 index 0000000000..b73f27ffdc --- /dev/null +++ b/sgx-jvm/avian/include/avian/tools/object-writer/tools.h @@ -0,0 +1,170 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#ifndef AVIAN_TOOLS_H_ +#define AVIAN_TOOLS_H_ + +#include + +#include +#include + +#include "avian/environment.h" + +namespace avian { + +namespace tools { + +class OutputStream { + public: + virtual void writeChunk(const void* data, size_t size) = 0; + virtual void write(uint8_t byte); + virtual void writeRepeat(uint8_t byte, size_t size); +}; + +class FileOutputStream : public OutputStream { + private: + FILE* file; + + public: + FileOutputStream(const char* name); + ~FileOutputStream(); + + bool isValid(); + + virtual void writeChunk(const void* data, size_t size); + virtual void write(uint8_t byte); +}; + +class SymbolInfo { + public: + unsigned addr; + util::String name; + + inline SymbolInfo(uint64_t addr, const util::String& name) + : addr(addr), name(name) + { + } + + inline SymbolInfo() : name("") + { + } +}; + +class Buffer { + public: + size_t capacity; + size_t length; + uint8_t* data; + + Buffer(); + ~Buffer(); + + void ensure(size_t more); + void write(const void* d, size_t size); +}; + +class StringTable : public Buffer { + public: + unsigned add(util::String str); +}; + +template +class DynamicArray : public util::Slice { + public: + size_t capacity; + + DynamicArray() : util::Slice((T*)malloc(10 * sizeof(T)), 0), capacity(10) + { + } + ~DynamicArray() + { + free(util::Slice::items); + } + + void ensure(size_t more) + { + if (util::Slice::count + more > capacity) { + capacity = capacity * 2 + more; + util::Slice::items + = (T*)realloc(util::Slice::items, capacity * sizeof(T)); + } + } + + void add(const T& item) + { + ensure(1); + util::Slice::items[util::Slice::count++] = item; + } +}; + +class PlatformInfo { + public: + enum Format { + Elf = AVIAN_FORMAT_ELF, + Pe = AVIAN_FORMAT_PE, + MachO = AVIAN_FORMAT_MACHO, + UnknownFormat = AVIAN_FORMAT_UNKNOWN + }; + + enum Architecture { + x86 = AVIAN_ARCH_X86, + x86_64 = AVIAN_ARCH_X86_64, + Arm = AVIAN_ARCH_ARM, + Arm64 = AVIAN_ARCH_ARM64, + UnknownArch = AVIAN_ARCH_UNKNOWN + }; + + const Format format; + const Architecture arch; + + static Format formatFromString(const char* format); + static Architecture archFromString(const char* arch); + + inline PlatformInfo(Format format, Architecture arch) + : format(format), arch(arch) + { + } + + inline bool operator==(const PlatformInfo& other) + { + return format == other.format && arch == other.arch; + } +}; + +class Platform { + private: + Platform* next; + static Platform* first; + + public: + PlatformInfo info; + + inline Platform(PlatformInfo info) : next(first), info(info) + { + first = this; + } + + enum AccessFlags { Writable = 1 << 0, Executable = 1 << 1 }; + + virtual bool writeObject(OutputStream* out, + util::Slice symbols, + util::Slice data, + unsigned accessFlags, + unsigned alignment) = 0; + + static Platform* getPlatform(PlatformInfo info); +}; + +} // namespace tools + +} // namespace avian + +#endif diff --git a/sgx-jvm/avian/include/avian/util/abort.h b/sgx-jvm/avian/include/avian/util/abort.h new file mode 100644 index 0000000000..c1c1e98010 --- /dev/null +++ b/sgx-jvm/avian/include/avian/util/abort.h @@ -0,0 +1,59 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#ifndef AVIAN_UTIL_ABORT_H +#define AVIAN_UTIL_ABORT_H + +// TODO: remove reference back into the source directory! +// Note: this is needed for UNLIKELY +#include + +namespace avian { +namespace util { + +class Aborter { + public: + virtual void NO_RETURN abort() = 0; +}; + +inline Aborter* getAborter(Aborter* a) +{ + return a; +} + +template +inline void NO_RETURN abort(T t) +{ + getAborter(t)->abort(); + ::abort(); +} + +template +inline void expect(T t, bool v) +{ + if (UNLIKELY(!v)) { + abort(t); + } +} + +#ifdef NDEBUG +#define assertT(t, v) +#else +template +inline void assertT(T t, bool v) +{ + expect(t, v); +} +#endif + +} // namespace util +} // namespace avian + +#endif // AVIAN_UTIL_ABORT_H diff --git a/sgx-jvm/avian/include/avian/util/allocator.h b/sgx-jvm/avian/include/avian/util/allocator.h new file mode 100644 index 0000000000..7060a759ef --- /dev/null +++ b/sgx-jvm/avian/include/avian/util/allocator.h @@ -0,0 +1,42 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#ifndef AVIAN_UTIL_ALLOCATOR_H +#define AVIAN_UTIL_ALLOCATOR_H + +#include + +namespace avian { +namespace util { + +class AllocOnly { + public: + virtual void* allocate(size_t size) = 0; +}; + +class Alloc : public AllocOnly { + public: + virtual void free(const void* p, size_t size) = 0; +}; + +class Allocator : public Alloc { + public: + virtual void* tryAllocate(size_t size) = 0; +}; + +} // namespace util +} // namespace avian + +inline void* operator new(size_t size, avian::util::AllocOnly* allocator) +{ + return allocator->allocate(size); +} + +#endif // AVIAN_UTIL_ALLOCATOR_H diff --git a/sgx-jvm/avian/include/avian/util/arg-parser.h b/sgx-jvm/avian/include/avian/util/arg-parser.h new file mode 100644 index 0000000000..83f089f983 --- /dev/null +++ b/sgx-jvm/avian/include/avian/util/arg-parser.h @@ -0,0 +1,48 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#ifndef AVIAN_UTIL_ARG_PARSER_H +#define AVIAN_UTIL_ARG_PARSER_H + +namespace avian { +namespace util { + +class Arg; + +class ArgParser { + public: + ArgParser(); + + bool parse(int ac, const char* const* av); + void printUsage(const char* exe); + + private: + friend class Arg; + + Arg* first; + Arg** last; +}; + +class Arg { + public: + Arg* next; + bool required; + const char* name; + const char* desc; + + const char* value; + + Arg(ArgParser& parser, bool required, const char* name, const char* desc); +}; + +} // namespace avian +} // namespace util + +#endif // AVIAN_UTIL_ARG_PARSER_H diff --git a/sgx-jvm/avian/include/avian/util/assert.h b/sgx-jvm/avian/include/avian/util/assert.h new file mode 100644 index 0000000000..ab6cee63ed --- /dev/null +++ b/sgx-jvm/avian/include/avian/util/assert.h @@ -0,0 +1,32 @@ +/* Copyright (c) 2008-2013, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#ifndef AVIAN_UTIL_ASSERT_H +#define AVIAN_UTIL_ASSERT_H + +#include + +namespace avian { +namespace util { + +#define UNREACHABLE_ ::abort() + +// TODO: print msg in debug mode +#define UNREACHABLE(msg) ::abort() + +#define ASSERT(that) \ + if (!(that)) { \ + UNREACHABLE(#that); \ + } + +} // namespace util +} // namespace avian + +#endif // AVIAN_UTIL_ASSERT_H diff --git a/sgx-jvm/avian/include/avian/util/cpp.h b/sgx-jvm/avian/include/avian/util/cpp.h new file mode 100644 index 0000000000..bbe1ff56f7 --- /dev/null +++ b/sgx-jvm/avian/include/avian/util/cpp.h @@ -0,0 +1,60 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#ifndef AVIAN_UTIL_CPP_H +#define AVIAN_UTIL_CPP_H + +#include "allocator.h" +#include "math.h" +#include "assert.h" + +namespace avian { +namespace util { + +template +struct NonConst; + +template +struct NonConst { + typedef T Type; +}; + +template +struct NonConst { + typedef T Type; +}; + +template +struct ArgumentCount; + +template +struct ArgumentCount { + enum { Result = 1 + ArgumentCount::Result }; +}; + +template <> +struct ArgumentCount<> { + enum { Result = 0 }; +}; + +template +void setArrayElements(T*) { +} + +template +void setArrayElements(T* arr, T elem, Ts... ts) { + *arr = elem; + setArrayElements(arr, ts...); +} + +} // namespace util +} // namespace avian + +#endif // AVIAN_UTIL_CPP_H diff --git a/sgx-jvm/avian/include/avian/util/fixed-allocator.h b/sgx-jvm/avian/include/avian/util/fixed-allocator.h new file mode 100644 index 0000000000..fa5a2c66b2 --- /dev/null +++ b/sgx-jvm/avian/include/avian/util/fixed-allocator.h @@ -0,0 +1,43 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#ifndef AVIAN_UTIL_FIXED_ALLOCATOR_H +#define AVIAN_UTIL_FIXED_ALLOCATOR_H + +#include "allocator.h" +#include "abort.h" +#include "slice.h" + +namespace avian { +namespace util { + +// An Allocator that allocates, bump-pointer style, out of a pre-defined chunk +// of memory. +class FixedAllocator : public Alloc { + public: + FixedAllocator(Aborter* a, Slice memory); + + virtual void* tryAllocate(size_t size); + + void* allocate(size_t size, unsigned padAlignment); + + virtual void* allocate(size_t size); + + virtual void free(const void* p, size_t size); + + Aborter* a; + Slice memory; + size_t offset; +}; + +} // namespace util +} // namespace avian + +#endif // AVIAN_UTIL_FIXED_ALLOCATOR_H diff --git a/sgx-jvm/avian/include/avian/util/hash.h b/sgx-jvm/avian/include/avian/util/hash.h new file mode 100644 index 0000000000..c9342b5a5f --- /dev/null +++ b/sgx-jvm/avian/include/avian/util/hash.h @@ -0,0 +1,57 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#ifndef AVIAN_UTIL_HASH_H +#define AVIAN_UTIL_HASH_H + +#include "slice.h" + +namespace avian { +namespace util { + +inline uint32_t hash(const char* s) +{ + uint32_t h = 0; + for (unsigned i = 0; s[i]; ++i) { + h = (h * 31) + s[i]; + } + return h; +} + +inline uint32_t hash(Slice data) +{ + const uint8_t* s = data.begin(); + uint32_t h = 0; + for (size_t i = 0; i < data.count; ++i) { + h = (h * 31) + s[i]; + } + return h; +} + +inline uint32_t hash(Slice data) +{ + return hash(Slice( + reinterpret_cast(data.begin()), data.count)); +} + +inline uint32_t hash(Slice data) +{ + const uint16_t* s = data.begin(); + uint32_t h = 0; + for (size_t i = 0; i < data.count; ++i) { + h = (h * 31) + s[i]; + } + return h; +} + +} // namespace util +} // namespace avian + +#endif // AVIAN_UTIL_HASH_H diff --git a/sgx-jvm/avian/include/avian/util/list.h b/sgx-jvm/avian/include/avian/util/list.h new file mode 100644 index 0000000000..b268176044 --- /dev/null +++ b/sgx-jvm/avian/include/avian/util/list.h @@ -0,0 +1,44 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#ifndef AVIAN_UTIL_LIST_H +#define AVIAN_UTIL_LIST_H + +#include "allocator.h" + +namespace avian { +namespace util { + +template +class List { + public: + List(const T& item, List* next) : item(item), next(next) + { + } + + unsigned count() + { + unsigned count = 0; + List* c = this; + while (c) { + ++count; + c = c->next; + } + return count; + } + + T item; + List* next; +}; + +} // namespace util +} // namespace avian + +#endif // AVIAN_UTIL_LIST_H diff --git a/sgx-jvm/avian/include/avian/util/math.h b/sgx-jvm/avian/include/avian/util/math.h new file mode 100644 index 0000000000..36a4ca0513 --- /dev/null +++ b/sgx-jvm/avian/include/avian/util/math.h @@ -0,0 +1,67 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#ifndef AVIAN_UTIL_MATH_H +#define AVIAN_UTIL_MATH_H + +#undef max +#undef min + +namespace avian { +namespace util { + +inline unsigned max(unsigned a, unsigned b) +{ + return (a > b ? a : b); +} + +inline unsigned min(unsigned a, unsigned b) +{ + return (a < b ? a : b); +} + +inline unsigned avg(unsigned a, unsigned b) +{ + return (a + b) / 2; +} + +inline unsigned ceilingDivide(unsigned n, unsigned d) +{ + return (n + d - 1) / d; +} + +inline bool powerOfTwo(unsigned n) +{ + for (; n > 2; n >>= 1) + if (n & 1) + return false; + return true; +} + +inline unsigned nextPowerOfTwo(unsigned n) +{ + unsigned r = 1; + while (r < n) + r <<= 1; + return r; +} + +inline unsigned log(unsigned n) +{ + unsigned r = 0; + for (unsigned i = 1; i < n; ++r) + i <<= 1; + return r; +} + +} // namespace util +} // namespace avian + +#endif // AVIAN_UTIL_MATH_H diff --git a/sgx-jvm/avian/include/avian/util/runtime-array.h b/sgx-jvm/avian/include/avian/util/runtime-array.h new file mode 100644 index 0000000000..d89ad1884d --- /dev/null +++ b/sgx-jvm/avian/include/avian/util/runtime-array.h @@ -0,0 +1,41 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#ifndef AVIAN_UTIL_RUNTIME_ARRAY_H +#define AVIAN_UTIL_RUNTIME_ARRAY_H + +#ifdef _MSC_VER + +template +class RuntimeArray { + public: + RuntimeArray(unsigned size) : body(static_cast(malloc(size * sizeof(T)))) + { + } + + ~RuntimeArray() + { + free(body); + } + + T* body; +}; + +#define RUNTIME_ARRAY(type, name, size) RuntimeArray name(size); +#define RUNTIME_ARRAY_BODY(name) name.body + +#else // not _MSC_VER + +#define RUNTIME_ARRAY(type, name, size) type name##_body[size]; +#define RUNTIME_ARRAY_BODY(name) name##_body + +#endif + +#endif // AVIAN_UTIL_RUNTIME_ARRAY_H diff --git a/sgx-jvm/avian/include/avian/util/slice.h b/sgx-jvm/avian/include/avian/util/slice.h new file mode 100644 index 0000000000..b8877819c0 --- /dev/null +++ b/sgx-jvm/avian/include/avian/util/slice.h @@ -0,0 +1,101 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#ifndef AVIAN_UTIL_SLICE_H +#define AVIAN_UTIL_SLICE_H + +#include "allocator.h" +#include "math.h" +#include "assert.h" +#include "cpp.h" + +namespace avian { +namespace util { + +template +class Slice { + public: + T* items; + size_t count; + + inline Slice(T* items, size_t count) : items(items), count(count) + { + } + + inline Slice(const Slice::Type>& copy) + : items(copy.items), count(copy.count) + { + } + + inline T& operator[](size_t index) + { + ASSERT(index < count); + return items[index]; + } + + inline T* begin() + { + return items; + } + + inline T* end() + { + return items + count; + } + + inline Slice subslice(size_t begin, size_t count) + { + ASSERT(begin <= this->count); + ASSERT(begin + count <= this->count); + return Slice(this->begin() + begin, count); + } + + static Slice alloc(AllocOnly* a, size_t count) + { + return Slice((T*)a->allocate(sizeof(T) * count), count); + } + + static Slice allocAndSet(AllocOnly* a, size_t count, const T& item) + { + Slice slice(alloc(a, count)); + for (size_t i = 0; i < count; i++) { + slice[i] = item; + } + return slice; + } + + Slice clone(AllocOnly* a, size_t newCount) + { + T* newItems = (T*)a->allocate(newCount * sizeof(T)); + memcpy(newItems, items, min(count, newCount) * sizeof(T)); + return Slice(newItems, newCount); + } + + Slice cloneAndSet(AllocOnly* a, size_t newCount, const T& item) + { + Slice slice(clone(a, newCount)); + for (size_t i = count; i < newCount; i++) { + slice[i] = item; + } + return slice; + } + + void resize(Alloc* a, size_t newCount) + { + Slice slice(clone(a, newCount)); + a->free(items, count); + *this = slice; + } +}; + +} // namespace util +} // namespace avian + +#endif // AVIAN_UTIL_SLICE_H diff --git a/sgx-jvm/avian/include/avian/util/stream.h b/sgx-jvm/avian/include/avian/util/stream.h new file mode 100644 index 0000000000..f957dc90de --- /dev/null +++ b/sgx-jvm/avian/include/avian/util/stream.h @@ -0,0 +1,126 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#ifndef STREAM_H +#define STREAM_H + +#include "avian/common.h" + +namespace vm { + +class AbstractStream { + public: + class Client { + public: + virtual void handleError() = 0; + }; + + AbstractStream(Client* client, unsigned size) + : client(client), size(size), position_(0) + { + } + + unsigned position() + { + return position_; + } + + void setPosition(unsigned p) + { + position_ = p; + } + + void skip(unsigned size) + { + if (size > this->size - position_) { + client->handleError(); + } else { + position_ += size; + } + } + + void read(uint8_t* dst, unsigned size) + { + if (size > this->size - position_) { + memset(dst, 0, size); + + client->handleError(); + } else { + copy(dst, position_, size); + position_ += size; + } + } + + uint8_t read1() + { + uint8_t v; + read(&v, 1); + return v; + } + + uint16_t read2() + { + uint16_t a = read1(); + uint16_t b = read1(); + return (a << 8) | b; + } + + uint32_t read4() + { + uint32_t a = read2(); + uint32_t b = read2(); + return (a << 16) | b; + } + + uint64_t read8() + { + uint64_t a = read4(); + uint64_t b = read4(); + return (a << 32) | b; + } + + uint32_t readFloat() + { + return read4(); + } + + uint64_t readDouble() + { + return read8(); + } + + protected: + virtual void copy(uint8_t* dst, unsigned offset, unsigned size) = 0; + + private: + Client* client; + unsigned size; + unsigned position_; +}; + +class Stream : public AbstractStream { + public: + Stream(Client* client, const uint8_t* data, unsigned size) + : AbstractStream(client, size), data(data) + { + } + + private: + virtual void copy(uint8_t* dst, unsigned offset, unsigned size) + { + memcpy(dst, data + offset, size); + } + + const uint8_t* data; +}; + +} // namespace vm + +#endif // STREAM_H diff --git a/sgx-jvm/avian/include/avian/util/string.h b/sgx-jvm/avian/include/avian/util/string.h new file mode 100644 index 0000000000..436bdeacd9 --- /dev/null +++ b/sgx-jvm/avian/include/avian/util/string.h @@ -0,0 +1,36 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#ifndef AVIAN_UTIL_STRING_H +#define AVIAN_UTIL_STRING_H + +#include + +namespace avian { +namespace util { + +class String { + public: + const char* text; + size_t length; + + String(const char* text) : text(text), length(strlen(text)) + { + } + + inline String(const char* text, size_t length) : text(text), length(length) + { + } +}; + +} // namespace util +} // namespace avain + +#endif // AVIAN_UTIL_STRING_H diff --git a/sgx-jvm/avian/include/avian/util/tokenizer.h b/sgx-jvm/avian/include/avian/util/tokenizer.h new file mode 100644 index 0000000000..0b790314b5 --- /dev/null +++ b/sgx-jvm/avian/include/avian/util/tokenizer.h @@ -0,0 +1,54 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#ifndef AVIAN_UTIL_TOKENIZER_H +#define AVIAN_UTIL_TOKENIZER_H + +#include "string.h" + +namespace avian { +namespace util { + +class Tokenizer { + public: + Tokenizer(const char* s, char delimiter) + : s(s), limit(0), delimiter(delimiter) + { + } + + Tokenizer(String str, char delimiter) + : s(str.text), limit(str.text + str.length), delimiter(delimiter) + { + } + + bool hasMore() + { + while (s != limit and *s == delimiter) + ++s; + return s != limit and *s != 0; + } + + String next() + { + const char* p = s; + while (s != limit and *s and *s != delimiter) + ++s; + return String(p, s - p); + } + + const char* s; + const char* limit; + char delimiter; +}; + +} // namespace util +} // namespace avain + +#endif // AVIAN_UTIL_TOKENIZER_H diff --git a/sgx-jvm/avian/makefile b/sgx-jvm/avian/makefile new file mode 100755 index 0000000000..d7db2484bb --- /dev/null +++ b/sgx-jvm/avian/makefile @@ -0,0 +1,2387 @@ +MAKEFLAGS = -s + +name = avian +version := $(shell grep version gradle.properties | cut -d'=' -f2) + +java-version := $(shell "$(JAVA_HOME)/bin/java" -version 2>&1 \ + | head -n 1 \ + | sed 's/.*version "1.\([^.]*\).*/\1/') + +build-arch := $(shell uname -m \ + | sed 's/^i.86$$/i386/' \ + | sed 's/^x86pc$$/i386/' \ + | sed 's/amd64/x86_64/' \ + | sed 's/^arm.*$$/arm/' \ + | sed 's/aarch64/arm64/') + +build-platform := \ + $(shell uname -s | tr [:upper:] [:lower:] \ + | sed \ + -e 's/^mingw64.*$$/mingw32/' \ + -e 's/^mingw32.*$$/mingw32/' \ + -e 's/^cygwin.*$$/cygwin/' \ + -e 's/^darwin.*$$/macosx/') + +arch = $(build-arch) +target-arch = $(arch) + +bootimage-platform = \ + $(subst cygwin,windows,$(subst mingw32,windows,$(build-platform))) + +platform = $(bootimage-platform) + +codegen-targets = native + +mode = fast +process = compile + +ifneq ($(process),compile) + options := -$(process) +endif +ifneq ($(mode),fast) + options := $(options)-$(mode) +endif +ifneq ($(lzma),) + options := $(options)-lzma +endif +ifeq ($(bootimage),true) + options := $(options)-bootimage + ifeq ($(bootimage-test),true) + # this option indicates that we should AOT-compile the test + # classes as well as the class library + options := $(options)-test + endif +endif +ifeq ($(tails),true) + options := $(options)-tails +endif +ifeq ($(continuations),true) + options := $(options)-continuations +endif +ifeq ($(codegen-targets),all) + options := $(options)-all +endif + +ifeq ($(filter debug debug-fast fast stress stress-major small,$(mode)),) + x := $(error "'$(mode)' is not a valid mode (choose one of: debug debug-fast fast stress stress-major small)") +endif + +ifeq ($(filter compile interpret,$(process)),) + x := $(error "'$(process)' is not a valid process (choose one of: compile interpret)") +endif + +ifeq ($(filter x86_64 i386 arm arm64,$(arch)),) + x := $(error "'$(arch)' is not a supported architecture (choose one of: x86_64 i386 arm arm64)") +endif + +ifeq ($(platform),darwin) + x := $(error "please use 'platform=macosx' or 'platform=ios' instead of 'platform=$(platform)'") +endif + +ifneq ($(ios),) + x := $(error "please use 'platform=ios' instead of 'ios=true'") +endif + +ifeq ($(filter linux windows macosx ios freebsd,$(platform)),) + x := $(error "'$(platform)' is not a supported platform (choose one of: linux windows macosx ios freebsd)") +endif + +ifeq ($(platform),macosx) + ifneq ($(filter arm arm64,$(arch)),) + x := $(error "please use ('arch=arm' or 'arch=arm64') 'platform=ios' to build for ios-arm") + endif +endif + +ifeq ($(platform),ios) + ifeq ($(filter i386 x86_64 arm arm64,$(arch)),) + x := $(error "please specify 'arch=i386', 'arch=x86_64', 'arch=arm', or 'arch=arm64' with 'platform=ios'") + endif +endif + +ifeq ($(bootimage-test),true) + ifneq ($(bootimage),true) + x := $(error "bootimage-test=true only works when bootimage=true") + endif +endif + +aot-only = false +root := $(shell (cd .. && pwd)) +build = build/$(platform)-$(arch)$(options) +host-build-root = $(build)/host +classpath-build = $(build)/classpath +test-build = $(build)/test +src = src +classpath-src = classpath +test = test +unittest = unittest +win32 ?= $(root)/win32 +win64 ?= $(root)/win64 +winrt ?= $(root)/winrt +wp8 ?= $(root)/wp8 + +classpath = avian + +bootimage-classpath = $(classpath-build) + +ifeq ($(bootimage-test),true) + bootimage-classpath = $(classpath-build):$(test-build) +endif + +ifeq ($(use-werror),true) + werror = -Werror +endif + +test-executable = $(shell pwd)/$(executable) +boot-classpath = $(classpath-build) +embed-prefix = /avian-embedded + +native-path = echo + +platform-kernel = $(subst macosx,darwin,$(subst ios,darwin,$1)) + +build-kernel = $(call platform-kernel,$(build-platform)) +kernel = $(call platform-kernel,$(platform)) + +ifeq ($(build-platform),cygwin) + native-path = cygpath -m +endif + +windows-path = echo + +path-separator = : + +ifneq (,$(filter mingw32 cygwin,$(build-platform))) + path-separator = ; +endif + +target-path-separator = : + +ifeq ($(platform),windows) + target-path-separator = ; +endif + +library-path-variable = LD_LIBRARY_PATH + +ifeq ($(build-kernel),darwin) + library-path-variable = DYLD_LIBRARY_PATH +endif + +library-path = $(library-path-variable)=$(build) + + + +ifneq ($(openjdk),) + openjdk-version := $(shell $(openjdk)/bin/java -version 2>&1 \ + | head -n 1 \ + | sed 's/.*version "1.\([^.]*\).*/\1/') + + openjdk-arch = $(arch) + ifeq ($(arch),x86_64) + openjdk-arch = amd64 + endif + + ifneq ($(android),) + x := $(error "android and openjdk are incompatible") + endif + + ifneq ($(openjdk-src),) + include openjdk-src.mk + options := $(options)-openjdk-src + classpath-objects = $(openjdk-objects) $(openjdk-local-objects) + classpath-cflags = -DAVIAN_OPENJDK_SRC -DBOOT_JAVAHOME + openjdk-jar-dep = $(build)/openjdk-jar.dep + classpath-jar-dep = $(openjdk-jar-dep) + javahome = $(embed-prefix)/javahomeJar + javahome-files = lib/currency.data lib/security/java.security \ + lib/security/java.policy lib/security/cacerts + + ifneq (,$(wildcard $(openjdk)/jre/lib/zi)) + javahome-files += lib/zi + endif + + ifneq (,$(wildcard $(openjdk)/jre/lib/tzdb.dat)) + javahome-files += lib/tzdb.dat + endif + + local-policy = lib/security/local_policy.jar + ifneq (,$(wildcard $(openjdk)/jre/$(local-policy))) + javahome-files += $(local-policy) + endif + + export-policy = lib/security/US_export_policy.jar + ifneq (,$(wildcard $(openjdk)/jre/$(export-policy))) + javahome-files += $(export-policy) + endif + + ifeq ($(platform),windows) + javahome-files += lib/tzmappings + endif + javahome-object = $(build)/javahome-jar.o + boot-javahome-object = $(build)/boot-javahome.o + stub-sources = $(src)/openjdk/stubs.cpp + stub-objects = $(call cpp-objects,$(stub-sources),$(src),$(build)) + else + soname-flag = -Wl,-soname -Wl,$(so-prefix)jvm$(so-suffix) + version-script-flag = -Wl,--version-script=openjdk.ld + options := $(options)-openjdk + test-executable = $(shell pwd)/$(executable-dynamic) + ifeq ($(build-kernel),darwin) + library-path = \ + $(library-path-variable)=$(build):$(openjdk)/jre/lib + else + library-path = \ + $(library-path-variable)=$(build):$(openjdk)/jre/lib/$(openjdk-arch) + endif + javahome = "$$($(native-path) "$(openjdk)/jre")" + endif + + classpath = openjdk + boot-classpath := "$(boot-classpath)$(path-separator)$$($(native-path) "$(openjdk)/jre/lib/rt.jar")" + build-javahome = $(openjdk)/jre +endif + +ifneq ($(android),) + options := $(options)-android + classpath-jar-dep = $(build)/android.dep + luni-native = $(android)/libcore/luni/src/main/native + classpath-cflags = -DBOOT_JAVAHOME + android-cflags = -I$(luni-native) \ + -I$(android)/libnativehelper/include/nativehelper \ + -I$(android)/libnativehelper \ + -I$(android)/system/core/include \ + -I$(android)/external/zlib \ + -I$(android)/external/icu4c/i18n \ + -I$(android)/external/icu4c/common \ + -I$(android)/external/expat \ + -I$(android)/external/openssl/include \ + -I$(android)/external/openssl \ + -I$(android)/libcore/include \ + -I$(build)/android-src/external/fdlibm \ + -I$(build)/android-src \ + -fno-exceptions \ + -D_FILE_OFFSET_BITS=64 \ + -DOS_SHARED_LIB_FORMAT_STR="\"$(so-prefix)%s$(so-suffix)\"" \ + -DJNI_JARJAR_PREFIX= \ + -D__DARWIN_UNIX03=1 \ + -D__PROVIDE_FIXMES \ + -DSTATIC_LIB \ + -D__STDC_FORMAT_MACROS=1 \ + -g3 \ + -Wno-shift-count-overflow + + # on Windows (in MinGW-based build) there are neither __BEGIN_DECLS nor __END_DECLS + # defines; we don't want to patch every file that uses them, so we stub them in + # using CFLAGS mechanism + # Also we have off64_t defined in mingw-w64 headers, so let's tell that + ifeq ($(platform),windows) + android-cflags += "-D__BEGIN_DECLS=extern \"C\" {" "-D__END_DECLS=}" "-DHAVE_OFF64_T" + endif + + luni-cpps := $(shell find $(luni-native) -name '*.cpp') + + libziparchive-native := $(android)/system/core/libziparchive + libziparchive-ccs := $(libziparchive-native)/zip_archive.cc + + libutils-native := $(android)/system/core/libutils + libutils-cpps := $(libutils-native)/FileMap.cpp + + libnativehelper-native := $(android)/libnativehelper + libnativehelper-cpps := $(libnativehelper-native)/JniConstants.cpp \ + $(libnativehelper-native)/toStringArray.cpp + + crypto-native := $(android)/external/conscrypt/src/main/native + crypto-cpps := $(crypto-native)/org_conscrypt_NativeCrypto.cpp + + ifeq ($(platform),windows) + android-cflags += -D__STDC_CONSTANT_MACROS -DHAVE_WIN32_FILEMAP -D__STDC_FORMAT_MACROS + blacklist = $(luni-native)/java_io_Console.cpp \ + $(luni-native)/java_lang_ProcessManager.cpp + + icu-libs := $(android)/external/icu4c/lib/libsicuin.a \ + $(android)/external/icu4c/lib/libsicuuc.a \ + $(android)/external/icu4c/lib/sicudt.a + platform-lflags := -lgdi32 -lshlwapi -lwsock32 -static-libgcc -static-libstdc++ -Wl,-Bstatic -lstdc++ -lpthread -Wl,-Bdynamic + else + android-cflags += -fPIC -DHAVE_SYS_UIO_H -DHAVE_POSIX_FILEMAP + blacklist = + + icu-libs := $(android)/external/icu4c/lib/libicui18n.a \ + $(android)/external/icu4c/lib/libicuuc.a \ + $(android)/external/icu4c/lib/libicudata.a + endif + luni-cpps := $(filter-out $(blacklist),$(luni-cpps)) + + classpath-lflags := \ + $(icu-libs) \ + $(android)/external/fdlibm/libfdm.a \ + $(android)/external/expat/.libs/libexpat.a \ + $(android)/openssl-upstream/libssl.a \ + $(android)/openssl-upstream/libcrypto.a \ + $(platform-lflags) \ + -lstdc++ + + ifeq ($(platform),linux) + android-cflags += -DHAVE_OFF64_T + classpath-lflags += -lrt + endif + + classpath-objects = \ + $(call cpp-objects,$(luni-cpps),$(luni-native),$(build)) \ + $(call cpp-objects,$(crypto-cpps),$(crypto-native),$(build)) \ + $(call cpp-objects,$(libnativehelper-cpps),$(libnativehelper-native),$(build)) \ + $(call cc-objects,$(libziparchive-ccs),$(libziparchive-native),$(build)) \ + $(call cpp-objects,$(libutils-cpps),$(libutils-native),$(build)) + luni-java = $(android)/libcore/luni/src/main/java + + luni-blacklist = \ + $(luni-java)/libcore/reflect/AnnotationAccess.java + + luni-javas := \ + $(filter-out $(luni-blacklist),$(shell find $(luni-java) -name '*.java')) + + luni-nonjavas := $(shell find $(luni-java) -not -type d -not -name '*.java') + luni-copied-nonjavas = $(call noop-files,$(luni-nonjavas),$(luni-java),) + + crypto-java = $(android)/external/conscrypt/src/main/java + crypto-javas := $(shell find $(crypto-java) -name '*.java') + + crypto-platform-java = $(android)/external/conscrypt/src/platform/java + crypto-platform-javas := $(shell find $(crypto-platform-java) -name '*.java') + + dalvik-java = $(android)/libcore/dalvik/src/main/java + dalvik-javas := \ + $(dalvik-java)/dalvik/system/DalvikLogHandler.java \ + $(dalvik-java)/dalvik/system/CloseGuard.java \ + $(dalvik-java)/dalvik/system/VMDebug.java \ + $(dalvik-java)/dalvik/system/BlockGuard.java \ + $(dalvik-java)/dalvik/system/SocketTagger.java \ + $(dalvik-java)/dalvik/system/DalvikLogging.java \ + + libart-java = $(android)/libcore/libart/src/main/java + libart-javas := \ + $(libart-java)/dalvik/system/VMRuntime.java \ + $(libart-java)/dalvik/system/VMStack.java \ + $(libart-java)/java/lang/Thread.java \ + $(libart-java)/java/lang/ThreadGroup.java \ + $(libart-java)/java/lang/Enum.java \ + $(libart-java)/java/lang/String.java \ + $(libart-java)/java/lang/ref/Reference.java \ + $(libart-java)/java/lang/reflect/AccessibleObject.java \ + + xml-java = $(android)/libcore/xml/src/main/java + xml-javas := $(shell find $(xml-java) -name '*.java') + + okhttp-android-java = $(android)/external/okhttp/android/main/java + okhttp-android-javas := $(shell find $(okhttp-android-java) -name '*.java') + + okhttp-java = $(android)/external/okhttp/okhttp/src/main/java + okhttp-javas := $(shell find $(okhttp-java) -name '*.java') + + okio-java = $(android)/external/okhttp/okio/src/main/java + okio-javas := $(shell find $(okio-java) -name '*.java') + + bcpkix-java = $(android)/external/bouncycastle/bcpkix/src/main/java + bcpkix-javas := $(shell find $(bcpkix-java) -name '*.java') + + bcprov-java = $(android)/external/bouncycastle/bcprov/src/main/java + bcprov-javas := $(shell find $(bcprov-java) -name '*.java') + + android-classes = \ + $(call java-classes,$(luni-javas),$(luni-java),$(build)/android) \ + $(call java-classes,$(crypto-javas),$(crypto-java),$(build)/android) \ + $(call java-classes,$(crypto-platform-javas),$(crypto-platform-java),$(build)/android) \ + $(call java-classes,$(dalvik-javas),$(dalvik-java),$(build)/android) \ + $(call java-classes,$(libart-javas),$(libart-java),$(build)/android) \ + $(call java-classes,$(xml-javas),$(xml-java),$(build)/android) \ + $(call java-classes,$(okhttp-javas),$(okhttp-java),$(build)/android) \ + $(call java-classes,$(okhttp-android-javas),$(okhttp-android-java),$(build)/android) \ + $(call java-classes,$(okio-javas),$(okio-java),$(build)/android) \ + $(call java-classes,$(bcpkix-javas),$(bcpkix-java),$(build)/android) \ + $(call java-classes,$(bcprov-javas),$(bcprov-java),$(build)/android) + + classpath = android + + javahome-files = tzdata + javahome-object = $(build)/javahome-jar.o + boot-javahome-object = $(build)/boot-javahome.o + build-javahome = $(android)/bionic/libc/zoneinfo + stub-sources = $(src)/android/stubs.cpp + stub-objects = $(call cpp-objects,$(stub-sources),$(src),$(build)) +endif + +ifeq ($(classpath),avian) + jni-sources := $(shell find $(classpath-src) -name '*.cpp') + jni-objects = $(call cpp-objects,$(jni-sources),$(classpath-src),$(build)) + classpath-objects = $(jni-objects) +endif + +input = List + +ifeq ($(use-clang),true) + build-cxx = clang++ -std=c++11 + build-cc = clang +else + build-cxx = g++ + build-cc = gcc +endif + +mflag = +ifneq ($(kernel),darwin) + ifeq ($(arch),i386) + mflag = -m32 + endif + ifeq ($(arch),x86_64) + mflag = -m64 + endif +endif + +target-format = elf + +cxx = $(build-cxx) $(mflag) +cc = $(build-cc) $(mflag) + +ar = ar +ranlib = ranlib +dlltool = dlltool +vg = nice valgrind --num-callers=32 --db-attach=yes --freelist-vol=100000000 +vg += --leak-check=full --suppressions=valgrind.supp +db = gdb --args +javac = "$(JAVA_HOME)/bin/javac" -encoding UTF-8 +javah = "$(JAVA_HOME)/bin/javah" +jar = "$(JAVA_HOME)/bin/jar" +strip = strip +strip-all = --strip-all + +rdynamic = -rdynamic + +cflags_debug = -O0 -g3 +cflags_debug_fast = -O0 -g3 +cflags_stress = -O0 -g3 +cflags_stress_major = -O0 -g3 +ifeq ($(use-clang),true) + cflags_fast = -O3 -g3 + cflags_small = -Oz -g3 +else + cflags_fast = -O3 -g3 + cflags_small = -Os -g3 +endif + +# note that we suppress the non-virtual-dtor warning because we never +# use the delete operator, which means we don't need virtual +# destructors: +warnings = -Wall -Wextra $(werror) -Wunused-parameter -Winit-self \ + -Wno-non-virtual-dtor + +target-cflags = -DTARGET_BYTES_PER_WORD=$(pointer-size) + +common-cflags = $(warnings) -std=c++0x -fno-rtti -fno-exceptions -I$(classpath-src) \ + "-I$(JAVA_HOME)/include" -I$(src) -I$(build) -Iinclude $(classpath-cflags) \ + -D__STDC_LIMIT_MACROS -D_JNI_IMPLEMENTATION_ -DAVIAN_VERSION=\"$(version)\" \ + -DAVIAN_INFO="\"$(info)\"" \ + -DUSE_ATOMIC_OPERATIONS -DAVIAN_JAVA_HOME=\"$(javahome)\" \ + -DAVIAN_EMBED_PREFIX=\"$(embed-prefix)\" $(target-cflags) + +asmflags = $(target-cflags) -I$(src) + +ifneq (,$(filter i386 x86_64,$(arch))) + ifeq ($(use-frame-pointer),true) + common-cflags += -fno-omit-frame-pointer -DAVIAN_USE_FRAME_POINTER + asmflags += -DAVIAN_USE_FRAME_POINTER + endif +endif + +build-cflags = $(common-cflags) -fPIC -fvisibility=hidden \ + "-I$(JAVA_HOME)/include/linux" -I$(src) -pthread + +converter-cflags = -D__STDC_CONSTANT_MACROS -std=c++0x -Iinclude/ -Isrc/ \ + -fno-rtti -fno-exceptions \ + -DAVIAN_TARGET_ARCH=AVIAN_ARCH_UNKNOWN \ + -DAVIAN_TARGET_FORMAT=AVIAN_FORMAT_UNKNOWN \ + -Wall -Wextra $(werror) -Wunused-parameter -Winit-self -Wno-non-virtual-dtor + +cflags = $(build-cflags) + +common-lflags = -lm -lz + +ifeq ($(use-clang),true) + ifeq ($(build-kernel),darwin) + common-lflags += -Wl,-export_dynamic + else + ifneq ($(platform),windows) + common-lflags += -Wl,-E + else + common-lflags += -Wl,--export-all-symbols + endif + endif +endif + +build-lflags = -lz -lpthread -ldl + +lflags = $(common-lflags) -lpthread -ldl + +build-system = posix + +system = posix +asm = x86 + +ifeq ($(system),sgx) + cflags += -DSGX +endif + +pointer-size = 8 + +so-prefix = lib +so-suffix = .so + +static-prefix = lib +static-suffix = .a + +output = -o $(1) +asm-output = -o $(1) +asm-input = -c $(1) +asm-format = S +as = $(cc) +ld = $(cc) +build-ld = $(build-cc) +build-ld-cpp = $(build-cxx) + +default-remote-test-host = localhost +default-remote-test-port = 22 +ifeq ($(remote-test-host),) + remote-test-host = $(default-remote-test-host) +else + remote-test = true +endif +ifeq ($(remote-test-port),) + remote-test-port = $(default-remote-test-port) +else + remote-test = true +endif +remote-test-user = ${USER} +remote-test-dir = /tmp/avian-test-${USER} + +static = -static +shared = -shared + +rpath = -Wl,-rpath=\$$ORIGIN -Wl,-z,origin + +openjdk-extra-cflags = -fvisibility=hidden + +bootimage-cflags = -DTARGET_BYTES_PER_WORD=$(pointer-size) +bootimage-symbols = _binary_bootimage_bin_start:_binary_bootimage_bin_end +codeimage-symbols = _binary_codeimage_bin_start:_binary_codeimage_bin_end + +developer-dir := $(shell if test -d /Developer/Platforms/$(target).platform/Developer/SDKs; then echo /Developer; \ + else echo /Applications/Xcode.app/Contents/Developer; fi) + +ifneq (,$(filter i386 arm,$(arch))) + pointer-size = 4 +endif + +ifneq (,$(filter arm arm64,$(arch))) + asm = arm + + ifneq ($(platform),ios) + ifneq ($(arch),arm64) + no-psabi = -Wno-psabi + cflags += -marm $(no-psabi) + + # By default, assume we can't use armv7-specific instructions on + # non-iOS platforms. Ideally, we'd detect this at runtime. + armv6=true + endif + endif + + ifneq ($(arch),$(build-arch)) + ifneq ($(kernel),darwin) + ifeq ($(arch),arm64) + cxx = aarch64-linux-gnu-g++ + cc = aarch64-linux-gnu-gcc + ar = aarch64-linux-gnu-ar + ranlib = aarch64-linux-gnu-ranlib + strip = aarch64-linux-gnu-strip + else + cxx = arm-linux-gnueabi-g++ + cc = arm-linux-gnueabi-gcc + ar = arm-linux-gnueabi-ar + ranlib = arm-linux-gnueabi-ranlib + strip = arm-linux-gnueabi-strip + endif + endif + endif +endif + +ifeq ($(armv6),true) + cflags += -DAVIAN_ASSUME_ARMV6 +endif + +ifeq ($(platform),ios) + cflags += -DAVIAN_IOS + use-lto = false +endif + +ifeq ($(build-kernel),darwin) + build-cflags = $(common-cflags) -fPIC -fvisibility=hidden -I$(src) + cflags += -Wno-deprecated-declarations + build-lflags += -framework CoreFoundation +endif + +ifeq ($(platform),qnx) + cflags = $(common-cflags) -fPIC -fvisibility=hidden -I$(src) + lflags = $(common-lflags) -lsocket + ifeq ($(build-platform),qnx) + build-cflags = $(common-cflags) -fPIC -fvisibility=hidden -I$(src) + build-lflags = $(common-lflags) + else + ifeq ($(arch),i386) + prefix = i486-pc-nto-qnx6.5.0- + else + prefix = arm-unknown-nto-qnx6.5.0- + endif + endif + cxx = $(prefix)g++ + cc = $(prefix)gcc + ar = $(prefix)ar + ranlib = $(prefix)ranlib + strip = $(prefix)strip + rdynamic = -Wl,--export-dynamic +endif + +ifeq ($(platform),freebsd) +# There is no -ldl on FreeBSD + build-lflags = $(common-lflags) -lz -lpthread + lflags = $(common-lflags) -lpthread +# include/freebsd instead of include/linux + build-cflags = $(common-cflags) -fPIC -fvisibility=hidden \ + "-I$(JAVA_HOME)/include/freebsd" -I$(src) -pthread + cflags = $(build-cflags) +endif +ifeq ($(platform),android) + ifeq ($(build-platform),cygwin) + ndk = "$$(cygpath -u "$(ANDROID_NDK)")" + else + ndk = $(ANDROID_NDK) + endif + + ifeq ($(android-version),) + android-version = 5 + endif + + ifeq ($(android-toolchain),) + android-toolchain = 4.7 + endif + + ifeq ($(arch),arm) + android-toolchain-name = arm-linux-androideabi + android-toolchain-prefix = arm-linux-androideabi- + endif + ifeq ($(arch),i386) + android-toolchain-name = x86 + android-toolchain-prefix = i686-linux-android- + endif + + ifeq ($(android-arm-arch),) + android-arm-arch = armv5 + endif + + options := $(options)-api$(android-version)-$(android-toolchain)-$(android-arm-arch) + + build-cflags = $(common-cflags) -I$(src) + build-lflags = -lz -lpthread + ifeq ($(subst cygwin,windows,$(subst mingw32,windows,$(build-platform))),windows) + toolchain-host-platform = $(subst cygwin,windows,$(subst mingw32,windows,$(build-platform))) + build-system = windows + build-cxx = i686-w64-mingw32-g++ + build-cc = i686-w64-mingw32-gcc + sysroot = "$$(cygpath -w "$(ndk)/platforms/android-$(android-version)/arch-arm")" + build-cflags += "-I$(JAVA_HOME)/include/win32" + else + toolchain-host-platform = $(subst cygwin,windows,$(subst mingw32,windows,$(build-platform)))-* + sysroot = $(ndk)/platforms/android-$(android-version)/arch-arm + build-cflags += "-I$(JAVA_HOME)/include/linux" + build-lflags += -ldl + endif + toolchain = $(ndk)/toolchains/$(android-toolchain-name)-$(android-toolchain)/prebuilt/$(toolchain-host-platform) + cflags = "-I$(sysroot)/usr/include" "-I$(JAVA_HOME)/include/linux" $(common-cflags) "-I$(src)" -std=c++11 $(no-psabi) + lflags = "-L$(sysroot)/usr/lib" $(common-lflags) -llog + target-format = elf + use-lto = false + + ifeq ($(arch),arm) + cflags += -marm -march=$(android-arm-arch) -ftree-vectorize -ffast-math -mfloat-abi=softfp + endif + ifeq ($(arch),i386) + endif + + cxx = $(toolchain)/bin/$(android-toolchain-prefix)g++ --sysroot="$(sysroot)" + cc = $(toolchain)/bin/$(android-toolchain-prefix)gcc --sysroot="$(sysroot)" + as = $(cxx) + ar = $(toolchain)/bin/$(android-toolchain-prefix)ar + ranlib = $(toolchain)/bin/$(android-toolchain-prefix)ranlib + strip = $(toolchain)/bin/$(android-toolchain-prefix)strip +endif + +ifeq ($(kernel),darwin) + target-format = macho + ifeq (${OSX_SDK_SYSROOT},) + OSX_SDK_SYSROOT = 10.6u + endif + ifeq (${OSX_SDK_VERSION},) + OSX_SDK_VERSION = 10.6 + endif + ifneq ($(build-kernel),darwin) + cxx = i686-apple-darwin8-g++ $(mflag) + cc = i686-apple-darwin8-gcc $(mflag) + ar = i686-apple-darwin8-ar + ranlib = i686-apple-darwin8-ranlib + strip = i686-apple-darwin8-strip + sysroot = /opt/mac/SDKs/MacOSX${OSX_SDK_SYSROOT}.sdk + cflags = -I$(sysroot)/System/Library/Frameworks/JavaVM.framework/Versions/1.5.0/Headers/ \ + $(common-cflags) -fPIC -fvisibility=hidden -I$(src) + endif + + ifneq ($(platform),ios) + platform-dir = $(developer-dir)/Platforms/MacOSX.platform + sdk-dir = $(platform-dir)/Developer/SDKs + + mac-version := $(shell \ + if test -d $(sdk-dir)/MacOSX10.11.sdk; then echo 10.11; \ + elif test -d $(sdk-dir)/MacOSX10.10.sdk; then echo 10.10; \ + elif test -d $(sdk-dir)/MacOSX10.9.sdk; then echo 10.9; \ + elif test -d $(sdk-dir)/MacOSX10.8.sdk; then echo 10.8; \ + elif test -d $(sdk-dir)/MacOSX10.7.sdk; then echo 10.7; \ + elif test -d $(sdk-dir)/MacOSX10.6.sdk; then echo 10.6; \ + else echo; fi) + + sysroot = $(sdk-dir)/MacOSX$(mac-version).sdk + endif + + soname-flag = + version-script-flag = + lflags = $(common-lflags) -ldl -framework CoreFoundation -framework Foundation + + ifeq (,$(shell ld -v 2>&1 | grep cctools)) + lflags += -Wl,-compatibility_version,1.0.0 + endif + + ifneq ($(platform),ios) + lflags += -framework CoreServices -framework SystemConfiguration \ + -framework Security + endif + ifeq ($(bootimage),true) + bootimage-lflags = -Wl,-segprot,__RWX,rwx,rwx + endif + rdynamic = + strip-all = -S -x + so-suffix = .dylib + shared = -dynamiclib + rpath = + + ifeq ($(platform),ios) + ifeq ($(sim),true) + target = iPhoneSimulator + sdk = iphonesimulator$(ios-version) + ifeq ($(arch),i386) + arch-flag = -arch i386 + else + arch-flag = -arch x86_64 + arch = x86_64 + endif + release = Release-iphonesimulator + else + target = iPhoneOS + sdk = iphoneos$(ios-version) + ifeq ($(arch),arm) + arch-flag = -arch armv7 + else + arch-flag = -arch arm64 + arch = arm64 + endif + release = Release-iphoneos + endif + + platform-dir = $(developer-dir)/Platforms/$(target).platform + sdk-dir = $(platform-dir)/Developer/SDKs + + ios-version := $(shell for x in 10.0 9.3 9.2 9.1 9.0 8.3 8.2 8.1 8.0; \ + do if test -d $(sdk-dir)/$(target)$$x.sdk \ + -o -L $(sdk-dir)/$(target)$$x.sdk; \ + then echo $$x; break; fi; done) + + ifeq ($(ios-version),) + x := $(error "couldn't find SDK in $(sdk-dir)") + endif + + sysroot = $(sdk-dir)/$(target)$(ios-version).sdk + +# apparently, the header files we need are part of the simulator SDK +# but not the device SDK, so we copy them from the former even if +# we're targeting the latter + + header-sysroot := $(subst iPhoneOS,iPhoneSimulator,$(sysroot)) + + ios-bin = $(platform-dir)/Developer/usr/bin + + found-gcc = $(shell if test -f $(ios-bin)/gcc; then echo true; else echo false; fi) + + ifeq ($(found-gcc),false) + use-clang = true + endif + + ifeq ($(use-clang),true) + cxx = clang -std=c++11 + cc = clang + else + cxx = $(ios-bin)/g++ + cc = $(ios-bin)/gcc + endif + + flags = -isysroot $(sdk-dir)/$(target)$(ios-version).sdk \ + $(arch-flag) + + classpath-extra-cflags += $(flags) + cflags += $(flags) + asmflags += $(flags) + lflags += $(flags) + + ios-version-min=$(ios-version) + ifdef ios_deployment_target + ios-version-min=ios_deployment_target + endif + + ifeq ($(sim),true) + ifeq ($(arch),x86_64) + classpath-extra-cflags += \ + -arch x86_64 -miphoneos-version-min=$(ios-version-min) + cflags += -arch x86_64 -miphoneos-version-min=$(ios-version-min) + asmflags += -arch x86_64 -miphoneos-version-min=$(ios-version-min) + lflags += -arch x86_64 -miphoneos-version-min=$(ios-version-min) + else + classpath-extra-cflags += \ + -arch i386 -miphoneos-version-min=$(ios-version-min) + cflags += -arch i386 -miphoneos-version-min=$(ios-version-min) + asmflags += -arch i386 -miphoneos-version-min=$(ios-version-min) + lflags += -arch i386 -miphoneos-version-min=$(ios-version-min) + endif + else + ifeq ($(arch),arm64) + classpath-extra-cflags += \ + -arch arm64 -miphoneos-version-min=$(ios-version-min) + cflags += -arch arm64 -miphoneos-version-min=$(ios-version-min) + asmflags += -arch arm64 -miphoneos-version-min=$(ios-version-min) + lflags += -arch arm64 -miphoneos-version-min=$(ios-version-min) + else + classpath-extra-cflags += \ + -arch armv7 -miphoneos-version-min=$(ios-version-min) + cflags += -arch armv7 -miphoneos-version-min=$(ios-version-min) + asmflags += -arch armv7 -miphoneos-version-min=$(ios-version-min) + lflags += -arch armv7 -miphoneos-version-min=$(ios-version-min) + endif + endif + else # not ios + ifeq ($(arch),i386) + classpath-extra-cflags += \ + -arch i386 -mmacosx-version-min=${OSX_SDK_VERSION} + cflags += -arch i386 -mmacosx-version-min=${OSX_SDK_VERSION} + asmflags += -arch i386 -mmacosx-version-min=${OSX_SDK_VERSION} + lflags += -arch i386 -mmacosx-version-min=${OSX_SDK_VERSION} + endif + + ifeq ($(arch),x86_64) + classpath-extra-cflags += -arch x86_64 + cflags += -arch x86_64 + asmflags += -arch x86_64 + lflags += -arch x86_64 + endif + endif + cflags += -I$(JAVA_HOME)/include/darwin +endif + +openjdk-extra-cflags += $(classpath-extra-cflags) + +find-tool = $(shell if ( command -v "$(1)$(2)" >/dev/null ); then (echo "$(1)$(2)") else (echo "$(2)"); fi) + +ifeq ($(platform),windows) + target-format = pe + + inc = "$(win32)/include" + lib = "$(win32)/lib" + + embed-prefix = c:/avian-embedded + system = windows + + so-prefix = + so-suffix = .dll + exe-suffix = .exe + rpath = + + lflags = -L$(lib) $(common-lflags) -lws2_32 -lversion -luuid -liphlpapi \ + -lmswsock -mconsole + + cflags = -I$(inc) $(common-cflags) -DWINVER=0x0500 -U__STRICT_ANSI__ + + ifeq (,$(filter mingw32 cygwin,$(build-platform))) + openjdk-extra-cflags += -I$(src)/openjdk/caseSensitive + prefix := $(shell i686-w64-mingw32-gcc --version >/dev/null 2>&1 \ + && echo i686-w64-mingw32- || echo x86_64-w64-mingw32-) + cxx = $(prefix)g++ -m32 + cc = $(prefix)gcc -m32 + dlltool = $(prefix)dlltool -mi386 --as-flags=--32 + ar = $(prefix)ar + ranlib = $(prefix)ranlib + strip = $(prefix)strip --strip-all + else + build-system = windows + static-on-windows = -static + common-cflags += "-I$(JAVA_HOME)/include/win32" + build-cflags = $(common-cflags) -I$(src) -I$(inc) -mthreads \ + -D_WIN32_WINNT=0x0500 + openjdk-extra-cflags = + build-lflags = -L$(lib) $(common-lflags) + ifeq ($(build-platform),cygwin) + build-cxx = i686-w64-mingw32-g++ + build-cc = i686-w64-mingw32-gcc + dlltool = i686-w64-mingw32-dlltool + ar = i686-w64-mingw32-ar + ranlib = i686-w64-mingw32-ranlib + strip = i686-w64-mingw32-strip + endif + endif + + ifeq ($(arch),x86_64) + ifeq ($(build-platform),cygwin) + build-cxx = x86_64-w64-mingw32-g++ + build-cc = x86_64-w64-mingw32-gcc + endif + cxx = x86_64-w64-mingw32-g++ $(mflag) + cc = x86_64-w64-mingw32-gcc $(mflag) + dlltool = $(call find-tool,x86_64-w64-mingw32-,dlltool) + ar = $(call find-tool,x86_64-w64-mingw32-,ar) + ranlib = $(call find-tool,x86_64-w64-mingw32-,ranlib) + strip = $(call find-tool,x86_64-w64-mingw32-,strip) + inc = "$(win64)/include" + lib = "$(win64)/lib" + else + shared += -Wl,--add-stdcall-alias + endif + + embed = $(build-embed)/embed$(exe-suffix) + embed-loader = $(build-embed-loader)/embed-loader$(exe-suffix) + embed-loader-o = $(build-embed)/embed-loader.o +endif + +ifeq ($(platform),wp8) + ifeq ($(shell uname -s | grep -i -c WOW64),1) + programFiles = Program Files (x86) + else + programFiles = Program Files + endif + ifeq ($(MSVS_ROOT),) + # Environment variable MSVS_ROOT not found. It should be something like + # "C:\$(programFiles)\Microsoft Visual Studio 11.0" + MSVS_ROOT = C:\$(programFiles)\Microsoft Visual Studio 11.0 + endif + ifeq ($(MSVC_ROOT),) + # Environment variable MSVC_ROOT not found. It should be something like + # "C:\$(programFiles)\Microsoft Visual Studio 11.0\VC" + MSVC_ROOT = $(MSVS_ROOT)\VC + endif + ifeq ($(WP80_SDK),) + # Environment variable WP8_SDK not found. It should be something like + # "C:\Program Files[ (x86)]\Microsoft Visual Studio 11.0\VC\WPSDK\WP80" + # TODO: Lookup in SOFTWARE\Microsoft\Microsoft SDKs\WindowsPhone\v8.0 + WP80_SDK = $(MSVS_ROOT)\VC\WPSDK\WP80 + endif + ifeq ($(WP80_KIT),) + # Environment variable WP8_KIT not found. It should be something like + # "c:\Program Files[ (x86)]\Windows Phone Kits\8.0" + # TODO: Lookup in SOFTWARE\Microsoft\Microsoft SDKs\WindowsPhone\v8.0 + WP80_KIT = C:\$(programFiles)\Windows Phone Kits\8.0 + endif + ifeq ($(WIN8_KIT),) + # Environment variable WIN8_KIT not found. It should be something like + # "c:\Program Files[ (x86)]\Windows Kits\8.0" + WIN8_KIT = C:\$(programFiles)\Windows Kits\8.0 + endif + ifeq ($(build-platform),cygwin) + windows-path = cygpath -w + else + windows-path = $(native-path) + endif + windows-java-home := $(shell $(windows-path) "$(JAVA_HOME)") + target-format = pe + ms_cl_compiler = wp8 + use-lto = false + supports_avian_executable = false + aot-only = true + ifneq ($(bootimage),true) + x := $(error Windows Phone 8 target requires bootimage=true) + endif + system = windows + build-system = windows + static-prefix = + static-suffix = .lib + so-prefix = + so-suffix = .dll + exe-suffix = .exe + manifest-flags = -MANIFEST:NO + + ifeq ($(arch),arm) + wp8_arch = \x86_arm + vc_arch = \arm + w8kit_arch = arm + deps_arch = ARM + as = "$$(cygpath -u "$(WP80_SDK)\bin\x86_arm\armasm.exe")" + cxx = "$$(cygpath -u "$(WP80_SDK)\bin\x86_arm\cl.exe")" + ld = "$$(cygpath -u "$(WP80_SDK)\bin\x86_arm\link.exe")" + asmflags = -machine ARM -32 + asm-output = -o $(1) + asm-input = $(1) + machine_type = ARM + bootimage-symbols = binary_bootimage_bin_start:binary_bootimage_bin_end + codeimage-symbols = binary_codeimage_bin_start:binary_codeimage_bin_end + endif + ifeq ($(arch),i386) + wp8_arch = + vc_arch = + w8kit_arch = x86 + deps_arch = x86 + asmflags = $(target-cflags) -safeseh -nologo -Gd + as = "$$(cygpath -u "$(WP80_SDK)\bin\ml.exe")" + cxx = "$$(cygpath -u "$(WP80_SDK)\bin\cl.exe")" + ld = "$$(cygpath -u "$(WP80_SDK)\bin\link.exe")" + ifeq ($(mode),debug) + asmflags += -Zd + endif + ifeq ($(mode),debug-fast) + asmflags += -Zd + endif + asm-output = $(output) + machine_type = X86 + endif + + PATH := $(shell cygpath -u "$(MSVS_ROOT)\Common7\IDE"):$(shell cygpath -u "$(WP80_SDK)\bin$(wp8_arch)"):$(shell cygpath -u "$(WP80_SDK)\bin"):${PATH} + + build-cflags = $(common-cflags) -I$(src) -I$(inc) -mthreads + build-lflags = -lz -lpthread + + cflags = -nologo \ + -AI"$(WP80_KIT)\Windows Metadata" \ + -I"$(WP80_SDK)\include" -I"$(WP80_KIT)\Include" -I"$(WP80_KIT)\Include\minwin" -I"$(WP80_KIT)\Include\mincore" \ + -DWINAPI_FAMILY=WINAPI_FAMILY_PHONE_APP -D_USRDLL -D_WINDLL \ + -DAVIAN_VERSION=\"$(version)\" -D_JNI_IMPLEMENTATION_ \ + -DUSE_ATOMIC_OPERATIONS -DAVIAN_JAVA_HOME=\"$(javahome)\" \ + -DAVIAN_EMBED_PREFIX=\"$(embed-prefix)\" \ + -I"$(shell $(windows-path) "$(wp8)/zlib/upstream")" -I"$(shell $(windows-path) "$(wp8)/interop/avian-interop-client")" \ + -I"$(shell $(windows-path) "$(wp8)/include")" -I$(src) -I$(classpath-src) \ + -I"$(build)" \ + -I"$(windows-java-home)/include" -I"$(windows-java-home)/include/win32" \ + -DTARGET_BYTES_PER_WORD=$(pointer-size) \ + -Gd -EHsc + + common-lflags = + + ifeq ($(mode),debug) + build-type = Debug + endif + ifeq ($(mode),debug-fast) + build-type = Debug + endif + ifeq ($(mode),stress-major) + build-type = Release + endif + ifeq ($(mode),fast) + build-type = Release + endif + ifeq ($(mode),fast) + build-type = Release + endif + ifeq ($(mode),small) + build-type = Release + endif + + arflags = -MACHINE:$(machine_type) + lflags = $(common-lflags) -nologo \ + -MACHINE:$(machine_type) \ + -LIBPATH:"$(WP80_KIT)\lib\$(w8kit_arch)" -LIBPATH:"$(WP80_SDK)\lib$(vc_arch)" -LIBPATH:"$(WIN8_KIT)\Lib\win8\um\$(w8kit_arch)" \ + ws2_32.lib \ + "$(shell $(windows-path) "$(wp8)\lib\$(deps_arch)\$(build-type)\zlib.lib")" "$(shell $(windows-path) "$(wp8)\lib\$(deps_arch)\$(build-type)\ThreadEmulation.lib")" \ + "$(shell $(windows-path) "$(wp8)\lib\$(deps_arch)\$(build-type)\AvianInteropClient.lib")" + lflags += -NXCOMPAT -DYNAMICBASE -SUBSYSTEM:CONSOLE -TLBID:1 + lflags += -NODEFAULTLIB:"ole32.lib" -NODEFAULTLIB:"kernel32.lib" + lflags += PhoneAppModelHost.lib WindowsPhoneCore.lib -WINMD -WINMDFILE:$(subst $(so-suffix),.winmd,$(@)) + + cc = $(cxx) + asm-format = masm + shared = -dll + ar = "$$(cygpath -u "$(WP80_SDK)\bin\lib.exe")" + arflags += -nologo + ifeq ($(build-platform),cygwin) + build-cxx = i686-w64-mingw32-g++ + build-cc = i686-w64-mingw32-gcc + dlltool = i686-w64-mingw32-dlltool + ranlib = + strip = + endif + output = -Fo$(1) + + #TODO: -MT or -ZW? + cflags_debug = -Od -Zi -MDd + cflags_debug_fast = -Od -Zi -MDd + cflags_stress = -O0 -g3 -MD + cflags_stress_major = -O0 -g3 -MD + cflags_fast = -O2 -Zi -MD + cflags_small = -O1s -Zi -MD + # -GL [whole program optimization] in 'fast' and 'small' breaks compilation for some reason + + ifeq ($(mode),debug) + cflags += + lflags += + endif + ifeq ($(mode),debug-fast) + cflags += -DNDEBUG + lflags += + endif + ifeq ($(mode),stress-major) + cflags += + lflags += + endif + ifeq ($(mode),fast) + cflags += + lflags += + endif + # -LTCG is needed only if -GL is used + ifeq ($(mode),fast) + cflags += -DNDEBUG + lflags += -LTCG + arflags += + endif + ifeq ($(mode),small) + cflags += -DNDEBUG + lflags += -LTCG + arflags += + endif + + strip = : +endif + +ifdef msvc + target-format = pe + windows-path = $(native-path) + windows-java-home := $(shell $(windows-path) "$(JAVA_HOME)") + zlib := $(shell $(windows-path) "$(win32)/msvc") + ms_cl_compiler = regular + as = $(build-cc) + cxx = "$(msvc)/BIN/cl.exe" + cc = $(cxx) + ld = "$(msvc)/BIN/link.exe" + mt = "mt.exe" + ar = "$(msvc)/BIN/lib.exe" + manifest-flags = -MANIFEST -MANIFESTFILE:$(@).manifest + cflags = -nologo -DAVIAN_VERSION=\"$(version)\" -D_JNI_IMPLEMENTATION_ \ + -DUSE_ATOMIC_OPERATIONS -DAVIAN_JAVA_HOME=\"$(javahome)\" \ + -DAVIAN_EMBED_PREFIX=\"$(embed-prefix)\" \ + -Fd$(build)/$(name).pdb -I"$(zlib)/include" -I$(src) -I$(classpath-src) \ + -I"$(build)" -Iinclude \ + -I"$(windows-java-home)/include" -I"$(windows-java-home)/include/win32" \ + -DTARGET_BYTES_PER_WORD=$(pointer-size) + + ifneq ($(lzma),) + cflags += -I$(shell $(windows-path) "$(lzma)") + endif + + shared = -dll + lflags = -nologo -LIBPATH:"$(zlib)/lib" -DEFAULTLIB:ws2_32 \ + -DEFAULTLIB:zlib -DEFAULTLIB:user32 -MANIFEST -debug + output = -Fo$(1) + + cflags_debug = -Od -Zi -MDd + cflags_debug_fast = -Od -Zi -DNDEBUG + cflags_fast = -O2 -GL -Zi -DNDEBUG + cflags_small = -O1s -Zi -GL -DNDEBUG + ifeq ($(mode),fast) + lflags += -LTCG + endif + ifeq ($(mode),small) + lflags += -LTCG + endif + + use-lto = false + strip = : +endif + +ifeq ($(mode),debug) + optimization-cflags = $(cflags_debug) + converter-cflags += $(cflags_debug) + strip = : +endif +ifeq ($(mode),debug-fast) + optimization-cflags = $(cflags_debug_fast) -DNDEBUG + strip = : +endif +ifeq ($(mode),stress) + optimization-cflags = $(cflags_stress) -DVM_STRESS + strip = : +endif +ifeq ($(mode),stress-major) + optimization-cflags = $(cflags_stress_major) -DVM_STRESS -DVM_STRESS_MAJOR + strip = : +endif +ifeq ($(mode),fast) + optimization-cflags = $(cflags_fast) -DNDEBUG +endif +ifeq ($(mode),small) + optimization-cflags = $(cflags_small) -DNDEBUG +endif + +ifeq ($(use-lto),true) + ifeq ($(use-clang),true) + optimization-cflags += -flto + lflags += $(optimization-cflags) + else +# only try to use LTO when GCC 4.6.0 or greater is available + gcc-major := $(shell $(cc) -dumpversion | cut -f1 -d.) + gcc-minor := $(shell $(cc) -dumpversion | cut -f2 -d.) + ifeq ($(shell expr 4 \< $(gcc-major) \ + \| \( 4 \<= $(gcc-major) \& 6 \<= $(gcc-minor) \)),1) + optimization-cflags += -flto + no-lto = -fno-lto + lflags += $(optimization-cflags) + endif + endif +endif + +cflags += $(optimization-cflags) + +ifndef ms_cl_compiler +ifneq ($(kernel),darwin) +ifeq ($(arch),i386) +# this is necessary to support __sync_bool_compare_and_swap: + cflags += -march=i586 + lflags += -march=i586 +endif +endif +endif + +c-objects = $(foreach x,$(1),$(patsubst $(2)/%.c,$(3)/%.o,$(x))) +cpp-objects = $(foreach x,$(1),$(patsubst $(2)/%.cpp,$(3)/%.o,$(x))) +cc-objects = $(foreach x,$(1),$(patsubst $(2)/%.cc,$(3)/%.o,$(x))) +asm-objects = $(foreach x,$(1),$(patsubst $(2)/%.$(asm-format),$(3)/%-asm.o,$(x))) +java-classes = $(foreach x,$(1),$(patsubst $(2)/%.java,$(3)/%.class,$(x))) +noop-files = $(foreach x,$(1),$(patsubst $(2)/%,$(3)/%,$(x))) + +generated-code = \ + $(build)/type-enums.cpp \ + $(build)/type-declarations.cpp \ + $(build)/type-constructors.cpp \ + $(build)/type-initializations.cpp \ + $(build)/type-java-initializations.cpp \ + $(build)/type-name-initializations.cpp \ + $(build)/type-maps.cpp + +vm-depends := $(generated-code) \ + $(shell find src include -name '*.h' -or -name '*.inc.cpp') + +vm-sources = \ + $(src)/system/$(system).cpp \ + $(wildcard $(src)/system/$(system)/*.cpp) \ + $(src)/finder.cpp \ + $(src)/machine.cpp \ + $(src)/util.cpp \ + $(src)/heap/heap.cpp \ + $(src)/$(process).cpp \ + $(src)/classpath-$(classpath).cpp \ + $(src)/builtin.cpp \ + $(src)/jnienv.cpp \ + $(src)/process.cpp \ + $(src)/heapdump.cpp + +vm-asm-sources = $(src)/$(arch).$(asm-format) + +target-asm = $(asm) + +build-embed = $(build)/embed +build-embed-loader = $(build)/embed-loader + +embed-loader-sources = $(src)/embedded-loader.cpp +embed-loader-objects = $(call cpp-objects,$(embed-loader-sources),$(src),$(build-embed-loader)) + +embed-sources = $(src)/embed.cpp +embed-objects = $(call cpp-objects,$(embed-sources),$(src),$(build-embed)) + +compiler-sources = \ + $(src)/codegen/compiler.cpp \ + $(wildcard $(src)/codegen/compiler/*.cpp) \ + $(src)/debug-util.cpp \ + $(src)/codegen/runtime.cpp \ + $(src)/codegen/targets.cpp \ + $(src)/util/fixed-allocator.cpp + +x86-assembler-sources = $(wildcard $(src)/codegen/target/x86/*.cpp) + +arm-assembler-sources = $(wildcard $(src)/codegen/target/arm/*.cpp) + +all-assembler-sources = \ + $(x86-assembler-sources) \ + $(arm-assembler-sources) + +native-assembler-sources = $($(target-asm)-assembler-sources) + +all-codegen-target-sources = \ + $(compiler-sources) \ + $(native-assembler-sources) + +ifeq ($(process),compile) + vm-sources += $(compiler-sources) + + ifeq ($(codegen-targets),native) + vm-sources += $(native-assembler-sources) + endif + ifeq ($(codegen-targets),all) + ifneq (,$(filter arm arm64,$(arch))) + # The x86 jit has a dependency on the x86 assembly code, + # and thus can't be successfully built on non-x86 platforms. + vm-sources += $(native-assembler-sources) + else + vm-sources += $(all-assembler-sources) + endif + endif + + vm-asm-sources += $(src)/compile-$(arch).$(asm-format) +endif +ifeq ($(aot-only),true) + cflags += -DAVIAN_AOT_ONLY +endif + +vm-cpp-objects = $(call cpp-objects,$(vm-sources),$(src),$(build)) +all-codegen-target-objects = $(call cpp-objects,$(all-codegen-target-sources),$(src),$(build)) +vm-asm-objects = $(call asm-objects,$(vm-asm-sources),$(src),$(build)) +vm-objects = $(vm-cpp-objects) $(vm-asm-objects) + +heapwalk-sources = $(src)/heapwalk.cpp +heapwalk-objects = \ + $(call cpp-objects,$(heapwalk-sources),$(src),$(build)) + +unittest-objects = $(call cpp-objects,$(unittest-sources),$(unittest),$(build)/unittest) + +vm-heapwalk-objects = $(heapwalk-objects) + +ifeq ($(tails),true) + cflags += -DAVIAN_TAILS +endif + +ifeq ($(continuations),true) + cflags += -DAVIAN_CONTINUATIONS + asmflags += -DAVIAN_CONTINUATIONS +endif + +bootimage-generator-sources = $(src)/tools/bootimage-generator/main.cpp $(src)/util/arg-parser.cpp $(stub-sources) + +ifneq ($(lzma),) + bootimage-generator-sources += $(src)/lzma-encode.cpp +endif + +bootimage-generator-objects = \ + $(call cpp-objects,$(bootimage-generator-sources),$(src),$(build)) +bootimage-generator = $(build)/bootimage-generator + +ifneq ($(mode),fast) + host-vm-options := -$(mode) +endif + +host-vm = build/$(build-platform)-$(build-arch)-interpret$(host-vm-options)/$(so-prefix)jvm$(so-suffix) + +bootimage-object = $(build)/bootimage-bin.o +codeimage-object = $(build)/codeimage-bin.o + +ifeq ($(bootimage),true) + vm-classpath-objects = $(bootimage-object) $(codeimage-object) + cflags += -DBOOT_IMAGE -DAVIAN_CLASSPATH=\"\" +else + vm-classpath-objects = $(classpath-object) + cflags += -DBOOT_CLASSPATH=\"[classpathJar]\" \ + -DAVIAN_CLASSPATH=\"[classpathJar]\" +endif + +cflags += $(extra-cflags) +lflags += $(extra-lflags) + +openjdk-cflags += $(extra-cflags) + +driver-source = $(src)/main.cpp +driver-object = $(build)/main.o +driver-dynamic-objects = \ + $(build)/main-dynamic.o + +boot-source = $(src)/boot.cpp +boot-object = $(build)/boot.o + +generator-depends := $(wildcard $(src)/*.h) +generator-sources = \ + $(src)/tools/type-generator/main.cpp \ + $(src)/system/$(build-system).cpp \ + $(wildcard $(src)/system/$(build-system)/*.cpp) \ + $(src)/finder.cpp \ + $(src)/util/arg-parser.cpp + +ifneq ($(lzma),) + common-cflags += -I$(lzma) -DAVIAN_USE_LZMA + + vm-sources += \ + $(src)/lzma-decode.cpp + + generator-sources += \ + $(src)/lzma-decode.cpp + + lzma-decode-sources = \ + $(lzma)/C/LzmaDec.c + + lzma-decode-objects = \ + $(call c-objects,$(lzma-decode-sources),$(lzma)/C,$(build)) + + lzma-encode-sources = \ + $(lzma)/C/LzmaEnc.c \ + $(lzma)/C/LzFind.c + + lzma-encode-objects = \ + $(call c-objects,$(lzma-encode-sources),$(lzma)/C,$(build)) + + lzma-encoder = $(build)/lzma/lzma + + lzma-build-cflags = -D_7ZIP_ST -D__STDC_CONSTANT_MACROS \ + -fno-exceptions -fPIC -I$(lzma)/C + + lzma-cflags = $(lzma-build-cflags) $(classpath-extra-cflags) + + lzma-encoder-sources = \ + $(src)/lzma/main.cpp + + lzma-encoder-objects = \ + $(call cpp-objects,$(lzma-encoder-sources),$(src),$(build)) + + lzma-encoder-lzma-sources = $(lzma-encode-sources) $(lzma-decode-sources) + + lzma-encoder-lzma-objects = \ + $(call generator-c-objects,$(lzma-encoder-lzma-sources),$(lzma)/C,$(build)) + + lzma-loader = $(build)/lzma/load.o + + lzma-library = $(build)/libavian-lzma.a +endif + +generator-cpp-objects = \ + $(foreach x,$(1),$(patsubst $(2)/%.cpp,$(3)/%-build.o,$(x))) +generator-c-objects = \ + $(foreach x,$(1),$(patsubst $(2)/%.c,$(3)/%-build.o,$(x))) +generator-objects = \ + $(call generator-cpp-objects,$(generator-sources),$(src),$(build)) +generator-lzma-objects = \ + $(call generator-c-objects,$(lzma-decode-sources),$(lzma)/C,$(build)) +generator = $(build)/generator + +all-depends = $(shell find include -name '*.h') + +object-writer-depends = $(shell find $(src)/tools/object-writer -name '*.h') +object-writer-sources = $(shell find $(src)/tools/object-writer -name '*.cpp') +object-writer-objects = $(call cpp-objects,$(object-writer-sources),$(src),$(build)) + +binary-to-object-depends = $(shell find $(src)/tools/binary-to-object/ -name '*.h') +binary-to-object-sources = $(shell find $(src)/tools/binary-to-object/ -name '*.cpp') +binary-to-object-objects = $(call cpp-objects,$(binary-to-object-sources),$(src),$(build)) + +converter-sources = $(object-writer-sources) + +converter-tool-depends = $(binary-to-object-depends) $(all-depends) +converter-tool-sources = $(binary-to-object-sources) + +converter-objects = $(call cpp-objects,$(converter-sources),$(src),$(build)) +converter-tool-objects = $(call cpp-objects,$(converter-tool-sources),$(src),$(build)) +converter = $(build)/binaryToObject/binaryToObject + +static-library = $(build)/$(static-prefix)$(name)$(static-suffix) +executable = $(build)/$(name)${exe-suffix} +dynamic-library = $(build)/$(so-prefix)jvm$(so-suffix) +executable-dynamic = $(build)/$(name)-dynamic$(exe-suffix) + +unittest-executable = $(build)/$(name)-unittest${exe-suffix} + +ifneq ($(classpath),avian) +# Assembler, ConstantPool, and Stream are not technically needed for a +# working build, but we include them since our Subroutine test uses +# them to synthesize a class: + classpath-sources := \ + $(classpath-src)/avian/Addendum.java \ + $(classpath-src)/avian/AnnotationInvocationHandler.java \ + $(classpath-src)/avian/Assembler.java \ + $(classpath-src)/avian/Callback.java \ + $(classpath-src)/avian/Cell.java \ + $(classpath-src)/avian/ClassAddendum.java \ + $(classpath-src)/avian/Classes.java \ + $(classpath-src)/avian/Code.java \ + $(classpath-src)/avian/ConstantPool.java \ + $(classpath-src)/avian/Continuations.java \ + $(classpath-src)/avian/FieldAddendum.java \ + $(classpath-src)/avian/Function.java \ + $(classpath-src)/avian/IncompatibleContinuationException.java \ + $(classpath-src)/avian/InnerClassReference.java \ + $(classpath-src)/avian/Machine.java \ + $(classpath-src)/avian/MethodAddendum.java \ + $(classpath-src)/avian/Pair.java \ + $(classpath-src)/avian/Singleton.java \ + $(classpath-src)/avian/Stream.java \ + $(classpath-src)/avian/SystemClassLoader.java \ + $(classpath-src)/avian/Traces.java \ + $(classpath-src)/avian/VMClass.java \ + $(classpath-src)/avian/VMField.java \ + $(classpath-src)/avian/VMMethod.java \ + $(classpath-src)/avian/avianvmresource/Handler.java \ + $(classpath-src)/avian/file/Handler.java \ + $(classpath-src)/java/lang/invoke/MethodHandle.java \ + $(classpath-src)/java/lang/invoke/MethodHandles.java \ + $(classpath-src)/java/lang/invoke/MethodType.java \ + $(classpath-src)/java/lang/invoke/LambdaMetafactory.java \ + $(classpath-src)/java/lang/invoke/LambdaConversionException.java \ + $(classpath-src)/java/lang/invoke/CallSite.java + + ifeq ($(openjdk),) + classpath-sources := $(classpath-sources) \ + $(classpath-src)/dalvik/system/BaseDexClassLoader.java \ + $(classpath-src)/libcore/reflect/AnnotationAccess.java \ + $(classpath-src)/sun/reflect/ConstantPool.java \ + $(classpath-src)/java/net/ProtocolFamily.java \ + $(classpath-src)/java/net/StandardProtocolFamily.java \ + $(classpath-src)/sun/misc/Cleaner.java \ + $(classpath-src)/sun/misc/Unsafe.java \ + $(classpath-src)/java/lang/Object.java \ + $(classpath-src)/java/lang/Class.java \ + $(classpath-src)/java/lang/ClassLoader.java \ + $(classpath-src)/java/lang/Package.java \ + $(classpath-src)/java/lang/reflect/Proxy.java \ + $(classpath-src)/java/lang/reflect/Field.java \ + $(classpath-src)/java/lang/reflect/SignatureParser.java \ + $(classpath-src)/java/lang/reflect/Constructor.java \ + $(classpath-src)/java/lang/reflect/AccessibleObject.java \ + $(classpath-src)/java/lang/reflect/Method.java + endif +else + classpath-sources := $(shell find $(classpath-src) -name '*.java') +endif + +classpath-classes = \ + $(call java-classes,$(classpath-sources),$(classpath-src),$(classpath-build)) +classpath-object = $(build)/classpath-jar.o +classpath-dep = $(classpath-build).dep + +vm-classes = \ + avian/*.class \ + avian/resource/*.class + +test-support-sources = $(shell find $(test)/avian/ -name '*.java') +test-sources := $(wildcard $(test)/*.java) + +# HACK ALERT!! +# This test fails regularly on travis, but nowhere else. We have yet to spend the time to investigate that test, so we disable it on PR builds. +# Note: travis set TRAVIS_PULL_REQUEST environment variable to either the PR number or "false", as appropriate +ifeq (false,$(TRAVIS_PULL_REQUEST)) +else +ifeq (,$(TRAVIS_PULL_REQUEST)) +else + test-sources := $(subst $(test)/Trace.java,,$(test-sources)) +endif +endif + +ifeq (7,$(java-version)) + test-sources := $(subst $(test)/InvokeDynamic.java,,$(test-sources)) + test-sources := $(subst $(test)/Interfaces.java,,$(test-sources)) +endif + +test-cpp-sources = $(wildcard $(test)/*.cpp) +test-sources += $(test-support-sources) +test-support-classes = $(call java-classes, $(test-support-sources),$(test),$(test-build)) +test-classes = $(call java-classes,$(test-sources),$(test),$(test-build)) +test-cpp-objects = $(call cpp-objects,$(test-cpp-sources),$(test),$(test-build)) +test-library = $(build)/$(so-prefix)test$(so-suffix) +test-dep = $(test-build).dep + +test-extra-sources = $(wildcard $(test)/extra/*.java) +test-extra-classes = \ + $(call java-classes,$(test-extra-sources),$(test),$(test-build)) +test-extra-dep = $(test-build)-extra.dep + +unittest-sources = \ + $(wildcard $(unittest)/*.cpp) \ + $(wildcard $(unittest)/util/*.cpp) \ + $(wildcard $(unittest)/codegen/*.cpp) + +unittest-depends = \ + $(wildcard $(unittest)/*.h) + +ifeq ($(continuations),true) + continuation-tests = \ + extra.ComposableContinuations \ + extra.Continuations \ + extra.Coroutines \ + extra.DynamicWind +endif + +ifeq ($(tails),true) + tail-tests = \ + extra.Tails +endif + +ifeq ($(target-arch),i386) + cflags += -DAVIAN_TARGET_ARCH=AVIAN_ARCH_X86 +endif + +ifeq ($(target-arch),x86_64) + cflags += -DAVIAN_TARGET_ARCH=AVIAN_ARCH_X86_64 +endif + +ifeq ($(target-arch),arm) + cflags += -DAVIAN_TARGET_ARCH=AVIAN_ARCH_ARM +endif + +ifeq ($(target-arch),arm64) + cflags += -DAVIAN_TARGET_ARCH=AVIAN_ARCH_ARM64 +endif + +ifeq ($(target-format),elf) + cflags += -DAVIAN_TARGET_FORMAT=AVIAN_FORMAT_ELF +endif + +ifeq ($(target-format),pe) + cflags += -DAVIAN_TARGET_FORMAT=AVIAN_FORMAT_PE +endif + +ifeq ($(target-format),macho) + cflags += -DAVIAN_TARGET_FORMAT=AVIAN_FORMAT_MACHO +endif + +class-name = $(patsubst $(1)/%.class,%,$(2)) +class-names = $(foreach x,$(2),$(call class-name,$(1),$(x))) + +test-flags = -Djava.library.path=$(build) \ + -cp '$(build)/test$(target-path-separator)$(build)/extra-dir' + +test-args = $(test-flags) $(input) + +ifneq ($(filter linux windows macosx,$(platform)),) +eclipse-exec-env = eclipse-ee +eclipse-jdk-dir = $(build)/eclipse/jdk +eclipse-ee-file = $(eclipse-jdk-dir)/avian.ee +eclipse-bin-dir = $(eclipse-jdk-dir)/bin +eclipse-lib-dir = $(eclipse-jdk-dir)/jre/lib +eclipse-src-dir = $(eclipse-jdk-dir)/src +define eclipse-ee-descriptor +# An Eclipse execution environment for the Avian JVM\ +\n-Dee.executable=bin/java${exe-suffix}\ +\n-Dee.bootclasspath=jre/lib/rt.jar\ +\n-Dee.language.level=1.7\ +\n-Dee.name=$(name)-$(version)-$(platform)-$(arch)$(options)\ +\n-Dee.src=src\ +\n-Dee.javadoc=file://$${ee.home}/doc\ +\n-Djava.home=$${ee.home}\n +endef +else +eclipse-exec-env = +endif + +.PHONY: build +ifneq ($(supports_avian_executable),false) +build: $(static-library) $(executable) $(dynamic-library) $(lzma-library) \ + $(lzma-encoder) $(executable-dynamic) $(classpath-dep) $(test-dep) \ + $(test-extra-dep) $(embed) $(build)/classpath.jar $(eclipse-exec-env) +else +build: $(static-library) $(dynamic-library) $(lzma-library) \ + $(lzma-encoder) $(classpath-dep) $(test-dep) \ + $(test-extra-dep) $(embed) $(build)/classpath.jar +endif + +$(test-dep): $(classpath-dep) + +$(test-extra-dep): $(classpath-dep) + +.PHONY: run +run: build + $(library-path) $(test-executable) $(test-args) + +.PHONY: debug +debug: build + $(library-path) $(db) $(test-executable) $(test-args) + +.PHONY: vg +vg: build + $(library-path) $(vg) $(test-executable) $(test-args) + +.PHONY: test +test: build-test run-test + +.PHONY: build-test +build-test: build $(build)/run-tests.sh $(build)/test.sh $(unittest-executable) + +.PHONY: run-test +run-test: +ifneq ($(remote-test),true) + /bin/sh $(build)/run-tests.sh +else + @echo "running tests on $(remote-test-user)@$(remote-test-host):$(remote-test-port), in $(remote-test-dir)" + rsync $(build) -rav --exclude '*.o' --rsh="ssh -p$(remote-test-port)" $(remote-test-user)@$(remote-test-host):$(remote-test-dir) + ssh -p$(remote-test-port) $(remote-test-user)@$(remote-test-host) sh "$(remote-test-dir)/$(platform)-$(arch)$(options)/run-tests.sh" +endif + +.PHONY: jdk-test +jdk-test: $(test-dep) $(build)/classpath.jar $(build)/jdk-run-tests.sh $(build)/test.sh + /bin/sh $(build)/jdk-run-tests.sh + +.PHONY: tarball +tarball: + @echo "creating build/avian-$(version).tar.bz2" + @mkdir -p build + (cd .. && tar --exclude=build --exclude=cmake-build --exclude=distrib \ + --exclude=lib --exclude='.*' --exclude='*~' \ + -cjf avian/build/avian-$(version).tar.bz2 avian) + +.PHONY: clean-current +clean-current: + @echo "removing $(build)" + rm -rf $(build) + +.PHONY: clean +clean: + @echo "removing build directories" + rm -rf build cmake-build distrib lib + +.PHONY: eclipse-ee +ifneq ($(strip $(eclipse-exec-env)),) +eclipse-ee: $(eclipse-ee-file) $(eclipse-lib-dir)/rt.jar $(eclipse-bin-dir)/java${exe-suffix} $(eclipse-src-dir) + +$(eclipse-bin-dir): + @mkdir -p $(@) + +$(eclipse-lib-dir): + @mkdir -p $(@) + +$(eclipse-jdk-dir): + @mkdir -p $(@) + +$(eclipse-ee-file): $(eclipse-jdk-dir) + @echo "writing eclipse execution environment descriptor to $(@)" + @printf '${eclipse-ee-descriptor}' > $(@) + +$(eclipse-src-dir): $(eclipse-jdk-dir) + @echo "symlinking classpath for $(@)" + @ln -sf ../../../../classpath $(@) + +$(eclipse-bin-dir)/java$(exe-suffix): $(eclipse-bin-dir) $(executable) + @echo "symlinking $(executable) for $(@)" + @ln -sf ../../../$(name)${exe-suffix} $(@) + +$(eclipse-lib-dir)/rt.jar: $(eclipse-lib-dir) $(build)/classpath.jar + @echo "symlinking $(build)/classpath.jar for $(@)" + @ln -sf ../../../../classpath.jar $(@) +else +eclipse-ee: + $(error "Eclipse execution environment for platform '$(platform)' is not supported") +endif + +ifeq ($(continuations),true) +$(build)/compile-x86-asm.o: $(src)/continuations-x86.$(asm-format) +endif + +$(build)/run-tests.sh: $(test-classes) makefile $(build)/extra-dir/multi-classpath-test.txt $(build)/test/multi-classpath-test.txt + echo 'cd $$(dirname $$0)' > $(@) + echo "sh ./test.sh 2>/dev/null \\" >> $(@) + echo "$(shell echo $(library-path) | sed 's|$(build)|\.|g') ./$(name)-unittest${exe-suffix} ./$(notdir $(test-executable)) $(mode) \"-Djava.library.path=. -cp test$(target-path-separator)extra-dir\" \\" >> $(@) + echo "$(call class-names,$(test-build),$(filter-out $(test-support-classes), $(test-classes))) \\" >> $(@) + echo "$(continuation-tests) $(tail-tests)" >> $(@) + +$(build)/jdk-run-tests.sh: $(test-classes) makefile $(build)/extra-dir/multi-classpath-test.txt $(build)/test/multi-classpath-test.txt + echo 'cd $$(dirname $$0)' > $(@) + echo "sh ./test.sh 2>/dev/null \\" >> $(@) + echo "'' true $(JAVA_HOME)/bin/java $(mode) \"-Xmx128m -Djava.library.path=. -cp test$(path-separator)extra-dir$(path-separator)classpath\" \\" >> $(@) + echo "$(call class-names,$(test-build),$(filter-out $(test-support-classes), $(test-classes))) \\" >> $(@) + echo "$(continuation-tests) $(tail-tests)" >> $(@) + +$(build)/extra-dir/multi-classpath-test.txt: + mkdir -p $(build)/extra-dir + echo "$@" > $@ + +$(build)/test/multi-classpath-test.txt: + echo "$@" > $@ + +$(build)/test.sh: $(test)/test.sh + cp $(<) $(@) + +gen-arg = $(shell echo $(1) | sed -e 's:$(build)/type-\(.*\)\.cpp:\1:') +$(generated-code): %.cpp: $(src)/types.def $(generator) $(classpath-dep) + @echo "generating $(@)" + @mkdir -p $(dir $(@)) + $(generator) -cp $(boot-classpath) -i $(<) -o $(@) -t $(call gen-arg,$(@)) + +$(classpath-dep): $(classpath-sources) $(classpath-jar-dep) + @echo "compiling classpath classes" + @mkdir -p $(classpath-build) + $(javac) -source 1.$(java-version) -target 1.$(java-version) \ + -d $(classpath-build) -bootclasspath $(boot-classpath) \ + $(classpath-sources) + @touch $(@) + +$(build)/android-src/%.cpp: $(luni-native)/%.cpp + cp $(<) $(@) + +$(build)/android-src/%.cpp: $(libnativehelper-native)/%.cpp + cp $(<) $(@) + +$(build)/android-src/%.cpp: $(crypto-native)/%.cpp + cp $(<) $(@) + +$(build)/android-src/%.cpp: $(libziparchive-native)/%.cc + cp $(<) $(@) + +$(build)/android-src/%.cpp: $(libutils-native)/%.cpp + cp $(<) $(@) + +$(build)/%.o: $(build)/android-src/%.cpp $(build)/android.dep + @echo "compiling $(@)" + @mkdir -p $(dir $(@)) + $(cxx) $(android-cflags) $(classpath-extra-cflags) -c \ + $$($(windows-path) $(<)) $(call output,$(@)) + +$(build)/android.dep: $(luni-javas) $(dalvik-javas) $(libart-javas) \ + $(xml-javas) $(okhttp-android-javas) $(okhttp-javas) $(okio-javas) \ + $(bcpkix-javas) $(bcprov-javas) $(luni-nonjavas) $(crypto-javas) $(crypto-platform-javas) + @echo "compiling luni classes" + @mkdir -p $(classpath-build) + @mkdir -p $(build)/android + @mkdir -p $(build)/android-src/external/fdlibm + @mkdir -p $(build)/android-src/libexpat + cp $(android)/external/fdlibm/fdlibm.h $(build)/android-src/external/fdlibm/ + cp $(android)/external/expat/lib/expat*.h $(build)/android-src/libexpat/ + cp -a $(luni-java)/* $(xml-java)/* $(okhttp-android-java)/* $(okhttp-java)/* $(okio-java)/* $(bcpkix-java)/* $(bcprov-java)/* $(build)/android-src/ + rm $(call noop-files,$(luni-blacklist),$(luni-java),$(build)/android-src) + (cd $(dalvik-java) && \ + $(jar) c $(call noop-files,$(dalvik-javas),$(dalvik-java),.)) \ + | (cd $(build)/android-src && $(jar) x) + (cd $(libart-java) && \ + $(jar) c $(call noop-files,$(libart-javas),$(libart-java),.)) \ + | (cd $(build)/android-src && $(jar) x) + (cd $(crypto-java) && \ + $(jar) c $(call noop-files,$(crypto-javas),$(crypto-java),.)) \ + | (cd $(build)/android-src && $(jar) x) + (cd $(crypto-platform-java) && \ + $(jar) c $(call noop-files,$(crypto-platform-javas),$(crypto-platform-java),.)) \ + | (cd $(build)/android-src && $(jar) x) + (cd $(classpath-src) && \ + $(jar) c $(call noop-files,$(classpath-sources),$(classpath-src),.)) \ + | (cd $(build)/android-src && $(jar) x) +# (cd android && $(jar) c *) | (cd $(build)/android-src && $(jar) x) + find $(build)/android-src -name '*.java' > $(build)/android.txt + $(javac) -Xmaxerrs 1000 -d $(build)/android @$(build)/android.txt + rm $(build)/android/sun/misc/Unsafe* \ + $(build)/android/java/lang/reflect/Proxy* + for x in $(luni-copied-nonjavas); \ + do cp $(luni-java)$${x} $(build)/android$${x} ; \ + done + # fix security.properties - get rid of "com.android" in front of classes starting with "org" + sed -i -e 's/\(.*=\)com\.android\.\(org\..*\)/\1\2/g' \ + $(build)/android/java/security/security.properties + chmod +w $(build)/android/java/security/security.properties + cp -r $(build)/android/* $(classpath-build) + @touch $(@) + +$(test-build)/%.class: $(test)/%.java + @echo $(<) + +$(test-dep): $(test-sources) $(test-library) + @echo "compiling test classes" + @mkdir -p $(test-build) + files="$(shell $(MAKE) -s --no-print-directory build=$(build) $(test-classes))"; \ + if test -n "$${files}"; then \ + $(javac) -source 1.$(java-version) -target 1.$(java-version) \ + -classpath $(test-build) -d $(test-build) -bootclasspath $(boot-classpath) $${files}; \ + fi + $(javac) -source 1.2 -target 1.1 -XDjsrlimit=0 -d $(test-build) \ + -bootclasspath $(boot-classpath) test/Subroutine.java + @touch $(@) + +$(test-extra-dep): $(test-extra-sources) + @echo "compiling extra test classes" + @mkdir -p $(test-build) + files="$(shell $(MAKE) -s --no-print-directory build=$(build) $(test-extra-classes))"; \ + if test -n "$${files}"; then \ + $(javac) -source 1.$(java-version) -target 1.$(java-version) \ + -d $(test-build) -bootclasspath $(boot-classpath) $${files}; \ + fi + @touch $(@) + +define compile-object + @echo "compiling $(@)" + @mkdir -p $(dir $(@)) + $(cxx) $(cflags) -c $$($(windows-path) $(<)) $(call output,$(@)) +endef + +define compile-asm-object + @echo "compiling $(@)" + @mkdir -p $(dir $(@)) + $(as) $(asmflags) $(call asm-output,$(@)) $(call asm-input,$(<)) +endef + +define compile-unittest-object + @echo "compiling $(@)" + @mkdir -p $(dir $(@)) + $(cxx) $(cflags) -c $$($(windows-path) $(<)) -I$(unittest) $(call output,$(@)) +endef + +$(vm-cpp-objects): $(build)/%.o: $(src)/%.cpp $(vm-depends) + $(compile-object) + +ifeq ($(process),interpret) +$(all-codegen-target-objects): $(build)/%.o: $(src)/%.cpp $(vm-depends) + $(compile-object) +endif + +$(unittest-objects): $(build)/unittest/%.o: $(unittest)/%.cpp $(vm-depends) $(unittest-depends) + $(compile-unittest-object) + +$(test-cpp-objects): $(test-build)/%.o: $(test)/%.cpp $(vm-depends) + $(compile-object) + +$(test-library): $(test-cpp-objects) + @echo "linking $(@)" +ifdef ms_cl_compiler + $(ld) $(shared) $(lflags) $(^) -out:$(@) \ + -debug -PDB:$(subst $(so-suffix),.pdb,$(@)) \ + -IMPLIB:$(test-build)/$(name).lib $(manifest-flags) +ifdef mt + $(mt) -nologo -manifest $(@).manifest -outputresource:"$(@);2" +endif +else + $(ld) $(^) $(shared) $(lflags) -o $(@) +endif + +ifdef embed +$(embed): $(embed-objects) $(embed-loader-o) + @echo "building $(embed)" +ifdef ms_cl_compiler + $(ld) $(lflags) $(^) -out:$(@) \ + -debug -PDB:$(subst $(exe-suffix),.pdb,$(@)) $(manifest-flags) +ifdef mt + $(mt) -nologo -manifest $(@).manifest -outputresource:"$(@);1" +endif +else + $(cxx) $(^) $(lflags) $(static) $(call output,$(@)) +endif + +$(build-embed)/%.o: $(src)/%.cpp + @echo "compiling $(@)" + @mkdir -p $(dir $(@)) + $(cxx) $(cflags) -c $(<) $(call output,$(@)) + +$(embed-loader-o): $(embed-loader) $(converter) + @mkdir -p $(dir $(@)) + $(converter) $(<) $(@) _binary_loader_start \ + _binary_loader_end $(target-format) $(arch) + +$(embed-loader): $(embed-loader-objects) $(vm-objects) $(classpath-objects) \ + $(heapwalk-objects) $(lzma-decode-objects) +ifdef ms_cl_compiler + $(ld) $(lflags) $(^) -out:$(@) \ + -debug -PDB:$(subst $(exe-suffix),.pdb,$(@)) $(manifest-flags) +ifdef mt + $(mt) -nologo -manifest $(@).manifest -outputresource:"$(@);1" +endif +else + $(dlltool) -z $(addsuffix .def,$(basename $(@))) $(^) + $(dlltool) -d $(addsuffix .def,$(basename $(@))) -e $(addsuffix .exp,$(basename $(@))) + $(ld) $(addsuffix .exp,$(basename $(@))) $(^) \ + $(lflags) $(classpath-lflags) $(bootimage-lflags) -o $(@) +endif + $(strip) $(strip-all) $(@) + +$(build-embed-loader)/%.o: $(src)/%.cpp + @echo "compiling $(@)" + @mkdir -p $(dir $(@)) + $(cxx) $(cflags) -c $(<) $(call output,$(@)) +endif + +$(build)/%.o: $(lzma)/C/%.c + @echo "compiling $(@)" + @mkdir -p $(dir $(@)) + $(cc) $(lzma-cflags) -c $$($(windows-path) $(<)) $(call output,$(@)) + +$(vm-asm-objects): $(build)/%-asm.o: $(src)/%.$(asm-format) + $(compile-asm-object) + +$(bootimage-generator-objects): $(build)/%.o: $(src)/%.cpp $(vm-depends) + $(compile-object) + +$(heapwalk-objects): $(build)/%.o: $(src)/%.cpp $(vm-depends) + $(compile-object) + +$(driver-object): $(driver-source) + $(compile-object) + +$(build)/main-dynamic.o: $(driver-source) + @echo "compiling $(@)" + @mkdir -p $(dir $(@)) + $(cxx) $(cflags) -DBOOT_LIBRARY=\"$(so-prefix)jvm$(so-suffix)\" \ + -c $(<) $(call output,$(@)) + +$(boot-object): $(boot-source) + $(compile-object) + +$(boot-javahome-object): $(src)/boot-javahome.cpp + $(compile-object) + +$(object-writer-objects) $(binary-to-object-objects): $(build)/%.o: $(src)/%.cpp $(binary-to-object-depends) $(object-writer-depends) $(all-depends) + @mkdir -p $(dir $(@)) + $(build-cxx) $(converter-cflags) -c $(<) -o $(@) + +$(converter): $(converter-objects) $(converter-tool-objects) + @mkdir -p $(dir $(@)) + $(build-cc) $(^) -g -o $(@) + +$(lzma-encoder-objects): $(build)/lzma/%.o: $(src)/lzma/%.cpp + @mkdir -p $(dir $(@)) + $(build-cxx) $(lzma-build-cflags) -c $(<) -o $(@) + +$(lzma-encoder): $(lzma-encoder-objects) $(lzma-encoder-lzma-objects) + $(build-cc) $(^) -g -o $(@) + +$(lzma-library): $(lzma-loader) $(lzma-decode-objects) + @echo "creating $(@)" + @rm -rf $(build)/libavian-lzma + @mkdir -p $(build)/libavian-lzma + rm -rf $(@) + for x in $(^); \ + do cp $${x} $(build)/libavian-lzma/$$(echo $${x} | sed s:/:_:g); \ + done +ifdef ms_cl_compiler + $(ar) $(arflags) $(build)/libavian-lzma/*.o -out:$(@) +else + $(ar) cru $(@) $(build)/libavian-lzma/*.o + $(ranlib) $(@) +endif + +$(lzma-loader): $(src)/lzma/load.cpp + $(compile-object) + +$(build)/classpath.jar: $(classpath-dep) $(classpath-jar-dep) + @echo "creating $(@)" + (wd=$$(pwd) && \ + cd $(classpath-build) && \ + $(jar) c0f "$$($(native-path) "$${wd}/$(@)")" .) + +$(classpath-object): $(build)/classpath.jar $(converter) + @echo "creating $(@)" + $(converter) $(<) $(@) _binary_classpath_jar_start \ + _binary_classpath_jar_end $(target-format) $(arch) + +$(build)/javahome.jar: + @echo "creating $(@)" + (wd=$$(pwd) && \ + cd "$(build-javahome)" && \ + $(jar) c0f "$$($(native-path) "$${wd}/$(@)")" $(javahome-files)) + +$(javahome-object): $(build)/javahome.jar $(converter) + @echo "creating $(@)" + $(converter) $(<) $(@) _binary_javahome_jar_start \ + _binary_javahome_jar_end $(target-format) $(arch) + +define compile-generator-object + @echo "compiling $(@)" + @mkdir -p $(dir $(@)) + $(build-cxx) -DPOINTER_SIZE=$(pointer-size) -O0 -g3 $(build-cflags) \ + -c $(<) -o $(@) +endef + +$(generator-objects): $(generator-depends) +$(generator-objects): $(build)/%-build.o: $(src)/%.cpp + $(compile-generator-object) + +$(build)/%-build.o: $(lzma)/C/%.c + @echo "compiling $(@)" + @mkdir -p $(dir $(@)) + $(build-cc) -DPOINTER_SIZE=$(pointer-size) -O0 -g3 $(lzma-build-cflags) \ + -c $(<) -o $(@) + +$(jni-objects): $(build)/%.o: $(classpath-src)/%.cpp $(vm-depends) + $(compile-object) + +$(static-library): $(vm-objects) $(classpath-objects) $(vm-heapwalk-objects) \ + $(javahome-object) $(boot-javahome-object) $(lzma-decode-objects) + @echo "creating $(@)" + @rm -rf $(build)/libavian + @mkdir -p $(build)/libavian + rm -rf $(@) + for x in $(^); \ + do cp $${x} $(build)/libavian/$$(echo $${x} | sed s:/:_:g); \ + done +ifdef ms_cl_compiler + $(ar) $(arflags) $(build)/libavian/*.o -out:$(@) +else + $(ar) cru $(@) $(build)/libavian/*.o + $(ranlib) $(@) +endif + +$(bootimage-object) $(codeimage-object): $(bootimage-generator) \ + $(classpath-jar-dep) $(test-dep) + @echo "generating bootimage and codeimage binaries from $(classpath-build) using $(<)" + $(<) -cp $(bootimage-classpath) -bootimage $(bootimage-object) -codeimage $(codeimage-object) \ + -bootimage-symbols $(bootimage-symbols) \ + -codeimage-symbols $(codeimage-symbols) \ + -hostvm $(host-vm) + +executable-objects = $(vm-objects) $(classpath-objects) $(driver-object) \ + $(vm-heapwalk-objects) $(boot-object) $(vm-classpath-objects) \ + $(javahome-object) $(boot-javahome-object) $(lzma-decode-objects) + +unittest-executable-objects = $(unittest-objects) $(vm-objects) \ + $(vm-heapwalk-objects) $(build)/util/arg-parser.o $(stub-objects) \ + $(lzma-decode-objects) + +ifeq ($(process),interpret) + unittest-executable-objects += $(all-codegen-target-objects) +endif + +# apparently, make does poorly with ifs inside of defines, and indented defines. +# I suggest re-indenting the following before making edits (and unindenting afterwards): +ifneq ($(platform),windows) +define link-executable + @echo linking $(@) + $(ld) $(^) $(rdynamic) $(lflags) $(classpath-lflags) $(bootimage-lflags) \ + -o $(@) +endef +else +ifdef ms_cl_compiler +ifdef mt +define link-executable + @echo linking $(@) + $(ld) $(lflags) $(^) -out:$(@) \ + -debug -PDB:$(subst $(exe-suffix),.pdb,$(@)) $(manifest-flags) + $(mt) -nologo -manifest $(@).manifest -outputresource:"$(@);1" +endef +else +define link-executable + @echo linking $(@) + $(mt) -nologo -manifest $(@).manifest -outputresource:"$(@);1" +endef +endif +else +define link-executable + @echo linking $(@) + $(dlltool) -z $(@).def $(^) + $(dlltool) -d $(@).def -e $(@).exp + $(ld) $(@).exp $(^) $(lflags) $(classpath-lflags) -o $(@) +endef +endif +endif + +$(executable): $(executable-objects) + $(link-executable) + +$(unittest-executable): $(unittest-executable-objects) + $(link-executable) + +$(bootimage-generator): $(bootimage-generator-objects) $(vm-objects) + echo building $(bootimage-generator) arch=$(build-arch) platform=$(bootimage-platform) + $(MAKE) process=interpret \ + bootimage= \ + bootimage-test= \ + mode=$(mode) \ + platform=$(bootimage-platform) \ + arch=$(build-arch) + $(MAKE) mode=$(mode) \ + build=$(host-build-root) \ + arch=$(build-arch) \ + aot-only=false \ + target-arch=$(arch) \ + armv6=$(armv6) \ + platform=$(bootimage-platform) \ + target-format=$(target-format) \ + android=$(android) \ + openjdk=$(openjdk) \ + openjdk-src=$(openjdk-src) \ + bootimage-generator= \ + build-bootimage-generator=$(bootimage-generator) \ + target-cflags="$(bootimage-cflags)" \ + target-asm=$(asm) \ + $(bootimage-generator) + +$(build-bootimage-generator): \ + $(vm-objects) $(classpath-object) \ + $(heapwalk-objects) $(bootimage-generator-objects) $(converter-objects) \ + $(lzma-decode-objects) $(lzma-encode-objects) + @echo "linking $(@)" +ifeq ($(platform),windows) +ifdef ms_cl_compiler + $(ld) $(bootimage-generator-lflags) $(lflags) $(^) -out:$(@) \ + -debug -PDB:$(subst $(exe-suffix),.pdb,$(@)) $(manifest-flags) +ifdef mt + $(mt) -nologo -manifest $(@).manifest -outputresource:"$(@);1" +endif +else + $(dlltool) -z $(@).def $(^) + $(dlltool) -d $(@).def -e $(@).exp + $(ld) $(@).exp $(^) $(bootimage-generator-lflags) $(lflags) -o $(@) +endif +else + $(ld) $(^) $(rdynamic) $(bootimage-generator-lflags) $(lflags) -o $(@) +endif + +$(dynamic-library): $(vm-objects) $(dynamic-object) $(classpath-objects) \ + $(vm-heapwalk-objects) $(boot-object) $(vm-classpath-objects) \ + $(classpath-libraries) $(javahome-object) $(boot-javahome-object) \ + $(lzma-decode-objects) + @echo "linking $(@)" +ifdef ms_cl_compiler + $(ld) $(shared) $(lflags) $(^) -out:$(@) \ + -debug -PDB:$(subst $(so-suffix),.pdb,$(@)) \ + -IMPLIB:$(subst $(so-suffix),.lib,$(@)) $(manifest-flags) +ifdef mt + $(mt) -nologo -manifest $(@).manifest -outputresource:"$(@);2" +endif +else + $(ld) $(^) $(version-script-flag) $(soname-flag) \ + $(shared) $(lflags) $(classpath-lflags) $(bootimage-lflags) \ + -o $(@) +endif + $(strip) $(strip-all) $(@) + +# todo: the $(no-lto) flag below is due to odd undefined reference errors on +# Ubuntu 11.10 which may be fixable without disabling LTO. +$(executable-dynamic): $(driver-dynamic-objects) $(dynamic-library) + @echo "linking $(@)" +ifdef ms_cl_compiler + $(ld) $(lflags) -LIBPATH:$(build) -DEFAULTLIB:$(name) \ + -debug -PDB:$(subst $(exe-suffix),.pdb,$(@)) \ + $(driver-dynamic-objects) -out:$(@) $(manifest-flags) +ifdef mt + $(mt) -nologo -manifest $(@).manifest -outputresource:"$(@);1" +endif +else + $(ld) $(driver-dynamic-objects) -L$(build) -ljvm $(lflags) $(no-lto) $(rpath) -o $(@) +endif + $(strip) $(strip-all) $(@) + +$(generator): $(generator-objects) $(generator-lzma-objects) + @echo "linking $(@)" + $(build-ld-cpp) $(^) $(build-lflags) $(static-on-windows) -o $(@) + +$(openjdk-objects): $(build)/openjdk/%-openjdk.o: $(openjdk-src)/%.c \ + $(openjdk-headers-dep) + @echo "compiling $(@)" + @mkdir -p $(dir $(@)) + sed 's/^static jclass ia_class;//' < $(<) > $(build)/openjdk/$(notdir $(<)) +ifeq ($(platform),ios) + sed \ + -e 's/^#ifndef __APPLE__/#if 1/' \ + -e 's/^#ifdef __APPLE__/#if 0/' \ + < "$(openjdk-src)/solaris/native/java/lang/ProcessEnvironment_md.c" \ + > $(build)/openjdk/ProcessEnvironment_md.c + sed \ + -e 's/^#ifndef __APPLE__/#if 1/' \ + -e 's/^#ifdef __APPLE__/#if 0/' \ + < "$(openjdk-src)/solaris/native/java/lang/UNIXProcess_md.c" \ + > $(build)/openjdk/UNIXProcess_md.c + if [ -e "$(openjdk-src)/solaris/native/java/lang/childproc.h" ]; then \ + sed \ + -e 's/^#ifndef __APPLE__/#if 1/' \ + -e 's/^#ifdef __APPLE__/#if 0/' \ + < "$(openjdk-src)/solaris/native/java/lang/childproc.h" \ + > $(build)/openjdk/childproc.h; \ + fi +endif +ifneq (7,$(openjdk-version)) + if [ -f openjdk-patches/$(notdir $(<)).8.patch ]; then \ + ( cd $(build) && patch -p0 ) < openjdk-patches/$(notdir $(<)).8.patch; \ + fi + if [ -f openjdk-patches/$(notdir $(<)).8.$(platform).patch ]; then \ + ( cd $(build) && patch -p0 ) < openjdk-patches/$(notdir $(<)).8.$(platform).patch; \ + fi +endif + if [ -f openjdk-patches/$(notdir $(<)).patch ]; then \ + ( cd $(build) && patch -p0 ) < openjdk-patches/$(notdir $(<)).patch; \ + fi + $(cc) -fPIC $(openjdk-extra-cflags) $(openjdk-cflags) \ + $(optimization-cflags) -w -c $(build)/openjdk/$(notdir $(<)) \ + $(call output,$(@)) -Wno-return-type + +$(openjdk-local-objects): $(build)/openjdk/%-openjdk.o: $(src)/openjdk/%.c \ + $(openjdk-headers-dep) + @echo "compiling $(@)" + @mkdir -p $(dir $(@)) + $(cc) -fPIC $(openjdk-extra-cflags) $(openjdk-cflags) \ + $(optimization-cflags) -w -c $(<) $(call output,$(@)) + +$(openjdk-headers-dep): + @echo "generating openjdk headers" + @mkdir -p $(dir $(@)) + $(javah) -d $(build)/openjdk -bootclasspath $(boot-classpath) \ + $(openjdk-headers-classes) +ifeq ($(platform),windows) + sed 's/^#ifdef _WIN64/#if 1/' \ + < "$(openjdk-src)/windows/native/java/net/net_util_md.h" \ + > $(build)/openjdk/net_util_md.h + sed \ + -e 's/\(^#include "net_util.h"\)/\1\n#if (defined _INC_NLDEF) || (defined _WS2DEF_)\n#define HIDE(x) hide_##x\n#else\n#define HIDE(x) x\n#define _WINSOCK2API_\n#endif/' \ + -e 's/\(IpPrefix[a-zA-Z_]*\)/HIDE(\1)/' \ + -e 's/\(IpSuffix[a-zA-Z_]*\)/HIDE(\1)/' \ + -e 's/\(IpDad[a-zA-Z_]*\)/HIDE(\1)/' \ + -e 's/\(ScopeLevel[a-zA-Z_]*\)/HIDE(\1)/' \ + -e 's/\(SCOPE_LEVEL[a-zA-Z_]*\)/HIDE(\1)/' \ + < "$(openjdk-src)/windows/native/java/net/NetworkInterface.h" \ + > $(build)/openjdk/NetworkInterface.h + echo 'static int getAddrsFromAdapter(IP_ADAPTER_ADDRESSES *ptr, netaddr **netaddrPP);' >> $(build)/openjdk/NetworkInterface.h +endif + +ifeq ($(kernel),darwin) + mkdir -p $(build)/openjdk/netinet + for file in \ + $(header-sysroot)/usr/include/netinet/ip.h \ + $(header-sysroot)/usr/include/netinet/in_systm.h \ + $(header-sysroot)/usr/include/netinet/ip_icmp.h \ + $(header-sysroot)/usr/include/netinet/in_var.h \ + $(header-sysroot)/usr/include/netinet/icmp6.h \ + $(header-sysroot)/usr/include/netinet/ip_var.h; do \ + if [ ! -f "$(build)/openjdk/netinet/$$(basename $${file})" ]; then \ + ln "$${file}" "$(build)/openjdk/netinet/$$(basename $${file})"; \ + fi; \ + done + mkdir -p $(build)/openjdk/netinet6 + for file in \ + $(header-sysroot)/usr/include/netinet6/in6_var.h; do \ + if [ ! -f "$(build)/openjdk/netinet6/$$(basename $${file})" ]; then \ + ln "$${file}" "$(build)/openjdk/netinet6/$$(basename $${file})"; \ + fi; \ + done + mkdir -p $(build)/openjdk/net + for file in \ + $(header-sysroot)/usr/include/net/if_arp.h; do \ + if [ ! -f "$(build)/openjdk/net/$$(basename $${file})" ]; then \ + ln "$${file}" "$(build)/openjdk/net/$$(basename $${file})"; \ + fi; \ + done + mkdir -p $(build)/openjdk/sys + for file in \ + $(header-sysroot)/usr/include/sys/kern_event.h \ + $(header-sysroot)/usr/include/sys/sys_domain.h; do \ + if [ ! -f "$(build)/openjdk/sys/$$(basename $${file})" ]; then \ + ln "$${file}" "$(build)/openjdk/sys/$$(basename $${file})"; \ + fi; \ + done +endif + @touch $(@) + +$(openjdk-jar-dep): + @echo "extracting openjdk classes" + @mkdir -p $(dir $(@)) + @mkdir -p $(classpath-build) + (cd $(classpath-build) && \ + $(jar) xf "$$($(native-path) "$(openjdk)/jre/lib/rt.jar")" && \ + $(jar) xf "$$($(native-path) "$(openjdk)/jre/lib/jsse.jar")" && \ + $(jar) xf "$$($(native-path) "$(openjdk)/jre/lib/jce.jar")" && \ + $(jar) xf "$$($(native-path) "$(openjdk)/jre/lib/charsets.jar")" && \ + $(jar) xf "$$($(native-path) "$(openjdk)/jre/lib/ext/sunjce_provider.jar")" && \ + $(jar) xf "$$($(native-path) "$(openjdk)/jre/lib/resources.jar")") + @touch $(@) diff --git a/sgx-jvm/avian/openjdk-patches/Inet4AddressImpl.c.8.patch b/sgx-jvm/avian/openjdk-patches/Inet4AddressImpl.c.8.patch new file mode 100644 index 0000000000..56e99af3bc --- /dev/null +++ b/sgx-jvm/avian/openjdk-patches/Inet4AddressImpl.c.8.patch @@ -0,0 +1,24 @@ +--- openjdk/Inet4AddressImpl.c ++++ openjdk/Inet4AddressImpl.c +@@ -461,6 +461,21 @@ + return JNI_FALSE; + } + ++#ifdef WIN32 ++DWORD WINAPI IcmpSendEcho2Ex(HANDLE, ++ HANDLE, ++ LPVOID, ++ PVOID, ++ IPAddr, ++ IPAddr, ++ LPVOID, ++ WORD, ++ LPVOID, ++ LPVOID, ++ DWORD, ++ DWORD); ++#endif ++ + /** + * ping implementation. + * Send a ICMP_ECHO_REQUEST packet every second until either the timeout diff --git a/sgx-jvm/avian/openjdk-patches/Inet6AddressImpl.c.8.patch b/sgx-jvm/avian/openjdk-patches/Inet6AddressImpl.c.8.patch new file mode 100644 index 0000000000..d2994ea21f --- /dev/null +++ b/sgx-jvm/avian/openjdk-patches/Inet6AddressImpl.c.8.patch @@ -0,0 +1,17 @@ +--- openjdk/Inet6AddressImpl.c ++++ openjdk/Inet6AddressImpl.c +@@ -360,6 +360,13 @@ + + #ifdef AF_INET6 + ++#ifdef __MINGW32__ ++typedef struct icmpv6_echo_reply_lh { ++ IPV6_ADDRESS_EX Address; ++ ULONG Status; ++ unsigned int RoundTripTime; ++} ICMPV6_ECHO_REPLY, *PICMPV6_ECHO_REPLY; ++#endif + + /** + * ping implementation. + diff --git a/sgx-jvm/avian/openjdk-patches/java_props_macosx.c.patch b/sgx-jvm/avian/openjdk-patches/java_props_macosx.c.patch new file mode 100644 index 0000000000..42622f6fda --- /dev/null +++ b/sgx-jvm/avian/openjdk-patches/java_props_macosx.c.patch @@ -0,0 +1,15 @@ +--- openjdk/java_props_macosx.c ++++ openjdk/java_props_macosx.c +@@ -37,11 +37,7 @@ + + // need dlopen/dlsym trick to avoid pulling in JavaRuntimeSupport before libjava.dylib is loaded + static void *getJRSFramework() { +- static void *jrsFwk = NULL; +- if (jrsFwk == NULL) { +- jrsFwk = dlopen("/System/Library/Frameworks/JavaVM.framework/Frameworks/JavaRuntimeSupport.framework/JavaRuntimeSupport", RTLD_LAZY | RTLD_LOCAL); +- } +- return jrsFwk; ++ return NULL; + } + + static char *getPosixLocale(int cat) { diff --git a/sgx-jvm/avian/openjdk-patches/java_props_md.c.8.windows.patch b/sgx-jvm/avian/openjdk-patches/java_props_md.c.8.windows.patch new file mode 100644 index 0000000000..0211421383 --- /dev/null +++ b/sgx-jvm/avian/openjdk-patches/java_props_md.c.8.windows.patch @@ -0,0 +1,24 @@ +--- openjdk/java_props_md.c ++++ openjdk/java_props_md.c +@@ -212,17 +212,17 @@ + * SHELL32 DLL is delay load DLL and we can use the trick with + * __try/__except block. + */ +- __try { ++ /* __try { */ + /* + * For Windows Vista and later (or patched MS OS) we need to use + * [SHGetKnownFolderPath] call to avoid MAX_PATH length limitation. + * Shell32.dll (version 6.0.6000 or later) + */ + hr = SHGetKnownFolderPath(&FOLDERID_Profile, KF_FLAG_DONT_VERIFY, NULL, &u_path); +- } __except(EXCEPTION_EXECUTE_HANDLER) { ++ /* } __except(EXCEPTION_EXECUTE_HANDLER) { */ + /* Exception: no [SHGetKnownFolderPath] entry */ +- hr = E_FAIL; +- } ++ /* hr = E_FAIL; */ ++ /* } */ + + if (FAILED(hr)) { + WCHAR path[MAX_PATH+1]; diff --git a/sgx-jvm/avian/openjdk-src.mk b/sgx-jvm/avian/openjdk-src.mk new file mode 100644 index 0000000000..f4ec22b9d0 --- /dev/null +++ b/sgx-jvm/avian/openjdk-src.mk @@ -0,0 +1,386 @@ +openjdk-sources = \ + $(openjdk-src)/share/native/common/check_code.c \ + $(openjdk-src)/share/native/common/check_format.c \ + $(openjdk-src)/share/native/common/check_version.c \ + $(openjdk-src)/share/native/common/jdk_util.c \ + $(openjdk-src)/share/native/common/jio.c \ + $(openjdk-src)/share/native/common/jni_util.c \ + $(openjdk-src)/share/native/common/verify_stub.c \ + $(openjdk-src)/share/native/java/io/FileInputStream.c \ + $(openjdk-src)/share/native/java/io/io_util.c \ + $(openjdk-src)/share/native/java/io/ObjectInputStream.c \ + $(openjdk-src)/share/native/java/io/ObjectOutputStream.c \ + $(openjdk-src)/share/native/java/io/ObjectStreamClass.c \ + $(openjdk-src)/share/native/java/io/RandomAccessFile.c \ + $(openjdk-src)/share/native/java/lang/Class.c \ + $(openjdk-src)/share/native/java/lang/ClassLoader.c \ + $(openjdk-src)/share/native/java/lang/Compiler.c \ + $(openjdk-src)/share/native/java/lang/Double.c \ + $(openjdk-src)/share/native/java/lang/Float.c \ + $(openjdk-src)/share/native/java/lang/Object.c \ + $(openjdk-src)/share/native/java/lang/Package.c \ + $(wildcard $(openjdk-src)/share/native/java/lang/ref/Finalizer.c) \ + $(openjdk-src)/share/native/java/lang/reflect/Array.c \ + $(openjdk-src)/share/native/java/lang/reflect/Proxy.c \ + $(wildcard $(openjdk-src)/share/native/java/lang/ResourceBundle.c) \ + $(openjdk-src)/share/native/java/lang/Runtime.c \ + $(openjdk-src)/share/native/java/lang/SecurityManager.c \ + $(openjdk-src)/share/native/java/lang/Shutdown.c \ + $(openjdk-src)/share/native/java/lang/StrictMath.c \ + $(openjdk-src)/share/native/java/lang/String.c \ + $(openjdk-src)/share/native/java/lang/System.c \ + $(openjdk-src)/share/native/java/lang/Thread.c \ + $(openjdk-src)/share/native/java/lang/Throwable.c \ + $(wildcard $(openjdk-src)/share/native/java/lang/fdlibm/src/*.c) \ + $(openjdk-src)/share/native/java/net/DatagramPacket.c \ + $(openjdk-src)/share/native/java/net/InetAddress.c \ + $(openjdk-src)/share/native/java/net/Inet4Address.c \ + $(openjdk-src)/share/native/java/net/Inet6Address.c \ + $(openjdk-src)/share/native/java/nio/Bits.c \ + $(openjdk-src)/share/native/java/security/AccessController.c \ + $(wildcard $(openjdk-src)/share/native/java/sql/DriverManager.c) \ + $(openjdk-src)/share/native/java/util/concurrent/atomic/AtomicLong.c \ + $(openjdk-src)/share/native/java/util/TimeZone.c \ + $(openjdk-src)/share/native/java/util/zip/Adler32.c \ + $(openjdk-src)/share/native/java/util/zip/CRC32.c \ + $(openjdk-src)/share/native/java/util/zip/Deflater.c \ + $(openjdk-src)/share/native/java/util/zip/Inflater.c \ + $(openjdk-src)/share/native/java/util/zip/ZipFile.c \ + $(openjdk-src)/share/native/java/util/zip/zip_util.c \ + $(openjdk-src)/share/native/sun/management/VMManagementImpl.c \ + $(openjdk-src)/share/native/sun/misc/GC.c \ + $(openjdk-src)/share/native/sun/misc/MessageUtils.c \ + $(openjdk-src)/share/native/sun/misc/NativeSignalHandler.c \ + $(openjdk-src)/share/native/sun/misc/Signal.c \ + $(openjdk-src)/share/native/sun/misc/Version.c \ + $(openjdk-src)/share/native/sun/misc/VM.c \ + $(openjdk-src)/share/native/sun/misc/VMSupport.c \ + $(openjdk-src)/share/native/sun/reflect/ConstantPool.c \ + $(openjdk-src)/share/native/sun/reflect/NativeAccessors.c \ + $(openjdk-src)/share/native/sun/reflect/Reflection.c + +openjdk-headers-classes = \ + java.io.Console \ + java.io.FileDescriptor \ + java.io.FileInputStream \ + java.io.FileOutputStream \ + java.io.FileSystem \ + java.io.ObjectInputStream \ + java.io.ObjectOutputStream \ + java.io.ObjectStreamClass \ + java.io.RandomAccessFile \ + java.lang.Class \ + java.lang.ClassLoader \ + java.lang.Compiler \ + java.lang.Double \ + java.lang.Float \ + java.lang.Integer \ + java.lang.Long \ + java.lang.Object \ + java.lang.Package \ + java.lang.Runtime \ + java.lang.SecurityManager \ + java.lang.Shutdown \ + java.lang.StrictMath \ + java.lang.String \ + java.lang.System \ + java.lang.Thread \ + java.lang.Throwable \ + java.lang.ref.Finalizer \ + java.lang.reflect.Array \ + java.lang.reflect.Proxy \ + java.net.InetAddress \ + java.net.Inet4Address \ + java.net.Inet6Address \ + java.net.DatagramPacket \ + java.net.SocketOptions \ + java.net.InetAddressImplFactory \ + java.net.Inet4AddressImpl \ + java.net.Inet6AddressImpl \ + java.net.NetworkInterface \ + java.net.PlainSocketImpl \ + java.net.SocketInputStream \ + java.net.SocketOutputStream \ + java.nio.MappedByteBuffer \ + java.security.AccessController \ + java.util.ResourceBundle \ + java.util.TimeZone \ + java.util.concurrent.atomic.AtomicLong \ + java.util.jar.JarFile \ + java.util.zip.Adler32 \ + java.util.zip.CRC32 \ + java.util.zip.Deflater \ + java.util.zip.Inflater \ + java.util.zip.ZipEntry \ + java.util.zip.ZipFile \ + sun.management.VMManagementImpl \ + sun.misc.GC \ + sun.misc.MessageUtils \ + sun.misc.NativeSignalHandler \ + sun.misc.Signal \ + sun.misc.VM \ + sun.misc.VMSupport \ + sun.misc.Version \ + sun.misc.URLClassPath \ + sun.net.spi.DefaultProxySelector \ + sun.nio.ch.FileKey \ + sun.nio.ch.FileChannelImpl \ + sun.nio.ch.FileDispatcherImpl \ + sun.nio.ch.DatagramChannelImpl \ + sun.nio.ch.DatagramDispatcher \ + sun.nio.ch.IOStatus \ + sun.nio.ch.IOUtil \ + sun.nio.ch.Net \ + sun.nio.ch.ServerSocketChannelImpl \ + sun.nio.ch.SocketChannelImpl \ + sun.nio.ch.SocketDispatcher \ + sun.nio.ch.PollArrayWrapper \ + sun.nio.ch.NativeThread \ + sun.reflect.ConstantPool \ + sun.reflect.NativeConstructorAccessorImpl \ + sun.reflect.NativeMethodAccessorImpl \ + sun.reflect.Reflection \ + sun.security.provider.NativeSeedGenerator + +ifneq (7,$(openjdk-version)) + openjdk-sources += \ + $(openjdk-src)/share/native/sun/misc/URLClassPath.c +endif + +# todo: set properties according to architecture targeted and OpenJDK +# version used: +openjdk-cflags = \ + "-I$(src)/openjdk" \ + "-I$(build)/openjdk" \ + "-I$(openjdk-src)/share/javavm/export" \ + "-I$(openjdk-src)/share/native/common" \ + "-I$(openjdk-src)/share/native/java/io" \ + "-I$(openjdk-src)/share/native/java/lang" \ + "-I$(openjdk-src)/share/native/java/lang/fdlibm/include" \ + "-I$(openjdk-src)/share/native/java/net" \ + "-I$(openjdk-src)/share/native/java/util/zip" \ + "-I$(openjdk-src)/share/native/sun/management" \ + "-I$(openjdk-src)/share/native/sun/nio/ch" \ + "-I$(openjdk-src)/share/javavm/include" \ + -D_LITTLE_ENDIAN \ + -DARCHPROPNAME=\"x86\" \ + -DRELEASE=\"1.6.0\" \ + -DJDK_MAJOR_VERSION=\"1\" \ + -DJDK_MINOR_VERSION=\"6\" \ + -DJDK_MICRO_VERSION=\"0\" \ + -DJDK_BUILD_NUMBER=\"0\" \ + -D_GNU_SOURCE + +ifeq ($(kernel),darwin) + openjdk-cflags += \ + -D_LFS_LARGEFILE=1 \ + -D_ALLBSD_SOURCE +endif + +ifeq ($(platform),windows) + openjdk-sources += \ + $(openjdk-src)/windows/native/common/jni_util_md.c \ + $(openjdk-src)/windows/native/java/io/canonicalize_md.c \ + $(openjdk-src)/windows/native/java/io/Console_md.c \ + $(openjdk-src)/windows/native/java/io/FileDescriptor_md.c \ + $(openjdk-src)/windows/native/java/io/FileInputStream_md.c \ + $(openjdk-src)/windows/native/java/io/FileOutputStream_md.c \ + $(openjdk-src)/windows/native/java/io/io_util_md.c \ + $(openjdk-src)/windows/native/java/io/RandomAccessFile_md.c \ + $(openjdk-src)/windows/native/java/io/WinNTFileSystem_md.c \ + $(openjdk-src)/windows/native/java/lang/java_props_md.c \ + $(openjdk-src)/windows/native/java/lang/ProcessEnvironment_md.c \ + $(openjdk-src)/windows/native/java/lang/ProcessImpl_md.c \ + $(openjdk-src)/windows/native/java/net/net_util_md.c \ + $(openjdk-src)/windows/native/java/net/ExtendedOptionsImpl.c \ + $(openjdk-src)/windows/native/java/net/DualStackPlainSocketImpl.c \ + $(openjdk-src)/windows/native/java/net/InetAddressImplFactory.c \ + $(openjdk-src)/windows/native/java/net/Inet4AddressImpl.c \ + $(openjdk-src)/windows/native/java/net/Inet6AddressImpl.c \ + $(openjdk-src)/windows/native/java/net/NetworkInterface.c \ + $(openjdk-src)/windows/native/java/net/NetworkInterface_winXP.c \ + $(openjdk-src)/windows/native/java/net/SocketInputStream.c \ + $(openjdk-src)/windows/native/java/net/SocketOutputStream.c \ + $(openjdk-src)/windows/native/java/net/TwoStacksPlainDatagramSocketImpl.c \ + $(openjdk-src)/windows/native/java/net/TwoStacksPlainSocketImpl.c \ + $(openjdk-src)/windows/native/java/util/WindowsPreferences.c \ + $(openjdk-src)/windows/native/java/util/logging.c \ + $(openjdk-src)/windows/native/java/util/TimeZone_md.c \ + $(openjdk-src)/windows/native/sun/io/Win32ErrorMode.c \ + $(openjdk-src)/windows/native/sun/nio/ch/DatagramChannelImpl.c \ + $(openjdk-src)/windows/native/sun/nio/ch/DatagramDispatcher.c \ + $(openjdk-src)/windows/native/sun/nio/ch/FileChannelImpl.c \ + $(openjdk-src)/windows/native/sun/nio/ch/FileDispatcherImpl.c \ + $(openjdk-src)/windows/native/sun/nio/ch/FileKey.c \ + $(openjdk-src)/windows/native/sun/nio/ch/IOUtil.c \ + $(openjdk-src)/windows/native/sun/nio/ch/Net.c \ + $(openjdk-src)/windows/native/sun/nio/ch/ServerSocketChannelImpl.c \ + $(openjdk-src)/windows/native/sun/nio/ch/SocketChannelImpl.c \ + $(openjdk-src)/windows/native/sun/nio/ch/SocketDispatcher.c \ + $(openjdk-src)/windows/native/sun/nio/ch/WindowsSelectorImpl.c \ + $(openjdk-src)/windows/native/sun/nio/fs/WindowsNativeDispatcher.c \ + $(openjdk-src)/windows/native/sun/security/provider/WinCAPISeedGenerator.c + + ifeq (7,$(openjdk-version)) + openjdk-sources += \ + $(openjdk-src)/windows/native/java/io/FileSystem_md.c \ + $(openjdk-src)/windows/native/java/io/Win32FileSystem_md.c + endif + + openjdk-headers-classes += \ + java.net.DualStackPlainSocketImpl \ + java.net.SocketImpl \ + java.net.TwoStacksPlainDatagramSocketImpl \ + java.net.TwoStacksPlainSocketImpl \ + java.lang.ProcessImpl \ + sun.io.Win32ErrorMode \ + sun.nio.ch.WindowsSelectorImpl \ + sun.nio.fs.WindowsNativeDispatcher \ + + openjdk-cflags += \ + "-I$(openjdk-src)/windows/javavm/export" \ + "-I$(openjdk-src)/windows/native/common" \ + "-I$(openjdk-src)/windows/native/java/io" \ + "-I$(openjdk-src)/windows/native/java/net" \ + "-I$(openjdk-src)/windows/native/java/util" \ + "-I$(openjdk-src)/windows/native/sun/nio/ch" \ + "-I$(openjdk-src)/windows/javavm/include" \ + -DLOCALE_SNAME=0x0000005c \ + -DLOCALE_SISO3166CTRYNAME2=0x00000068 \ + -DLOCALE_SISO639LANGNAME2=0x00000067 \ + -D_JNI_IMPLEMENTATION_ \ + -D_JAVASOFT_WIN32_TYPEDEF_MD_H_ \ + -D_WIN32_WINNT=0x0600 \ + -Ds6_words=_s6_words \ + -Ds6_bytes=_s6_bytes + + ifeq ($(arch),x86_64) + openjdk-cflags += "-I$(root)/win64/include" + else + openjdk-cflags += "-I$(root)/win32/include" + endif +else + openjdk-sources += \ + $(shell find $(openjdk-src)/solaris/native/common -name '*.c') \ + $(openjdk-src)/solaris/native/java/io/canonicalize_md.c \ + $(openjdk-src)/solaris/native/java/io/Console_md.c \ + $(openjdk-src)/solaris/native/java/io/FileDescriptor_md.c \ + $(openjdk-src)/solaris/native/java/io/FileInputStream_md.c \ + $(openjdk-src)/solaris/native/java/io/FileOutputStream_md.c \ + $(wildcard $(openjdk-src)/solaris/native/java/io/FileSystem_md.c) \ + $(openjdk-src)/solaris/native/java/io/io_util_md.c \ + $(openjdk-src)/solaris/native/java/io/RandomAccessFile_md.c \ + $(openjdk-src)/solaris/native/java/io/UnixFileSystem_md.c \ + $(openjdk-src)/solaris/native/java/lang/java_props_md.c \ + $(wildcard $(openjdk-src)/solaris/native/java/lang/childproc.c) \ + $(openjdk-src)/solaris/native/java/lang/ProcessEnvironment_md.c \ + $(openjdk-src)/solaris/native/java/lang/UNIXProcess_md.c \ + $(openjdk-src)/solaris/native/java/net/net_util_md.c \ + $(openjdk-src)/solaris/native/java/net/ExtendedOptionsImpl.c \ + $(openjdk-src)/solaris/native/java/net/InetAddressImplFactory.c \ + $(openjdk-src)/solaris/native/java/net/Inet4AddressImpl.c \ + $(openjdk-src)/solaris/native/java/net/Inet6AddressImpl.c \ + $(openjdk-src)/solaris/native/java/net/NetworkInterface.c \ + $(openjdk-src)/solaris/native/java/net/PlainSocketImpl.c \ + $(openjdk-src)/solaris/native/java/net/PlainDatagramSocketImpl.c \ + $(openjdk-src)/solaris/native/java/net/SocketInputStream.c \ + $(openjdk-src)/solaris/native/java/net/SocketOutputStream.c \ + $(openjdk-src)/solaris/native/java/nio/MappedByteBuffer.c \ + $(openjdk-src)/solaris/native/java/util/FileSystemPreferences.c \ + $(openjdk-src)/solaris/native/java/util/logging.c \ + $(openjdk-src)/solaris/native/java/util/TimeZone_md.c \ + $(openjdk-src)/solaris/native/sun/net/dns/ResolverConfigurationImpl.c \ + $(openjdk-src)/solaris/native/sun/net/spi/DefaultProxySelector.c \ + $(openjdk-src)/solaris/native/sun/nio/ch/DatagramChannelImpl.c \ + $(openjdk-src)/solaris/native/sun/nio/ch/DatagramDispatcher.c \ + $(openjdk-src)/solaris/native/sun/nio/ch/FileChannelImpl.c \ + $(openjdk-src)/solaris/native/sun/nio/ch/FileDispatcherImpl.c \ + $(openjdk-src)/solaris/native/sun/nio/ch/FileKey.c \ + $(openjdk-src)/solaris/native/sun/nio/ch/IOUtil.c \ + $(openjdk-src)/solaris/native/sun/nio/ch/Net.c \ + $(openjdk-src)/solaris/native/sun/nio/ch/ServerSocketChannelImpl.c \ + $(openjdk-src)/solaris/native/sun/nio/ch/SocketChannelImpl.c \ + $(openjdk-src)/solaris/native/sun/nio/ch/SocketDispatcher.c \ + $(openjdk-src)/solaris/native/sun/nio/ch/PollArrayWrapper.c \ + $(openjdk-src)/solaris/native/sun/nio/ch/InheritedChannel.c \ + $(openjdk-src)/solaris/native/sun/nio/ch/NativeThread.c \ + $(openjdk-src)/solaris/native/sun/nio/fs/UnixNativeDispatcher.c \ + + openjdk-headers-classes += \ + java.net.PlainDatagramSocketImpl \ + java.io.UnixFileSystem \ + sun.nio.ch.InheritedChannel \ + sun.nio.fs.UnixNativeDispatcher \ + + ifneq (7,$(openjdk-version)) + openjdk-headers-classes += \ + jdk.net.SocketFlow + endif + + openjdk-cflags += \ + "-I$(openjdk-src)/solaris/javavm/export" \ + "-I$(openjdk-src)/solaris/native/common" \ + "-I$(openjdk-src)/solaris/native/java/io" \ + "-I$(openjdk-src)/solaris/native/java/lang" \ + "-I$(openjdk-src)/solaris/native/java/net" \ + "-I$(openjdk-src)/solaris/native/java/util" \ + "-I$(openjdk-src)/solaris/native/sun/management" \ + "-I$(openjdk-src)/solaris/native/sun/nio/ch" \ + "-I$(openjdk-src)/solaris/javavm/include" \ + "-I$(openjdk-src)/solaris/hpi/include" \ + "-I$(openjdk-src)/solaris/native/common/deps" \ + "-I$(openjdk-src)/solaris/native/common/deps/fontconfig2" \ + "-I$(openjdk-src)/solaris/native/common/deps/gconf2" \ + "-I$(openjdk-src)/solaris/native/common/deps/glib2" \ + "-I$(openjdk-src)/solaris/native/common/deps/gtk2" \ + "-DX11_PATH=\"/usr/X11R6\"" + + ifeq ($(platform),linux) + openjdk-sources += \ + $(openjdk-src)/solaris/native/java/net/linux_close.c \ + $(openjdk-src)/solaris/native/sun/nio/ch/EPollArrayWrapper.c + + openjdk-headers-classes += \ + sun.nio.ch.EPollArrayWrapper + + openjdk-cflags += \ + "-I$(openjdk-src)/solaris/native/common/deps/glib2" \ + "-I$(openjdk-src)/solaris/native/common/deps/gconf2" \ + "-I$(openjdk-src)/solaris/native/common/deps/fontconfig2" \ + "-I$(openjdk-src)/solaris/native/common/deps/gtk2" \ + $(shell pkg-config --cflags glib-2.0) \ + $(shell pkg-config --cflags gconf-2.0) + endif + + ifeq ($(kernel),darwin) + openjdk-sources += \ + $(openjdk-src)/solaris/native/java/net/bsd_close.c \ + $(openjdk-src)/macosx/native/sun/nio/ch/KQueueArrayWrapper.c + + ifeq ($(platform),ios) + openjdk-local-sources += \ + $(src)/openjdk/my_java_props_macosx.c + else + openjdk-sources += \ + $(openjdk-src)/solaris/native/java/lang/java_props_macosx.c + endif + + openjdk-cflags += \ + -DMACOSX -x objective-c + endif +endif + +openjdk-local-sources += \ + $(src)/openjdk/my_net_util.c \ + $(src)/openjdk/my_management.c + +openjdk-c-objects = \ + $(foreach x,$(1),$(patsubst $(2)/%.c,$(3)/%-openjdk.o,$(x))) + +openjdk-objects = \ + $(call openjdk-c-objects,$(openjdk-sources),$(openjdk-src),$(build)/openjdk) + +openjdk-local-objects = \ + $(call openjdk-c-objects,$(openjdk-local-sources),$(src)/openjdk,$(build)/openjdk) + +openjdk-headers-dep = $(build)/openjdk/headers.dep diff --git a/sgx-jvm/avian/openjdk.ld b/sgx-jvm/avian/openjdk.ld new file mode 100644 index 0000000000..915cdde6e2 --- /dev/null +++ b/sgx-jvm/avian/openjdk.ld @@ -0,0 +1,294 @@ +# +# @(#)mapfile-vers-product 1.19 08/02/12 10:56:37 +# + +# +# Copyright 2002-2008 Sun Microsystems, Inc. All Rights Reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, +# CA 95054 USA or visit www.sun.com if you need additional information or +# have any questions. +# +# + +# Define public interface. + +SUNWprivate_1.1 { + global: + # JNI + JNI_CreateJavaVM; + JNI_GetCreatedJavaVMs; + JNI_GetDefaultJavaVMInitArgs; + + # JVM + JVM_Accept; + JVM_ActiveProcessorCount; + JVM_AllocateNewArray; + JVM_AllocateNewObject; + JVM_ArrayCopy; + JVM_AssertionStatusDirectives; + JVM_Available; + JVM_Bind; + JVM_ClassDepth; + JVM_ClassLoaderDepth; + JVM_Clone; + JVM_Close; + JVM_CX8Field; + JVM_CompileClass; + JVM_CompileClasses; + JVM_CompilerCommand; + JVM_Connect; + JVM_ConstantPoolGetClassAt; + JVM_ConstantPoolGetClassAtIfLoaded; + JVM_ConstantPoolGetDoubleAt; + JVM_ConstantPoolGetFieldAt; + JVM_ConstantPoolGetFieldAtIfLoaded; + JVM_ConstantPoolGetFloatAt; + JVM_ConstantPoolGetIntAt; + JVM_ConstantPoolGetLongAt; + JVM_ConstantPoolGetMethodAt; + JVM_ConstantPoolGetMethodAtIfLoaded; + JVM_ConstantPoolGetMemberRefInfoAt; + JVM_ConstantPoolGetSize; + JVM_ConstantPoolGetStringAt; + JVM_ConstantPoolGetUTF8At; + JVM_CountStackFrames; + JVM_CurrentClassLoader; + JVM_CurrentLoadedClass; + JVM_CurrentThread; + JVM_CurrentTimeMillis; + JVM_DefineClass; + JVM_DefineClassWithSource; + JVM_DefineClassWithSourceCond; + JVM_DesiredAssertionStatus; + JVM_DisableCompiler; + JVM_DoPrivileged; + JVM_DTraceGetVersion; + JVM_DTraceActivate; + JVM_DTraceIsProbeEnabled; + JVM_DTraceIsSupported; + JVM_DTraceDispose; + JVM_DumpAllStacks; + JVM_DumpThreads; + JVM_EnableCompiler; + JVM_Exit; + JVM_FillInStackTrace; + JVM_FindClassFromCaller; + JVM_FindClassFromClass; + JVM_FindClassFromClassLoader; + JVM_FindClassFromBootLoader; + JVM_FindLibraryEntry; + JVM_FindLoadedClass; + JVM_FindPrimitiveClass; + JVM_FindSignal; + JVM_FreeMemory; + JVM_GC; + JVM_GetAllThreads; + JVM_GetArrayElement; + JVM_GetArrayLength; + JVM_GetCPClassNameUTF; + JVM_GetCPFieldClassNameUTF; + JVM_GetCPFieldModifiers; + JVM_GetCPFieldNameUTF; + JVM_GetCPFieldSignatureUTF; + JVM_GetCPMethodClassNameUTF; + JVM_GetCPMethodModifiers; + JVM_GetCPMethodNameUTF; + JVM_GetCPMethodSignatureUTF; + JVM_GetCallerClass; + JVM_GetClassAccessFlags; + JVM_GetClassAnnotations; + JVM_GetClassCPEntriesCount; + JVM_GetClassCPTypes; + JVM_GetClassConstantPool; + JVM_GetClassContext; + JVM_GetClassDeclaredConstructors; + JVM_GetClassDeclaredFields; + JVM_GetClassDeclaredMethods; + JVM_GetClassFieldsCount; + JVM_GetClassInterfaces; + JVM_GetClassLoader; + JVM_GetClassMethodsCount; + JVM_GetClassModifiers; + JVM_GetClassName; + JVM_GetClassNameUTF; + JVM_GetClassSignature; + JVM_GetClassSigners; + JVM_GetClassTypeAnnotations; + JVM_GetComponentType; + JVM_GetDeclaredClasses; + JVM_GetDeclaringClass; + JVM_GetEnclosingMethodInfo; + JVM_GetFieldAnnotations; + JVM_GetFieldIxModifiers; + JVM_GetFieldTypeAnnotations; + JVM_GetHostName; + JVM_GetInheritedAccessControlContext; + JVM_GetInterfaceVersion; + JVM_GetLastErrorString; + JVM_GetManagement; + JVM_GetMethodAnnotations; + JVM_GetMethodDefaultAnnotationValue; + JVM_GetMethodIxArgsSize; + JVM_GetMethodIxByteCode; + JVM_GetMethodIxByteCodeLength; + JVM_GetMethodIxExceptionIndexes; + JVM_GetMethodIxExceptionTableEntry; + JVM_GetMethodIxExceptionTableLength; + JVM_GetMethodIxExceptionsCount; + JVM_GetMethodIxLocalsCount; + JVM_GetMethodIxMaxStack; + JVM_GetMethodIxModifiers; + JVM_GetMethodIxNameUTF; + JVM_GetMethodIxSignatureUTF; + JVM_GetMethodParameterAnnotations; + JVM_GetPrimitiveArrayElement; + JVM_GetProtectionDomain; + JVM_GetResourceLookupCacheURLs; + JVM_GetSockName; + JVM_GetSockOpt; + JVM_GetStackAccessControlContext; + JVM_GetStackTraceDepth; + JVM_GetStackTraceElement; + JVM_GetSystemPackage; + JVM_GetSystemPackages; + JVM_GetThreadStateNames; + JVM_GetThreadStateValues; + JVM_GetVersionInfo; + JVM_Halt; + JVM_HoldsLock; + JVM_IHashCode; + JVM_InitAgentProperties; + JVM_InitProperties; + JVM_InitializeCompiler; + JVM_InitializeSocketLibrary; + JVM_InternString; + JVM_Interrupt; + JVM_InvokeMethod; + JVM_IsArrayClass; + JVM_IsConstructorIx; + JVM_IsInterface; + JVM_IsInterrupted; + JVM_IsNaN; + JVM_IsPrimitiveClass; + JVM_IsSameClassPackage; + JVM_IsSilentCompiler; + JVM_IsSupportedJNIVersion; + JVM_IsThreadAlive; + JVM_IsVMGeneratedMethodIx; + JVM_LatestUserDefinedLoader; + JVM_Listen; + JVM_LoadClass0; + JVM_LoadLibrary; + JVM_Lseek; + JVM_MaxObjectInspectionAge; + JVM_MaxMemory; + JVM_MonitorNotify; + JVM_MonitorNotifyAll; + JVM_MonitorWait; + JVM_NanoTime; + JVM_NativePath; + JVM_NewArray; + JVM_NewInstanceFromConstructor; + JVM_NewMultiArray; + JVM_OnExit; + JVM_Open; + JVM_PrintStackTrace; + JVM_RaiseSignal; + JVM_RawMonitorCreate; + JVM_RawMonitorDestroy; + JVM_RawMonitorEnter; + JVM_RawMonitorExit; + JVM_Read; + JVM_Recv; + JVM_RecvFrom; + JVM_RegisterSignal; + JVM_ReleaseUTF; + JVM_ResolveClass; + JVM_ResumeThread; + JVM_Send; + JVM_SendTo; + JVM_SetArrayElement; + JVM_SetClassSigners; + JVM_SetLength; + JVM_SetNativeThreadName; + JVM_SetPrimitiveArrayElement; + JVM_SetProtectionDomain; + JVM_SetSockOpt; + JVM_SetThreadPriority; + JVM_Sleep; + JVM_Socket; + JVM_SocketAvailable; + JVM_SocketClose; + JVM_SocketShutdown; + JVM_StartThread; + JVM_StopThread; + JVM_SuspendThread; + JVM_SupportsCX8; + JVM_Sync; + JVM_Timeout; + JVM_TotalMemory; + JVM_TraceInstructions; + JVM_TraceMethodCalls; + JVM_UnloadLibrary; + JVM_Write; + JVM_Yield; + JVM_handle_linux_signal; + + # Old reflection routines + # These do not need to be present in the product build in JDK 1.4 + # but their code has not been removed yet because there will not + # be a substantial code savings until JVM_InvokeMethod and + # JVM_NewInstanceFromConstructor can also be removed; see + # reflectionCompat.hpp. + JVM_GetClassConstructor; + JVM_GetClassConstructors; + JVM_GetClassField; + JVM_GetClassFields; + JVM_GetClassMethod; + JVM_GetClassMethods; + JVM_GetField; + JVM_GetPrimitiveField; + JVM_NewInstance; + JVM_SetField; + JVM_SetPrimitiveField; + + # Needed for dropping VM into JDK 1.3.x, 1.4 + _JVM_native_threads; + jdk_sem_init; + jdk_sem_post; + jdk_sem_wait; + jdk_pthread_sigmask; + jdk_waitpid; + + # miscellaneous functions + jio_fprintf; + jio_printf; + jio_snprintf; + jio_vfprintf; + jio_vsnprintf; + fork1; + numa_warn; + numa_error; + + # Needed because there is no JVM interface for this. + sysThreadAvailableStackWithSlack; + + # This is for Forte Analyzer profiling support. + AsyncGetCallTrace; +}; diff --git a/sgx-jvm/avian/openjdk.pro b/sgx-jvm/avian/openjdk.pro new file mode 100644 index 0000000000..2393930fff --- /dev/null +++ b/sgx-jvm/avian/openjdk.pro @@ -0,0 +1,334 @@ +# proguard include file (http://proguard.sourceforge.net) + +# This file is for use in combination with vm.pro when ProGuarding +# OpenJDK-based builds + +# the following methods and fields are refered to by name in the VM: + +-keepclassmembers class java.lang.Thread { + public void run(); + } + +-keepclassmembers class java.lang.ThreadGroup { + void threadTerminated(java.lang.Thread); + } + +-keep class java.lang.System { + private static void initializeSystemClass(); + public static void setProperties(java.util.Properties); + } + +-keep class sun.misc.Launcher { + public static sun.misc.Launcher getLauncher(); + } + +-keep class java.lang.ClassLoader { + private static java.lang.ClassLoader scl; + private static boolean sclSet; + + protected ClassLoader(java.lang.ClassLoader); + } + +-keep class avian.SystemClassLoader { + protected java.net.URL findResource(java.lang.String); + } + +-keepnames class java.lang.ClassLoader { + public java.lang.Class loadClass(java.lang.String); + static void loadLibrary(java.lang.Class, java.lang.String, boolean); + private static java.net.URL getBootstrapResource(java.lang.String); + private static java.util.Enumeration getBootstrapResources(java.lang.String); + } + +-keep class java.util.Properties { + public java.lang.Object setProperty(java.lang.String, java.lang.String); + public java.lang.String getProperty(java.lang.String); + } + +-keep class java.util.Hashtable { + public java.lang.Object remove(java.lang.Object); + } + +-keep class avian.OpenJDK { + ; + } + +-keepclassmembers public class java.security.PrivilegedAction { + public java.lang.Object run(); + } + +-keepclassmembers public class * implements java.security.PrivilegedAction { + public java.lang.Object run(); + } + +-keepclassmembers public class java.security.PrivilegedExceptionAction { + public java.lang.Object run(); + } + +-keepclassmembers public class * implements java.security.PrivilegedExceptionAction { + public java.lang.Object run(); + } + +-keep public class java.security.PrivilegedActionException { + public PrivilegedActionException(java.lang.Exception); + } + +# these class names are used to disambiguate JNI method lookups: + +-keepnames public class java.net.URL +-keepnames public class java.util.Enumeration +-keepnames public class java.security.ProtectionDomain +-keepnames public class java.security.PrivilegedAction +-keepnames public class java.security.PrivilegedExceptionAction +-keepnames public class java.security.AccessControlContext + +# the following methods and fields are refered to by name in the OpenJDK +# native code: + +-keep class java.util.Properties { + public java.lang.Object put(java.lang.Object, java.lang.Object); + } + +-keepclassmembers class * { + public boolean equals(java.lang.Object); + public void wait(); + public void notify(); + public void notifyAll(); + public java.lang.String toString(); + } + +-keepclassmembers class java.lang.String { + public String(byte[]); + public String(byte[], java.lang.String); + public byte[] getBytes(); + public byte[] getBytes(java.lang.String); + } + +-keepclassmembers class java.lang.Boolean { + public boolean getBoolean(java.lang.String); + } + +-keepclassmembers class java.util.zip.Inflater { + long strm; + boolean needDict; + boolean finished; + byte[] buf; + int off; + int len; + } + +-keepclassmembers class java.io.FileDescriptor { + private int fd; + private long handle; + } + +-keep class java.net.NetworkInterface { + ; + } +-keep class java.net.InetAddress { + ; + } +-keep class java.net.Inet4Address { + ; + } +-keep class java.net.Inet4AddressImpl +-keep class java.net.Inet6Address { + ; + } +-keep class java.net.Inet6AddressImpl +-keep class java.net.InetSocketAddress { + public InetSocketAddress(java.net.InetAddress, int); + } +-keep class java.net.ServerSocket +-keep class java.net.SocketTimeoutException + +-keepclassmembers class java.net.PlainSocketImpl { + ; + } + +-keepclassmembers class java.net.TwoStacksPlainSocketImpl { + *** fd1; + *** lastfd; +} + +-keepclassmembers class java.net.AbstractPlainSocketImpl { + *** timeout; + *** trafficClass; +} + +-keepclassmembers class java.net.SocketImpl { + *** serverSocket; + *** fd; + *** address; + *** port; + *** localport; +} + +-keepclassmembers class java.io.FileInputStream { + private java.io.FileDescriptor fd; + } + +-keepclassmembers class java.io.FileOutputStream { + private java.io.FileDescriptor fd; + private boolean append; + } + +# changed in native code via sun.misc.Unsafe (todo: handle other +# Atomic* classes) +-keepclassmembers class java.util.concurrent.atomic.AtomicInteger { + private int value; + } + +# avoid inlining due to access check using a fixed offset into call stack: +-keep,allowshrinking,allowobfuscation class java.util.concurrent.atomic.AtomicReferenceFieldUpdater { + *** newUpdater(...); + } + +# accessed reflectively via an AtomicReferenceFieldUpdater: +-keepclassmembers class java.io.BufferedInputStream { + protected byte[] buf; + } + +-keep class java.lang.System { + public static java.io.InputStream in; + public static java.io.PrintStream out; + public static java.io.PrintStream err; + # avoid inlining due to access check using fixed offset into call stack: + static java.lang.Class getCallerClass(); + # called from jni_util.c: + static java.lang.String getProperty(java.lang.String); + } + +# refered to by name from native code: +-keepnames public class java.io.InputStream +-keepnames public class java.io.PrintStream + +# avoid inlining due to access check using fixed offset into call stack: +-keep,allowshrinking,allowobfuscation class java.lang.System { + static java.lang.Class getCallerClass(); + } + +-keep class java.io.UnixFileSystem { + public UnixFileSystem(); + } + +-keep class java.io.WinNTFileSystem { + public WinNTFileSystem(); + } + +-keep class java.io.File { + private java.lang.String path; + } + +-keepclassmembers class java.lang.ClassLoader$NativeLibrary { + long handle; + private int jniVersion; + } + +-keep class java.nio.charset.Charset { + # called from jni_util.c: + boolean isSupported(java.lang.String); + } + +# Charsets are loaded via reflection. If you need others besides +# UTF-8, you'll need to add them (e.g. sun.nio.cs.ISO_8859_1). +-keep class sun.nio.cs.UTF_8 + +# loaded reflectively to handle embedded resources: +-keep class avian.avianvmresource.Handler + +# loaded reflectively by sun.misc.Launcher: +-keep class avian.file.Handler + +# refered to symbolically in MethodAccessorGenerator: +-keep class sun.reflect.MethodAccessorImpl { + ; + } +-keep class sun.reflect.ConstructorAccessorImpl { + ; + } +-keep class sun.reflect.SerializationConstructorAccessorImpl { + ; + } + +# referred to by name in LocaleData to load resources: +-keep class sun.util.resources.CalendarData +-keep class sun.util.resources.TimeZoneNames +-keep class sun.text.resources.FormatData + +# loaded via reflection from DefaultFileSystemProvider: +-keep class sun.nio.fs.LinuxFileSystemProvider +-keep class sun.nio.fs.BsdFileSystemProvider + +# loaded via JNI in UnixNativeDispatcher.c: +-keep class sun.nio.fs.UnixFileAttributes { + ; +} +-keep class sun.nio.fs.UnixFileStoreAttributes { + ; +} +-keep class sun.nio.fs.UnixMountEntry { + ; +} + +-keep class sun.nio.fs.UnixException { + UnixException(int); + } + +-keep class sun.net.www.protocol.jar.Handler + +# These concurrent classes refer to certain members reflectively in their static initializers +-keepclassmembers class java.util.concurrent.ConcurrentHashMap$HashEntry { + *** next; +} + +-keepclassmembers class java.util.concurrent.CopyOnWriteArrayList { + *** lock; +} + +-keepclassmembers class java.util.concurrent.CountDownLatch { + *** allocationSpinLock; +} + +-keepclassmembers class java.util.concurrent.PriorityBlockingQueue { + *** allocationSpinLock; +} + +-keepclassmembers class java.util.concurrent.SynchronousQueue$TransferStack { + *** head; +} + +-keepclassmembers class java.util.concurrent.ConcurrentLinkedQueue { + *** head; + *** tail; +} + +-keepclassmembers class java.util.concurrent.ConcurrentLinkedQueue$Node { + *** item; + *** next; +} + +-keepclassmembers class java.util.concurrent.SynchronousQueue$TransferStack$SNode { + *** match; + *** next; +} + +# These classes are accessed via bytecode generated on the fly. +-keepclassmembers class java.lang.reflect.Proxy { + ; +} + +-keepclassmembers class java.lang.reflect.InvocationHandler { + ; +} + +# Don't strip special enum members. +-keepclassmembers,allowoptimization enum * { + public static **[] values(); + public static ** valueOf(java.lang.String); +} + +-keepclassmembers class java.lang.reflect.Executable { + ; +} + diff --git a/sgx-jvm/avian/settings.gradle b/sgx-jvm/avian/settings.gradle new file mode 100644 index 0000000000..1d99d5dcf6 --- /dev/null +++ b/sgx-jvm/avian/settings.gradle @@ -0,0 +1 @@ +rootProject.name="avian" \ No newline at end of file diff --git a/sgx-jvm/avian/src/CMakeLists.txt b/sgx-jvm/avian/src/CMakeLists.txt new file mode 100644 index 0000000000..c949643c0a --- /dev/null +++ b/sgx-jvm/avian/src/CMakeLists.txt @@ -0,0 +1,7 @@ +add_subdirectory(codegen) +add_subdirectory(system) +add_subdirectory(heap) +add_subdirectory(util) +add_subdirectory(tools) + +add_library(avian_jvm_finder finder.cpp) \ No newline at end of file diff --git a/sgx-jvm/avian/src/android/stubs.cpp b/sgx-jvm/avian/src/android/stubs.cpp new file mode 100644 index 0000000000..0c1295d464 --- /dev/null +++ b/sgx-jvm/avian/src/android/stubs.cpp @@ -0,0 +1,24 @@ +struct JavaVM; + +extern "C" int JNI_OnLoad(JavaVM*, void*) +{ + return 0; +} + +struct _JNIEnv; + +struct JniConstants { + static void init(_JNIEnv* env); +}; + +void JniConstants::init(_JNIEnv*) +{ + // ignore +} + +struct _JavaVM; + +int libconscrypt_JNI_OnLoad(_JavaVM*, void*) +{ + return 0; +} diff --git a/sgx-jvm/avian/src/arm.S b/sgx-jvm/avian/src/arm.S new file mode 100644 index 0000000000..941097d4e8 --- /dev/null +++ b/sgx-jvm/avian/src/arm.S @@ -0,0 +1,132 @@ +/* arm.S: JNI gluecode for ARM + Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#include "avian/types.h" + +.text + +#define LOCAL(x) .L##x + +#ifdef __APPLE__ +# define GLOBAL(x) _##x +#else +# define GLOBAL(x) x +#endif + +.globl GLOBAL(vmNativeCall) +.align 2 +GLOBAL(vmNativeCall): + /* + arguments: + r0 -> r4 : function + r1 -> r5 : stackTotal + r2 : memoryTable + r3 : memoryCount + [sp, #0] -> r6 : gprTable + [sp, #4] -> r7 : vfpTable + [sp, #8] -> r8 : returnType + */ + mov ip, sp // save stack frame + stmfd sp!, {r4-r8, lr} // save clobbered non-volatile regs + + // mv args into non-volatile regs + mov r4, r0 + mov r5, r1 + ldr r6, [ip] + ldr r7, [ip, #4] + ldr r8, [ip, #8] + + // setup stack arguments if necessary + sub sp, sp, r5 // allocate stack + mov ip, sp +LOCAL(loop): + tst r3, r3 + ldrne r0, [r2], #4 + strne r0, [ip], #4 + subne r3, r3, #4 + bne LOCAL(loop) + + // setup argument registers if necessary + tst r6, r6 +#if (defined __APPLE__) && (defined __clang_major__) && (__clang_major__ >= 4) + ldmiane r6, {r0-r3} +#else + ldmneia r6, {r0-r3} +#endif +#if defined(__ARM_PCS_VFP) + // and VFP registers + vldmia r7, {d0-d7} +#endif + +#if defined(__ARM_ARCH_4__) || defined(__ARM_ARCH_4T__) + mov lr, pc + bx r4 +#else + blx r4 // call function +#endif + add sp, sp, r5 // deallocate stack + +#if defined(__ARM_PCS_VFP) + cmp r8,#FLOAT_TYPE + bne LOCAL(double) + fmrs r0,s0 + b LOCAL(exit) + +LOCAL(double): + cmp r8,#DOUBLE_TYPE + bne LOCAL(exit) + fmrrd r0,r1,d0 +#endif + +LOCAL(exit): + ldmfd sp!, {r4-r8, pc} // restore non-volatile regs and return + +.globl GLOBAL(vmJump) +.align 2 +GLOBAL(vmJump): + mov lr, r0 + ldr r0, [sp] + ldr r1, [sp, #4] + mov sp, r2 + mov r8, r3 + bx lr + +#define CHECKPOINT_THREAD 4 +#define CHECKPOINT_STACK 24 + +.globl GLOBAL(vmRun) +.align 2 +GLOBAL(vmRun): + // r0: function + // r1: arguments + // r2: checkpoint + stmfd sp!, {r4-r11, lr} + // align stack + sub sp, sp, #12 + + str sp, [r2, #CHECKPOINT_STACK] + + mov r12, r0 + ldr r0, [r2, #CHECKPOINT_THREAD] + +#if defined(__ARM_ARCH_4__) || defined(__ARM_ARCH_4T__) + mov lr, pc + bx r12 +#else + blx r12 +#endif + +.globl GLOBAL(vmRun_returnAddress) +.align 2 +GLOBAL(vmRun_returnAddress): + add sp, sp, #12 + ldmfd sp!, {r4-r11, lr} + bx lr diff --git a/sgx-jvm/avian/src/arm.masm b/sgx-jvm/avian/src/arm.masm new file mode 100644 index 0000000000..ae036db58f --- /dev/null +++ b/sgx-jvm/avian/src/arm.masm @@ -0,0 +1,89 @@ +; Copyright (c) 2008-2015, Avian Contributors +; +; Permission to use, copy, modify, and/or distribute this software +; for any purpose with or without fee is hereby granted, provided +; that the above copyright notice and this permission notice appear +; in all copies. +; +; There is NO WARRANTY for this software. See license.txt for +; details. +; +; ORIGIN: https://github.com/gkvas/avian/tree/wince + + AREA text, CODE, ARM + + EXPORT vmNativeCall +vmNativeCall + ; arguments: + ; r0 -> r4 : function + ; r1 -> r5 : stackTotal + ; r2 : memoryTable + ; r3 : memoryCount + ; [sp, #0] -> r6 : gprTable + + mov ip, sp ; save stack frame + stmfd sp!, {r4-r6, lr} ; save clobbered non-volatile regs + + ; mv args into non-volatile regs + mov r4, r0 + mov r5, r1 + ldr r6, [ip] + + ; setup stack arguments if necessary + sub sp, sp, r5 ; allocate stack + mov ip, sp +loop + tst r3, r3 + ldrne r0, [r2], #4 + strne r0, [ip], #4 + subne r3, r3, #4 + bne loop + + ; setup argument registers if necessary + tst r6, r6 + ldmneia r6, {r0-r3} + + blx r4 ; call function + add sp, sp, r5 ; deallocate stack + + ldmfd sp!, {r4-r6, pc} ; restore non-volatile regs and return + + EXPORT vmJump +vmJump + mov lr, r0 + ldr r0, [sp] + ldr r1, [sp, #4] + mov sp, r2 + mov r8, r3 + bx lr + +CHECKPOINT_THREAD EQU 4 +CHECKPOINT_STACK EQU 24 + + EXPORT vmRun +vmRun + ; r0: function + ; r1: arguments + ; r2: checkpoint + stmfd sp!, {r4-r11, lr} + ; align stack + sub sp, sp, #12 + + str sp, [r2, #CHECKPOINT_STACK] + + mov r12, r0 + ldr r0, [r2, #CHECKPOINT_THREAD] + + blx r12 + + EXPORT vmRun_returnAddress +vmRun_returnAddress + add sp, sp, #12 + ldmfd sp!, {r4-r11, lr} + bx lr + + EXPORT vmTrap +vmTrap + bkpt 3 + + END \ No newline at end of file diff --git a/sgx-jvm/avian/src/arm64.S b/sgx-jvm/avian/src/arm64.S new file mode 100644 index 0000000000..1941be3ea6 --- /dev/null +++ b/sgx-jvm/avian/src/arm64.S @@ -0,0 +1,148 @@ +/* arm.S: JNI gluecode for ARM + Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#include "avian/types.h" + +.text + +#define LOCAL(x) .L##x + +#ifdef __APPLE__ +# define GLOBAL(x) _##x +#else +# define GLOBAL(x) x +#endif + +.globl GLOBAL(vmNativeCall) +.align 2 +GLOBAL(vmNativeCall): + // arguments: + // x0 -> x19 : function + // w1 -> w20 : stackTotal + // x2 : memoryTable + // w3 : memoryCount + // x4 -> x21 : gprTable + // x5 -> x22 : vfpTable + // w6 -> w23 : returnType + + // allocate frame + stp x29, x30, [sp,#-64]! + mov x29, sp + + // save callee-saved register values so we can clobber them + stp x19, x20, [sp,#16] + stp x21, x22, [sp,#32] + str x23, [sp,#48] + + // move arguments into callee-saved registers + mov x19, x0 + mov w20, w1 + mov x21, x4 + mov x22, x5 + mov w23, w6 + + // setup stack arguments if necessary + sub sp, sp, w20, uxtw // allocate stack + mov x9, sp +LOCAL(loop): + cmp w3, wzr + b.eq LOCAL(populateGPRs) + ldr x0, [x2], #8 + str x0, [x9], #8 + sub w3, w3, #8 + b LOCAL(loop) + +LOCAL(populateGPRs): + cmp x21, xzr + b.eq LOCAL(populateVFPs) + ldp x0, x1, [x21] + ldp x2, x3, [x21,#16] + ldp x4, x5, [x21,#32] + ldp x6, x7, [x21,#48] + +LOCAL(populateVFPs): + cmp x22, xzr + b.eq LOCAL(doCall) + ldp d0, d1, [x22] + ldp d2, d3, [x22,#16] + ldp d4, d5, [x22,#32] + ldp d6, d7, [x22,#48] + +LOCAL(doCall): + blr x19 // call function + add sp, sp, w20, uxtw // deallocate stack + + cmp w23,#FLOAT_TYPE + b.ne LOCAL(double) + fmov w0,s0 + b LOCAL(exit) + +LOCAL(double): + cmp w23,#DOUBLE_TYPE + b.ne LOCAL(exit) + fmov x0,d0 + +LOCAL(exit): + ldp x19, x20, [sp,#16] + ldp x21, x22, [sp,#32] + ldr x23, [sp,#48] + ldp x29, x30, [sp],#64 + ret + +.globl GLOBAL(vmJump) +.align 2 +GLOBAL(vmJump): + mov x30, x0 + mov x0, x4 + mov x1, x5 + mov sp, x2 + mov x19, x3 + br x30 + +#define CHECKPOINT_THREAD 8 +#define CHECKPOINT_STACK 48 + +.globl GLOBAL(vmRun) +.align 2 +GLOBAL(vmRun): + // x0: function + // x1: arguments + // x2: checkpoint + + // allocate frame + stp x29, x30, [sp,#-96]! + mov x29, sp + + // save callee-saved register values + stp x19, x20, [sp,#16] + stp x21, x22, [sp,#32] + stp x23, x24, [sp,#48] + stp x25, x26, [sp,#64] + stp x27, x28, [sp,#80] + + mov x19, sp + str x19, [x2, #CHECKPOINT_STACK] + + mov x19, x0 + ldr x0, [x2, #CHECKPOINT_THREAD] + + blr x19 + +.globl GLOBAL(vmRun_returnAddress) +.align 2 +GLOBAL(vmRun_returnAddress): + ldp x19, x20, [sp,#16] + ldp x21, x22, [sp,#32] + ldp x23, x24, [sp,#48] + ldp x25, x26, [sp,#64] + ldp x27, x28, [sp,#80] + ldp x29, x30, [sp],#96 + br x30 diff --git a/sgx-jvm/avian/src/avian/alloc-vector.h b/sgx-jvm/avian/src/avian/alloc-vector.h new file mode 100644 index 0000000000..b1df61e31c --- /dev/null +++ b/sgx-jvm/avian/src/avian/alloc-vector.h @@ -0,0 +1,186 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#ifndef VECTOR_H +#define VECTOR_H + +#include + +#include +#include +#include +#include + +#undef max +#undef min + +namespace vm { + +class Vector { + public: + Vector(avian::util::Aborter* a, + avian::util::Alloc* allocator, + size_t minimumCapacity) + : a(a), + allocator(allocator), + data(0, 0), + position(0), + minimumCapacity(minimumCapacity) + { + } + + ~Vector() + { + dispose(); + } + + void dispose() + { + if (data.items and minimumCapacity > 0) { + allocator->free(data.items, data.count); + data.items = 0; + data.count = 0; + } + } + + void ensure(size_t space) + { + if (position + space > data.count) { + assertT(a, minimumCapacity > 0); + + size_t newCapacity = avian::util::max( + position + space, avian::util::max(minimumCapacity, data.count * 2)); + if (data.begin()) { + data.resize(allocator, newCapacity); + } else { + data = avian::util::Slice::alloc(allocator, newCapacity); + } + } + } + + void get(size_t offset, void* dst, size_t size) + { + assertT(a, offset + size <= position); + memcpy(dst, data.begin() + offset, size); + } + + void set(size_t offset, const void* src, size_t size) + { + assertT(a, offset + size <= position); + memcpy(data.begin() + offset, src, size); + } + + void pop(void* dst, size_t size) + { + get(position - size, dst, size); + position -= size; + } + + void* allocate(size_t size) + { + ensure(size); + void* r = data.begin() + position; + position += size; + return r; + } + + void* append(const void* p, size_t size) + { + void* r = allocate(size); + memcpy(r, p, size); + return r; + } + + void append(uint8_t v) + { + append(&v, 1); + } + + void append2(uint16_t v) + { + append(&v, 2); + } + + void append4(uint32_t v) + { + append(&v, 4); + } + + void appendTargetAddress(target_uintptr_t v) + { + append(&v, TargetBytesPerWord); + } + + void appendAddress(uintptr_t v) + { + append(&v, BytesPerWord); + } + + void appendAddress(void* v) + { + append(&v, BytesPerWord); + } + + void set2(size_t offset, uint16_t v) + { + assertT(a, offset <= position - 2); + memcpy(data.begin() + offset, &v, 2); + } + + size_t get(size_t offset) + { + uint8_t v; + get(offset, &v, 1); + return v; + } + + size_t get2(size_t offset) + { + uint16_t v; + get(offset, &v, 2); + return v; + } + + size_t get4(size_t offset) + { + uint32_t v; + get(offset, &v, 4); + return v; + } + + uintptr_t getAddress(size_t offset) + { + uintptr_t v; + get(offset, &v, BytesPerWord); + return v; + } + + size_t length() + { + return position; + } + + template + T* peek(size_t offset) + { + assertT(a, offset + sizeof(T) <= position); + return reinterpret_cast(data.begin() + offset); + } + + avian::util::Aborter* a; + avian::util::Alloc* allocator; + avian::util::Slice data; + size_t position; + size_t minimumCapacity; +}; + +} // namespace vm + +#endif // VECTOR_H diff --git a/sgx-jvm/avian/src/avian/append.h b/sgx-jvm/avian/src/avian/append.h new file mode 100644 index 0000000000..5ea19bbfeb --- /dev/null +++ b/sgx-jvm/avian/src/avian/append.h @@ -0,0 +1,56 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#ifndef APPEND_H +#define APPEND_H + +#include +#include + +namespace vm { + +inline const char* append(avian::util::AllocOnly* allocator, + const char* a, + const char* b, + const char* c) +{ + unsigned al = strlen(a); + unsigned bl = strlen(b); + unsigned cl = strlen(c); + char* p = static_cast(allocator->allocate((al + bl + cl) + 1)); + memcpy(p, a, al); + memcpy(p + al, b, bl); + memcpy(p + al + bl, c, cl + 1); + return p; +} + +inline const char* append(avian::util::AllocOnly* allocator, + const char* a, + const char* b) +{ + unsigned al = strlen(a); + unsigned bl = strlen(b); + char* p = static_cast(allocator->allocate((al + bl) + 1)); + memcpy(p, a, al); + memcpy(p + al, b, bl + 1); + return p; +} + +inline const char* copy(avian::util::AllocOnly* allocator, const char* a) +{ + unsigned al = strlen(a); + char* p = static_cast(allocator->allocate(al + 1)); + memcpy(p, a, al + 1); + return p; +} + +} // namespace vm + +#endif // APPEND_H diff --git a/sgx-jvm/avian/src/avian/arch.h b/sgx-jvm/avian/src/avian/arch.h new file mode 100644 index 0000000000..0328d4124f --- /dev/null +++ b/sgx-jvm/avian/src/avian/arch.h @@ -0,0 +1,52 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#ifndef ARCH_H +#define ARCH_H + +#ifdef _MSC_VER +#include "windows.h" +#pragma push_macro("assert") +#include "intrin.h" +#pragma pop_macro("assert") +#undef interface +#endif + +#include "avian/common.h" + +extern "C" void NO_RETURN vmJump(void* address, + void* frame, + void* stack, + void* thread, + uintptr_t returnLow, + uintptr_t returnHigh); + +namespace vm { + +inline void compileTimeMemoryBarrier() +{ +#ifdef _MSC_VER + _ReadWriteBarrier(); +#else + __asm__ __volatile__("" : : : "memory"); +#endif +} + +} // namespace vm + +#if (defined ARCH_x86_32) || (defined ARCH_x86_64) +#include "x86.h" +#elif (defined ARCH_arm) || (defined ARCH_arm64) +#include "arm.h" +#else +#error unsupported architecture +#endif + +#endif // ARCH_H diff --git a/sgx-jvm/avian/src/avian/arm.h b/sgx-jvm/avian/src/avian/arm.h new file mode 100644 index 0000000000..4a0797207b --- /dev/null +++ b/sgx-jvm/avian/src/avian/arm.h @@ -0,0 +1,403 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#ifndef ARM_H +#define ARM_H + +#include "avian/types.h" +#include "avian/common.h" +#include + +#ifdef __APPLE__ +#include "libkern/OSAtomic.h" +#include "libkern/OSCacheControl.h" +#include "mach/mach_types.h" +#include "mach/thread_act.h" +#include "mach/thread_status.h" + +#define THREAD_STATE ARM_THREAD_STATE +#define THREAD_STATE_TYPE arm_thread_state_t +#define THREAD_STATE_COUNT ARM_THREAD_STATE_COUNT + +#if __DARWIN_UNIX03 && defined(_STRUCT_ARM_EXCEPTION_STATE) +#define FIELD(x) __##x +#else +#define FIELD(x) x +#endif + +#define THREAD_STATE_IP(state) ((state).FIELD(pc)) +#define THREAD_STATE_STACK(state) ((state).FIELD(sp)) +#if (defined __APPLE__) && (defined ARCH_arm64) +#define THREAD_STATE_THREAD(state) ((state).FIELD(x[19])) +#else +#define THREAD_STATE_THREAD(state) ((state).FIELD(r[8])) +#endif +#define THREAD_STATE_LINK(state) ((state).FIELD(lr)) + +#define IP_REGISTER(context) THREAD_STATE_IP(context->uc_mcontext->FIELD(ss)) +#define STACK_REGISTER(context) \ + THREAD_STATE_STACK(context->uc_mcontext->FIELD(ss)) +#define THREAD_REGISTER(context) \ + THREAD_STATE_THREAD(context->uc_mcontext->FIELD(ss)) +#define LINK_REGISTER(context) \ + THREAD_STATE_LINK(context->uc_mcontext->FIELD(ss)) +#elif(defined __QNX__) +#include "arm/smpxchg.h" +#include "sys/mman.h" + +#define IP_REGISTER(context) (context->uc_mcontext.cpu.gpr[ARM_REG_PC]) +#define STACK_REGISTER(context) (context->uc_mcontext.cpu.gpr[ARM_REG_SP]) +#define THREAD_REGISTER(context) (context->uc_mcontext.cpu.gpr[ARM_REG_IP]) +#define LINK_REGISTER(context) (context->uc_mcontext.cpu.gpr[ARM_REG_LR]) +#else +#ifdef ARCH_arm +#define IP_REGISTER(context) (context->uc_mcontext.arm_pc) +#define STACK_REGISTER(context) (context->uc_mcontext.arm_sp) +#define THREAD_REGISTER(context) (context->uc_mcontext.arm_ip) +#define LINK_REGISTER(context) (context->uc_mcontext.arm_lr) +#else +#define IP_REGISTER(context) (context->uc_mcontext.pc) +#define STACK_REGISTER(context) (context->uc_mcontext.sp) +#define THREAD_REGISTER(context) (context->uc_mcontext.regs[19]) +#define LINK_REGISTER(context) (context->uc_mcontext.regs[30]) +#endif +#endif + +#define VA_LIST(x) (&(x)) + +extern "C" uint64_t vmNativeCall(void* function, + unsigned stackTotal, + void* memoryTable, + unsigned memoryCount, + void* gprTable, + void* vfpTable, + unsigned returnType); + +namespace vm { + +inline void trap() +{ +#ifdef _MSC_VER + __debugbreak(); +#else + asm("brk 0"); +#endif +} + +// todo: determine the minimal operation types and domains needed to +// implement the following barriers (see +// http://community.arm.com/groups/processors/blog/2011/10/19/memory-access-ordering-part-3--memory-access-ordering-in-the-arm-architecture). +// For now, we just use DMB SY as a conservative but not necessarily +// performant choice. + +#ifndef _MSC_VER +inline void memoryBarrier() +{ +#ifdef __APPLE__ + OSMemoryBarrier(); +#elif(__GNUC__ >= 4) && (__GNUC_MINOR__ >= 1) + return __sync_synchronize(); +#elif(!defined AVIAN_ASSUME_ARMV6) + __asm__ __volatile__("dmb" : : : "memory"); +#else + __asm__ __volatile__("" : : : "memory"); +#endif +} +#endif + +inline void storeStoreMemoryBarrier() +{ +#ifdef _MSC_VER + _ReadWriteBarrier(); +#else + memoryBarrier(); +#endif +} + +inline void storeLoadMemoryBarrier() +{ +#ifdef _MSC_VER + MemoryBarrier(); +#else + memoryBarrier(); +#endif +} + +inline void loadMemoryBarrier() +{ +#ifdef _MSC_VER + _ReadWriteBarrier(); +#else + memoryBarrier(); +#endif +} + +#if !defined(AVIAN_AOT_ONLY) + +#if defined(__ANDROID__) || defined(__linux__) +// http://code.google.com/p/android/issues/detail?id=1803 +extern "C" void __clear_cache(void* beg __attribute__((__unused__)), + void* end __attribute__((__unused__))); +#endif +inline void syncInstructionCache(const void* start, unsigned size) +{ +#ifdef __APPLE__ + sys_icache_invalidate(const_cast(start), size); +#elif(defined __QNX__) + msync(const_cast(start), size, MS_INVALIDATE_ICACHE); +#else + __clear_cache( + const_cast(start), + const_cast(static_cast(start) + size)); +#endif +} + +#endif // AVIAN_AOT_ONLY + +#ifndef __APPLE__ +typedef int(__kernel_cmpxchg_t)(int oldval, int newval, int* ptr); +#define __kernel_cmpxchg (*(__kernel_cmpxchg_t*)0xffff0fc0) +#endif + +inline bool atomicCompareAndSwap32(uint32_t* p, uint32_t old, uint32_t new_) +{ +#ifdef __APPLE__ + return OSAtomicCompareAndSwap32Barrier( + old, new_, reinterpret_cast(p)); +#elif(defined __QNX__) + return old == _smp_cmpxchg(p, old, new_); +#elif (defined ARCH_arm64) + return __sync_bool_compare_and_swap(p, old, new_); +#else + int r = __kernel_cmpxchg( + static_cast(old), static_cast(new_), reinterpret_cast(p)); + return (!r ? true : false); +#endif +} + +#ifdef ARCH_arm64 +inline bool atomicCompareAndSwap64(uint64_t* p, uint64_t old, uint64_t new_) +{ + return __sync_bool_compare_and_swap(p, old, new_); +} + +inline bool atomicCompareAndSwap(uintptr_t* p, uintptr_t old, uintptr_t new_) +{ + return atomicCompareAndSwap64(reinterpret_cast(p), old, new_); +} +#else +inline bool atomicCompareAndSwap(uintptr_t* p, uintptr_t old, uintptr_t new_) +{ + return atomicCompareAndSwap32(reinterpret_cast(p), old, new_); +} +#endif + +#if (defined __APPLE__) && (defined ARCH_arm64) +const bool AppleARM64 = true; +#else +const bool AppleARM64 = false; +#endif + +inline void advance(unsigned* stackIndex, + unsigned* stackSubIndex, + unsigned newStackSubIndex) +{ + if (AppleARM64) { + if (newStackSubIndex == BytesPerWord) { + *stackSubIndex = 0; + ++(*stackIndex); + } else { + *stackSubIndex = newStackSubIndex; + } + } +} + +inline void push(uint8_t type, + uintptr_t* stack, + unsigned* stackIndex, + unsigned* stackSubIndex, + uintptr_t argument) +{ + if (AppleARM64) { + // See + // https://developer.apple.com/library/ios/documentation/Xcode/Conceptual/iPhoneOSABIReference/Articles/ARM64FunctionCallingConventions.html + // for how Apple diverges from the generic ARM64 ABI on iOS. + // Specifically, arguments passed on the stack are aligned to + // their natural alignment rather than 8. + switch (type) { + case INT8_TYPE: + reinterpret_cast(stack + *stackIndex)[*stackSubIndex] = argument; + advance(stackIndex, stackSubIndex, *stackSubIndex + 1); + break; + + case INT16_TYPE: + advance(stackIndex, stackSubIndex, pad(*stackSubIndex, 2)); + reinterpret_cast(stack + *stackIndex)[*stackSubIndex / 2] + = argument; + advance(stackIndex, stackSubIndex, *stackSubIndex + 2); + break; + + case INT32_TYPE: + case FLOAT_TYPE: + advance(stackIndex, stackSubIndex, pad(*stackSubIndex, 4)); + reinterpret_cast(stack + *stackIndex)[*stackSubIndex / 4] + = argument; + advance(stackIndex, stackSubIndex, *stackSubIndex + 4); + break; + + case POINTER_TYPE: + advance(stackIndex, stackSubIndex, pad(*stackSubIndex)); + stack[(*stackIndex)++] = argument; + break; + + default: + abort(); + } + } else { + stack[(*stackIndex)++] = argument; + } +} + +inline uint64_t dynamicCall(void* function, + uintptr_t* arguments, + uint8_t* argumentTypes, + unsigned argumentCount, + unsigned argumentsSize UNUSED, + unsigned returnType) +{ +#if (defined __APPLE__) || (defined ARCH_arm64) + const unsigned Alignment = 1; +#else + const unsigned Alignment = 2; +#endif + + const unsigned GprCount = BytesPerWord; + uintptr_t gprTable[GprCount]; + unsigned gprIndex = 0; + + const unsigned VfpCount = BytesPerWord == 8 ? 8 : 16; + uintptr_t vfpTable[VfpCount]; + unsigned vfpIndex = 0; + unsigned vfpBackfillIndex UNUSED = 0; + + RUNTIME_ARRAY(uintptr_t, + stack, + (argumentCount * 8) + / BytesPerWord); // is > argumentSize to account for padding + unsigned stackIndex = 0; + unsigned stackSubIndex = 0; + + unsigned ai = 0; + for (unsigned ati = 0; ati < argumentCount; ++ati) { + switch (argumentTypes[ati]) { + case DOUBLE_TYPE: +#if (defined __ARM_PCS_VFP) || (defined ARCH_arm64) + { + if (vfpIndex + Alignment <= VfpCount) { + if (vfpIndex % Alignment) { + vfpBackfillIndex = vfpIndex; + ++vfpIndex; + } + + memcpy(vfpTable + vfpIndex, arguments + ai, 8); + vfpIndex += 8 / BytesPerWord; + } else { + advance(&stackIndex, &stackSubIndex, pad(stackSubIndex)); + vfpIndex = VfpCount; + if (stackIndex % Alignment) { + ++stackIndex; + } + + memcpy(RUNTIME_ARRAY_BODY(stack) + stackIndex, arguments + ai, 8); + stackIndex += 8 / BytesPerWord; + } + ai += 8 / BytesPerWord; + } break; + + case FLOAT_TYPE: + if (vfpBackfillIndex) { + vfpTable[vfpBackfillIndex] = arguments[ai]; + vfpBackfillIndex = 0; + } else if (vfpIndex < VfpCount) { + vfpTable[vfpIndex++] = arguments[ai]; + } else { + push(argumentTypes[ati], + RUNTIME_ARRAY_BODY(stack), + &stackIndex, + &stackSubIndex, + arguments[ai]); + } + ++ai; + break; +#endif + case INT64_TYPE: { + if (gprIndex + Alignment <= GprCount) { // pass argument in register(s) + if (Alignment == 1 and BytesPerWord < 8 + and gprIndex + Alignment == GprCount) { + gprTable[gprIndex++] = arguments[ai]; + RUNTIME_ARRAY_BODY(stack)[stackIndex++] = arguments[ai + 1]; + } else { + if (gprIndex % Alignment) { + ++gprIndex; + } + + memcpy(gprTable + gprIndex, arguments + ai, 8); + gprIndex += 8 / BytesPerWord; + } + } else { // pass argument on stack + advance(&stackIndex, &stackSubIndex, pad(stackSubIndex)); + gprIndex = GprCount; + if (stackIndex % Alignment) { + ++stackIndex; + } + + memcpy(RUNTIME_ARRAY_BODY(stack) + stackIndex, arguments + ai, 8); + stackIndex += 8 / BytesPerWord; + } + ai += 8 / BytesPerWord; + } break; + + default: { + if (gprIndex < GprCount) { + gprTable[gprIndex++] = arguments[ai]; + } else { + push(argumentTypes[ati], + RUNTIME_ARRAY_BODY(stack), + &stackIndex, + &stackSubIndex, + arguments[ai]); + } + ++ai; + } break; + } + } + + if (gprIndex < GprCount) { // pad since assembly loads all GPRs + memset(gprTable + gprIndex, 0, (GprCount - gprIndex) * 4); + gprIndex = GprCount; + } + if (vfpIndex < VfpCount) { + memset(vfpTable + vfpIndex, 0, (VfpCount - vfpIndex) * 4); + vfpIndex = VfpCount; + } + + unsigned stackSize = pad(stackIndex * BytesPerWord + stackSubIndex, 16); + return vmNativeCall(function, + stackSize, + RUNTIME_ARRAY_BODY(stack), + pad(stackIndex * BytesPerWord + stackSubIndex, BytesPerWord), + (gprIndex ? gprTable : 0), + (vfpIndex ? vfpTable : 0), + returnType); +} + +} // namespace vm + +#endif // ARM_H diff --git a/sgx-jvm/avian/src/avian/bootimage.h b/sgx-jvm/avian/src/avian/bootimage.h new file mode 100644 index 0000000000..d14755f8b3 --- /dev/null +++ b/sgx-jvm/avian/src/avian/bootimage.h @@ -0,0 +1,81 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#ifndef BOOTIMAGE_H +#define BOOTIMAGE_H + +#include "avian/common.h" +#include "java-common.h" +#include "avian/target.h" +#include "avian/machine.h" + +#include + +namespace vm { + +class BootImage { + public: + class Thunk { + public: + Thunk() : start(0), frameSavedOffset(0), length(0) + { + } + + Thunk(uint32_t start, uint32_t frameSavedOffset, uint32_t length) + : start(start), frameSavedOffset(frameSavedOffset), length(length) + { + } + + uint32_t start; + uint32_t frameSavedOffset; + uint32_t length; + } PACKED; + + class ThunkCollection { + public: +#define THUNK_FIELD(name) Thunk name; +#include "bootimage-fields.cpp" +#undef THUNK_FIELD + } PACKED; + + static const uint32_t Magic = 0x22377322; + +#define FIELD(name) uint32_t name; +#include "bootimage-fields.cpp" +#undef FIELD + + ThunkCollection thunks; +} PACKED; + +class GcField; +class GcClass; + +class OffsetResolver { + public: + virtual unsigned fieldOffset(Thread*, GcField*) = 0; + + virtual void addClass(Thread*, GcClass*, const uint8_t*, size_t) = 0; +}; + +#define NAME(x) Target##x +#define LABEL(x) target_##x +#include "bootimage-template.cpp" +#undef LABEL +#undef NAME + +#define NAME(x) x +#define LABEL(x) x +#include "bootimage-template.cpp" +#undef LABEL +#undef NAME + +} // namespace vm + +#endif // BOOTIMAGE_H diff --git a/sgx-jvm/avian/src/avian/classpath-common.h b/sgx-jvm/avian/src/avian/classpath-common.h new file mode 100644 index 0000000000..85815cbb76 --- /dev/null +++ b/sgx-jvm/avian/src/avian/classpath-common.h @@ -0,0 +1,864 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#ifndef CLASSPATH_COMMON_H +#define CLASSPATH_COMMON_H + +#include +#include +#include + +using namespace avian::util; + +namespace vm { + +object getTrace(Thread* t, unsigned skipCount) +{ + class Visitor : public Processor::StackVisitor { + public: + Visitor(Thread* t, int skipCount) : t(t), trace(0), skipCount(skipCount) + { + } + + virtual bool visit(Processor::StackWalker* walker) + { + if (skipCount == 0) { + GcMethod* method = walker->method(); + if (isAssignableFrom(t, type(t, GcThrowable::Type), method->class_()) + and vm::strcmp(reinterpret_cast(""), + method->name()->body().begin()) == 0) { + return true; + } else { + trace = makeTrace(t, walker); + return false; + } + } else { + --skipCount; + return true; + } + } + + Thread* t; + object trace; + unsigned skipCount; + } v(t, skipCount); + + t->m->processor->walkStack(t, &v); + + if (v.trace == 0) + v.trace = makeObjectArray(t, 0); + + return v.trace; +} + +bool compatibleArrayTypes(Thread* t UNUSED, GcClass* a, GcClass* b) +{ + return a->arrayElementSize() and b->arrayElementSize() + and (a == b or (not((a->vmFlags() & PrimitiveFlag) + or (b->vmFlags() & PrimitiveFlag)))); +} + +void arrayCopy(Thread* t, + object src, + int32_t srcOffset, + object dst, + int32_t dstOffset, + int32_t length) +{ + if (LIKELY(src and dst)) { + if (LIKELY(compatibleArrayTypes( + t, objectClass(t, src), objectClass(t, dst)))) { + unsigned elementSize = objectClass(t, src)->arrayElementSize(); + + if (LIKELY(elementSize)) { + intptr_t sl = fieldAtOffset(src, BytesPerWord); + intptr_t dl = fieldAtOffset(dst, BytesPerWord); + if (LIKELY(length > 0)) { + if (LIKELY(srcOffset >= 0 and srcOffset + length <= sl + and dstOffset >= 0 and dstOffset + length <= dl)) { + uint8_t* sbody = &fieldAtOffset(src, ArrayBody); + uint8_t* dbody = &fieldAtOffset(dst, ArrayBody); + if (src == dst) { + memmove(dbody + (dstOffset * elementSize), + sbody + (srcOffset * elementSize), + length * elementSize); + } else { + memcpy(dbody + (dstOffset * elementSize), + sbody + (srcOffset * elementSize), + length * elementSize); + } + + if (objectClass(t, dst)->objectMask()) { + mark(t, dst, ArrayBody + (dstOffset * BytesPerWord), length); + } + + return; + } else { + throwNew(t, GcIndexOutOfBoundsException::Type); + } + } else { + return; + } + } + } + } else { + throwNew(t, GcNullPointerException::Type); + return; + } + + throwNew(t, GcArrayStoreException::Type); +} + +void runOnLoadIfFound(Thread* t, System::Library* library) +{ + void* p = library->resolve("JNI_OnLoad"); + +#ifdef PLATFORM_WINDOWS + if (p == 0) { + p = library->resolve("_JNI_OnLoad@8"); + if (p == 0) { + p = library->resolve("JNI_OnLoad@8"); + } + } +#endif + + if (p) { + jint(JNICALL * JNI_OnLoad)(Machine*, void*); + memcpy(&JNI_OnLoad, &p, sizeof(void*)); + JNI_OnLoad(t->m, 0); + } +} + +System::Library* loadLibrary(Thread* t, const char* name) +{ + ACQUIRE(t, t->m->classLock); + + System::Library* last = t->m->libraries; + for (System::Library* lib = t->m->libraries; lib; lib = lib->next()) { + if (lib->name() and ::strcmp(lib->name(), name) == 0) { + // already loaded + return lib; + } + last = lib; + } + + System::Library* lib; + if (t->m->system->success(t->m->system->load(&lib, name))) { + last->setNext(lib); + return lib; + } else { + return 0; + } +} + +System::Library* loadLibrary(Thread* t, + const char* path, + const char* name, + bool mapName, + bool runOnLoad, + bool throw_ = true) +{ + ACQUIRE(t, t->m->classLock); + + char* mappedName; + unsigned nameLength = strlen(name); + if (mapName) { + const char* builtins = findProperty(t, "avian.builtins"); + if (builtins) { + const char* s = builtins; + while (*s) { + if (::strncmp(s, name, nameLength) == 0 + and (s[nameLength] == ',' or s[nameLength] == 0)) { + // library is built in to this executable + if (runOnLoad and not t->m->triedBuiltinOnLoad) { + t->m->triedBuiltinOnLoad = true; + // todo: release the classLock before calling this to + // avoid the possibility of deadlock: + runOnLoadIfFound(t, t->m->libraries); + } + return t->m->libraries; + } else { + while (*s and *s != ',') + ++s; + if (*s) + ++s; + } + } + } + + const char* prefix = t->m->system->libraryPrefix(); + const char* suffix = t->m->system->librarySuffix(); + unsigned mappedNameLength = nameLength + strlen(prefix) + strlen(suffix); + + mappedName = static_cast(t->m->heap->allocate(mappedNameLength + 1)); + + snprintf(mappedName, mappedNameLength + 1, "%s%s%s", prefix, name, suffix); + + name = mappedName; + nameLength = mappedNameLength; + } else { + mappedName = 0; + } + + THREAD_RESOURCE2(t, char*, mappedName, unsigned, nameLength, if (mappedName) { + t->m->heap->free(mappedName, nameLength + 1); + }); + + System::Library* lib = 0; + for (Tokenizer tokenizer(path, t->m->system->pathSeparator()); + tokenizer.hasMore();) { + String token(tokenizer.next()); + + unsigned fullNameLength = token.length + 1 + nameLength; + THREAD_RUNTIME_ARRAY(t, char, fullName, fullNameLength + 1); + + snprintf(RUNTIME_ARRAY_BODY(fullName), + fullNameLength + 1, + "%.*s/%s", + token.length, + token.text, + name); + + lib = loadLibrary(t, RUNTIME_ARRAY_BODY(fullName)); + if (lib) + break; + } + + if (lib == 0) { + lib = loadLibrary(t, name); + } + + if (lib) { + if (runOnLoad) { + runOnLoadIfFound(t, lib); + } + } else if (throw_) { + throwNew(t, + GcUnsatisfiedLinkError::Type, + "library not found in %s: %s", + path, + name); + } + + return lib; +} + +GcStackTraceElement* makeStackTraceElement(Thread* t, GcTraceElement* e) +{ + PROTECT(t, e); + + GcMethod* method = cast(t, e->method()); + PROTECT(t, method); + + GcByteArray* class_name = method->class_()->name(); + PROTECT(t, class_name); + + THREAD_RUNTIME_ARRAY(t, char, s, class_name->length()); + replace('/', + '.', + RUNTIME_ARRAY_BODY(s), + reinterpret_cast(class_name->body().begin())); + GcString* class_name_string = makeString(t, "%s", RUNTIME_ARRAY_BODY(s)); + PROTECT(t, class_name_string); + + GcByteArray* method_name = method->name(); + PROTECT(t, method_name); + + GcString* method_name_string = t->m->classpath->makeString( + t, method_name, 0, method_name->length() - 1); + PROTECT(t, method_name_string); + + unsigned line = t->m->processor->lineNumber(t, method, e->ip()); + + GcByteArray* file = method->class_()->sourceFile(); + GcString* file_string + = file ? t->m->classpath->makeString(t, file, 0, file->length() - 1) : 0; + + return makeStackTraceElement( + t, class_name_string, method_name_string, file_string, line); +} + +GcObject* translateInvokeResult(Thread* t, unsigned returnCode, object o) +{ + switch (returnCode) { + case ByteField: + return makeByte(t, cast(t, o)->value()); + + case BooleanField: + return makeBoolean(t, cast(t, o)->value() != 0); + + case CharField: + return makeChar(t, cast(t, o)->value()); + + case ShortField: + return makeShort(t, cast(t, o)->value()); + + case FloatField: + return makeFloat(t, cast(t, o)->value()); + + case IntField: + case LongField: + case ObjectField: + case VoidField: + return reinterpret_cast(o); + + case DoubleField: + return makeDouble(t, cast(t, o)->value()); + + default: + abort(t); + } +} + +GcClass* resolveClassBySpec(Thread* t, + GcClassLoader* loader, + const char* spec, + unsigned specLength) +{ + switch (*spec) { + case 'L': { + THREAD_RUNTIME_ARRAY(t, char, s, specLength - 1); + memcpy(RUNTIME_ARRAY_BODY(s), spec + 1, specLength - 2); + RUNTIME_ARRAY_BODY(s)[specLength - 2] = 0; + return resolveClass(t, loader, RUNTIME_ARRAY_BODY(s)); + } + + case '[': { + THREAD_RUNTIME_ARRAY(t, char, s, specLength + 1); + memcpy(RUNTIME_ARRAY_BODY(s), spec, specLength); + RUNTIME_ARRAY_BODY(s)[specLength] = 0; + return resolveClass(t, loader, RUNTIME_ARRAY_BODY(s)); + } + + default: + return primitiveClass(t, *spec); + } +} + +GcJclass* resolveJType(Thread* t, + GcClassLoader* loader, + const char* spec, + unsigned specLength) +{ + return getJClass(t, resolveClassBySpec(t, loader, spec, specLength)); +} + +GcPair* resolveParameterTypes(Thread* t, + GcClassLoader* loader, + GcByteArray* spec, + unsigned* parameterCount, + unsigned* returnTypeSpec) +{ + PROTECT(t, loader); + PROTECT(t, spec); + + GcPair* list = 0; + PROTECT(t, list); + + unsigned offset = 1; + unsigned count = 0; + while (spec->body()[offset] != ')') { + switch (spec->body()[offset]) { + case 'L': { + unsigned start = offset; + ++offset; + while (spec->body()[offset] != ';') + ++offset; + ++offset; + + GcClass* type + = resolveClassBySpec(t, + loader, + reinterpret_cast(&spec->body()[start]), + offset - start); + + list = makePair(t, type, list); + + ++count; + } break; + + case '[': { + unsigned start = offset; + while (spec->body()[offset] == '[') + ++offset; + switch (spec->body()[offset]) { + case 'L': + ++offset; + while (spec->body()[offset] != ';') + ++offset; + ++offset; + break; + + default: + ++offset; + break; + } + + GcClass* type + = resolveClassBySpec(t, + loader, + reinterpret_cast(&spec->body()[start]), + offset - start); + + list = makePair(t, type, list); + ++count; + } break; + + default: + list = makePair(t, primitiveClass(t, spec->body()[offset]), list); + ++offset; + ++count; + break; + } + } + + *parameterCount = count; + *returnTypeSpec = offset + 1; + return list; +} + +object resolveParameterJTypes(Thread* t, + GcClassLoader* loader, + GcByteArray* spec, + unsigned* parameterCount, + unsigned* returnTypeSpec) +{ + GcPair* list + = resolveParameterTypes(t, loader, spec, parameterCount, returnTypeSpec); + + PROTECT(t, list); + + object array = makeObjectArray(t, type(t, GcJclass::Type), *parameterCount); + PROTECT(t, array); + + for (int i = *parameterCount - 1; i >= 0; --i) { + object c = getJClass(t, cast(t, list->first())); + reinterpret_cast(array)->setBodyElement(t, i, c); + list = cast(t, list->second()); + } + + return array; +} + +object resolveExceptionJTypes(Thread* t, + GcClassLoader* loader, + GcMethodAddendum* addendum) +{ + if (addendum == 0 or addendum->exceptionTable() == 0) { + return makeObjectArray(t, type(t, GcJclass::Type), 0); + } + + PROTECT(t, loader); + PROTECT(t, addendum); + + GcShortArray* exceptionTable + = cast(t, addendum->exceptionTable()); + PROTECT(t, exceptionTable); + + object array + = makeObjectArray(t, type(t, GcJclass::Type), exceptionTable->length()); + PROTECT(t, array); + + for (unsigned i = 0; i < exceptionTable->length(); ++i) { + uint16_t index = exceptionTable->body()[i] - 1; + + object o = singletonObject(t, addendum->pool()->as(t), index); + + if (objectClass(t, o) == type(t, GcReference::Type)) { + o = resolveClass(t, loader, cast(t, o)->name()); + + addendum->pool()->setBodyElement( + t, index, reinterpret_cast(o)); + } + + o = getJClass(t, cast(t, o)); + + reinterpret_cast(array)->setBodyElement(t, i, o); + } + + return array; +} + +object invoke(Thread* t, GcMethod* method, object instance, object args) +{ + PROTECT(t, method); + PROTECT(t, instance); + PROTECT(t, args); + + if (method->flags() & ACC_STATIC) { + instance = 0; + } + + if ((args == 0 ? 0 : objectArrayLength(t, args)) + != method->parameterCount()) { + throwNew(t, GcIllegalArgumentException::Type); + } + + if (method->parameterCount()) { + unsigned specLength = method->spec()->length(); + THREAD_RUNTIME_ARRAY(t, char, spec, specLength); + memcpy( + RUNTIME_ARRAY_BODY(spec), method->spec()->body().begin(), specLength); + unsigned i = 0; + for (MethodSpecIterator it(t, RUNTIME_ARRAY_BODY(spec)); it.hasNext();) { + GcClass* type; + bool objectType = false; + const char* p = it.next(); + switch (*p) { + case 'Z': + type = vm::type(t, GcBoolean::Type); + break; + case 'B': + type = vm::type(t, GcByte::Type); + break; + case 'S': + type = vm::type(t, GcShort::Type); + break; + case 'C': + type = vm::type(t, GcChar::Type); + break; + case 'I': + type = vm::type(t, GcInt::Type); + break; + case 'F': + type = vm::type(t, GcFloat::Type); + break; + case 'J': + type = vm::type(t, GcLong::Type); + break; + case 'D': + type = vm::type(t, GcDouble::Type); + break; + + case 'L': + case '[': { + objectType = true; + unsigned nameLength; + if (*p == 'L') { + ++p; + nameLength = it.s - p; + } else { + nameLength = (it.s - p) + 1; + } + THREAD_RUNTIME_ARRAY(t, char, name, nameLength); + memcpy(RUNTIME_ARRAY_BODY(name), p, nameLength - 1); + RUNTIME_ARRAY_BODY(name)[nameLength - 1] = 0; + type = resolveClass( + t, method->class_()->loader(), RUNTIME_ARRAY_BODY(name)); + } break; + + default: + abort(); + } + + object arg = objectArrayBody(t, args, i++); + if ((arg == 0 and (not objectType)) + or (arg and (not instanceOf(t, type, arg)))) { + if (false) { + fprintf(stderr, + "%s is not a %s\n", + arg ? objectClass(t, arg)->name()->body().begin() + : reinterpret_cast(""), + type->name()->body().begin()); + } + + throwNew(t, GcIllegalArgumentException::Type); + } + } + } + + initClass(t, method->class_()); + + unsigned returnCode = method->returnCode(); + + THREAD_RESOURCE0(t, { + if (t->exception) { + t->exception = makeThrowable( + t, GcInvocationTargetException::Type, 0, 0, t->exception); + + t->exception->as(t) + ->setTarget(t, t->exception->cause()); + } + }); + + object result; + if (args) { + result = t->m->processor->invokeArray(t, method, instance, args); + } else { + result = t->m->processor->invoke(t, method, instance); + } + + return translateInvokeResult(t, returnCode, result); +} + +// only safe to call during bootstrap when there's only one thread +// running: +void intercept(Thread* t, + GcClass* c, + const char* name, + const char* spec, + void* function, + bool updateRuntimeData) +{ + GcMethod* m = findMethodOrNull(t, c, name, spec); + if (m) { + PROTECT(t, m); + + if (updateRuntimeData) { + GcMethod* clone = methodClone(t, m); + + m->flags() |= ACC_NATIVE; + + // make clone private to prevent vtable updates at compilation + // time. Otherwise, our interception might be bypassed by calls + // through the vtable. + clone->flags() |= ACC_PRIVATE; + + GcNativeIntercept* native = makeNativeIntercept(t, function, true, clone); + + PROTECT(t, native); + + GcMethodRuntimeData* runtimeData = getMethodRuntimeData(t, m); + + runtimeData->setNative(t, native->as(t)); + } else { + m->flags() |= ACC_NATIVE; + } + } else { + // If we can't find the method, just ignore it, since ProGuard may + // have stripped it out as unused. Otherwise, the code below can + // be enabled for debugging purposes. + + if (false) { + fprintf(stderr, + "unable to find %s%s in %s\n", + name, + spec, + c->name()->body().begin()); + + abort(t); + } + } +} + +Finder* getFinder(Thread* t, const char* name, size_t nameLength) +{ + ACQUIRE(t, t->m->referenceLock); + + for (GcFinder* p = roots(t)->virtualFileFinders(); p; p = p->next()) { + if (p->name()->length() == nameLength + and strncmp(reinterpret_cast(p->name()->body().begin()), + name, + nameLength)) { + return static_cast(p->finder()); + } + } + + GcByteArray* n = makeByteArray(t, nameLength + 1); + memcpy(n->body().begin(), name, nameLength); + + void* p = t->m->libraries->resolve( + reinterpret_cast(n->body().begin())); + + if (p) { + uint8_t* (*function)(size_t*); + memcpy(&function, &p, BytesPerWord); + + size_t size = 0; + uint8_t* data = function(&size); + if (data) { + Finder* f = makeFinder(t->m->system, t->m->heap, data, size); + GcFinder* finder = makeFinder(t, f, n, roots(t)->virtualFileFinders()); + + roots(t)->setVirtualFileFinders(t, finder); + + return f; + } + } + + return 0; +} + +object getDeclaredClasses(Thread* t, GcClass* c, bool publicOnly) +{ + GcClassAddendum* addendum = c->addendum(); + if (addendum) { + GcArray* table = cast(t, addendum->innerClassTable()); + if (table) { + PROTECT(t, table); + + unsigned count = 0; + for (unsigned i = 0; i < table->length(); ++i) { + GcInnerClassReference* reference + = cast(t, table->body()[i]); + GcByteArray* outer = reference->outer(); + if (outer and byteArrayEqual(t, outer, c->name()) + and ((not publicOnly) or (reference->flags() & ACC_PUBLIC))) { + ++count; + } + } + + object result = makeObjectArray(t, type(t, GcJclass::Type), count); + PROTECT(t, result); + + for (unsigned i = 0; i < table->length(); ++i) { + GcInnerClassReference* reference + = cast(t, table->body()[i]); + GcByteArray* outer = reference->outer(); + if (outer and byteArrayEqual(t, outer, c->name()) + and ((not publicOnly) or (reference->flags() & ACC_PUBLIC))) { + object inner + = getJClass(t, resolveClass(t, c->loader(), reference->inner())); + + --count; + reinterpret_cast(result)->setBodyElement(t, count, inner); + } + } + + return result; + } + } + + return makeObjectArray(t, type(t, GcJclass::Type), 0); +} + +unsigned classModifiers(Thread* t, GcClass* c) +{ + GcClassAddendum* addendum = c->addendum(); + if (addendum) { + GcArray* table = cast(t, addendum->innerClassTable()); + if (table) { + for (unsigned i = 0; i < table->length(); ++i) { + GcInnerClassReference* reference + = cast(t, table->body()[i]); + if (0 == strcmp(c->name()->body().begin(), + reference->inner()->body().begin())) { + return reference->flags(); + } + } + } + } + + return c->flags(); +} + +object makeMethod(Thread* t, GcJclass* class_, int index) +{ + GcMethod* method = cast( + t, cast(t, class_->vmClass()->methodTable())->body()[index]); + PROTECT(t, method); + + GcClass* c + = resolveClass(t, roots(t)->bootLoader(), "java/lang/reflect/Method"); + PROTECT(t, c); + + object instance = makeNew(t, c); + PROTECT(t, instance); + + GcMethod* constructor = resolveMethod(t, c, "", "(Lavian/VMMethod;)V"); + + t->m->processor->invoke(t, constructor, instance, method); + + if (method->name()->body()[0] == '<') { + object oldInstance = instance; + + c = resolveClass( + t, roots(t)->bootLoader(), "java/lang/reflect/Constructor"); + + object instance = makeNew(t, c); + + GcMethod* constructor + = resolveMethod(t, c, "", "(Ljava/lang/Method;)V"); + + t->m->processor->invoke(t, constructor, instance, oldInstance); + } + + return instance; +} + +int64_t getPrimitive(Thread* t, object instance, int code, int offset) +{ + switch (code) { + case ByteField: + return fieldAtOffset(instance, offset); + case BooleanField: + return fieldAtOffset(instance, offset); + case CharField: + return fieldAtOffset(instance, offset); + case ShortField: + return fieldAtOffset(instance, offset); + case IntField: + return fieldAtOffset(instance, offset); + case LongField: + return fieldAtOffset(instance, offset); + case FloatField: + return fieldAtOffset(instance, offset); + case DoubleField: + return fieldAtOffset(instance, offset); + default: + abort(t); + } +} + +void setPrimitive(Thread* t, + object instance, + int code, + int offset, + int64_t value) +{ + switch (code) { + case ByteField: + fieldAtOffset(instance, offset) = static_cast(value); + break; + case BooleanField: + fieldAtOffset(instance, offset) = static_cast(value); + break; + case CharField: + fieldAtOffset(instance, offset) = static_cast(value); + break; + case ShortField: + fieldAtOffset(instance, offset) = static_cast(value); + break; + case IntField: + fieldAtOffset(instance, offset) = static_cast(value); + break; + case LongField: + fieldAtOffset(instance, offset) = static_cast(value); + break; + case FloatField: + fieldAtOffset(instance, offset) = static_cast(value); + break; + case DoubleField: + fieldAtOffset(instance, offset) = static_cast(value); + break; + default: + abort(t); + } +} + +int64_t invokeMethod(Thread* t, GcMethod* method, object instance, object args) +{ + THREAD_RESOURCE0(t, { + if (t->exception) { + GcThrowable* exception = t->exception; + t->exception = makeThrowable( + t, GcInvocationTargetException::Type, 0, 0, exception); + } + }); + + unsigned returnCode = method->returnCode(); + + return reinterpret_cast(translateInvokeResult( + t, returnCode, t->m->processor->invokeArray(t, method, instance, args))); +} + +} // namespace vm + +#endif // CLASSPATH_COMMON_H diff --git a/sgx-jvm/avian/src/avian/common.h b/sgx-jvm/avian/src/avian/common.h new file mode 100644 index 0000000000..fc837d6e88 --- /dev/null +++ b/sgx-jvm/avian/src/avian/common.h @@ -0,0 +1,497 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#ifndef AVIAN_COMMON_H +#define AVIAN_COMMON_H + +#ifndef __STDC_CONSTANT_MACROS +#define __STDC_CONSTANT_MACROS +#endif + +#ifndef __STDC_FORMAT_MACROS +#define __STDC_FORMAT_MACROS +#endif + +#include + +#include +#include +#include +#include +#include +#include +#include "avian/types.h" +#include + +#ifdef UNUSED +#undef UNUSED +#endif + +#ifdef _MSC_VER + +#include +#include + +#ifdef linux +#undef linux +#endif + +// don't complain about using 'this' in member initializers: +#pragma warning(disable : 4355) + +#define strncasecmp _strnicmp + +#define FP_UNDEF 2 + +#define not ! +#define or || +#define and && +#define xor ^ + +#define LIKELY(v) v +#define UNLIKELY(v) v + +#define UNUSED + +#define NO_RETURN __declspec(noreturn) + +#define PACKED + +#define PLATFORM_WINDOWS + +#ifdef _M_IX86 +typedef int32_t intptr_t; +typedef uint32_t uintptr_t; +#define ARCH_x86_32 +#define BYTES_PER_WORD 4 +#elif defined _M_X64 +typedef int64_t intptr_t; +typedef uint64_t uintptr_t; +#define ARCH_x86_64 +#define BYTES_PER_WORD 8 +#elif defined _M_ARM_FP +typedef int32_t intptr_t; +typedef uint32_t uintptr_t; +#define ARCH_arm +#define BYTES_PER_WORD 4 +#else +#error "unsupported architecture" +#endif + +namespace vm { + +typedef intptr_t intptr_alias_t; + +} // namespace vm + +#else // not _MSC_VER + +#include + +#define BYTES_PER_WORD __SIZEOF_POINTER__ + +#define LIKELY(v) __builtin_expect((v) != 0, true) +#define UNLIKELY(v) __builtin_expect((v) != 0, false) + +#define UNUSED __attribute__((unused)) + +#define NO_RETURN __attribute__((noreturn)) + +#define PACKED __attribute__((packed)) + +#ifdef __MINGW32__ +#define PLATFORM_WINDOWS +#endif + +#ifdef __i386__ +#define ARCH_x86_32 +#elif defined __x86_64__ +#define ARCH_x86_64 +#elif defined __arm__ +#define ARCH_arm +#elif defined __aarch64__ +#define ARCH_arm64 +#else +#error "unsupported architecture" +#endif + +namespace vm { + +typedef intptr_t __attribute__((__may_alias__)) intptr_alias_t; + +} // namespace vm + +#endif // not _MSC_VER + +#ifdef PLATFORM_WINDOWS +#define AVIAN_EXPORT __declspec(dllexport) +#define PATH_SEPARATOR ';' +#else // not PLATFORM_WINDOWS +#define AVIAN_EXPORT \ + __attribute__((visibility("default"))) __attribute__((used)) +#define PATH_SEPARATOR ':' +#endif // not PLATFORM_WINDOWS + +#ifdef PRId64 +#define LLD PRId64 +#define ULD PRIu64 +#define LD PRIdPTR +#define LX PRIxPTR +#else +#if (defined ARCH_x86_32) || (defined ARCH_arm) +#define LD "ld" +#if (defined _MSC_VER) || ((defined __MINGW32__) && __GNUC__ >= 4) +#if (__GNUC__ == 4 && __GNUC_MINOR__ <= 8) +#define LLD "I64d" +#else +#define LLD "lld" +#endif +#else +#define LLD "lld" +#endif +#ifdef __APPLE__ +#define ULD "lu" +#define LX "lx" +#else +#define LX "x" +#define ULD "u" +#endif +#elif defined ARCH_x86_64 +#define LD "ld" +#define LX "lx" +#if (defined _MSC_VER) || (defined __MINGW32__) +#if (__GNUC__ == 4 && __GNUC_MINOR__ <= 8) +#define LLD "I64d" +#define ULD "I64x" +#else +#define LLD "lld" +#define ULD "llu" +#endif +#else +#ifdef __APPLE__ +#define LLD "lld" +#else +#define LLD "ld" +#endif +#define ULD "lu" +#endif +#else +#error "Unsupported architecture" +#endif +#endif + +#ifdef PLATFORM_WINDOWS +#define SO_PREFIX "" +#else +#define SO_PREFIX "lib" +#endif + +#ifdef __APPLE__ +#define SO_SUFFIX ".dylib" +#elif defined PLATFORM_WINDOWS +#define SO_SUFFIX ".dll" +#else +#define SO_SUFFIX ".so" +#endif + +#define MACRO_XY(X, Y) X##Y +#define MACRO_MakeNameXY(FX, LINE) MACRO_XY(FX, LINE) +#define MAKE_NAME(FX) MACRO_MakeNameXY(FX, __LINE__) + +#define RESOURCE(type, name, release) \ + class MAKE_NAME(Resource_) { \ + public: \ + MAKE_NAME(Resource_)(type name) : name(name) \ + { \ + } \ + ~MAKE_NAME(Resource_)() \ + { \ + release; \ + } \ + \ + private: \ + type name; \ + } MAKE_NAME(resource_)(name); + +#ifdef _MSC_VER +#pragma warning(disable : 4291) +#endif + +namespace vm { + +inline intptr_alias_t& alias(void* p, unsigned offset) +{ + return *reinterpret_cast(static_cast(p) + offset); +} + +#ifdef _MSC_VER + +inline int vsnprintf(char* dst, size_t size, const char* format, va_list a) +{ + return vsnprintf_s(dst, size, _TRUNCATE, format, a); +} + +inline int snprintf(char* dst, size_t size, const char* format, ...) +{ + va_list a; + va_start(a, format); + int r = vsnprintf(dst, size, format, a); + va_end(a); + return r; +} + +inline FILE* fopen(const char* name, const char* mode) +{ + FILE* file; + if (fopen_s(&file, name, mode) == 0) { + return file; + } else { + return 0; + } +} + +#else // not _MSC_VER + +inline int vsnprintf(char* dst, size_t size, const char* format, va_list a) +{ + return ::vsnprintf(dst, size, format, a); +} + +inline int snprintf(char* dst, size_t size, const char* format, ...) +{ + va_list a; + va_start(a, format); + int r = vsnprintf(dst, size, format, a); + va_end(a); + return r; +} + +inline FILE* fopen(const char* name, const char* mode) +{ + return ::fopen(name, mode); +} + +#endif // not _MSC_VER + +const unsigned BytesPerWord = sizeof(uintptr_t); +const unsigned BitsPerWord = BytesPerWord * 8; + +const uintptr_t PointerMask = ((~static_cast(0)) / BytesPerWord) + * BytesPerWord; + +const unsigned LikelyPageSizeInBytes = 4 * 1024; + +inline unsigned pad(unsigned n, unsigned alignment) +{ + return (n + (alignment - 1)) & ~(alignment - 1); +} + +inline unsigned pad(unsigned n) +{ + return pad(n, BytesPerWord); +} + +inline uintptr_t padWord(uintptr_t n, uintptr_t alignment) +{ + return (n + (alignment - 1)) & ~(alignment - 1); +} + +inline uintptr_t padWord(uintptr_t n) +{ + return padWord(n, BytesPerWord); +} + +inline bool fitsInInt8(int64_t v) +{ + return v == static_cast(v); +} + +inline bool fitsInInt16(int64_t v) +{ + return v == static_cast(v); +} + +inline bool fitsInInt32(int64_t v) +{ + return v == static_cast(v); +} +template +inline unsigned wordOf(unsigned i) +{ + return i / (sizeof(T) * 8); +} + +inline unsigned wordOf(unsigned i) +{ + return wordOf(i); +} + +template +inline unsigned bitOf(unsigned i) +{ + return i % (sizeof(T) * 8); +} + +inline unsigned bitOf(unsigned i) +{ + return bitOf(i); +} + +template +inline unsigned indexOf(unsigned word, unsigned bit) +{ + return (word * (sizeof(T) * 8)) + bit; +} + +inline unsigned indexOf(unsigned word, unsigned bit) +{ + return indexOf(word, bit); +} + +template +inline void markBit(T* map, unsigned i) +{ + map[wordOf(i)] |= static_cast(1) << bitOf(i); +} + +template +inline void clearBit(T* map, unsigned i) +{ + map[wordOf(i)] &= ~(static_cast(1) << bitOf(i)); +} + +template +inline unsigned getBit(T* map, unsigned i) +{ + return (map[wordOf(i)] & (static_cast(1) << bitOf(i))) + >> bitOf(i); +} + +// todo: the following (clearBits, setBits, and getBits) could be made +// more efficient by operating on a word at a time instead of a bit at +// a time: + +template +inline void clearBits(T* map, unsigned bitsPerRecord, unsigned index) +{ + for (unsigned i = index, limit = index + bitsPerRecord; i < limit; ++i) { + clearBit(map, i); + } +} + +template +inline void setBits(T* map, unsigned bitsPerRecord, int index, unsigned v) +{ + for (int i = index + bitsPerRecord - 1; i >= index; --i) { + if (v & 1) + markBit(map, i); + else + clearBit(map, i); + v >>= 1; + } +} + +template +inline unsigned getBits(T* map, unsigned bitsPerRecord, unsigned index) +{ + unsigned v = 0; + for (unsigned i = index, limit = index + bitsPerRecord; i < limit; ++i) { + v <<= 1; + v |= getBit(map, i); + } + return v; +} + +template +inline T& fieldAtOffset(void* p, unsigned offset) +{ + return *reinterpret_cast(static_cast(p) + offset); +} + +template +inline T* maskAlignedPointer(T* p) +{ + return reinterpret_cast(reinterpret_cast(p) & PointerMask); +} + +inline void write4(uint8_t* dst, uint32_t v) +{ + memcpy(dst, &v, 4); +} + +inline uint32_t floatToBits(float f) +{ + uint32_t bits; + memcpy(&bits, &f, 4); + return bits; +} + +inline uint64_t doubleToBits(double d) +{ + uint64_t bits; + memcpy(&bits, &d, 8); + return bits; +} + +inline double bitsToDouble(uint64_t bits) +{ + double d; + memcpy(&d, &bits, 8); + return d; +} + +inline float bitsToFloat(uint32_t bits) +{ + float f; + memcpy(&f, &bits, 4); + return f; +} + +inline int difference(void* a, void* b) +{ + return reinterpret_cast(a) - reinterpret_cast(b); +} + +template +inline void* voidPointer(T function) +{ + void* p; + memcpy(&p, &function, sizeof(void*)); + return p; +} + +inline void replace(char a, char b, char* c) +{ + for (; *c; ++c) + if (*c == a) + *c = b; +} + +inline void replace(char a, char b, char* dst, const char* src) +{ + unsigned i = 0; + for (; src[i]; ++i) { + dst[i] = src[i] == a ? b : src[i]; + } + dst[i] = 0; +} + +inline bool equal(const void* a, unsigned al, const void* b, unsigned bl) +{ + if (al == bl) { + return memcmp(a, b, al) == 0; + } else { + return false; + } +} + +} // namespace vm + +#endif // AVIAN_COMMON_H diff --git a/sgx-jvm/avian/src/avian/constants.h b/sgx-jvm/avian/src/avian/constants.h new file mode 100644 index 0000000000..ebeb975af3 --- /dev/null +++ b/sgx-jvm/avian/src/avian/constants.h @@ -0,0 +1,294 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#ifndef CONSTANTS_H +#define CONSTANTS_H + +namespace vm { + +enum OpCode { + aaload = 0x32, + aastore = 0x53, + aconst_null = 0x01, + aload = 0x19, + aload_0 = 0x2a, + aload_1 = 0x2b, + aload_2 = 0x2c, + aload_3 = 0x2d, + anewarray = 0xbd, + areturn = 0xb0, + arraylength = 0xbe, + astore = 0x3a, + astore_0 = 0x4b, + astore_1 = 0x4c, + astore_2 = 0x4d, + astore_3 = 0x4e, + athrow = 0xbf, + baload = 0x33, + bastore = 0x54, + bipush = 0x10, + breakpoint = 0xca, + caload = 0x34, + castore = 0x55, + checkcast = 0xc0, + d2f = 0x90, + d2i = 0x8e, + d2l = 0x8f, + dadd = 0x63, + daload = 0x31, + dastore = 0x52, + dcmpg = 0x98, + dcmpl = 0x97, + dconst_0 = 0x0e, + dconst_1 = 0x0f, + ddiv = 0x6f, + dload = 0x18, + dload_0 = 0x26, + dload_1 = 0x27, + dload_2 = 0x28, + dload_3 = 0x29, + dmul = 0x6b, + dneg = 0x77, + drem = 0x73, + dreturn = 0xaf, + dstore = 0x39, + dstore_0 = 0x47, + dstore_1 = 0x48, + dstore_2 = 0x49, + dstore_3 = 0x4a, + dsub = 0x67, + dup = 0x59, + dup_x1 = 0x5a, + dup_x2 = 0x5b, + dup2 = 0x5c, + dup2_x1 = 0x5d, + dup2_x2 = 0x5e, + f2d = 0x8d, + f2i = 0x8b, + f2l = 0x8c, + fadd = 0x62, + faload = 0x30, + fastore = 0x51, + fcmpg = 0x96, + fcmpl = 0x95, + fconst_0 = 0x0b, + fconst_1 = 0x0c, + fconst_2 = 0x0d, + fdiv = 0x6e, + fload = 0x17, + fload_0 = 0x22, + fload_1 = 0x23, + fload_2 = 0x24, + fload_3 = 0x25, + fmul = 0x6a, + fneg = 0x76, + frem = 0x72, + freturn = 0xae, + fstore = 0x38, + fstore_0 = 0x43, + fstore_1 = 0x44, + fstore_2 = 0x45, + fstore_3 = 0x46, + fsub = 0x66, + getfield = 0xb4, + getstatic = 0xb2, + goto_ = 0xa7, + goto_w = 0xc8, + i2b = 0x91, + i2c = 0x92, + i2d = 0x87, + i2f = 0x86, + i2l = 0x85, + i2s = 0x93, + iadd = 0x60, + iaload = 0x2e, + iand = 0x7e, + iastore = 0x4f, + iconst_m1 = 0x02, + iconst_0 = 0x03, + iconst_1 = 0x04, + iconst_2 = 0x05, + iconst_3 = 0x06, + iconst_4 = 0x07, + iconst_5 = 0x08, + idiv = 0x6c, + if_acmpeq = 0xa5, + if_acmpne = 0xa6, + if_icmpeq = 0x9f, + if_icmpne = 0xa0, + if_icmplt = 0xa1, + if_icmpge = 0xa2, + if_icmpgt = 0xa3, + if_icmple = 0xa4, + ifeq = 0x99, + ifge = 0x9c, + ifgt = 0x9d, + ifle = 0x9e, + iflt = 0x9b, + ifne = 0x9a, + ifnonnull = 0xc7, + ifnull = 0xc6, + iinc = 0x84, + iload = 0x15, + iload_0 = 0x1a, + iload_1 = 0x1b, + iload_2 = 0x1c, + iload_3 = 0x1d, + impdep1 = 0xfe, + impdep2 = 0xff, + imul = 0x68, + ineg = 0x74, + instanceof = 0xc1, + invokedynamic = 0xba, + invokeinterface = 0xb9, + invokespecial = 0xb7, + invokestatic = 0xb8, + invokevirtual = 0xb6, + ior = 0x80, + irem = 0x70, + ireturn = 0xac, + ishl = 0x78, + ishr = 0x7a, + istore = 0x36, + istore_0 = 0x3b, + istore_1 = 0x3c, + istore_2 = 0x3d, + istore_3 = 0x3e, + isub = 0x64, + iushr = 0x7c, + ixor = 0x82, + jsr = 0xa8, + jsr_w = 0xc9, + l2d = 0x8a, + l2f = 0x89, + l2i = 0x88, + ladd = 0x61, + laload = 0x2f, + land = 0x7f, + lastore = 0x50, + lcmp = 0x94, + lconst_0 = 0x09, + lconst_1 = 0x0a, + ldc = 0x12, + ldc_w = 0x13, + ldc2_w = 0x14, + ldiv_ = 0x6d, + lload = 0x16, + lload_0 = 0x1e, + lload_1 = 0x1f, + lload_2 = 0x20, + lload_3 = 0x21, + lmul = 0x69, + lneg = 0x75, + lookupswitch = 0xab, + lor = 0x81, + lrem = 0x71, + lreturn = 0xad, + lshl = 0x79, + lshr = 0x7b, + lstore = 0x37, + lstore_0 = 0x3f, + lstore_1 = 0x40, + lstore_2 = 0x41, + lstore_3 = 0x42, + lsub = 0x65, + lushr = 0x7d, + lxor = 0x83, + monitorenter = 0xc2, + monitorexit = 0xc3, + multianewarray = 0xc5, + new_ = 0xbb, + newarray = 0xbc, + nop = 0x00, + pop_ = 0x57, + pop2 = 0x58, + putfield = 0xb5, + putstatic = 0xb3, + ret = 0xa9, + return_ = 0xb1, + saload = 0x35, + sastore = 0x56, + sipush = 0x11, + swap = 0x5f, + tableswitch = 0xaa, + wide = 0xc4 +}; + +enum TypeCode { + T_BOOLEAN = 4, + T_CHAR = 5, + T_FLOAT = 6, + T_DOUBLE = 7, + T_BYTE = 8, + T_SHORT = 9, + T_INT = 10, + T_LONG = 11 +}; + +enum Constant { + CONSTANT_Class = 7, + CONSTANT_Double = 6, + CONSTANT_Fieldref = 9, + CONSTANT_Float = 4, + CONSTANT_Integer = 3, + CONSTANT_InterfaceMethodref = 11, + CONSTANT_InvokeDynamic = 18, + CONSTANT_Long = 5, + CONSTANT_MethodHandle = 15, + CONSTANT_MethodType = 16, + CONSTANT_Methodref = 10, + CONSTANT_NameAndType = 12, + CONSTANT_String = 8, + CONSTANT_Utf8 = 1 +}; + +const unsigned ACC_PUBLIC = 1 << 0; +const unsigned ACC_PRIVATE = 1 << 1; +const unsigned ACC_PROTECTED = 1 << 2; +const unsigned ACC_STATIC = 1 << 3; +const unsigned ACC_FINAL = 1 << 4; +const unsigned ACC_SUPER = 1 << 5; +const unsigned ACC_SYNCHRONIZED = ACC_SUPER; +const unsigned ACC_VOLATILE = 1 << 6; +const unsigned ACC_TRANSIENT = 1 << 7; +const unsigned ACC_VARARGS = 1 << 7; +const unsigned ACC_NATIVE = 1 << 8; +const unsigned ACC_INTERFACE = 1 << 9; +const unsigned ACC_ABSTRACT = 1 << 10; +const unsigned ACC_STRICT = 1 << 11; + +const unsigned REF_getField = 1; +const unsigned REF_getStatic = 2; +const unsigned REF_putField = 3; +const unsigned REF_putStatic = 4; +const unsigned REF_invokeVirtual = 5; +const unsigned REF_invokeStatic = 6; +const unsigned REF_invokeSpecial = 7; +const unsigned REF_newInvokeSpecial = 8; +const unsigned REF_invokeInterface = 9; + +const int AVIAN_JNI_COMMIT = 1; +const int AVIAN_JNI_ABORT = 2; + +const int AVIAN_JNI_OK = 0; +const int AVIAN_JNI_ERR = -1; +const int AVIAN_JNI_EDETACHED = -2; +const int AVIAN_JNI_EVERSION = -3; +const int AVIAN_JNI_ENOMEM = -4; +const int AVIAN_JNI_EEXIST = -5; +const int AVIAN_JNI_EINVAL = -6; + +const int AVIAN_JNI_VERSION_1_1 = 0x00010001; +const int AVIAN_JNI_VERSION_1_2 = 0x00010002; +const int AVIAN_JNI_VERSION_1_4 = 0x00010004; + +} // namespace vm + +#endif // CONSTANTS_H diff --git a/sgx-jvm/avian/src/avian/embed.h b/sgx-jvm/avian/src/avian/embed.h new file mode 100644 index 0000000000..7f1f457f99 --- /dev/null +++ b/sgx-jvm/avian/src/avian/embed.h @@ -0,0 +1,17 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#ifndef EMBED_H +#define EMBED_H + +#define RESID_MAIN_CLASS 100 +#define RESID_BOOT_JAR L"BOOT.JAR" + +#endif diff --git a/sgx-jvm/avian/src/avian/environment.h b/sgx-jvm/avian/src/avian/environment.h new file mode 100644 index 0000000000..a4eba6dbb5 --- /dev/null +++ b/sgx-jvm/avian/src/avian/environment.h @@ -0,0 +1,33 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#ifndef AVIAN_ENVIRONMENT_H +#define AVIAN_ENVIRONMENT_H + +#ifndef AVIAN_TARGET_FORMAT +#error build system should have defined AVIAN_TARGET_FORMAT +#endif + +#ifndef AVIAN_TARGET_ARCH +#error build system should have defined AVIAN_TARGET_ARCH +#endif + +#define AVIAN_FORMAT_UNKNOWN 0 +#define AVIAN_FORMAT_ELF 1 +#define AVIAN_FORMAT_PE 2 +#define AVIAN_FORMAT_MACHO 3 + +#define AVIAN_ARCH_UNKNOWN 0 +#define AVIAN_ARCH_X86 (1 << 8) +#define AVIAN_ARCH_X86_64 (2 << 8) +#define AVIAN_ARCH_ARM (3 << 8) +#define AVIAN_ARCH_ARM64 (4 << 8) + +#endif diff --git a/sgx-jvm/avian/src/avian/finder.h b/sgx-jvm/avian/src/avian/finder.h new file mode 100644 index 0000000000..133f1127ee --- /dev/null +++ b/sgx-jvm/avian/src/avian/finder.h @@ -0,0 +1,216 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#ifndef FINDER_H +#define FINDER_H + +#include "avian/common.h" +#include + +namespace avian { +namespace util { +class Alloc; +} +} + +namespace vm { + +const unsigned LocalHeaderSize = 30; +const unsigned HeaderSize = 46; + +const unsigned CentralDirectorySignature = 0x06054b50; +const unsigned EntrySignature = 0x02014b50; + +const unsigned CentralDirectorySearchStart = 22; + +inline uint16_t get2(const uint8_t* p) +{ + return (static_cast(p[1]) << 8) | (static_cast(p[0])); +} + +inline uint32_t get4(const uint8_t* p) +{ + return (static_cast(p[3]) << 24) + | (static_cast(p[2]) << 16) + | (static_cast(p[1]) << 8) | (static_cast(p[0])); +} + +inline uint32_t signature(const uint8_t* p) +{ + return get4(p); +} + +inline uint16_t compressionMethod(const uint8_t* centralHeader) +{ + return get2(centralHeader + 10); +} + +inline uint32_t fileTime(const uint8_t* centralHeader) +{ + return get4(centralHeader + 12); +} + +inline uint32_t fileCRC(const uint8_t* centralHeader) +{ + return get4(centralHeader + 16); +} + +inline uint32_t compressedSize(const uint8_t* centralHeader) +{ + return get4(centralHeader + 20); +} + +inline uint32_t uncompressedSize(const uint8_t* centralHeader) +{ + return get4(centralHeader + 24); +} + +inline uint16_t fileNameLength(const uint8_t* centralHeader) +{ + return get2(centralHeader + 28); +} + +inline uint16_t extraFieldLength(const uint8_t* centralHeader) +{ + return get2(centralHeader + 30); +} + +inline uint16_t commentFieldLength(const uint8_t* centralHeader) +{ + return get2(centralHeader + 32); +} + +inline uint32_t localHeaderOffset(const uint8_t* centralHeader) +{ + return get4(centralHeader + 42); +} + +inline uint16_t localFileNameLength(const uint8_t* localHeader) +{ + return get2(localHeader + 26); +} + +inline uint16_t localExtraFieldLength(const uint8_t* localHeader) +{ + return get2(localHeader + 28); +} + +inline uint32_t centralDirectoryOffset(const uint8_t* centralHeader) +{ + return get4(centralHeader + 16); +} + +inline const uint8_t* fileName(const uint8_t* centralHeader) +{ + return centralHeader + 46; +} + +inline const uint8_t* fileData(const uint8_t* localHeader) +{ + return localHeader + LocalHeaderSize + localFileNameLength(localHeader) + + localExtraFieldLength(localHeader); +} + +inline const uint8_t* endOfEntry(const uint8_t* p) +{ + return p + HeaderSize + fileNameLength(p) + extraFieldLength(p) + + commentFieldLength(p); +} + +inline bool readLine(const uint8_t* base, + unsigned total, + size_t* start, + size_t* length) +{ + const uint8_t* p = base + *start; + const uint8_t* end = base + total; + while (p != end and (*p == '\n' or *p == '\r')) + ++p; + + *start = p - base; + while (p != end and not(*p == '\n' or *p == '\r')) + ++p; + + *length = (p - base) - *start; + + return *length != 0; +} + +class Finder { + public: + class IteratorImp { + public: + virtual const char* next(size_t* size) = 0; + virtual void dispose() = 0; + }; + + class Iterator { + public: + Iterator(Finder* finder) + : it(finder->iterator()), current(it->next(¤tSize)) + { + } + + ~Iterator() + { + it->dispose(); + } + + bool hasMore() + { + if (current) + return true; + current = it->next(¤tSize); + return current != 0; + } + + const char* next(size_t* size) + { + if (hasMore()) { + *size = currentSize; + const char* v = current; + current = 0; + return v; + } else { + return 0; + } + } + + IteratorImp* it; + const char* current; + size_t currentSize; + }; + + virtual IteratorImp* iterator() = 0; + virtual System::Region* find(const char* name) = 0; + virtual System::FileType stat(const char* name, + size_t* length, + bool tryDirectory = false) = 0; + virtual const char* urlPrefix(const char* name) = 0; + virtual const char* nextUrlPrefix(const char* name, void*& finderElementPtr) + = 0; + virtual const char* sourceUrl(const char* name) = 0; + virtual const char* path() = 0; + virtual void dispose() = 0; +}; + +AVIAN_EXPORT Finder* makeFinder(System* s, + avian::util::Alloc* a, + const char* path, + const char* bootLibrary); + +Finder* makeFinder(System* s, + avian::util::Alloc* a, + const uint8_t* jarData, + size_t jarLength); + +} // namespace vm + +#endif // FINDER_H diff --git a/sgx-jvm/avian/src/avian/heapwalk.h b/sgx-jvm/avian/src/avian/heapwalk.h new file mode 100644 index 0000000000..32bf0104aa --- /dev/null +++ b/sgx-jvm/avian/src/avian/heapwalk.h @@ -0,0 +1,49 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#ifndef HEAPWALK_H +#define HEAPWALK_H + +#include "avian/common.h" +#include "java-common.h" + +namespace vm { + +class Thread; + +class HeapMap { + public: + virtual int find(object value) = 0; + virtual void dispose() = 0; +}; + +class HeapVisitor { + public: + virtual void root() = 0; + virtual unsigned visitNew(object value) = 0; + virtual void visitOld(object value, unsigned number) = 0; + virtual void push(object parent, unsigned parentNumber, unsigned childOffset) + = 0; + virtual void pop() = 0; +}; + +class HeapWalker { + public: + virtual unsigned visitRoot(object root) = 0; + virtual void visitAllRoots() = 0; + virtual HeapMap* map() = 0; + virtual void dispose() = 0; +}; + +HeapWalker* makeHeapWalker(Thread* t, HeapVisitor* v); + +} // namespace vm + +#endif // HEAPWALK_H diff --git a/sgx-jvm/avian/src/avian/java-common.h b/sgx-jvm/avian/src/avian/java-common.h new file mode 100644 index 0000000000..52b8c9d499 --- /dev/null +++ b/sgx-jvm/avian/src/avian/java-common.h @@ -0,0 +1,83 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#ifndef JAVA_COMMON_H +#define JAVA_COMMON_H + +namespace vm { + +class Machine; +class Thread; + +class GcObject; +; + +typedef GcObject* object; + +typedef uint8_t jboolean; +typedef int8_t jbyte; +typedef uint16_t jchar; +typedef int16_t jshort; +typedef int32_t jint; +typedef int64_t jlong; +typedef float jfloat; +typedef double jdouble; + +typedef jint jsize; + +typedef object* jobject; + +class GcString; +class GcJclass; +class GcThrowable; +class GcBooleanArray; +class GcByteArray; +class GcCharArray; +class GcShortArray; +class GcIntArray; +class GcLongArray; +class GcFloatArray; +class GcDoubleArray; +class GcObjectArray; + +typedef GcJclass** jclass; +typedef GcThrowable** jthrowable; +typedef GcString** jstring; +typedef jobject jweak; + +typedef jobject jarray; +typedef GcBooleanArray** jbooleanArray; +typedef GcByteArray** jbyteArray; +typedef GcCharArray** jcharArray; +typedef GcShortArray** jshortArray; +typedef GcIntArray** jintArray; +typedef GcLongArray** jlongArray; +typedef GcFloatArray** jfloatArray; +typedef GcDoubleArray** jdoubleArray; +typedef GcObjectArray** jobjectArray; + +typedef uintptr_t jfieldID; +typedef uintptr_t jmethodID; + +union jvalue { + jboolean z; + jbyte b; + jchar c; + jshort s; + jint i; + jlong j; + jfloat f; + jdouble d; + jobject l; +}; + +} // namespace vm + +#endif // JAVA_COMMON_H diff --git a/sgx-jvm/avian/src/avian/jnienv.h b/sgx-jvm/avian/src/avian/jnienv.h new file mode 100644 index 0000000000..9947ade6ec --- /dev/null +++ b/sgx-jvm/avian/src/avian/jnienv.h @@ -0,0 +1,34 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#ifndef JNIENV_H +#define JNIENV_H + +#include "avian/machine.h" + +#define BOOTSTRAP_PROPERTY "avian.bootstrap" +#define JAVA_COMMAND_PROPERTY "sun.java.command" +#define JAVA_LAUNCHER_PROPERTY "sun.java.launcher" +#define CRASHDIR_PROPERTY "avian.crash.dir" +#define EMBED_PREFIX_PROPERTY "avian.embed.prefix" +#define CLASSPATH_PROPERTY "java.class.path" +#define JAVA_HOME_PROPERTY "java.home" +#define REENTRANT_PROPERTY "avian.reentrant" +#define BOOTCLASSPATH_PREPEND_OPTION "bootclasspath/p" +#define BOOTCLASSPATH_OPTION "bootclasspath" +#define BOOTCLASSPATH_APPEND_OPTION "bootclasspath/a" + +namespace vm { + +void populateJNITables(JavaVMVTable* vmTable, JNIEnvVTable* envTable); + +} // namespace vm + +#endif // JNIENV_H diff --git a/sgx-jvm/avian/src/avian/lzma-util.h b/sgx-jvm/avian/src/avian/lzma-util.h new file mode 100644 index 0000000000..6837f79dd9 --- /dev/null +++ b/sgx-jvm/avian/src/avian/lzma-util.h @@ -0,0 +1,56 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#ifndef LZMA_UTIL_H +#define LZMA_UTIL_H + +#include +#include +#include +#include + +namespace vm { + +const unsigned Padding = 16; + +class LzmaAllocator { + public: + LzmaAllocator(avian::util::Alloc* a) : a(a) + { + allocator.Alloc = allocate; + allocator.Free = free; + } + + ISzAlloc allocator; + avian::util::Alloc* a; + + static void* allocate(void* allocator, size_t size) + { + uint8_t* p = static_cast( + static_cast(allocator)->a->allocate(size + Padding)); + int32_t size32 = size; + memcpy(p, &size32, 4); + return p + Padding; + } + + static void free(void* allocator, void* address) + { + if (address) { + void* p = static_cast(address) - Padding; + int32_t size32; + memcpy(&size32, p, 4); + static_cast(allocator)->a->free(p, size32 + Padding); + } + } +}; + +} // namespace vm + +#endif // LZMA_UTIL_H diff --git a/sgx-jvm/avian/src/avian/lzma.h b/sgx-jvm/avian/src/avian/lzma.h new file mode 100644 index 0000000000..a9c6baa545 --- /dev/null +++ b/sgx-jvm/avian/src/avian/lzma.h @@ -0,0 +1,38 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#ifndef LZMA_H +#define LZMA_H + +#include + +namespace avian { +namespace util { +class AllocOnly; +} +} + +namespace vm { + +uint8_t* decodeLZMA(System* s, + avian::util::Alloc* a, + uint8_t* in, + size_t inSize, + size_t* outSize); + +uint8_t* encodeLZMA(System* s, + avian::util::Alloc* a, + uint8_t* in, + size_t inSize, + size_t* outSize); + +} // namespace vm + +#endif // LZMA_H diff --git a/sgx-jvm/avian/src/avian/machine.h b/sgx-jvm/avian/src/avian/machine.h new file mode 100644 index 0000000000..8b59bb85a2 --- /dev/null +++ b/sgx-jvm/avian/src/avian/machine.h @@ -0,0 +1,3868 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#ifndef MACHINE_H +#define MACHINE_H + +#include "avian/common.h" +#include "java-common.h" +#include +#include +#include +#include +#include "avian/finder.h" +#include "avian/processor.h" +#include "avian/constants.h" +#include "avian/arch.h" + +using namespace avian::util; + +#ifdef PLATFORM_WINDOWS +#define JNICALL __stdcall +#else +#define JNICALL +#endif + +#define PROTECT(thread, name) \ + Thread::SingleProtector MAKE_NAME(protector_)(thread, &name); + +#define ACQUIRE(t, x) MonitorResource MAKE_NAME(monitorResource_)(t, x) + +#define ACQUIRE_OBJECT(t, x) \ + ObjectMonitorResource MAKE_NAME(monitorResource_)(t, x) + +#define ACQUIRE_FIELD_FOR_READ(t, field) \ + FieldReadResource MAKE_NAME(monitorResource_)(t, field) + +#define ACQUIRE_FIELD_FOR_WRITE(t, field) \ + FieldWriteResource MAKE_NAME(monitorResource_)(t, field) + +#define ACQUIRE_RAW(t, x) RawMonitorResource MAKE_NAME(monitorResource_)(t, x) + +#define ENTER(t, state) StateResource MAKE_NAME(stateResource_)(t, state) + +#define THREAD_RESOURCE0(t, releaseBody) \ + class MAKE_NAME(Resource_) : public Thread::AutoResource { \ + public: \ + MAKE_NAME(Resource_)(Thread * t) : AutoResource(t) \ + { \ + } \ + ~MAKE_NAME(Resource_)() \ + { \ + releaseBody; \ + } \ + virtual void release() \ + { \ + this->MAKE_NAME(Resource_)::~MAKE_NAME(Resource_)(); \ + } \ + } MAKE_NAME(resource_)(t); + +#define OBJECT_RESOURCE(t, name, releaseBody) \ + class MAKE_NAME(Resource_) : public Thread::AutoResource { \ + public: \ + MAKE_NAME(Resource_)(Thread * t, object name) \ + : AutoResource(t), name(name), protector(t, &(this->name)) \ + { \ + } \ + ~MAKE_NAME(Resource_)() \ + { \ + releaseBody; \ + } \ + virtual void release() \ + { \ + this->MAKE_NAME(Resource_)::~MAKE_NAME(Resource_)(); \ + } \ + \ + private: \ + object name; \ + Thread::SingleProtector protector; \ + } MAKE_NAME(resource_)(t, name); + +#define THREAD_RESOURCE(t, type, name, releaseBody) \ + class MAKE_NAME(Resource_) : public Thread::AutoResource { \ + public: \ + MAKE_NAME(Resource_)(Thread * t, type name) : AutoResource(t), name(name) \ + { \ + } \ + ~MAKE_NAME(Resource_)() \ + { \ + releaseBody; \ + } \ + virtual void release() \ + { \ + this->MAKE_NAME(Resource_)::~MAKE_NAME(Resource_)(); \ + } \ + \ + private: \ + type name; \ + } MAKE_NAME(resource_)(t, name); + +#define THREAD_RESOURCE2(t, type1, name1, type2, name2, releaseBody) \ + class MAKE_NAME(Resource_) : public Thread::AutoResource { \ + public: \ + MAKE_NAME(Resource_)(Thread * t, type1 name1, type2 name2) \ + : AutoResource(t), name1(name1), name2(name2) \ + { \ + } \ + ~MAKE_NAME(Resource_)() \ + { \ + releaseBody; \ + } \ + virtual void release() \ + { \ + this->MAKE_NAME(Resource_)::~MAKE_NAME(Resource_)(); \ + } \ + \ + private: \ + type1 name1; \ + type2 name2; \ + } MAKE_NAME(resource_)(t, name1, name2); + +AVIAN_EXPORT void vmPrintTrace(vm::Thread* t); + +AVIAN_EXPORT void vmfPrintTrace(vm::Thread* t, FILE* out); + +namespace vm { + +const bool Verbose = false; +const bool DebugRun = false; +const bool DebugCalls = false; +const bool DebugStack = false; +const bool DebugMonitors = false; +const bool DebugReferences = false; + +const bool AbortOnOutOfMemoryError = false; + +const uintptr_t HashTakenMark = 1; +const uintptr_t ExtendedMark = 2; +const uintptr_t FixedMark = 3; + +const unsigned ThreadHeapSizeInBytes = 64 * 1024; +const unsigned ThreadHeapSizeInWords = ThreadHeapSizeInBytes / BytesPerWord; + +const unsigned ThreadBackupHeapSizeInBytes = 2 * 1024; +const unsigned ThreadBackupHeapSizeInWords = ThreadBackupHeapSizeInBytes + / BytesPerWord; + +const unsigned ThreadHeapPoolSize = 64; + +const unsigned FixedFootprintThresholdInBytes = ThreadHeapPoolSize + * ThreadHeapSizeInBytes; + +// number of zombie threads which may accumulate before we force a GC +// to clean them up: +const unsigned ZombieCollectionThreshold = 16; + +enum FieldCode { + VoidField, + ByteField, + CharField, + DoubleField, + FloatField, + IntField, + LongField, + ShortField, + BooleanField, + ObjectField +}; + +enum StackTag { + IntTag, // must be zero + ObjectTag +}; + +const int NativeLine = -2; +const int UnknownLine = -1; + +// class vmFlags: +const unsigned ReferenceFlag = 1 << 0; +const unsigned WeakReferenceFlag = 1 << 1; +const unsigned NeedInitFlag = 1 << 2; +const unsigned InitFlag = 1 << 3; +const unsigned InitErrorFlag = 1 << 4; +const unsigned PrimitiveFlag = 1 << 5; +const unsigned BootstrapFlag = 1 << 6; +const unsigned HasFinalizerFlag = 1 << 7; +const unsigned LinkFlag = 1 << 8; +const unsigned HasFinalMemberFlag = 1 << 9; +const unsigned SingletonFlag = 1 << 10; +const unsigned ContinuationFlag = 1 << 11; + +// method vmFlags: +const unsigned ClassInitFlag = 1 << 0; +const unsigned ConstructorFlag = 1 << 1; + +#ifndef JNI_VERSION_1_6 +#define JNI_VERSION_1_6 0x00010006 +#endif + +#ifndef JNI_TRUE +#define JNI_TRUE 1 +#endif + +#ifndef JNI_OK +#define JNI_OK 0 +#endif + +typedef Machine JavaVM; +typedef Thread JNIEnv; + +struct JNINativeMethod { + char* name; + char* signature; + void* function; +}; + +struct JavaVMOption { + char* optionString; + void* extraInfo; +}; + +struct JavaVMInitArgs { + jint version; + + jint nOptions; + JavaVMOption* options; + jboolean ignoreUnrecognized; +}; + +struct JavaVMVTable { + void* reserved0; + void* reserved1; + void* reserved2; + + jint(JNICALL* DestroyJavaVM)(JavaVM*); + + jint(JNICALL* AttachCurrentThread)(JavaVM*, JNIEnv**, void*); + + jint(JNICALL* DetachCurrentThread)(JavaVM*); + + jint(JNICALL* GetEnv)(JavaVM*, JNIEnv**, jint); + + jint(JNICALL* AttachCurrentThreadAsDaemon)(JavaVM*, JNIEnv**, void*); +}; + +struct JNIEnvVTable { + void* reserved0; + void* reserved1; + void* reserved2; + void* reserved3; + + jint(JNICALL* GetVersion)(JNIEnv*); + + jclass( + JNICALL* DefineClass)(JNIEnv*, const char*, jobject, const jbyte*, jsize); + + jclass(JNICALL* FindClass)(JNIEnv*, const char*); + + jmethodID(JNICALL* FromReflectedMethod)(JNIEnv*, jobject); + + jfieldID(JNICALL* FromReflectedField)(JNIEnv*, jobject); + + jobject(JNICALL* ToReflectedMethod)(JNIEnv*, jclass, jmethodID, jboolean); + + jclass(JNICALL* GetSuperclass)(JNIEnv*, jclass); + + jboolean(JNICALL* IsAssignableFrom)(JNIEnv*, jclass, jclass); + + jobject(JNICALL* ToReflectedField)(JNIEnv*, jclass, jfieldID, jboolean); + + jint(JNICALL* Throw)(JNIEnv*, jthrowable); + + jint(JNICALL* ThrowNew)(JNIEnv*, jclass, const char*); + + jthrowable(JNICALL* ExceptionOccurred)(JNIEnv*); + + void(JNICALL* ExceptionDescribe)(JNIEnv*); + + void(JNICALL* ExceptionClear)(JNIEnv*); + + void(JNICALL* FatalError)(JNIEnv*, const char*); + + jint(JNICALL* PushLocalFrame)(JNIEnv*, jint); + + jobject(JNICALL* PopLocalFrame)(JNIEnv*, jobject); + + jobject(JNICALL* NewGlobalRef)(JNIEnv*, jobject); + + void(JNICALL* DeleteGlobalRef)(JNIEnv*, jobject); + + void(JNICALL* DeleteLocalRef)(JNIEnv*, jobject); + + jboolean(JNICALL* IsSameObject)(JNIEnv*, jobject, jobject); + + jobject(JNICALL* NewLocalRef)(JNIEnv*, jobject); + + jint(JNICALL* EnsureLocalCapacity)(JNIEnv*, jint); + + jobject(JNICALL* AllocObject)(JNIEnv*, jclass); + + jobject(JNICALL* NewObject)(JNIEnv*, jclass, jmethodID, ...); + + jobject(JNICALL* NewObjectV)(JNIEnv*, jclass, jmethodID, va_list); + + jobject(JNICALL* NewObjectA)(JNIEnv*, jclass, jmethodID, const jvalue*); + + jclass(JNICALL* GetObjectClass)(JNIEnv*, jobject); + + jboolean(JNICALL* IsInstanceOf)(JNIEnv*, jobject, jclass); + + jmethodID(JNICALL* GetMethodID)(JNIEnv*, jclass, const char*, const char*); + + jobject(JNICALL* CallObjectMethod)(JNIEnv*, jobject, jmethodID, ...); + + jobject(JNICALL* CallObjectMethodV)(JNIEnv*, jobject, jmethodID, va_list); + + jobject(JNICALL* CallObjectMethodA)(JNIEnv*, + jobject, + jmethodID, + const jvalue*); + + jboolean(JNICALL* CallBooleanMethod)(JNIEnv*, jobject, jmethodID, ...); + + jboolean(JNICALL* CallBooleanMethodV)(JNIEnv*, jobject, jmethodID, va_list); + + jboolean(JNICALL* CallBooleanMethodA)(JNIEnv*, + jobject, + jmethodID, + const jvalue*); + + jbyte(JNICALL* CallByteMethod)(JNIEnv*, jobject, jmethodID, ...); + + jbyte(JNICALL* CallByteMethodV)(JNIEnv*, jobject, jmethodID, va_list); + + jbyte(JNICALL* CallByteMethodA)(JNIEnv*, jobject, jmethodID, const jvalue*); + + jchar(JNICALL* CallCharMethod)(JNIEnv*, jobject, jmethodID, ...); + + jchar(JNICALL* CallCharMethodV)(JNIEnv*, jobject, jmethodID, va_list); + + jchar(JNICALL* CallCharMethodA)(JNIEnv*, jobject, jmethodID, const jvalue*); + + jshort(JNICALL* CallShortMethod)(JNIEnv*, jobject, jmethodID, ...); + + jshort(JNICALL* CallShortMethodV)(JNIEnv*, jobject, jmethodID, va_list); + + jshort(JNICALL* CallShortMethodA)(JNIEnv*, jobject, jmethodID, const jvalue*); + + jint(JNICALL* CallIntMethod)(JNIEnv*, jobject, jmethodID, ...); + + jint(JNICALL* CallIntMethodV)(JNIEnv*, jobject, jmethodID, va_list); + + jint(JNICALL* CallIntMethodA)(JNIEnv*, jobject, jmethodID, const jvalue*); + + jlong(JNICALL* CallLongMethod)(JNIEnv*, jobject, jmethodID, ...); + + jlong(JNICALL* CallLongMethodV)(JNIEnv*, jobject, jmethodID, va_list); + + jlong(JNICALL* CallLongMethodA)(JNIEnv*, jobject, jmethodID, const jvalue*); + + jfloat(JNICALL* CallFloatMethod)(JNIEnv*, jobject, jmethodID, ...); + + jfloat(JNICALL* CallFloatMethodV)(JNIEnv*, jobject, jmethodID, va_list); + + jfloat(JNICALL* CallFloatMethodA)(JNIEnv*, jobject, jmethodID, const jvalue*); + + jdouble(JNICALL* CallDoubleMethod)(JNIEnv*, jobject, jmethodID, ...); + + jdouble(JNICALL* CallDoubleMethodV)(JNIEnv*, jobject, jmethodID, va_list); + + jdouble(JNICALL* CallDoubleMethodA)(JNIEnv*, + jobject, + jmethodID, + const jvalue*); + + void(JNICALL* CallVoidMethod)(JNIEnv*, jobject, jmethodID, ...); + + void(JNICALL* CallVoidMethodV)(JNIEnv*, jobject, jmethodID, va_list); + + void(JNICALL* CallVoidMethodA)(JNIEnv*, jobject, jmethodID, const jvalue*); + + jobject(JNICALL* CallNonvirtualObjectMethod)(JNIEnv*, + jobject, + jclass, + jmethodID, + ...); + + jobject(JNICALL* CallNonvirtualObjectMethodV)(JNIEnv*, + jobject, + jclass, + jmethodID, + va_list); + + jobject(JNICALL* CallNonvirtualObjectMethodA)(JNIEnv*, + jobject, + jclass, + jmethodID, + const jvalue*); + + jboolean(JNICALL* CallNonvirtualBooleanMethod)(JNIEnv*, + jobject, + jclass, + jmethodID, + ...); + + jboolean(JNICALL* CallNonvirtualBooleanMethodV)(JNIEnv*, + jobject, + jclass, + jmethodID, + va_list); + + jboolean(JNICALL* CallNonvirtualBooleanMethodA)(JNIEnv*, + jobject, + jclass, + jmethodID, + const jvalue*); + + jbyte(JNICALL* CallNonvirtualByteMethod)(JNIEnv*, + jobject, + jclass, + jmethodID, + ...); + + jbyte(JNICALL* CallNonvirtualByteMethodV)(JNIEnv*, + jobject, + jclass, + jmethodID, + va_list); + + jbyte(JNICALL* CallNonvirtualByteMethodA)(JNIEnv*, + jobject, + jclass, + jmethodID, + const jvalue*); + + jchar(JNICALL* CallNonvirtualCharMethod)(JNIEnv*, + jobject, + jclass, + jmethodID, + ...); + + jchar(JNICALL* CallNonvirtualCharMethodV)(JNIEnv*, + jobject, + jclass, + jmethodID, + va_list); + + jchar(JNICALL* CallNonvirtualCharMethodA)(JNIEnv*, + jobject, + jclass, + jmethodID, + const jvalue*); + + jshort(JNICALL* CallNonvirtualShortMethod)(JNIEnv*, + jobject, + jclass, + jmethodID, + ...); + + jshort(JNICALL* CallNonvirtualShortMethodV)(JNIEnv*, + jobject, + jclass, + jmethodID, + va_list); + + jshort(JNICALL* CallNonvirtualShortMethodA)(JNIEnv*, + jobject, + jclass, + jmethodID, + const jvalue*); + + jint(JNICALL* CallNonvirtualIntMethod)(JNIEnv*, + jobject, + jclass, + jmethodID, + ...); + + jint(JNICALL* CallNonvirtualIntMethodV)(JNIEnv*, + jobject, + jclass, + jmethodID, + va_list); + + jint(JNICALL* CallNonvirtualIntMethodA)(JNIEnv*, + jobject, + jclass, + jmethodID, + const jvalue*); + + jlong(JNICALL* CallNonvirtualLongMethod)(JNIEnv*, + jobject, + jclass, + jmethodID, + ...); + + jlong(JNICALL* CallNonvirtualLongMethodV)(JNIEnv*, + jobject, + jclass, + jmethodID, + va_list); + jlong(JNICALL* CallNonvirtualLongMethodA)(JNIEnv*, + jobject, + jclass, + jmethodID, + const jvalue*); + + jfloat(JNICALL* CallNonvirtualFloatMethod)(JNIEnv*, + jobject, + jclass, + jmethodID, + ...); + + jfloat(JNICALL* CallNonvirtualFloatMethodV)(JNIEnv*, + jobject, + jclass, + jmethodID, + va_list); + + jfloat(JNICALL* CallNonvirtualFloatMethodA)(JNIEnv*, + jobject, + jclass, + jmethodID, + const jvalue*); + + jdouble(JNICALL* CallNonvirtualDoubleMethod)(JNIEnv*, + jobject, + jclass, + jmethodID, + ...); + + jdouble(JNICALL* CallNonvirtualDoubleMethodV)(JNIEnv*, + jobject, + jclass, + jmethodID, + va_list); + + jdouble(JNICALL* CallNonvirtualDoubleMethodA)(JNIEnv*, + jobject, + jclass, + jmethodID, + const jvalue*); + + void(JNICALL* CallNonvirtualVoidMethod)(JNIEnv*, + jobject, + jclass, + jmethodID, + ...); + + void(JNICALL* CallNonvirtualVoidMethodV)(JNIEnv*, + jobject, + jclass, + jmethodID, + va_list); + + void(JNICALL* CallNonvirtualVoidMethodA)(JNIEnv*, + jobject, + jclass, + jmethodID, + const jvalue*); + + jfieldID(JNICALL* GetFieldID)(JNIEnv*, jclass, const char*, const char*); + + jobject(JNICALL* GetObjectField)(JNIEnv*, jobject, jfieldID); + + jboolean(JNICALL* GetBooleanField)(JNIEnv*, jobject, jfieldID); + + jbyte(JNICALL* GetByteField)(JNIEnv*, jobject, jfieldID); + + jchar(JNICALL* GetCharField)(JNIEnv*, jobject, jfieldID); + + jshort(JNICALL* GetShortField)(JNIEnv*, jobject, jfieldID); + + jint(JNICALL* GetIntField)(JNIEnv*, jobject, jfieldID); + + jlong(JNICALL* GetLongField)(JNIEnv*, jobject, jfieldID); + + jfloat(JNICALL* GetFloatField)(JNIEnv*, jobject, jfieldID); + + jdouble(JNICALL* GetDoubleField)(JNIEnv*, jobject, jfieldID); + + void(JNICALL* SetObjectField)(JNIEnv*, jobject, jfieldID, jobject); + + void(JNICALL* SetBooleanField)(JNIEnv*, jobject, jfieldID, jboolean); + + void(JNICALL* SetByteField)(JNIEnv*, jobject, jfieldID, jbyte); + + void(JNICALL* SetCharField)(JNIEnv*, jobject, jfieldID, jchar); + + void(JNICALL* SetShortField)(JNIEnv*, jobject, jfieldID, jshort); + + void(JNICALL* SetIntField)(JNIEnv*, jobject, jfieldID, jint); + + void(JNICALL* SetLongField)(JNIEnv*, jobject, jfieldID, jlong); + + void(JNICALL* SetFloatField)(JNIEnv*, jobject, jfieldID, jfloat); + + void(JNICALL* SetDoubleField)(JNIEnv*, jobject, jfieldID, jdouble); + + jmethodID(JNICALL* GetStaticMethodID)(JNIEnv*, + jclass, + const char*, + const char*); + + jobject(JNICALL* CallStaticObjectMethod)(JNIEnv*, jclass, jmethodID, ...); + + jobject(JNICALL* CallStaticObjectMethodV)(JNIEnv*, + jclass, + jmethodID, + va_list); + + jobject(JNICALL* CallStaticObjectMethodA)(JNIEnv*, + jclass, + jmethodID, + const jvalue*); + + jboolean(JNICALL* CallStaticBooleanMethod)(JNIEnv*, jclass, jmethodID, ...); + + jboolean(JNICALL* CallStaticBooleanMethodV)(JNIEnv*, + jclass, + jmethodID, + va_list); + + jboolean(JNICALL* CallStaticBooleanMethodA)(JNIEnv*, + jclass, + jmethodID, + const jvalue*); + + jbyte(JNICALL* CallStaticByteMethod)(JNIEnv*, jclass, jmethodID, ...); + + jbyte(JNICALL* CallStaticByteMethodV)(JNIEnv*, jclass, jmethodID, va_list); + + jbyte(JNICALL* CallStaticByteMethodA)(JNIEnv*, + jclass, + jmethodID, + const jvalue*); + + jchar(JNICALL* CallStaticCharMethod)(JNIEnv*, jclass, jmethodID, ...); + + jchar(JNICALL* CallStaticCharMethodV)(JNIEnv*, jclass, jmethodID, va_list); + + jchar(JNICALL* CallStaticCharMethodA)(JNIEnv*, + jclass, + jmethodID, + const jvalue*); + + jshort(JNICALL* CallStaticShortMethod)(JNIEnv*, jclass, jmethodID, ...); + + jshort(JNICALL* CallStaticShortMethodV)(JNIEnv*, jclass, jmethodID, va_list); + + jshort(JNICALL* CallStaticShortMethodA)(JNIEnv*, + jclass, + jmethodID, + const jvalue*); + + jint(JNICALL* CallStaticIntMethod)(JNIEnv*, jclass, jmethodID, ...); + + jint(JNICALL* CallStaticIntMethodV)(JNIEnv*, jclass, jmethodID, va_list); + + jint(JNICALL* CallStaticIntMethodA)(JNIEnv*, + jclass, + jmethodID, + const jvalue*); + + jlong(JNICALL* CallStaticLongMethod)(JNIEnv*, jclass, jmethodID, ...); + + jlong(JNICALL* CallStaticLongMethodV)(JNIEnv*, jclass, jmethodID, va_list); + + jlong(JNICALL* CallStaticLongMethodA)(JNIEnv*, + jclass, + jmethodID, + const jvalue*); + + jfloat(JNICALL* CallStaticFloatMethod)(JNIEnv*, jclass, jmethodID, ...); + + jfloat(JNICALL* CallStaticFloatMethodV)(JNIEnv*, jclass, jmethodID, va_list); + + jfloat(JNICALL* CallStaticFloatMethodA)(JNIEnv*, + jclass, + jmethodID, + const jvalue*); + + jdouble(JNICALL* CallStaticDoubleMethod)(JNIEnv*, jclass, jmethodID, ...); + + jdouble(JNICALL* CallStaticDoubleMethodV)(JNIEnv*, + jclass, + jmethodID, + va_list); + + jdouble(JNICALL* CallStaticDoubleMethodA)(JNIEnv*, + jclass, + jmethodID, + const jvalue*); + + void(JNICALL* CallStaticVoidMethod)(JNIEnv*, jclass, jmethodID, ...); + + void(JNICALL* CallStaticVoidMethodV)(JNIEnv*, jclass, jmethodID, va_list); + + void(JNICALL* CallStaticVoidMethodA)(JNIEnv*, + jclass, + jmethodID, + const jvalue*); + + jfieldID(JNICALL* GetStaticFieldID)(JNIEnv*, + jclass, + const char*, + const char*); + + jobject(JNICALL* GetStaticObjectField)(JNIEnv*, jclass, jfieldID); + + jboolean(JNICALL* GetStaticBooleanField)(JNIEnv*, jclass, jfieldID); + + jbyte(JNICALL* GetStaticByteField)(JNIEnv*, jclass, jfieldID); + + jchar(JNICALL* GetStaticCharField)(JNIEnv*, jclass, jfieldID); + + jshort(JNICALL* GetStaticShortField)(JNIEnv*, jclass, jfieldID); + + jint(JNICALL* GetStaticIntField)(JNIEnv*, jclass, jfieldID); + + jlong(JNICALL* GetStaticLongField)(JNIEnv*, jclass, jfieldID); + + jfloat(JNICALL* GetStaticFloatField)(JNIEnv*, jclass, jfieldID); + + jdouble(JNICALL* GetStaticDoubleField)(JNIEnv*, jclass, jfieldID); + + void(JNICALL* SetStaticObjectField)(JNIEnv*, jclass, jfieldID, jobject); + + void(JNICALL* SetStaticBooleanField)(JNIEnv*, jclass, jfieldID, jboolean); + + void(JNICALL* SetStaticByteField)(JNIEnv*, jclass, jfieldID, jbyte); + + void(JNICALL* SetStaticCharField)(JNIEnv*, jclass, jfieldID, jchar); + + void(JNICALL* SetStaticShortField)(JNIEnv*, jclass, jfieldID, jshort); + + void(JNICALL* SetStaticIntField)(JNIEnv*, jclass, jfieldID, jint); + + void(JNICALL* SetStaticLongField)(JNIEnv*, jclass, jfieldID, jlong); + + void(JNICALL* SetStaticFloatField)(JNIEnv*, jclass, jfieldID, jfloat); + + void(JNICALL* SetStaticDoubleField)(JNIEnv*, jclass, jfieldID, jdouble); + + jstring(JNICALL* NewString)(JNIEnv*, const jchar*, jsize); + + jsize(JNICALL* GetStringLength)(JNIEnv*, jstring); + + const jchar*(JNICALL* GetStringChars)(JNIEnv*, jstring, jboolean*); + + void(JNICALL* ReleaseStringChars)(JNIEnv*, jstring, const jchar*); + + jstring(JNICALL* NewStringUTF)(JNIEnv*, const char*); + + jsize(JNICALL* GetStringUTFLength)(JNIEnv*, jstring); + + const char*(JNICALL* GetStringUTFChars)(JNIEnv*, jstring, jboolean*); + + void(JNICALL* ReleaseStringUTFChars)(JNIEnv*, jstring, const char*); + + jsize(JNICALL* GetArrayLength)(JNIEnv*, jarray); + + jobjectArray(JNICALL* NewObjectArray)(JNIEnv*, jsize, jclass, jobject); + + jobject(JNICALL* GetObjectArrayElement)(JNIEnv*, jobjectArray, jsize); + + void(JNICALL* SetObjectArrayElement)(JNIEnv*, jobjectArray, jsize, jobject); + + jbooleanArray(JNICALL* NewBooleanArray)(JNIEnv*, jsize); + + jbyteArray(JNICALL* NewByteArray)(JNIEnv*, jsize); + + jcharArray(JNICALL* NewCharArray)(JNIEnv*, jsize); + + jshortArray(JNICALL* NewShortArray)(JNIEnv*, jsize); + + jintArray(JNICALL* NewIntArray)(JNIEnv*, jsize); + + jlongArray(JNICALL* NewLongArray)(JNIEnv*, jsize); + + jfloatArray(JNICALL* NewFloatArray)(JNIEnv*, jsize); + + jdoubleArray(JNICALL* NewDoubleArray)(JNIEnv*, jsize); + + jboolean*(JNICALL* GetBooleanArrayElements)(JNIEnv*, + jbooleanArray, + jboolean*); + + jbyte*(JNICALL* GetByteArrayElements)(JNIEnv*, jbyteArray, jboolean*); + + jchar*(JNICALL* GetCharArrayElements)(JNIEnv*, jcharArray, jboolean*); + + jshort*(JNICALL* GetShortArrayElements)(JNIEnv*, jshortArray, jboolean*); + + jint*(JNICALL* GetIntArrayElements)(JNIEnv*, jintArray, jboolean*); + + jlong*(JNICALL* GetLongArrayElements)(JNIEnv*, jlongArray, jboolean*); + + jfloat*(JNICALL* GetFloatArrayElements)(JNIEnv*, jfloatArray, jboolean*); + + jdouble*(JNICALL* GetDoubleArrayElements)(JNIEnv*, jdoubleArray, jboolean*); + + void(JNICALL* ReleaseBooleanArrayElements)(JNIEnv*, + jbooleanArray, + jboolean*, + jint); + + void(JNICALL* ReleaseByteArrayElements)(JNIEnv*, jbyteArray, jbyte*, jint); + + void(JNICALL* ReleaseCharArrayElements)(JNIEnv*, jcharArray, jchar*, jint); + + void(JNICALL* ReleaseShortArrayElements)(JNIEnv*, jshortArray, jshort*, jint); + + void(JNICALL* ReleaseIntArrayElements)(JNIEnv*, jintArray, jint*, jint); + + void(JNICALL* ReleaseLongArrayElements)(JNIEnv*, jlongArray, jlong*, jint); + + void(JNICALL* ReleaseFloatArrayElements)(JNIEnv*, jfloatArray, jfloat*, jint); + + void(JNICALL* ReleaseDoubleArrayElements)(JNIEnv*, + jdoubleArray, + jdouble*, + jint); + + void(JNICALL* GetBooleanArrayRegion)(JNIEnv*, + jbooleanArray, + jsize, + jsize, + jboolean*); + + void(JNICALL* GetByteArrayRegion)(JNIEnv*, jbyteArray, jsize, jsize, jbyte*); + + void(JNICALL* GetCharArrayRegion)(JNIEnv*, jcharArray, jsize, jsize, jchar*); + + void(JNICALL* GetShortArrayRegion)(JNIEnv*, + jshortArray, + jsize, + jsize, + jshort*); + + void(JNICALL* GetIntArrayRegion)(JNIEnv*, jintArray, jsize, jsize, jint*); + + void(JNICALL* GetLongArrayRegion)(JNIEnv*, jlongArray, jsize, jsize, jlong*); + + void(JNICALL* GetFloatArrayRegion)(JNIEnv*, + jfloatArray, + jsize, + jsize, + jfloat*); + + void(JNICALL* GetDoubleArrayRegion)(JNIEnv*, + jdoubleArray, + jsize, + jsize, + jdouble*); + + void(JNICALL* SetBooleanArrayRegion)(JNIEnv*, + jbooleanArray, + jsize, + jsize, + const jboolean*); + + void(JNICALL* SetByteArrayRegion)(JNIEnv*, + jbyteArray, + jsize, + jsize, + const jbyte*); + + void(JNICALL* SetCharArrayRegion)(JNIEnv*, + jcharArray, + jsize, + jsize, + const jchar*); + + void(JNICALL* SetShortArrayRegion)(JNIEnv*, + jshortArray, + jsize, + jsize, + const jshort*); + + void(JNICALL* SetIntArrayRegion)(JNIEnv*, + jintArray, + jsize, + jsize, + const jint*); + + void(JNICALL* SetLongArrayRegion)(JNIEnv*, + jlongArray, + jsize, + jsize, + const jlong*); + + void(JNICALL* SetFloatArrayRegion)(JNIEnv*, + jfloatArray, + jsize, + jsize, + const jfloat*); + + void(JNICALL* SetDoubleArrayRegion)(JNIEnv*, + jdoubleArray, + jsize, + jsize, + const jdouble*); + + jint(JNICALL* RegisterNatives)(JNIEnv*, jclass, const JNINativeMethod*, jint); + + jint(JNICALL* UnregisterNatives)(JNIEnv*, jclass); + + jint(JNICALL* MonitorEnter)(JNIEnv*, jobject); + + jint(JNICALL* MonitorExit)(JNIEnv*, jobject); + + jint(JNICALL* GetJavaVM)(JNIEnv*, JavaVM**); + + void(JNICALL* GetStringRegion)(JNIEnv*, jstring, jsize, jsize, jchar*); + + void(JNICALL* GetStringUTFRegion)(JNIEnv*, jstring, jsize, jsize, char*); + + void*(JNICALL* GetPrimitiveArrayCritical)(JNIEnv*, jarray, jboolean*); + + void(JNICALL* ReleasePrimitiveArrayCritical)(JNIEnv*, jarray, void*, jint); + + const jchar*(JNICALL* GetStringCritical)(JNIEnv*, jstring, jboolean*); + + void(JNICALL* ReleaseStringCritical)(JNIEnv*, jstring, const jchar*); + + jweak(JNICALL* NewWeakGlobalRef)(JNIEnv*, jobject); + + void(JNICALL* DeleteWeakGlobalRef)(JNIEnv*, jweak); + + jboolean(JNICALL* ExceptionCheck)(JNIEnv*); + + jobject(JNICALL* NewDirectByteBuffer)(JNIEnv*, void*, jlong); + + void*(JNICALL* GetDirectBufferAddress)(JNIEnv* env, jobject); + + jlong(JNICALL* GetDirectBufferCapacity)(JNIEnv*, jobject); +}; + +inline void atomicOr(uint32_t* p, int v) +{ + for (uint32_t old = *p; not atomicCompareAndSwap32(p, old, old | v); + old = *p) { + } +} + +inline void atomicAnd(uint32_t* p, int v) +{ + for (uint32_t old = *p; not atomicCompareAndSwap32(p, old, old & v); + old = *p) { + } +} + +inline int strcmp(const int8_t* a, const int8_t* b) +{ + return ::strcmp(reinterpret_cast(a), + reinterpret_cast(b)); +} + +void noop(); + +class Reference { + public: + Reference(object target, Reference** handle, bool weak) + : target(target), next(*handle), handle(handle), count(0), weak(weak) + { + if (next) { + next->handle = &next; + } + *handle = this; + } + + object target; + Reference* next; + Reference** handle; + unsigned count; + bool weak; +}; + +class Classpath; + +class Gc { + public: + enum Type { +#include "type-enums.cpp" + }; +}; + +class GcObject { + public: + template + T* as(Thread* t); + + template + bool isa(Thread* t); + + protected: + template + T& field_at(size_t offset) + { + return *reinterpret_cast(reinterpret_cast(this) + offset); + } +}; + +class GcFinalizer; +class GcClassLoader; +class GcJreference; +class GcArray; +class GcThrowable; +class GcRoots; + +class Machine { + public: + enum AllocationType { + MovableAllocation, + FixedAllocation, + ImmortalAllocation + }; + + Machine(System* system, + Heap* heap, + Finder* bootFinder, + Finder* appFinder, + Processor* processor, + Classpath* classpath, + const char** properties, + unsigned propertyCount, + const char** arguments, + unsigned argumentCount, + unsigned stackSizeInBytes); + + ~Machine() + { + dispose(); + } + + void dispose(); + + JavaVMVTable* vtable; + System* system; + Heap::Client* heapClient; + Heap* heap; + Finder* bootFinder; + Finder* appFinder; + Processor* processor; + Classpath* classpath; + Thread* rootThread; + Thread* exclusive; + Thread* finalizeThread; + Reference* jniReferences; + char** properties; + unsigned propertyCount; + const char** arguments; + unsigned argumentCount; + unsigned threadCount; + unsigned activeCount; + unsigned liveCount; + unsigned daemonCount; + unsigned fixedFootprint; + unsigned stackSizeInBytes; + System::Local* localThread; + System::Monitor* stateLock; + System::Monitor* heapLock; + System::Monitor* classLock; + System::Monitor* referenceLock; + System::Monitor* shutdownLock; + System::Library* libraries; + FILE* errorLog; + BootImage* bootimage; + GcArray* types; + GcRoots* roots; + GcFinalizer* finalizers; + GcFinalizer* tenuredFinalizers; + GcFinalizer* finalizeQueue; + GcJreference* weakReferences; + GcJreference* tenuredWeakReferences; + bool unsafe; + bool collecting; + bool triedBuiltinOnLoad; + bool dumpedHeapOnOOM; + bool alive; + JavaVMVTable javaVMVTable; + JNIEnvVTable jniEnvVTable; + uintptr_t* heapPool[ThreadHeapPoolSize]; + unsigned heapPoolIndex; + size_t bootimageSize; +}; + +void printTrace(Thread* t, GcThrowable* exception); + +void enterActiveState(Thread* t); + +#ifdef VM_STRESS + +inline void stress(Thread* t); + +#else // not VM_STRESS + +#define stress(t) + +#endif // not VM_STRESS + +uint64_t runThread(Thread*, uintptr_t*); + +uint64_t run(Thread* t, + uint64_t (*function)(Thread*, uintptr_t*), + uintptr_t* arguments); + +void checkDaemon(Thread* t); + +GcRoots* roots(Thread* t); + +extern "C" uint64_t vmRun(uint64_t (*function)(Thread*, uintptr_t*), + uintptr_t* arguments, + void* checkpoint); + +extern "C" void vmRun_returnAddress(); + +class GcThread; +class GcThrowable; +class GcString; + +class Thread { + public: + enum State { + NoState, + ActiveState, + IdleState, + ZombieState, + JoinedState, + ExclusiveState, + ExitState + }; + + enum Flag { + UseBackupHeapFlag = 1 << 0, + WaitingFlag = 1 << 1, + TracingFlag = 1 << 2, + DaemonFlag = 1 << 3, + StressFlag = 1 << 4, + ActiveFlag = 1 << 5, + SystemFlag = 1 << 6, + JoinFlag = 1 << 7, + TryNativeFlag = 1 << 8 + }; + + class Protector { + public: + Protector(Thread* t) : t(t), next(t->protector) + { + t->protector = this; + } + + ~Protector() + { + t->protector = next; + } + + virtual void visit(Heap::Visitor* v) = 0; + + Thread* t; + Protector* next; + }; + + class SingleProtector : public Protector { + public: + SingleProtector(Thread* t, void* p) : Protector(t), p(p) + { + } + + virtual void visit(Heap::Visitor* v) + { + v->visit(p); + } + + void* p; + }; + + class Resource { + public: + Resource(Thread* t, Resource* next) : t(t), next(next) + { + t->resource = this; + } + + virtual void release() = 0; + + Thread* t; + Resource* next; + }; + + class AutoResource : public Resource { + public: + AutoResource(Thread* t) : Resource(t, t->resource) + { + } + + ~AutoResource() + { + t->resource = next; + } + + virtual void release() = 0; + }; + + class ClassInitStack : public AutoResource { + public: + ClassInitStack(Thread* t, GcClass* class_) + : AutoResource(t), + next(t->classInitStack), + class_(class_), + protector(t, &(this->class_)) + { + t->classInitStack = this; + } + + ~ClassInitStack() + { + t->classInitStack = next; + } + + virtual void release() + { + this->ClassInitStack::~ClassInitStack(); + } + + ClassInitStack* next; + GcClass* class_; + SingleProtector protector; + }; + + class LibraryLoadStack : public AutoResource { + public: + LibraryLoadStack(Thread* t, GcClassLoader* classLoader) + : AutoResource(t), + next(t->libraryLoadStack), + classLoader(classLoader), + protector(t, &(this->classLoader)) + { + t->libraryLoadStack = this; + } + + ~LibraryLoadStack() + { + t->libraryLoadStack = next; + } + + virtual void release() + { + this->LibraryLoadStack::~LibraryLoadStack(); + } + + LibraryLoadStack* next; + GcClassLoader* classLoader; + SingleProtector protector; + }; + + class Checkpoint { + public: + Checkpoint(Thread* t) + : t(t), + next(t->checkpoint), + resource(t->resource), + protector(t->protector), + noThrow(false) + { + t->checkpoint = this; + } + + ~Checkpoint() + { + t->checkpoint = next; + } + + virtual void NO_RETURN unwind() = 0; + + Thread* t; + Checkpoint* next; + Resource* resource; + Protector* protector; + bool noThrow; + }; + + class RunCheckpoint : public Checkpoint { + public: + RunCheckpoint(Thread* t) : Checkpoint(t), stack(0) + { + } + + virtual void unwind() + { + void* stack = this->stack; + this->stack = 0; + expect(t->m->system, stack); + vmJump(voidPointer(vmRun_returnAddress), 0, stack, t, 0, 0); + } + + void* stack; + }; + + class Runnable : public System::Runnable { + public: + Runnable(Thread* t) : t(t) + { + } + + virtual void attach(System::Thread* st) + { + t->systemThread = st; + } + + virtual void run(); + + virtual bool interrupted(); + + virtual void setInterrupted(bool v); + + Thread* t; + }; + + Thread(Machine* m, GcThread* javaThread, Thread* parent); + + void init(); + void exit(); + void dispose(); + + void setFlag(Flag flag) { + atomicOr(&flags, flag); + } + + void clearFlag(Flag flag) { + atomicAnd(&flags, ~flag); + } + + unsigned getFlags() { + return flags; + } + + JNIEnvVTable* vtable; + Machine* m; + Thread* parent; + Thread* peer; + Thread* child; + Thread* waitNext; + State state; + unsigned criticalLevel; + System::Thread* systemThread; + System::Monitor* lock; + GcThread* javaThread; + GcThrowable* exception; + unsigned heapIndex; + unsigned heapOffset; + Protector* protector; + ClassInitStack* classInitStack; + LibraryLoadStack* libraryLoadStack; + Resource* resource; + Checkpoint* checkpoint; + Runnable runnable; + uintptr_t* defaultHeap; + uintptr_t* heap; + uintptr_t backupHeap[ThreadBackupHeapSizeInWords]; + unsigned backupHeapIndex; + + private: + unsigned flags; +}; + +class GcJfield; + +class Classpath { + public: + virtual GcJclass* makeJclass(Thread* t, GcClass* class_) = 0; + + virtual GcString* makeString(Thread* t, + object array, + int32_t offset, + int32_t length) = 0; + + virtual GcThread* makeThread(Thread* t, Thread* parent) = 0; + + virtual object makeJMethod(Thread* t, GcMethod* vmMethod) = 0; + + virtual GcMethod* getVMMethod(Thread* t, object jmethod) = 0; + + virtual object makeJField(Thread* t, GcField* vmField) = 0; + + virtual GcField* getVMField(Thread* t, GcJfield* jfield) = 0; + + virtual void clearInterrupted(Thread* t) = 0; + + virtual void runThread(Thread* t) = 0; + + virtual void resolveNative(Thread* t, GcMethod* method) = 0; + + virtual void interceptMethods(Thread* t) = 0; + + virtual void preBoot(Thread* t) = 0; + + virtual bool mayInitClasses() = 0; + + virtual void boot(Thread* t) = 0; + + virtual const char* bootClasspath() = 0; + + virtual object makeDirectByteBuffer(Thread* t, void* p, jlong capacity) = 0; + + virtual void* getDirectBufferAddress(Thread* t, object buffer) = 0; + + virtual int64_t getDirectBufferCapacity(Thread* t, object buffer) = 0; + + virtual bool canTailCall(Thread* t, + GcMethod* caller, + GcByteArray* calleeClassName, + GcByteArray* calleeMethodName, + GcByteArray* calleeMethodSpec) = 0; + + virtual GcClassLoader* libraryClassLoader(Thread* t, GcMethod* caller) = 0; + + virtual void shutDown(Thread* t) = 0; + + virtual void dispose() = 0; +}; + +#ifdef _MSC_VER + +template +class ThreadRuntimeArray : public Thread::AutoResource { + public: + ThreadRuntimeArray(Thread* t, unsigned size) + : AutoResource(t), + body(static_cast(t->m->heap->allocate(size * sizeof(T)))), + size(size) + { + } + + ~ThreadRuntimeArray() + { + t->m->heap->free(body, size * sizeof(T)); + } + + virtual void release() + { + ThreadRuntimeArray::~ThreadRuntimeArray(); + } + + T* body; + unsigned size; +}; + +#define THREAD_RUNTIME_ARRAY(thread, type, name, size) \ + ThreadRuntimeArray name(thread, size); + +#else // not _MSC_VER + +#define THREAD_RUNTIME_ARRAY(thread, type, name, size) type name##_body[size]; + +#endif // not _MSC_VER + +Classpath* makeClasspath(System* system, + Allocator* allocator, + const char* javaHome, + const char* embedPrefix); + +typedef uint64_t(JNICALL* FastNativeFunction)(Thread*, GcMethod*, uintptr_t*); +typedef void(JNICALL* FastVoidNativeFunction)(Thread*, GcMethod*, uintptr_t*); + +inline GcClass* objectClass(Thread*, object o) +{ + return reinterpret_cast( + maskAlignedPointer(fieldAtOffset(o, 0))); +} + +inline unsigned stackSizeInWords(Thread* t) +{ + return t->m->stackSizeInBytes / BytesPerWord; +} + +void enter(Thread* t, Thread::State state); + +inline void enterActiveState(Thread* t) +{ + enter(t, Thread::ActiveState); +} + +class StateResource : public Thread::AutoResource { + public: + StateResource(Thread* t, Thread::State state) + : AutoResource(t), oldState(t->state) + { + enter(t, state); + } + + ~StateResource() + { + enter(t, oldState); + } + + virtual void release() + { + this->StateResource::~StateResource(); + } + + private: + Thread::State oldState; +}; + +inline void dispose(Thread* t, Reference* r) +{ + *(r->handle) = r->next; + if (r->next) { + r->next->handle = r->handle; + } + t->m->heap->free(r, sizeof(*r)); +} + +inline void acquire(Thread*, Reference* r) +{ + ++r->count; +} + +inline void release(Thread* t, Reference* r) +{ + if ((--r->count) == 0) { + dispose(t, r); + } +} + +void collect(Thread* t, Heap::CollectionType type, int pendingAllocation = 0); + +void shutDown(Thread* t); + +#ifdef VM_STRESS + +inline void stress(Thread* t) +{ + if ((not t->m->unsafe) + and (t->getFlags() & (Thread::StressFlag | Thread::TracingFlag)) == 0 + and t->state != Thread::NoState and t->state != Thread::IdleState) { + t->setFlag(Thread::StressFlag); + +#ifdef VM_STRESS_MAJOR + collect(t, Heap::MajorCollection); +#else // not VM_STRESS_MAJOR + collect(t, Heap::MinorCollection); +#endif // not VM_STRESS_MAJOR + + t->clearFlag(Thread::StressFlag); + } +} + +#endif // not VM_STRESS + +inline void acquire(Thread* t, System::Monitor* m) +{ + if (not m->tryAcquire(t->systemThread)) { + ENTER(t, Thread::IdleState); + m->acquire(t->systemThread); + } + + stress(t); +} + +inline void release(Thread* t, System::Monitor* m) +{ + m->release(t->systemThread); +} + +class MonitorResource : public Thread::AutoResource { + public: + MonitorResource(Thread* t, System::Monitor* m) : AutoResource(t), m(m) + { + acquire(t, m); + } + + ~MonitorResource() + { + vm::release(t, m); + } + + virtual void release() + { + this->MonitorResource::~MonitorResource(); + } + + private: + System::Monitor* m; +}; + +class RawMonitorResource : public Thread::Resource { + public: + RawMonitorResource(Thread* t, System::Monitor* m) + : Resource(t, t->resource), m(m) + { + m->acquire(t->systemThread); + } + + ~RawMonitorResource() + { + t->resource = next; + vm::release(t, m); + } + + virtual void release() + { + this->RawMonitorResource::~RawMonitorResource(); + } + + private: + System::Monitor* m; +}; + +inline Aborter* getAborter(Thread* t) +{ + return t->m->system; +} + +inline bool ensure(Thread* t, unsigned sizeInBytes) +{ + if (t->heapIndex + ceilingDivide(sizeInBytes, BytesPerWord) + > ThreadHeapSizeInWords) { + if (sizeInBytes <= ThreadBackupHeapSizeInBytes) { + expect(t, (t->getFlags() & Thread::UseBackupHeapFlag) == 0); + + t->setFlag(Thread::UseBackupHeapFlag); + + return true; + } else { + return false; + } + } else { + return true; + } +} + +object allocate2(Thread* t, unsigned sizeInBytes, bool objectMask); + +object allocate3(Thread* t, + Alloc* allocator, + Machine::AllocationType type, + unsigned sizeInBytes, + bool objectMask); + +inline object allocateSmall(Thread* t, unsigned sizeInBytes) +{ + assertT(t, + t->heapIndex + ceilingDivide(sizeInBytes, BytesPerWord) + <= ThreadHeapSizeInWords); + + object o = reinterpret_cast(t->heap + t->heapIndex); + t->heapIndex += ceilingDivide(sizeInBytes, BytesPerWord); + return o; +} + +inline object allocate(Thread* t, unsigned sizeInBytes, bool objectMask) +{ + stress(t); + + if (UNLIKELY(t->heapIndex + ceilingDivide(sizeInBytes, BytesPerWord) + > ThreadHeapSizeInWords or t->m->exclusive)) { + return allocate2(t, sizeInBytes, objectMask); + } else { + assertT(t, t->criticalLevel == 0); + return allocateSmall(t, sizeInBytes); + } +} + +inline void mark(Thread* t, object o, unsigned offset, unsigned count) +{ + t->m->heap->mark(o, offset / BytesPerWord, count); +} + +inline void mark(Thread* t, object o, unsigned offset) +{ + t->m->heap->mark(o, offset / BytesPerWord, 1); +} + +inline void setField(Thread* t, object target, unsigned offset, object value) +{ + fieldAtOffset(target, offset) = value; + mark(t, target, offset); +} + +inline void setObject(Thread* t, + GcObject* target, + unsigned offset, + GcObject* value) +{ + setField(t, target, offset, value); +} + +inline void setObjectClass(Thread*, object o, GcClass* c) +{ + fieldAtOffset(o, 0) = reinterpret_cast( + reinterpret_cast(c) + | (reinterpret_cast(fieldAtOffset(o, 0)) + & (~PointerMask))); +} + +inline const char* findProperty(Machine* m, const char* name) +{ + for (unsigned i = 0; i < m->propertyCount; ++i) { + const char* p = m->properties[i]; + const char* n = name; + while (*p and *p != '=' and *n and *p == *n) { + ++p; + ++n; + } + if (*p == '=' and *n == 0) { + return p + 1; + } + } + return 0; +} + +inline const char* findProperty(Thread* t, const char* name) +{ + return findProperty(t->m, name); +} + +object arrayBodyUnsafe(Thread*, GcArray*, unsigned); + +bool instanceOf(Thread* t, GcClass* class_, object o); + +template +T* GcObject::as(Thread* t UNUSED) +{ + assertT(t, + t->m->unsafe || instanceOf(t, + reinterpret_cast(arrayBodyUnsafe( + t, t->m->types, T::Type)), + this)); + return static_cast(this); +} + +template +bool GcObject::isa(Thread* t) +{ + return instanceOf( + t, + reinterpret_cast(arrayBodyUnsafe(t, t->m->types, T::Type)), + this); +} + +template +T* cast(Thread* t UNUSED, object o) +{ + if (o == 0) { + return 0; + } + assertT(t, + t->m->unsafe || instanceOf(t, + reinterpret_cast(arrayBodyUnsafe( + t, t->m->types, T::Type)), + o)); + return reinterpret_cast(o); +} + +#include "type-declarations.cpp" + +inline object arrayBodyUnsafe(Thread*, GcArray* a, unsigned index) +{ + return a->body()[index]; +} + +inline void Thread::Runnable::run() +{ + enterActiveState(t); + + vm::run(t, runThread, 0); + + if (t->exception and t->exception != roots(t)->shutdownInProgress()) { + printTrace(t, t->exception); + } + + t->exit(); +} + +inline bool Thread::Runnable::interrupted() +{ + return t->javaThread and t->javaThread->interrupted(); +} + +inline void Thread::Runnable::setInterrupted(bool v) +{ + t->javaThread->interrupted() = v; +} + +inline uint64_t runRaw(Thread* t, + uint64_t (*function)(Thread*, uintptr_t*), + uintptr_t* arguments) +{ + Thread::RunCheckpoint checkpoint(t); + return vmRun(function, arguments, &checkpoint); +} + +inline uint64_t run(Thread* t, + uint64_t (*function)(Thread*, uintptr_t*), + uintptr_t* arguments) +{ + ENTER(t, Thread::ActiveState); + return runRaw(t, function, arguments); +} + +inline void runJavaThread(Thread* t) +{ + t->m->classpath->runThread(t); +} + +void runFinalizeThread(Thread* t); + +inline uint64_t runThread(Thread* t, uintptr_t*) +{ + t->m->localThread->set(t); + + checkDaemon(t); + + if (t == t->m->finalizeThread) { + runFinalizeThread(t); + } else if (t->javaThread) { + runJavaThread(t); + } + + return 1; +} + +inline bool startThread(Thread* t, Thread* p) +{ + p->setFlag(Thread::JoinFlag); +#ifdef SGX + static const char16_t *nameToSkip = u"Reference Handler"; + if (p->javaThread->name()->length(t) == 17) { + if (!memcmp(nameToSkip, cast(t, p->javaThread->name()->data())->body().begin(), 17 * 2)) { + printf("Skipping start of reference handler thread\n"); + return true; + } + } +#endif + return t->m->system->success(t->m->system->start(&(p->runnable))); +} + +inline void addThread(Thread* t, Thread* p) +{ + ACQUIRE_RAW(t, t->m->stateLock); + + assertT(t, p->state == Thread::NoState); + expect(t, + t->state == Thread::ActiveState || t->state == Thread::ExclusiveState + || t->state == Thread::NoState); + + p->state = Thread::IdleState; + ++t->m->threadCount; + ++t->m->liveCount; + + p->peer = p->parent->child; + p->parent->child = p; + + if (p->javaThread) { + p->javaThread->peer() = reinterpret_cast(p); + } +} + +inline void removeThread(Thread* t, Thread* p) +{ + ACQUIRE_RAW(t, t->m->stateLock); + + assertT(t, p->state == Thread::IdleState); + + --t->m->liveCount; + --t->m->threadCount; + + t->m->stateLock->notifyAll(t->systemThread); + + p->parent->child = p->peer; + + if (p->javaThread) { + p->javaThread->peer() = 0; + } + + p->dispose(); +} + +inline Thread* startThread(Thread* t, GcThread* javaThread) +{ + { + PROTECT(t, javaThread); + + stress(t); + + ACQUIRE_RAW(t, t->m->stateLock); + + if (t->m->threadCount > t->m->liveCount + ZombieCollectionThreshold) { + collect(t, Heap::MinorCollection); + } + } + + Thread* p = t->m->processor->makeThread(t->m, javaThread, t); + + addThread(t, p); + + if (startThread(t, p)) { + return p; + } else { + removeThread(t, p); + return 0; + } +} + +inline void registerDaemon(Thread* t) +{ + ACQUIRE_RAW(t, t->m->stateLock); + + t->setFlag(Thread::DaemonFlag); + + ++t->m->daemonCount; + + t->m->stateLock->notifyAll(t->systemThread); +} + +inline void checkDaemon(Thread* t) +{ + if (t->javaThread->daemon()) { + registerDaemon(t); + } +} + +inline uint64_t initAttachedThread(Thread* t, uintptr_t* arguments) +{ + bool daemon = arguments[0]; + + t->javaThread = t->m->classpath->makeThread(t, t->m->rootThread); + + t->javaThread->peer() = reinterpret_cast(t); + + if (daemon) { + t->javaThread->daemon() = true; + + registerDaemon(t); + } + + t->m->localThread->set(t); + + return 1; +} + +inline Thread* attachThread(Machine* m, bool daemon) +{ + Thread* t = m->processor->makeThread(m, 0, m->rootThread); + m->system->attach(&(t->runnable)); + + addThread(t, t); + + enter(t, Thread::ActiveState); + + uintptr_t arguments[] = {daemon}; + + if (run(t, initAttachedThread, arguments)) { + enter(t, Thread::IdleState); + return t; + } else { + t->exit(); + return 0; + } +} + +inline GcRoots* roots(Thread* t) +{ + return t->m->roots; +} + +inline GcClass* type(Thread* t, Gc::Type type) +{ + return cast(t, t->m->types->body()[type]); +} + +inline void setType(Thread* t, Gc::Type type, GcClass* value) +{ + t->m->types->setBodyElement(t, type, value); +} + +inline bool objectFixed(Thread*, object o) +{ + return (alias(o, 0) & (~PointerMask)) == FixedMark; +} + +inline bool objectExtended(Thread*, object o) +{ + return (alias(o, 0) & (~PointerMask)) == ExtendedMark; +} + +inline bool hashTaken(Thread*, object o) +{ + return (alias(o, 0) & (~PointerMask)) == HashTakenMark; +} + +inline unsigned baseSize(Thread* t UNUSED, object o, GcClass* class_) +{ + assertT(t, class_->fixedSize() >= BytesPerWord); + + unsigned size = ceilingDivide(class_->fixedSize(), BytesPerWord); + if (class_->arrayElementSize() > 0) { + size += ceilingDivide(class_->arrayElementSize() + * fieldAtOffset( + o, class_->fixedSize() - BytesPerWord), + BytesPerWord); + } + return size; +} + +object makeTrace(Thread* t, Processor::StackWalker* walker); + +object makeTrace(Thread* t, Thread* target); + +inline object makeTrace(Thread* t) +{ + return makeTrace(t, t); +} + +inline object makeNew(Thread* t, GcClass* class_) +{ + assertT(t, t->state == Thread::NoState or t->state == Thread::ActiveState); + + PROTECT(t, class_); + unsigned sizeInBytes = pad(class_->fixedSize()); + assertT(t, sizeInBytes); + object instance = allocate(t, sizeInBytes, class_->objectMask()); + setObjectClass(t, instance, class_); + + return instance; +} + +object makeNewGeneral(Thread* t, GcClass* class_); + +inline object make(Thread* t, GcClass* class_) +{ + if (UNLIKELY(class_->vmFlags() & (WeakReferenceFlag | HasFinalizerFlag))) { + return makeNewGeneral(t, class_); + } else { + return makeNew(t, class_); + } +} + +GcByteArray* makeByteArrayV(Thread* t, const char* format, va_list a, int size); + +GcByteArray* makeByteArray(Thread* t, const char* format, ...); + +GcString* makeString(Thread* t, const char* format, ...); + +#ifndef HAVE_StringOffset + +inline uint32_t GcString::length(Thread* t) +{ + return cast(t, this->data())->length(); +} + +inline uint32_t GcString::offset(Thread*) +{ + return 0; +} + +#ifndef HAVE_StringHash32 + +inline GcString* makeString(Thread* t, object data, int32_t hash, int32_t) +{ + return makeString(t, data, hash); +} + +#endif // not HAVE_StringHash32 + +inline GcString* makeString(Thread* t, + object odata, + unsigned offset, + unsigned length, + unsigned) +{ + GcCharArray* data = cast(t, odata); + if (offset == 0 and length == data->length()) { + return makeString(t, reinterpret_cast(data), 0, 0); + } else { + PROTECT(t, data); + + GcCharArray* array = makeCharArray(t, length); + + memcpy(array->body().begin(), &data->body()[offset], length * 2); + + return makeString(t, reinterpret_cast(array), 0, 0); + } +} + +#endif // not HAVE_StringOffset + +int stringUTFLength(Thread* t, + GcString* string, + unsigned start, + unsigned length); + +inline int stringUTFLength(Thread* t, GcString* string) +{ + return stringUTFLength(t, string, 0, string->length(t)); +} + +void stringChars(Thread* t, + GcString* string, + unsigned start, + unsigned length, + char* chars); + +inline void stringChars(Thread* t, GcString* string, char* chars) +{ + stringChars(t, string, 0, string->length(t), chars); +} + +void stringChars(Thread* t, + GcString* string, + unsigned start, + unsigned length, + uint16_t* chars); + +inline void stringChars(Thread* t, GcString* string, uint16_t* chars) +{ + stringChars(t, string, 0, string->length(t), chars); +} + +void stringUTFChars(Thread* t, + GcString* string, + unsigned start, + unsigned length, + char* chars, + unsigned charsLength); + +inline void stringUTFChars(Thread* t, + GcString* string, + char* chars, + unsigned charsLength) +{ + stringUTFChars(t, string, 0, string->length(t), chars, charsLength); +} + +bool isAssignableFrom(Thread* t, GcClass* a, GcClass* b); + +GcMethod* classInitializer(Thread* t, GcClass* class_); + +object frameMethod(Thread* t, int frame); + +inline uintptr_t& extendedWord(Thread* t UNUSED, object o, unsigned baseSize) +{ + assertT(t, objectExtended(t, o)); + return fieldAtOffset(o, baseSize * BytesPerWord); +} + +inline unsigned extendedSize(Thread* t, object o, unsigned baseSize) +{ + return baseSize + objectExtended(t, o); +} + +inline void markHashTaken(Thread* t, object o) +{ + assertT(t, not objectExtended(t, o)); + assertT(t, not objectFixed(t, o)); + + ACQUIRE_RAW(t, t->m->heapLock); + + alias(o, 0) |= HashTakenMark; + t->m->heap->pad(o); +} + +inline uint32_t takeHash(Thread*, object o) +{ + // some broken code implicitly relies on System.identityHashCode + // always returning a non-negative number (e.g. old versions of + // com/sun/xml/bind/v2/util/CollisionCheckStack.hash), hence the "& + // 0x7FFFFFFF": + return (reinterpret_cast(o) / BytesPerWord) & 0x7FFFFFFF; +} + +inline uint32_t objectHash(Thread* t, object o) +{ + if (objectExtended(t, o)) { + return extendedWord(t, o, baseSize(t, o, objectClass(t, o))); + } else { + if (not objectFixed(t, o)) { + markHashTaken(t, o); + } + return takeHash(t, o); + } +} + +inline bool objectEqual(Thread*, object a, object b) +{ + return a == b; +} + +inline uint32_t byteArrayHash(Thread* t UNUSED, object ao) +{ + GcByteArray* a = cast(t, ao); + return hash(a->body()); +} + +inline uint32_t charArrayHash(Thread* t UNUSED, object ao) +{ + GcByteArray* a = cast(t, ao); + return hash(a->body()); +} + +inline bool byteArrayEqual(Thread* t UNUSED, object ao, object bo) +{ + GcByteArray* a = cast(t, ao); + GcByteArray* b = cast(t, bo); + return a == b + or ((a->length() == b->length()) + and memcmp(a->body().begin(), b->body().begin(), a->length()) + == 0); +} + +inline uint32_t stringHash(Thread* t, object so) +{ + GcString* s = cast(t, so); + if (s->hashCode() == 0 and s->length(t)) { + if (objectClass(t, s->data()) == type(t, GcByteArray::Type)) { + s->hashCode() = hash(cast(t, s->data())->body().subslice( + s->offset(t), s->length(t))); + } else { + s->hashCode() = hash(cast(t, s->data())->body().subslice( + s->offset(t), s->length(t))); + } + } + return s->hashCode(); +} + +inline uint16_t stringCharAt(Thread* t, GcString* s, int i) +{ + if (objectClass(t, s->data()) == type(t, GcByteArray::Type)) { + return cast(t, s->data())->body()[s->offset(t) + i]; + } else { + return cast(t, s->data())->body()[s->offset(t) + i]; + } +} + +inline bool stringEqual(Thread* t, object ao, object bo) +{ + GcString* a = cast(t, ao); + GcString* b = cast(t, bo); + if (a == b) { + return true; + } else if (a->length(t) == b->length(t)) { + for (unsigned i = 0; i < a->length(t); ++i) { + if (stringCharAt(t, a, i) != stringCharAt(t, b, i)) { + return false; + } + } + return true; + } else { + return false; + } +} + +inline uint32_t methodHash(Thread* t, object mo) +{ + GcMethod* method = cast(t, mo); + return byteArrayHash(t, method->name()) ^ byteArrayHash(t, method->spec()); +} + +inline bool methodEqual(Thread* t, object ao, object bo) +{ + GcMethod* a = cast(t, ao); + GcMethod* b = cast(t, bo); + return a == b or (byteArrayEqual(t, a->name(), b->name()) + and byteArrayEqual(t, a->spec(), b->spec())); +} + +class MethodSpecIterator { + public: + MethodSpecIterator(Thread* t, const char* s) : t(t), s(s + 1) + { + } + + const char* next() + { + assertT(t, *s != ')'); + + const char* p = s; + + switch (*s) { + case 'L': + while (*s and *s != ';') + ++s; + ++s; + break; + + case '[': + while (*s == '[') + ++s; + switch (*s) { + case 'L': + while (*s and *s != ';') + ++s; + ++s; + break; + + default: + ++s; + break; + } + break; + + default: + ++s; + break; + } + + return p; + } + + bool hasNext() + { + return *s != ')'; + } + + const char* returnSpec() + { + assertT(t, *s == ')'); + return s + 1; + } + + Thread* t; + const char* s; +}; + +unsigned fieldCode(Thread* t, unsigned javaCode); + +unsigned fieldType(Thread* t, unsigned code); + +unsigned primitiveSize(Thread* t, unsigned code); + +inline unsigned fieldSize(Thread* t, unsigned code) +{ + if (code == ObjectField) { + return BytesPerWord; + } else { + return primitiveSize(t, code); + } +} + +inline unsigned fieldSize(Thread* t, GcField* field) +{ + return fieldSize(t, field->code()); +} + +inline void scanMethodSpec(Thread* t, + const char* s, + bool static_, + unsigned* parameterCount, + unsigned* parameterFootprint, + unsigned* returnCode) +{ + unsigned count = 0; + unsigned footprint = 0; + MethodSpecIterator it(t, s); + while (it.hasNext()) { + ++count; + switch (*it.next()) { + case 'J': + case 'D': + footprint += 2; + break; + + default: + ++footprint; + break; + } + } + + if (not static_) { + ++footprint; + } + + *parameterCount = count; + *parameterFootprint = footprint; + *returnCode = fieldCode(t, *it.returnSpec()); +} + +GcClass* findLoadedClass(Thread* t, GcClassLoader* loader, GcByteArray* spec); + +GcJclass* getDeclaringClass(Thread* t, GcClass* c); + +GcCallSite* resolveDynamic(Thread* t, GcInvocation* invocation); + +inline bool emptyMethod(Thread* t UNUSED, GcMethod* method) +{ + return ((method->flags() & ACC_NATIVE) == 0) + and (method->code()->length() == 1) + and (method->code()->body()[0] == return_); +} + +object parseUtf8(Thread* t, const char* data, unsigned length); + +object parseUtf8(Thread* t, GcByteArray* array); + +GcClass* parseClass(Thread* t, + GcClassLoader* loader, + const uint8_t* data, + unsigned length, + Gc::Type throwType = GcNoClassDefFoundError::Type); + +GcClass* resolveClass(Thread* t, + GcClassLoader* loader, + GcByteArray* name, + bool throw_ = true, + Gc::Type throwType = GcNoClassDefFoundError::Type); + +inline GcClass* resolveClass(Thread* t, + GcClassLoader* loader, + const char* name, + bool throw_ = true, + Gc::Type throwType = GcNoClassDefFoundError::Type) +{ + PROTECT(t, loader); + GcByteArray* n = makeByteArray(t, "%s", name); + return resolveClass(t, loader, n, throw_, throwType); +} + +GcClass* resolveSystemClass(Thread* t, + GcClassLoader* loader, + GcByteArray* name, + bool throw_ = true, + Gc::Type throwType = GcNoClassDefFoundError::Type); + +inline GcClass* resolveSystemClass(Thread* t, + GcClassLoader* loader, + const char* name) +{ + return resolveSystemClass(t, loader, makeByteArray(t, "%s", name)); +} + +void linkClass(Thread* t, GcClassLoader* loader, GcClass* class_); + +GcMethod* resolveMethod(Thread* t, + GcClass* class_, + const char* methodName, + const char* methodSpec); + +inline GcMethod* resolveMethod(Thread* t, + GcClassLoader* loader, + const char* className, + const char* methodName, + const char* methodSpec) +{ + return resolveMethod( + t, resolveClass(t, loader, className), methodName, methodSpec); +} + +GcField* resolveField(Thread* t, + GcClass* class_, + const char* fieldName, + const char* fieldSpec); + +inline GcField* resolveField(Thread* t, + GcClassLoader* loader, + const char* className, + const char* fieldName, + const char* fieldSpec) +{ + return resolveField( + t, resolveClass(t, loader, className), fieldName, fieldSpec); +} + +bool classNeedsInit(Thread* t, GcClass* c); + +bool preInitClass(Thread* t, GcClass* c); + +void postInitClass(Thread* t, GcClass* c); + +void initClass(Thread* t, GcClass* c); + +GcClass* resolveObjectArrayClass(Thread* t, + GcClassLoader* loader, + GcClass* elementClass); + +object makeObjectArray(Thread* t, GcClass* elementClass, unsigned count); + +inline object makeObjectArray(Thread* t, unsigned count) +{ + return makeObjectArray(t, type(t, GcJobject::Type), count); +} + +object findFieldInClass(Thread* t, + GcClass* class_, + GcByteArray* name, + GcByteArray* spec); + +inline GcField* findFieldInClass2(Thread* t, + GcClass* class_, + const char* name, + const char* spec) +{ + PROTECT(t, class_); + GcByteArray* n = makeByteArray(t, "%s", name); + PROTECT(t, n); + GcByteArray* s = makeByteArray(t, "%s", spec); + return cast(t, findFieldInClass(t, class_, n, s)); +} + +object findMethodInClass(Thread* t, + GcClass* class_, + GcByteArray* name, + GcByteArray* spec); + +inline GcThrowable* makeThrowable(Thread* t, + Gc::Type type, + GcString* message = 0, + object trace = 0, + GcThrowable* cause = 0) +{ + PROTECT(t, message); + PROTECT(t, trace); + PROTECT(t, cause); + + if (trace == 0) { + trace = makeTrace(t); + } + + GcThrowable* result = cast(t, make(t, vm::type(t, type))); + + result->setMessage(t, message); + result->setTrace(t, trace); + result->setCause(t, cause); + + return result; +} + +inline GcThrowable* makeThrowableV(Thread* t, + Gc::Type type, + const char* format, + va_list a, + int size) +{ + GcByteArray* s = makeByteArrayV(t, format, a, size); + + if (s) { + GcString* message = t->m->classpath->makeString(t, s, 0, s->length() - 1); + + return makeThrowable(t, type, message); + } else { + return 0; + } +} + +inline GcThrowable* makeThrowable(Thread* t, + Gc::Type type, + const char* format, + ...) +{ + int size = 256; + while (true) { + va_list a; + va_start(a, format); + GcThrowable* r = makeThrowableV(t, type, format, a, size); + va_end(a); + + if (r) { + return r; + } else { + size *= 2; + } + } +} + +void popResources(Thread* t); + +} // namespace vm + +namespace vm { + +void dumpHeap(Thread* t, FILE* out); + +inline void NO_RETURN throw_(Thread* t, GcThrowable* e) +{ + assertT(t, t->exception == 0); + assertT(t, e); + + expect(t, not t->checkpoint->noThrow); + + t->exception = e; + + if (objectClass(t, e) == type(t, GcOutOfMemoryError::Type)) { + if (not t->m->dumpedHeapOnOOM) { + t->m->dumpedHeapOnOOM = true; + const char* path = findProperty(t, "avian.heap.dump"); + if (path) { + FILE* out = vm::fopen(path, "wb"); + if (out) { + dumpHeap(t, out); + fclose(out); + } + } + } + + if (AbortOnOutOfMemoryError) { + fprintf(stderr, "OutOfMemoryError\n"); + vmPrintTrace(t); + abort(); + } + } + + // printTrace(t, e); + + popResources(t); + + t->checkpoint->unwind(); + + abort(t); +} + +inline void NO_RETURN throwNew(Thread* t, + Gc::Type type, + GcString* message = 0, + object trace = 0, + GcThrowable* cause = 0) +{ + throw_(t, makeThrowable(t, type, message, trace, cause)); +} + +inline void NO_RETURN + throwNew(Thread* t, Gc::Type type, const char* format, ...) +{ + int size = 256; + while (true) { + va_list a; + va_start(a, format); + GcThrowable* r = makeThrowableV(t, type, format, a, size); + va_end(a); + + if (r) { + throw_(t, r); + } else { + size *= 2; + } + } +} + +object findInHierarchyOrNull( + Thread* t, + GcClass* class_, + GcByteArray* name, + GcByteArray* spec, + object (*find)(Thread*, GcClass*, GcByteArray*, GcByteArray*)); + +inline object findInHierarchy( + Thread* t, + GcClass* class_, + GcByteArray* name, + GcByteArray* spec, + object (*find)(Thread*, GcClass*, GcByteArray*, GcByteArray*), + Gc::Type errorType, + bool throw_ = true) +{ + object o = findInHierarchyOrNull(t, class_, name, spec, find); + + if (throw_ and o == 0) { + throwNew(t, + errorType, + "%s %s not found in %s", + name->body().begin(), + spec->body().begin(), + class_->name()->body().begin()); + } + + return o; +} + +inline GcMethod* findMethod(Thread* t, + GcClass* class_, + GcByteArray* name, + GcByteArray* spec) +{ + return cast( + t, + findInHierarchy( + t, class_, name, spec, findMethodInClass, GcNoSuchMethodError::Type)); +} + +inline GcMethod* findMethodOrNull(Thread* t, + GcClass* class_, + const char* name, + const char* spec) +{ + PROTECT(t, class_); + GcByteArray* n = makeByteArray(t, "%s", name); + PROTECT(t, n); + GcByteArray* s = makeByteArray(t, "%s", spec); + return cast( + t, findInHierarchyOrNull(t, class_, n, s, findMethodInClass)); +} + +inline GcMethod* findVirtualMethod(Thread* t, GcMethod* method, GcClass* class_) +{ + return cast( + t, cast(t, class_->virtualTable())->body()[method->offset()]); +} + +inline GcMethod* findInterfaceMethod(Thread* t, + GcMethod* method, + GcClass* class_) +{ + if (UNLIKELY(class_->vmFlags() & BootstrapFlag)) { + PROTECT(t, method); + PROTECT(t, class_); + + resolveSystemClass(t, roots(t)->bootLoader(), class_->name()); + } + + GcClass* interface = method->class_(); + GcArray* itable = cast(t, class_->interfaceTable()); + for (unsigned i = 0; i < itable->length(); i += 2) { + if (itable->body()[i] == interface) { + return cast( + t, cast(t, itable->body()[i + 1])->body()[method->offset()]); + } + } + abort(t); +} + +inline unsigned objectArrayLength(Thread* t UNUSED, object array) +{ + assertT(t, objectClass(t, array)->fixedSize() == BytesPerWord * 2); + assertT(t, objectClass(t, array)->arrayElementSize() == BytesPerWord); + return fieldAtOffset(array, BytesPerWord); +} + +inline object& objectArrayBody(Thread* t UNUSED, object array, unsigned index) +{ + assertT(t, objectClass(t, array)->fixedSize() == BytesPerWord * 2); + assertT(t, objectClass(t, array)->arrayElementSize() == BytesPerWord); + assertT( + t, + objectClass(t, array)->objectMask() + == cast(t, t->m->types->body()[GcArray::Type])->objectMask()); + return fieldAtOffset(array, ArrayBody + (index * BytesPerWord)); +} + +unsigned parameterFootprint(Thread* t, const char* s, bool static_); + +void addFinalizer(Thread* t, object target, void (*finalize)(Thread*, object)); + +inline bool acquireSystem(Thread* t, Thread* target) +{ + ACQUIRE_RAW(t, t->m->stateLock); + + if (t->state != Thread::JoinedState) { + target->setFlag(Thread::SystemFlag); + return true; + } else { + return false; + } +} + +inline void releaseSystem(Thread* t, Thread* target) +{ + ACQUIRE_RAW(t, t->m->stateLock); + + assertT(t, t->state != Thread::JoinedState); + + target->clearFlag(Thread::SystemFlag); +} + +inline bool atomicCompareAndSwapObject(Thread* t, + object target, + unsigned offset, + object old, + object new_) +{ + if (atomicCompareAndSwap(&fieldAtOffset(target, offset), + reinterpret_cast(old), + reinterpret_cast(new_))) { + mark(t, target, offset); + return true; + } else { + return false; + } +} + +// The following two methods (monitorAtomicAppendAcquire and +// monitorAtomicPollAcquire) use the Michael and Scott Non-Blocking +// Queue Algorithm: http://www.cs.rochester.edu/u/michael/PODC96.html + +inline void monitorAtomicAppendAcquire(Thread* t, + GcMonitor* monitor, + GcMonitorNode* node) +{ + if (node == 0) { + PROTECT(t, monitor); + + node = makeMonitorNode(t, t, 0); + } + + while (true) { + GcMonitorNode* tail = cast(t, monitor->acquireTail()); + + loadMemoryBarrier(); + + object next = tail->next(); + + loadMemoryBarrier(); + + if (tail == cast(t, monitor->acquireTail())) { + if (next) { + atomicCompareAndSwapObject(t, monitor, MonitorAcquireTail, tail, next); + } else if (atomicCompareAndSwapObject( + t, tail, MonitorNodeNext, 0, node)) { + atomicCompareAndSwapObject(t, monitor, MonitorAcquireTail, tail, node); + return; + } + } + } +} + +inline Thread* monitorAtomicPollAcquire(Thread* t, + GcMonitor* monitor, + bool remove) +{ + while (true) { + GcMonitorNode* head = cast(t, monitor->acquireHead()); + + loadMemoryBarrier(); + + GcMonitorNode* tail = cast(t, monitor->acquireTail()); + + loadMemoryBarrier(); + + GcMonitorNode* next = cast(t, head->next()); + + loadMemoryBarrier(); + + if (head == cast(t, monitor->acquireHead())) { + if (head == tail) { + if (next) { + atomicCompareAndSwapObject( + t, monitor, MonitorAcquireTail, tail, next); + } else { + return 0; + } + } else { + Thread* value = static_cast(next->value()); + if ((not remove) or atomicCompareAndSwapObject( + t, monitor, MonitorAcquireHead, head, next)) { + return value; + } + } + } + } +} + +inline bool monitorTryAcquire(Thread* t, GcMonitor* monitor) +{ + if (monitor->owner() == t + or (monitorAtomicPollAcquire(t, monitor, false) == 0 + and atomicCompareAndSwap( + reinterpret_cast(&monitor->owner()), + 0, + reinterpret_cast(t)))) { + ++monitor->depth(); + return true; + } else { + return false; + } +} + +inline void monitorAcquire(Thread* t, + GcMonitor* monitor, + GcMonitorNode* node = 0) +{ + if (not monitorTryAcquire(t, monitor)) { + PROTECT(t, monitor); + PROTECT(t, node); + + ACQUIRE(t, t->lock); + + monitorAtomicAppendAcquire(t, monitor, node); + + // note that we don't try to acquire the lock until we're first in + // line, both because it's fair and because we don't support + // removing elements from arbitrary positions in the queue + + while (not(t == monitorAtomicPollAcquire(t, monitor, false) + and atomicCompareAndSwap( + reinterpret_cast(&monitor->owner()), + 0, + reinterpret_cast(t)))) { + ENTER(t, Thread::IdleState); + + t->lock->wait(t->systemThread, 0); + } + + expect(t, t == monitorAtomicPollAcquire(t, monitor, true)); + + ++monitor->depth(); + } + + assertT(t, monitor->owner() == t); +} + +inline void monitorRelease(Thread* t, GcMonitor* monitor) +{ + expect(t, monitor->owner() == t); + + if (--monitor->depth() == 0) { + monitor->owner() = 0; + + storeLoadMemoryBarrier(); + + Thread* next = monitorAtomicPollAcquire(t, monitor, false); + + if (next and acquireSystem(t, next)) { + ACQUIRE(t, next->lock); + + next->lock->notify(t->systemThread); + + releaseSystem(t, next); + } + } +} + +inline void monitorAppendWait(Thread* t, GcMonitor* monitor) +{ + assertT(t, monitor->owner() == t); + + expect(t, (t->getFlags() & Thread::WaitingFlag) == 0); + expect(t, t->waitNext == 0); + + t->setFlag(Thread::WaitingFlag); + + if (monitor->waitTail()) { + static_cast(monitor->waitTail())->waitNext = t; + } else { + monitor->waitHead() = t; + } + + monitor->waitTail() = t; +} + +inline void monitorRemoveWait(Thread* t, GcMonitor* monitor) +{ + assertT(t, monitor->owner() == t); + + Thread* previous = 0; + for (Thread* current = static_cast(monitor->waitHead()); current; + current = current->waitNext) { + if (t == current) { + if (t == monitor->waitHead()) { + monitor->waitHead() = t->waitNext; + } else { + previous->waitNext = t->waitNext; + } + + if (t == monitor->waitTail()) { + assertT(t, t->waitNext == 0); + monitor->waitTail() = previous; + } + + t->waitNext = 0; + t->clearFlag(Thread::WaitingFlag); + + return; + } else { + previous = current; + } + } + + abort(t); +} + +inline bool monitorFindWait(Thread* t, GcMonitor* monitor) +{ + assertT(t, monitor->owner() == t); + + for (Thread* current = static_cast(monitor->waitHead()); current; + current = current->waitNext) { + if (t == current) { + return true; + } + } + + return false; +} + +inline bool monitorWait(Thread* t, GcMonitor* monitor, int64_t time) +{ + expect(t, monitor->owner() == t); + + bool interrupted; + unsigned depth; + + PROTECT(t, monitor); + + // pre-allocate monitor node so we don't get an OutOfMemoryError + // when we try to re-acquire the monitor below + GcMonitorNode* monitorNode = makeMonitorNode(t, t, 0); + PROTECT(t, monitorNode); + + { + ACQUIRE(t, t->lock); + + monitorAppendWait(t, monitor); + + depth = monitor->depth(); + monitor->depth() = 1; + + monitorRelease(t, monitor); + + ENTER(t, Thread::IdleState); + + interrupted = t->lock->waitAndClearInterrupted(t->systemThread, time); + } + + monitorAcquire(t, monitor, monitorNode); + + monitor->depth() = depth; + + if (t->getFlags() & Thread::WaitingFlag) { + monitorRemoveWait(t, monitor); + } else { + expect(t, not monitorFindWait(t, monitor)); + } + + assertT(t, monitor->owner() == t); + + return interrupted; +} + +inline Thread* monitorPollWait(Thread* t UNUSED, GcMonitor* monitor) +{ + assertT(t, monitor->owner() == t); + + Thread* next = static_cast(monitor->waitHead()); + + if (next) { + monitor->waitHead() = next->waitNext; + next->clearFlag(Thread::WaitingFlag); + next->waitNext = 0; + if (next == monitor->waitTail()) { + monitor->waitTail() = 0; + } + } else { + assertT(t, monitor->waitTail() == 0); + } + + return next; +} + +inline bool monitorNotify(Thread* t, GcMonitor* monitor) +{ + expect(t, monitor->owner() == t); + + Thread* next = monitorPollWait(t, monitor); + + if (next) { + ACQUIRE(t, next->lock); + + next->lock->notify(t->systemThread); + + return true; + } else { + return false; + } +} + +inline void monitorNotifyAll(Thread* t, GcMonitor* monitor) +{ + PROTECT(t, monitor); + + while (monitorNotify(t, monitor)) { + } +} + +class ObjectMonitorResource { + public: + ObjectMonitorResource(Thread* t, GcMonitor* o) + : o(o), protector(t, &(this->o)) + { + monitorAcquire(protector.t, o); + } + + ~ObjectMonitorResource() + { + monitorRelease(protector.t, o); + } + + private: + GcMonitor* o; + Thread::SingleProtector protector; +}; + +GcMonitor* objectMonitor(Thread* t, object o, bool createNew); + +inline void acquire(Thread* t, object o) +{ + unsigned hash; + if (DebugMonitors) { + hash = objectHash(t, o); + } + + GcMonitor* m = objectMonitor(t, o, true); + + if (DebugMonitors) { + fprintf(stderr, "thread %p acquires %p for %x\n", t, m, hash); + } + + monitorAcquire(t, m); +} + +inline void release(Thread* t, object o) +{ + unsigned hash; + if (DebugMonitors) { + hash = objectHash(t, o); + } + + GcMonitor* m = objectMonitor(t, o, false); + + if (DebugMonitors) { + fprintf(stderr, "thread %p releases %p for %x\n", t, m, hash); + } + + monitorRelease(t, m); +} + +inline void wait(Thread* t, object o, int64_t milliseconds) +{ + unsigned hash; + if (DebugMonitors) { + hash = objectHash(t, o); + } + + GcMonitor* m = objectMonitor(t, o, false); + + if (DebugMonitors) { + fprintf(stderr, + "thread %p waits %d millis on %p for %x\n", + t, + static_cast(milliseconds), + m, + hash); + } + + if (m and m->owner() == t) { + PROTECT(t, m); + + bool interrupted = monitorWait(t, m, milliseconds); + + if (interrupted) { + if (t->m->alive or (t->getFlags() & Thread::DaemonFlag) == 0) { + t->m->classpath->clearInterrupted(t); + throwNew(t, GcInterruptedException::Type); + } else { + throw_(t, roots(t)->shutdownInProgress()); + } + } + } else { + throwNew(t, GcIllegalMonitorStateException::Type); + } + + if (DebugMonitors) { + fprintf(stderr, "thread %p wakes up on %p for %x\n", t, m, hash); + } + + stress(t); +} + +inline void notify(Thread* t, object o) +{ + unsigned hash; + if (DebugMonitors) { + hash = objectHash(t, o); + } + + GcMonitor* m = objectMonitor(t, o, false); + + if (DebugMonitors) { + fprintf(stderr, "thread %p notifies on %p for %x\n", t, m, hash); + } + + if (m and m->owner() == t) { + monitorNotify(t, m); + } else { + throwNew(t, GcIllegalMonitorStateException::Type); + } +} + +inline void notifyAll(Thread* t, object o) +{ + GcMonitor* m = objectMonitor(t, o, false); + + if (DebugMonitors) { + fprintf(stderr, + "thread %p notifies all on %p for %x\n", + t, + m, + objectHash(t, o)); + } + + if (m and m->owner() == t) { + monitorNotifyAll(t, m); + } else { + throwNew(t, GcIllegalMonitorStateException::Type); + } +} + +inline void interrupt(Thread* t, Thread* target) +{ + if (acquireSystem(t, target)) { + target->systemThread->interrupt(); + releaseSystem(t, target); + } +} + +inline bool getAndClearInterrupted(Thread* t, Thread* target) +{ + if (acquireSystem(t, target)) { + bool result = target->systemThread->getAndClearInterrupted(); + releaseSystem(t, target); + return result; + } else { + return false; + } +} + +inline bool exceptionMatch(Thread* t, GcClass* type, GcThrowable* exception) +{ + return type == 0 or (exception != roots(t)->shutdownInProgress() + and instanceOf(t, type, t->exception)); +} + +object intern(Thread* t, object s); + +object clone(Thread* t, object o); + +void walk(Thread* t, Heap::Walker* w, object o, unsigned start); + +int walkNext(Thread* t, object o, int previous); + +void visitRoots(Machine* m, Heap::Visitor* v); + +inline jobject makeLocalReference(Thread* t, object o) +{ + return t->m->processor->makeLocalReference(t, o); +} + +inline void disposeLocalReference(Thread* t, jobject r) +{ + t->m->processor->disposeLocalReference(t, r); +} + +inline bool methodVirtual(Thread* t UNUSED, GcMethod* method) +{ + return (method->flags() & (ACC_STATIC | ACC_PRIVATE)) == 0 + and method->name()->body()[0] != '<'; +} + +inline unsigned singletonMaskSize(unsigned count, unsigned bitsPerWord) +{ + if (count) { + return ceilingDivide(count + 2, bitsPerWord); + } + return 0; +} + +inline unsigned singletonMaskSize(unsigned count) +{ + return singletonMaskSize(count, BitsPerWord); +} + +inline unsigned singletonMaskSize(Thread* t UNUSED, GcSingleton* singleton) +{ + unsigned length = singleton->length(); + if (length) { + return ceilingDivide(length + 2, BitsPerWord + 1); + } + return 0; +} + +inline unsigned singletonCount(Thread* t, GcSingleton* singleton) +{ + return singleton->length() - singletonMaskSize(t, singleton); +} + +inline uint32_t* singletonMask(Thread* t UNUSED, GcSingleton* singleton) +{ + assertT(t, singleton->length()); + return reinterpret_cast( + &singleton->body()[singletonCount(t, singleton)]); +} + +inline void singletonMarkObject(uint32_t* mask, unsigned index) +{ + mask[(index + 2) / 32] |= (static_cast(1) << ((index + 2) % 32)); +} + +inline void singletonMarkObject(Thread* t, + GcSingleton* singleton, + unsigned index) +{ + singletonMarkObject(singletonMask(t, singleton), index); +} + +inline bool singletonIsObject(Thread* t, GcSingleton* singleton, unsigned index) +{ + assertT(t, index < singletonCount(t, singleton)); + + return (singletonMask(t, singleton)[(index + 2) / 32] + & (static_cast(1) << ((index + 2) % 32))) != 0; +} + +inline object& singletonObject(Thread* t UNUSED, + GcSingleton* singleton, + unsigned index) +{ + assertT(t, singletonIsObject(t, singleton, index)); + return reinterpret_cast(singleton->body()[index]); +} + +inline uintptr_t& singletonValue(Thread* t UNUSED, + GcSingleton* singleton, + unsigned index) +{ + assertT(t, not singletonIsObject(t, singleton, index)); + return singleton->body()[index]; +} + +inline GcSingleton* makeSingletonOfSize(Thread* t, unsigned count) +{ + GcSingleton* o = makeSingleton(t, count + singletonMaskSize(count)); + assertT(t, o->length() == count + singletonMaskSize(t, o)); + if (count) { + singletonMask(t, o)[0] = 1; + } + return o; +} + +inline void singletonSetBit(Thread* t, + GcSingleton* singleton, + unsigned start, + unsigned index) +{ + singletonValue(t, singleton, start + (index / BitsPerWord)) + |= static_cast(1) << (index % BitsPerWord); +} + +inline bool singletonBit(Thread* t, + GcSingleton* singleton, + unsigned start, + unsigned index) +{ + return (singletonValue(t, singleton, start + (index / BitsPerWord)) + & (static_cast(1) << (index % BitsPerWord))) != 0; +} + +inline unsigned poolMaskSize(unsigned count, unsigned bitsPerWord) +{ + return ceilingDivide(count, bitsPerWord); +} + +inline unsigned poolMaskSize(unsigned count) +{ + return poolMaskSize(count, BitsPerWord); +} + +inline unsigned poolMaskSize(Thread* t, GcSingleton* pool) +{ + return ceilingDivide(singletonCount(t, pool), BitsPerWord + 1); +} + +inline unsigned poolSize(Thread* t, GcSingleton* pool) +{ + return singletonCount(t, pool) - poolMaskSize(t, pool); +} + +inline GcClass* resolveClassInObject(Thread* t, + GcClassLoader* loader, + object container, + unsigned classOffset, + bool throw_ = true) +{ + object o = fieldAtOffset(container, classOffset); + + loadMemoryBarrier(); + + if (objectClass(t, o) == type(t, GcByteArray::Type)) { + GcByteArray* name = cast(t, o); + PROTECT(t, container); + + GcClass* c = resolveClass(t, loader, name, throw_); + + if (c) { + storeStoreMemoryBarrier(); + + setField(t, container, classOffset, c); + } + + return c; + } + return cast(t, o); +} + +inline GcClass* resolveClassInPool(Thread* t, + GcClassLoader* loader, + GcMethod* method, + unsigned index, + bool throw_ = true) +{ + object o = singletonObject(t, method->code()->pool(), index); + + loadMemoryBarrier(); + + if (objectClass(t, o) == type(t, GcReference::Type)) { + PROTECT(t, method); + + GcClass* c + = resolveClass(t, loader, cast(t, o)->name(), throw_); + + if (c) { + storeStoreMemoryBarrier(); + + method->code()->pool()->setBodyElement( + t, index, reinterpret_cast(c)); + } + return c; + } + return cast(t, o); +} + +inline GcClass* resolveClassInPool(Thread* t, + GcMethod* method, + unsigned index, + bool throw_ = true) +{ + return resolveClassInPool( + t, method->class_()->loader(), method, index, throw_); +} + +inline object resolve( + Thread* t, + GcClassLoader* loader, + GcSingleton* pool, + unsigned index, + object (*find)(vm::Thread*, GcClass*, GcByteArray*, GcByteArray*), + Gc::Type errorType, + bool throw_ = true) +{ + object o = singletonObject(t, pool, index); + + loadMemoryBarrier(); + + if (objectClass(t, o) == type(t, GcReference::Type)) { + PROTECT(t, pool); + + GcReference* reference = cast(t, o); + PROTECT(t, reference); + + GcClass* class_ + = resolveClassInObject(t, loader, o, ReferenceClass, throw_); + + if (class_) { + o = findInHierarchy(t, + class_, + reference->name(), + reference->spec(), + find, + errorType, + throw_); + + if (o) { + storeStoreMemoryBarrier(); + + pool->setBodyElement(t, index, reinterpret_cast(o)); + } + } else { + o = 0; + } + } + + return o; +} + +inline GcField* resolveField(Thread* t, + GcClassLoader* loader, + GcMethod* method, + unsigned index, + bool throw_ = true) +{ + return cast(t, + resolve(t, + loader, + method->code()->pool(), + index, + findFieldInClass, + GcNoSuchFieldError::Type, + throw_)); +} + +inline GcField* resolveField(Thread* t, + GcMethod* method, + unsigned index, + bool throw_ = true) +{ + return resolveField(t, method->class_()->loader(), method, index, throw_); +} + +inline void acquireFieldForRead(Thread* t, GcField* field) +{ + if (UNLIKELY( + (field->flags() & ACC_VOLATILE) and BytesPerWord == 4 + and (field->code() == DoubleField or field->code() == LongField))) { + acquire(t, field); + } +} + +inline void releaseFieldForRead(Thread* t, GcField* field) +{ + if (UNLIKELY(field->flags() & ACC_VOLATILE)) { + if (BytesPerWord == 4 + and (field->code() == DoubleField or field->code() == LongField)) { + release(t, field); + } else { + loadMemoryBarrier(); + } + } +} + +class FieldReadResource { + public: + FieldReadResource(Thread* t, GcField* o) : o(o), protector(t, &(this->o)) + { + acquireFieldForRead(protector.t, o); + } + + ~FieldReadResource() + { + releaseFieldForRead(protector.t, o); + } + + private: + GcField* o; + Thread::SingleProtector protector; +}; + +inline void acquireFieldForWrite(Thread* t, GcField* field) +{ + if (UNLIKELY(field->flags() & ACC_VOLATILE)) { + if (BytesPerWord == 4 + and (field->code() == DoubleField or field->code() == LongField)) { + acquire(t, field); + } else { + storeStoreMemoryBarrier(); + } + } +} + +inline void releaseFieldForWrite(Thread* t, GcField* field) +{ + if (UNLIKELY(field->flags() & ACC_VOLATILE)) { + if (BytesPerWord == 4 + and (field->code() == DoubleField or field->code() == LongField)) { + release(t, field); + } else { + storeLoadMemoryBarrier(); + } + } +} + +class FieldWriteResource { + public: + FieldWriteResource(Thread* t, GcField* o) : o(o), protector(t, &(this->o)) + { + acquireFieldForWrite(protector.t, o); + } + + ~FieldWriteResource() + { + releaseFieldForWrite(protector.t, o); + } + + private: + GcField* o; + Thread::SingleProtector protector; +}; + +inline GcMethod* resolveMethod(Thread* t, + GcClassLoader* loader, + GcMethod* method, + unsigned index, + bool throw_ = true) +{ + return cast(t, + resolve(t, + loader, + method->code()->pool(), + index, + findMethodInClass, + GcNoSuchMethodError::Type, + throw_)); +} + +inline GcMethod* resolveMethod(Thread* t, + GcMethod* method, + unsigned index, + bool throw_ = true) +{ + return resolveMethod(t, method->class_()->loader(), method, index, throw_); +} + +GcVector* vectorAppend(Thread*, GcVector*, object); + +inline GcClassRuntimeData* getClassRuntimeDataIfExists(Thread* t, GcClass* c) +{ + if (c->runtimeDataIndex()) { + return cast( + t, + roots(t)->classRuntimeDataTable()->body()[c->runtimeDataIndex() - 1]); + } else { + return 0; + } +} + +inline GcClassRuntimeData* getClassRuntimeData(Thread* t, GcClass* c) +{ + if (c->runtimeDataIndex() == 0) { + PROTECT(t, c); + + ACQUIRE(t, t->m->classLock); + + if (c->runtimeDataIndex() == 0) { + GcClassRuntimeData* runtimeData = makeClassRuntimeData(t, 0, 0, 0, 0); + + { + GcVector* v + = vectorAppend(t, roots(t)->classRuntimeDataTable(), runtimeData); + // sequence point, for gc (don't recombine statements) + roots(t)->setClassRuntimeDataTable(t, v); + } + + c->runtimeDataIndex() = roots(t)->classRuntimeDataTable()->size(); + } + } + + return cast( + t, roots(t)->classRuntimeDataTable()->body()[c->runtimeDataIndex() - 1]); +} + +inline GcMethodRuntimeData* getMethodRuntimeData(Thread* t, GcMethod* method) +{ + int index = method->runtimeDataIndex(); + + loadMemoryBarrier(); + + if (index == 0) { + PROTECT(t, method); + + ACQUIRE(t, t->m->classLock); + + if (method->runtimeDataIndex() == 0) { + GcMethodRuntimeData* runtimeData = makeMethodRuntimeData(t, 0); + + { + GcVector* v + = vectorAppend(t, roots(t)->methodRuntimeDataTable(), runtimeData); + // sequence point, for gc (don't recombine statements) + roots(t)->setMethodRuntimeDataTable(t, v); + } + + storeStoreMemoryBarrier(); + + method->runtimeDataIndex() = roots(t)->methodRuntimeDataTable()->size(); + } + } + + return cast(t, + roots(t)->methodRuntimeDataTable()->body() + [method->runtimeDataIndex() - 1]); +} + +inline GcJclass* getJClass(Thread* t, GcClass* c) +{ + PROTECT(t, c); + + GcJclass* jclass = cast(t, getClassRuntimeData(t, c)->jclass()); + + loadMemoryBarrier(); + + if (jclass == 0) { + ACQUIRE(t, t->m->classLock); + + jclass = cast(t, getClassRuntimeData(t, c)->jclass()); + if (jclass == 0) { + jclass = t->m->classpath->makeJclass(t, c); + + storeStoreMemoryBarrier(); + + getClassRuntimeData(t, c)->setJclass(t, jclass); + } + } + + return jclass; +} + +inline GcClass* primitiveClass(Thread* t, char name) +{ + switch (name) { + case 'B': + return type(t, GcJbyte::Type); + case 'C': + return type(t, GcJchar::Type); + case 'D': + return type(t, GcJdouble::Type); + case 'F': + return type(t, GcJfloat::Type); + case 'I': + return type(t, GcJint::Type); + case 'J': + return type(t, GcJlong::Type); + case 'S': + return type(t, GcJshort::Type); + case 'V': + return type(t, GcJvoid::Type); + case 'Z': + return type(t, GcJboolean::Type); + default: + throwNew(t, GcIllegalArgumentException::Type); + } +} + +inline void registerNative(Thread* t, GcMethod* method, void* function) +{ + PROTECT(t, method); + + expect(t, method->flags() & ACC_NATIVE); + + GcNative* native = makeNative(t, function, false); + PROTECT(t, native); + + GcMethodRuntimeData* runtimeData = getMethodRuntimeData(t, method); + + // ensure other threads only see the methodRuntimeDataNative field + // populated once the object it points to has been populated: + storeStoreMemoryBarrier(); + + runtimeData->setNative(t, native); +} + +inline void unregisterNatives(Thread* t, GcClass* c) +{ + GcArray* table = cast(t, c->methodTable()); + if (table) { + for (unsigned i = 0; i < table->length(); ++i) { + GcMethod* method = cast(t, table->body()[i]); + if (method->flags() & ACC_NATIVE) { + getMethodRuntimeData(t, method)->setNative(t, 0); + } + } + } +} + +void populateMultiArray(Thread* t, + object array, + int32_t* counts, + unsigned index, + unsigned dimensions); + +GcMethod* getCaller(Thread* t, unsigned target, bool skipMethodInvoke = false); + +GcClass* defineClass(Thread* t, + GcClassLoader* loader, + const uint8_t* buffer, + unsigned length); + +inline GcMethod* methodClone(Thread* t, GcMethod* method) +{ + return makeMethod(t, + method->vmFlags(), + method->returnCode(), + method->parameterCount(), + method->parameterFootprint(), + method->flags(), + method->offset(), + method->nativeID(), + method->runtimeDataIndex(), + method->name(), + method->spec(), + method->addendum(), + method->class_(), + method->code()); +} + +inline uint64_t exceptionHandler(uint64_t start, + uint64_t end, + uint64_t ip, + uint64_t catchType) +{ + return (start << 48) | (end << 32) | (ip << 16) | catchType; +} + +inline unsigned exceptionHandlerStart(uint64_t eh) +{ + return eh >> 48; +} + +inline unsigned exceptionHandlerEnd(uint64_t eh) +{ + return (eh >> 32) & 0xFFFF; +} + +inline unsigned exceptionHandlerIp(uint64_t eh) +{ + return (eh >> 16) & 0xFFFF; +} + +inline unsigned exceptionHandlerCatchType(uint64_t eh) +{ + return eh & 0xFFFF; +} + +inline uint64_t lineNumber(uint64_t ip, uint64_t line) +{ + return (ip << 32) | line; +} + +inline unsigned lineNumberIp(uint64_t ln) +{ + return ln >> 32; +} + +inline unsigned lineNumberLine(uint64_t ln) +{ + return ln & 0xFFFFFFFF; +} + +object interruptLock(Thread* t, GcThread* thread); + +void clearInterrupted(Thread* t); + +void threadInterrupt(Thread* t, GcThread* thread); + +bool threadIsInterrupted(Thread* t, GcThread* thread, bool clear); + +inline FILE* errorLog(Thread* t) +{ + if (t->m->errorLog == 0) { + const char* path = findProperty(t, "avian.error.log"); + if (path) { + t->m->errorLog = vm::fopen(path, "wb"); + } else { + t->m->errorLog = stderr; + } + } + + return t->m->errorLog; +} + +} // namespace vm + +AVIAN_EXPORT void* vmAddressFromLine(vm::Thread* t, + vm::object m, + unsigned line); + +#endif // MACHINE_H diff --git a/sgx-jvm/avian/src/avian/process.h b/sgx-jvm/avian/src/avian/process.h new file mode 100644 index 0000000000..531927f421 --- /dev/null +++ b/sgx-jvm/avian/src/avian/process.h @@ -0,0 +1,61 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#ifndef PROCESS_H +#define PROCESS_H + +#include "avian/common.h" +#include +#include "avian/machine.h" +#include "avian/constants.h" + +namespace vm { + +inline int16_t codeReadInt16(Thread* t UNUSED, GcCode* code, unsigned& ip) +{ + uint8_t v1 = code->body()[ip++]; + uint8_t v2 = code->body()[ip++]; + return ((v1 << 8) | v2); +} + +inline int32_t codeReadInt32(Thread* t UNUSED, GcCode* code, unsigned& ip) +{ + uint8_t v1 = code->body()[ip++]; + uint8_t v2 = code->body()[ip++]; + uint8_t v3 = code->body()[ip++]; + uint8_t v4 = code->body()[ip++]; + return ((v1 << 24) | (v2 << 16) | (v3 << 8) | v4); +} + +inline bool isSuperclass(Thread* t UNUSED, GcClass* class_, GcClass* base) +{ + for (GcClass* oc = base->super(); oc; oc = oc->super()) { + if (oc == class_) { + return true; + } + } + return false; +} + +inline bool isSpecialMethod(Thread* t, GcMethod* method, GcClass* class_) +{ + return (class_->flags() & ACC_SUPER) + and strcmp(reinterpret_cast(""), + method->name()->body().begin()) != 0 + and isSuperclass(t, method->class_(), class_); +} + +void resolveNative(Thread* t, GcMethod* method); + +int findLineNumber(Thread* t, GcMethod* method, unsigned ip); + +} // namespace vm + +#endif // PROCESS_H diff --git a/sgx-jvm/avian/src/avian/processor.h b/sgx-jvm/avian/src/avian/processor.h new file mode 100644 index 0000000000..7e9df08ae3 --- /dev/null +++ b/sgx-jvm/avian/src/avian/processor.h @@ -0,0 +1,241 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#ifndef PROCESSOR_H +#define PROCESSOR_H + +#include "avian/common.h" +#include +#include +#include +#include "bootimage.h" +#include "avian/heapwalk.h" +#include "avian/zone.h" + +namespace avian { +namespace codegen { +class DelayedPromise; +} + +namespace util { +template +class Slice; +} +} + +namespace vm { + +class GcByteArray; +class GcCode; +class GcClass; +class GcMethod; +class GcMethodAddendum; +class GcIntArray; +class GcContinuation; +class GcThrowable; +class GcThread; +class GcClassAddendum; +class GcClassLoader; +class GcArray; +class GcSingleton; +class GcTriple; + +class Processor { + public: + class StackWalker; + + class StackVisitor { + public: + virtual bool visit(StackWalker* walker) = 0; + }; + + class StackWalker { + public: + virtual void walk(StackVisitor* v) = 0; + + virtual GcMethod* method() = 0; + + virtual int ip() = 0; + + virtual unsigned count() = 0; + }; + + class CompilationHandler { + public: + virtual void compiled(const void* code, + unsigned size, + unsigned frameSize, + const char* name) = 0; + + virtual void dispose() = 0; + }; + + virtual Thread* makeThread(Machine* m, GcThread* javaThread, Thread* parent) + = 0; + + virtual GcMethod* makeMethod(Thread* t, + uint8_t vmFlags, + uint8_t returnCode, + uint8_t parameterCount, + uint8_t parameterFootprint, + uint16_t flags, + uint16_t offset, + GcByteArray* name, + GcByteArray* spec, + GcMethodAddendum* addendum, + GcClass* class_, + GcCode* code) = 0; + + virtual GcClass* makeClass(Thread* t, + uint16_t flags, + uint16_t vmFlags, + uint16_t fixedSize, + uint8_t arrayElementSize, + uint8_t arrayDimensions, + GcClass* arrayElementClass, + GcIntArray* objectMask, + GcByteArray* name, + GcByteArray* sourceFile, + GcClass* super, + object interfaceTable, + object virtualTable, + object fieldTable, + object methodTable, + GcClassAddendum* addendum, + GcSingleton* staticTable, + GcClassLoader* loader, + unsigned vtableLength) = 0; + + virtual void initVtable(Thread* t, GcClass* c) = 0; + + virtual void visitObjects(Thread* t, Heap::Visitor* v) = 0; + + virtual void walkStack(Thread* t, StackVisitor* v) = 0; + + virtual int lineNumber(Thread* t, GcMethod* method, int ip) = 0; + + virtual object* makeLocalReference(Thread* t, object o) = 0; + + virtual void disposeLocalReference(Thread* t, object* r) = 0; + + virtual bool pushLocalFrame(Thread* t, unsigned capacity) = 0; + + virtual void popLocalFrame(Thread* t) = 0; + + virtual object invokeArray(Thread* t, + GcMethod* method, + object this_, + object arguments) = 0; + + virtual object invokeArray(Thread* t, + GcMethod* method, + object this_, + const jvalue* arguments) = 0; + + virtual object invokeList(Thread* t, + GcMethod* method, + object this_, + bool indirectObjects, + va_list arguments) = 0; + + virtual object invokeList(Thread* t, + GcClassLoader* loader, + const char* className, + const char* methodName, + const char* methodSpec, + object this_, + va_list arguments) = 0; + + virtual void dispose(Thread* t) = 0; + + virtual void dispose() = 0; + + virtual object getStackTrace(Thread* t, Thread* target) = 0; + + virtual void initialize(BootImage* image, avian::util::Slice code) + = 0; + + virtual void addCompilationHandler(CompilationHandler* handler) = 0; + + virtual void compileMethod(Thread* t, + Zone* zone, + GcTriple** constants, + GcTriple** calls, + avian::codegen::DelayedPromise** addresses, + GcMethod* method, + OffsetResolver* resolver, + Machine* hostVM) = 0; + + virtual void visitRoots(Thread* t, HeapWalker* w) = 0; + + virtual void normalizeVirtualThunks(Thread* t) = 0; + + virtual unsigned* makeCallTable(Thread* t, HeapWalker* w) = 0; + + virtual void boot(Thread* t, BootImage* image, uint8_t* code) = 0; + + virtual void callWithCurrentContinuation(Thread* t, object receiver) = 0; + + virtual void dynamicWind(Thread* t, object before, object thunk, object after) + = 0; + + virtual void feedResultToContinuation(Thread* t, + GcContinuation* continuation, + object result) = 0; + + virtual void feedExceptionToContinuation(Thread* t, + GcContinuation* continuation, + GcThrowable* exception) = 0; + + virtual void walkContinuationBody(Thread* t, + Heap::Walker* w, + object o, + unsigned start) = 0; + + object invoke(Thread* t, GcMethod* method, object this_, ...) + { + va_list a; + va_start(a, this_); + + object r = invokeList(t, method, this_, false, a); + + va_end(a); + + return r; + } + + object invoke(Thread* t, + GcClassLoader* loader, + const char* className, + const char* methodName, + const char* methodSpec, + object this_, + ...) + { + va_list a; + va_start(a, this_); + + object r + = invokeList(t, loader, className, methodName, methodSpec, this_, a); + + va_end(a); + + return r; + } +}; + +Processor* makeProcessor(System* system, + avian::util::Allocator* allocator, + const char* crashDumpDirectory, + bool useNativeFeatures); + +} // namespace vm + +#endif // PROCESSOR_H diff --git a/sgx-jvm/avian/src/avian/target-fields.h b/sgx-jvm/avian/src/avian/target-fields.h new file mode 100644 index 0000000000..ac4402ece1 --- /dev/null +++ b/sgx-jvm/avian/src/avian/target-fields.h @@ -0,0 +1,64 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#ifndef AVIAN_TARGET_FIELDS_H +#define AVIAN_TARGET_FIELDS_H + +#ifdef TARGET_BYTES_PER_WORD +#if (TARGET_BYTES_PER_WORD == 8) + +#define TARGET_THREAD_EXCEPTION 80 +#define TARGET_THREAD_EXCEPTIONSTACKADJUSTMENT 2264 +#define TARGET_THREAD_EXCEPTIONOFFSET 2272 +#define TARGET_THREAD_EXCEPTIONHANDLER 2280 + +#define TARGET_THREAD_IP 2224 +#define TARGET_THREAD_STACK 2232 +#define TARGET_THREAD_NEWSTACK 2240 +#define TARGET_THREAD_SCRATCH 2248 +#define TARGET_THREAD_CONTINUATION 2256 +#define TARGET_THREAD_TAILADDRESS 2288 +#define TARGET_THREAD_VIRTUALCALLTARGET 2296 +#define TARGET_THREAD_VIRTUALCALLINDEX 2304 +#define TARGET_THREAD_HEAPIMAGE 2312 +#define TARGET_THREAD_CODEIMAGE 2320 +#define TARGET_THREAD_THUNKTABLE 2328 +#define TARGET_THREAD_DYNAMICTABLE 2336 +#define TARGET_THREAD_STACKLIMIT 2384 + +#elif(TARGET_BYTES_PER_WORD == 4) + +#define TARGET_THREAD_EXCEPTION 44 +#define TARGET_THREAD_EXCEPTIONSTACKADJUSTMENT 2168 +#define TARGET_THREAD_EXCEPTIONOFFSET 2172 +#define TARGET_THREAD_EXCEPTIONHANDLER 2176 + +#define TARGET_THREAD_IP 2148 +#define TARGET_THREAD_STACK 2152 +#define TARGET_THREAD_NEWSTACK 2156 +#define TARGET_THREAD_SCRATCH 2160 +#define TARGET_THREAD_CONTINUATION 2164 +#define TARGET_THREAD_TAILADDRESS 2180 +#define TARGET_THREAD_VIRTUALCALLTARGET 2184 +#define TARGET_THREAD_VIRTUALCALLINDEX 2188 +#define TARGET_THREAD_HEAPIMAGE 2192 +#define TARGET_THREAD_CODEIMAGE 2196 +#define TARGET_THREAD_THUNKTABLE 2200 +#define TARGET_THREAD_DYNAMICTABLE 2204 +#define TARGET_THREAD_STACKLIMIT 2228 + +#else +#error +#endif +#else +#error +#endif + +#endif diff --git a/sgx-jvm/avian/src/avian/target.h b/sgx-jvm/avian/src/avian/target.h new file mode 100644 index 0000000000..d2ffa01f2b --- /dev/null +++ b/sgx-jvm/avian/src/avian/target.h @@ -0,0 +1,152 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#ifndef TARGET_H +#define TARGET_H + +#include "avian/target-fields.h" +#include "avian/common.h" + +namespace vm { + +template +inline T targetV1(T v) +{ + return v; +} + +template +inline T swapV2(T v) +{ + return (((v >> 8) & 0xFF) | ((v << 8))); +} + +template +inline T swapV4(T v) +{ + return (((v >> 24) & 0x000000FF) | ((v >> 8) & 0x0000FF00) + | ((v << 8) & 0x00FF0000) | ((v << 24))); +} + +template +inline T swapV8(T v) +{ + return (((static_cast(v) >> 56) & UINT64_C(0x00000000000000FF)) + | ((static_cast(v) >> 40) & UINT64_C(0x000000000000FF00)) + | ((static_cast(v) >> 24) & UINT64_C(0x0000000000FF0000)) + | ((static_cast(v) >> 8) & UINT64_C(0x00000000FF000000)) + | ((static_cast(v) << 8) & UINT64_C(0x000000FF00000000)) + | ((static_cast(v) << 24) & UINT64_C(0x0000FF0000000000)) + | ((static_cast(v) << 40) & UINT64_C(0x00FF000000000000)) + | ((static_cast(v) << 56))); +} + +#ifdef TARGET_OPPOSITE_ENDIAN + +template +inline T targetV2(T v) +{ + return swapV2(v); +} + +template +inline T targetV4(T v) +{ + return swapV4(v); +} + +template +inline T targetV8(T v) +{ + return swapV8(v); +} + +#else +template +inline T targetV2(T v) +{ + return v; +} + +template +inline T targetV4(T v) +{ + return v; +} + +template +inline T targetV8(T v) +{ + return v; +} +#endif + +#ifdef TARGET_BYTES_PER_WORD +#if (TARGET_BYTES_PER_WORD == 8) + +template +inline T targetVW(T v) +{ + return targetV8(v); +} + +typedef uint64_t target_uintptr_t; +typedef int64_t target_intptr_t; + +const unsigned TargetClassFixedSize = 12; +const unsigned TargetClassArrayElementSize = 14; +const unsigned TargetClassVtable = 136; + +const unsigned TargetFieldOffset = 12; + +#elif(TARGET_BYTES_PER_WORD == 4) + +template +inline T targetVW(T v) +{ + return targetV4(v); +} + +typedef uint32_t target_uintptr_t; +typedef int32_t target_intptr_t; + +const unsigned TargetClassFixedSize = 8; +const unsigned TargetClassArrayElementSize = 10; +const unsigned TargetClassVtable = 72; + +const unsigned TargetFieldOffset = 8; + +#else +#error +#endif +#else +#error +#endif + +const unsigned TargetBytesPerWord = TARGET_BYTES_PER_WORD; + +const unsigned TargetBitsPerWord = TargetBytesPerWord * 8; + +const target_uintptr_t TargetPointerMask + = ((~static_cast(0)) / TargetBytesPerWord) + * TargetBytesPerWord; + +const unsigned TargetArrayLength = TargetBytesPerWord; +const unsigned TargetArrayBody = TargetBytesPerWord * 2; + +inline void targetMarkBit(target_uintptr_t* map, unsigned i) +{ + map[wordOf(i)] |= targetVW(static_cast(1) + << bitOf(i)); +} + +} // namespace vm + +#endif // TARGET_H diff --git a/sgx-jvm/avian/src/avian/types.h b/sgx-jvm/avian/src/avian/types.h new file mode 100644 index 0000000000..43ad0bfc3c --- /dev/null +++ b/sgx-jvm/avian/src/avian/types.h @@ -0,0 +1,23 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#ifndef TYPES_H +#define TYPES_H + +#define VOID_TYPE 0 +#define INT8_TYPE 1 +#define INT16_TYPE 2 +#define INT32_TYPE 3 +#define INT64_TYPE 4 +#define FLOAT_TYPE 5 +#define DOUBLE_TYPE 6 +#define POINTER_TYPE 7 + +#endif // TYPES_H diff --git a/sgx-jvm/avian/src/avian/util.h b/sgx-jvm/avian/src/avian/util.h new file mode 100644 index 0000000000..dd5293bd17 --- /dev/null +++ b/sgx-jvm/avian/src/avian/util.h @@ -0,0 +1,172 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#ifndef UTIL_H +#define UTIL_H + +#include "avian/machine.h" +#include "avian/zone.h" + +namespace vm { + +GcTriple* hashMapFindNode(Thread* t, + GcHashMap* map, + object key, + uint32_t (*hash)(Thread*, object), + bool (*equal)(Thread*, object, object)); + +inline object hashMapFind(Thread* t, + GcHashMap* map, + object key, + uint32_t (*hash)(Thread*, object), + bool (*equal)(Thread*, object, object)) +{ + GcTriple* n = hashMapFindNode(t, map, key, hash, equal); + return (n ? n->second() : 0); +} + +void hashMapResize(Thread* t, + GcHashMap* map, + uint32_t (*hash)(Thread*, object), + unsigned size); + +void hashMapInsert(Thread* t, + GcHashMap* map, + object key, + object value, + uint32_t (*hash)(Thread*, object)); + +inline bool hashMapInsertOrReplace(Thread* t, + GcHashMap* map, + object key, + object value, + uint32_t (*hash)(Thread*, object), + bool (*equal)(Thread*, object, object)) +{ + GcTriple* n = hashMapFindNode(t, map, key, hash, equal); + if (n == 0) { + hashMapInsert(t, map, key, value, hash); + return true; + } else { + n->setSecond(t, value); + return false; + } +} + +inline bool hashMapInsertMaybe(Thread* t, + GcHashMap* map, + object key, + object value, + uint32_t (*hash)(Thread*, object), + bool (*equal)(Thread*, object, object)) +{ + GcTriple* n = hashMapFindNode(t, map, key, hash, equal); + if (n == 0) { + hashMapInsert(t, map, key, value, hash); + return true; + } else { + return false; + } +} + +object hashMapRemove(Thread* t, + GcHashMap* map, + object key, + uint32_t (*hash)(Thread*, object), + bool (*equal)(Thread*, object, object)); + +object hashMapIterator(Thread* t, GcHashMap* map); + +object hashMapIteratorNext(Thread* t, object it); + +void listAppend(Thread* t, GcList* list, object value); + +GcVector* vectorAppend(Thread* t, GcVector* vector, object value); + +GcArray* growArray(Thread* t, GcArray* array); + +object treeQuery(Thread* t, + GcTreeNode* tree, + intptr_t key, + GcTreeNode* sentinal, + intptr_t (*compare)(Thread* t, intptr_t key, object b)); + +GcTreeNode* treeInsert(Thread* t, + Zone* zone, + GcTreeNode* tree, + intptr_t key, + object value, + GcTreeNode* sentinal, + intptr_t (*compare)(Thread* t, intptr_t key, object b)); + +void treeUpdate(Thread* t, + GcTreeNode* tree, + intptr_t key, + object value, + GcTreeNode* sentinal, + intptr_t (*compare)(Thread* t, intptr_t key, object b)); + +class HashMapIterator : public Thread::Protector { + public: + HashMapIterator(Thread* t, GcHashMap* map) + : Protector(t), map(map), node(0), index(0) + { + find(); + } + + void find() + { + GcArray* array = map->array(); + if (array) { + for (unsigned i = index; i < array->length(); ++i) { + if (array->body()[i]) { + node = cast(t, array->body()[i]); + index = i + 1; + return; + } + } + } + node = 0; + } + + bool hasMore() + { + return node != 0; + } + + GcTriple* next() + { + if (node) { + GcTriple* n = node; + if (node->third()) { + node = cast(t, node->third()); + } else { + find(); + } + return n; + } else { + return 0; + } + } + + virtual void visit(Heap::Visitor* v) + { + v->visit(&map); + v->visit(&node); + } + + GcHashMap* map; + GcTriple* node; + unsigned index; +}; + +} // vm + +#endif // UTIL_H diff --git a/sgx-jvm/avian/src/avian/x86.h b/sgx-jvm/avian/src/avian/x86.h new file mode 100644 index 0000000000..c54a17763f --- /dev/null +++ b/sgx-jvm/avian/src/avian/x86.h @@ -0,0 +1,332 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#ifndef X86_H +#define X86_H + +#include "avian/types.h" +#include "avian/common.h" + +#ifdef _MSC_VER +#include "windows.h" +#pragma push_macro("assert") +#include "intrin.h" +#pragma pop_macro("assert") +#undef interface +#endif + +#if (defined ARCH_x86_32) || (defined PLATFORM_WINDOWS) +#define VA_LIST(x) (&(x)) +#else +#define VA_LIST(x) (x) +#endif + +#ifdef __APPLE__ +#include "mach/mach_types.h" +#include "mach/thread_act.h" +#include "mach/thread_status.h" + +#if __DARWIN_UNIX03 && defined(_STRUCT_X86_EXCEPTION_STATE32) +#define FIELD(x) __##x +#else +#define FIELD(x) x +#endif +#endif + +#ifdef ARCH_x86_32 + +#ifdef __APPLE__ +#define THREAD_STATE x86_THREAD_STATE32 +#define THREAD_STATE_TYPE x86_thread_state32_t +#define THREAD_STATE_COUNT x86_THREAD_STATE32_COUNT + +#define THREAD_STATE_IP(state) ((state).FIELD(eip)) +#define THREAD_STATE_STACK(state) ((state).FIELD(esp)) +#define THREAD_STATE_THREAD(state) ((state).FIELD(ebx)) +#define THREAD_STATE_LINK(state) ((state).FIELD(ecx)) +#define THREAD_STATE_FRAME(state) ((state).FIELD(ebp)) + +#define IP_REGISTER(context) THREAD_STATE_IP(context->uc_mcontext->FIELD(ss)) +#define STACK_REGISTER(context) \ + THREAD_STATE_STACK(context->uc_mcontext->FIELD(ss)) +#define THREAD_REGISTER(context) \ + THREAD_STATE_THREAD(context->uc_mcontext->FIELD(ss)) +#define LINK_REGISTER(context) \ + THREAD_STATE_LINK(context->uc_mcontext->FIELD(ss)) +#define FRAME_REGISTER(context) \ + THREAD_STATE_FRAME(context->uc_mcontext->FIELD(ss)) + +#elif(defined __QNX__) +#define IP_REGISTER(context) (context->uc_mcontext.cpu.eip) +#define STACK_REGISTER(context) (context->uc_mcontext.cpu.esp) +#define THREAD_REGISTER(context) (context->uc_mcontext.cpu.ebx) +#define LINK_REGISTER(context) (context->uc_mcontext.cpu.ecx) +#define FRAME_REGISTER(context) (context->uc_mcontext.cpu.ebp) +#elif(defined __FreeBSD__) +#define IP_REGISTER(context) (context->uc_mcontext.mc_eip) +#define STACK_REGISTER(context) (context->uc_mcontext.mc_esp) +#define THREAD_REGISTER(context) (context->uc_mcontext.mc_ebx) +#define LINK_REGISTER(context) (context->uc_mcontext.mc_ecx) +#define FRAME_REGISTER(context) (context->uc_mcontext.mc_ebp) +#else +#define IP_REGISTER(context) (context->uc_mcontext.gregs[REG_EIP]) +#define STACK_REGISTER(context) (context->uc_mcontext.gregs[REG_ESP]) +#define THREAD_REGISTER(context) (context->uc_mcontext.gregs[REG_EBX]) +#define LINK_REGISTER(context) (context->uc_mcontext.gregs[REG_ECX]) +#define FRAME_REGISTER(context) (context->uc_mcontext.gregs[REG_EBP]) +#endif + +extern "C" uint64_t vmNativeCall(void* function, + void* stack, + unsigned stackSize, + unsigned returnType); + +namespace vm { + +inline uint64_t dynamicCall(void* function, + uintptr_t* arguments, + uint8_t*, + unsigned, + unsigned argumentsSize, + unsigned returnType) +{ + return vmNativeCall(function, arguments, argumentsSize, returnType); +} + +} // namespace vm + +#elif defined ARCH_x86_64 + +#ifdef __APPLE__ +#define THREAD_STATE x86_THREAD_STATE64 +#define THREAD_STATE_TYPE x86_thread_state64_t +#define THREAD_STATE_COUNT x86_THREAD_STATE64_COUNT + +#define THREAD_STATE_IP(state) ((state).FIELD(rip)) +#define THREAD_STATE_STACK(state) ((state).FIELD(rsp)) +#define THREAD_STATE_THREAD(state) ((state).FIELD(rbx)) +#define THREAD_STATE_LINK(state) ((state).FIELD(rcx)) +#define THREAD_STATE_FRAME(state) ((state).FIELD(rbp)) + +#define IP_REGISTER(context) THREAD_STATE_IP(context->uc_mcontext->FIELD(ss)) +#define STACK_REGISTER(context) \ + THREAD_STATE_STACK(context->uc_mcontext->FIELD(ss)) +#define THREAD_REGISTER(context) \ + THREAD_STATE_THREAD(context->uc_mcontext->FIELD(ss)) +#define LINK_REGISTER(context) \ + THREAD_STATE_LINK(context->uc_mcontext->FIELD(ss)) +#define FRAME_REGISTER(context) \ + THREAD_STATE_FRAME(context->uc_mcontext->FIELD(ss)) + +#elif(defined __FreeBSD__) +#define IP_REGISTER(context) (context->uc_mcontext.mc_rip) +#define STACK_REGISTER(context) (context->uc_mcontext.mc_rsp) +#define THREAD_REGISTER(context) (context->uc_mcontext.mc_rbx) +#define LINK_REGISTER(context) (context->uc_mcontext.mc_rcx) +#define FRAME_REGISTER(context) (context->uc_mcontext.mc_rbp) +#else +#define IP_REGISTER(context) (context->uc_mcontext.gregs[REG_RIP]) +#define STACK_REGISTER(context) (context->uc_mcontext.gregs[REG_RSP]) +#define THREAD_REGISTER(context) (context->uc_mcontext.gregs[REG_RBX]) +#define LINK_REGISTER(context) (context->uc_mcontext.gregs[REG_RCX]) +#define FRAME_REGISTER(context) (context->uc_mcontext.gregs[REG_RBP]) +#endif + +extern "C" uint64_t +#ifdef PLATFORM_WINDOWS + vmNativeCall(void* function, + void* stack, + unsigned stackSize, + unsigned returnType); +#else + vmNativeCall(void* function, + void* stack, + unsigned stackSize, + void* gprTable, + void* sseTable, + unsigned returnType); +#endif + +namespace vm { + +#ifdef PLATFORM_WINDOWS +inline uint64_t dynamicCall(void* function, + uint64_t* arguments, + UNUSED uint8_t* argumentTypes, + unsigned argumentCount, + unsigned, + unsigned returnType) +{ + return vmNativeCall(function, arguments, argumentCount, returnType); +} +#else +inline uint64_t dynamicCall(void* function, + uintptr_t* arguments, + uint8_t* argumentTypes, + unsigned argumentCount, + unsigned, + unsigned returnType) +{ + const unsigned GprCount = 6; + uint64_t gprTable[GprCount]; + unsigned gprIndex = 0; + + const unsigned SseCount = 8; + uint64_t sseTable[SseCount]; + unsigned sseIndex = 0; + + uint64_t stack[argumentCount]; + unsigned stackIndex = 0; + + for (unsigned i = 0; i < argumentCount; ++i) { + switch (argumentTypes[i]) { + case FLOAT_TYPE: + case DOUBLE_TYPE: { + if (sseIndex < SseCount) { + sseTable[sseIndex++] = arguments[i]; + } else { + stack[stackIndex++] = arguments[i]; + } + } break; + + default: { + if (gprIndex < GprCount) { + gprTable[gprIndex++] = arguments[i]; + } else { + stack[stackIndex++] = arguments[i]; + } + } break; + } + } + + return vmNativeCall(function, + stack, + stackIndex * BytesPerWord, + (gprIndex ? gprTable : 0), + (sseIndex ? sseTable : 0), + returnType); +} +#endif + +} // namespace vm + +#else +#error unsupported architecture +#endif + +namespace vm { + +inline void trap() +{ +#ifdef _MSC_VER + __asm int 3 +#else + asm("int3"); +#endif +} + +inline void programOrderMemoryBarrier() +{ + compileTimeMemoryBarrier(); +} + +inline void storeStoreMemoryBarrier() +{ + programOrderMemoryBarrier(); +} + +inline void storeLoadMemoryBarrier() +{ +#ifdef _MSC_VER + MemoryBarrier(); +#elif defined ARCH_x86_32 + __asm__ __volatile__("lock; addl $0,0(%%esp)" : : : "memory"); +#elif defined ARCH_x86_64 + __asm__ __volatile__("mfence" : : : "memory"); +#endif // ARCH_x86_64 +} + +inline void loadMemoryBarrier() +{ + programOrderMemoryBarrier(); +} + +inline void syncInstructionCache(const void*, unsigned) +{ + programOrderMemoryBarrier(); +} + +#ifdef USE_ATOMIC_OPERATIONS +inline bool atomicCompareAndSwap32(uint32_t* p, uint32_t old, uint32_t new_) +{ +#ifdef _MSC_VER + return old + == InterlockedCompareExchange(reinterpret_cast(p), new_, old); +#elif(__GNUC__ >= 4) && (__GNUC_MINOR__ >= 1) + return __sync_bool_compare_and_swap(p, old, new_); +#else + uint8_t result; + + __asm__ __volatile__("lock; cmpxchgl %2, %0; setz %1" + : "=m"(*p), "=q"(result) + : "r"(new_), "a"(old), "m"(*p) + : "memory"); + + return result != 0; +#endif +} + +#define AVIAN_HAS_CAS64 + +inline bool atomicCompareAndSwap64(uint64_t* p, uint64_t old, uint64_t new_) +{ +#ifdef _MSC_VER + return old == InterlockedCompareExchange64( + reinterpret_cast(p), new_, old); +#elif(__GNUC__ >= 4) && (__GNUC_MINOR__ >= 1) + return __sync_bool_compare_and_swap(p, old, new_); +#elif defined ARCH_x86_32 + uint8_t result; + + __asm__ __volatile__("lock; cmpxchg8b %0; setz %1" + : "=m"(*p), "=q"(result) + : "a"(static_cast(old)), + "d"(static_cast(old >> 32)), + "b"(static_cast(new_)), + "c"(static_cast(new_ >> 32)), + "m"(*p) + : "memory"); + + return result != 0; +#else + uint8_t result; + + __asm__ __volatile__("lock; cmpxchgq %2, %0; setz %1" + : "=m"(*p), "=q"(result) + : "r"(new_), "a"(old), "m"(*p) + : "memory"); + + return result != 0; +#endif +} + +inline bool atomicCompareAndSwap(uintptr_t* p, uintptr_t old, uintptr_t new_) +{ +#ifdef ARCH_x86_32 + return atomicCompareAndSwap32(reinterpret_cast(p), old, new_); +#elif defined ARCH_x86_64 + return atomicCompareAndSwap64(reinterpret_cast(p), old, new_); +#endif // ARCH_x86_64 +} +#endif // USE_ATOMIC_OPERATIONS + +} // namespace vm + +#endif // X86_H diff --git a/sgx-jvm/avian/src/avian/zlib-custom.h b/sgx-jvm/avian/src/avian/zlib-custom.h new file mode 100644 index 0000000000..73a62c81bb --- /dev/null +++ b/sgx-jvm/avian/src/avian/zlib-custom.h @@ -0,0 +1,31 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#include "zlib.h" + +#ifdef inflateInit2 +#undef inflateInit2 +#define inflateInit2(strm, windowBits) \ + inflateInit2_( \ + (strm), (windowBits), ZLIB_VERSION, static_cast(sizeof(z_stream))) +#endif + +#ifdef deflateInit2 +#undef deflateInit2 +#define deflateInit2(strm, level, windowBits) \ + deflateInit2_((strm), \ + (level), \ + Z_DEFLATED, \ + (windowBits), \ + 8, \ + Z_DEFAULT_STRATEGY, \ + ZLIB_VERSION, \ + static_cast(sizeof(z_stream))) +#endif diff --git a/sgx-jvm/avian/src/avian/zone.h b/sgx-jvm/avian/src/avian/zone.h new file mode 100644 index 0000000000..1274abfa73 --- /dev/null +++ b/sgx-jvm/avian/src/avian/zone.h @@ -0,0 +1,156 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#ifndef ZONE_H +#define ZONE_H + +#include +#include +#include + +namespace vm { + +class Zone : public avian::util::AllocOnly { + public: + class Segment { + public: + Segment(Segment* next, unsigned size) : next(next), size(size), position(0) + { + } + + Segment* next; + uintptr_t size; + uintptr_t position; + uint8_t data[0]; + }; + + Zone(avian::util::Allocator* allocator, size_t minimumFootprint) + : allocator(allocator), + segment(0), + minimumFootprint(minimumFootprint < sizeof(Segment) + ? 0 + : minimumFootprint - sizeof(Segment)) + { + } + + ~Zone() + { + dispose(); + } + + void dispose() + { + for (Segment* seg = segment, *next; seg; seg = next) { + next = seg->next; + allocator->free(seg, sizeof(Segment) + seg->size); + } + + segment = 0; + } + + virtual void* allocate(size_t size) + { + size = pad(size); + void* p = tryAllocate(size); + if (p) { + return p; + } else { + ensure(size); + void* r = segment->data + segment->position; + segment->position += size; + return r; + } + } + + void* peek(size_t size) + { + size = pad(size); + Segment* s = segment; + while (s->position < size) { + size -= s->position; + s = s->next; + } + return s->data + (s->position - size); + } + + void pop(size_t size) + { + size = pad(size); + Segment* s = segment; + while (s->position < size) { + size -= s->position; + Segment* next = s->next; + allocator->free(s, sizeof(Segment) + s->size); + s = next; + } + s->position -= size; + segment = s; + } + + private: + static unsigned padToPage(unsigned size) + { + return (size + (LikelyPageSizeInBytes - 1)) & ~(LikelyPageSizeInBytes - 1); + } + + bool tryEnsure(unsigned space) + { + if (segment == 0 or segment->position + space > segment->size) { + unsigned size = padToPage( + avian::util::max( + space, + avian::util::max(minimumFootprint, + segment == 0 ? 0 : segment->size * 2)) + + sizeof(Segment)); + + void* p = allocator->tryAllocate(size); + if (p == 0) { + size = padToPage(space + sizeof(Segment)); + p = allocator->tryAllocate(size); + if (p == 0) { + return false; + } + } + + segment = new (p) Segment(segment, size - sizeof(Segment)); + } + return true; + } + + void ensure(unsigned space) + { + if (segment == 0 or segment->position + space > segment->size) { + unsigned size = padToPage(space + sizeof(Segment)); + + segment = new (allocator->allocate(size)) + Segment(segment, size - sizeof(Segment)); + } + } + + void* tryAllocate(size_t size) + { + size = pad(size); + if (tryEnsure(size)) { + void* r = segment->data + segment->position; + segment->position += size; + return r; + } else { + return 0; + } + } + + avian::util::Allocator* allocator; + Segment* segment; + unsigned minimumFootprint; +}; + +} // namespace vm + +#endif // ZONE_H diff --git a/sgx-jvm/avian/src/boot-javahome.cpp b/sgx-jvm/avian/src/boot-javahome.cpp new file mode 100644 index 0000000000..026910ede6 --- /dev/null +++ b/sgx-jvm/avian/src/boot-javahome.cpp @@ -0,0 +1,34 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#include "avian/common.h" + +#ifdef BOOT_JAVAHOME + +#if (!defined __x86_64__) && ((defined __MINGW32__) || (defined _MSC_VER)) +#define SYMBOL(x) binary_javahome_jar_##x +#else +#define SYMBOL(x) _binary_javahome_jar_##x +#endif + +extern "C" { +extern const uint8_t SYMBOL(start)[]; +extern const uint8_t SYMBOL(end)[]; + +AVIAN_EXPORT const uint8_t* javahomeJar(size_t* size) +{ + *size = SYMBOL(end) - SYMBOL(start); + return SYMBOL(start); +} +} + +#undef SYMBOL + +#endif // BOOT_JAVAHOME diff --git a/sgx-jvm/avian/src/boot.cpp b/sgx-jvm/avian/src/boot.cpp new file mode 100644 index 0000000000..3849c9eed0 --- /dev/null +++ b/sgx-jvm/avian/src/boot.cpp @@ -0,0 +1,77 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#include + +#include "avian/common.h" + +// since we aren't linking against libstdc++, we must implement this +// ourselves: +extern "C" void __cxa_pure_virtual(void) +{ + abort(); +} + +#ifdef BOOT_IMAGE + +#if (!defined __x86_64__) && ((defined __MINGW32__) || (defined _MSC_VER)) +#define BOOTIMAGE_SYMBOL(x) binary_bootimage_bin_##x +#define CODEIMAGE_SYMBOL(x) binary_codeimage_bin_##x +#else +#define BOOTIMAGE_SYMBOL(x) _binary_bootimage_bin_##x +#define CODEIMAGE_SYMBOL(x) _binary_codeimage_bin_##x +#endif + +extern "C" { +extern const uint8_t BOOTIMAGE_SYMBOL(start)[]; +extern const uint8_t BOOTIMAGE_SYMBOL(end)[]; + +AVIAN_EXPORT const uint8_t* bootimageBin(size_t* size) +{ + *size = BOOTIMAGE_SYMBOL(end) - BOOTIMAGE_SYMBOL(start); + return BOOTIMAGE_SYMBOL(start); +} + +extern const uint8_t CODEIMAGE_SYMBOL(start)[]; +extern const uint8_t CODEIMAGE_SYMBOL(end)[]; + +AVIAN_EXPORT const uint8_t* codeimageBin(size_t* size) +{ + *size = CODEIMAGE_SYMBOL(end) - CODEIMAGE_SYMBOL(start); + return CODEIMAGE_SYMBOL(start); +} +} + +#undef SYMBOL + +#endif // BOOT_IMAGE + +#ifdef BOOT_CLASSPATH + +#if (!defined __x86_64__) && ((defined __MINGW32__) || (defined _MSC_VER)) +#define SYMBOL(x) binary_classpath_jar_##x +#else +#define SYMBOL(x) _binary_classpath_jar_##x +#endif + +extern "C" { +extern const uint8_t SYMBOL(start)[]; +extern const uint8_t SYMBOL(end)[]; + +AVIAN_EXPORT const uint8_t* classpathJar(size_t* size) +{ + *size = SYMBOL(end) - SYMBOL(start); + return SYMBOL(start); +} +} + +#undef SYMBOL + +#endif // BOOT_CLASSPATH diff --git a/sgx-jvm/avian/src/bootimage-fields.cpp b/sgx-jvm/avian/src/bootimage-fields.cpp new file mode 100644 index 0000000000..1cd72c73ea --- /dev/null +++ b/sgx-jvm/avian/src/bootimage-fields.cpp @@ -0,0 +1,46 @@ +#ifndef FIELD +#define FIELD(name) +#define FIELD_DEFINED +#endif + +FIELD(magic) + +FIELD(initialized) + +FIELD(heapSize) +FIELD(codeSize) + +FIELD(bootClassCount) +FIELD(appClassCount) +FIELD(stringCount) +FIELD(callCount) + +FIELD(bootLoader) +FIELD(appLoader) +FIELD(types) +FIELD(methodTree) +FIELD(methodTreeSentinal) +FIELD(virtualThunks) + +#ifdef FIELD_DEFINED +#undef FIELD +#undef FIELD_DEFINED +#endif + +#ifndef THUNK_FIELD +#define THUNK_FIELD(name) +#define THUNK_FIELD_DEFINED +#endif + +THUNK_FIELD(default_); +THUNK_FIELD(defaultVirtual); +THUNK_FIELD(defaultDynamic); +THUNK_FIELD(native); +THUNK_FIELD(aioob); +THUNK_FIELD(stackOverflow); +THUNK_FIELD(table); + +#ifdef THUNK_FIELD_DEFINED +#undef THUNK_FIELD +#undef THUNK_FIELD_DEFINED +#endif diff --git a/sgx-jvm/avian/src/bootimage-template.cpp b/sgx-jvm/avian/src/bootimage-template.cpp new file mode 100644 index 0000000000..16dd85e11e --- /dev/null +++ b/sgx-jvm/avian/src/bootimage-template.cpp @@ -0,0 +1,26 @@ +const unsigned NAME(BootMask) = (~static_cast(0)) + / NAME(BytesPerWord); + +const unsigned NAME(BootShift) UNUSED = 32 - avian::util::log(NAME(BytesPerWord)); + +inline unsigned LABEL(codeMapSize)(unsigned codeSize) +{ + return avian::util::ceilingDivide(codeSize, TargetBitsPerWord) + * TargetBytesPerWord; +} + +inline unsigned LABEL(heapMapSize)(unsigned heapSize) +{ + return avian::util::ceilingDivide(heapSize, + TargetBitsPerWord * TargetBytesPerWord) + * TargetBytesPerWord; +} + +inline object LABEL(bootObject)(LABEL(uintptr_t) * heap, unsigned offset) +{ + if (offset) { + return reinterpret_cast(heap + offset - 1); + } else { + return 0; + } +} diff --git a/sgx-jvm/avian/src/builtin.cpp b/sgx-jvm/avian/src/builtin.cpp new file mode 100644 index 0000000000..4369ec62d2 --- /dev/null +++ b/sgx-jvm/avian/src/builtin.cpp @@ -0,0 +1,1393 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#include "avian/machine.h" +#include "avian/constants.h" +#include "avian/processor.h" +#include "avian/util.h" + +#include + +using namespace vm; + +namespace { + +int64_t search(Thread* t, + GcClassLoader* loader, + GcString* name, + GcClass* (*op)(Thread*, GcClassLoader*, GcByteArray*), + bool replaceDots) +{ + if (LIKELY(name)) { + PROTECT(t, loader); + PROTECT(t, name); + + GcByteArray* n = makeByteArray(t, name->length(t) + 1); + char* s = reinterpret_cast(n->body().begin()); + stringChars(t, name, s); + + if (replaceDots) { + replace('.', '/', s); + } + + return reinterpret_cast(op(t, loader, n)); + } else { + throwNew(t, GcNullPointerException::Type); + } +} + +GcClass* resolveSystemClassThrow(Thread* t, + GcClassLoader* loader, + GcByteArray* spec) +{ + return resolveSystemClass( + t, loader, spec, true, GcClassNotFoundException::Type); +} + +GcField* fieldForOffsetInClass(Thread* t, GcClass* c, unsigned offset) +{ + GcClass* super = c->super(); + if (super) { + GcField* field = fieldForOffsetInClass(t, super, offset); + if (field) { + return field; + } + } + + object table = c->fieldTable(); + if (table) { + for (unsigned i = 0; i < objectArrayLength(t, table); ++i) { + GcField* field = cast(t, objectArrayBody(t, table, i)); + if ((field->flags() & ACC_STATIC) == 0 and field->offset() == offset) { + return field; + } + } + } + + return 0; +} + +GcField* fieldForOffset(Thread* t, object o, unsigned offset) +{ + GcClass* c = objectClass(t, o); + if (c->vmFlags() & SingletonFlag) { + GcSingleton* s = cast(t, o); + + // If the object is a Singleton, we assume it's the static table of a class - + // which will always have the parent class as the first (0th) element. + c = cast(t, singletonObject(t, s, 0)); + + object table = c->fieldTable(); + if (table) { + for (unsigned i = 0; i < objectArrayLength(t, table); ++i) { + GcField* field = cast(t, objectArrayBody(t, table, i)); + if ((field->flags() & ACC_STATIC) and field->offset() == offset) { + return field; + } + } + } + abort(t); + } else { + GcField* field = fieldForOffsetInClass(t, c, offset); + if (field) { + return field; + } else { + abort(t); + } + } +} + +} // namespace + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_avian_Classes_toVMClass(Thread* t, object, uintptr_t* arguments) +{ + return reinterpret_cast( + cast(t, reinterpret_cast(arguments[0]))->vmClass()); +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_avian_Classes_toVMMethod(Thread* t, object, uintptr_t* arguments) +{ + return reinterpret_cast(t->m->classpath->getVMMethod( + t, cast(t, reinterpret_cast(arguments[0])))); +} + +extern "C" AVIAN_EXPORT void JNICALL + Avian_avian_Classes_initialize(Thread* t, object, uintptr_t* arguments) +{ + GcClass* this_ = cast(t, reinterpret_cast(arguments[0])); + + initClass(t, this_); +} + +extern "C" AVIAN_EXPORT void JNICALL + Avian_avian_Classes_acquireClassLock(Thread* t, object, uintptr_t*) +{ + acquire(t, t->m->classLock); +} + +extern "C" AVIAN_EXPORT void JNICALL + Avian_avian_Classes_releaseClassLock(Thread* t, object, uintptr_t*) +{ + release(t, t->m->classLock); +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_avian_Classes_resolveVMClass(Thread* t, object, uintptr_t* arguments) +{ + GcClassLoader* loader + = cast(t, reinterpret_cast(arguments[0])); + GcByteArray* spec + = cast(t, reinterpret_cast(arguments[1])); + + return reinterpret_cast( + resolveClass(t, loader, spec, true, GcClassNotFoundException::Type)); +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_avian_Classes_defineVMClass(Thread* t, object, uintptr_t* arguments) +{ + GcClassLoader* loader + = cast(t, reinterpret_cast(arguments[0])); + GcByteArray* b = cast(t, reinterpret_cast(arguments[1])); + int offset = arguments[2]; + int length = arguments[3]; + + uint8_t* buffer = static_cast(t->m->heap->allocate(length)); + + THREAD_RESOURCE2( + t, uint8_t*, buffer, int, length, t->m->heap->free(buffer, length)); + + memcpy(buffer, &b->body()[offset], length); + + return reinterpret_cast(defineClass(t, loader, buffer, length)); +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_avian_Classes_makeString(Thread* t, object, uintptr_t* arguments) +{ + GcByteArray* array + = cast(t, reinterpret_cast(arguments[0])); + int offset = arguments[1]; + int length = arguments[2]; + + return reinterpret_cast( + t->m->classpath->makeString(t, array, offset, length)); +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_avian_SystemClassLoader_appLoader(Thread* t, object, uintptr_t*) +{ + return reinterpret_cast(roots(t)->appLoader()); +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_avian_SystemClassLoader_findLoadedVMClass(Thread* t, + object, + uintptr_t* arguments) +{ + GcClassLoader* loader + = cast(t, reinterpret_cast(arguments[0])); + GcString* name = cast(t, reinterpret_cast(arguments[1])); + + return search(t, loader, name, findLoadedClass, true); +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_avian_SystemClassLoader_vmClass(Thread* t, + object, + uintptr_t* arguments) +{ + return reinterpret_cast( + cast(t, reinterpret_cast(arguments[0]))->vmClass()); +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_avian_SystemClassLoader_findVMClass(Thread* t, + object, + uintptr_t* arguments) +{ + GcClassLoader* loader + = cast(t, reinterpret_cast(arguments[0])); + GcString* name = cast(t, reinterpret_cast(arguments[1])); + + return search(t, loader, name, resolveSystemClassThrow, true); +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_avian_SystemClassLoader_resourceURLPrefix(Thread* t, + object, + uintptr_t* arguments) +{ + GcClassLoader* loader + = cast(t, reinterpret_cast(arguments[0])); + GcString* name = cast(t, reinterpret_cast(arguments[1])); + + if (LIKELY(name)) { + THREAD_RUNTIME_ARRAY(t, char, n, name->length(t) + 1); + stringChars(t, name, RUNTIME_ARRAY_BODY(n)); + + const char* name + = static_cast(loader->as(t)->finder()) + ->urlPrefix(RUNTIME_ARRAY_BODY(n)); + + return name ? reinterpret_cast(makeString(t, "%s", name)) : 0; + } else { + throwNew(t, GcNullPointerException::Type); + } +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_avian_SystemClassLoader_00024ResourceEnumeration_nextResourceURLPrefix( + Thread* t, + object, + uintptr_t* arguments) +{ + GcClassLoader* loader + = cast(t, reinterpret_cast(arguments[1])); + GcString* name = cast(t, reinterpret_cast(arguments[2])); + GcLongArray* finderElementPtrPtr + = cast(t, reinterpret_cast(arguments[3])); + + if (LIKELY(name) && LIKELY(finderElementPtrPtr)) { + THREAD_RUNTIME_ARRAY(t, char, n, name->length(t) + 1); + stringChars(t, name, RUNTIME_ARRAY_BODY(n)); + + void*& finderElementPtr + = reinterpret_cast(finderElementPtrPtr->body()[0]); + const char* name + = static_cast(loader->as(t)->finder()) + ->nextUrlPrefix(RUNTIME_ARRAY_BODY(n), finderElementPtr); + + return name ? reinterpret_cast(makeString(t, "%s", name)) : 0; + } else { + throwNew(t, GcNullPointerException::Type); + } +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_avian_SystemClassLoader_getClass(Thread* t, + object, + uintptr_t* arguments) +{ + return reinterpret_cast( + getJClass(t, cast(t, reinterpret_cast(arguments[0])))); +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_avian_SystemClassLoader_getPackageSource(Thread* t, + object, + uintptr_t* arguments) +{ + GcString* name = cast(t, reinterpret_cast(arguments[0])); + PROTECT(t, name); + + ACQUIRE(t, t->m->classLock); + + THREAD_RUNTIME_ARRAY(t, char, chars, name->length(t) + 2); + stringChars(t, name, RUNTIME_ARRAY_BODY(chars)); + replace('.', '/', RUNTIME_ARRAY_BODY(chars)); + RUNTIME_ARRAY_BODY(chars)[name->length(t)] = '/'; + RUNTIME_ARRAY_BODY(chars)[name->length(t) + 1] = 0; + + GcByteArray* key = makeByteArray(t, RUNTIME_ARRAY_BODY(chars)); + + GcByteArray* array = cast( + t, + hashMapFind( + t, roots(t)->packageMap(), key, byteArrayHash, byteArrayEqual)); + + if (array) { + return reinterpret_cast(makeLocalReference( + t, t->m->classpath->makeString(t, array, 0, array->length()))); + } else { + return 0; + } +} + +extern "C" AVIAN_EXPORT void JNICALL + Avian_avian_Machine_dumpHeap(Thread* t, object, uintptr_t* arguments) +{ + GcString* outputFile + = static_cast(reinterpret_cast(*arguments)); + + unsigned length = outputFile->length(t); + THREAD_RUNTIME_ARRAY(t, char, n, length + 1); + stringChars(t, outputFile, RUNTIME_ARRAY_BODY(n)); + FILE* out = vm::fopen(RUNTIME_ARRAY_BODY(n), "wb"); + if (out) { + { + ENTER(t, Thread::ExclusiveState); + dumpHeap(t, out); + } + fclose(out); + } else { + throwNew(t, + GcRuntimeException::Type, + "file not found: %s", + RUNTIME_ARRAY_BODY(n)); + } +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_avian_Machine_tryNative(Thread* t, object, uintptr_t* arguments) +{ + int64_t function; + memcpy(&function, arguments, 8); + int64_t argument; + memcpy(&argument, arguments + 2, 8); + + t->setFlag(Thread::TryNativeFlag); + THREAD_RESOURCE0(t, t->clearFlag(Thread::TryNativeFlag)); + + return reinterpret_cast(function)(argument); +} + +extern "C" AVIAN_EXPORT void JNICALL + Avian_java_lang_Runtime_exit(Thread* t, object, uintptr_t* arguments) +{ + shutDown(t); + + t->m->system->exit(arguments[1]); +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_java_lang_Runtime_freeMemory(Thread* t, object, uintptr_t*) +{ + return t->m->heap->remaining(); +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_java_lang_Runtime_totalMemory(Thread* t, object, uintptr_t*) +{ + return t->m->heap->limit(); +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_java_lang_Runtime_maxMemory(Thread* t, object, uintptr_t*) +{ + return t->m->heap->limit(); +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_avian_avianvmresource_Handler_00024ResourceInputStream_getContentLength( + Thread* t, + object, + uintptr_t* arguments) +{ + GcString* path = cast(t, reinterpret_cast(*arguments)); + + if (LIKELY(path)) { + THREAD_RUNTIME_ARRAY(t, char, p, path->length(t) + 1); + stringChars(t, path, RUNTIME_ARRAY_BODY(p)); + + System::Region* r = t->m->bootFinder->find(RUNTIME_ARRAY_BODY(p)); + if (r == 0) { + r = t->m->appFinder->find(RUNTIME_ARRAY_BODY(p)); + } + + if (r) { + jint rSize = r->length(); + r->dispose(); + return rSize; + } + } + return -1; +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_avian_avianvmresource_Handler_00024ResourceInputStream_open( + Thread* t, + object, + uintptr_t* arguments) +{ + GcString* path = cast(t, reinterpret_cast(*arguments)); + + if (LIKELY(path)) { + THREAD_RUNTIME_ARRAY(t, char, p, path->length(t) + 1); + stringChars(t, path, RUNTIME_ARRAY_BODY(p)); + + System::Region* r = t->m->bootFinder->find(RUNTIME_ARRAY_BODY(p)); + if (r == 0) { + r = t->m->appFinder->find(RUNTIME_ARRAY_BODY(p)); + } + + return reinterpret_cast(r); + } else { + throwNew(t, GcNullPointerException::Type); + } +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_avian_avianvmresource_Handler_00024ResourceInputStream_available( + Thread*, + object, + uintptr_t* arguments) +{ + int64_t peer; + memcpy(&peer, arguments, 8); + int32_t position = arguments[2]; + + System::Region* region = reinterpret_cast(peer); + return static_cast(region->length()) - position; +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_avian_avianvmresource_Handler_00024ResourceInputStream_read__JI( + Thread*, + object, + uintptr_t* arguments) +{ + int64_t peer; + memcpy(&peer, arguments, 8); + int32_t position = arguments[2]; + + System::Region* region = reinterpret_cast(peer); + if (position >= static_cast(region->length())) { + return -1; + } else { + return region->start()[position]; + } +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_avian_avianvmresource_Handler_00024ResourceInputStream_read__JI_3BII( + Thread* t, + object, + uintptr_t* arguments) +{ + int64_t peer; + memcpy(&peer, arguments, 8); + int32_t position = arguments[2]; + GcByteArray* buffer + = cast(t, reinterpret_cast(arguments[3])); + int32_t offset = arguments[4]; + int32_t length = arguments[5]; + + if (length == 0) + return 0; + + System::Region* region = reinterpret_cast(peer); + if (length > static_cast(region->length()) - position) { + length = static_cast(region->length()) - position; + } + if (length <= 0) { + return -1; + } else { + memcpy(&buffer->body()[offset], region->start() + position, length); + return length; + } +} + +extern "C" AVIAN_EXPORT void JNICALL + Avian_avian_avianvmresource_Handler_00024ResourceInputStream_close( + Thread*, + object, + uintptr_t* arguments) +{ + int64_t peer; + memcpy(&peer, arguments, 8); + reinterpret_cast(peer)->dispose(); +} + +extern "C" AVIAN_EXPORT void JNICALL + Avian_avian_Continuations_callWithCurrentContinuation(Thread* t, + object, + uintptr_t* arguments) +{ + t->m->processor->callWithCurrentContinuation( + t, reinterpret_cast(*arguments)); + + abort(t); +} + +extern "C" AVIAN_EXPORT void JNICALL + Avian_avian_Continuations_dynamicWind2(Thread* t, + object, + uintptr_t* arguments) +{ + t->m->processor->dynamicWind(t, + reinterpret_cast(arguments[0]), + reinterpret_cast(arguments[1]), + reinterpret_cast(arguments[2])); + + abort(t); +} + +extern "C" AVIAN_EXPORT void JNICALL + Avian_avian_Continuations_00024Continuation_handleResult( + Thread* t, + object, + uintptr_t* arguments) +{ + t->m->processor->feedResultToContinuation( + t, + cast(t, reinterpret_cast(arguments[0])), + reinterpret_cast(arguments[1])); + + abort(t); +} + +extern "C" AVIAN_EXPORT void JNICALL + Avian_avian_Continuations_00024Continuation_handleException( + Thread* t, + object, + uintptr_t* arguments) +{ + t->m->processor->feedExceptionToContinuation( + t, + cast(t, reinterpret_cast(arguments[0])), + cast(t, reinterpret_cast(arguments[1]))); + + abort(t); +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_avian_Singleton_getObject(Thread* t, object, uintptr_t* arguments) +{ + return reinterpret_cast(singletonObject( + t, + cast(t, reinterpret_cast(arguments[0])), + arguments[1])); +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_avian_Singleton_getInt(Thread* t, object, uintptr_t* arguments) +{ + return singletonValue( + t, + cast(t, reinterpret_cast(arguments[0])), + arguments[1]); +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_avian_Singleton_getLong(Thread* t, object, uintptr_t* arguments) +{ + int64_t v; + memcpy(&v, + &singletonValue( + t, + cast(t, reinterpret_cast(arguments[0])), + arguments[1]), + 8); + return v; +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_sun_misc_Unsafe_allocateMemory(Thread* t, + object, + uintptr_t* arguments) +{ + int64_t size; + memcpy(&size, arguments + 1, 8); + void* p = malloc(size); + if (p) { + return reinterpret_cast(p); + } else { + throwNew(t, GcOutOfMemoryError::Type); + } +} + +extern "C" AVIAN_EXPORT void JNICALL + Avian_sun_misc_Unsafe_freeMemory(Thread*, object, uintptr_t* arguments) +{ + int64_t p; + memcpy(&p, arguments + 1, 8); + if (p) { + free(reinterpret_cast(p)); + } +} + +extern "C" AVIAN_EXPORT void JNICALL + Avian_sun_misc_Unsafe_setMemory(Thread* t, object, uintptr_t* arguments) +{ + object base = reinterpret_cast(arguments[1]); + int64_t offset; + memcpy(&offset, arguments + 2, 8); + int64_t count; + memcpy(&count, arguments + 4, 8); + int8_t value = arguments[6]; + + PROTECT(t, base); + + ACQUIRE(t, t->m->referenceLock); + + if (base) { + memset(&fieldAtOffset(base, offset), value, count); + } else { + memset(reinterpret_cast(offset), value, count); + } +} + +// NB: The following primitive get/put methods are only used by the +// interpreter. The JIT/AOT compiler implements them as intrinsics, +// so these versions will be ignored. + +extern "C" AVIAN_EXPORT void JNICALL + Avian_sun_misc_Unsafe_putByte__JB(Thread*, object, uintptr_t* arguments) +{ + int64_t p; + memcpy(&p, arguments + 1, 8); + int8_t v = arguments[3]; + + *reinterpret_cast(p) = v; +} + +extern "C" AVIAN_EXPORT void JNICALL + Avian_sun_misc_Unsafe_putShort__JS(Thread*, object, uintptr_t* arguments) +{ + int64_t p; + memcpy(&p, arguments + 1, 8); + int16_t v = arguments[3]; + + *reinterpret_cast(p) = v; +} + +extern "C" AVIAN_EXPORT void JNICALL + Avian_sun_misc_Unsafe_putChar__JC(Thread* t, + object method, + uintptr_t* arguments) +{ + Avian_sun_misc_Unsafe_putShort__JS(t, method, arguments); +} + +extern "C" AVIAN_EXPORT void JNICALL + Avian_sun_misc_Unsafe_putInt__JI(Thread*, object, uintptr_t* arguments) +{ + int64_t p; + memcpy(&p, arguments + 1, 8); + int32_t v = arguments[3]; + + *reinterpret_cast(p) = v; +} + +extern "C" AVIAN_EXPORT void JNICALL + Avian_sun_misc_Unsafe_putFloat__JF(Thread* t, + object method, + uintptr_t* arguments) +{ + Avian_sun_misc_Unsafe_putInt__JI(t, method, arguments); +} + +extern "C" AVIAN_EXPORT void JNICALL + Avian_sun_misc_Unsafe_putLong__JJ(Thread*, object, uintptr_t* arguments) +{ + int64_t p; + memcpy(&p, arguments + 1, 8); + int64_t v; + memcpy(&v, arguments + 3, 8); + + *reinterpret_cast(p) = v; +} + +extern "C" AVIAN_EXPORT void JNICALL + Avian_sun_misc_Unsafe_putDouble__JD(Thread* t, + object method, + uintptr_t* arguments) +{ + Avian_sun_misc_Unsafe_putLong__JJ(t, method, arguments); +} + +extern "C" AVIAN_EXPORT void JNICALL + Avian_sun_misc_Unsafe_putAddress__JJ(Thread*, object, uintptr_t* arguments) +{ + int64_t p; + memcpy(&p, arguments + 1, 8); + int64_t v; + memcpy(&v, arguments + 3, 8); + + *reinterpret_cast(p) = v; +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_sun_misc_Unsafe_getByte__J(Thread*, object, uintptr_t* arguments) +{ + int64_t p; + memcpy(&p, arguments + 1, 8); + + return *reinterpret_cast(p); +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_sun_misc_Unsafe_getShort__J(Thread*, object, uintptr_t* arguments) +{ + int64_t p; + memcpy(&p, arguments + 1, 8); + + return *reinterpret_cast(p); +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_sun_misc_Unsafe_getChar__J(Thread* t, + object method, + uintptr_t* arguments) +{ + return Avian_sun_misc_Unsafe_getShort__J(t, method, arguments); +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_sun_misc_Unsafe_getInt__J(Thread*, object, uintptr_t* arguments) +{ + int64_t p; + memcpy(&p, arguments + 1, 8); + + return *reinterpret_cast(p); +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_sun_misc_Unsafe_getFloat__J(Thread* t, + object method, + uintptr_t* arguments) +{ + return Avian_sun_misc_Unsafe_getInt__J(t, method, arguments); +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_sun_misc_Unsafe_getLong__J(Thread*, object, uintptr_t* arguments) +{ + int64_t p; + memcpy(&p, arguments + 1, 8); + + return *reinterpret_cast(p); +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_sun_misc_Unsafe_getDouble__J(Thread* t, + object method, + uintptr_t* arguments) +{ + return Avian_sun_misc_Unsafe_getLong__J(t, method, arguments); +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_sun_misc_Unsafe_getAddress__J(Thread*, object, uintptr_t* arguments) +{ + int64_t p; + memcpy(&p, arguments + 1, 8); + + return *reinterpret_cast(p); +} + +extern "C" AVIAN_EXPORT void JNICALL + Avian_sun_misc_Unsafe_copyMemory(Thread* t, object, uintptr_t* arguments) +{ + object srcBase = reinterpret_cast(arguments[1]); + int64_t srcOffset; + memcpy(&srcOffset, arguments + 2, 8); + object dstBase = reinterpret_cast(arguments[4]); + int64_t dstOffset; + memcpy(&dstOffset, arguments + 5, 8); + int64_t count; + memcpy(&count, arguments + 7, 8); + + PROTECT(t, srcBase); + PROTECT(t, dstBase); + + ACQUIRE(t, t->m->referenceLock); + + void* src = srcBase ? &fieldAtOffset(srcBase, srcOffset) + : reinterpret_cast(srcOffset); + + void* dst = dstBase ? &fieldAtOffset(dstBase, dstOffset) + : reinterpret_cast(dstOffset); + + memcpy(dst, src, count); +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_sun_misc_Unsafe_arrayBaseOffset(Thread*, object, uintptr_t*) +{ + return ArrayBody; +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_sun_misc_Unsafe_arrayIndexScale(Thread* t, + object, + uintptr_t* arguments) +{ + GcClass* c + = cast(t, reinterpret_cast(arguments[1]))->vmClass(); + + if (c == type(t, GcBooleanArray::Type) || c == type(t, GcByteArray::Type)) + return 1; + else if (c == type(t, GcShortArray::Type) || c == type(t, GcCharArray::Type)) + return 2; + else if (c == type(t, GcIntArray::Type) || c == type(t, GcFloatArray::Type)) + return 4; + else if (c == type(t, GcLongArray::Type) || c == type(t, GcDoubleArray::Type)) + return 8; + else + return BytesPerWord; +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_java_nio_FixedArrayByteBuffer_allocateFixed(Thread* t, + object, + uintptr_t* arguments) +{ + int capacity = arguments[0]; + GcLongArray* address + = cast(t, reinterpret_cast(arguments[1])); + PROTECT(t, address); + + GcArray* array = reinterpret_cast(allocate3( + t, t->m->heap, Machine::FixedAllocation, ArrayBody + capacity, false)); + + setObjectClass( + t, reinterpret_cast(array), type(t, GcByteArray::Type)); + array->length() = capacity; + + address->body()[0] = reinterpret_cast(array) + ArrayBody; + + return reinterpret_cast(array); +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_sun_misc_Unsafe_getObject(Thread*, object, uintptr_t* arguments) +{ + object o = reinterpret_cast(arguments[1]); + int64_t offset; + memcpy(&offset, arguments + 2, 8); + + return fieldAtOffset(o, offset); +} + +extern "C" AVIAN_EXPORT void JNICALL + Avian_sun_misc_Unsafe_putObject(Thread* t, object, uintptr_t* arguments) +{ + object o = reinterpret_cast(arguments[1]); + int64_t offset; + memcpy(&offset, arguments + 2, 8); + uintptr_t value = arguments[4]; + + setField(t, o, offset, reinterpret_cast(value)); +} + +extern "C" AVIAN_EXPORT void JNICALL + Avian_sun_misc_Unsafe_putObjectVolatile(Thread* t, + object, + uintptr_t* arguments) +{ + object o = reinterpret_cast(arguments[1]); + int64_t offset; + memcpy(&offset, arguments + 2, 8); + object value = reinterpret_cast(arguments[4]); + + storeStoreMemoryBarrier(); + setField(t, o, offset, value); + storeLoadMemoryBarrier(); +} + +extern "C" AVIAN_EXPORT void JNICALL + Avian_sun_misc_Unsafe_putOrderedObject(Thread* t, + object method, + uintptr_t* arguments) +{ + Avian_sun_misc_Unsafe_putObjectVolatile(t, method, arguments); +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_sun_misc_Unsafe_getObjectVolatile(Thread*, + object, + uintptr_t* arguments) +{ + object o = reinterpret_cast(arguments[1]); + int64_t offset; + memcpy(&offset, arguments + 2, 8); + + uintptr_t value = fieldAtOffset(o, offset); + loadMemoryBarrier(); + return value; +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_sun_misc_Unsafe_compareAndSwapObject(Thread* t, + object, + uintptr_t* arguments) +{ + object target = reinterpret_cast(arguments[1]); + int64_t offset; + memcpy(&offset, arguments + 2, 8); + uintptr_t expect = arguments[4]; + uintptr_t update = arguments[5]; + + bool success = atomicCompareAndSwap( + &fieldAtOffset(target, offset), expect, update); + + if (success) { + mark(t, target, offset); + } + + return success; +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_sun_misc_Unsafe_compareAndSwapInt(Thread*, + object, + uintptr_t* arguments) +{ + object target = reinterpret_cast(arguments[1]); + int64_t offset; + memcpy(&offset, arguments + 2, 8); + uint32_t expect = arguments[4]; + uint32_t update = arguments[5]; + + return atomicCompareAndSwap32( + &fieldAtOffset(target, offset), expect, update); +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_sun_misc_Unsafe_compareAndSwapLong(Thread* t UNUSED, + object, + uintptr_t* arguments) +{ + object target = reinterpret_cast(arguments[1]); + int64_t offset; + memcpy(&offset, arguments + 2, 8); + uint64_t expect; + memcpy(&expect, arguments + 4, 8); + uint64_t update; + memcpy(&update, arguments + 6, 8); + +#ifdef AVIAN_HAS_CAS64 + return atomicCompareAndSwap64( + &fieldAtOffset(target, offset), expect, update); +#else + PROTECT(t, target); + ACQUIRE_FIELD_FOR_WRITE(t, fieldForOffset(t, target, offset)); + if (fieldAtOffset(target, offset) == expect) { + fieldAtOffset(target, offset) = update; + return true; + } else { + return false; + } +#endif +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_sun_misc_Unsafe_getLongVolatile(Thread* t, + object, + uintptr_t* arguments) +{ + object o = reinterpret_cast(arguments[1]); + int64_t offset; + memcpy(&offset, arguments + 2, 8); + + object lock; + if (BytesPerWord < 8) { + if (objectClass(t, o)->arrayDimensions()) { + lock = objectClass(t, o); + } else { + lock = fieldForOffset(t, cast(t, o), offset); + } + + PROTECT(t, o); + PROTECT(t, lock); + acquire(t, lock); + } + + int64_t result = fieldAtOffset(o, offset); + + if (BytesPerWord < 8) { + release(t, lock); + } else { + loadMemoryBarrier(); + } + + return result; +} + +extern "C" AVIAN_EXPORT void JNICALL + Avian_sun_misc_Unsafe_putLongVolatile(Thread* t, + object, + uintptr_t* arguments) +{ + object o = reinterpret_cast(arguments[1]); + int64_t offset; + memcpy(&offset, arguments + 2, 8); + int64_t value; + memcpy(&value, arguments + 4, 8); + + object lock; + if (BytesPerWord < 8) { + if (objectClass(t, o)->arrayDimensions()) { + lock = objectClass(t, o); + } else { + lock = fieldForOffset(t, cast(t, o), offset); + } + + PROTECT(t, o); + PROTECT(t, lock); + acquire(t, lock); + } else { + storeStoreMemoryBarrier(); + } + + fieldAtOffset(o, offset) = value; + + if (BytesPerWord < 8) { + release(t, lock); + } else { + storeLoadMemoryBarrier(); + } +} + +extern "C" AVIAN_EXPORT void JNICALL + Avian_sun_misc_Unsafe_putOrderedLong(Thread* t, + object method, + uintptr_t* arguments) +{ + // todo: we might be able to use weaker barriers here than + // putLongVolatile does + Avian_sun_misc_Unsafe_putLongVolatile(t, method, arguments); +} + +extern "C" AVIAN_EXPORT void JNICALL + Avian_sun_misc_Unsafe_unpark(Thread* t, object, uintptr_t* arguments) +{ + GcThread* thread = cast(t, reinterpret_cast(arguments[1])); + + monitorAcquire(t, cast(t, interruptLock(t, thread))); + thread->unparked() = true; + monitorNotify(t, cast(t, interruptLock(t, thread))); + monitorRelease(t, cast(t, interruptLock(t, thread))); +} + +extern "C" AVIAN_EXPORT void JNICALL + Avian_sun_misc_Unsafe_park(Thread* t, object, uintptr_t* arguments) +{ + bool absolute = arguments[1]; + int64_t time; + memcpy(&time, arguments + 2, 8); + + int64_t then = t->m->system->now(); + + if (absolute) { + time -= then; + if (time <= 0) { + return; + } + } else if (time) { + // if not absolute, interpret time as nanoseconds, but make sure + // it doesn't become zero when we convert to milliseconds, since + // zero is interpreted as infinity below + time = (time / (1000 * 1000)) + 1; + } + + monitorAcquire(t, cast(t, interruptLock(t, t->javaThread))); + bool interrupted = false; + while (time >= 0 + and (not(t->javaThread->unparked() or t->javaThread->interrupted() + or (interrupted = monitorWait( + t, + cast(t, interruptLock(t, t->javaThread)), + time))))) { + int64_t now = t->m->system->now(); + time -= now - then; + then = now; + + if (time == 0) { + break; + } + } + if (interrupted) { + t->javaThread->interrupted() = true; + } + t->javaThread->unparked() = false; + monitorRelease(t, cast(t, interruptLock(t, t->javaThread))); +} + +extern "C" AVIAN_EXPORT void JNICALL + Avian_sun_misc_Unsafe_putIntVolatile(Thread*, object, uintptr_t* arguments) +{ + object o = reinterpret_cast(arguments[1]); + int64_t offset; + memcpy(&offset, arguments + 2, 8); + int32_t value = arguments[4]; + + storeStoreMemoryBarrier(); + fieldAtOffset(o, offset) = value; + storeLoadMemoryBarrier(); +} + +extern "C" AVIAN_EXPORT void JNICALL + Avian_sun_misc_Unsafe_putOrderedInt(Thread* t, + object method, + uintptr_t* arguments) +{ + Avian_sun_misc_Unsafe_putIntVolatile(t, method, arguments); +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_sun_misc_Unsafe_getIntVolatile(Thread*, object, uintptr_t* arguments) +{ + object o = reinterpret_cast(arguments[1]); + int64_t offset; + memcpy(&offset, arguments + 2, 8); + + int32_t result = fieldAtOffset(o, offset); + loadMemoryBarrier(); + return result; +} + +extern "C" AVIAN_EXPORT void JNICALL + Avian_sun_misc_Unsafe_putByteVolatile(Thread*, object, uintptr_t* arguments) +{ + object o = reinterpret_cast(arguments[1]); + int64_t offset; + memcpy(&offset, arguments + 2, 8); + int8_t value = arguments[4]; + + storeStoreMemoryBarrier(); + fieldAtOffset(o, offset) = value; + storeLoadMemoryBarrier(); +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_sun_misc_Unsafe_getByteVolatile(Thread*, object, uintptr_t* arguments) +{ + object o = reinterpret_cast(arguments[1]); + int64_t offset; + memcpy(&offset, arguments + 2, 8); + + int8_t result = fieldAtOffset(o, offset); + loadMemoryBarrier(); + return result; +} + +extern "C" AVIAN_EXPORT void JNICALL + Avian_sun_misc_Unsafe_putBooleanVolatile(Thread* t, + object method, + uintptr_t* arguments) +{ + Avian_sun_misc_Unsafe_putByteVolatile(t, method, arguments); +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_sun_misc_Unsafe_getBooleanVolatile(Thread* t, + object method, + uintptr_t* arguments) +{ + return Avian_sun_misc_Unsafe_getByteVolatile(t, method, arguments); +} + +extern "C" AVIAN_EXPORT void JNICALL + Avian_sun_misc_Unsafe_putShortVolatile(Thread*, + object, + uintptr_t* arguments) +{ + object o = reinterpret_cast(arguments[1]); + int64_t offset; + memcpy(&offset, arguments + 2, 8); + int16_t value = arguments[4]; + + storeStoreMemoryBarrier(); + fieldAtOffset(o, offset) = value; + storeLoadMemoryBarrier(); +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_sun_misc_Unsafe_getShortVolatile(Thread*, + object, + uintptr_t* arguments) +{ + object o = reinterpret_cast(arguments[1]); + int64_t offset; + memcpy(&offset, arguments + 2, 8); + + int16_t result = fieldAtOffset(o, offset); + loadMemoryBarrier(); + return result; +} + +extern "C" AVIAN_EXPORT void JNICALL + Avian_sun_misc_Unsafe_putCharVolatile(Thread* t, + object method, + uintptr_t* arguments) +{ + Avian_sun_misc_Unsafe_putShortVolatile(t, method, arguments); +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_sun_misc_Unsafe_getCharVolatile(Thread* t, + object method, + uintptr_t* arguments) +{ + return Avian_sun_misc_Unsafe_getShortVolatile(t, method, arguments); +} + +extern "C" AVIAN_EXPORT void JNICALL + Avian_sun_misc_Unsafe_putFloatVolatile(Thread* t, + object method, + uintptr_t* arguments) +{ + Avian_sun_misc_Unsafe_putIntVolatile(t, method, arguments); +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_sun_misc_Unsafe_getFloatVolatile(Thread* t, + object method, + uintptr_t* arguments) +{ + return Avian_sun_misc_Unsafe_getIntVolatile(t, method, arguments); +} + +extern "C" AVIAN_EXPORT void JNICALL + Avian_sun_misc_Unsafe_putDoubleVolatile(Thread* t, + object method, + uintptr_t* arguments) +{ + Avian_sun_misc_Unsafe_putLongVolatile(t, method, arguments); +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_sun_misc_Unsafe_getDoubleVolatile(Thread* t, + object method, + uintptr_t* arguments) +{ + return Avian_sun_misc_Unsafe_getLongVolatile(t, method, arguments); +} + +extern "C" AVIAN_EXPORT void JNICALL + Avian_sun_misc_Unsafe_throwException(Thread* t, + object, + uintptr_t* arguments) +{ + vm::throw_(t, cast(t, reinterpret_cast(arguments[1]))); +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_avian_Classes_primitiveClass(Thread* t, object, uintptr_t* arguments) +{ + return reinterpret_cast(primitiveClass(t, arguments[0])); +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_java_lang_Class_getEnclosingMethod(Thread* t, + object, + uintptr_t* arguments) +{ + GcClass* c + = cast(t, reinterpret_cast(arguments[0]))->vmClass(); + PROTECT(t, c); + + GcClassAddendum* addendum = c->addendum(); + if (addendum) { + PROTECT(t, addendum); + + GcByteArray* enclosingClass + = cast(t, addendum->enclosingClass()); + + if (enclosingClass) { + GcClass* enclosing = resolveClass(t, c->loader(), enclosingClass); + + GcPair* enclosingMethod = cast(t, addendum->enclosingMethod()); + + if (enclosingMethod) { + return reinterpret_cast(t->m->classpath->makeJMethod( + t, + cast( + t, + findMethodInClass( + t, + enclosing, + cast(t, enclosingMethod->first()), + cast(t, enclosingMethod->second()))))); + } + } + } + return 0; +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_java_lang_Class_getEnclosingClass(Thread* t, + object, + uintptr_t* arguments) +{ + GcClass* c + = cast(t, reinterpret_cast(arguments[0]))->vmClass(); + PROTECT(t, c); + + GcClassAddendum* addendum = c->addendum(); + if (addendum) { + GcByteArray* enclosingClass + = cast(t, addendum->enclosingClass()); + + if (enclosingClass) { + return reinterpret_cast( + getJClass(t, resolveClass(t, c->loader(), enclosingClass))); + } + } + return 0; +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_java_lang_Class_getEnclosingConstructor(Thread* t, + object method, + uintptr_t* arguments) +{ + return Avian_java_lang_Class_getEnclosingMethod(t, method, arguments); +} + + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_java_lang_Object_toString(Thread* t, object, uintptr_t* arguments) +{ + object this_ = reinterpret_cast(arguments[0]); + + unsigned hash = objectHash(t, this_); + GcString* s = makeString( + t, "%s@0x%x", objectClass(t, this_)->name()->body().begin(), hash); + + return reinterpret_cast(s); +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_java_lang_Object_getVMClass(Thread* t, object, uintptr_t* arguments) +{ + return reinterpret_cast( + objectClass(t, reinterpret_cast(arguments[0]))); +} + +extern "C" AVIAN_EXPORT void JNICALL + Avian_java_lang_Object_wait(Thread* t, object, uintptr_t* arguments) +{ + object this_ = reinterpret_cast(arguments[0]); + int64_t milliseconds; + memcpy(&milliseconds, arguments + 1, 8); + + vm::wait(t, this_, milliseconds); +} + +extern "C" AVIAN_EXPORT void JNICALL + Avian_java_lang_Object_notify(Thread* t, object, uintptr_t* arguments) +{ + notify(t, reinterpret_cast(arguments[0])); +} + +extern "C" AVIAN_EXPORT void JNICALL + Avian_java_lang_Object_notifyAll(Thread* t, object, uintptr_t* arguments) +{ + notifyAll(t, reinterpret_cast(arguments[0])); +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_java_lang_Object_hashCode(Thread* t, object, uintptr_t* arguments) +{ + return objectHash(t, reinterpret_cast(arguments[0])); +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_java_lang_Object_clone(Thread* t, object, uintptr_t* arguments) +{ + return reinterpret_cast( + clone(t, reinterpret_cast(arguments[0]))); +} diff --git a/sgx-jvm/avian/src/classpath-android.cpp b/sgx-jvm/avian/src/classpath-android.cpp new file mode 100644 index 0000000000..c5db8be5e8 --- /dev/null +++ b/sgx-jvm/avian/src/classpath-android.cpp @@ -0,0 +1,1680 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#include +using namespace std; + +struct JavaVM; +struct _JavaVM; +struct _JNIEnv; + +struct JniConstants { + static void init(_JNIEnv* env); +}; + +extern "C" int JNI_OnLoad(JavaVM*, void*); + +int libconscrypt_JNI_OnLoad(_JavaVM*, void*); + +#define _POSIX_C_SOURCE 200112L +#undef _GNU_SOURCE +#include "avian/machine.h" +#include "avian/classpath-common.h" +#include "avian/process.h" +#include "avian/util.h" + +#ifdef PLATFORM_WINDOWS +const char* getErrnoDescription( + int err); // This function is defined in mingw-extensions.cpp +#endif + +using namespace vm; + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_avian_Classes_defineVMClass(Thread*, object, uintptr_t*); + +namespace { + +namespace local { + +void* getDirectBufferAddress(Thread* t, object b) +{ + PROTECT(t, b); + + GcField* field + = resolveField(t, objectClass(t, b), "effectiveDirectAddress", "J"); + + return reinterpret_cast(fieldAtOffset(b, field->offset())); +} + +void JNICALL loadLibrary(Thread* t, object, uintptr_t* arguments) +{ + GcString* name = cast(t, reinterpret_cast(arguments[1])); + + Thread::LibraryLoadStack stack( + t, cast(t, reinterpret_cast(arguments[2]))); + + unsigned length = name->length(t); + THREAD_RUNTIME_ARRAY(t, char, n, length + 1); + stringChars(t, name, RUNTIME_ARRAY_BODY(n)); + + /* org_conscrypt_NativeCrypto.o is linked statically, and in Avian build + the package is named org.conscrypt.NativeCrypto. When Android code sees + that name it thinks the library isn't linked as a part of Android, so it + tries to load in dynamically, but there's actually no need to, so we + just ignore this request. */ + if (strcmp(RUNTIME_ARRAY_BODY(n), "conscrypt_jni") != 0) { + loadLibrary(t, "", RUNTIME_ARRAY_BODY(n), true, true); + } +} + +void JNICALL gc(Thread* t, object, uintptr_t*) +{ + collect(t, Heap::MajorCollection); +} + +void JNICALL finalizeAllEnqueued(Thread*, object, uintptr_t*) +{ + // ignore +} + +int64_t JNICALL appLoader(Thread* t, object, uintptr_t*) +{ + return reinterpret_cast(roots(t)->appLoader()); +} + +int64_t JNICALL defineClass(Thread* t, object method, uintptr_t* arguments) +{ + uintptr_t args[] = {arguments[0], arguments[2], arguments[3], arguments[4]}; + + int64_t v = Avian_avian_Classes_defineVMClass(t, method, args); + + if (v) { + return reinterpret_cast( + getJClass(t, cast(t, reinterpret_cast(v)))); + } else { + return 0; + } +} + +int64_t JNICALL mapData(Thread*, object, uintptr_t*); + +void JNICALL closeMemoryMappedFile(Thread*, GcMethod*, uintptr_t*); + +object translateStackTrace(Thread* t, object raw) +{ + PROTECT(t, raw); + + object array = makeObjectArray( + t, + resolveClass(t, roots(t)->bootLoader(), "java/lang/StackTraceElement"), + objectArrayLength(t, raw)); + PROTECT(t, array); + + for (unsigned i = 0; i < objectArrayLength(t, array); ++i) { + GcStackTraceElement* e = makeStackTraceElement( + t, cast(t, objectArrayBody(t, raw, i))); + + setField(t, array, ArrayBody + (i * BytesPerWord), e); + } + + return array; +} + +class MyClasspath : public Classpath { + public: + MyClasspath(Allocator* allocator) + : allocator(allocator), tzdata(0), mayInitClasses_(false) + { + } + + virtual GcJclass* makeJclass(Thread* t, GcClass* class_) + { + PROTECT(t, class_); + + GcJclass* c + = reinterpret_cast(allocate(t, GcJclass::FixedSize, true)); + setObjectClass(t, c, type(t, GcJclass::Type)); + c->setVmClass(t, class_); + + return c; + } + + virtual GcString* makeString(Thread* t, + object array, + int32_t offset, + int32_t length) + { + if (objectClass(t, array) == type(t, GcByteArray::Type)) { + GcByteArray* byteArray = cast(t, array); + PROTECT(t, byteArray); + + assertT(t, offset + length <= static_cast(byteArray->length())); + + GcCharArray* charArray = makeCharArray(t, length); + for (int i = 0; i < length; ++i) { + expect(t, (byteArray->body()[offset + i] & 0x80) == 0); + + charArray->body()[i] = byteArray->body()[offset + i]; + } + + array = charArray; + offset = 0; + } else { + expect(t, objectClass(t, array) == type(t, GcCharArray::Type)); + + assertT(t, + offset + length + <= static_cast(cast(t, array)->length())); + } + + return vm::makeString(t, array, offset, length, 0); + } + + virtual GcThread* makeThread(Thread* t, Thread* parent) + { + const unsigned NormalPriority = 5; + + GcThreadGroup* group = 0; + PROTECT(t, group); + if (parent) { + group = parent->javaThread->group(); + } else { + resolveSystemClass(t, + roots(t)->bootLoader(), + type(t, GcThreadGroup::Type)->name(), + false); + + group = cast(t, makeNew(t, type(t, GcThreadGroup::Type))); + + GcMethod* constructor + = resolveMethod(t, type(t, GcThreadGroup::Type), "", "()V"); + + t->m->processor->invoke(t, constructor, group); + } + + resolveSystemClass( + t, roots(t)->bootLoader(), type(t, GcThread::Type)->name(), false); + + GcThread* thread = cast(t, makeNew(t, type(t, GcThread::Type))); + PROTECT(t, thread); + + GcMethod* constructor + = resolveMethod(t, + type(t, GcThread::Type), + "", + "(Ljava/lang/ThreadGroup;Ljava/lang/String;IZ)V"); + + t->m->processor->invoke( + t, constructor, thread, group, 0, NormalPriority, false); + + thread->setContextClassLoader(t, roots(t)->appLoader()); + + return thread; + } + + virtual object makeJMethod(Thread* t, GcMethod* vmMethod) + { + PROTECT(t, vmMethod); + + GcJmethod* jmethod = makeJmethod(t, vmMethod, false); + + return vmMethod->name()->body()[0] == '<' + ? static_cast(makeJconstructor(t, jmethod)) + : static_cast(jmethod); + } + + virtual GcMethod* getVMMethod(Thread* t, object jmethod) + { + return objectClass(t, jmethod) == type(t, GcJmethod::Type) + ? cast(t, jmethod)->vmMethod() + : cast(t, jmethod)->method()->vmMethod(); + } + + virtual object makeJField(Thread* t, GcField* vmField) + { + return makeJfield(t, vmField, false); + } + + virtual GcField* getVMField(Thread* t UNUSED, GcJfield* jfield) + { + return jfield->vmField(); + } + + virtual void clearInterrupted(Thread*) + { + // ignore + } + + virtual void runThread(Thread* t) + { + // force monitor creation so we don't get an OutOfMemory error + // later when we try to acquire it: + objectMonitor(t, t->javaThread->lock(), true); + + THREAD_RESOURCE0(t, { + vm::acquire(t, t->javaThread->lock()); + t->clearFlag(Thread::ActiveFlag); + t->javaThread->peer() = 0; + vm::notifyAll(t, t->javaThread->lock()); + vm::release(t, t->javaThread->lock()); + }); + + GcMethod* method = resolveMethod( + t, roots(t)->bootLoader(), "java/lang/Thread", "run", "()V"); + + t->m->processor->invoke(t, method, t->javaThread); + } + + virtual void resolveNative(Thread* t, GcMethod* method) + { + vm::resolveNative(t, method); + } + + void interceptMethods(Thread* t, bool updateRuntimeData) + { + { + GcClass* c + = resolveClass(t, roots(t)->bootLoader(), "java/lang/Runtime", false); + + if (c) { + PROTECT(t, c); + + intercept(t, + c, + "loadLibrary", + "(Ljava/lang/String;Ljava/lang/ClassLoader;)V", + voidPointer(loadLibrary), + updateRuntimeData); + } + } + + { + GcClass* c + = resolveClass(t, roots(t)->bootLoader(), "java/lang/System", false); + + if (c) { + PROTECT(t, c); + + intercept(t, c, "gc", "()V", voidPointer(gc), updateRuntimeData); + } + } + + { + GcClass* c = resolveClass( + t, roots(t)->bootLoader(), "java/lang/ref/FinalizerReference", false); + + if (c) { + PROTECT(t, c); + + intercept(t, + c, + "finalizeAllEnqueued", + "()V", + voidPointer(finalizeAllEnqueued), + updateRuntimeData); + } + } + + { + GcClass* c = resolveClass( + t, roots(t)->bootLoader(), "java/lang/ClassLoader", false); + + if (c) { + PROTECT(t, c); + + intercept(t, + c, + "createSystemClassLoader", + "()Ljava/lang/ClassLoader;", + voidPointer(appLoader), + updateRuntimeData); + + intercept(t, + c, + "defineClass", + "(Ljava/lang/String;[BII)Ljava/lang/Class;", + voidPointer(defineClass), + updateRuntimeData); + } + } + + { + GcClass* c = resolveClass( + t, roots(t)->bootLoader(), "libcore/util/ZoneInfoDB", false); + + if (c) { + PROTECT(t, c); + + intercept(t, + c, + "mapData", + "()Llibcore/io/MemoryMappedFile;", + voidPointer(mapData), + updateRuntimeData); + } + } + + { + GcClass* c = resolveClass( + t, roots(t)->bootLoader(), "libcore/io/MemoryMappedFile", false); + + if (c) { + PROTECT(t, c); + + intercept(t, + c, + "close", + "()V", + voidPointer(closeMemoryMappedFile), + updateRuntimeData); + } + } + } + + virtual void interceptMethods(Thread* t) + { + interceptMethods(t, false); + } + + virtual void preBoot(Thread* t) + { +// Android's System.initSystemProperties throws an NPE if +// LD_LIBRARY_PATH is not set as of this writing: +#ifdef PLATFORM_WINDOWS + _wputenv(L"LD_LIBRARY_PATH=(dummy)"); +#elif(!defined AVIAN_IOS) + setenv("LD_LIBRARY_PATH", "", false); +#endif + + interceptMethods(t, true); + + JniConstants::init(reinterpret_cast<_JNIEnv*>(t)); + + JNI_OnLoad(reinterpret_cast< ::JavaVM*>(t->m), 0); + + libconscrypt_JNI_OnLoad(reinterpret_cast< ::_JavaVM*>(t->m), 0); + + mayInitClasses_ = true; + } + + virtual bool mayInitClasses() + { + return mayInitClasses_; + } + + virtual void boot(Thread*) + { + // ignore + } + + virtual const char* bootClasspath() + { + return AVIAN_CLASSPATH; + } + + virtual object makeDirectByteBuffer(Thread* t, void* p, jlong capacity) + { + GcClass* c + = resolveClass(t, roots(t)->bootLoader(), "java/nio/DirectByteBuffer"); + PROTECT(t, c); + + object instance = makeNew(t, c); + PROTECT(t, instance); + + GcMethod* constructor = resolveMethod(t, c, "", "(JI)V"); + + t->m->processor->invoke(t, + constructor, + instance, + reinterpret_cast(p), + static_cast(capacity)); + + return instance; + } + + virtual void* getDirectBufferAddress(Thread* t, object b) + { + return local::getDirectBufferAddress(t, b); + } + + virtual int64_t getDirectBufferCapacity(Thread* t, object b) + { + PROTECT(t, b); + + GcField* field = resolveField(t, objectClass(t, b), "capacity", "I"); + + return fieldAtOffset(b, field->offset()); + } + + virtual bool canTailCall(Thread* t UNUSED, + GcMethod*, + GcByteArray* calleeClassName, + GcByteArray* calleeMethodName, + GcByteArray*) + { + // we can't tail call System.load[Library] or + // Runtime.load[Library] due to their use of + // ClassLoader.getCaller, which gets confused if we elide stack + // frames. + + return ( + (strcmp("loadLibrary", + reinterpret_cast(calleeMethodName->body().begin())) + and strcmp("load", + reinterpret_cast(calleeMethodName->body().begin()))) + or (strcmp("java/lang/System", + reinterpret_cast(calleeClassName->body().begin())) + and strcmp( + "java/lang/Runtime", + reinterpret_cast(calleeClassName->body().begin())))); + } + + virtual GcClassLoader* libraryClassLoader(Thread* t, GcMethod* caller) + { + return strcmp("java/lang/Runtime", + reinterpret_cast( + caller->class_()->name()->body().begin())) == 0 + ? t->libraryLoadStack->classLoader + : caller->class_()->loader(); + } + + virtual void shutDown(Thread*) + { + // ignore + } + + virtual void dispose() + { + if (tzdata) { + tzdata->dispose(); + } + allocator->free(this, sizeof(*this)); + } + + Allocator* allocator; + System::Region* tzdata; + bool mayInitClasses_; +}; + +int64_t JNICALL mapData(Thread* t, object, uintptr_t*) +{ + GcClass* c + = resolveClass(t, roots(t)->bootLoader(), "libcore/io/MemoryMappedFile"); + PROTECT(t, c); + + object instance = makeNew(t, c); + PROTECT(t, instance); + + GcMethod* constructor = resolveMethod(t, c, "", "(JJ)V"); + + const char* jar = "javahomeJar"; + Finder* finder = getFinder(t, jar, strlen(jar)); + if (finder) { + System::Region* r = finder->find("tzdata"); + if (r) { + MyClasspath* cp = static_cast(t->m->classpath); + + expect(t, cp->tzdata == 0); + + cp->tzdata = r; + + t->m->processor->invoke(t, + constructor, + instance, + reinterpret_cast(r->start()), + static_cast(r->length())); + + return reinterpret_cast(instance); + } + } + + throwNew(t, GcRuntimeException::Type); +} + +void JNICALL + closeMemoryMappedFile(Thread* t, GcMethod* method, uintptr_t* arguments) +{ + object file = reinterpret_cast(arguments[0]); + PROTECT(t, file); + + MyClasspath* cp = static_cast(t->m->classpath); + + if (cp->tzdata) { + GcField* field = resolveField(t, objectClass(t, file), "address", "J"); + + if (fieldAtOffset(file, field->offset()) + == reinterpret_cast(cp->tzdata->start())) { + cp->tzdata->dispose(); + cp->tzdata = 0; + + fieldAtOffset(file, field->offset()) = 0; + return; + } + } + + t->m->processor->invoke(t, + cast(t, + getMethodRuntimeData(t, method) + ->native() + ->as(t) + ->original()), + file); +} + +} // namespace local + +} // namespace + +namespace vm { + +Classpath* makeClasspath(System*, + Allocator* allocator, + const char*, + const char*) +{ + return new (allocator->allocate(sizeof(local::MyClasspath))) + local::MyClasspath(allocator); +} + +} // namespace vm + +extern "C" int jniRegisterNativeMethods(JNIEnv* e, + const char* className, + const JNINativeMethod* methods, + int methodCount) +{ + jclass c = e->vtable->FindClass(e, className); + + if (c) { + e->vtable->RegisterNatives(e, c, methods, methodCount); + } else { + e->vtable->ExceptionClear(e); + } + + return 0; +} + +extern "C" void jniLogException(JNIEnv*, int, const char*, jthrowable) +{ + // ignore +} + +extern "C" int jniThrowException(JNIEnv* e, + const char* className, + const char* message) +{ + jclass c = e->vtable->FindClass(e, className); + + if (c) { + e->vtable->ThrowNew(e, c, message); + } + + return 0; +} + +extern "C" int jniThrowExceptionFmt(JNIEnv* e, + const char* className, + const char* format, + va_list args) +{ + const unsigned size = 4096; + char buffer[size]; + ::vsnprintf(buffer, size, format, args); + return jniThrowException(e, className, buffer); +} + +extern "C" int jniThrowNullPointerException(JNIEnv* e, const char* message) +{ + return jniThrowException(e, "java/lang/NullPointerException", message); +} + +extern "C" int jniThrowRuntimeException(JNIEnv* e, const char* message) +{ + return jniThrowException(e, "java/lang/RuntimeException", message); +} + +extern "C" int jniThrowIOException(JNIEnv* e, const char* message) +{ + return jniThrowException(e, "java/lang/IOException", message); +} + +extern "C" const char* jniStrError(int error, char* buffer, size_t length) +{ +#ifdef PLATFORM_WINDOWS + const char* s = getErrnoDescription(error); + if (strlen(s) < length) { + strncpy(buffer, s, length); + return buffer; + } else { + return 0; + } +#else + if (static_cast(strerror_r(error, buffer, length)) == 0) { + return buffer; + } else { + return 0; + } +#endif +} + +/* + * Android log priority values (as text) + */ +const char* const androidLogPriorityTitles[] = {"UNKNOWN", + "DEFAULT", + "VERBOSE", + "DEBUG", + "INFO", + "WARNING", + "ERROR", + "FATAL", + "SILENT"}; + +extern "C" int __android_log_print(int priority, + const char* tag, + const char* format, + ...) +{ + va_list a; + const unsigned size = 4096; + char buffer[size]; + + va_start(a, format); + ::vsnprintf(buffer, size, format, a); + va_end(a); + +#ifndef PLATFORM_WINDOWS + return printf( + "[%s] %s: %s\n", androidLogPriorityTitles[priority], tag, buffer); +#else + return __mingw_fprintf( + stderr, "[%s] %s: %s\n", androidLogPriorityTitles[priority], tag, buffer); +#endif +} + +extern "C" int jniGetFDFromFileDescriptor(JNIEnv* e, jobject descriptor) +{ + return e->vtable->GetIntField( + e, + descriptor, + e->vtable->GetFieldID(e, + e->vtable->FindClass(e, "java/io/FileDescriptor"), + "descriptor", + "I")); +} + +extern "C" void jniSetFileDescriptorOfFD(JNIEnv* e, + jobject descriptor, + int value) +{ + e->vtable->SetIntField( + e, + descriptor, + e->vtable->GetFieldID(e, + e->vtable->FindClass(e, "java/io/FileDescriptor"), + "descriptor", + "I"), + value); +} + +extern "C" jobject jniCreateFileDescriptor(JNIEnv* e, int fd) +{ + jobject descriptor = e->vtable->NewObject( + e, + e->vtable->FindClass(e, "java/io/FileDescriptor"), + e->vtable->GetMethodID(e, + e->vtable->FindClass(e, "java/io/FileDescriptor"), + "", + "()V")); + + jniSetFileDescriptorOfFD(e, descriptor, fd); + + return descriptor; +} + +int register_org_apache_harmony_dalvik_NativeTestTarget(_JNIEnv*) +{ + // ignore + return 0; +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_java_lang_String_compareTo(Thread* t, object, uintptr_t* arguments) +{ + GcString* a = cast(t, reinterpret_cast(arguments[0])); + GcString* b = cast(t, reinterpret_cast(arguments[1])); + + unsigned length = a->length(t); + if (length > b->length(t)) { + length = b->length(t); + } + + for (unsigned i = 0; i < length; ++i) { + int d = stringCharAt(t, a, i) - stringCharAt(t, b, i); + if (d) { + return d; + } + } + + return a->length(t) - b->length(t); +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_java_lang_String_isEmpty(Thread* t, object, uintptr_t* arguments) +{ + return cast(t, reinterpret_cast(arguments[0]))->length(t) + == 0; +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_java_lang_String_length(Thread* t, object, uintptr_t* arguments) +{ + return cast(t, reinterpret_cast(arguments[0]))->length(t); +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_java_lang_String_intern(Thread* t, object, uintptr_t* arguments) +{ + return reinterpret_cast( + intern(t, reinterpret_cast(arguments[0]))); +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_java_lang_String_charAt(Thread* t, object, uintptr_t* arguments) +{ + return stringCharAt(t, + cast(t, reinterpret_cast(arguments[0])), + arguments[1]); +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_java_lang_String_equals(Thread* t, object, uintptr_t* arguments) +{ + return arguments[1] and stringEqual(t, + reinterpret_cast(arguments[0]), + reinterpret_cast(arguments[1])); +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_java_lang_String_fastIndexOf(Thread* t, object, uintptr_t* arguments) +{ + GcString* s = cast(t, reinterpret_cast(arguments[0])); + unsigned c = arguments[1]; + unsigned start = arguments[2]; + + for (unsigned i = start; i < s->length(t); ++i) { + if (stringCharAt(t, s, i) == c) { + return i; + } + } + + return -1; +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_avian_SystemClassLoader_findLoadedVMClass(Thread*, + object, + uintptr_t*); + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_dalvik_system_VMRuntime_bootClassPath(Thread* t, object, uintptr_t*) +{ + return reinterpret_cast(roots(t)->bootLoader()); +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_dalvik_system_VMRuntime_classPath(Thread* t, object, uintptr_t*) +{ + return reinterpret_cast(roots(t)->appLoader()); +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_dalvik_system_VMRuntime_vmVersion(Thread* t, object, uintptr_t*) +{ + return reinterpret_cast(makeString(t, "%s", AVIAN_VERSION)); +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_dalvik_system_VMRuntime_properties(Thread* t, object, uintptr_t*) +{ + object array + = makeObjectArray(t, type(t, GcString::Type), t->m->propertyCount + 1); + PROTECT(t, array); + + unsigned i; + for (i = 0; i < t->m->propertyCount; ++i) { + GcString* s = makeString(t, "%s", t->m->properties[i]); + setField( + t, array, ArrayBody + (i * BytesPerWord), reinterpret_cast(s)); + } + + { + GcString* s = makeString(t, "%s", "java.protocol.handler.pkgs=avian"); + setField(t, + array, + ArrayBody + (i++ * BytesPerWord), + reinterpret_cast(s)); + } + + return reinterpret_cast(array); +} + +extern "C" AVIAN_EXPORT void JNICALL + Avian_java_lang_Runtime_gc(Thread* t, object, uintptr_t*) +{ + collect(t, Heap::MajorCollection); +} + +extern "C" AVIAN_EXPORT jlong JNICALL + Avian_java_lang_Runtime_maxMemory(Thread* t, object, uintptr_t*) +{ + return t->m->heap->limit(); +} + +extern "C" AVIAN_EXPORT void JNICALL + Avian_java_lang_Runtime_nativeExit(Thread* t, object, uintptr_t* arguments) +{ + shutDown(t); + + t->m->system->exit(arguments[0]); +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_java_lang_Runtime_nativeLoad(Thread* t, object, uintptr_t* arguments) +{ + GcString* name = cast(t, reinterpret_cast(arguments[0])); + PROTECT(t, name); + + unsigned length = name->length(t); + THREAD_RUNTIME_ARRAY(t, char, n, length + 1); + stringChars(t, name, RUNTIME_ARRAY_BODY(n)); + + if (loadLibrary(t, "", RUNTIME_ARRAY_BODY(n), false, true)) { + return 0; + } else { + return reinterpret_cast(name); + } +} + +extern "C" AVIAN_EXPORT void JNICALL + Avian_java_lang_System_arraycopy(Thread* t, object, uintptr_t* arguments) +{ + arrayCopy(t, + reinterpret_cast(arguments[0]), + arguments[1], + reinterpret_cast(arguments[2]), + arguments[3], + arguments[4]); +} + +extern "C" AVIAN_EXPORT void JNICALL + Avian_java_lang_System_arraycopyCharUnchecked(Thread* t, + object method, + uintptr_t* arguments) +{ + Avian_java_lang_System_arraycopy(t, method, arguments); +} + +extern "C" AVIAN_EXPORT void JNICALL + Avian_java_lang_System_arraycopyByteUnchecked(Thread* t, + object method, + uintptr_t* arguments) +{ + Avian_java_lang_System_arraycopy(t, method, arguments); +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_sun_misc_Unsafe_objectFieldOffset(Thread* t, + object, + uintptr_t* arguments) +{ + return cast(t, reinterpret_cast(arguments[1])) + ->vmField() + ->offset(); +} + +extern "C" AVIAN_EXPORT void JNICALL + Avian_java_lang_Thread_nativeInterrupt(Thread* t, + object, + uintptr_t* arguments) +{ + interrupt( + t, + reinterpret_cast( + cast(t, reinterpret_cast(arguments[0]))->peer())); +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_java_lang_Thread_interrupted(Thread* t, object, uintptr_t*) +{ + return getAndClearInterrupted(t, t); +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_java_lang_Thread_isInterrupted(Thread* t, + object, + uintptr_t* arguments) +{ + return cast(t, reinterpret_cast(arguments[0])) + ->interrupted(); +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_java_lang_Thread_nativeGetStatus(Thread*, + object, + uintptr_t* arguments) +{ + enum { New, Runnable, Blocked, Waiting, TimedWaiting, Terminated }; + + // todo: more detail? (e.g. waiting, terminated, etc.) + return arguments[1] ? Runnable : New; +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_java_lang_Thread_currentThread(Thread* t, object, uintptr_t*) +{ + return reinterpret_cast(t->javaThread); +} + +extern "C" AVIAN_EXPORT void JNICALL + Avian_java_lang_Thread_nativeCreate(Thread* t, object, uintptr_t* arguments) +{ + startThread(t, cast(t, reinterpret_cast(arguments[0]))); +} + +extern "C" AVIAN_EXPORT void JNICALL + Avian_java_lang_Thread_nativeSetName(Thread*, object, uintptr_t*) +{ + // ignore +} + +extern "C" AVIAN_EXPORT void JNICALL + Avian_java_lang_Thread_sleep(Thread* t, object, uintptr_t* arguments) +{ + object lock = reinterpret_cast(arguments[0]); + PROTECT(t, lock); + + int64_t milliseconds; + memcpy(&milliseconds, arguments + 1, 8); + if (arguments[2] > 0) + ++milliseconds; + if (milliseconds <= 0) + milliseconds = 1; + + acquire(t, lock); + vm::wait(t, lock, milliseconds); + release(t, lock); +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_java_lang_Thread_nativeHoldsLock(Thread* t, + object, + uintptr_t* arguments) +{ + if (cast(t, reinterpret_cast(arguments[0])) + != t->javaThread) { + throwNew(t, + GcIllegalStateException::Type, + "VMThread.holdsLock may only be called on current thread"); + } + + GcMonitor* m + = objectMonitor(t, reinterpret_cast(arguments[1]), false); + + return m and m->owner() == t; +} + +extern "C" AVIAN_EXPORT void JNICALL + Avian_java_lang_Thread_yield(Thread* t, object, uintptr_t*) +{ + t->m->system->yield(); +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_dalvik_system_VMStack_getThreadStackTrace(Thread* t, + object, + uintptr_t* arguments) +{ + Thread* p = reinterpret_cast( + cast(t, reinterpret_cast(arguments[0]))->peer()); + + return reinterpret_cast(local::translateStackTrace( + t, p == t ? makeTrace(t) : t->m->processor->getStackTrace(t, p))); +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_dalvik_system_VMStack_getCallingClassLoader(Thread* t, + object, + uintptr_t*) +{ + class Visitor : public Processor::StackVisitor { + public: + Visitor(Thread* t) : t(t), loader(0), counter(2) + { + } + + virtual bool visit(Processor::StackWalker* walker) + { + if (counter--) { + return true; + } else { + this->loader = walker->method()->class_()->loader(); + return false; + } + } + + Thread* t; + GcClassLoader* loader; + unsigned counter; + } v(t); + + t->m->processor->walkStack(t, &v); + + return reinterpret_cast(v.loader); +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_dalvik_system_VMStack_getClosestUserClassLoader(Thread* t, + object, + uintptr_t* arguments) +{ + GcClassLoader* boot + = cast(t, reinterpret_cast(arguments[0])); + + GcClassLoader* app + = cast(t, reinterpret_cast(arguments[1])); + + class Visitor : public Processor::StackVisitor { + public: + Visitor(Thread* t, GcClassLoader* boot, GcClassLoader* app) + : t(t), loader(0), boot(boot), app(app) + { + } + + virtual bool visit(Processor::StackWalker* walker) + { + GcClassLoader* loader = walker->method()->class_()->loader(); + if (loader == boot or loader == app) { + return true; + } else { + this->loader = loader; + return false; + } + } + + Thread* t; + GcClassLoader* loader; + GcClassLoader* boot; + GcClassLoader* app; + } v(t, boot, app); + + t->m->processor->walkStack(t, &v); + + return reinterpret_cast(v.loader); +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_dalvik_system_VMStack_getClasses(Thread* t, object, uintptr_t*) +{ + class Visitor : public Processor::StackVisitor { + public: + Visitor(Thread* t) : t(t), array(0), counter(0) + { + } + + virtual bool visit(Processor::StackWalker* walker) + { + if (counter < 2) { + return true; + } else { + if (array == 0) { + array = makeObjectArray(t, type(t, GcJclass::Type), walker->count()); + } + + GcJclass* c = getJClass(t, walker->method()->class_()); + + assertT(t, counter - 2 < objectArrayLength(t, array)); + + setField(t, array, ArrayBody + ((counter - 2) * BytesPerWord), c); + + return true; + } + + ++counter; + } + + Thread* t; + object array; + unsigned counter; + } v(t); + + PROTECT(t, v.array); + + t->m->processor->walkStack(t, &v); + + return reinterpret_cast( + v.array ? v.array : makeObjectArray(t, type(t, GcJclass::Type), 0)); +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_java_lang_Math_min(Thread*, object, uintptr_t* arguments) +{ + return min(static_cast(arguments[0]), static_cast(arguments[1])); +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_java_lang_Math_max(Thread*, object, uintptr_t* arguments) +{ + return max(static_cast(arguments[0]), static_cast(arguments[1])); +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_java_lang_Math_cos(Thread*, object, uintptr_t* arguments) +{ + int64_t v; + memcpy(&v, arguments, 8); + return doubleToBits(cos(bitsToDouble(v))); +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_java_lang_Math_sin(Thread*, object, uintptr_t* arguments) +{ + int64_t v; + memcpy(&v, arguments, 8); + return doubleToBits(sin(bitsToDouble(v))); +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_java_lang_Math_sqrt(Thread*, object, uintptr_t* arguments) +{ + int64_t v; + memcpy(&v, arguments, 8); + return doubleToBits(sqrt(bitsToDouble(v))); +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_java_lang_Math_abs__I(Thread*, object, uintptr_t* arguments) +{ + return abs(static_cast(arguments[0])); +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_java_lang_Math_abs__J(Thread*, object, uintptr_t* arguments) +{ + int64_t v; memcpy(&v, arguments, 8); + return llabs(v); +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_java_lang_Math_abs__F(Thread*, object, uintptr_t* arguments) +{ + return floatToBits(abs(bitsToFloat(arguments[0]))); +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_java_lang_Float_intBitsToFloat(Thread*, object, uintptr_t* arguments) +{ + return arguments[0]; +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_java_lang_Float_floatToIntBits(Thread*, object, uintptr_t* arguments) +{ + if (((arguments[0] & 0x7F800000) == 0x7F800000) + and ((arguments[0] & 0x007FFFFF) != 0)) { + return 0x7fc00000; + } else { + return arguments[0]; + } +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_java_lang_Double_doubleToRawLongBits(Thread*, + object, + uintptr_t* arguments) +{ + int64_t v; + memcpy(&v, arguments, 8); + // todo: do we need to do NaN checks as in + // Avian_java_lang_Float_floatToIntBits above? If so, update + // Double.doubleToRawLongBits in the Avian class library too. + return v; +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_java_lang_reflect_Method_getCaller(Thread* t, object, uintptr_t*) +{ + return reinterpret_cast(getCaller(t, 2)); +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_java_lang_reflect_Method_invoke(Thread* t, + object, + uintptr_t* arguments) +{ + return invokeMethod(t, + cast(t, reinterpret_cast(arguments[0])), + reinterpret_cast(arguments[1]), + reinterpret_cast(arguments[2])); +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_java_lang_reflect_Field_getObject(Thread*, + object, + uintptr_t* arguments) +{ + return reinterpret_cast(fieldAtOffset( + reinterpret_cast(arguments[0]), arguments[1])); +} + +extern "C" AVIAN_EXPORT void JNICALL + Avian_java_lang_reflect_Field_setObject(Thread* t, + object, + uintptr_t* arguments) +{ + setField(t, + reinterpret_cast(arguments[0]), + arguments[1], + reinterpret_cast(arguments[2])); +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_java_lang_reflect_Field_getPrimitive(Thread* t, + object, + uintptr_t* arguments) +{ + return getPrimitive( + t, reinterpret_cast(arguments[0]), arguments[1], arguments[2]); +} + +extern "C" AVIAN_EXPORT void JNICALL + Avian_java_lang_reflect_Field_setPrimitive(Thread* t, + object, + uintptr_t* arguments) +{ + int64_t value; + memcpy(&value, arguments + 3, 8); + + setPrimitive(t, + reinterpret_cast(arguments[0]), + arguments[1], + arguments[2], + value); +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_java_lang_reflect_Constructor_make(Thread* t, + object, + uintptr_t* arguments) +{ + return reinterpret_cast( + make(t, cast(t, reinterpret_cast(arguments[0])))); +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_java_lang_ref_Reference_get(Thread* t, object, uintptr_t* arguments) +{ + return reinterpret_cast( + cast(t, reinterpret_cast(arguments[0]))->target()); +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_java_lang_Throwable_nativeFillInStackTrace(Thread* t, + object, + uintptr_t*) +{ + return reinterpret_cast(getTrace(t, 2)); +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_java_lang_Throwable_nativeGetStackTrace(Thread* t, + object, + uintptr_t* arguments) +{ + return reinterpret_cast( + local::translateStackTrace(t, reinterpret_cast(arguments[0]))); +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_avian_Classes_getVMClass(Thread* t, object, uintptr_t* arguments) +{ + return reinterpret_cast( + objectClass(t, reinterpret_cast(arguments[0]))); +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_avian_Classes_makeMethod(Thread* t, object, uintptr_t* arguments) +{ + return reinterpret_cast( + makeMethod(t, + cast(t, reinterpret_cast(arguments[0])), + arguments[1])); +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_avian_Classes_isAssignableFrom(Thread* t, + object, + uintptr_t* arguments) +{ + GcClass* this_ = cast(t, reinterpret_cast(arguments[0])); + GcClass* that = cast(t, reinterpret_cast(arguments[1])); + + if (LIKELY(that)) { + return vm::isAssignableFrom(t, this_, that); + } else { + throwNew(t, GcNullPointerException::Type); + } +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_java_lang_reflect_Array_createObjectArray(Thread* t, + object, + uintptr_t* arguments) +{ + return reinterpret_cast(makeObjectArray( + t, + cast(t, reinterpret_cast(arguments[0]))->vmClass(), + arguments[1])); +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_java_nio_ByteOrder_isLittleEndian(Thread*, object, uintptr_t*) +{ + return true; +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_dalvik_system_VMRuntime_newNonMovableArray(Thread* t, + object, + uintptr_t* arguments) +{ + if (cast(t, reinterpret_cast(arguments[1]))->vmClass() + == type(t, GcJbyte::Type)) { + GcByteArray* array + = reinterpret_cast(allocate3(t, + t->m->heap, + Machine::FixedAllocation, + ArrayBody + arguments[2], + false)); + + setObjectClass(t, array, type(t, GcByteArray::Type)); + array->length() = arguments[2]; + + return reinterpret_cast(array); + } else { + // todo + abort(t); + } +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_dalvik_system_VMRuntime_addressOf(Thread*, + object, + uintptr_t* arguments) +{ + return arguments[1] + ArrayBody; +} + +extern "C" AVIAN_EXPORT void JNICALL + Avian_libcore_io_Memory_pokeLong(Thread*, object, uintptr_t* arguments) +{ + int64_t address; + memcpy(&address, arguments, 8); + int64_t v; + memcpy(&v, arguments + 2, 8); + if (arguments[4]) { + v = swapV8(v); + } + memcpy(reinterpret_cast(address), &v, 8); +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_libcore_io_Memory_peekLong(Thread*, object, uintptr_t* arguments) +{ + int64_t address; + memcpy(&address, arguments, 8); + int64_t v; + memcpy(&v, reinterpret_cast(address), 8); + return arguments[2] ? swapV8(v) : v; +} + +extern "C" AVIAN_EXPORT void JNICALL + Avian_libcore_io_Memory_pokeInt(Thread*, object, uintptr_t* arguments) +{ + int64_t address; + memcpy(&address, arguments, 8); + int32_t v = arguments[3] ? swapV4(arguments[2]) : arguments[2]; + memcpy(reinterpret_cast(address), &v, 4); +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_libcore_io_Memory_peekInt(Thread*, object, uintptr_t* arguments) +{ + int64_t address; + memcpy(&address, arguments, 8); + int32_t v; + memcpy(&v, reinterpret_cast(address), 4); + return arguments[2] ? swapV4(v) : v; +} + +extern "C" AVIAN_EXPORT void JNICALL + Avian_libcore_io_Memory_pokeShort(Thread*, object, uintptr_t* arguments) +{ + int64_t address; + memcpy(&address, arguments, 8); + int16_t v = arguments[3] ? swapV2(arguments[2]) : arguments[2]; + memcpy(reinterpret_cast(address), &v, 2); +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_libcore_io_Memory_peekShort(Thread*, object, uintptr_t* arguments) +{ + int64_t address; + memcpy(&address, arguments, 8); + int16_t v; + memcpy(&v, reinterpret_cast(address), 2); + return arguments[2] ? swapV2(v) : v; +} + +extern "C" AVIAN_EXPORT void JNICALL + Avian_libcore_io_Memory_pokeByte(Thread*, object, uintptr_t* arguments) +{ + int64_t address; + memcpy(&address, arguments, 8); + *reinterpret_cast(address) = arguments[2]; +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_libcore_io_Memory_peekByte(Thread*, object, uintptr_t* arguments) +{ + int64_t address; + memcpy(&address, arguments, 8); + return *reinterpret_cast(address); +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_java_lang_System_nanoTime(Thread* t, object, uintptr_t*) +{ + return t->m->system->now() * 1000 * 1000; +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_java_lang_System_currentTimeMillis(Thread* t, object, uintptr_t*) +{ + return t->m->system->now(); +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_java_lang_System_identityHashCode(Thread* t, + object, + uintptr_t* arguments) +{ + return objectHash(t, reinterpret_cast(arguments[0])); +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_java_util_concurrent_atomic_AtomicLong_VMSupportsCS8(Thread*, + object, + uintptr_t*) +{ + return true; +} + +#ifdef PLATFORM_WINDOWS + +#include + +void register_java_io_Console(_JNIEnv*) +{ +} +void register_java_lang_ProcessManager(_JNIEnv*) +{ +} +void register_libcore_net_RawSocket(_JNIEnv*) +{ +} +// void register_org_apache_harmony_xnet_provider_jsse_NativeCrypto(_JNIEnv*) { +// } + +extern "C" AVIAN_EXPORT void JNICALL + Avian_libcore_io_OsConstants_initConstants(Thread* t, + object m, + uintptr_t*) +{ + GcMethod* method = cast(t, m); + GcClass* c = method->class_(); + PROTECT(t, c); + + object table = c->staticTable(); + PROTECT(t, table); + + GcField* field = resolveField(t, c, "STDIN_FILENO", "I"); + fieldAtOffset(table, field->offset()) = 0; + + field = resolveField(t, c, "STDOUT_FILENO", "I"); + fieldAtOffset(table, field->offset()) = 1; + + field = resolveField(t, c, "STDERR_FILENO", "I"); + fieldAtOffset(table, field->offset()) = 2; +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_libcore_io_Posix_getenv(Thread* t, object, uintptr_t* arguments) +{ + GcString* name = cast(t, reinterpret_cast(arguments[1])); + + THREAD_RUNTIME_ARRAY(t, uint16_t, chars, name->length(t) + 1); + stringChars(t, name, RUNTIME_ARRAY_BODY(chars)); + + wchar_t* value + = _wgetenv(reinterpret_cast(RUNTIME_ARRAY_BODY(chars))); + + if (value) { + unsigned size = wcslen(value); + + GcCharArray* a = makeCharArray(t, size); + if (size) { + memcpy(a->body().begin(), value, size * sizeof(jchar)); + } + + return reinterpret_cast( + t->m->classpath->makeString(t, a, 0, size)); + } else { + return 0; + } +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_libcore_io_Posix_uname(Thread* t, object, uintptr_t*) +{ + GcClass* c + = resolveClass(t, roots(t)->bootLoader(), "libcore/io/StructUtsname"); + PROTECT(t, c); + + object instance = makeNew(t, c); + PROTECT(t, instance); + +#ifdef ARCH_x86_32 + object arch = makeString(t, "x86"); +#elif defined ARCH_x86_64 + object arch = makeString(t, "x86_64"); +#elif defined ARCH_arm + object arch = makeString(t, "arm"); +#else + object arch = makeString(t, "unknown"); +#endif + + setField(t, + instance, + resolveField(t, c, "machine", "Ljava/lang/String;")->offset(), + arch); + + object platform = makeString(t, "Windows"); + + setField(t, + instance, + resolveField(t, c, "sysname", "Ljava/lang/String;")->offset(), + platform); + + object version = makeString(t, "unknown"); + + setField(t, + instance, + resolveField(t, c, "release", "Ljava/lang/String;")->offset(), + version); + + return reinterpret_cast(instance); +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_libcore_io_Posix_writeBytes(Thread* t, object, uintptr_t* arguments) +{ + object fd = reinterpret_cast(arguments[1]); + PROTECT(t, fd); + + GcByteArray* buffer = cast(t, reinterpret_cast(arguments[2])); + PROTECT(t, buffer); + + int offset = arguments[3]; + int count = arguments[4]; + + int d = jniGetFDFromFileDescriptor(t, &fd); + + int r; + if (objectClass(t, buffer) == type(t, GcByteArray::Type)) { + void* tmp = t->m->heap->allocate(count); + memcpy(tmp, &buffer->body()[offset], count); + { + ENTER(t, Thread::IdleState); + r = _write(d, tmp, count); + } + t->m->heap->free(tmp, count); + } else { + void* p = local::getDirectBufferAddress(t, buffer); + { + ENTER(t, Thread::IdleState); + r = _write(d, p, count); + } + } + + if (r < 0) { + THREAD_RUNTIME_ARRAY(t, char, message, 256); + throwNew(t, + GcRuntimeException::Type, + "writeBytes %d: %s", + d, + jniStrError(errno, RUNTIME_ARRAY_BODY(message), 0)); + } else { + return r; + } +} + +#endif diff --git a/sgx-jvm/avian/src/classpath-avian.cpp b/sgx-jvm/avian/src/classpath-avian.cpp new file mode 100644 index 0000000000..41ca4b1637 --- /dev/null +++ b/sgx-jvm/avian/src/classpath-avian.cpp @@ -0,0 +1,692 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#include "avian/machine.h" +#include "avian/classpath-common.h" +#include "avian/process.h" + +#include + +using namespace vm; + +namespace { + +namespace local { + +class MyClasspath : public Classpath { + public: + MyClasspath(Allocator* allocator) : allocator(allocator) + { + } + + virtual GcJclass* makeJclass(Thread* t, GcClass* class_) + { + return vm::makeJclass(t, class_); + } + + virtual GcString* makeString(Thread* t, + object array, + int32_t offset, + int32_t length) + { + return vm::makeString(t, array, offset, length, 0); + } + + virtual GcThread* makeThread(Thread* t, Thread* parent) + { + GcThreadGroup* group; + if (parent) { + group = parent->javaThread->group(); + } else { + group = makeThreadGroup(t, 0, 0, 0); + } + + const unsigned NewState = 0; + const unsigned NormalPriority = 5; + + return vm::makeThread(t, + 0, + 0, + 0, + 0, + 0, + NewState, + NormalPriority, + 0, + 0, + 0, + roots(t)->appLoader(), + 0, + 0, + group, + 0); + } + + virtual object makeJMethod(Thread* t, GcMethod* vmMethod) + { + PROTECT(t, vmMethod); + + GcJmethod* jmethod = makeJmethod(t, vmMethod, false); + + return vmMethod->name()->body()[0] == '<' + ? (object)makeJconstructor(t, jmethod) + : (object)jmethod; + } + + virtual GcMethod* getVMMethod(Thread* t, object jmethod) + { + return objectClass(t, jmethod) == type(t, GcJmethod::Type) + ? cast(t, jmethod)->vmMethod() + : cast(t, jmethod)->method()->vmMethod(); + } + + virtual object makeJField(Thread* t, GcField* vmField) + { + return makeJfield(t, vmField, false); + } + + virtual GcField* getVMField(Thread* t UNUSED, GcJfield* jfield) + { + return jfield->vmField(); + } + + virtual void clearInterrupted(Thread*) + { + // ignore + } + + virtual void runThread(Thread* t) + { + GcMethod* method = resolveMethod(t, + roots(t)->bootLoader(), + "java/lang/Thread", + "run", + "(Ljava/lang/Thread;)V"); + + t->m->processor->invoke(t, method, 0, t->javaThread); + } + + virtual void resolveNative(Thread* t, GcMethod* method) + { + vm::resolveNative(t, method); + } + + virtual void interceptMethods(Thread*) + { + // ignore + } + + virtual void preBoot(Thread*) + { + // ignore + } + + virtual bool mayInitClasses() + { + return true; + } + + virtual void boot(Thread*) + { + // ignore + } + + virtual const char* bootClasspath() + { + return AVIAN_CLASSPATH; + } + + virtual object makeDirectByteBuffer(Thread* t, void* p, jlong capacity) + { + GcClass* c + = resolveClass(t, roots(t)->bootLoader(), "java/nio/DirectByteBuffer"); + PROTECT(t, c); + + object instance = makeNew(t, c); + PROTECT(t, instance); + + GcMethod* constructor = resolveMethod(t, c, "", "(JI)V"); + + t->m->processor->invoke(t, + constructor, + instance, + reinterpret_cast(p), + static_cast(capacity)); + + return instance; + } + + virtual void* getDirectBufferAddress(Thread* t, object b) + { + PROTECT(t, b); + + GcField* field = resolveField(t, objectClass(t, b), "address", "J"); + + return reinterpret_cast(fieldAtOffset(b, field->offset())); + } + + virtual int64_t getDirectBufferCapacity(Thread* t, object b) + { + PROTECT(t, b); + + GcField* field = resolveField(t, objectClass(t, b), "capacity", "I"); + + return fieldAtOffset(b, field->offset()); + } + + virtual bool canTailCall(Thread* t UNUSED, + GcMethod*, + GcByteArray* calleeClassName, + GcByteArray* calleeMethodName, + GcByteArray*) + { + // we can't tail call System.load[Library] or + // Runtime.load[Library] due to their use of + // ClassLoader.getCaller, which gets confused if we elide stack + // frames. + + return ( + (strcmp("loadLibrary", + reinterpret_cast(calleeMethodName->body().begin())) + and strcmp("load", + reinterpret_cast(calleeMethodName->body().begin()))) + or (strcmp("java/lang/System", + reinterpret_cast(calleeClassName->body().begin())) + and strcmp( + "java/lang/Runtime", + reinterpret_cast(calleeClassName->body().begin())))); + } + + virtual GcClassLoader* libraryClassLoader(Thread* t, GcMethod* caller) + { + return (caller->class_() == type(t, Gc::ClassLoaderType) + and t->libraryLoadStack) + ? t->libraryLoadStack->classLoader + : caller->class_()->loader(); + } + + virtual void shutDown(Thread*) + { + // ignore + } + + virtual void dispose() + { + allocator->free(this, sizeof(*this)); + } + + Allocator* allocator; +}; + +void enumerateThreads(Thread* t, + Thread* x, + GcArray* array, + unsigned* index, + unsigned limit) +{ + if (*index < limit) { + array->setBodyElement(t, *index, x->javaThread); + ++(*index); + + if (x->peer) + enumerateThreads(t, x->peer, array, index, limit); + + if (x->child) + enumerateThreads(t, x->child, array, index, limit); + } +} + +} // namespace local + +} // namespace + +namespace vm { + +Classpath* makeClasspath(System*, + Allocator* allocator, + const char*, + const char*) +{ + return new (allocator->allocate(sizeof(local::MyClasspath))) + local::MyClasspath(allocator); +} + +} // namespace vm + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_java_io_ObjectInputStream_makeInstance(Thread* t, + object, + uintptr_t* arguments) +{ + GcClass* c = cast(t, reinterpret_cast(arguments[0])); + + return reinterpret_cast(make(t, c)); +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_avian_LegacyObjectInputStream_makeInstance(Thread* t, + object, + uintptr_t* arguments) +{ + return Avian_java_io_ObjectInputStream_makeInstance(t, NULL, arguments); +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_java_lang_reflect_Field_getPrimitive(Thread* t, + object, + uintptr_t* arguments) +{ + return getPrimitive( + t, reinterpret_cast(arguments[0]), arguments[1], arguments[2]); +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_java_lang_reflect_Field_getObject(Thread*, + object, + uintptr_t* arguments) +{ + return reinterpret_cast(fieldAtOffset( + reinterpret_cast(arguments[0]), arguments[1])); +} + +extern "C" AVIAN_EXPORT void JNICALL + Avian_java_lang_reflect_Field_setPrimitive(Thread* t, + object, + uintptr_t* arguments) +{ + int64_t value; + memcpy(&value, arguments + 3, 8); + + setPrimitive(t, + reinterpret_cast(arguments[0]), + arguments[1], + arguments[2], + value); +} + +extern "C" AVIAN_EXPORT void JNICALL + Avian_java_lang_reflect_Field_setObject(Thread* t, + object, + uintptr_t* arguments) +{ + setField(t, + reinterpret_cast(arguments[0]), + arguments[1], + reinterpret_cast(arguments[2])); +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_java_lang_reflect_Constructor_make(Thread* t, + object, + uintptr_t* arguments) +{ + return reinterpret_cast( + make(t, cast(t, reinterpret_cast(arguments[0])))); +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_java_lang_reflect_Method_getCaller(Thread* t, object, uintptr_t*) +{ + return reinterpret_cast(getCaller(t, 2)); +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_java_lang_reflect_Method_invoke(Thread* t, + object, + uintptr_t* arguments) +{ + return invokeMethod(t, + cast(t, reinterpret_cast(arguments[0])), + reinterpret_cast(arguments[1]), + reinterpret_cast(arguments[2])); +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_java_lang_reflect_Array_getLength(Thread* t, + object, + uintptr_t* arguments) +{ + object array = reinterpret_cast(arguments[0]); + + if (LIKELY(array)) { + unsigned elementSize = objectClass(t, array)->arrayElementSize(); + + if (LIKELY(elementSize)) { + return fieldAtOffset(array, BytesPerWord); + } else { + throwNew(t, GcIllegalArgumentException::Type); + } + } else { + throwNew(t, GcNullPointerException::Type); + } +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_java_lang_reflect_Array_makeObjectArray(Thread* t, + object, + uintptr_t* arguments) +{ + GcJclass* elementType + = cast(t, reinterpret_cast(arguments[0])); + int length = arguments[1]; + + return reinterpret_cast( + makeObjectArray(t, elementType->vmClass(), length)); +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_java_lang_Float_floatToRawIntBits(Thread*, + object, + uintptr_t* arguments) +{ + return static_cast(*arguments); +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_java_lang_Float_intBitsToFloat(Thread*, object, uintptr_t* arguments) +{ + return static_cast(*arguments); +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_java_lang_Double_doubleToRawLongBits(Thread*, + object, + uintptr_t* arguments) +{ + int64_t v; + memcpy(&v, arguments, 8); + return v; +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_java_lang_Double_longBitsToDouble(Thread*, + object, + uintptr_t* arguments) +{ + int64_t v; + memcpy(&v, arguments, 8); + return v; +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_java_lang_String_intern(Thread* t, object, uintptr_t* arguments) +{ + object this_ = reinterpret_cast(arguments[0]); + + return reinterpret_cast(intern(t, this_)); +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_java_lang_System_getVMProperties(Thread* t, object, uintptr_t*) +{ + object array + = makeObjectArray(t, type(t, GcString::Type), t->m->propertyCount); + PROTECT(t, array); + + for (unsigned i = 0; i < t->m->propertyCount; ++i) { + GcString* s = makeString(t, "%s", t->m->properties[i]); + reinterpret_cast(array)->setBodyElement(t, i, s); + } + + return reinterpret_cast(array); +} + +extern "C" AVIAN_EXPORT void JNICALL + Avian_java_lang_System_arraycopy(Thread* t, object, uintptr_t* arguments) +{ + arrayCopy(t, + reinterpret_cast(arguments[0]), + arguments[1], + reinterpret_cast(arguments[2]), + arguments[3], + arguments[4]); +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_java_lang_System_identityHashCode(Thread* t, + object, + uintptr_t* arguments) +{ + object o = reinterpret_cast(arguments[0]); + + if (LIKELY(o)) { + return objectHash(t, o); + } else { + throwNew(t, GcNullPointerException::Type); + } +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_java_lang_ClassLoader_getCaller(Thread* t, object, uintptr_t*) +{ + return reinterpret_cast(getJClass(t, getCaller(t, 2)->class_())); +} + +extern "C" AVIAN_EXPORT void JNICALL + Avian_java_lang_ClassLoader_load(Thread* t, object, uintptr_t* arguments) +{ + GcString* name = cast(t, reinterpret_cast(arguments[0])); + + Thread::LibraryLoadStack stack( + t, + cast(t, reinterpret_cast(arguments[1])) + ->vmClass() + ->loader()); + + bool mapName = arguments[2]; + + unsigned length = name->length(t); + THREAD_RUNTIME_ARRAY(t, char, n, length + 1); + stringChars(t, name, RUNTIME_ARRAY_BODY(n)); + + loadLibrary(t, "", RUNTIME_ARRAY_BODY(n), mapName, true); +} + +extern "C" AVIAN_EXPORT void JNICALL + Avian_java_lang_Runtime_gc(Thread* t, object, uintptr_t*) +{ + collect(t, Heap::MajorCollection); +} + +extern "C" AVIAN_EXPORT void JNICALL + Avian_java_lang_Runtime_addShutdownHook(Thread* t, + object, + uintptr_t* arguments) +{ + object hook = reinterpret_cast(arguments[1]); + PROTECT(t, hook); + + ACQUIRE(t, t->m->shutdownLock); + + GcPair* p = makePair(t, hook, roots(t)->shutdownHooks()); + // sequence point, for gc (don't recombine statements) + roots(t)->setShutdownHooks(t, p); +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_java_lang_Throwable_trace(Thread* t, object, uintptr_t* arguments) +{ + return reinterpret_cast(getTrace(t, arguments[0])); +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_java_lang_Throwable_resolveTrace(Thread* t, + object, + uintptr_t* arguments) +{ + object trace = reinterpret_cast(*arguments); + PROTECT(t, trace); + + unsigned length = objectArrayLength(t, trace); + GcClass* elementType = type(t, GcStackTraceElement::Type); + object array = makeObjectArray(t, elementType, length); + PROTECT(t, array); + + for (unsigned i = 0; i < length; ++i) { + GcStackTraceElement* ste = makeStackTraceElement( + t, cast(t, objectArrayBody(t, trace, i))); + reinterpret_cast(array)->setBodyElement(t, i, ste); + } + + return reinterpret_cast(array); +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_java_lang_Thread_currentThread(Thread* t, object, uintptr_t*) +{ + return reinterpret_cast(t->javaThread); +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_java_lang_Thread_doStart(Thread* t, object, uintptr_t* arguments) +{ + return reinterpret_cast( + startThread(t, cast(t, reinterpret_cast(*arguments)))); +} + +extern "C" AVIAN_EXPORT void JNICALL + Avian_java_lang_Thread_interrupt(Thread* t, object, uintptr_t* arguments) +{ + int64_t peer; + memcpy(&peer, arguments, 8); + + threadInterrupt(t, reinterpret_cast(peer)->javaThread); +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_java_lang_Thread_interrupted(Thread* t, object, uintptr_t* arguments) +{ + int64_t peer; + memcpy(&peer, arguments, 8); + + return threadIsInterrupted( + t, reinterpret_cast(peer)->javaThread, true); +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_java_lang_Thread_getStackTrace(Thread* t, + object, + uintptr_t* arguments) +{ + int64_t peer; + memcpy(&peer, arguments, 8); + + if (reinterpret_cast(peer) == t) { + return reinterpret_cast(makeTrace(t)); + } else { + return reinterpret_cast( + t->m->processor->getStackTrace(t, reinterpret_cast(peer))); + } +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_java_lang_Thread_activeCount(Thread* t, object, uintptr_t*) +{ + return t->m->liveCount; +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_java_lang_Thread_enumerate(Thread* t, object, uintptr_t* arguments) +{ + GcArray* array = cast(t, reinterpret_cast(*arguments)); + + ACQUIRE_RAW(t, t->m->stateLock); + + unsigned count = min(t->m->liveCount, + objectArrayLength(t, reinterpret_cast(array))); + unsigned index = 0; + local::enumerateThreads(t, t->m->rootThread, array, &index, count); + return count; +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_java_lang_Thread_holdsLock(Thread* t, object, uintptr_t* arguments) +{ + GcMonitor* m + = objectMonitor(t, reinterpret_cast(arguments[0]), false); + + return m and m->owner() == t; +} + +extern "C" AVIAN_EXPORT void JNICALL + Avian_java_lang_Thread_yield(Thread* t, object, uintptr_t*) +{ + t->m->system->yield(); +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_avian_Atomic_getOffset(Thread* t, object, uintptr_t* arguments) +{ + return cast(t, reinterpret_cast(arguments[0])) + ->vmField() + ->offset(); +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_sun_misc_Unsafe_objectFieldOffset(Thread* t, + object, + uintptr_t* arguments) +{ + return cast(t, reinterpret_cast(arguments[1])) + ->vmField() + ->offset(); +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_avian_Atomic_compareAndSwapObject(Thread* t, + object, + uintptr_t* arguments) +{ + object target = reinterpret_cast(arguments[0]); + int64_t offset; + memcpy(&offset, arguments + 1, 8); + uintptr_t expect = arguments[3]; + uintptr_t update = arguments[4]; + + bool success = atomicCompareAndSwap( + &fieldAtOffset(target, offset), expect, update); + + if (success) { + mark(t, target, offset); + } + + return success; +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_avian_Classes_isAssignableFrom(Thread* t, + object, + uintptr_t* arguments) +{ + GcClass* this_ = cast(t, reinterpret_cast(arguments[0])); + GcClass* that = cast(t, reinterpret_cast(arguments[1])); + + if (LIKELY(that)) { + return vm::isAssignableFrom(t, this_, that); + } else { + throwNew(t, GcNullPointerException::Type); + } +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_avian_Classes_getVMClass(Thread* t, object, uintptr_t* arguments) +{ + return reinterpret_cast( + objectClass(t, reinterpret_cast(arguments[0]))); +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_avian_Classes_makeMethod(Thread* t, object, uintptr_t* arguments) +{ + return reinterpret_cast( + makeMethod(t, + cast(t, reinterpret_cast(arguments[0])), + arguments[1])); +} diff --git a/sgx-jvm/avian/src/classpath-openjdk.cpp b/sgx-jvm/avian/src/classpath-openjdk.cpp new file mode 100644 index 0000000000..dfc8464c2e --- /dev/null +++ b/sgx-jvm/avian/src/classpath-openjdk.cpp @@ -0,0 +1,6149 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#include "avian/machine.h" +#include "avian/classpath-common.h" +#include "avian/util.h" +#include "avian/process.h" + +#ifdef PLATFORM_WINDOWS + +#include +#include +#include +#include +#include +#include +#include +#include + +#undef interface + +#define CLOSE _close +#define READ _read +#define WRITE _write +#define FSTAT _fstat +#define STAT _stat +#define LSEEK _lseek + +#define S_ISSOCK(x) false + +#ifdef _MSC_VER +#define S_ISREG(x) ((x) | _S_IFREG) +#define S_ISDIR(x) ((x) | _S_IFDIR) +#define S_IRUSR _S_IREAD +#define S_IWUSR _S_IWRITE +#else +#define OPEN _open +#endif + +#define O_RDONLY _O_RDONLY + +#if (defined AVIAN_OPENJDK_SRC) \ + || ((defined __x86_64__) && (defined __MINGW32__)) +#define EXPORT(x) x +#else +#define EXPORT(x) _##x +#endif + +typedef int socklen_t; + +#define RTLD_DEFAULT 0 + +#else // not PLATFORM_WINDOWS + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define OPEN open +#define CLOSE close +#define READ read +#define WRITE write +#define STAT stat +#define FSTAT fstat +#define LSEEK lseek + +#define EXPORT(x) x + +#endif // not PLATFORM_WINDOWS + +#define JVM_EEXIST -100 + +using namespace vm; + +namespace { + +#ifdef _MSC_VER +inline int OPEN(string_t path, int mask, int mode) +{ + int fd; + if (_wsopen_s(&fd, path, mask, _SH_DENYNO, mode) == 0) { + return fd; + } else { + return -1; + } +} +#endif + +namespace local { + +const int JMM_VERSION_1_0 = 0x20010000; + +struct jmmOptionalSupport { + unsigned isLowMemoryDetectionSupported : 1; + unsigned isCompilationTimeMonitoringSupported : 1; + unsigned isThreadContentionMonitoringSupported : 1; + unsigned isCurrentThreadCpuTimeSupported : 1; + unsigned isOtherThreadCpuTimeSupported : 1; + unsigned isBootClassPathSupported : 1; + unsigned isObjectMonitorUsageSupported : 1; + unsigned isSynchronizerUsageSupported : 1; +}; + +typedef unsigned jmmLongAttribute; +typedef unsigned jmmBoolAttribute; +typedef unsigned jmmStatisticType; +typedef unsigned jmmThresholdType; +typedef unsigned jmmVMGlobalType; +typedef unsigned jmmVMGlobalOrigin; + +struct jmmVMGlobal { + jstring name; + jvalue value; + jmmVMGlobalType type; + jmmVMGlobalOrigin origin; + unsigned writeable : 1; + unsigned external : 1; + unsigned reserved : 30; + void* reserved1; + void* reserved2; +}; + +struct jmmExtAttributeInfo { + const char* name; + char type; + const char* description; +}; + +struct jmmGCStat { + jlong gc_index; + jlong start_time; + jlong end_time; + jobjectArray usage_before_gc; + jobjectArray usage_after_gc; + jint gc_ext_attribute_values_size; + jvalue* gc_ext_attribute_values; + jint num_gc_ext_attributes; +}; + +struct JmmInterface { + void* reserved1; + void* reserved2; + + jint(JNICALL* GetVersion)(JNIEnv*); + + jint(JNICALL* GetOptionalSupport)(JNIEnv*, jmmOptionalSupport*); + + jobject(JNICALL* GetInputArguments)(JNIEnv*); + + jint(JNICALL* GetThreadInfo)(JNIEnv*, jlongArray, jint, jobjectArray); + + jobjectArray(JNICALL* GetInputArgumentArray)(JNIEnv*); + + jobjectArray(JNICALL* GetMemoryPools)(JNIEnv*, jobject); + + jobjectArray(JNICALL* GetMemoryManagers)(JNIEnv*, jobject); + + jobject(JNICALL* GetMemoryPoolUsage)(JNIEnv*, jobject); + + jobject(JNICALL* GetPeakMemoryPoolUsage)(JNIEnv*, jobject); + + void* reserved4; + + jobject(JNICALL* GetMemoryUsage)(JNIEnv*, jboolean); + + jlong(JNICALL* GetLongAttribute)(JNIEnv*, jobject, jmmLongAttribute); + + jboolean(JNICALL* GetBoolAttribute)(JNIEnv*, jmmBoolAttribute); + + jboolean(JNICALL* SetBoolAttribute)(JNIEnv*, jmmBoolAttribute, jboolean); + + jint(JNICALL* GetLongAttributes)(JNIEnv*, + jobject, + jmmLongAttribute*, + jint, + jlong*); + + jobjectArray(JNICALL* FindCircularBlockedThreads)(JNIEnv*); + + jlong(JNICALL* GetThreadCpuTime)(JNIEnv*, jlong); + + jobjectArray(JNICALL* GetVMGlobalNames)(JNIEnv*); + + jint(JNICALL* GetVMGlobals)(JNIEnv*, jobjectArray, jmmVMGlobal*, jint); + + jint(JNICALL* GetInternalThreadTimes)(JNIEnv*, jobjectArray, jlongArray); + + jboolean(JNICALL* ResetStatistic)(JNIEnv*, jvalue, jmmStatisticType); + + void(JNICALL* SetPoolSensor)(JNIEnv*, jobject, jmmThresholdType, jobject); + + jlong(JNICALL* SetPoolThreshold)(JNIEnv*, jobject, jmmThresholdType, jlong); + + jobject(JNICALL* GetPoolCollectionUsage)(JNIEnv*, jobject); + + jint(JNICALL* GetGCExtAttributeInfo)(JNIEnv*, + jobject, + jmmExtAttributeInfo*, + jint); + + void(JNICALL* GetLastGCStat)(JNIEnv*, jobject, jmmGCStat*); + + jlong(JNICALL* GetThreadCpuTimeWithKind)(JNIEnv*, jlong, jboolean); + + void* reserved5; + + jint(JNICALL* DumpHeap0)(JNIEnv*, jstring, jboolean); + + jobjectArray(JNICALL* FindDeadlocks)(JNIEnv*, jboolean); + + void(JNICALL* SetVMGlobal)(JNIEnv*, jstring, jvalue); + + void* reserved6; + + jobjectArray(JNICALL* DumpThreads)(JNIEnv*, jlongArray, jboolean, jboolean); +}; + +const unsigned InterfaceVersion = 4; +const unsigned PageSize = 4 * 1024; +#ifdef AVIAN_OPENJDK_SRC +const int VirtualFileBase = 1000000000; +#endif + +Machine* globalMachine; + +const char* primitiveName(Thread* t, GcClass* c) +{ + if (c == primitiveClass(t, 'V')) { + return "void"; + } else if (c == primitiveClass(t, 'Z')) { + return "boolean"; + } else if (c == primitiveClass(t, 'B')) { + return "byte"; + } else if (c == primitiveClass(t, 'C')) { + return "char"; + } else if (c == primitiveClass(t, 'S')) { + return "short"; + } else if (c == primitiveClass(t, 'I')) { + return "int"; + } else if (c == primitiveClass(t, 'F')) { + return "float"; + } else if (c == primitiveClass(t, 'J')) { + return "long"; + } else if (c == primitiveClass(t, 'D')) { + return "double"; + } else { + abort(t); + } +} + +GcByteArray* getClassName(Thread* t, GcClass* c) +{ + if (c->name() == 0) { + if (c->vmFlags() & PrimitiveFlag) { + PROTECT(t, c); + + GcByteArray* name = makeByteArray(t, primitiveName(t, c)); + + c->setName(t, name); + } else { + abort(t); + } + } + + return c->name(); +} + +GcString* makeClassNameString(Thread* t, GcByteArray* name) +{ + THREAD_RUNTIME_ARRAY(t, char, s, name->length()); + replace('/', + '.', + RUNTIME_ARRAY_BODY(s), + reinterpret_cast(name->body().begin())); + + return makeString(t, "%s", RUNTIME_ARRAY_BODY(s)); +} + +object makeJmethod(Thread* t, GcMethod* vmMethod, int index = -1); + +object makeJconstructor(Thread* t, GcMethod* vmMethod, int index = -1); + +object makeJfield(Thread* t, GcField* vmField, int index = -1); + +#ifdef AVIAN_OPENJDK_SRC +void interceptFileOperations(Thread*, bool); +#endif + +class MyClasspath : public Classpath { + public: + MyClasspath(System* s, + Allocator* allocator, + const char* javaHome, + const char* embedPrefix) + : allocator(allocator), ranNetOnLoad(0), ranManagementOnLoad(0) + { + class StringBuilder { + public: + StringBuilder(System* s, Allocator* allocator) + : s(s), + allocator(allocator), + bufferSize(1024), + buffer(static_cast(allocator->allocate(bufferSize))), + offset(0) + { + } + + void ensure(unsigned capacity) + { + if (capacity > bufferSize) { + unsigned size = max(bufferSize * 2, capacity); + char* b = static_cast(allocator->allocate(size)); + + if (offset) { + memcpy(b, buffer, offset); + } + + allocator->free(buffer, bufferSize); + + buffer = b; + bufferSize = size; + } + } + + void append(const char* append) + { + unsigned length = strlen(append); + ensure(offset + length + 1); + + strncpy(buffer + offset, append, length + 1); + + offset += length; + } + + void append(char c) + { + ensure(2); + + buffer[offset] = c; + buffer[offset + 1] = 0; + + ++offset; + } + + System* s; + Allocator* allocator; + unsigned bufferSize; + char* buffer; + unsigned offset; + } sb(s, allocator); + + unsigned javaHomeOffset = sb.offset; + sb.append(javaHome); + sb.append('\0'); + + unsigned classpathOffset = sb.offset; + sb.append(AVIAN_CLASSPATH); + sb.append(s->pathSeparator()); + sb.append(javaHome); + sb.append("/lib/rt.jar"); + sb.append(s->pathSeparator()); + sb.append(javaHome); + sb.append("/lib/jsse.jar"); + sb.append(s->pathSeparator()); + sb.append(javaHome); + sb.append("/lib/jce.jar"); + sb.append(s->pathSeparator()); + sb.append(javaHome); + sb.append("/lib/ext/sunjce_provider.jar"); + sb.append(s->pathSeparator()); + sb.append(javaHome); + sb.append("/lib/resources.jar"); + sb.append('\0'); + + unsigned libraryPathOffset = sb.offset; + sb.append(javaHome); +#ifdef PLATFORM_WINDOWS +#define LIB_DIR "/bin" +#elif defined __APPLE__ +#define LIB_DIR "/lib" +#elif defined ARCH_x86_64 +#define LIB_DIR "/lib/amd64" +#elif defined ARCH_arm +#define LIB_DIR "/lib/arm" +#else +// todo: handle other architectures +#define LIB_DIR "/lib/i386" +#endif + +#ifdef PLATFORM_WINDOWS + sb.append(LIB_DIR); +#else + sb.append(LIB_DIR ":"); + sb.append(javaHome); + sb.append(LIB_DIR "/xawt"); +#endif + sb.append('\0'); + + unsigned tzMappingsOffset = sb.offset; + sb.append(javaHome); + sb.append("/lib/tzmappings"); + this->tzMappingsLength = sb.offset - tzMappingsOffset; + sb.append('\0'); + + unsigned embedPrefixOffset = sb.offset; + sb.append(embedPrefix); + this->embedPrefixLength = sb.offset - embedPrefixOffset; + + this->javaHome = sb.buffer + javaHomeOffset; + this->classpath = sb.buffer + classpathOffset; + this->libraryPath = sb.buffer + libraryPathOffset; + this->tzMappings = sb.buffer + tzMappingsOffset; + this->embedPrefix = sb.buffer + embedPrefixOffset; + this->buffer = sb.buffer; + this->bufferSize = sb.bufferSize; + } + + virtual GcJclass* makeJclass(Thread* t, GcClass* class_) + { + PROTECT(t, class_); + + GcString* name = makeClassNameString(t, getClassName(t, class_)); + PROTECT(t, name); + + GcJclass* c + = reinterpret_cast(allocate(t, GcJclass::FixedSize, true)); + setObjectClass(t, c, type(t, GcJclass::Type)); + c->setName(t, name); + c->setVmClass(t, class_); +#ifdef HAVE_JclassClassLoader + if (class_->loader() != roots(t)->bootLoader()) { + c->setClassLoader(t, class_->loader()); + } +#endif + + return c; + } + + virtual GcString* makeString(Thread* t, + object oarray, + int32_t offset, + int32_t length) + { + if (objectClass(t, oarray) == type(t, GcByteArray::Type)) { + GcByteArray* array = cast(t, oarray); + PROTECT(t, array); + + GcCharArray* charArray = makeCharArray(t, length); + for (int i = 0; i < length; ++i) { + if (array->body()[offset + i] & 0x80) { + GcMethod* constructor = resolveMethod(t, + type(t, GcString::Type), + "", + "([BIILjava/lang/String;)V"); + PROTECT(t, constructor); + + GcString* utf8 = vm::makeString(t, "UTF8"); + PROTECT(t, utf8); + + object s = makeNew(t, type(t, GcString::Type)); + PROTECT(t, s); + + t->m->processor->invoke( + t, constructor, s, array, offset, length, utf8); + + return cast(t, s); + } + + charArray->body()[i] = array->body()[offset + i]; + } + + oarray = charArray; + offset = 0; + } else { + expect(t, objectClass(t, oarray) == type(t, GcCharArray::Type)); + } + + return vm::makeString(t, oarray, offset, length, 0); + } + + virtual GcThread* makeThread(Thread* t, Thread* parent) + { + const unsigned MaxPriority = 10; + const unsigned NormalPriority = 5; + + GcThreadGroup* group; + if (parent) { + group = parent->javaThread->group(); + } else { + group = reinterpret_cast( + allocate(t, GcThreadGroup::FixedSize, true)); + setObjectClass(t, group, type(t, GcThreadGroup::Type)); + group->maxPriority() = MaxPriority; + } + + PROTECT(t, group); + + GcThread* thread + = reinterpret_cast(allocate(t, GcThread::FixedSize, true)); + setObjectClass(t, thread, type(t, GcThread::Type)); + thread->priority() = NormalPriority; + + thread->setGroup(t, group); + + thread->setContextClassLoader(t, roots(t)->appLoader()); + + PROTECT(t, thread); + + GcJobject* blockerLock = makeJobject(t); + thread->setBlockerLock(t, blockerLock); + +#if HAVE_ThreadName_Ljava_lang_String_ + GcString* name = vm::makeString(t, "Thread-%p", thread); +#else + const unsigned BufferSize = 256; + char buffer[BufferSize]; + unsigned length = vm::snprintf(buffer, BufferSize, "Thread-%p", thread); + GcCharArray* name = makeCharArray(t, length); + for (unsigned i = 0; i < length; ++i) { + name->body()[i] = buffer[i]; + } +#endif + thread->setName(t, name); + + return thread; + } + + virtual object makeJMethod(Thread* t, GcMethod* vmMethod) + { + PROTECT(t, vmMethod); + + return vmMethod->name()->body()[0] == '<' ? makeJconstructor(t, vmMethod) + : makeJmethod(t, vmMethod); + } + + virtual GcMethod* getVMMethod(Thread* t, object jmethod) + { + return cast( + t, + objectClass(t, jmethod) == type(t, GcJmethod::Type) + ? cast(t, + cast(t, jmethod) + ->clazz() + ->vmClass() + ->methodTable()) + ->body()[cast(t, jmethod)->slot()] + : cast(t, + cast(t, jmethod) + ->clazz() + ->vmClass() + ->methodTable()) + ->body()[cast(t, jmethod)->slot()]); + } + + virtual object makeJField(Thread* t, GcField* vmField) + { + return makeJfield(t, vmField); + } + + virtual GcField* getVMField(Thread* t, GcJfield* jfield) + { + return cast( + t, + cast(t, jfield->clazz()->vmClass()->fieldTable()) + ->body()[jfield->slot()]); + } + + virtual void clearInterrupted(Thread* t) + { + vm::clearInterrupted(t); + } + + virtual void runThread(Thread* t) + { + // force monitor creation so we don't get an OutOfMemory error + // later when we try to acquire it: + objectMonitor(t, t->javaThread, true); + + THREAD_RESOURCE0(t, { + vm::acquire(t, t->javaThread); + t->clearFlag(Thread::ActiveFlag); + vm::notifyAll(t, t->javaThread); + vm::release(t, t->javaThread); + + GcThrowable* e = t->exception; + PROTECT(t, e); + + t->exception = 0; + + t->m->processor->invoke(t, + cast(t, roots(t)->threadTerminated()), + t->javaThread->group(), + t->javaThread); + + t->exception = e; + }); + + GcMethod* method = resolveMethod( + t, roots(t)->bootLoader(), "java/lang/Thread", "run", "()V"); + + t->m->processor->invoke(t, method, t->javaThread); + } + + virtual void resolveNative(Thread* t, GcMethod* method) + { + if (strcmp(reinterpret_cast("sun/font/SunFontManager"), + method->class_()->name()->body().begin()) == 0 + and strcmp(reinterpret_cast("initIDs"), + method->name()->body().begin()) == 0 + and strcmp(reinterpret_cast("()V"), + method->spec()->body().begin()) == 0) { + PROTECT(t, method); + + expect(t, loadLibrary(t, libraryPath, "fontmanager", true, true)); + } + + vm::resolveNative(t, method); + } + + virtual void interceptMethods(Thread* t UNUSED) + { +#ifdef AVIAN_OPENJDK_SRC + interceptFileOperations(t, false); +#endif + } + + virtual void preBoot(Thread*) + { + // ignore + } + + virtual bool mayInitClasses() + { + return true; + } + + virtual void boot(Thread* t) + { + globalMachine = t->m; + + resolveSystemClass( + t, roots(t)->bootLoader(), type(t, GcClassLoader::Type)->name()); + + GcMethod* method = resolveMethod(t, + roots(t)->bootLoader(), + "java/lang/ThreadGroup", + "threadTerminated", + "(Ljava/lang/Thread;)V"); + // sequence point, for gc (don't recombine statements) + roots(t)->setThreadTerminated(t, method); + +#ifdef AVIAN_OPENJDK_SRC + interceptFileOperations(t, true); +#else // not AVIAN_OPENJDK_SRC +# ifdef PLATFORM_WINDOWS + expect(t, loadLibrary(t, libraryPath, "msvcr100", true, true)); +# endif + // necessary for using OpenJDK builds from + // https://github.com/ojdkbuild/ojdkbuild: + loadLibrary(t, libraryPath, "ojdkbuild_zlib", true, true, false); + + expect(t, loadLibrary(t, libraryPath, "verify", true, true)); + expect(t, loadLibrary(t, libraryPath, "java", true, true)); +#endif // not AVIAN_OPENJDK_SRC + + { + GcField* assertionLock = resolveField(t, + type(t, GcClassLoader::Type), + "assertionLock", + "Ljava/lang/Object;"); + + setField(t, + roots(t)->bootLoader(), + assertionLock->offset(), + roots(t)->bootLoader()); + } + + { + GcClass* class_ = resolveClass(t, + roots(t)->bootLoader(), + "java/util/Properties", + true, + GcNoClassDefFoundError::Type); + + PROTECT(t, class_); + + object instance = makeNew(t, class_); + + PROTECT(t, instance); + + GcMethod* constructor = resolveMethod(t, class_, "", "()V"); + + t->m->processor->invoke(t, constructor, instance); + + t->m->processor->invoke(t, + roots(t)->bootLoader(), + "java/lang/System", + "setProperties", + "(Ljava/util/Properties;)V", + 0, + instance); + } + + { + GcMethod* constructor = resolveMethod(t, + type(t, GcClassLoader::Type), + "", + "(Ljava/lang/ClassLoader;)V"); + + PROTECT(t, constructor); + + t->m->processor->invoke(t, constructor, roots(t)->bootLoader(), 0); + + t->m->processor->invoke( + t, constructor, roots(t)->appLoader(), roots(t)->bootLoader()); + } + + { + GcField* scl = resolveField( + t, type(t, GcClassLoader::Type), "scl", "Ljava/lang/ClassLoader;"); + + PROTECT(t, scl); + + GcField* sclSet + = resolveField(t, type(t, GcClassLoader::Type), "sclSet", "Z"); + + setField(t, + type(t, GcClassLoader::Type)->staticTable(), + scl->offset(), + roots(t)->appLoader()); + + fieldAtOffset(type(t, GcClassLoader::Type)->staticTable(), + sclSet->offset()) = true; + } + + t->m->processor->invoke(t, + roots(t)->bootLoader(), + "java/lang/System", + "initializeSystemClass", + "()V", + 0); + + t->m->processor->invoke(t, + roots(t)->bootLoader(), + "sun/misc/Launcher", + "getLauncher", + "()Lsun/misc/Launcher;", + 0); + + t->javaThread->setContextClassLoader(t, roots(t)->appLoader()); + } + + virtual const char* bootClasspath() + { + return classpath; + } + + virtual object makeDirectByteBuffer(Thread* t, void* p, jlong capacity) + { + GcClass* c + = resolveClass(t, roots(t)->bootLoader(), "java/nio/DirectByteBuffer"); + PROTECT(t, c); + + object instance = makeNew(t, c); + PROTECT(t, instance); + + GcMethod* constructor = resolveMethod(t, c, "", "(JI)V"); + + t->m->processor->invoke(t, + constructor, + instance, + reinterpret_cast(p), + static_cast(capacity)); + + return instance; + } + + virtual void* getDirectBufferAddress(Thread* t, object b) + { + PROTECT(t, b); + + GcField* field = resolveField(t, objectClass(t, b), "address", "J"); + + return reinterpret_cast(fieldAtOffset(b, field->offset())); + } + + virtual int64_t getDirectBufferCapacity(Thread* t, object b) + { + PROTECT(t, b); + + GcField* field = resolveField(t, objectClass(t, b), "capacity", "I"); + + return fieldAtOffset(b, field->offset()); + } + + virtual bool canTailCall(Thread* t UNUSED, + GcMethod*, + GcByteArray* calleeClassName, + GcByteArray* calleeMethodName, + GcByteArray*) + { + // we can't tail call System.loadLibrary or Runtime.loadLibrary + // due to their use of System.getCallerClass, which gets confused + // if we elide stack frames. + + return (strcmp("loadLibrary", + reinterpret_cast(calleeMethodName->body().begin())) + or (strcmp("java/lang/System", + reinterpret_cast(calleeClassName->body().begin())) + and strcmp("java/lang/Runtime", + reinterpret_cast( + calleeClassName->body().begin())))) + + // and we can't tail call Reflection.getCallerClass because the + // number of stack frames will be wrong + and (strcmp( + "getCallerClass", + reinterpret_cast(calleeMethodName->body().begin())) + or strcmp("sun/reflect/Reflection", + reinterpret_cast( + calleeClassName->body().begin()))); + } + + virtual GcClassLoader* libraryClassLoader(Thread* t, GcMethod* caller) + { +#ifdef AVIAN_OPENJDK_SRC + return (caller->class_() == type(t, GcClassLoader::Type) + and t->libraryLoadStack) + ? t->libraryLoadStack->classLoader +#else + return strcmp("java/lang/ClassLoader$NativeLibrary", + reinterpret_cast( + caller->class_()->name()->body().begin())) == 0 + ? cast( + t, + cast(t, + t->m->processor->invoke( + t, + resolveMethod(t, + caller->class_(), + "getFromClass", + "()Ljava/lang/Class;"), + 0))->vmClass())->loader() +#endif + : caller->class_()->loader(); + } + + virtual void shutDown(Thread* t) + { + GcClass* c + = resolveClass(t, roots(t)->bootLoader(), "java/lang/Shutdown", false); + + if (c) { + GcMethod* m = findMethodOrNull(t, c, "shutdown", "()V"); + + if (m) { + t->m->processor->invoke(t, m, 0); + } + } + } + + virtual void dispose() + { + allocator->free(buffer, bufferSize); + allocator->free(this, sizeof(*this)); + } + + Allocator* allocator; + const char* javaHome; + const char* classpath; + const char* libraryPath; + const char* tzMappings; + const char* embedPrefix; + char* buffer; + unsigned bufferSize; + unsigned tzMappingsLength; + unsigned embedPrefixLength; + unsigned filePathField; + unsigned fileDescriptorFdField; + unsigned fileInputStreamFdField; + unsigned zipFileJzfileField; + unsigned zipEntryNameField; + unsigned zipEntryTimeField; + unsigned zipEntryCrcField; + unsigned zipEntrySizeField; + unsigned zipEntryCsizeField; + unsigned zipEntryMethodField; + bool ranNetOnLoad; + bool ranManagementOnLoad; + JmmInterface jmmInterface; +}; + +struct JVM_ExceptionTableEntryType { + jint start_pc; + jint end_pc; + jint handler_pc; + jint catchType; +}; + +struct jvm_version_info { + unsigned jvm_version; + unsigned update_version : 8; + unsigned special_update_version : 8; + unsigned reserved1 : 16; + unsigned reserved2; + unsigned is_attach_supported : 1; + unsigned is_kernel_jvm : 1; + unsigned : 30; + unsigned : 32; + unsigned : 32; +}; + +bool pathEqual(const char* a, const char* b, unsigned length) +{ +#ifdef PLATFORM_WINDOWS + return strncasecmp(a, b, length) == 0; +#else + return strncmp(a, b, length) == 0; +#endif +} + +class EmbeddedFile { + public: + EmbeddedFile(MyClasspath* cp, const char* path, unsigned pathLength) + { + if (pathEqual(cp->embedPrefix, path, cp->embedPrefixLength)) { + const char* p = path + cp->embedPrefixLength; + while (*p == '/') + ++p; + + this->jar = p; + + if (*p == 0) { + this->jarLength = 0; + this->path = 0; + this->pathLength = 0; + return; + } + + while (*p and *p != '/') + ++p; + + this->jarLength = p - this->jar; + + while (*p == '/') + ++p; + + this->path = p; + this->pathLength = pathLength - (p - path); + } else { + this->jar = 0; + this->jarLength = 0; + this->path = 0; + this->pathLength = 0; + } + } + + const char* jar; + const char* path; + unsigned jarLength; + unsigned pathLength; +}; + +#ifdef AVIAN_OPENJDK_SRC +int64_t JNICALL + getFileAttributes(Thread* t, GcMethod* method, uintptr_t* arguments) +{ + const unsigned Exists = 1; + const unsigned Regular = 2; + const unsigned Directory = 4; + + MyClasspath* cp = static_cast(t->m->classpath); + + object file = reinterpret_cast(arguments[1]); + GcString* path + = cast(t, fieldAtOffset(file, cp->filePathField)); + + THREAD_RUNTIME_ARRAY(t, char, p, path->length(t) + 1); + stringChars(t, path, RUNTIME_ARRAY_BODY(p)); + replace('\\', '/', RUNTIME_ARRAY_BODY(p)); + + EmbeddedFile ef(cp, RUNTIME_ARRAY_BODY(p), path->length(t)); + if (ef.jar) { + if (ef.jarLength == 0) { + return Exists | Directory; + } + + Finder* finder = getFinder(t, ef.jar, ef.jarLength); + if (finder) { + if (ef.pathLength == 0) { + return Exists | Directory; + } + + size_t length; + System::FileType type = finder->stat(ef.path, &length, true); + switch (type) { + case System::TypeUnknown: + return Exists; + case System::TypeDoesNotExist: + return 0; + case System::TypeFile: + return Exists | Regular; + case System::TypeDirectory: + return Exists | Directory; + default: + abort(t); + } + } else { + return 0; + } + } else { + return cast(t, + t->m->processor->invoke( + t, + cast( + t, + cast( + t, getMethodRuntimeData(t, method)->native()) + ->original()), + reinterpret_cast(arguments[0]), + file))->value(); + } +} + +int64_t JNICALL + checkFileAccess(Thread* t, GcMethod* method, uintptr_t* arguments) +{ + const unsigned Read = 4; + + MyClasspath* cp = static_cast(t->m->classpath); + + object file = reinterpret_cast(arguments[1]); + unsigned mask = arguments[2]; + GcString* path + = cast(t, fieldAtOffset(file, cp->filePathField)); + + THREAD_RUNTIME_ARRAY(t, char, p, path->length(t) + 1); + stringChars(t, path, RUNTIME_ARRAY_BODY(p)); + replace('\\', '/', RUNTIME_ARRAY_BODY(p)); + + EmbeddedFile ef(cp, RUNTIME_ARRAY_BODY(p), path->length(t)); + if (ef.jar) { + if (ef.jarLength == 0) { + return mask == Read; + } + + Finder* finder = getFinder(t, ef.jar, ef.jarLength); + if (finder) { + if (ef.pathLength == 0) { + return mask == Read; + } + + size_t length; + System::FileType type = finder->stat(ef.path, &length, true); + switch (type) { + case System::TypeDoesNotExist: + return false; + case System::TypeUnknown: + case System::TypeFile: + case System::TypeDirectory: + return mask == Read; + default: + abort(t); + } + } else { + return 0; + } + } else { + return cast(t, + t->m->processor->invoke( + t, + cast( + t, + cast( + t, getMethodRuntimeData(t, method)->native()) + ->original()), + reinterpret_cast(arguments[0]), + file, + mask))->value() != 0; + } +} + +int64_t JNICALL getFileLength(Thread* t, GcMethod* method, uintptr_t* arguments) +{ + MyClasspath* cp = static_cast(t->m->classpath); + + object file = reinterpret_cast(arguments[1]); + GcString* path + = cast(t, fieldAtOffset(file, cp->filePathField)); + + THREAD_RUNTIME_ARRAY(t, char, p, path->length(t) + 1); + stringChars(t, path, RUNTIME_ARRAY_BODY(p)); + replace('\\', '/', RUNTIME_ARRAY_BODY(p)); + + EmbeddedFile ef(cp, RUNTIME_ARRAY_BODY(p), path->length(t)); + if (ef.jar) { + if (ef.jarLength == 0) { + return 0; + } + + Finder* finder = getFinder(t, ef.jar, ef.jarLength); + if (finder) { + if (ef.pathLength == 0) { + return 0; + } + + size_t fileLength; + finder->stat(ef.path, &fileLength); + return fileLength; + } + + return 0; + } else { + return cast(t, + t->m->processor->invoke( + t, + cast(t, + cast( + t, + getMethodRuntimeData(t, method) + ->native())->original()), + reinterpret_cast(arguments[0]), + file))->value(); + } +} + +void JNICALL openFile(Thread* t, GcMethod* method, uintptr_t* arguments) +{ + object this_ = reinterpret_cast(arguments[0]); + GcString* path = cast(t, reinterpret_cast(arguments[1])); + + MyClasspath* cp = static_cast(t->m->classpath); + + THREAD_RUNTIME_ARRAY(t, char, p, path->length(t) + 1); + stringChars(t, path, RUNTIME_ARRAY_BODY(p)); + replace('\\', '/', RUNTIME_ARRAY_BODY(p)); + + EmbeddedFile ef(cp, RUNTIME_ARRAY_BODY(p), path->length(t)); + if (ef.jar) { + if (ef.jarLength == 0 or ef.pathLength == 0) { + throwNew(t, GcFileNotFoundException::Type); + } + + Finder* finder = getFinder(t, ef.jar, ef.jarLength); + if (finder == 0) { + throwNew(t, GcFileNotFoundException::Type); + } + + System::Region* r = finder->find(ef.path); + if (r == 0) { + throwNew(t, GcFileNotFoundException::Type); + } + + PROTECT(t, this_); + + ACQUIRE(t, t->m->referenceLock); + + int index = -1; + unsigned oldLength + = roots(t)->virtualFiles() ? roots(t)->virtualFiles()->length() : 0; + + for (unsigned i = 0; i < oldLength; ++i) { + if (roots(t)->virtualFiles()->body()[i] == 0) { + index = i; + break; + } + } + + if (index == -1) { + GcArray* newArray = growArray(t, roots(t)->virtualFiles()); + roots(t)->setVirtualFiles(t, newArray); + index = oldLength; + } + + object region = makeRegion(t, r, 0); + roots(t)->virtualFiles()->setBodyElement(t, index, region); + + fieldAtOffset( + fieldAtOffset(this_, cp->fileInputStreamFdField), + cp->fileDescriptorFdField) = index + VirtualFileBase; + } else { + t->m->processor->invoke( + t, + cast( + t, + cast( + t, getMethodRuntimeData(t, method)->native())->original()), + this_, + path); + } +} + +int64_t JNICALL + readByteFromFile(Thread* t, GcMethod* method, uintptr_t* arguments) +{ + object this_ = reinterpret_cast(arguments[0]); + + MyClasspath* cp = static_cast(t->m->classpath); + + int fd = fieldAtOffset( + fieldAtOffset(this_, cp->fileInputStreamFdField), + cp->fileDescriptorFdField); + + if (fd >= VirtualFileBase) { + ACQUIRE(t, t->m->referenceLock); + + GcRegion* region = cast( + t, roots(t)->virtualFiles()->body()[fd - VirtualFileBase]); + + if (region) { + System::Region* r = static_cast(region->region()); + + if (r->length() > region->position()) { + return r->start()[region->position()++]; + } else { + return -1; + } + } else { + throwNew(t, GcIoException::Type); + } + } else { + return cast(t, + t->m->processor->invoke( + t, + cast( + t, + cast( + t, getMethodRuntimeData(t, method)->native()) + ->original()), + this_))->value(); + } +} + +int64_t JNICALL + readBytesFromFile(Thread* t, GcMethod* method, uintptr_t* arguments) +{ + object this_ = reinterpret_cast(arguments[0]); + GcByteArray* dst + = cast(t, reinterpret_cast(arguments[1])); + int32_t offset = arguments[2]; + int32_t length = arguments[3]; + + MyClasspath* cp = static_cast(t->m->classpath); + + int fd = fieldAtOffset( + fieldAtOffset(this_, cp->fileInputStreamFdField), + cp->fileDescriptorFdField); + + if (fd >= VirtualFileBase) { + PROTECT(t, dst); + + ACQUIRE(t, t->m->referenceLock); + + GcRegion* region = cast( + t, roots(t)->virtualFiles()->body()[fd - VirtualFileBase]); + + if (region) { + System::Region* r = static_cast(region->region()); + + int available = r->length() - region->position(); + if (available == 0) { + return -1; + } + + if (length > available) { + length = available; + } + + memcpy(&dst->body()[offset], r->start() + region->position(), length); + + region->position() += length; + + return length; + } else { + throwNew(t, GcIoException::Type); + } + } else { + return cast(t, + t->m->processor->invoke( + t, + cast( + t, + cast( + t, getMethodRuntimeData(t, method)->native()) + ->original()), + this_, + dst, + offset, + length))->value(); + } +} + +int64_t JNICALL + skipBytesInFile(Thread* t, GcMethod* method, uintptr_t* arguments) +{ + object this_ = reinterpret_cast(arguments[0]); + int64_t count; + memcpy(&count, arguments + 1, 8); + + MyClasspath* cp = static_cast(t->m->classpath); + + int fd = fieldAtOffset( + fieldAtOffset(this_, cp->fileInputStreamFdField), + cp->fileDescriptorFdField); + + if (fd >= VirtualFileBase) { + ACQUIRE(t, t->m->referenceLock); + + GcRegion* region = cast( + t, roots(t)->virtualFiles()->body()[fd - VirtualFileBase]); + + if (region) { + System::Region* r = static_cast(region->region()); + + int available = r->length() - region->position(); + if (count > available) { + count = available; + } + + region->position() += count; + + return count; + } else { + throwNew(t, GcIoException::Type); + } + } else { + return cast(t, + t->m->processor->invoke( + t, + cast(t, + cast( + t, + getMethodRuntimeData(t, method) + ->native())->original()), + this_, + count))->value(); + } +} + +int64_t JNICALL + availableBytesInFile(Thread* t, GcMethod* method, uintptr_t* arguments) +{ + object this_ = reinterpret_cast(arguments[0]); + + MyClasspath* cp = static_cast(t->m->classpath); + + int fd = fieldAtOffset( + fieldAtOffset(this_, cp->fileInputStreamFdField), + cp->fileDescriptorFdField); + + if (fd >= VirtualFileBase) { + ACQUIRE(t, t->m->referenceLock); + + GcRegion* region = cast( + t, roots(t)->virtualFiles()->body()[fd - VirtualFileBase]); + + if (region) { + return static_cast(region->region())->length() + - region->position(); + } else { + throwNew(t, GcIoException::Type); + } + } else { + object r = t->m->processor->invoke( + t, + cast( + t, + cast( + t, getMethodRuntimeData(t, method)->native())->original()), + this_); + + return r ? cast(t, r)->value() : 0; + } +} + +void JNICALL closeFile(Thread* t, GcMethod* method, uintptr_t* arguments) +{ + object this_ = reinterpret_cast(arguments[0]); + + MyClasspath* cp = static_cast(t->m->classpath); + + int fd = fieldAtOffset( + fieldAtOffset(this_, cp->fileInputStreamFdField), + cp->fileDescriptorFdField); + + if (fd >= VirtualFileBase) { + ACQUIRE(t, t->m->referenceLock); + + int index = fd - VirtualFileBase; + GcRegion* region + = cast(t, roots(t)->virtualFiles()->body()[index]); + + if (region) { + static_cast(region->region())->dispose(); + } + + roots(t)->virtualFiles()->setBodyElement(t, index, 0); + } else { + t->m->processor->invoke( + t, + cast( + t, + cast( + t, getMethodRuntimeData(t, method)->native())->original()), + this_); + } +} + +class ZipFile { + public: + class Entry { + public: + Entry(unsigned hash, const uint8_t* start, Entry* next) + : hash(hash), start(start), next(next), entry(0) + { + } + + Entry(int64_t entry) : hash(0), start(0), next(0), entry(entry) + { + } + + Entry() : hash(0), start(0), next(0), entry(0) + { + } + + unsigned hash; + const uint8_t* start; + Entry* next; + int64_t entry; + }; + + ZipFile(Thread* t, System::Region* region, unsigned entryCount) + : region(region), + entryCount(entryCount), + indexSize(nextPowerOfTwo(entryCount)), + index(reinterpret_cast( + t->m->heap->allocate(sizeof(ZipFile::Entry*) * indexSize))), + file(0) + { + memset(index, 0, sizeof(ZipFile::Entry*) * indexSize); + } + + ZipFile(int64_t file) + : region(0), entryCount(0), indexSize(0), index(0), file(file) + { + } + + System::Region* region; + unsigned entryCount; + unsigned indexSize; + Entry** index; + int64_t file; + Entry entries[0]; +}; + +int64_t JNICALL openZipFile(Thread* t, GcMethod* method, uintptr_t* arguments) +{ + GcString* path = cast(t, reinterpret_cast(arguments[0])); + int mode = arguments[1]; + int64_t lastModified; + memcpy(&lastModified, arguments + 2, 8); + + MyClasspath* cp = static_cast(t->m->classpath); + + THREAD_RUNTIME_ARRAY(t, char, p, path->length(t) + 1); + stringChars(t, path, RUNTIME_ARRAY_BODY(p)); + replace('\\', '/', RUNTIME_ARRAY_BODY(p)); + + EmbeddedFile ef(cp, RUNTIME_ARRAY_BODY(p), path->length(t)); + if (ef.jar) { + if (ef.jarLength == 0 or ef.pathLength == 0) { + throwNew(t, GcFileNotFoundException::Type); + } + + Finder* finder = getFinder(t, ef.jar, ef.jarLength); + if (finder == 0) { + throwNew(t, GcFileNotFoundException::Type); + } + + System::Region* r = finder->find(ef.path); + if (r == 0) { + throwNew(t, GcFileNotFoundException::Type); + } + + const uint8_t* start = r->start(); + const uint8_t* end = start + r->length(); + unsigned entryCount = 0; + for (const uint8_t* p = end - CentralDirectorySearchStart; p > start;) { + if (get4(p) == CentralDirectorySignature) { + p = start + centralDirectoryOffset(p); + + while (p < end) { + if (get4(p) == EntrySignature) { + ++entryCount; + + p = endOfEntry(p); + } else { + goto make; + } + } + } else { + --p; + } + } + + make: + ZipFile* file = new (t->m->heap->allocate( + sizeof(ZipFile) + (sizeof(ZipFile::Entry) * entryCount))) + ZipFile(t, r, entryCount); + + { + unsigned position = 0; + for (const uint8_t* p = end - CentralDirectorySearchStart; p > start;) { + if (get4(p) == CentralDirectorySignature) { + p = start + centralDirectoryOffset(p); + + while (p < end) { + if (get4(p) == EntrySignature) { + unsigned h + = hash(Slice(fileName(p), fileNameLength(p))); + unsigned i = h & (file->indexSize - 1); + + file->index[i] = new (file->entries + (position++)) + ZipFile::Entry(h, p, file->index[i]); + + p = endOfEntry(p); + } else { + goto exit; + } + } + } else { + --p; + } + } + } + + exit: + return reinterpret_cast(file); + } else { + return reinterpret_cast( + new (t->m->heap->allocate(sizeof(ZipFile))) ZipFile( + cast(t, + t->m->processor->invoke( + t, + cast(t, + cast( + t, + getMethodRuntimeData(t, method) + ->native())->original()), + 0, + path, + mode, + lastModified))->value())); + } +} + +int64_t JNICALL + getZipFileEntryCount(Thread* t, GcMethod* method, uintptr_t* arguments) +{ + int64_t peer; + memcpy(&peer, arguments, 8); + + ZipFile* file = reinterpret_cast(peer); + if (file->region) { + return file->entryCount; + } else { + return cast(t, + t->m->processor->invoke( + t, + cast( + t, + cast( + t, getMethodRuntimeData(t, method)->native()) + ->original()), + 0, + file->file))->value(); + } +} + +ZipFile::Entry* find(ZipFile* file, const char* path, unsigned pathLength) +{ + if (pathLength > 0 && path[0] == '/') { + ++path; + --pathLength; + } + unsigned i = hash(path) & (file->indexSize - 1); + for (ZipFile::Entry* e = file->index[i]; e; e = e->next) { + const uint8_t* p = e->start; + if (equal(path, pathLength, fileName(p), fileNameLength(p))) { + return e; + } + } + return 0; +} + +int64_t JNICALL + getZipFileEntry(Thread* t, GcMethod* method, uintptr_t* arguments) +{ + int64_t peer; + memcpy(&peer, arguments, 8); + GcByteArray* path + = cast(t, reinterpret_cast(arguments[2])); + bool addSlash = arguments[3]; + + ZipFile* file = reinterpret_cast(peer); + if (file->region) { + THREAD_RUNTIME_ARRAY(t, char, p, path->length() + 2); + memcpy(RUNTIME_ARRAY_BODY(p), path->body().begin(), path->length()); + RUNTIME_ARRAY_BODY(p)[path->length()] = 0; + replace('\\', '/', RUNTIME_ARRAY_BODY(p)); + + ZipFile::Entry *e = find(file, RUNTIME_ARRAY_BODY(p), path->length()); + + if (e == 0 and addSlash and RUNTIME_ARRAY_BODY(p)[path->length()] != '/') { + RUNTIME_ARRAY_BODY(p)[path->length()] = '/'; + RUNTIME_ARRAY_BODY(p)[path->length() + 1] = 0; + + e = find(file, RUNTIME_ARRAY_BODY(p), path->length()); + } + + return reinterpret_cast(e); + } else { + int64_t entry + = cast(t, + t->m->processor->invoke( + t, + cast( + t, + cast( + t, getMethodRuntimeData(t, method)->native()) + ->original()), + 0, + file->file, + path, + addSlash))->value(); + + return entry ? reinterpret_cast(new (t->m->heap->allocate( + sizeof(ZipFile::Entry))) ZipFile::Entry(entry)) + : 0; + } +} + +int64_t JNICALL + getZipFileEntryBytes(Thread* t, GcMethod* method, uintptr_t* arguments) +{ + int64_t peer; + memcpy(&peer, arguments, 8); + int type = arguments[2]; + + ZipFile::Entry* entry = reinterpret_cast(peer); + if (entry->start) { + switch (type) { + case 0: { // name + unsigned nameLength = fileNameLength(entry->start); + GcByteArray* array = makeByteArray(t, nameLength); + memcpy(array->body().begin(), fileName(entry->start), nameLength); + return reinterpret_cast(array); + } break; + + case 1: { // extra + return 0; + } break; + + case 2: { // comment + return 0; + } break; + + default: + abort(t); + } + return compressedSize(entry->start); + } else { + return reinterpret_cast(t->m->processor->invoke( + t, + cast( + t, + cast( + t, getMethodRuntimeData(t, method)->native())->original()), + 0, + entry->entry, + type)); + } +} + +int64_t JNICALL + getNextZipFileEntry(Thread* t, GcMethod* method, uintptr_t* arguments) +{ + int64_t peer; + memcpy(&peer, arguments, 8); + int index = arguments[2]; + + ZipFile* file = reinterpret_cast(peer); + if (file->region) { + return reinterpret_cast(file->entries + index); + } else { + int64_t entry + = cast(t, + t->m->processor->invoke( + t, + cast( + t, + cast( + t, getMethodRuntimeData(t, method)->native()) + ->original()), + 0, + file->file, + index))->value(); + + return entry ? reinterpret_cast(new (t->m->heap->allocate( + sizeof(ZipFile::Entry))) ZipFile::Entry(entry)) + : 0; + } +} + +int64_t JNICALL + getZipFileEntryMethod(Thread* t, GcMethod* method, uintptr_t* arguments) +{ + int64_t peer; + memcpy(&peer, arguments, 8); + + ZipFile::Entry* entry = reinterpret_cast(peer); + if (entry->start) { + return compressionMethod(entry->start); + } else { + return cast(t, + t->m->processor->invoke( + t, + cast( + t, + cast( + t, getMethodRuntimeData(t, method)->native()) + ->original()), + 0, + entry->entry))->value(); + } +} + +int64_t JNICALL getZipFileEntryCompressedSize(Thread* t, + GcMethod* method, + uintptr_t* arguments) +{ + int64_t peer; + memcpy(&peer, arguments, 8); + + ZipFile::Entry* entry = reinterpret_cast(peer); + if (entry->start) { + return compressedSize(entry->start); + } else { + return cast(t, + t->m->processor->invoke( + t, + cast(t, + cast( + t, + getMethodRuntimeData(t, method) + ->native())->original()), + 0, + entry->entry))->value(); + } +} + +int64_t JNICALL getZipFileEntryUncompressedSize(Thread* t, + GcMethod* method, + uintptr_t* arguments) +{ + int64_t peer; + memcpy(&peer, arguments, 8); + + ZipFile::Entry* entry = reinterpret_cast(peer); + if (entry->start) { + return uncompressedSize(entry->start); + } else { + return cast(t, + t->m->processor->invoke( + t, + cast(t, + cast( + t, + getMethodRuntimeData(t, method) + ->native())->original()), + 0, + entry->entry))->value(); + } +} + +void JNICALL freeZipFileEntry(Thread* t, GcMethod* method, uintptr_t* arguments) +{ + int64_t filePeer; + memcpy(&filePeer, arguments, 8); + int64_t entryPeer; + memcpy(&entryPeer, arguments + 2, 8); + + ZipFile* file = reinterpret_cast(filePeer); + ZipFile::Entry* entry = reinterpret_cast(entryPeer); + if (file->region == 0) { + t->m->processor->invoke( + t, + cast( + t, + cast( + t, getMethodRuntimeData(t, method)->native())->original()), + 0, + file->file, + entry->entry); + + t->m->heap->free(entry, sizeof(ZipFile::Entry)); + } +} + +int64_t JNICALL + readZipFileEntry(Thread* t, GcMethod* method, uintptr_t* arguments) +{ + int64_t filePeer; + memcpy(&filePeer, arguments, 8); + int64_t entryPeer; + memcpy(&entryPeer, arguments + 2, 8); + int64_t position; + memcpy(&position, arguments + 4, 8); + GcByteArray* buffer + = cast(t, reinterpret_cast(arguments[6])); + int offset = arguments[7]; + int length = arguments[8]; + + ZipFile* file = reinterpret_cast(filePeer); + ZipFile::Entry* entry = reinterpret_cast(entryPeer); + if (file->region) { + unsigned size = uncompressedSize(entry->start); + if (position >= size) { + return -1; + } + + if (position + length > size) { + length = size - position; + } + + memcpy(&buffer->body()[offset], + fileData(file->region->start() + localHeaderOffset(entry->start)) + + position, + length); + + return length; + } else { + return cast(t, + t->m->processor->invoke( + t, + cast( + t, + cast( + t, getMethodRuntimeData(t, method)->native()) + ->original()), + 0, + file->file, + entry->entry, + position, + buffer, + offset, + length))->value(); + } +} + +int64_t JNICALL getZipMessage(Thread* t, GcMethod* method, uintptr_t* arguments) +{ + int64_t peer; + memcpy(&peer, arguments, 8); + + ZipFile* file = reinterpret_cast(peer); + if (file->region) { + return 0; + } else { + return reinterpret_cast(t->m->processor->invoke( + t, + cast( + t, + cast( + t, getMethodRuntimeData(t, method)->native())->original()), + 0, + file->file)); + } +} + +int64_t JNICALL getJarFileMetaInfEntryNames(Thread* t, + GcMethod* method, + uintptr_t* arguments) +{ + object this_ = reinterpret_cast(arguments[0]); + + MyClasspath* cp = static_cast(t->m->classpath); + + int64_t peer = fieldAtOffset(this_, cp->zipFileJzfileField); + ZipFile* file = reinterpret_cast(peer); + if (file->region) { + return 0; + } else { + PROTECT(t, method); + + // OpenJDK's Java_java_util_jar_JarFile_getMetaInfEntryNames + // implementation expects to find a pointer to an instance of its + // jzfile structure in the ZipFile.jzfile field of the object we + // pass in. However, we can't pass this_ in, because its + // ZipFile.jzfile field points to a ZipFile instance, not a + // jzfile. So we pass in a temporary object instead which has the + // desired pointer at the same offset. We assume here that + // ZipFile.jzfile is the first field in that class and that + // Java_java_util_jar_JarFile_getMetaInfEntryNames will not look + // for any other fields in the object. + object pseudoThis = makeLong(t, file->file); + + return reinterpret_cast(t->m->processor->invoke( + t, + cast( + t, + cast( + t, getMethodRuntimeData(t, method)->native())->original()), + pseudoThis)); + } +} + +void JNICALL closeZipFile(Thread* t, GcMethod* method, uintptr_t* arguments) +{ + int64_t peer; + memcpy(&peer, arguments, 8); + + ZipFile* file = reinterpret_cast(peer); + if (file->region) { + file->region->dispose(); + t->m->heap->free( + file, sizeof(ZipFile) + (sizeof(ZipFile::Entry) * file->entryCount)); + } else { + t->m->processor->invoke( + t, + cast( + t, + cast( + t, getMethodRuntimeData(t, method)->native())->original()), + 0, + file->file); + + t->m->heap->free(file, sizeof(ZipFile)); + } +} + +int64_t JNICALL getBootstrapResource(Thread* t, object, uintptr_t* arguments) +{ + object name = reinterpret_cast(arguments[0]); + PROTECT(t, name); + + GcMethod* m = findMethodOrNull(t, + type(t, GcSystemClassLoader::Type), + "findResource", + "(Ljava/lang/String;)Ljava/net/URL;"); + + if (m) { + return reinterpret_cast( + t->m->processor->invoke(t, m, roots(t)->bootLoader(), name)); + } else { + return 0; + } +} + +int64_t JNICALL getBootstrapResources(Thread* t, object, uintptr_t* arguments) +{ + object name = reinterpret_cast(arguments[0]); + PROTECT(t, name); + + GcMethod* m = findMethodOrNull(t, + type(t, GcSystemClassLoader::Type), + "findResources", + "(Ljava/lang/String;)Ljava/util/Enumeration;"); + + if (m) { + return reinterpret_cast( + t->m->processor->invoke(t, m, roots(t)->bootLoader(), name)); + } else { + return 0; + } +} + +extern "C" AVIAN_EXPORT jint JNICALL net_JNI_OnLoad(JavaVM*, void*); + +extern "C" AVIAN_EXPORT jint JNICALL management_JNI_OnLoad(JavaVM*, void*); + +void JNICALL loadLibrary(Thread* t, object, uintptr_t* arguments) +{ + Thread::LibraryLoadStack stack( + t, + cast(t, reinterpret_cast(arguments[0])) + ->vmClass() + ->loader()); + + GcString* name = cast(t, reinterpret_cast(arguments[1])); + THREAD_RUNTIME_ARRAY(t, char, n, name->length(t) + 1); + stringChars(t, name, RUNTIME_ARRAY_BODY(n)); + + bool absolute = arguments[2]; + + if (not absolute) { + if (strcmp(RUNTIME_ARRAY_BODY(n), "net") == 0) { + bool ran; + + { + ACQUIRE(t, t->m->classLock); + + local::MyClasspath* c + = static_cast(t->m->classpath); + + ran = c->ranNetOnLoad; + c->ranNetOnLoad = true; + } + + if (not ran) { + net_JNI_OnLoad(t->m, 0); + } + + return; + } else if (strcmp(RUNTIME_ARRAY_BODY(n), "management") == 0) { + bool ran; + + { + ACQUIRE(t, t->m->classLock); + + local::MyClasspath* c + = static_cast(t->m->classpath); + + ran = c->ranManagementOnLoad; + c->ranManagementOnLoad = true; + } + + if (not ran) { + management_JNI_OnLoad(t->m, 0); + } + + return; + } else if (strcmp(RUNTIME_ARRAY_BODY(n), "zip") == 0 + or strcmp(RUNTIME_ARRAY_BODY(n), "nio") == 0) { + return; + } + } + + loadLibrary(t, + static_cast(t->m->classpath)->libraryPath, + RUNTIME_ARRAY_BODY(n), + not absolute, + true); +} + +void interceptFileOperations(Thread* t, bool updateRuntimeData) +{ + MyClasspath* cp = static_cast(t->m->classpath); + + { + GcClass* fileClass + = resolveClass(t, roots(t)->bootLoader(), "java/io/File", false); + + if (fileClass) { + GcField* filePathField + = findFieldInClass2(t, fileClass, "path", "Ljava/lang/String;"); + + if (filePathField) { + cp->filePathField = filePathField->offset(); + } + } + } + + { + GcClass* fileDescriptorClass = resolveClass( + t, roots(t)->bootLoader(), "java/io/FileDescriptor", false); + + if (fileDescriptorClass) { + GcField* fileDescriptorFdField + = findFieldInClass2(t, fileDescriptorClass, "fd", "I"); + + if (fileDescriptorFdField) { + cp->fileDescriptorFdField = fileDescriptorFdField->offset(); + } + } + } + + { + GcClass* fileInputStreamClass = resolveClass( + t, roots(t)->bootLoader(), "java/io/FileInputStream", false); + + if (fileInputStreamClass) { + PROTECT(t, fileInputStreamClass); + + GcField* fileInputStreamFdField = findFieldInClass2( + t, fileInputStreamClass, "fd", "Ljava/io/FileDescriptor;"); + + if (fileInputStreamFdField) { + cp->fileInputStreamFdField = fileInputStreamFdField->offset(); + + if (findMethodOrNull(t, fileInputStreamClass, "open0", "(Ljava/lang/String;)V") != 0) { + intercept(t, + fileInputStreamClass, + "open0", + "(Ljava/lang/String;)V", + voidPointer(openFile), + updateRuntimeData); + } else { + intercept(t, + fileInputStreamClass, + "open", + "(Ljava/lang/String;)V", + voidPointer(openFile), + updateRuntimeData); + } + + if (findMethodOrNull(t, fileInputStreamClass, "read0", "()I") != 0) { + intercept(t, + fileInputStreamClass, + "read0", + "()I", + voidPointer(readByteFromFile), + updateRuntimeData); + } else { + intercept(t, + fileInputStreamClass, + "read", + "()I", + voidPointer(readByteFromFile), + updateRuntimeData); + } + + intercept(t, + fileInputStreamClass, + "readBytes", + "([BII)I", + voidPointer(readBytesFromFile), + updateRuntimeData); + + intercept(t, + fileInputStreamClass, + "skip", + "(J)J", + voidPointer(skipBytesInFile), + updateRuntimeData); + + intercept(t, + fileInputStreamClass, + "available", + "()I", + voidPointer(availableBytesInFile), + updateRuntimeData); + + intercept(t, + fileInputStreamClass, + "close0", + "()V", + voidPointer(closeFile), + updateRuntimeData); + } + } + } + + { + GcClass* zipFileClass = resolveClass( + t, roots(t)->bootLoader(), "java/util/zip/ZipFile", false); + + if (zipFileClass) { + PROTECT(t, zipFileClass); + + GcField* zipFileJzfileField + = findFieldInClass2(t, zipFileClass, "jzfile", "J"); + + if (zipFileJzfileField) { + cp->zipFileJzfileField = zipFileJzfileField->offset(); + + intercept(t, + zipFileClass, + "open", + "(Ljava/lang/String;IJZ)J", + voidPointer(openZipFile), + updateRuntimeData); + + intercept(t, + zipFileClass, + "getTotal", + "(J)I", + voidPointer(getZipFileEntryCount), + updateRuntimeData); + + intercept(t, + zipFileClass, + "getEntry", + "(J[BZ)J", + voidPointer(getZipFileEntry), + updateRuntimeData); + + intercept(t, + zipFileClass, + "getEntryBytes", + "(JI)[B", + voidPointer(getZipFileEntryBytes), + updateRuntimeData); + + intercept(t, + zipFileClass, + "getNextEntry", + "(JI)J", + voidPointer(getNextZipFileEntry), + updateRuntimeData); + + intercept(t, + zipFileClass, + "getEntryMethod", + "(J)I", + voidPointer(getZipFileEntryMethod), + updateRuntimeData); + + intercept(t, + zipFileClass, + "freeEntry", + "(JJ)V", + voidPointer(freeZipFileEntry), + updateRuntimeData); + + intercept(t, + zipFileClass, + "read", + "(JJJ[BII)I", + voidPointer(readZipFileEntry), + updateRuntimeData); + + intercept(t, + zipFileClass, + "getEntryCSize", + "(J)J", + voidPointer(getZipFileEntryCompressedSize), + updateRuntimeData); + + intercept(t, + zipFileClass, + "getEntrySize", + "(J)J", + voidPointer(getZipFileEntryUncompressedSize), + updateRuntimeData); + + intercept(t, + zipFileClass, + "getZipMessage", + "(J)Ljava/lang/String;", + voidPointer(getZipMessage), + updateRuntimeData); + + intercept(t, + zipFileClass, + "close", + "(J)V", + voidPointer(closeZipFile), + updateRuntimeData); + } + } + } + + { + GcClass* jarFileClass = resolveClass( + t, roots(t)->bootLoader(), "java/util/jar/JarFile", false); + + if (jarFileClass) { + intercept(t, + jarFileClass, + "getMetaInfEntryNames", + "()[Ljava/lang/String;", + voidPointer(getJarFileMetaInfEntryNames), + updateRuntimeData); + } + } + + { +#ifdef PLATFORM_WINDOWS + const char* const fsClassName = "java/io/WinNTFileSystem"; + const char* const gbaMethodName = "getBooleanAttributes"; +#else + const char* const fsClassName = "java/io/UnixFileSystem"; + const char* const gbaMethodName = "getBooleanAttributes0"; +#endif + + GcClass* fsClass + = resolveClass(t, roots(t)->bootLoader(), fsClassName, false); + + if (fsClass) { + PROTECT(t, fsClass); + + intercept(t, + fsClass, + gbaMethodName, + "(Ljava/io/File;)I", + voidPointer(getFileAttributes), + updateRuntimeData); + + intercept(t, + fsClass, + "checkAccess", + "(Ljava/io/File;I)Z", + voidPointer(checkFileAccess), + updateRuntimeData); + + intercept(t, + fsClass, + "getLength", + "(Ljava/io/File;)J", + voidPointer(getFileLength), + updateRuntimeData); + } + } + + intercept(t, + type(t, GcClassLoader::Type), + "loadLibrary", + "(Ljava/lang/Class;Ljava/lang/String;Z)V", + voidPointer(loadLibrary), + updateRuntimeData); + + intercept(t, + type(t, GcClassLoader::Type), + "getBootstrapResource", + "(Ljava/lang/String;)Ljava/net/URL;", + voidPointer(getBootstrapResource), + updateRuntimeData); + + intercept(t, + type(t, GcClassLoader::Type), + "getBootstrapResources", + "(Ljava/lang/String;)Ljava/util/Enumeration;", + voidPointer(getBootstrapResources), + updateRuntimeData); +} +#endif // AVIAN_OPENJDK_SRC + +unsigned classDeclaredMethodCount(Thread* t, GcClass* c) +{ + GcClassAddendum* addendum = c->addendum(); + if (addendum) { + int count = addendum->declaredMethodCount(); + if (count >= 0) { + return count; + } + } + GcArray* table = cast(t, c->methodTable()); + return table == 0 ? 0 : table->length(); +} + +unsigned countMethods(Thread* t, GcClass* c, bool publicOnly) +{ + GcArray* table = cast(t, c->methodTable()); + unsigned count = 0; + for (unsigned i = 0, j = classDeclaredMethodCount(t, c); i < j; ++i) { + GcMethod* vmMethod = cast(t, table->body()[i]); + if (((not publicOnly) or (vmMethod->flags() & ACC_PUBLIC)) + and vmMethod->name()->body()[0] != '<') { + ++count; + } + } + return count; +} + +unsigned countFields(Thread* t, GcClass* c, bool publicOnly) +{ + GcArray* table = cast(t, c->fieldTable()); + if (publicOnly) { + unsigned count = 0; + for (unsigned i = 0; i < table->length(); ++i) { + GcField* vmField = cast(t, table->body()[i]); + if (vmField->flags() & ACC_PUBLIC) { + ++count; + } + } + return count; + } else { + return objectArrayLength(t, table); + } +} + +unsigned countConstructors(Thread* t, GcClass* c, bool publicOnly) +{ + GcArray* table = cast(t, c->methodTable()); + unsigned count = 0; + for (unsigned i = 0, j = classDeclaredMethodCount(t, c); i < j; ++i) { + GcMethod* vmMethod = cast(t, table->body()[i]); + if (((not publicOnly) or (vmMethod->flags() & ACC_PUBLIC)) + and strcmp(reinterpret_cast(vmMethod->name()->body().begin()), + "") == 0) { + ++count; + } + } + return count; +} + +#ifdef HAVE_JexecutableHasRealParameterData +object makeJmethod(Thread* t, + uint8_t override, + object securityCheckCache, + object clazz, + uint32_t slot, + object name, + object returnType, + object parameterTypes, + object exceptionTypes, + uint32_t modifiers, + object signature, + object genericInfo, + object annotations, + object parameterAnnotations, + object annotationDefault, + object methodAccessor, + object root, + object declaredAnnotations) +{ + return makeJmethod(t, + override, + securityCheckCache, + 0, + 0, + declaredAnnotations, + cast(t, clazz), + slot, + cast(t, name), + cast(t, returnType), + parameterTypes, + exceptionTypes, + modifiers, + cast(t, signature), + genericInfo, + cast(t, annotations), + cast(t, parameterAnnotations), + cast(t, annotationDefault), + methodAccessor, + cast(t, root)); +} + +object makeJconstructor(Thread* t, + uint8_t override, + object securityCheckCache, + object clazz, + uint32_t slot, + object parameterTypes, + object exceptionTypes, + uint32_t modifiers, + object signature, + object genericInfo, + object annotations, + object parameterAnnotations, + object constructorAccessor, + object root, + object declaredAnnotations) +{ + return makeJconstructor(t, + override, + securityCheckCache, + 0, + 0, + declaredAnnotations, + cast(t, clazz), + slot, + parameterTypes, + exceptionTypes, + modifiers, + cast(t, signature), + genericInfo, + cast(t, annotations), + cast(t, parameterAnnotations), + constructorAccessor, + cast(t, root)); +} +#endif // HAVE_JexecutableHasRealParameterData + +object makeJmethod(Thread* t, GcMethod* vmMethod, int index) +{ + PROTECT(t, vmMethod); + + object name + = intern(t, + t->m->classpath->makeString( + t, vmMethod->name(), 0, vmMethod->name()->length() - 1)); + PROTECT(t, name); + + unsigned parameterCount; + unsigned returnTypeSpec; + object parameterTypes = resolveParameterJTypes(t, + vmMethod->class_()->loader(), + vmMethod->spec(), + ¶meterCount, + &returnTypeSpec); + PROTECT(t, parameterTypes); + + GcJclass* returnType = resolveJType( + t, + vmMethod->class_()->loader(), + reinterpret_cast(&vmMethod->spec()->body()[returnTypeSpec]), + vmMethod->spec()->length() - 1 - returnTypeSpec); + PROTECT(t, returnType); + + object exceptionTypes = resolveExceptionJTypes( + t, vmMethod->class_()->loader(), vmMethod->addendum()); + PROTECT(t, exceptionTypes); + + object signature; + object annotationTable; + object parameterAnnotationTable; + object annotationDefault; + GcMethodAddendum* addendum = vmMethod->addendum(); + if (addendum) { + signature = addendum->signature(); + if (signature) { + PROTECT(t, addendum); + + signature = t->m->classpath->makeString( + t, signature, 0, cast(t, signature)->length() - 1); + } + + annotationTable = addendum->annotationTable(); + + parameterAnnotationTable = addendum->parameterAnnotationTable(); + + annotationDefault = addendum->annotationDefault(); + } else { + signature = 0; + annotationTable = 0; + parameterAnnotationTable = 0; + annotationDefault = 0; + } + + PROTECT(t, signature); + PROTECT(t, annotationTable); + PROTECT(t, parameterAnnotationTable); + PROTECT(t, annotationDefault); + + if (annotationTable or parameterAnnotationTable or annotationDefault) { + GcClassRuntimeData* runtimeData + = getClassRuntimeData(t, vmMethod->class_()); + + runtimeData->setPool(t, vmMethod->addendum()->pool()); + } + + if (index == -1) { + GcArray* table = cast(t, vmMethod->class_()->methodTable()); + for (unsigned i = 0; i < table->length(); ++i) { + if (vmMethod == table->body()[i]) { + index = i; + break; + } + } + } + + expect(t, index != -1); + + GcJclass* jclass = getJClass(t, vmMethod->class_()); + + return makeJmethod(t, + true, + 0, + jclass, + index, + cast(t, name), + returnType, + parameterTypes, + exceptionTypes, + vmMethod->flags(), + cast(t, signature), + 0, + cast(t, annotationTable), + cast(t, parameterAnnotationTable), + cast(t, annotationDefault), + 0, + 0, + 0); +} + +object makeJconstructor(Thread* t, GcMethod* vmMethod, int index) +{ + PROTECT(t, vmMethod); + + unsigned parameterCount; + unsigned returnTypeSpec; + object parameterTypes = resolveParameterJTypes(t, + vmMethod->class_()->loader(), + vmMethod->spec(), + ¶meterCount, + &returnTypeSpec); + PROTECT(t, parameterTypes); + + object exceptionTypes = resolveExceptionJTypes( + t, vmMethod->class_()->loader(), vmMethod->addendum()); + PROTECT(t, exceptionTypes); + + object signature; + object annotationTable; + object parameterAnnotationTable; + GcMethodAddendum* addendum = vmMethod->addendum(); + if (addendum) { + signature = addendum->signature(); + if (signature) { + PROTECT(t, addendum); + + signature = t->m->classpath->makeString( + t, signature, 0, cast(t, signature)->length() - 1); + } + + annotationTable = addendum->annotationTable(); + parameterAnnotationTable = addendum->parameterAnnotationTable(); + } else { + signature = 0; + annotationTable = 0; + parameterAnnotationTable = 0; + } + + PROTECT(t, signature); + PROTECT(t, annotationTable); + PROTECT(t, parameterAnnotationTable); + + if (annotationTable or parameterAnnotationTable) { + GcClassRuntimeData* runtimeData + = getClassRuntimeData(t, vmMethod->class_()); + + runtimeData->setPool(t, vmMethod->addendum()->pool()); + } + + if (index == -1) { + GcArray* table = cast(t, vmMethod->class_()->methodTable()); + for (unsigned i = 0; i < table->length(); ++i) { + if (vmMethod == table->body()[i]) { + index = i; + break; + } + } + } + + expect(t, index != -1); + + GcJclass* jclass = getJClass(t, vmMethod->class_()); + + return makeJconstructor(t, + true, + 0, + jclass, + index, + parameterTypes, + exceptionTypes, + vmMethod->flags(), + cast(t, signature), + 0, + cast(t, annotationTable), + cast(t, parameterAnnotationTable), + 0, + 0, + 0); +} + +object makeJfield(Thread* t, GcField* vmField, int index) +{ + PROTECT(t, vmField); + + object name + = intern(t, + t->m->classpath->makeString( + t, vmField->name(), 0, vmField->name()->length() - 1)); + PROTECT(t, name); + + GcClass* type = resolveClassBySpec( + t, + vmField->class_()->loader(), + reinterpret_cast(vmField->spec()->body().begin()), + vmField->spec()->length() - 1); + PROTECT(t, type); + + GcJclass* jtype = getJClass(t, type); + + object signature; + object annotationTable; + GcFieldAddendum* addendum = vmField->addendum(); + if (addendum) { + signature = addendum->signature(); + if (signature) { + PROTECT(t, addendum); + + signature = t->m->classpath->makeString( + t, signature, 0, cast(t, signature)->length() - 1); + } + + annotationTable = addendum->annotationTable(); + } else { + signature = 0; + annotationTable = 0; + } + + PROTECT(t, signature); + PROTECT(t, annotationTable); + + if (annotationTable) { + GcClassRuntimeData* runtimeData = getClassRuntimeData(t, vmField->class_()); + + runtimeData->setPool(t, vmField->addendum()->pool()); + } + + if (index == -1) { + GcArray* table = cast(t, vmField->class_()->fieldTable()); + for (unsigned i = 0; i < table->length(); ++i) { + if (vmField == table->body()[i]) { + index = i; + break; + } + } + } + + expect(t, index != -1); + + GcJclass* jclass = getJClass(t, vmField->class_()); + + return makeJfield(t, + true, + 0, + jclass, + index, + cast(t, name), + jtype, + vmField->flags(), + cast(t, signature), + 0, + cast(t, annotationTable), + 0, + 0, + 0, + 0); +} + +void setProperty(Thread* t, + GcMethod* method, + object properties, + const char* name, + const void* value, + const char* format = "%s") +{ + PROTECT(t, method); + PROTECT(t, properties); + + GcString* n = makeString(t, "%s", name); + PROTECT(t, n); + + GcString* v = makeString(t, format, value); + + t->m->processor->invoke(t, method, properties, n, v); +} + +bool pipeAvailable(int fd, int* available) +{ +#ifdef PLATFORM_WINDOWS + HANDLE h = reinterpret_cast(_get_osfhandle(fd)); + if (h == INVALID_HANDLE_VALUE) { + return false; + } + + DWORD n; + if (PeekNamedPipe(h, 0, 0, 0, &n, 0)) { + *available = n; + } else { + if (GetLastError() != ERROR_BROKEN_PIPE) { + return false; + } + *available = 0; + } + + return true; +#else + return ioctl(fd, FIONREAD, available) >= 0; +#endif +} + +} // namespace local + +} // namespace + +namespace vm { + +Classpath* makeClasspath(System* s, + Allocator* allocator, + const char* javaHome, + const char* embedPrefix) +{ + return new (allocator->allocate(sizeof(local::MyClasspath))) + local::MyClasspath(s, allocator, javaHome, embedPrefix); +} + +} // namespace vm + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_java_lang_Class_getSuperclass(Thread* t, object, uintptr_t* arguments) +{ + GcClass* class_ + = cast(t, reinterpret_cast(arguments[0]))->vmClass(); + if (class_->flags() & ACC_INTERFACE) { + return 0; + } else { + GcClass* super = class_->super(); + return super ? reinterpret_cast(getJClass(t, super)) : 0; + } +} + +extern "C" AVIAN_EXPORT void Avian_sun_misc_Unsafe_registerNatives(Thread*, + object, + uintptr_t*) +{ + // ignore +} + +extern "C" AVIAN_EXPORT void Avian_sun_misc_Perf_registerNatives(Thread*, + object, + uintptr_t*) +{ + // ignore +} + +extern "C" AVIAN_EXPORT int64_t + Avian_sun_misc_Perf_createLong(Thread* t, object, uintptr_t*) +{ + return reinterpret_cast( + t->m->processor->invoke(t, + resolveMethod(t, + roots(t)->bootLoader(), + "java/nio/ByteBuffer", + "allocate", + "(I)Ljava/nio/ByteBuffer;"), + 0, + 8)); +} + +extern "C" AVIAN_EXPORT int64_t + Avian_sun_misc_Unsafe_addressSize(Thread*, object, uintptr_t*) +{ + return BytesPerWord; +} + +extern "C" AVIAN_EXPORT int64_t + Avian_sun_misc_Unsafe_defineClass__Ljava_lang_String_2_3BIILjava_lang_ClassLoader_2Ljava_security_ProtectionDomain_2( + Thread* t, + object, + uintptr_t* arguments) +{ + // object name = reinterpret_cast(arguments[1]); + GcByteArray* data + = cast(t, reinterpret_cast(arguments[2])); + int32_t offset = arguments[3]; + int32_t length = arguments[4]; + GcClassLoader* loader + = cast(t, reinterpret_cast(arguments[5])); + // object domain = reinterpret_cast(arguments[6]); + + uint8_t* buffer = static_cast(t->m->heap->allocate(length)); + + THREAD_RESOURCE2( + t, uint8_t*, buffer, int, length, t->m->heap->free(buffer, length)); + + memcpy(buffer, &data->body()[offset], length); + + return reinterpret_cast( + getJClass(t, cast(t, defineClass(t, loader, buffer, length)))); +} + +extern "C" AVIAN_EXPORT int64_t + Avian_sun_misc_Unsafe_allocateInstance(Thread* t, + object, + uintptr_t* arguments) +{ + GcClass* c + = cast(t, reinterpret_cast(arguments[1]))->vmClass(); + PROTECT(t, c); + + initClass(t, c); + + return reinterpret_cast(make(t, c)); +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_sun_misc_Unsafe_staticFieldOffset(Thread* t, + object, + uintptr_t* arguments) +{ + GcJfield* jfield = cast(t, reinterpret_cast(arguments[1])); + return cast( + t, + cast(t, jfield->clazz()->vmClass()->fieldTable()) + ->body()[jfield->slot()])->offset(); +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_sun_misc_Unsafe_staticFieldBase(Thread* t, + object, + uintptr_t* arguments) +{ + return reinterpret_cast( + cast(t, reinterpret_cast(arguments[1])) + ->clazz() + ->vmClass() + ->staticTable()); +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_sun_misc_Unsafe_objectFieldOffset(Thread* t, + object, + uintptr_t* arguments) +{ + GcJfield* jfield = cast(t, reinterpret_cast(arguments[1])); + return cast( + t, + cast(t, jfield->clazz()->vmClass()->fieldTable()) + ->body()[jfield->slot()])->offset(); +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_sun_misc_Unsafe_getShort__Ljava_lang_Object_2J(Thread*, + object, + uintptr_t* arguments) +{ + object o = reinterpret_cast(arguments[1]); + int64_t offset; + memcpy(&offset, arguments + 2, 8); + + return fieldAtOffset(o, offset); +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_sun_misc_Unsafe_getChar__Ljava_lang_Object_2J(Thread*, + object, + uintptr_t* arguments) +{ + object o = reinterpret_cast(arguments[1]); + int64_t offset; + memcpy(&offset, arguments + 2, 8); + + return fieldAtOffset(o, offset); +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_sun_misc_Unsafe_getInt__Ljava_lang_Object_2J(Thread*, + object, + uintptr_t* arguments) +{ + object o = reinterpret_cast(arguments[1]); + int64_t offset; + memcpy(&offset, arguments + 2, 8); + + return fieldAtOffset(o, offset); +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_sun_misc_Unsafe_getFloat__Ljava_lang_Object_2J(Thread*, + object, + uintptr_t* arguments) +{ + object o = reinterpret_cast(arguments[1]); + int64_t offset; + memcpy(&offset, arguments + 2, 8); + + return fieldAtOffset(o, offset); +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_sun_misc_Unsafe_getLong__Ljava_lang_Object_2J(Thread*, + object, + uintptr_t* arguments) +{ + object o = reinterpret_cast(arguments[1]); + int64_t offset; + memcpy(&offset, arguments + 2, 8); + + return fieldAtOffset(o, offset); +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_sun_misc_Unsafe_getDouble__Ljava_lang_Object_2J(Thread* t, + GcMethod* method, + uintptr_t* arguments) +{ + return Avian_sun_misc_Unsafe_getLong__Ljava_lang_Object_2J( + t, method, arguments); +} + +extern "C" AVIAN_EXPORT void JNICALL + Avian_sun_misc_Unsafe_putByte__Ljava_lang_Object_2JB(Thread*, + object, + uintptr_t* arguments) +{ + object o = reinterpret_cast(arguments[1]); + int64_t offset; + memcpy(&offset, arguments + 2, 8); + int8_t value = arguments[4]; + + fieldAtOffset(o, offset) = value; +} + +extern "C" AVIAN_EXPORT void JNICALL + Avian_sun_misc_Unsafe_putShort__Ljava_lang_Object_2JS(Thread*, + object, + uintptr_t* arguments) +{ + object o = reinterpret_cast(arguments[1]); + int64_t offset; + memcpy(&offset, arguments + 2, 8); + int16_t value = arguments[4]; + + fieldAtOffset(o, offset) = value; +} + +extern "C" AVIAN_EXPORT void JNICALL + Avian_sun_misc_Unsafe_putChar__Ljava_lang_Object_2JC(Thread*, + object, + uintptr_t* arguments) +{ + object o = reinterpret_cast(arguments[1]); + int64_t offset; + memcpy(&offset, arguments + 2, 8); + uint16_t value = arguments[4]; + + fieldAtOffset(o, offset) = value; +} + +extern "C" AVIAN_EXPORT void JNICALL + Avian_sun_misc_Unsafe_putInt__Ljava_lang_Object_2JI(Thread*, + object, + uintptr_t* arguments) +{ + object o = reinterpret_cast(arguments[1]); + int64_t offset; + memcpy(&offset, arguments + 2, 8); + int32_t value = arguments[4]; + + fieldAtOffset(o, offset) = value; +} + +extern "C" AVIAN_EXPORT void JNICALL + Avian_sun_misc_Unsafe_putFloat__Ljava_lang_Object_2JF(Thread*, + object, + uintptr_t* arguments) +{ + object o = reinterpret_cast(arguments[1]); + int64_t offset; + memcpy(&offset, arguments + 2, 8); + int32_t value = arguments[4]; + + fieldAtOffset(o, offset) = value; +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_sun_misc_Unsafe_getByte__Ljava_lang_Object_2J(Thread*, + object, + uintptr_t* arguments) +{ + object o = reinterpret_cast(arguments[1]); + int64_t offset; + memcpy(&offset, arguments + 2, 8); + + return fieldAtOffset(o, offset); +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_sun_misc_Unsafe_getBoolean__Ljava_lang_Object_2J(Thread* t, + object method, + uintptr_t* arguments) +{ + return Avian_sun_misc_Unsafe_getByte__Ljava_lang_Object_2J( + t, method, arguments); +} + +extern "C" AVIAN_EXPORT void JNICALL + Avian_sun_misc_Unsafe_putBoolean__Ljava_lang_Object_2JZ( + Thread*, + object, + uintptr_t* arguments) +{ + object o = reinterpret_cast(arguments[1]); + int64_t offset; + memcpy(&offset, arguments + 2, 8); + uint8_t value = arguments[4]; + + fieldAtOffset(o, offset) = value; +} + +extern "C" AVIAN_EXPORT void JNICALL + Avian_sun_misc_Unsafe_putLong__Ljava_lang_Object_2JJ(Thread*, + object, + uintptr_t* arguments) +{ + object o = reinterpret_cast(arguments[1]); + int64_t offset; + memcpy(&offset, arguments + 2, 8); + int64_t value; + memcpy(&value, arguments + 4, 8); + + fieldAtOffset(o, offset) = value; +} + +extern "C" AVIAN_EXPORT void JNICALL +Avian_sun_misc_Unsafe_putDouble__Ljava_lang_Object_2JD(Thread*, + object, + uintptr_t* arguments) +{ + object o = reinterpret_cast(arguments[1]); + int64_t offset; + memcpy(&offset, arguments + 2, 8); + jdouble value; + memcpy(&value, arguments + 4, 8); + + fieldAtOffset(o, offset) = value; +} + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_sun_misc_Unsafe_pageSize(Thread*, object, uintptr_t*) +{ + return local::PageSize; +} + +extern "C" AVIAN_EXPORT void JNICALL + Avian_sun_misc_Unsafe_ensureClassInitialized(Thread* t, + object, + uintptr_t* arguments) +{ + initClass( + t, cast(t, reinterpret_cast(arguments[1]))->vmClass()); +} + +extern "C" AVIAN_EXPORT void JNICALL + Avian_sun_misc_Unsafe_monitorEnter(Thread* t, object, uintptr_t* arguments) +{ + acquire(t, reinterpret_cast(arguments[1])); +} + +extern "C" AVIAN_EXPORT void JNICALL + Avian_sun_misc_Unsafe_monitorExit(Thread* t, object, uintptr_t* arguments) +{ + release(t, reinterpret_cast(arguments[1])); +} + +extern "C" AVIAN_EXPORT jboolean JNICALL + Avian_sun_misc_Unsafe_isBigEndian0(Thread*, object, uintptr_t*) +{ + return false; +} + +extern "C" AVIAN_EXPORT jboolean JNICALL + Avian_sun_misc_Unsafe_unalignedAccess0(Thread*, object, uintptr_t*) +{ + return false; +} + +namespace { + +namespace local { + +extern "C" AVIAN_EXPORT jobjectArray JNICALL EXPORT(JVM_GetMethodParameters)(Thread*, jobject) +{ + abort(); +} + +extern "C" AVIAN_EXPORT jint JNICALL EXPORT(JVM_GetInterfaceVersion)() +{ + return local::InterfaceVersion; +} + +extern "C" AVIAN_EXPORT jint JNICALL EXPORT(JVM_IHashCode)(Thread* t, jobject o) +{ + ENTER(t, Thread::ActiveState); + + return o ? objectHash(t, *o) : 0; +} + +uint64_t jvmWait(Thread* t, uintptr_t* arguments) +{ + jobject o = reinterpret_cast(arguments[0]); + jlong milliseconds; + memcpy(&milliseconds, arguments + 1, sizeof(jlong)); + + vm::wait(t, *o, milliseconds); + + return 1; +} + +extern "C" AVIAN_EXPORT void JNICALL + EXPORT(JVM_MonitorWait)(Thread* t, jobject o, jlong milliseconds) +{ + uintptr_t arguments[1 + (sizeof(jlong) / BytesPerWord)]; + arguments[0] = reinterpret_cast(o); + memcpy(arguments + 1, &milliseconds, sizeof(jlong)); + + run(t, jvmWait, arguments); +} + +uint64_t jvmNotify(Thread* t, uintptr_t* arguments) +{ + jobject o = reinterpret_cast(arguments[0]); + + notify(t, *o); + + return 1; +} + +extern "C" AVIAN_EXPORT void JNICALL + EXPORT(JVM_MonitorNotify)(Thread* t, jobject o) +{ + uintptr_t arguments[] = {reinterpret_cast(o)}; + + run(t, jvmNotify, arguments); +} + +uint64_t jvmNotifyAll(Thread* t, uintptr_t* arguments) +{ + jobject o = reinterpret_cast(arguments[0]); + + notifyAll(t, *o); + + return 1; +} + +extern "C" AVIAN_EXPORT void JNICALL + EXPORT(JVM_MonitorNotifyAll)(Thread* t, jobject o) +{ + uintptr_t arguments[] = {reinterpret_cast(o)}; + + run(t, jvmNotifyAll, arguments); +} + +uint64_t jvmClone(Thread* t, uintptr_t* arguments) +{ + jobject o = reinterpret_cast(arguments[0]); + + return reinterpret_cast(makeLocalReference(t, clone(t, *o))); +} + +extern "C" AVIAN_EXPORT jobject JNICALL EXPORT(JVM_Clone)(Thread* t, jobject o) +{ + uintptr_t arguments[] = {reinterpret_cast(o)}; + + return reinterpret_cast(run(t, jvmClone, arguments)); +} + +uint64_t jvmInternString(Thread* t, uintptr_t* arguments) +{ + jobject o = reinterpret_cast(arguments[0]); + + return reinterpret_cast(makeLocalReference(t, intern(t, *o))); +} + +extern "C" AVIAN_EXPORT jstring JNICALL + EXPORT(JVM_InternString)(Thread* t, jstring s) +{ + uintptr_t arguments[] = {reinterpret_cast(s)}; + + return reinterpret_cast(run(t, jvmInternString, arguments)); +} + +extern "C" AVIAN_EXPORT jlong JNICALL + EXPORT(JVM_CurrentTimeMillis)(Thread* t, jclass) +{ + return t->m->system->now(); +} + +extern "C" AVIAN_EXPORT jlong JNICALL EXPORT(JVM_NanoTime)(Thread* t, jclass) +{ + return t->m->system->now() * 1000 * 1000; +} + +uint64_t jvmArrayCopy(Thread* t, uintptr_t* arguments) +{ + jobject src = reinterpret_cast(arguments[0]); + jint srcOffset = arguments[1]; + jobject dst = reinterpret_cast(arguments[2]); + jint dstOffset = arguments[3]; + jint length = arguments[4]; + + arrayCopy(t, *src, srcOffset, *dst, dstOffset, length); + + return 1; +} + +extern "C" AVIAN_EXPORT void JNICALL EXPORT(JVM_ArrayCopy)(Thread* t, + jclass, + jobject src, + jint srcOffset, + jobject dst, + jint dstOffset, + jint length) +{ + uintptr_t arguments[] = {reinterpret_cast(src), + static_cast(srcOffset), + reinterpret_cast(dst), + static_cast(dstOffset), + static_cast(length)}; + + run(t, jvmArrayCopy, arguments); +} + +uint64_t jvmInitProperties(Thread* t, uintptr_t* arguments) +{ + jobject properties = reinterpret_cast(arguments[0]); + + GcMethod* method = resolveMethod( + t, + roots(t)->bootLoader(), + "java/util/Properties", + "setProperty", + "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/Object;"); + + PROTECT(t, method); + +#ifdef PLATFORM_WINDOWS + local::setProperty(t, method, *properties, "line.separator", "\r\n"); + local::setProperty(t, method, *properties, "file.separator", "\\"); + local::setProperty(t, method, *properties, "path.separator", ";"); + local::setProperty(t, method, *properties, "os.name", "Windows"); + + TCHAR buffer[MAX_PATH]; + GetTempPath(MAX_PATH, buffer); + + local::setProperty(t, method, *properties, "java.io.tmpdir", buffer); + local::setProperty(t, method, *properties, "java.home", buffer); + local::setProperty( + t, method, *properties, "user.home", _wgetenv(L"USERPROFILE"), "%ls"); + + GetCurrentDirectory(MAX_PATH, buffer); + + local::setProperty(t, method, *properties, "user.dir", buffer); +#else // not PLATFORM_WINDOWS + local::setProperty(t, method, *properties, "line.separator", "\n"); + local::setProperty(t, method, *properties, "file.separator", "/"); + local::setProperty(t, method, *properties, "path.separator", ":"); +#ifdef __APPLE__ + local::setProperty(t, method, *properties, "os.name", "Mac OS X"); +#elif defined __FreeBSD__ + local::setProperty(t, method, *properties, "os.name", "FreeBSD"); +#else // not __APPLE__ + local::setProperty(t, method, *properties, "os.name", "Linux"); +#endif // not __APPLE__ + local::setProperty(t, method, *properties, "java.io.tmpdir", "/tmp"); + local::setProperty(t, method, *properties, "user.home", getenv("HOME")); + + char buffer[PATH_MAX]; + local::setProperty( + t, method, *properties, "user.dir", getcwd(buffer, PATH_MAX)); +#endif // not PLATFORM_WINDOWS + + local::setProperty( + t, method, *properties, "java.protocol.handler.pkgs", "avian"); + + local::setProperty( + t, method, *properties, "java.vm.vendor", "Avian Contributors"); + + local::setProperty(t, method, *properties, "java.vm.name", "Avian"); +#ifdef AVIAN_VERSION + local::setProperty(t, method, *properties, "java.vm.version", AVIAN_VERSION); +#endif +#ifdef AVIAN_INFO + local::setProperty(t, method, *properties, "java.vm.info", AVIAN_INFO); +#endif + + local::setProperty(t, + method, + *properties, + "java.vm.specification.name", + "Java Virtual Machine Specification"); + + local::setProperty( + t, + method, + *properties, + "java.home", + static_cast(t->m->classpath)->javaHome); + + local::setProperty( + t, + method, + *properties, + "sun.boot.library.path", + static_cast(t->m->classpath)->libraryPath); + + local::setProperty( + t, + method, + *properties, + "sun.boot.class.path", + static_cast( + roots(t)->bootLoader()->as(t)->finder()) + ->path()); + + local::setProperty(t, method, *properties, "file.encoding", "UTF-8"); + + local::setProperty(t, method, *properties, "jdk.lang.Process.launchMechanism", "fork"); + +#ifdef ARCH_x86_32 + local::setProperty(t, method, *properties, "os.arch", "x86"); +#elif defined ARCH_x86_64 + local::setProperty(t, method, *properties, "os.arch", "x86_64"); +#elif defined ARCH_arm + local::setProperty(t, method, *properties, "os.arch", "arm"); +#else + local::setProperty(t, method, *properties, "os.arch", "unknown"); +#endif + + for (unsigned i = 0; i < t->m->propertyCount; ++i) { + const char* start = t->m->properties[i]; + const char* p = start; + while (*p and *p != '=') + ++p; + + if (*p == '=') { + THREAD_RUNTIME_ARRAY(t, char, name, (p - start) + 1); + memcpy(RUNTIME_ARRAY_BODY(name), start, p - start); + RUNTIME_ARRAY_BODY(name)[p - start] = 0; + local::setProperty( + t, method, *properties, RUNTIME_ARRAY_BODY(name), p + 1); + } + } + + return reinterpret_cast(properties); +} + +extern "C" AVIAN_EXPORT jobject JNICALL + EXPORT(JVM_InitProperties)(Thread* t, jobject properties) +{ + uintptr_t arguments[] = {reinterpret_cast(properties)}; + + return reinterpret_cast(run(t, jvmInitProperties, arguments)); +} + +extern "C" AVIAN_EXPORT void JNICALL EXPORT(JVM_OnExit)(void (*)(void)) +{ + abort(); +} + +extern "C" AVIAN_EXPORT void JNICALL EXPORT(JVM_Exit)(jint code) +{ + exit(code); +} + +extern "C" AVIAN_EXPORT void JNICALL EXPORT(JVM_Halt)(jint code) +{ + exit(code); +} + +uint64_t jvmGC(Thread* t, uintptr_t*) +{ + collect(t, Heap::MajorCollection); + + return 1; +} + +extern "C" AVIAN_EXPORT void JNICALL EXPORT(JVM_GC)() +{ + Thread* t = static_cast(local::globalMachine->localThread->get()); + + run(t, jvmGC, 0); +} + +extern "C" AVIAN_EXPORT jlong JNICALL EXPORT(JVM_MaxObjectInspectionAge)(void) +{ + return 0; +} + +extern "C" AVIAN_EXPORT void JNICALL EXPORT(JVM_TraceInstructions)(jboolean) +{ + abort(); +} + +extern "C" AVIAN_EXPORT void JNICALL EXPORT(JVM_TraceMethodCalls)(jboolean) +{ + abort(); +} + +extern "C" AVIAN_EXPORT jlong JNICALL EXPORT(JVM_TotalMemory)() +{ + return 0; +} + +extern "C" AVIAN_EXPORT jlong JNICALL EXPORT(JVM_FreeMemory)() +{ + return 0; +} + +extern "C" AVIAN_EXPORT jlong JNICALL EXPORT(JVM_MaxMemory)() +{ + return local::globalMachine->heap->limit(); +} + +extern "C" AVIAN_EXPORT jint JNICALL EXPORT(JVM_ActiveProcessorCount)() +{ +#ifdef PLATFORM_WINDOWS + SYSTEM_INFO si; + GetSystemInfo(&si); + return si.dwNumberOfProcessors; +#else + return sysconf(_SC_NPROCESSORS_ONLN); +#endif +} + +uint64_t jvmLoadLibrary(Thread* t, uintptr_t* arguments) +{ + const char* path = reinterpret_cast(arguments[0]); + + THREAD_RUNTIME_ARRAY(t, char, p, strlen(path) + 1); + replace('\\', '/', RUNTIME_ARRAY_BODY(p), path); + + return reinterpret_cast(loadLibrary( + t, + static_cast(t->m->classpath)->libraryPath, + RUNTIME_ARRAY_BODY(p), + false, + false)); +} + +extern "C" AVIAN_EXPORT void* JNICALL EXPORT(JVM_LoadLibrary)(const char* path) +{ + Thread* t = static_cast(local::globalMachine->localThread->get()); + + uintptr_t arguments[] = {reinterpret_cast(path)}; + + return reinterpret_cast(run(t, jvmLoadLibrary, arguments)); +} + +extern "C" AVIAN_EXPORT void JNICALL EXPORT(JVM_UnloadLibrary)(void*) +{ + // todo: implement this correctly for POSIX and Windows +} + +extern "C" AVIAN_EXPORT void* JNICALL + EXPORT(JVM_FindLibraryEntry)(void* library, const char* name) +{ + Thread* t = static_cast(local::globalMachine->localThread->get()); + + ENTER(t, Thread::ActiveState); + + if (library == RTLD_DEFAULT) { + library = t->m->libraries; + } + + for (System::Library* lib = t->m->libraries; lib; lib = lib->next()) { + if (library == lib) { + return lib->resolve(name); + } + } + + return 0; +} + +extern "C" AVIAN_EXPORT jboolean JNICALL + EXPORT(JVM_IsSupportedJNIVersion)(jint version) +{ + return version <= JNI_VERSION_1_6; +} + +extern "C" AVIAN_EXPORT jboolean JNICALL EXPORT(JVM_IsNaN)(jdouble v) +{ + return isnan(v); +} + +uint64_t jvmFillInStackTrace(Thread* t, uintptr_t* arguments) +{ + GcThrowable* throwable + = cast(t, *reinterpret_cast(arguments[0])); + PROTECT(t, throwable); + + object trace = getTrace(t, 2); + throwable->setTrace(t, trace); + + return 1; +} + +extern "C" AVIAN_EXPORT void JNICALL + EXPORT(JVM_FillInStackTrace)(Thread* t, jobject throwable) +{ + uintptr_t arguments[] = {reinterpret_cast(throwable)}; + + run(t, jvmFillInStackTrace, arguments); +} + +extern "C" AVIAN_EXPORT void JNICALL + EXPORT(JVM_PrintStackTrace)(Thread*, jobject, jobject) +{ + abort(); +} + +extern "C" AVIAN_EXPORT jint JNICALL + EXPORT(JVM_GetStackTraceDepth)(Thread* t, jobject throwable) +{ + ENTER(t, Thread::ActiveState); + + return objectArrayLength(t, cast(t, *throwable)->trace()); +} + +uint64_t jvmGetStackTraceElement(Thread* t, uintptr_t* arguments) +{ + jobject throwable = reinterpret_cast(arguments[0]); + jint index = arguments[1]; + + return reinterpret_cast(makeLocalReference( + t, + makeStackTraceElement( + t, + cast( + t, + objectArrayBody( + t, cast(t, *throwable)->trace(), index))))); +} + +extern "C" AVIAN_EXPORT jobject JNICALL + EXPORT(JVM_GetStackTraceElement)(Thread* t, jobject throwable, jint index) +{ + uintptr_t arguments[] + = {reinterpret_cast(throwable), static_cast(index)}; + + return reinterpret_cast(run(t, jvmGetStackTraceElement, arguments)); +} + +extern "C" AVIAN_EXPORT void JNICALL + EXPORT(JVM_InitializeCompiler)(Thread*, jclass) +{ + abort(); +} + +extern "C" AVIAN_EXPORT jboolean JNICALL + EXPORT(JVM_IsSilentCompiler)(Thread*, jclass) +{ + abort(); +} + +extern "C" AVIAN_EXPORT jboolean JNICALL + EXPORT(JVM_CompileClass)(Thread*, jclass, jclass) +{ + return false; +} + +extern "C" AVIAN_EXPORT jboolean JNICALL + EXPORT(JVM_CompileClasses)(Thread*, jclass, jstring) +{ + return false; +} + +extern "C" AVIAN_EXPORT jobject JNICALL + EXPORT(JVM_CompilerCommand)(Thread*, jclass, jobject) +{ + abort(); +} + +extern "C" AVIAN_EXPORT void JNICALL EXPORT(JVM_EnableCompiler)(Thread*, jclass) +{ + // ignore +} + +extern "C" AVIAN_EXPORT void JNICALL + EXPORT(JVM_DisableCompiler)(Thread*, jclass) +{ + // ignore +} + +uint64_t jvmStartThread(Thread* t, uintptr_t* arguments) +{ + jobject thread = reinterpret_cast(arguments[0]); + + return startThread(t, cast(t, *thread)) != 0; +} + +extern "C" AVIAN_EXPORT void JNICALL + EXPORT(JVM_StartThread)(Thread* t, jobject thread) +{ + uintptr_t arguments[] = {reinterpret_cast(thread)}; + + run(t, jvmStartThread, arguments); +} + +extern "C" AVIAN_EXPORT void JNICALL + EXPORT(JVM_StopThread)(Thread*, jobject, jobject) +{ + abort(); +} + +extern "C" AVIAN_EXPORT jboolean JNICALL + EXPORT(JVM_IsThreadAlive)(Thread* t, jobject thread) +{ + ENTER(t, Thread::ActiveState); + + Thread* p = reinterpret_cast(cast(t, *thread)->peer()); + return p and (p->getFlags() & Thread::ActiveFlag) != 0; +} + +extern "C" AVIAN_EXPORT void JNICALL EXPORT(JVM_SuspendThread)(Thread*, jobject) +{ + abort(); +} + +extern "C" AVIAN_EXPORT void JNICALL EXPORT(JVM_ResumeThread)(Thread*, jobject) +{ + abort(); +} + +extern "C" AVIAN_EXPORT void JNICALL + EXPORT(JVM_SetThreadPriority)(Thread*, jobject, jint) +{ + // ignore +} + +extern "C" AVIAN_EXPORT void JNICALL EXPORT(JVM_Yield)(Thread* t, jclass) +{ + t->m->system->yield(); +} + +uint64_t jvmSleep(Thread* t, uintptr_t* arguments) +{ + jlong milliseconds; + memcpy(&milliseconds, arguments, sizeof(jlong)); + + if (milliseconds <= 0) { + milliseconds = 1; + } + + if (t->javaThread->sleepLock() == 0) { + GcJobject* lock = makeJobject(t); + t->javaThread->setSleepLock(t, lock); + } + + acquire(t, t->javaThread->sleepLock()); + vm::wait(t, t->javaThread->sleepLock(), milliseconds); + release(t, t->javaThread->sleepLock()); + + return 1; +} + +extern "C" AVIAN_EXPORT void JNICALL + EXPORT(JVM_Sleep)(Thread* t, jclass, jlong milliseconds) +{ + uintptr_t arguments[sizeof(jlong) / BytesPerWord]; + memcpy(arguments, &milliseconds, sizeof(jlong)); + + run(t, jvmSleep, arguments); +} + +extern "C" AVIAN_EXPORT jobject JNICALL + EXPORT(JVM_CurrentThread)(Thread* t, jclass) +{ + ENTER(t, Thread::ActiveState); + + return makeLocalReference(t, t->javaThread); +} + +extern "C" AVIAN_EXPORT jint JNICALL + EXPORT(JVM_CountStackFrames)(Thread*, jobject) +{ + abort(); +} + +uint64_t jvmInterrupt(Thread* t, uintptr_t* arguments) +{ + threadInterrupt(t, + cast(t, *reinterpret_cast(arguments[0]))); + + return 1; +} + +extern "C" AVIAN_EXPORT void JNICALL + EXPORT(JVM_Interrupt)(Thread* t, jobject thread) +{ + uintptr_t arguments[] = {reinterpret_cast(thread)}; + + run(t, jvmInterrupt, arguments); +} + +uint64_t jvmIsInterrupted(Thread* t, uintptr_t* arguments) +{ + jobject thread = reinterpret_cast(arguments[0]); + jboolean clear = arguments[1]; + + return threadIsInterrupted(t, cast(t, *thread), clear); +} + +extern "C" AVIAN_EXPORT jboolean JNICALL + EXPORT(JVM_IsInterrupted)(Thread* t, jobject thread, jboolean clear) +{ + uintptr_t arguments[] = {reinterpret_cast(thread), clear}; + + return run(t, jvmIsInterrupted, arguments); +} + +uint64_t jvmHoldsLock(Thread* t, uintptr_t* arguments) +{ + GcMonitor* m + = objectMonitor(t, *reinterpret_cast(arguments[0]), false); + + return m and m->owner() == t; +} + +extern "C" AVIAN_EXPORT jboolean JNICALL + EXPORT(JVM_HoldsLock)(Thread* t, jclass, jobject o) +{ + uintptr_t arguments[] = {reinterpret_cast(o)}; + + return run(t, jvmHoldsLock, arguments); +} + +extern "C" AVIAN_EXPORT void JNICALL EXPORT(JVM_DumpAllStacks)(Thread*, jclass) +{ + abort(); +} + +extern "C" AVIAN_EXPORT jobjectArray JNICALL + EXPORT(JVM_GetAllThreads)(Thread*, jclass) +{ + abort(); +} + +uint64_t jvmDumpThreads(Thread* t, uintptr_t* arguments) +{ + jobjectArray threads = reinterpret_cast(arguments[0]); + + unsigned threadsLength + = objectArrayLength(t, reinterpret_cast(*threads)); + GcClass* arrayClass + = resolveObjectArrayClass(t, + type(t, GcStackTraceElement::Type)->loader(), + type(t, GcStackTraceElement::Type)); + object result = makeObjectArray(t, arrayClass, threadsLength); + PROTECT(t, result); + + for (unsigned threadsIndex = 0; threadsIndex < threadsLength; + ++threadsIndex) { + Thread* peer = reinterpret_cast( + cast(t, + objectArrayBody( + t, reinterpret_cast(*threads), threadsIndex)) + ->peer()); + + if (peer) { + object trace = t->m->processor->getStackTrace(t, peer); + PROTECT(t, trace); + + unsigned traceLength = objectArrayLength(t, trace); + object array + = makeObjectArray(t, type(t, GcStackTraceElement::Type), traceLength); + PROTECT(t, array); + + for (unsigned traceIndex = 0; traceIndex < traceLength; ++traceIndex) { + object ste = makeStackTraceElement( + t, cast(t, objectArrayBody(t, trace, traceIndex))); + setField(t, array, ArrayBody + (traceIndex * BytesPerWord), ste); + } + + setField(t, result, ArrayBody + (threadsIndex * BytesPerWord), array); + } + } + + return reinterpret_cast(makeLocalReference(t, result)); +} + +extern "C" AVIAN_EXPORT jobjectArray JNICALL + EXPORT(JVM_DumpThreads)(Thread* t, jclass, jobjectArray threads) +{ + uintptr_t arguments[] = {reinterpret_cast(threads)}; + + return reinterpret_cast(run(t, jvmDumpThreads, arguments)); +} + +extern "C" AVIAN_EXPORT jclass JNICALL EXPORT(JVM_CurrentLoadedClass)(Thread*) +{ + abort(); +} + +extern "C" AVIAN_EXPORT jobject JNICALL EXPORT(JVM_CurrentClassLoader)(Thread*) +{ + // just return null, i.e. tell SecurityManager.currentClassLoader + // all permissions are granted, since Avian doesn't do any internal + // security checks: + return 0; +} + +uint64_t jvmGetClassContext(Thread* t, uintptr_t*) +{ + object trace = getTrace(t, 1); + PROTECT(t, trace); + + object context = makeObjectArray( + t, type(t, GcJclass::Type), objectArrayLength(t, trace)); + PROTECT(t, context); + + for (unsigned i = 0; i < objectArrayLength(t, trace); ++i) { + object c = getJClass( + t, + cast( + t, cast(t, objectArrayBody(t, trace, i))->method()) + ->class_()); + + setField(t, context, ArrayBody + (i * BytesPerWord), c); + } + + return reinterpret_cast(makeLocalReference(t, context)); +} + +extern "C" AVIAN_EXPORT jobjectArray JNICALL + EXPORT(JVM_GetClassContext)(Thread* t) +{ + return reinterpret_cast(run(t, jvmGetClassContext, 0)); +} + +extern "C" AVIAN_EXPORT jint JNICALL EXPORT(JVM_ClassDepth)(Thread*, jstring) +{ + abort(); +} + +extern "C" AVIAN_EXPORT jint JNICALL EXPORT(JVM_ClassLoaderDepth)(Thread*) +{ + abort(); +} + +uint64_t jvmGetSystemPackage(Thread* t, uintptr_t* arguments) +{ + jstring s = reinterpret_cast(arguments[0]); + + ACQUIRE(t, t->m->classLock); + + THREAD_RUNTIME_ARRAY(t, char, chars, (*s)->length(t) + 1); + stringChars(t, *s, RUNTIME_ARRAY_BODY(chars)); + + object key = makeByteArray(t, RUNTIME_ARRAY_BODY(chars)); + + GcByteArray* array = cast( + t, + hashMapFind( + t, roots(t)->packageMap(), key, byteArrayHash, byteArrayEqual)); + + if (array) { + return reinterpret_cast(makeLocalReference( + t, t->m->classpath->makeString(t, array, 0, array->length()))); + } else { + return 0; + } +} + +extern "C" AVIAN_EXPORT jstring JNICALL + EXPORT(JVM_GetSystemPackage)(Thread* t, jstring s) +{ + uintptr_t arguments[] = {reinterpret_cast(s)}; + + return reinterpret_cast(run(t, jvmGetSystemPackage, arguments)); +} + +uint64_t jvmGetSystemPackages(Thread* t, uintptr_t*) +{ + return reinterpret_cast(makeLocalReference( + t, + makeObjectArray( + t, resolveClass(t, roots(t)->bootLoader(), "java/lang/Package"), 0))); +} + +extern "C" AVIAN_EXPORT jobjectArray JNICALL + EXPORT(JVM_GetSystemPackages)(Thread* t) +{ + return reinterpret_cast(run(t, jvmGetSystemPackages, 0)); +} + +extern "C" AVIAN_EXPORT jobject JNICALL + EXPORT(JVM_AllocateNewObject)(Thread*, jobject, jclass, jclass) +{ + abort(); +} + +extern "C" AVIAN_EXPORT jobject JNICALL + EXPORT(JVM_AllocateNewArray)(Thread*, jobject, jclass, jint) +{ + abort(); +} + +extern "C" AVIAN_EXPORT jobject JNICALL + EXPORT(JVM_LatestUserDefinedLoader)(Thread* t) +{ + ENTER(t, Thread::ActiveState); + + class Visitor : public Processor::StackVisitor { + public: + Visitor(Thread* t) : t(t), loader(0) + { + } + + virtual bool visit(Processor::StackWalker* walker) + { + GcClassLoader* loader = walker->method()->class_()->loader(); + if (loader and loader != roots(t)->bootLoader() + and strcmp(objectClass(t, loader)->name()->body().begin(), + reinterpret_cast( + "sun/reflect/DelegatingClassLoader"))) { + this->loader = loader; + return false; + } else { + return true; + } + } + + Thread* t; + GcClassLoader* loader; + } v(t); + + t->m->processor->walkStack(t, &v); + + return makeLocalReference(t, v.loader); +} + +extern "C" AVIAN_EXPORT jclass JNICALL + EXPORT(JVM_LoadClass0)(Thread*, jobject, jclass, jstring) +{ + abort(); +} + +extern "C" AVIAN_EXPORT jint JNICALL + EXPORT(JVM_GetArrayLength)(Thread* t, jobject array) +{ + ENTER(t, Thread::ActiveState); + + return fieldAtOffset(*array, BytesPerWord); +} + +uint64_t jvmGetArrayElement(Thread* t, uintptr_t* arguments) +{ + jobject array = reinterpret_cast(arguments[0]); + jint index = arguments[1]; + + switch (objectClass(t, *array)->name()->body()[1]) { + case 'Z': + return reinterpret_cast(makeLocalReference( + t, makeBoolean(t, fieldAtOffset(*array, ArrayBody + index)))); + case 'B': + return reinterpret_cast(makeLocalReference( + t, makeByte(t, fieldAtOffset(*array, ArrayBody + index)))); + case 'C': + return reinterpret_cast(makeLocalReference( + t, + makeChar(t, fieldAtOffset(*array, ArrayBody + (index * 2))))); + case 'S': + return reinterpret_cast(makeLocalReference( + t, + makeShort(t, fieldAtOffset(*array, ArrayBody + (index * 2))))); + case 'I': + return reinterpret_cast(makeLocalReference( + t, + makeInt(t, fieldAtOffset(*array, ArrayBody + (index * 4))))); + case 'F': + return reinterpret_cast(makeLocalReference( + t, + makeFloat(t, fieldAtOffset(*array, ArrayBody + (index * 4))))); + case 'J': + return reinterpret_cast(makeLocalReference( + t, + makeLong(t, fieldAtOffset(*array, ArrayBody + (index * 8))))); + case 'D': + return reinterpret_cast(makeLocalReference( + t, + makeDouble(t, + fieldAtOffset(*array, ArrayBody + (index * 8))))); + case 'L': + case '[': + return reinterpret_cast(makeLocalReference( + t, fieldAtOffset(*array, ArrayBody + (index * BytesPerWord)))); + default: + abort(t); + } +} + +extern "C" AVIAN_EXPORT jobject JNICALL + EXPORT(JVM_GetArrayElement)(Thread* t, jobject array, jint index) +{ + uintptr_t arguments[] + = {reinterpret_cast(array), static_cast(index)}; + + return reinterpret_cast(run(t, jvmGetArrayElement, arguments)); +} + +extern "C" AVIAN_EXPORT jvalue JNICALL + EXPORT(JVM_GetPrimitiveArrayElement)(Thread*, jobject, jint, jint) +{ + abort(); +} + +extern "C" AVIAN_EXPORT void JNICALL EXPORT(JVM_SetArrayElement)(Thread* t, + jobject array, + jint index, + jobject value) +{ + ENTER(t, Thread::ActiveState); + + switch (objectClass(t, *array)->name()->body()[1]) { + case 'Z': + fieldAtOffset(*array, ArrayBody + index) + = cast(t, *value)->value(); + break; + case 'B': + fieldAtOffset(*array, ArrayBody + index) + = cast(t, *value)->value(); + break; + case 'C': + fieldAtOffset(*array, ArrayBody + (index * 2)) + = cast(t, *value)->value(); + break; + case 'S': + fieldAtOffset(*array, ArrayBody + (index * 2)) + = cast(t, *value)->value(); + break; + case 'I': + fieldAtOffset(*array, ArrayBody + (index * 4)) + = cast(t, *value)->value(); + break; + case 'F': + fieldAtOffset(*array, ArrayBody + (index * 4)) + = cast(t, *value)->value(); + break; + case 'J': + fieldAtOffset(*array, ArrayBody + (index * 8)) + = cast(t, *value)->value(); + break; + case 'D': + fieldAtOffset(*array, ArrayBody + (index * 8)) + = cast(t, *value)->value(); + break; + case 'L': + case '[': + setField( + t, *array, ArrayBody + (index * BytesPerWord), (value ? *value : 0)); + break; + default: + abort(t); + } +} + +extern "C" AVIAN_EXPORT void JNICALL EXPORT( + JVM_SetPrimitiveArrayElement)(Thread*, jobject, jint, jvalue, unsigned char) +{ + abort(); +} + +object makeNewArray(Thread* t, GcClass* c, unsigned length) +{ + if (c->vmFlags() & PrimitiveFlag) { + const char* name + = reinterpret_cast(local::getClassName(t, c)->body().begin()); + + switch (*name) { + case 'b': + if (name[1] == 'o') { + return makeBooleanArray(t, length); + } else { + return makeByteArray(t, length); + } + case 'c': + return makeCharArray(t, length); + case 'd': + return makeDoubleArray(t, length); + case 'f': + return makeFloatArray(t, length); + case 'i': + return makeIntArray(t, length); + case 'l': + return makeLongArray(t, length); + case 's': + return makeShortArray(t, length); + default: + abort(t); + } + } else { + return makeObjectArray(t, c, length); + } +} + +uint64_t jvmNewArray(Thread* t, uintptr_t* arguments) +{ + jclass elementClass = reinterpret_cast(arguments[0]); + jint length = arguments[1]; + + return reinterpret_cast(makeLocalReference( + t, makeNewArray(t, (*elementClass)->vmClass(), length))); +} + +extern "C" AVIAN_EXPORT jobject JNICALL + EXPORT(JVM_NewArray)(Thread* t, jclass elementClass, jint length) +{ + uintptr_t arguments[] = {reinterpret_cast(elementClass), + static_cast(length)}; + + return reinterpret_cast(run(t, jvmNewArray, arguments)); +} + +uint64_t jvmNewMultiArray(Thread* t, uintptr_t* arguments) +{ + jclass elementClass = reinterpret_cast(arguments[0]); + jintArray dimensions = reinterpret_cast(arguments[1]); + + THREAD_RUNTIME_ARRAY(t, int32_t, counts, (*dimensions)->length()); + for (int i = (*dimensions)->length() - 1; i >= 0; --i) { + RUNTIME_ARRAY_BODY(counts)[i] = (*dimensions)->body()[i]; + if (UNLIKELY(RUNTIME_ARRAY_BODY(counts)[i] < 0)) { + throwNew(t, + GcNegativeArraySizeException::Type, + "%d", + RUNTIME_ARRAY_BODY(counts)[i]); + return 0; + } + } + + object array = makeNewArray( + t, (*elementClass)->vmClass(), RUNTIME_ARRAY_BODY(counts)[0]); + PROTECT(t, array); + + populateMultiArray( + t, array, RUNTIME_ARRAY_BODY(counts), 0, (*dimensions)->length()); + + return reinterpret_cast(makeLocalReference(t, array)); +} + +extern "C" AVIAN_EXPORT jobject JNICALL + EXPORT(JVM_NewMultiArray)(Thread* t, + jclass elementClass, + jintArray dimensions) +{ + uintptr_t arguments[] = {reinterpret_cast(elementClass), + reinterpret_cast(dimensions)}; + + return reinterpret_cast(run(t, jvmNewMultiArray, arguments)); +} + +extern "C" AVIAN_EXPORT jclass JNICALL + EXPORT(JVM_GetCallerClass)(Thread* t, int target) +{ + ENTER(t, Thread::ActiveState); + + GcMethod* method = getCaller(t, target, true); + + return method ? reinterpret_cast( + makeLocalReference(t, getJClass(t, method->class_()))) + : 0; +} + +extern "C" AVIAN_EXPORT jclass JNICALL + EXPORT(JVM_FindPrimitiveClass)(Thread* t, const char* name) +{ + ENTER(t, Thread::ActiveState); + + switch (*name) { + case 'b': + if (name[1] == 'o') { + return reinterpret_cast( + makeLocalReference(t, getJClass(t, type(t, GcJboolean::Type)))); + } else { + return reinterpret_cast( + makeLocalReference(t, getJClass(t, type(t, GcJbyte::Type)))); + } + case 'c': + return reinterpret_cast( + makeLocalReference(t, getJClass(t, type(t, GcJchar::Type)))); + case 'd': + return reinterpret_cast( + makeLocalReference(t, getJClass(t, type(t, GcJdouble::Type)))); + case 'f': + return reinterpret_cast( + makeLocalReference(t, getJClass(t, type(t, GcJfloat::Type)))); + case 'i': + return reinterpret_cast( + makeLocalReference(t, getJClass(t, type(t, GcJint::Type)))); + case 'l': + return reinterpret_cast( + makeLocalReference(t, getJClass(t, type(t, GcJlong::Type)))); + case 's': + return reinterpret_cast( + makeLocalReference(t, getJClass(t, type(t, GcJshort::Type)))); + case 'v': + return reinterpret_cast( + makeLocalReference(t, getJClass(t, type(t, GcJvoid::Type)))); + default: + throwNew(t, GcIllegalArgumentException::Type); + } +} + +uint64_t jvmResolveClass(Thread* t, uintptr_t* arguments) +{ + jclass c = reinterpret_cast(arguments[0]); + + GcMethod* method = resolveMethod( + t, roots(t)->bootLoader(), "avian/Classes", "link", "(Lavian/VMClass;)V"); + + t->m->processor->invoke(t, method, 0, (*c)->vmClass()); + + return 1; +} + +extern "C" AVIAN_EXPORT void JNICALL + EXPORT(JVM_ResolveClass)(Thread* t, jclass c) +{ + uintptr_t arguments[] = {reinterpret_cast(c)}; + + run(t, jvmResolveClass, arguments); +} + +uint64_t jvmFindClassFromCaller(Thread* t, uintptr_t* arguments) +{ + const char* name = reinterpret_cast(arguments[0]); + jboolean init = arguments[1]; + jobject loader = reinterpret_cast(arguments[2]); + // jclass caller = reinterpret_cast(arguments[3]); + + /* XXX The caller's protection domain should be used during + the resolveClass but there is no specification or + unit-test in OpenJDK documenting the desired effect */ + + GcClass* c = resolveClass( + t, + loader ? cast(t, *loader) : roots(t)->bootLoader(), + name, + true, + static_cast(GcClassNotFoundException::Type)); + + if (init) { + PROTECT(t, c); + + initClass(t, c); + } + + return reinterpret_cast(makeLocalReference(t, getJClass(t, c))); +} + +extern "C" AVIAN_EXPORT jclass JNICALL + EXPORT(JVM_FindClassFromCaller)(Thread* t, + const char* name, + jboolean init, + jobject loader, + jclass caller) +{ + uintptr_t arguments[] = {reinterpret_cast(name), + init, + reinterpret_cast(loader), + reinterpret_cast(caller)}; + + return reinterpret_cast( + run(t, jvmFindClassFromCaller, arguments)); +} + +uint64_t jvmFindClassFromClassLoader(Thread* t, uintptr_t* arguments) +{ + const char* name = reinterpret_cast(arguments[0]); + jboolean init = arguments[1]; + jobject loader = reinterpret_cast(arguments[2]); + jboolean throwError = arguments[3]; + + GcClass* c = resolveClass( + t, + loader ? cast(t, *loader) : roots(t)->bootLoader(), + name, + true, + throwError ? static_cast(GcNoClassDefFoundError::Type) + : static_cast(GcClassNotFoundException::Type)); + + if (init) { + PROTECT(t, c); + + initClass(t, c); + } + + return reinterpret_cast(makeLocalReference(t, getJClass(t, c))); +} + +extern "C" AVIAN_EXPORT jclass JNICALL + EXPORT(JVM_FindClassFromClassLoader)(Thread* t, + const char* name, + jboolean init, + jobject loader, + jboolean throwError) +{ + uintptr_t arguments[] = {reinterpret_cast(name), + init, + reinterpret_cast(loader), + throwError}; + + return reinterpret_cast( + run(t, jvmFindClassFromClassLoader, arguments)); +} + +extern "C" AVIAN_EXPORT jclass JNICALL + JVM_FindClassFromBootLoader(Thread* t, const char* name) +{ + return EXPORT(JVM_FindClassFromClassLoader)(t, name, false, 0, false); +} + +extern "C" AVIAN_EXPORT jclass JNICALL + EXPORT(JVM_FindClassFromClass)(Thread*, const char*, jboolean, jclass) +{ + abort(); +} + +uint64_t jvmFindLoadedClass(Thread* t, uintptr_t* arguments) +{ + jobject loader = reinterpret_cast(arguments[0]); + jstring name = reinterpret_cast(arguments[1]); + + GcByteArray* spec = makeByteArray(t, (*name)->length(t) + 1); + + { + char* s = reinterpret_cast(spec->body().begin()); + stringChars(t, (*name), s); + replace('.', '/', s); + } + + GcClass* c = findLoadedClass(t, cast(t, *loader), spec); + + return reinterpret_cast(c ? makeLocalReference(t, getJClass(t, c)) + : 0); +} + +extern "C" AVIAN_EXPORT jclass JNICALL + EXPORT(JVM_FindLoadedClass)(Thread* t, jobject loader, jstring name) +{ + uintptr_t arguments[] = {reinterpret_cast(loader), + reinterpret_cast(name)}; + + return reinterpret_cast(run(t, jvmFindLoadedClass, arguments)); +} + +uint64_t jvmDefineClass(Thread* t, uintptr_t* arguments) +{ + jobject loader = reinterpret_cast(arguments[0]); + const uint8_t* data = reinterpret_cast(arguments[1]); + jsize length = arguments[2]; + + return reinterpret_cast(makeLocalReference( + t, + getJClass( + t, + cast( + t, + defineClass(t, cast(t, *loader), data, length))))); +} + +extern "C" AVIAN_EXPORT jclass JNICALL + EXPORT(JVM_DefineClass)(Thread* t, + const char*, + jobject loader, + const uint8_t* data, + jsize length, + jobject) +{ + uintptr_t arguments[] = {reinterpret_cast(loader), + reinterpret_cast(data), + static_cast(length)}; + + return reinterpret_cast(run(t, jvmDefineClass, arguments)); +} + +extern "C" AVIAN_EXPORT jclass JNICALL + EXPORT(JVM_DefineClassWithSource)(Thread* t, + const char*, + jobject loader, + const uint8_t* data, + jsize length, + jobject, + const char*) +{ + return EXPORT(JVM_DefineClass)(t, 0, loader, data, length, 0); +} + +extern "C" AVIAN_EXPORT jclass JNICALL + EXPORT(JVM_DefineClassWithSourceCond)(Thread* t, + const char*, + jobject loader, + const uint8_t* data, + jsize length, + jobject, + const char*, + jboolean) +{ + return EXPORT(JVM_DefineClass)(t, 0, loader, data, length, 0); +} + +extern "C" AVIAN_EXPORT jstring JNICALL + EXPORT(JVM_GetClassName)(Thread* t, jclass c) +{ + ENTER(t, Thread::ActiveState); + + return reinterpret_cast(makeLocalReference(t, (*c)->name())); +} + +uint64_t jvmGetClassInterfaces(Thread* t, uintptr_t* arguments) +{ + jclass c = reinterpret_cast(arguments[0]); + + GcClassAddendum* addendum = (*c)->vmClass()->addendum(); + if (addendum) { + GcArray* table = cast(t, addendum->interfaceTable()); + if (table) { + PROTECT(t, table); + + object array + = makeObjectArray(t, type(t, GcJclass::Type), table->length()); + PROTECT(t, array); + + for (unsigned i = 0; i < table->length(); ++i) { + object c = getJClass(t, cast(t, table->body()[i])); + setField(t, array, ArrayBody + (i * BytesPerWord), c); + } + + return reinterpret_cast(makeLocalReference(t, array)); + } + } + + return reinterpret_cast( + makeLocalReference(t, makeObjectArray(t, type(t, GcJclass::Type), 0))); +} + +extern "C" AVIAN_EXPORT jobjectArray JNICALL + EXPORT(JVM_GetClassInterfaces)(Thread* t, jclass c) +{ + uintptr_t arguments[] = {reinterpret_cast(c)}; + + return reinterpret_cast( + run(t, jvmGetClassInterfaces, arguments)); +} + +extern "C" AVIAN_EXPORT jobject JNICALL + EXPORT(JVM_GetClassLoader)(Thread* t, jclass c) +{ + ENTER(t, Thread::ActiveState); + + GcClassLoader* loader = (*c)->vmClass()->loader(); + + if (loader == roots(t)->bootLoader()) { + // sun.misc.Unsafe.getUnsafe expects a null result if the class + // loader is the boot classloader and will throw a + // SecurityException otherwise. + GcMethod* caller = getCaller(t, 2); + if (caller + and strcmp(reinterpret_cast( + caller->class_()->name()->body().begin()), + "sun/misc/Unsafe") == 0) { + return 0; + } else { + return makeLocalReference(t, roots(t)->bootLoader()); + } + } else { + return makeLocalReference(t, loader); + } +} + +extern "C" AVIAN_EXPORT jboolean JNICALL + EXPORT(JVM_IsInterface)(Thread* t, jclass c) +{ + ENTER(t, Thread::ActiveState); + + return ((*c)->vmClass()->flags() & ACC_INTERFACE) != 0; +} + +extern "C" AVIAN_EXPORT jobjectArray JNICALL + EXPORT(JVM_GetClassSigners)(Thread* t, jclass c) +{ + ENTER(t, Thread::ActiveState); + + GcClassRuntimeData* runtimeData + = getClassRuntimeDataIfExists(t, (*c)->vmClass()); + + return runtimeData ? reinterpret_cast( + makeLocalReference(t, runtimeData->signers())) + : 0; +} + +extern "C" AVIAN_EXPORT jbyteArray JNICALL + EXPORT(JVM_GetClassTypeAnnotations)(Thread*, jclass) +{ + abort(); +} + +extern "C" AVIAN_EXPORT jbyteArray JNICALL + EXPORT(JVM_GetFieldTypeAnnotations)(Thread*, jobject) +{ + abort(); +} + +extern "C" AVIAN_EXPORT jbyteArray JNICALL + EXPORT(JVM_GetMethodTypeAnnotations)(Thread*, jobject) +{ + abort(); +} + +extern "C" AVIAN_EXPORT void JNICALL + EXPORT(JVM_SetClassSigners)(Thread* t, jclass c, jobjectArray signers) +{ + ENTER(t, Thread::ActiveState); + + GcClassRuntimeData* runtimeData = getClassRuntimeData(t, (*c)->vmClass()); + + runtimeData->setSigners(t, reinterpret_cast(*signers)); +} + +uint64_t jvmGetProtectionDomain(Thread* t, uintptr_t* arguments) +{ + jclass c = reinterpret_cast(arguments[0]); + + GcMethod* method + = resolveMethod(t, + roots(t)->bootLoader(), + "avian/Classes", + "getProtectionDomain", + "(Lavian/VMClass;)Ljava/security/ProtectionDomain;"); + + return reinterpret_cast(makeLocalReference( + t, t->m->processor->invoke(t, method, 0, (*c)->vmClass()))); +} + +extern "C" AVIAN_EXPORT jobject JNICALL + EXPORT(JVM_GetProtectionDomain)(Thread* t, jclass c) +{ + uintptr_t arguments[] = {reinterpret_cast(c)}; + + return reinterpret_cast(run(t, jvmGetProtectionDomain, arguments)); +} + +extern "C" AVIAN_EXPORT jobject JNICALL + EXPORT(JVM_GetResourceLookupCacheURLs)(Thread*, jobject) +{ + return 0; +} + +extern "C" AVIAN_EXPORT void JNICALL + EXPORT(JVM_SetProtectionDomain)(Thread*, jclass, jobject) +{ + abort(); +} + +extern "C" AVIAN_EXPORT jboolean JNICALL + EXPORT(JVM_IsArrayClass)(Thread* t, jclass c) +{ + ENTER(t, Thread::ActiveState); + + return (*c)->vmClass()->arrayDimensions() != 0; +} + +extern "C" AVIAN_EXPORT jboolean JNICALL + EXPORT(JVM_IsPrimitiveClass)(Thread* t, jclass c) +{ + ENTER(t, Thread::ActiveState); + + return ((*c)->vmClass()->vmFlags() & PrimitiveFlag) != 0; +} + +uint64_t jvmGetComponentType(Thread* t, uintptr_t* arguments) +{ + jclass c = reinterpret_cast(arguments[0]); + + if ((*c)->vmClass()->arrayDimensions()) { + uint8_t n = (*c)->vmClass()->name()->body()[1]; + if (n != 'L' and n != '[') { + return reinterpret_cast( + makeLocalReference(t, getJClass(t, primitiveClass(t, n)))); + } else { + return reinterpret_cast(makeLocalReference( + t, getJClass(t, (*c)->vmClass()->arrayElementClass()))); + } + } else { + return 0; + } +} + +extern "C" AVIAN_EXPORT jclass JNICALL + EXPORT(JVM_GetComponentType)(Thread* t, jclass c) +{ + uintptr_t arguments[] = {reinterpret_cast(c)}; + + return reinterpret_cast(run(t, jvmGetComponentType, arguments)); +} + +uint64_t jvmGetClassModifiers(Thread* t, uintptr_t* arguments) +{ + return classModifiers( + t, + cast(t, *reinterpret_cast(arguments[0]))->vmClass()); +} + +extern "C" AVIAN_EXPORT jint JNICALL + EXPORT(JVM_GetClassModifiers)(Thread* t, jclass c) +{ + uintptr_t arguments[] = {reinterpret_cast(c)}; + + return run(t, jvmGetClassModifiers, arguments); +} + +uint64_t jvmGetDeclaredClasses(Thread* t, uintptr_t* arguments) +{ + return reinterpret_cast(makeLocalReference( + t, + getDeclaredClasses( + t, + cast(t, *reinterpret_cast(arguments[0])) + ->vmClass(), + false))); +} + +extern "C" AVIAN_EXPORT jobjectArray JNICALL + EXPORT(JVM_GetDeclaredClasses)(Thread* t, jclass c) +{ + uintptr_t arguments[] = {reinterpret_cast(c)}; + + return reinterpret_cast( + run(t, jvmGetDeclaredClasses, arguments)); +} + +uint64_t jvmGetDeclaringClass(Thread* t, uintptr_t* arguments) +{ + return reinterpret_cast(makeLocalReference( + t, + getDeclaringClass( + t, + cast(t, *reinterpret_cast(arguments[0])) + ->vmClass()))); +} + +extern "C" AVIAN_EXPORT jclass JNICALL + EXPORT(JVM_GetDeclaringClass)(Thread* t, jclass c) +{ + uintptr_t arguments[] = {reinterpret_cast(c)}; + + return reinterpret_cast(run(t, jvmGetDeclaringClass, arguments)); +} + +uint64_t jvmGetClassSignature(Thread* t, uintptr_t* arguments) +{ + jclass c = reinterpret_cast(arguments[0]); + + GcClassAddendum* addendum = (*c)->vmClass()->addendum(); + if (addendum) { + GcByteArray* signature = cast(t, addendum->signature()); + if (signature) { + return reinterpret_cast( + makeLocalReference(t, + t->m->classpath->makeString( + t, signature, 0, signature->length() - 1))); + } + } + return 0; +} + +extern "C" AVIAN_EXPORT jstring JNICALL + EXPORT(JVM_GetClassSignature)(Thread* t, jclass c) +{ + uintptr_t arguments[] = {reinterpret_cast(c)}; + + return reinterpret_cast(run(t, jvmGetClassSignature, arguments)); +} + +extern "C" AVIAN_EXPORT jbyteArray JNICALL + EXPORT(JVM_GetClassAnnotations)(Thread* t, jclass c) +{ + ENTER(t, Thread::ActiveState); + + GcClassAddendum* addendum = (*c)->vmClass()->addendum(); + return addendum ? reinterpret_cast( + makeLocalReference(t, addendum->annotationTable())) + : 0; +} + +uint64_t jvmGetClassDeclaredMethods(Thread* t, uintptr_t* arguments) +{ + jclass c = reinterpret_cast(arguments[0]); + jboolean publicOnly = arguments[1]; + + GcArray* table = cast(t, (*c)->vmClass()->methodTable()); + if (table) { + PROTECT(t, table); + + object array + = makeObjectArray(t, + type(t, GcJmethod::Type), + local::countMethods(t, (*c)->vmClass(), publicOnly)); + PROTECT(t, array); + + unsigned ai = 0; + for (unsigned i = 0, j = classDeclaredMethodCount(t, (*c)->vmClass()); + i < j; + ++i) { + GcMethod* vmMethod = cast(t, table->body()[i]); + PROTECT(t, vmMethod); + + if (((not publicOnly) or (vmMethod->flags() & ACC_PUBLIC)) + and vmMethod->name()->body()[0] != '<') { + object method = makeJmethod(t, vmMethod, i); + + assertT(t, ai < objectArrayLength(t, array)); + + setField(t, array, ArrayBody + ((ai++) * BytesPerWord), method); + } + } + + return reinterpret_cast(makeLocalReference(t, array)); + } else { + return reinterpret_cast( + makeLocalReference(t, makeObjectArray(t, type(t, GcJmethod::Type), 0))); + } +} + +extern "C" AVIAN_EXPORT jobjectArray JNICALL + EXPORT(JVM_GetClassDeclaredMethods)(Thread* t, + jclass c, + jboolean publicOnly) +{ + uintptr_t arguments[] = {reinterpret_cast(c), publicOnly}; + + return reinterpret_cast( + run(t, jvmGetClassDeclaredMethods, arguments)); +} + +uint64_t jvmGetClassDeclaredFields(Thread* t, uintptr_t* arguments) +{ + jclass c = reinterpret_cast(arguments[0]); + jboolean publicOnly = arguments[1]; + GcArray* table = cast(t, (*c)->vmClass()->fieldTable()); + if (table) { + PROTECT(t, table); + + object array + = makeObjectArray(t, + type(t, GcJfield::Type), + local::countFields(t, (*c)->vmClass(), publicOnly)); + PROTECT(t, array); + + unsigned ai = 0; + for (unsigned i = 0; i < table->length(); ++i) { + GcField* vmField = cast(t, table->body()[i]); + PROTECT(t, vmField); + + if ((not publicOnly) or (vmField->flags() & ACC_PUBLIC)) { + object field = makeJfield(t, vmField, i); + + assertT(t, ai < objectArrayLength(t, array)); + + setField(t, array, ArrayBody + ((ai++) * BytesPerWord), field); + } + } + assertT(t, ai == objectArrayLength(t, array)); + + return reinterpret_cast(makeLocalReference(t, array)); + } else { + return reinterpret_cast( + makeLocalReference(t, makeObjectArray(t, type(t, GcJfield::Type), 0))); + } +} + +extern "C" AVIAN_EXPORT jobjectArray JNICALL + EXPORT(JVM_GetClassDeclaredFields)(Thread* t, jclass c, jboolean publicOnly) +{ + uintptr_t arguments[] = {reinterpret_cast(c), publicOnly}; + + return reinterpret_cast( + run(t, jvmGetClassDeclaredFields, arguments)); +} + +uint64_t jvmGetClassDeclaredConstructors(Thread* t, uintptr_t* arguments) +{ + jclass c = reinterpret_cast(arguments[0]); + jboolean publicOnly = arguments[1]; + + GcArray* table = cast(t, (*c)->vmClass()->methodTable()); + if (table) { + PROTECT(t, table); + + object array = makeObjectArray( + t, + type(t, GcJconstructor::Type), + local::countConstructors(t, (*c)->vmClass(), publicOnly)); + PROTECT(t, array); + + unsigned ai = 0; + for (unsigned i = 0, j = classDeclaredMethodCount(t, (*c)->vmClass()); + i < j; + ++i) { + GcMethod* vmMethod = cast(t, table->body()[i]); + PROTECT(t, vmMethod); + + bool isCtor = strcmp(reinterpret_cast(vmMethod->name()->body().begin()), "") == 0; + if (((not publicOnly) or (vmMethod->flags() & ACC_PUBLIC)) and isCtor) { + object method = makeJconstructor(t, vmMethod, i); + + assertT(t, ai < objectArrayLength(t, array)); + + setField(t, array, ArrayBody + ((ai++) * BytesPerWord), method); + } + } + + return reinterpret_cast(makeLocalReference(t, array)); + } else { + return reinterpret_cast(makeLocalReference( + t, makeObjectArray(t, type(t, GcJconstructor::Type), 0))); + } +} + +extern "C" AVIAN_EXPORT jobjectArray JNICALL + EXPORT(JVM_GetClassDeclaredConstructors)(Thread* t, + jclass c, + jboolean publicOnly) +{ + uintptr_t arguments[] = {reinterpret_cast(c), publicOnly}; + + return reinterpret_cast( + run(t, jvmGetClassDeclaredConstructors, arguments)); +} + +extern "C" AVIAN_EXPORT jint JNICALL + EXPORT(JVM_GetClassAccessFlags)(Thread* t, jclass c) +{ + ENTER(t, Thread::ActiveState); + + return (*c)->vmClass()->flags(); +} + +uint64_t jvmInvokeMethod(Thread* t, uintptr_t* arguments) +{ + jobject method = reinterpret_cast(arguments[0]); + jobject instance = reinterpret_cast(arguments[1]); + jobjectArray args = reinterpret_cast(arguments[2]); + + GcMethod* vmMethod = cast( + t, + cast( + t, cast(t, *method)->clazz()->vmClass()->methodTable()) + ->body()[cast(t, *method)->slot()]); + + if (vmMethod->flags() & ACC_STATIC) { + instance = 0; + } + + if (instance and not instanceOf(t, vmMethod->class_(), *instance)) { + throwNew(t, GcIllegalArgumentException::Type); + } + + return reinterpret_cast( + makeLocalReference(t, + invoke(t, + vmMethod, + instance ? *instance : 0, + args ? reinterpret_cast(*args) : 0))); +} + +extern "C" AVIAN_EXPORT jobject JNICALL + EXPORT(JVM_InvokeMethod)(Thread* t, + jobject method, + jobject instance, + jobjectArray args) +{ + uintptr_t arguments[] = {reinterpret_cast(method), + reinterpret_cast(instance), + reinterpret_cast(args)}; + + return reinterpret_cast(run(t, jvmInvokeMethod, arguments)); +} + +uint64_t jvmNewInstanceFromConstructor(Thread* t, uintptr_t* arguments) +{ + jobject constructor = reinterpret_cast(arguments[0]); + jobjectArray args = reinterpret_cast(arguments[1]); + + object instance + = make(t, cast(t, *constructor)->clazz()->vmClass()); + PROTECT(t, instance); + + GcMethod* method = cast( + t, + cast(t, + cast(t, *constructor) + ->clazz() + ->vmClass() + ->methodTable()) + ->body()[cast(t, *constructor)->slot()]); + + invoke(t, method, instance, args ? reinterpret_cast(*args) : 0); + + return reinterpret_cast(makeLocalReference(t, instance)); +} + +extern "C" AVIAN_EXPORT jobject JNICALL + EXPORT(JVM_NewInstanceFromConstructor)(Thread* t, + jobject constructor, + jobjectArray args) +{ + uintptr_t arguments[] = {reinterpret_cast(constructor), + reinterpret_cast(args)}; + + return reinterpret_cast( + run(t, jvmNewInstanceFromConstructor, arguments)); +} + +extern "C" AVIAN_EXPORT jobject JNICALL + EXPORT(JVM_GetClassConstantPool)(Thread* t, jclass c) +{ + ENTER(t, Thread::ActiveState); + + GcClass* vmClass = (*c)->vmClass(); + GcClassAddendum* addendum = vmClass->addendum(); + object pool; + if (addendum) { + pool = addendum->pool(); + } else { + pool = 0; + } + + if (pool == 0) { + pool = getClassRuntimeData(t, vmClass)->pool(); + } + + return makeLocalReference(t, makeConstantPool(t, pool)); +} + +extern "C" AVIAN_EXPORT jint JNICALL + EXPORT(JVM_ConstantPoolGetSize)(Thread* t, jobject, jobject pool) +{ + if (pool == 0) + return 0; + + ENTER(t, Thread::ActiveState); + + return singletonCount(t, cast(t, *pool)); +} + +extern "C" AVIAN_EXPORT jclass JNICALL + EXPORT(JVM_ConstantPoolGetClassAt)(Thread*, jobject, jobject, jint) +{ + abort(); +} + +extern "C" AVIAN_EXPORT jclass JNICALL + EXPORT(JVM_ConstantPoolGetClassAtIfLoaded)(Thread*, jobject, jobject, jint) +{ + abort(); +} + +extern "C" AVIAN_EXPORT jobject JNICALL + EXPORT(JVM_ConstantPoolGetMethodAt)(Thread*, jobject, jobject, jint) +{ + abort(); +} + +extern "C" AVIAN_EXPORT jobject JNICALL + EXPORT(JVM_ConstantPoolGetMethodAtIfLoaded)(Thread*, jobject, jobject, jint) +{ + abort(); +} + +extern "C" AVIAN_EXPORT jobject JNICALL + EXPORT(JVM_ConstantPoolGetFieldAt)(Thread*, jobject, jobject, jint) +{ + abort(); +} + +extern "C" AVIAN_EXPORT jobject JNICALL + EXPORT(JVM_ConstantPoolGetFieldAtIfLoaded)(Thread*, jobject, jobject, jint) +{ + abort(); +} + +extern "C" AVIAN_EXPORT jobjectArray JNICALL + EXPORT(JVM_ConstantPoolGetMemberRefInfoAt)(Thread*, jobject, jobject, jint) +{ + abort(); +} + +extern "C" AVIAN_EXPORT jint JNICALL EXPORT( + JVM_ConstantPoolGetIntAt)(Thread* t, jobject, jobject pool, jint index) +{ + ENTER(t, Thread::ActiveState); + + return singletonValue(t, cast(t, *pool), index - 1); +} + +extern "C" AVIAN_EXPORT jlong JNICALL EXPORT( + JVM_ConstantPoolGetLongAt)(Thread* t, jobject, jobject pool, jint index) +{ + ENTER(t, Thread::ActiveState); + + uint64_t v; + memcpy(&v, &singletonValue(t, cast(t, *pool), index - 1), 8); + + return v; +} + +extern "C" AVIAN_EXPORT jfloat JNICALL EXPORT( + JVM_ConstantPoolGetFloatAt)(Thread* t, jobject, jobject pool, jint index) +{ + ENTER(t, Thread::ActiveState); + + return bitsToFloat(singletonValue(t, cast(t, *pool), index - 1)); +} + +extern "C" AVIAN_EXPORT jdouble JNICALL EXPORT( + JVM_ConstantPoolGetDoubleAt)(Thread* t, jobject, jobject pool, jint index) +{ + ENTER(t, Thread::ActiveState); + + double v; + memcpy(&v, &singletonValue(t, cast(t, *pool), index - 1), 8); + + return v; +} + +extern "C" AVIAN_EXPORT jstring JNICALL + EXPORT(JVM_ConstantPoolGetStringAt)(Thread*, jobject, jobject, jint) +{ + abort(); +} + +uint64_t jvmConstantPoolGetUTF8At(Thread* t, uintptr_t* arguments) +{ + jobject pool = reinterpret_cast(arguments[0]); + jint index = arguments[1]; + + object array = parseUtf8( + t, + cast( + t, singletonObject(t, cast(t, *pool), index - 1))); + + return reinterpret_cast(makeLocalReference( + t, + t->m->classpath->makeString( + t, array, 0, fieldAtOffset(array, BytesPerWord) - 1))); +} + +extern "C" AVIAN_EXPORT jstring JNICALL EXPORT( + JVM_ConstantPoolGetUTF8At)(Thread* t, jobject, jobject pool, jint index) +{ + uintptr_t arguments[] + = {reinterpret_cast(pool), static_cast(index)}; + + return reinterpret_cast(run(t, jvmConstantPoolGetUTF8At, arguments)); +} + +void maybeWrap(Thread* t, bool wrapException) +{ + if (t->exception and wrapException + and not(instanceOf(t, type(t, GcError::Type), t->exception) + or instanceOf( + t, type(t, GcRuntimeException::Type), t->exception))) { + GcThrowable* exception = t->exception; + t->exception = 0; + + PROTECT(t, exception); + + GcClass* paeClass = resolveClass( + t, roots(t)->bootLoader(), "java/security/PrivilegedActionException"); + PROTECT(t, paeClass); + + GcMethod* paeConstructor + = resolveMethod(t, paeClass, "", "(Ljava/lang/Exception;)V"); + PROTECT(t, paeConstructor); + + GcThrowable* result = cast(t, make(t, paeClass)); + PROTECT(t, result); + + t->m->processor->invoke(t, paeConstructor, result, exception); + + t->exception = result; + } +} + +uint64_t jvmDoPrivileged(Thread* t, uintptr_t* arguments) +{ + jobject action = reinterpret_cast(arguments[0]); + jboolean wrapException = arguments[1]; + + // todo: cache these class and method lookups in the t->m->classpath + // object: + + GcClass* privilegedAction = resolveClass( + t, roots(t)->bootLoader(), "java/security/PrivilegedAction"); + + GcMethod* method; + if (instanceOf(t, privilegedAction, *action)) { + method = resolveMethod(t, privilegedAction, "run", "()Ljava/lang/Object;"); + } else { + GcClass* privilegedExceptionAction = resolveClass( + t, roots(t)->bootLoader(), "java/security/PrivilegedExceptionAction"); + + method = resolveMethod( + t, privilegedExceptionAction, "run", "()Ljava/lang/Object;"); + } + + THREAD_RESOURCE(t, jboolean, wrapException, maybeWrap(t, wrapException)); + + return reinterpret_cast( + makeLocalReference(t, t->m->processor->invoke(t, method, *action))); +} + +extern "C" AVIAN_EXPORT jobject JNICALL + EXPORT(JVM_DoPrivileged)(Thread* t, + jclass, + jobject action, + jobject, + jboolean wrapException) +{ + uintptr_t arguments[] = {reinterpret_cast(action), wrapException}; + + return reinterpret_cast(run(t, jvmDoPrivileged, arguments)); +} + +extern "C" AVIAN_EXPORT jobject JNICALL + EXPORT(JVM_GetInheritedAccessControlContext)(Thread*, jclass) +{ + abort(); +} + +extern "C" AVIAN_EXPORT jobject JNICALL + EXPORT(JVM_GetStackAccessControlContext)(Thread*, jclass) +{ + return 0; +} + +extern "C" AVIAN_EXPORT void* JNICALL EXPORT(JVM_RegisterSignal)(jint, void*) +{ + abort(); +} + +extern "C" AVIAN_EXPORT jboolean JNICALL EXPORT(JVM_RaiseSignal)(jint) +{ + abort(); +} + +extern "C" AVIAN_EXPORT jint JNICALL EXPORT(JVM_FindSignal)(const char*) +{ + return -1; +} + +extern "C" AVIAN_EXPORT jboolean JNICALL + EXPORT(JVM_DesiredAssertionStatus)(Thread*, jclass, jclass) +{ + return false; +} + +extern "C" AVIAN_EXPORT jobject JNICALL + EXPORT(JVM_AssertionStatusDirectives)(Thread*, jclass) +{ + abort(); +} + +extern "C" AVIAN_EXPORT jboolean JNICALL EXPORT(JVM_SupportsCX8)() +{ + return true; +} + +extern "C" AVIAN_EXPORT const char* JNICALL + EXPORT(JVM_GetClassNameUTF)(Thread*, jclass) +{ + abort(); +} + +extern "C" AVIAN_EXPORT void JNICALL + EXPORT(JVM_GetClassCPTypes)(Thread*, jclass, unsigned char*) +{ + abort(); +} + +extern "C" AVIAN_EXPORT jint JNICALL + EXPORT(JVM_GetClassCPEntriesCount)(Thread*, jclass) +{ + abort(); +} + +extern "C" AVIAN_EXPORT jint JNICALL + EXPORT(JVM_GetClassFieldsCount)(Thread*, jclass) +{ + abort(); +} + +extern "C" AVIAN_EXPORT jint JNICALL + EXPORT(JVM_GetClassMethodsCount)(Thread*, jclass) +{ + abort(); +} + +extern "C" AVIAN_EXPORT void JNICALL EXPORT( + JVM_GetMethodIxExceptionIndexes)(Thread*, jclass, jint, unsigned short*) +{ + abort(); +} + +extern "C" AVIAN_EXPORT jint JNICALL + EXPORT(JVM_GetMethodIxExceptionsCount)(Thread*, jclass, jint) +{ + abort(); +} + +extern "C" AVIAN_EXPORT void JNICALL + EXPORT(JVM_GetMethodIxByteCode)(Thread*, jclass, jint, unsigned char*) +{ + abort(); +} + +extern "C" AVIAN_EXPORT jint JNICALL + EXPORT(JVM_GetMethodIxByteCodeLength)(Thread*, jclass, jint) +{ + abort(); +} + +extern "C" AVIAN_EXPORT void JNICALL EXPORT(JVM_GetMethodIxExceptionTableEntry)( + Thread*, + jclass, + jint, + jint, + local::JVM_ExceptionTableEntryType*) +{ + abort(); +} + +extern "C" AVIAN_EXPORT jint JNICALL + EXPORT(JVM_GetMethodIxExceptionTableLength)(Thread*, jclass, int) +{ + abort(); +} + +extern "C" AVIAN_EXPORT jint JNICALL + EXPORT(JVM_GetFieldIxModifiers)(Thread*, jclass, int) +{ + abort(); +} + +extern "C" AVIAN_EXPORT jint JNICALL + EXPORT(JVM_GetMethodIxModifiers)(Thread*, jclass, int) +{ + abort(); +} + +extern "C" AVIAN_EXPORT jint JNICALL + EXPORT(JVM_GetMethodIxLocalsCount)(Thread*, jclass, int) +{ + abort(); +} + +extern "C" AVIAN_EXPORT jint JNICALL + EXPORT(JVM_GetMethodIxArgsSize)(Thread*, jclass, int) +{ + abort(); +} + +extern "C" AVIAN_EXPORT jint JNICALL + EXPORT(JVM_GetMethodIxMaxStack)(Thread*, jclass, int) +{ + abort(); +} + +extern "C" AVIAN_EXPORT jboolean JNICALL + EXPORT(JVM_IsConstructorIx)(Thread*, jclass, int) +{ + abort(); +} + +extern "C" AVIAN_EXPORT jboolean JNICALL + EXPORT(JVM_IsVMGeneratedMethodIx)(Thread*, jclass, int) +{ + abort(); +} + +extern "C" AVIAN_EXPORT const char* JNICALL + EXPORT(JVM_GetMethodIxNameUTF)(Thread*, jclass, jint) +{ + abort(); +} + +extern "C" AVIAN_EXPORT const char* JNICALL + EXPORT(JVM_GetMethodIxSignatureUTF)(Thread*, jclass, jint) +{ + abort(); +} + +extern "C" AVIAN_EXPORT const char* JNICALL + EXPORT(JVM_GetCPFieldNameUTF)(Thread*, jclass, jint) +{ + abort(); +} + +extern "C" AVIAN_EXPORT const char* JNICALL + EXPORT(JVM_GetCPMethodNameUTF)(Thread*, jclass, jint) +{ + abort(); +} + +extern "C" AVIAN_EXPORT const char* JNICALL + EXPORT(JVM_GetCPMethodSignatureUTF)(Thread*, jclass, jint) +{ + abort(); +} + +extern "C" AVIAN_EXPORT const char* JNICALL + EXPORT(JVM_GetCPFieldSignatureUTF)(Thread*, jclass, jint) +{ + abort(); +} + +extern "C" AVIAN_EXPORT const char* JNICALL + EXPORT(JVM_GetCPClassNameUTF)(Thread*, jclass, jint) +{ + abort(); +} + +extern "C" AVIAN_EXPORT const char* JNICALL + EXPORT(JVM_GetCPFieldClassNameUTF)(Thread*, jclass, jint) +{ + abort(); +} + +extern "C" AVIAN_EXPORT const char* JNICALL + EXPORT(JVM_GetCPMethodClassNameUTF)(Thread*, jclass, jint) +{ + abort(); +} + +extern "C" AVIAN_EXPORT jint JNICALL + EXPORT(JVM_GetCPFieldModifiers)(Thread*, jclass, int, jclass) +{ + abort(); +} + +extern "C" AVIAN_EXPORT jint JNICALL + EXPORT(JVM_GetCPMethodModifiers)(Thread*, jclass, int, jclass) +{ + abort(); +} + +extern "C" AVIAN_EXPORT void JNICALL EXPORT(JVM_ReleaseUTF)(const char*) +{ + abort(); +} + +extern "C" AVIAN_EXPORT jboolean JNICALL + EXPORT(JVM_IsSameClassPackage)(Thread*, jclass, jclass) +{ + abort(); +} + +extern "C" AVIAN_EXPORT jint JNICALL + EXPORT(JVM_GetLastErrorString)(char* dst, int length) +{ + strncpy(dst, strerror(errno), length); + return strlen(dst); +} + +extern "C" AVIAN_EXPORT char* JNICALL EXPORT(JVM_NativePath)(char* path) +{ + return path; +} + +extern "C" AVIAN_EXPORT jint JNICALL + EXPORT(JVM_Open)(const char* path, jint flags, jint mode) +{ + int r = OPEN(path, flags & 0xFFFF, mode); + if (r == -1) { + return errno == EEXIST ? JVM_EEXIST : -1; + } else { + return r; + } +} + +extern "C" AVIAN_EXPORT jint JNICALL EXPORT(JVM_Close)(jint fd) +{ + return CLOSE(fd); +} + +extern "C" AVIAN_EXPORT jint JNICALL + EXPORT(JVM_Read)(jint fd, char* dst, jint length) +{ + return READ(fd, dst, length); +} + +extern "C" AVIAN_EXPORT jint JNICALL + EXPORT(JVM_Write)(jint fd, char* src, jint length) +{ + return WRITE(fd, src, length); +} + +extern "C" AVIAN_EXPORT jint JNICALL + EXPORT(JVM_Available)(jint fd, jlong* result) +{ + struct STAT buffer; + int n; + if (FSTAT(fd, &buffer) >= 0 + and (S_ISCHR(buffer.st_mode) or S_ISFIFO(buffer.st_mode) + or S_ISSOCK(buffer.st_mode)) and local::pipeAvailable(fd, &n)) { + *result = n; + return 1; + } + + int current = LSEEK(fd, 0, SEEK_CUR); + if (current == -1) + return 0; + + int end = LSEEK(fd, 0, SEEK_END); + if (end == -1) + return 0; + + if (LSEEK(fd, current, SEEK_SET) == -1) + return 0; + + *result = end - current; + return 1; +} + +extern "C" AVIAN_EXPORT jlong JNICALL + EXPORT(JVM_Lseek)(jint fd, jlong offset, jint seek) +{ + return LSEEK(fd, offset, seek); +} + +extern "C" AVIAN_EXPORT jint JNICALL + EXPORT(JVM_SetLength)(jint fd, jlong length) +{ +#ifdef PLATFORM_WINDOWS + HANDLE h = reinterpret_cast(_get_osfhandle(fd)); + if (h == INVALID_HANDLE_VALUE) { + errno = EBADF; + return -1; + } + + long high = length >> 32; + DWORD r = SetFilePointer(h, static_cast(length), &high, FILE_BEGIN); + if (r == 0xFFFFFFFF and GetLastError() != NO_ERROR) { + errno = EIO; + return -1; + } + + if (SetEndOfFile(h)) { + return 0; + } else { + errno = EIO; + return -1; + } +#else + return ftruncate(fd, length); +#endif +} + +extern "C" AVIAN_EXPORT jint JNICALL EXPORT(JVM_Sync)(jint fd) +{ +#ifdef PLATFORM_WINDOWS + HANDLE h = reinterpret_cast(_get_osfhandle(fd)); + if (h == INVALID_HANDLE_VALUE) { + errno = EBADF; + return -1; + } + + if (FlushFileBuffers(h)) { + return 0; + } else { + errno = EIO; + return -1; + } +#else + return fsync(fd); +#endif +} + +extern "C" AVIAN_EXPORT jint JNICALL EXPORT(JVM_InitializeSocketLibrary)() +{ +#ifdef PLATFORM_WINDOWS + static bool wsaInitialized = false; + if (not wsaInitialized) { + WSADATA data; + int r = WSAStartup(MAKEWORD(2, 2), &data); + if (r or LOBYTE(data.wVersion) != 2 or HIBYTE(data.wVersion) != 2) { + return -1; + } else { + wsaInitialized = true; + } + } +#endif + return 0; +} + +extern "C" AVIAN_EXPORT jint JNICALL + EXPORT(JVM_Socket)(jint domain, jint type, jint protocol) +{ + return socket(domain, type, protocol); +} + +extern "C" AVIAN_EXPORT jint JNICALL EXPORT(JVM_SocketClose)(jint socket) +{ +#ifdef PLATFORM_WINDOWS + return closesocket(socket); +#else + return close(socket); +#endif +} + +extern "C" AVIAN_EXPORT jint JNICALL + EXPORT(JVM_SocketShutdown)(jint socket, jint how) +{ + return shutdown(socket, how); +} + +extern "C" AVIAN_EXPORT jint JNICALL + EXPORT(JVM_Recv)(jint socket, char* dst, jint count, jint flags) +{ + return recv(socket, dst, count, flags); +} + +extern "C" AVIAN_EXPORT jint JNICALL + EXPORT(JVM_Send)(jint socket, char* src, jint count, jint flags) +{ + return send(socket, src, count, flags); +} + +extern "C" AVIAN_EXPORT jint JNICALL EXPORT(JVM_Timeout)(int, long) +{ + abort(); +} + +extern "C" AVIAN_EXPORT jint JNICALL EXPORT(JVM_Listen)(jint socket, jint count) +{ + return listen(socket, count); +} + +extern "C" AVIAN_EXPORT jint JNICALL + EXPORT(JVM_Connect)(jint socket, sockaddr* address, jint addressLength) +{ + return connect(socket, address, addressLength); +} + +extern "C" AVIAN_EXPORT jint JNICALL + EXPORT(JVM_Bind)(jint, struct sockaddr*, jint) +{ + abort(); +} + +extern "C" AVIAN_EXPORT jint JNICALL + EXPORT(JVM_Accept)(jint socket, + struct sockaddr* address, + jint* addressLength) +{ + socklen_t length = *addressLength; + int r = accept(socket, address, &length); + *addressLength = length; + return r; +} + +extern "C" AVIAN_EXPORT jint JNICALL + EXPORT(JVM_RecvFrom)(jint, char*, int, int, struct sockaddr*, int*) +{ + abort(); +} + +extern "C" AVIAN_EXPORT jint JNICALL + EXPORT(JVM_SendTo)(jint, char*, int, int, struct sockaddr*, int) +{ + abort(); +} + +extern "C" AVIAN_EXPORT jint JNICALL + EXPORT(JVM_SocketAvailable)(jint socket, jint* count) +{ +#ifdef PLATFORM_WINDOWS + unsigned long c = *count; + int r = ioctlsocket(socket, FIONREAD, &c); + *count = c; + return r; +#else + return ioctl(socket, FIONREAD, count) < 0 ? 0 : 1; +#endif +} + +extern "C" AVIAN_EXPORT jint JNICALL + EXPORT(JVM_GetSockName)(jint socket, + struct sockaddr* address, + int* addressLength) +{ + socklen_t length = *addressLength; + int r = getsockname(socket, address, &length); + *addressLength = length; + return r; +} + +extern "C" AVIAN_EXPORT jint JNICALL EXPORT(JVM_GetSockOpt)(jint socket, + int level, + int optionName, + char* optionValue, + int* optionLength) +{ + socklen_t length = *optionLength; + int rv = getsockopt(socket, level, optionName, optionValue, &length); + *optionLength = length; + return rv; +} + +extern "C" AVIAN_EXPORT jint JNICALL + EXPORT(JVM_SetSockOpt)(jint socket, + int level, + int optionName, + const char* optionValue, + int optionLength) +{ + return setsockopt(socket, level, optionName, optionValue, optionLength); +} + +extern "C" AVIAN_EXPORT struct protoent* JNICALL + EXPORT(JVM_GetProtoByName)(char*) +{ + abort(); +} + +extern "C" AVIAN_EXPORT struct hostent* JNICALL + EXPORT(JVM_GetHostByAddr)(const char*, int, int) +{ + abort(); +} + +extern "C" AVIAN_EXPORT struct hostent* JNICALL EXPORT(JVM_GetHostByName)(char*) +{ + abort(); +} + +extern "C" AVIAN_EXPORT int JNICALL + EXPORT(JVM_GetHostName)(char* name, int length) +{ + return gethostname(name, length); +} + +extern "C" AVIAN_EXPORT void* JNICALL EXPORT(JVM_RawMonitorCreate)(void) +{ + System* s = local::globalMachine->system; + System::Monitor* lock; + if (s->success(s->make(&lock))) { + return lock; + } else { + return 0; + } +} + +extern "C" AVIAN_EXPORT void JNICALL EXPORT(JVM_RawMonitorDestroy)(void* lock) +{ + static_cast(lock)->dispose(); +} + +extern "C" AVIAN_EXPORT jint JNICALL EXPORT(JVM_RawMonitorEnter)(void* lock) +{ + static_cast(lock) + ->acquire(static_cast(local::globalMachine->localThread->get()) + ->systemThread); + + return 0; +} + +extern "C" AVIAN_EXPORT void JNICALL EXPORT(JVM_RawMonitorExit)(void* lock) +{ + static_cast(lock) + ->release(static_cast(local::globalMachine->localThread->get()) + ->systemThread); +} + +int JNICALL GetVersion(Thread*) +{ + return JMM_VERSION_1_0; +} + +uint64_t getInputArgumentArray(Thread* t, uintptr_t*) +{ + object array + = makeObjectArray(t, type(t, GcString::Type), t->m->argumentCount); + PROTECT(t, array); + + for (unsigned i = 0; i < t->m->argumentCount; ++i) { + GcString* argument = makeString(t, t->m->arguments[i]); + setField(t, array, ArrayBody + (i * BytesPerWord), argument); + } + + return reinterpret_cast(makeLocalReference(t, array)); +} + +jobjectArray JNICALL GetInputArgumentArray(Thread* t) +{ + return reinterpret_cast(run(t, getInputArgumentArray, 0)); +} + +jint JNICALL GetOptionalSupport(Thread*, jmmOptionalSupport* support) +{ + memset(support, 0, sizeof(jmmOptionalSupport)); + return 0; +} + +jlong JNICALL GetLongAttribute(Thread* t, jobject, jmmLongAttribute attribute) +{ + const unsigned JMM_JVM_INIT_DONE_TIME_MS = 7; + + switch (attribute) { + case JMM_JVM_INIT_DONE_TIME_MS: + return 0; + + default: + abort(t); + } +} + +jboolean JNICALL GetBoolAttribute(Thread* t, jmmBoolAttribute attribute) +{ + const unsigned JMM_THREAD_CPU_TIME = 24; + const unsigned JMM_THREAD_ALLOCATED_MEMORY = 25; + + switch (attribute) { + case JMM_THREAD_CPU_TIME: + case JMM_THREAD_ALLOCATED_MEMORY: + return false; + + default: + abort(t); + } +} + +uint64_t getMemoryManagers(Thread* t, uintptr_t*) +{ + return reinterpret_cast(makeLocalReference( + t, + makeObjectArray(t, + resolveClass(t, + roots(t)->bootLoader(), + "java/lang/management/MemoryManagerMXBean"), + 0))); +} + +jobjectArray JNICALL GetMemoryManagers(Thread* t, jobject) +{ + return reinterpret_cast(run(t, getMemoryManagers, 0)); +} + +uint64_t getMemoryPools(Thread* t, uintptr_t*) +{ + return reinterpret_cast(makeLocalReference( + t, + makeObjectArray(t, + resolveClass(t, + roots(t)->bootLoader(), + "java/lang/management/MemoryPoolMXBean"), + 0))); +} + +jobjectArray JNICALL GetMemoryPools(Thread* t, jobject) +{ + return reinterpret_cast(run(t, getMemoryPools, 0)); +} + +extern "C" AVIAN_EXPORT void* JNICALL EXPORT(JVM_GetManagement)(jint version) +{ + if (version == JMM_VERSION_1_0) { + JmmInterface* interface = &(static_cast( + local::globalMachine->classpath) + ->jmmInterface); + + memset(interface, 0, sizeof(JmmInterface)); + + interface->GetVersion = GetVersion; + interface->GetOptionalSupport = GetOptionalSupport; + interface->GetLongAttribute = GetLongAttribute; + interface->GetBoolAttribute = GetBoolAttribute; + interface->GetMemoryManagers = GetMemoryManagers; + interface->GetMemoryPools = GetMemoryPools; + interface->GetInputArgumentArray = GetInputArgumentArray; + + return interface; + } else { + return 0; + } +} + +extern "C" AVIAN_EXPORT jobject JNICALL + EXPORT(JVM_InitAgentProperties)(Thread*, jobject) +{ + abort(); +} + +uint64_t getEnclosingMethodInfo(Thread* t, uintptr_t* arguments) +{ + jclass c = reinterpret_cast(arguments[0]); + GcClass* class_ = (*c)->vmClass(); + PROTECT(t, class_); + + GcClassAddendum* addendum = class_->addendum(); + if (addendum) { + object enclosingClass = addendum->enclosingClass(); + if (enclosingClass) { + PROTECT(t, enclosingClass); + + object array = makeObjectArray(t, type(t, GcJobject::Type), 3); + PROTECT(t, array); + + enclosingClass = getJClass( + t, + resolveClass( + t, class_->loader(), cast(t, enclosingClass))); + + setField(t, array, ArrayBody, enclosingClass); + + GcPair* enclosingMethod = cast(t, addendum->enclosingMethod()); + + if (enclosingMethod) { + PROTECT(t, enclosingMethod); + + GcString* name = t->m->classpath->makeString( + t, + enclosingMethod->first(), + 0, + cast(t, enclosingMethod->first())->length() - 1); + + setField(t, array, ArrayBody + BytesPerWord, name); + + GcString* spec = t->m->classpath->makeString( + t, + enclosingMethod->second(), + 0, + cast(t, enclosingMethod->second())->length() - 1); + + setField(t, array, ArrayBody + (2 * BytesPerWord), spec); + } + + return reinterpret_cast(makeLocalReference(t, array)); + } + } + return 0; +} + +extern "C" AVIAN_EXPORT jobjectArray JNICALL + EXPORT(JVM_GetEnclosingMethodInfo)(Thread* t, jclass c) +{ + uintptr_t arguments[] = {reinterpret_cast(c)}; + + return reinterpret_cast( + run(t, getEnclosingMethodInfo, arguments)); +} + +extern "C" AVIAN_EXPORT jintArray JNICALL + EXPORT(JVM_GetThreadStateValues)(JNIEnv*, jint) +{ + abort(); +} + +extern "C" AVIAN_EXPORT jobjectArray JNICALL + EXPORT(JVM_GetThreadStateNames)(JNIEnv*, jint, jintArray) +{ + abort(); +} + +extern "C" AVIAN_EXPORT void JNICALL + EXPORT(JVM_GetVersionInfo)(JNIEnv*, + local::jvm_version_info* info, + size_t size) +{ + memset(info, 0, size); + info->jvm_version = 0x01070000; +} + +extern "C" AVIAN_EXPORT jboolean JNICALL + EXPORT(JVM_CX8Field)(JNIEnv*, jobject*, jfieldID*, jlong, jlong) +{ + abort(); +} + +extern "C" AVIAN_EXPORT void JNICALL + EXPORT(JVM_SetNativeThreadName)(JNIEnv*, jobject, jstring) +{ + abort(); +} + +} // namespace local + +} // namespace + +extern "C" AVIAN_EXPORT int jio_vsnprintf(char* dst, + size_t size, + const char* format, + va_list a) +{ + return vm::vsnprintf(dst, size, format, a); +} + +extern "C" AVIAN_EXPORT int jio_vfprintf(FILE* stream, + const char* format, + va_list a) +{ + return vfprintf(stream, format, a); +} + +#ifdef PLATFORM_WINDOWS +extern "C" AVIAN_EXPORT void* JNICALL EXPORT(JVM_GetThreadInterruptEvent)() +{ + // hack: We don't want to expose thread interruption implementation + // details, so we give the class library a fake event to play with. + // This means that threads won't be interruptable when blocked in + // Process.waitFor. + static HANDLE fake = 0; + if (fake == 0) { + fake = CreateEvent(0, true, false, 0); + } + return fake; +} + +namespace { +HMODULE jvmHandle = 0; +} + +extern "C" int JDK_InitJvmHandle() +{ + jvmHandle = GetModuleHandle(0); + return jvmHandle != 0; +} + +extern "C" void* JDK_FindJvmEntry(const char* name) +{ + return voidPointer(GetProcAddress(jvmHandle, name)); +} + +extern "C" HMODULE JDK_LoadSystemLibrary(const char* name) { + HMODULE handle; + char path[MAX_PATH]; + + if (GetSystemDirectory(path, sizeof(path)) != 0) { + strcat(path, "\\"); + strcat(path, name); + handle = LoadLibrary(path); + } else { + handle = nullptr; + } + + if (handle == nullptr) { + if (GetWindowsDirectory(path, sizeof(path)) != 0) { + strcat(path, "\\"); + strcat(path, name); + handle = LoadLibrary(path); + } + } + return handle; +} + +#ifdef AVIAN_OPENJDK_SRC + +extern "C" char* findJavaTZ_md(const char*, const char*); + +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_java_util_TimeZone_getSystemTimeZoneID(Thread* t, + object, + uintptr_t* arguments) +{ + // On Windows, findJavaTZ_md loads tzmappings from the filesystem + // using fopen, so we have no opportunity to make it read straight + // from the embedded JAR file as with files read from Java code. + // Therefore, we must extract tzmappings to a temporary location + // before calling findJavaTZ_md. We could avoid this by + // implementing findJavaTZ_md ourselves from scratch, but that would + // be a lot of code to implement and maintain. + + GcString* country = cast(t, reinterpret_cast(arguments[1])); + + THREAD_RUNTIME_ARRAY(t, char, countryChars, country->length(t) + 1); + stringChars(t, country, RUNTIME_ARRAY_BODY(countryChars)); + + local::MyClasspath* cp = static_cast(t->m->classpath); + + local::EmbeddedFile ef(cp, cp->tzMappings, cp->tzMappingsLength); + if (ef.jar == 0 or ef.jarLength == 0 or ef.pathLength == 0) { + return 0; + } + + Finder* finder = getFinder(t, ef.jar, ef.jarLength); + if (finder == 0) { + return 0; + } + + System::Region* r = finder->find(ef.path); + if (r == 0) { + return 0; + } + + THREAD_RESOURCE(t, System::Region*, r, r->dispose()); + + char tmpPath[MAX_PATH + 1]; + GetTempPathA(MAX_PATH, tmpPath); + + char tmpDir[MAX_PATH + 1]; + vm::snprintf(tmpDir, MAX_PATH, "%s/avian-tmp", tmpPath); + if (_mkdir(tmpDir) != 0 and errno != EEXIST) { + return 0; + } + + THREAD_RESOURCE(t, char*, tmpDir, rmdir(tmpDir)); + + char libDir[MAX_PATH + 1]; + vm::snprintf(libDir, MAX_PATH, "%s/lib", tmpDir); + if (mkdir(libDir) != 0 and errno != EEXIST) { + return 0; + } + + THREAD_RESOURCE(t, char*, libDir, rmdir(libDir)); + + char file[MAX_PATH + 1]; + vm::snprintf(file, MAX_PATH, "%s/tzmappings", libDir); + FILE* out = vm::fopen(file, "wb"); + if (out == 0) { + return 0; + } + + THREAD_RESOURCE(t, char*, file, unlink(file)); + THREAD_RESOURCE(t, FILE*, out, fclose(out)); + + if (fwrite(r->start(), 1, r->length(), out) != r->length() + or fflush(out) != 0) { + return 0; + } + + char* javaTZ = findJavaTZ_md(tmpDir, RUNTIME_ARRAY_BODY(countryChars)); + if (javaTZ) { + THREAD_RESOURCE(t, char*, javaTZ, free(javaTZ)); + + return reinterpret_cast(makeString(t, "%s", javaTZ)); + } else { + return 0; + } +} +#else // not AVIAN_OPENJDK_SRC +extern "C" AVIAN_EXPORT int jio_snprintf(char* dst, + size_t size, + const char* format, + ...) +{ + va_list a; + va_start(a, format); + + int r = jio_vsnprintf(dst, size, format, a); + + va_end(a); + + return r; +} + +extern "C" AVIAN_EXPORT int jio_fprintf(FILE* stream, const char* format, ...) +{ + va_list a; + va_start(a, format); + + int r = jio_vfprintf(stream, format, a); + + va_end(a); + + return r; +} +#endif // not AVIAN_OPENJDK_SRC +#endif // PLATFORM_WINDOWS diff --git a/sgx-jvm/avian/src/codegen/CMakeLists.txt b/sgx-jvm/avian/src/codegen/CMakeLists.txt new file mode 100644 index 0000000000..001a8681d3 --- /dev/null +++ b/sgx-jvm/avian/src/codegen/CMakeLists.txt @@ -0,0 +1,18 @@ +add_library (avian_codegen + compiler.cpp + runtime.cpp + targets.cpp + + compiler/context.cpp + compiler/event.cpp + compiler/frame.cpp + compiler/ir.cpp + compiler/promise.cpp + compiler/read.cpp + compiler/regalloc.cpp + compiler/resource.cpp + compiler/site.cpp + compiler/value.cpp +) + +add_subdirectory(target) diff --git a/sgx-jvm/avian/src/codegen/compiler.cpp b/sgx-jvm/avian/src/codegen/compiler.cpp new file mode 100644 index 0000000000..24ac8c9239 --- /dev/null +++ b/sgx-jvm/avian/src/codegen/compiler.cpp @@ -0,0 +1,2964 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#include "avian/target.h" + +#include + +#include +#include +#include +#include + +#include "codegen/compiler/regalloc.h" +#include "codegen/compiler/context.h" +#include "codegen/compiler/resource.h" +#include "codegen/compiler/value.h" +#include "codegen/compiler/site.h" +#include "codegen/compiler/read.h" +#include "codegen/compiler/event.h" +#include "codegen/compiler/promise.h" +#include "codegen/compiler/frame.h" +#include "codegen/compiler/ir.h" + +using namespace vm; + +namespace avian { +namespace codegen { +namespace compiler { + +const bool DebugAppend = false; +const bool DebugCompile = false; +const bool DebugResources = false; +const bool DebugFrame = false; +const bool DebugControl = false; +const bool DebugBuddies = false; + +const unsigned StealRegisterReserveCount = 2; + +// this should be equal to the largest number of registers used by a +// compare instruction: +const unsigned ResolveRegisterReserveCount = (TargetBytesPerWord == 8 ? 2 : 4); + +void apply(Context* c, + lir::UnaryOperation op, + unsigned s1Size, + Site* s1Low, + Site* s1High); + +void apply(Context* c, + lir::BinaryOperation op, + unsigned s1Size, + Site* s1Low, + Site* s1High, + unsigned s2Size, + Site* s2Low, + Site* s2High); + +void apply(Context* c, + lir::TernaryOperation op, + unsigned s1Size, + Site* s1Low, + Site* s1High, + unsigned s2Size, + Site* s2Low, + Site* s2High, + unsigned s3Size, + Site* s3Low, + Site* s3High); + +class ConstantPoolNode { + public: + ConstantPoolNode(Promise* promise) : promise(promise), next(0) + { + } + + Promise* promise; + ConstantPoolNode* next; +}; + +Read* live(Context* c UNUSED, Value* v) +{ + assertT(c, v->buddy->hasBuddy(c, v)); + + Value* p = v; + do { + if (valid(p->reads)) { + return p->reads; + } + p = p->buddy; + } while (p != v); + + return 0; +} + +unsigned sitesToString(Context* c, Value* v, char* buffer, unsigned size); + +void deadWord(Context* c, Value* v) +{ + Value* nextWord = v->nextWord; + assertT(c, nextWord != v); + + for (SiteIterator it(c, v, true, false); it.hasMore();) { + Site* s = it.next(); + + if (s->registerSize(c) > TargetBytesPerWord) { + it.remove(c); + nextWord->addSite(c, s); + } + } +} + +void deadBuddy(Context* c, Value* v, Read* r UNUSED) +{ + assertT(c, v->buddy != v); + assertT(c, r); + + if (DebugBuddies) { + fprintf(stderr, "remove dead buddy %p from", v); + for (Value* p = v->buddy; p != v; p = p->buddy) { + fprintf(stderr, " %p", p); + } + fprintf(stderr, "\n"); + } + + assertT(c, v->buddy); + + Value* next = v->buddy; + v->buddy = v; + Value* p = next; + while (p->buddy != v) + p = p->buddy; + p->buddy = next; + + assertT(c, p->buddy); + + for (SiteIterator it(c, v, false, false); it.hasMore();) { + Site* s = it.next(); + it.remove(c); + + next->addSite(c, s); + } +} + +void popRead(Context* c, Event* e UNUSED, Value* v) +{ + assertT(c, e == v->reads->event); + + if (DebugReads) { + fprintf(stderr, + "pop read %p from %p next %p event %p (%s)\n", + v->reads, + v, + v->reads->next(c), + e, + (e ? e->name() : 0)); + } + + v->reads = v->reads->next(c); + + if (not valid(v->reads)) { + Value* nextWord = v->nextWord; + if (nextWord != v) { + if (valid(nextWord->reads)) { + deadWord(c, v); + } else { + deadWord(c, nextWord); + } + } + + Read* r = live(c, v); + if (r) { + deadBuddy(c, v, r); + } else { + v->clearSites(c); + } + } +} + +void addBuddy(Value* original, Value* buddy) +{ + buddy->buddy = original; + Value* p = original; + while (p->buddy != original) + p = p->buddy; + p->buddy = buddy; + + if (DebugBuddies) { + fprintf(stderr, "add buddy %p to", buddy); + for (Value* p = buddy->buddy; p != buddy; p = p->buddy) { + fprintf(stderr, " %p", p); + } + fprintf(stderr, "\n"); + } +} + +void move(Context* c, Value* value, Site* src, Site* dst); + +unsigned sitesToString(Context* c, Site* sites, char* buffer, unsigned size) +{ + unsigned total = 0; + for (Site* s = sites; s; s = s->next) { + total += s->toString(c, buffer + total, size - total); + + if (s->next) { + assertT(c, size > total + 2); + memcpy(buffer + total, ", ", 2); + total += 2; + } + } + + assertT(c, size > total); + buffer[total] = 0; + + return total; +} + +unsigned sitesToString(Context* c, Value* v, char* buffer, unsigned size) +{ + unsigned total = 0; + Value* p = v; + do { + if (total) { + assertT(c, size > total + 2); + memcpy(buffer + total, "; ", 2); + total += 2; + } + + if (p->sites) { + total += vm::snprintf(buffer + total, size - total, "%p has ", p); + total += sitesToString(c, p->sites, buffer + total, size - total); + } else { + total += vm::snprintf(buffer + total, size - total, "%p has nothing", p); + } + + p = p->buddy; + } while (p != v); + + return total; +} + +Site* pickTargetSite(Context* c, + Read* read, + bool intersectRead = false, + unsigned registerReserveCount = 0, + CostCalculator* costCalculator = 0) +{ + Target target( + pickTarget(c, read, intersectRead, registerReserveCount, costCalculator)); + + expect(c, target.cost < Target::Impossible); + + if (target.type == lir::Operand::Type::Memory) { + return frameSite(c, target.index); + } else { + return registerSite(c, Register(target.index)); + } +} + +bool acceptMatch(Context* c, Site* s, Read*, const SiteMask& mask) +{ + return s->match(c, mask); +} + +Site* pickSourceSite(Context* c, + Read* read, + Site* target = 0, + unsigned* cost = 0, + SiteMask* extraMask = 0, + bool intersectRead = true, + bool includeBuddies = true, + bool includeNextWord = true, + bool (*accept)(Context*, Site*, Read*, const SiteMask&) + = acceptMatch) +{ + SiteMask mask; + + if (extraMask) { + mask = mask.intersectionWith(*extraMask); + } + + if (intersectRead) { + read->intersect(&mask); + } + + Site* site = 0; + unsigned copyCost = 0xFFFFFFFF; + for (SiteIterator it(c, read->value, includeBuddies, includeNextWord); + it.hasMore();) { + Site* s = it.next(); + if (accept(c, s, read, mask)) { + unsigned v = s->copyCost(c, target); + if (v < copyCost) { + site = s; + copyCost = v; + } + } + } + + if (DebugMoves and site and target) { + char srcb[256]; + site->toString(c, srcb, 256); + char dstb[256]; + target->toString(c, dstb, 256); + fprintf(stderr, + "pick source %s to %s for %p cost %d\n", + srcb, + dstb, + read->value, + copyCost); + } + + if (cost) + *cost = copyCost; + return site; +} + +Site* maybeMove(Context* c, + Read* read, + bool intersectRead, + bool includeNextWord, + unsigned registerReserveCount = 0) +{ + Value* value = read->value; + unsigned size = value == value->nextWord ? TargetBytesPerWord : 8; + + class MyCostCalculator : public CostCalculator { + public: + MyCostCalculator(Value* value, unsigned size, bool includeNextWord) + : value(value), size(size), includeNextWord(includeNextWord) + { + } + + virtual unsigned cost(Context* c, SiteMask dstMask) + { + OperandMask src; + OperandMask tmp; + c->arch->planMove( + size, src, tmp, OperandMask(dstMask.typeMask, dstMask.registerMask, 0)); + + SiteMask srcMask = SiteMask::lowPart(src); + for (SiteIterator it(c, value, true, includeNextWord); it.hasMore();) { + Site* s = it.next(); + if (s->match(c, srcMask) or s->match(c, dstMask)) { + return 0; + } + } + + return Target::IndirectMovePenalty; + } + + Value* value; + unsigned size; + bool includeNextWord; + } costCalculator(value, size, includeNextWord); + + Site* dstSite = pickTargetSite( + c, read, intersectRead, registerReserveCount, &costCalculator); + + OperandMask src; + OperandMask tmp; + c->arch->planMove( + size, + src, + tmp, + OperandMask(1 << (unsigned)dstSite->type(c), dstSite->registerMask(c), 0)); + + SiteMask srcMask = SiteMask::lowPart(src); + unsigned cost = 0xFFFFFFFF; + Site* srcSite = 0; + for (SiteIterator it(c, value, true, includeNextWord); it.hasMore();) { + Site* s = it.next(); + unsigned v = s->copyCost(c, dstSite); + if (v == 0) { + srcSite = s; + cost = 0; + break; + } + if (not s->match(c, srcMask)) { + v += CopyPenalty; + } + if (v < cost) { + srcSite = s; + cost = v; + } + } + + if (cost) { + if (DebugMoves) { + char srcb[256]; + srcSite->toString(c, srcb, 256); + char dstb[256]; + dstSite->toString(c, dstb, 256); + fprintf(stderr, + "maybe move %s to %s for %p to %p\n", + srcb, + dstb, + value, + value); + } + + srcSite->freeze(c, value); + + value->addSite(c, dstSite); + + srcSite->thaw(c, value); + + if (not srcSite->match(c, srcMask)) { + srcSite->freeze(c, value); + dstSite->freeze(c, value); + + SiteMask tmpMask = SiteMask::lowPart(tmp); + SingleRead tmpRead(tmpMask, 0); + tmpRead.value = value; + tmpRead.successor_ = value; + + Site* tmpSite = pickTargetSite(c, &tmpRead, true); + + value->addSite(c, tmpSite); + + move(c, value, srcSite, tmpSite); + + dstSite->thaw(c, value); + srcSite->thaw(c, value); + + srcSite = tmpSite; + } + + move(c, value, srcSite, dstSite); + } + + return dstSite; +} + +Site* maybeMove(Context* c, + Value* v, + const SiteMask& mask, + bool intersectMask, + bool includeNextWord, + unsigned registerReserveCount = 0) +{ + SingleRead read(mask, 0); + read.value = v; + read.successor_ = v; + + return maybeMove( + c, &read, intersectMask, includeNextWord, registerReserveCount); +} + +Site* pickSiteOrMove(Context* c, + Read* read, + bool intersectRead, + bool includeNextWord, + unsigned registerReserveCount = 0) +{ + Site* s + = pickSourceSite(c, read, 0, 0, 0, intersectRead, true, includeNextWord); + + if (s) { + return s; + } else { + return maybeMove( + c, read, intersectRead, includeNextWord, registerReserveCount); + } +} + +Site* pickSiteOrMove(Context* c, + Value* v, + const SiteMask& mask, + bool intersectMask, + bool includeNextWord, + unsigned registerReserveCount = 0) +{ + SingleRead read(mask, 0); + read.value = v; + read.successor_ = v; + + return pickSiteOrMove( + c, &read, intersectMask, includeNextWord, registerReserveCount); +} + +void steal(Context* c, Resource* r, Value* thief) +{ + if (DebugResources) { + char resourceBuffer[256]; + r->toString(c, resourceBuffer, 256); + char siteBuffer[1024]; + sitesToString(c, r->value, siteBuffer, 1024); + fprintf(stderr, + "%p steal %s from %p (%s)\n", + thief, + resourceBuffer, + r->value, + siteBuffer); + } + + if ((not(thief and thief->isBuddyOf(r->value)) + and r->value->uniqueSite(c, r->site))) { + r->site->freeze(c, r->value); + + maybeMove(c, live(c, r->value), false, true, StealRegisterReserveCount); + + r->site->thaw(c, r->value); + } + + r->value->removeSite(c, r->site); +} + +SiteMask generalRegisterMask(Context* c) +{ + return SiteMask(lir::Operand::RegisterPairMask, + c->regFile->generalRegisters, + NoFrameIndex); +} + +SiteMask generalRegisterOrConstantMask(Context* c) +{ + return SiteMask(lir::Operand::RegisterPairMask | lir::Operand::ConstantMask, + c->regFile->generalRegisters, + NoFrameIndex); +} + +MultiRead* multiRead(Context* c) +{ + return new (c->zone) MultiRead; +} + +StubRead* stubRead(Context* c) +{ + return new (c->zone) StubRead; +} + +Site* pickSite(Context* c, + Value* v, + Site* s, + unsigned index, + bool includeNextWord) +{ + for (SiteIterator it(c, v, true, includeNextWord); it.hasMore();) { + Site* candidate = it.next(); + if (s->matchNextWord(c, candidate, index)) { + return candidate; + } + } + + return 0; +} + +Site* pickSiteOrMove(Context* c, Value* v, Site* s, unsigned index) +{ + Site* n = pickSite(c, v, s, index, false); + if (n) { + return n; + } + + return maybeMove(c, v, s->nextWordMask(c, index), true, false); +} + +Site* pickSiteOrMove(Context* c, Value* v, Site* s, Site** low, Site** high) +{ + if (v->wordIndex == 0) { + *low = s; + *high = pickSiteOrMove(c, v->nextWord, s, 1); + return *high; + } else { + *low = pickSiteOrMove(c, v->nextWord, s, 0); + *high = s; + return *low; + } +} + +Site* pickSiteOrGrow(Context* c, Value* v, Site* s, unsigned index) +{ + Site* n = pickSite(c, v, s, index, false); + if (n) { + return n; + } + + n = s->makeNextWord(c, index); + v->addSite(c, n); + return n; +} + +Site* pickSiteOrGrow(Context* c, Value* v, Site* s, Site** low, Site** high) +{ + if (v->wordIndex == 0) { + *low = s; + *high = pickSiteOrGrow(c, v->nextWord, s, 1); + return *high; + } else { + *low = pickSiteOrGrow(c, v->nextWord, s, 0); + *high = s; + return *low; + } +} + +bool isHome(Value* v, int frameIndex) +{ + Value* p = v; + do { + if (p->home == frameIndex) { + return true; + } + p = p->buddy; + } while (p != v); + + return false; +} + +bool acceptForResolve(Context* c, Site* s, Read* read, const SiteMask& mask) +{ + if (acceptMatch(c, s, read, mask) and (not s->frozen(c))) { + if (s->type(c) == lir::Operand::Type::RegisterPair) { + return c->availableGeneralRegisterCount > ResolveRegisterReserveCount; + } else { + assertT(c, + s->match(c, SiteMask(lir::Operand::MemoryMask, 0, AnyFrameIndex))); + + return isHome(read->value, + offsetToFrameIndex(c, static_cast(s)->offset)); + } + } else { + return false; + } +} + +void move(Context* c, Value* value, Site* src, Site* dst) +{ + if (DebugMoves) { + char srcb[256]; + src->toString(c, srcb, 256); + char dstb[256]; + dst->toString(c, dstb, 256); + fprintf(stderr, "move %s to %s for %p to %p\n", srcb, dstb, value, value); + } + + assertT(c, value->findSite(dst)); + + src->freeze(c, value); + dst->freeze(c, value); + + unsigned srcSize; + unsigned dstSize; + if (value->nextWord == value) { + srcSize = TargetBytesPerWord; + dstSize = TargetBytesPerWord; + } else { + srcSize = src->registerSize(c); + dstSize = dst->registerSize(c); + } + + if (srcSize == dstSize) { + apply(c, lir::Move, srcSize, src, src, dstSize, dst, dst); + } else if (srcSize > TargetBytesPerWord) { + Site* low, *high, *other = pickSiteOrGrow(c, value, dst, &low, &high); + other->freeze(c, value->nextWord); + + apply(c, lir::Move, srcSize, src, src, srcSize, low, high); + + other->thaw(c, value->nextWord); + } else { + Site* low, *high, *other = pickSiteOrMove(c, value, src, &low, &high); + other->freeze(c, value->nextWord); + + apply(c, lir::Move, dstSize, low, high, dstSize, dst, dst); + + other->thaw(c, value->nextWord); + } + + dst->thaw(c, value); + src->thaw(c, value); +} + +void asAssemblerOperand(Context* c, Site* low, Site* high, lir::Operand* result) +{ + low->asAssemblerOperand(c, high, result); +} + +class OperandUnion : public lir::Operand { + public: + // must be large enough and aligned properly to hold any operand + // type (we'd use an actual union type here, except that classes + // with constructors cannot be used in a union): + uintptr_t padding[4]; +}; + +void apply(Context* c, + lir::UnaryOperation op, + unsigned s1Size, + Site* s1Low, + Site* s1High) +{ + assertT(c, s1Low->type(c) == s1High->type(c)); + + lir::Operand::Type s1Type = s1Low->type(c); + OperandUnion s1Union; + asAssemblerOperand(c, s1Low, s1High, &s1Union); + + c->assembler->apply(op, OperandInfo(s1Size, s1Type, &s1Union)); +} + +void apply(Context* c, + lir::BinaryOperation op, + unsigned s1Size, + Site* s1Low, + Site* s1High, + unsigned s2Size, + Site* s2Low, + Site* s2High) +{ + assertT(c, s1Low->type(c) == s1High->type(c)); + assertT(c, s2Low->type(c) == s2High->type(c)); + + lir::Operand::Type s1Type = s1Low->type(c); + OperandUnion s1Union; + asAssemblerOperand(c, s1Low, s1High, &s1Union); + + lir::Operand::Type s2Type = s2Low->type(c); + OperandUnion s2Union; + asAssemblerOperand(c, s2Low, s2High, &s2Union); + + c->assembler->apply(op, + OperandInfo(s1Size, s1Type, &s1Union), + OperandInfo(s2Size, s2Type, &s2Union)); +} + +void apply(Context* c, + lir::TernaryOperation op, + unsigned s1Size, + Site* s1Low, + Site* s1High, + unsigned s2Size, + Site* s2Low, + Site* s2High, + unsigned s3Size, + Site* s3Low, + Site* s3High) +{ + assertT(c, s1Low->type(c) == s1High->type(c)); + assertT(c, s2Low->type(c) == s2High->type(c)); + assertT(c, s3Low->type(c) == s3High->type(c)); + + lir::Operand::Type s1Type = s1Low->type(c); + OperandUnion s1Union; + asAssemblerOperand(c, s1Low, s1High, &s1Union); + + lir::Operand::Type s2Type = s2Low->type(c); + OperandUnion s2Union; + asAssemblerOperand(c, s2Low, s2High, &s2Union); + + lir::Operand::Type s3Type = s3Low->type(c); + OperandUnion s3Union; + asAssemblerOperand(c, s3Low, s3High, &s3Union); + + c->assembler->apply(op, + OperandInfo(s1Size, s1Type, &s1Union), + OperandInfo(s2Size, s2Type, &s2Union), + OperandInfo(s3Size, s3Type, &s3Union)); +} + +void append(Context* c, Event* e); + +void saveLocals(Context* c, Event* e) +{ + for (unsigned li = 0; li < c->localFootprint; ++li) { + Local* local = e->localsBefore + li; + if (local->value) { + if (DebugReads) { + fprintf(stderr, + "local save read %p at %d of %d\n", + local->value, + compiler::frameIndex(c, li), + totalFrameSize(c)); + } + + e->addRead( + c, + local->value, + SiteMask(lir::Operand::MemoryMask, 0, compiler::frameIndex(c, li))); + } + } +} + +void maybeMove(Context* c, + lir::BinaryOperation op, + unsigned srcSize, + unsigned srcSelectSize, + Value* srcValue, + unsigned dstSize, + Value* dstValue, + const SiteMask& dstMask) +{ + Read* read = live(c, dstValue); + bool isStore = read == 0; + + Site* target; + if (dstValue->target) { + target = dstValue->target; + } else if (isStore) { + return; + } else { + target = pickTargetSite(c, read); + } + + unsigned cost = srcValue->source->copyCost(c, target); + + if (srcSelectSize < dstSize) + cost = 1; + + if (cost) { + // todo: let c->arch->planMove decide this: + bool useTemporary = ((target->type(c) == lir::Operand::Type::Memory + and srcValue->source->type(c) == lir::Operand::Type::Memory) + or (srcSelectSize < dstSize + and target->type(c) != lir::Operand::Type::RegisterPair)); + + srcValue->source->freeze(c, srcValue); + + dstValue->addSite(c, target); + + srcValue->source->thaw(c, srcValue); + + bool addOffset = srcSize != srcSelectSize and c->arch->bigEndian() + and srcValue->source->type(c) == lir::Operand::Type::Memory; + + if (addOffset) { + static_cast(srcValue->source)->offset + += (srcSize - srcSelectSize); + } + + target->freeze(c, dstValue); + + if (target->match(c, dstMask) and not useTemporary) { + if (DebugMoves) { + char srcb[256]; + srcValue->source->toString(c, srcb, 256); + char dstb[256]; + target->toString(c, dstb, 256); + fprintf(stderr, + "move %s to %s for %p to %p\n", + srcb, + dstb, + srcValue, + dstValue); + } + + srcValue->source->freeze(c, srcValue); + + apply(c, + op, + min(srcSelectSize, dstSize), + srcValue->source, + srcValue->source, + dstSize, + target, + target); + + srcValue->source->thaw(c, srcValue); + } else { + // pick a temporary register which is valid as both a + // destination and a source for the moves we need to perform: + + dstValue->removeSite(c, target); + + bool thunk; + OperandMask src; + + c->arch->planSource(op, dstSize, src, dstSize, &thunk); + + if (isGeneralValue(srcValue)) { + src.lowRegisterMask &= c->regFile->generalRegisters; + } + + assertT(c, thunk == 0); + assertT(c, dstMask.typeMask & src.typeMask & lir::Operand::RegisterPairMask); + + Site* tmpTarget + = freeRegisterSite(c, dstMask.registerMask & src.lowRegisterMask); + + srcValue->source->freeze(c, srcValue); + + dstValue->addSite(c, tmpTarget); + + tmpTarget->freeze(c, dstValue); + + if (DebugMoves) { + char srcb[256]; + srcValue->source->toString(c, srcb, 256); + char dstb[256]; + tmpTarget->toString(c, dstb, 256); + fprintf(stderr, + "move %s to %s for %p to %p\n", + srcb, + dstb, + srcValue, + dstValue); + } + + apply(c, + op, + srcSelectSize, + srcValue->source, + srcValue->source, + dstSize, + tmpTarget, + tmpTarget); + + tmpTarget->thaw(c, dstValue); + + srcValue->source->thaw(c, srcValue); + + if (useTemporary or isStore) { + if (DebugMoves) { + char srcb[256]; + tmpTarget->toString(c, srcb, 256); + char dstb[256]; + target->toString(c, dstb, 256); + fprintf(stderr, + "move %s to %s for %p to %p\n", + srcb, + dstb, + srcValue, + dstValue); + } + + dstValue->addSite(c, target); + + tmpTarget->freeze(c, dstValue); + + apply(c, + lir::Move, + dstSize, + tmpTarget, + tmpTarget, + dstSize, + target, + target); + + tmpTarget->thaw(c, dstValue); + + if (isStore) { + dstValue->removeSite(c, tmpTarget); + } + } + } + + target->thaw(c, dstValue); + + if (addOffset) { + static_cast(srcValue->source)->offset + -= (srcSize - srcSelectSize); + } + } else { + target = srcValue->source; + + if (DebugMoves) { + char dstb[256]; + target->toString(c, dstb, 256); + fprintf( + stderr, "null move in %s for %p to %p\n", dstb, srcValue, dstValue); + } + } + + if (isStore) { + dstValue->removeSite(c, target); + } +} + +Site* pickMatchOrMove(Context* c, + Read* r, + Site* nextWord, + unsigned index, + bool intersectRead) +{ + Site* s = pickSite(c, r->value, nextWord, index, true); + SiteMask mask; + if (intersectRead) { + r->intersect(&mask); + } + if (s and s->match(c, mask)) { + return s; + } + + return pickSiteOrMove(c, + r->value, + mask.intersectionWith(nextWord->nextWordMask(c, index)), + true, + true); +} + +Site* pickSiteOrMove(Context* c, + Value* src, + Value* dst, + Site* nextWord, + unsigned index) +{ + if (live(c, dst)) { + Read* read = live(c, src); + Site* s; + if (nextWord) { + s = pickMatchOrMove(c, read, nextWord, index, false); + } else { + s = pickSourceSite(c, read, 0, 0, 0, false, true, true); + + if (s == 0 or s->isVolatile(c)) { + s = maybeMove(c, read, false, true); + } + } + assertT(c, s); + + addBuddy(src, dst); + + if (src->source->isVolatile(c)) { + src->removeSite(c, src->source); + } + + return s; + } else { + return 0; + } +} + +ConstantSite* findConstantSite(Context* c, Value* v); + +Site* getTarget(Context* c, + Value* value, + Value* result, + const SiteMask& resultMask); + +void freezeSource(Context* c, unsigned size, Value* v); + +void thawSource(Context* c, unsigned size, Value* v); + +void removeBuddy(Context* c, Value* v) +{ + if (v->buddy != v) { + if (DebugBuddies) { + fprintf(stderr, "remove buddy %p from", v); + for (Value* p = v->buddy; p != v; p = p->buddy) { + fprintf(stderr, " %p", p); + } + fprintf(stderr, "\n"); + } + + assertT(c, v->buddy); + + Value* next = v->buddy; + v->buddy = v; + Value* p = next; + while (p->buddy != v) + p = p->buddy; + p->buddy = next; + + assertT(c, p->buddy); + + if (not live(c, next)) { + next->clearSites(c); + } + + if (not live(c, v)) { + v->clearSites(c); + } + } +} + +Site* copy(Context* c, Site* s) +{ + Site* start = 0; + Site* end = 0; + for (; s; s = s->next) { + Site* n = s->copy(c); + if (end) { + end->next = n; + } else { + start = n; + } + end = n; + } + return start; +} + +class Snapshot { + public: + Snapshot(Context* c, Value* value, Snapshot* next) + : value(value), + buddy(value->buddy), + sites(copy(c, value->sites)), + next(next) + { + } + + Value* value; + Value* buddy; + Site* sites; + Snapshot* next; +}; + +Snapshot* snapshot(Context* c, Value* value, Snapshot* next) +{ + if (DebugControl) { + char buffer[256]; + sitesToString(c, value->sites, buffer, 256); + fprintf( + stderr, "snapshot %p buddy %p sites %s\n", value, value->buddy, buffer); + } + + return new (c->zone) Snapshot(c, value, next); +} + +Snapshot* makeSnapshots(Context* c, Value* value, Snapshot* next) +{ + next = snapshot(c, value, next); + for (Value* p = value->buddy; p != value; p = p->buddy) { + next = snapshot(c, p, next); + } + return next; +} + +Value* maybeBuddy(Context* c, Value* v); + +Value* pushWord(Context* c, Value* v) +{ + if (v) { + v = maybeBuddy(c, v); + } + + Stack* s = stack(c, v, c->stack); + + if (DebugFrame) { + fprintf(stderr, "push %p\n", v); + } + + if (v) { + v->home = frameIndex(c, s->index + c->localFootprint); + } + c->stack = s; + + return v; +} + +void push(Context* c, unsigned footprint, Value* v) +{ + assertT(c, footprint); + + bool bigEndian = c->arch->bigEndian(); + + Value* low = v; + + if (bigEndian) { + v = pushWord(c, v); + } + + Value* high; + if (footprint > 1) { + assertT(c, footprint == 2); + + if (TargetBytesPerWord == 4) { + low->maybeSplit(c); + high = pushWord(c, low->nextWord); + } else { + high = pushWord(c, 0); + } + } else { + high = 0; + } + + if (not bigEndian) { + v = pushWord(c, v); + } + + if (high) { + v->nextWord = high; + high->nextWord = v; + high->wordIndex = 1; + } +} + +void popWord(Context* c) +{ + Stack* s = c->stack; + assertT(c, s->value == 0 or s->value->home >= 0); + + if (DebugFrame) { + fprintf(stderr, "pop %p\n", s->value); + } + + c->stack = s->next; +} + +Value* pop(Context* c, unsigned footprint) +{ + assertT(c, footprint); + + Stack* s = 0; + + bool bigEndian = c->arch->bigEndian(); + + if (not bigEndian) { + s = c->stack; + } + + if (footprint > 1) { + assertT(c, footprint == 2); + +#ifndef NDEBUG + Stack* low; + Stack* high; + if (bigEndian) { + high = c->stack; + low = high->next; + } else { + low = c->stack; + high = low->next; + } + + assertT( + c, + (TargetBytesPerWord == 8 and low->value->nextWord == low->value + and high->value == 0) + or (TargetBytesPerWord == 4 and low->value->nextWord == high->value)); +#endif // not NDEBUG + + popWord(c); + } + + if (bigEndian) { + s = c->stack; + } + + popWord(c); + + return s->value; +} + +Value* storeLocal(Context* c, + unsigned footprint, + Value* v, + unsigned index, + bool copy) +{ + assertT(c, index + footprint <= c->localFootprint); + + if (copy) { + unsigned sizeInBytes = sizeof(Local) * c->localFootprint; + Local* newLocals = static_cast(c->zone->allocate(sizeInBytes)); + memcpy(newLocals, c->locals, sizeInBytes); + c->locals = newLocals; + } + + Value* high; + if (footprint > 1) { + assertT(c, footprint == 2); + + unsigned highIndex; + unsigned lowIndex; + if (c->arch->bigEndian()) { + highIndex = index + 1; + lowIndex = index; + } else { + lowIndex = index + 1; + highIndex = index; + } + + if (TargetBytesPerWord == 4) { + assertT(c, v->nextWord != v); + + high = storeLocal(c, 1, v->nextWord, highIndex, false); + } else { + high = 0; + } + + index = lowIndex; + } else { + high = 0; + } + + v = maybeBuddy(c, v); + + if (high != 0) { + v->nextWord = high; + high->nextWord = v; + high->wordIndex = 1; + } + + Local* local = c->locals + index; + local->value = v; + + if (DebugFrame) { + fprintf(stderr, "store local %p at %d\n", local->value, index); + } + + local->value->home = frameIndex(c, index); + + return v; +} + +unsigned typeFootprint(Context* c, ir::Type type) +{ + // TODO: this function is very Java-specific in nature. Generalize. + switch (type.flavor()) { + case ir::Type::Float: + case ir::Type::Integer: + return type.rawSize() / 4; + case ir::Type::Object: + case ir::Type::Address: + return 1; + case ir::Type::Void: + return 0; + default: + abort(c); + } +} + +Value* loadLocal(Context* c, ir::Type type, unsigned index) +{ + unsigned footprint = typeFootprint(c, type); + assertT(c, index + footprint <= c->localFootprint); + + if (footprint > 1) { + assertT(c, footprint == 2); + + if (not c->arch->bigEndian()) { + ++index; + } + } + + assertT(c, c->locals[index].value); + assertT(c, c->locals[index].value->home >= 0); + + if (DebugFrame) { + fprintf(stderr, "load local %p at %d\n", c->locals[index].value, index); + } + + return c->locals[index].value; +} + +Value* threadRegister(Context* c) +{ + Site* s = registerSite(c, c->arch->thread()); + return value(c, ir::Type::addr(), s, s); +} + +unsigned frameFootprint(Context* c, Stack* s) +{ + return c->localFootprint + (s ? (s->index + 1) : 0); +} + +void visit(Context* c, Link* link) +{ + if (false) { + fprintf(stderr, + "visit link from %d to %d fork %p junction %p\n", + link->predecessor->logicalInstruction->index, + link->successor->logicalInstruction->index, + link->forkState, + link->junctionState); + } + + ForkState* forkState = link->forkState; + if (forkState) { + for (unsigned i = 0; i < forkState->readCount; ++i) { + ForkElement* p = forkState->elements + i; + Value* v = p->value; + v->reads = p->read->nextTarget(); + if (false) { + fprintf(stderr, "next read %p for %p from %p\n", v->reads, v, p->read); + } + if (not live(c, v)) { + v->clearSites(c); + } + } + } + + JunctionState* junctionState = link->junctionState; + if (junctionState) { + for (unsigned i = 0; i < junctionState->frameFootprint; ++i) { + StubReadPair* p = junctionState->reads + i; + + if (p->value and p->value->reads) { + assertT(c, p->value->reads == p->read); + popRead(c, 0, p->value); + } + } + } +} + +class BuddyEvent : public Event { + public: + BuddyEvent(Context* c, Value* original, Value* buddy) + : Event(c), original(original), buddy(buddy) + { + this->addRead(c, original, SiteMask(~0, ~0, AnyFrameIndex), buddy); + } + + virtual const char* name() + { + return "BuddyEvent"; + } + + virtual void compile(Context* c) + { + if (DebugBuddies) { + fprintf(stderr, "original %p buddy %p\n", original, buddy); + } + + assertT(c, original->hasSite(c)); + + assertT(c, original); + assertT(c, buddy); + + addBuddy(original, buddy); + + popRead(c, this, original); + } + + Value* original; + Value* buddy; +}; + +void appendBuddy(Context* c, Value* original, Value* buddy) +{ + append(c, new (c->zone) BuddyEvent(c, original, buddy)); +} + +void append(Context* c, Event* e) +{ + LogicalInstruction* i = c->logicalCode[c->logicalIp]; + if (c->stack != i->stack or c->locals != i->locals) { + appendDummy(c); + } + + if (DebugAppend) { + fprintf(stderr, + " -- append %s at %d with %d stack before\n", + e->name(), + e->logicalInstruction->index, + c->stack ? c->stack->index + 1 : 0); + } + + if (c->lastEvent) { + c->lastEvent->next = e; + } else { + c->firstEvent = e; + } + c->lastEvent = e; + + Event* p = c->predecessor; + if (p) { + if (DebugAppend) { + fprintf(stderr, + "%d precedes %d\n", + p->logicalInstruction->index, + e->logicalInstruction->index); + } + + Link* link + = compiler::link(c, p, e->predecessors, e, p->successors, c->forkState); + e->predecessors = link; + p->successors = link; + } + c->forkState = 0; + + c->predecessor = e; + + if (e->logicalInstruction->firstEvent == 0) { + e->logicalInstruction->firstEvent = e; + } + e->logicalInstruction->lastEvent = e; +} + +Site* readSource(Context* c, Read* r) +{ + Value* v = r->value; + + if (DebugReads) { + char buffer[1024]; + sitesToString(c, v, buffer, 1024); + fprintf(stderr, "read source for %p from %s\n", v, buffer); + } + + if (not v->hasSite(c)) { + if (DebugReads) { + fprintf(stderr, "no sites found for %p\n", v); + } + return 0; + } + + Value* high = r->high(c); + if (high) { + return pickMatchOrMove(c, r, high->source, 0, true); + } else { + return pickSiteOrMove(c, r, true, true); + } +} + +void propagateJunctionSites(Context* c, Event* e, Site** sites) +{ + for (Link* pl = e->predecessors; pl; pl = pl->nextPredecessor) { + Event* p = pl->predecessor; + if (p->junctionSites == 0) { + p->junctionSites = sites; + for (Link* sl = p->successors; sl; sl = sl->nextSuccessor) { + Event* s = sl->successor; + propagateJunctionSites(c, s, sites); + } + } + } +} + +void propagateJunctionSites(Context* c, Event* e) +{ + for (Link* sl = e->successors; sl; sl = sl->nextSuccessor) { + Event* s = sl->successor; + if (s->predecessors->nextPredecessor) { + unsigned size = sizeof(Site*) * frameFootprint(c, e->stackAfter); + Site** junctionSites = static_cast(c->zone->allocate(size)); + memset(junctionSites, 0, size); + + propagateJunctionSites(c, s, junctionSites); + break; + } + } +} + +class SiteRecord { + public: + Site* site; + Value* value; +}; + +void init(SiteRecord* r, Site* s, Value* v) +{ + r->site = s; + r->value = v; +} + +class SiteRecordList { + public: + SiteRecordList(SiteRecord* records, unsigned capacity) + : records(records), index(0), capacity(capacity) + { + } + + SiteRecord* records; + unsigned index; + unsigned capacity; +}; + +void freeze(Context* c, SiteRecordList* frozen, Site* s, Value* v) +{ + assertT(c, frozen->index < frozen->capacity); + + s->freeze(c, v); + init(new (frozen->records + (frozen->index++)) SiteRecord, s, v); +} + +void thaw(Context* c, SiteRecordList* frozen) +{ + while (frozen->index) { + SiteRecord* sr = frozen->records + (--frozen->index); + sr->site->thaw(c, sr->value); + } +} + +bool resolveOriginalSites(Context* c, + Event* e, + SiteRecordList* frozen, + Site** sites) +{ + bool complete = true; + for (FrameIterator it(c, e->stackAfter, e->localsAfter, true); + it.hasMore();) { + FrameIterator::Element el = it.next(c); + Value* v = el.value; + Read* r = v ? live(c, v) : 0; + Site* s = sites[el.localIndex]; + + if (r) { + if (s) { + if (DebugControl) { + char buffer[256]; + s->toString(c, buffer, 256); + fprintf(stderr, + "resolve original %s for %p local %d frame %d\n", + buffer, + v, + el.localIndex, + el.frameIndex(c)); + } + + Site* target = pickSiteOrMove( + c, v, s->mask(c), true, true, ResolveRegisterReserveCount); + + freeze(c, frozen, target, v); + } else { + complete = false; + } + } else if (s) { + if (DebugControl) { + char buffer[256]; + s->toString(c, buffer, 256); + fprintf(stderr, + "freeze original %s for %p local %d frame %d\n", + buffer, + v, + el.localIndex, + el.frameIndex(c)); + } + + Value dummy(0, 0, ir::Type::addr()); + dummy.addSite(c, s); + dummy.removeSite(c, s); + freeze(c, frozen, s, 0); + } + } + + return complete; +} + +bool resolveSourceSites(Context* c, + Event* e, + SiteRecordList* frozen, + Site** sites) +{ + bool complete = true; + for (FrameIterator it(c, e->stackAfter, e->localsAfter); it.hasMore();) { + FrameIterator::Element el = it.next(c); + Value* v = el.value; + Read* r = live(c, v); + + if (r and sites[el.localIndex] == 0) { + SiteMask mask(lir::Operand::RegisterPairMask | lir::Operand::MemoryMask, + c->regFile->generalRegisters, + AnyFrameIndex); + + Site* s = pickSourceSite( + c, r, 0, 0, &mask, true, false, true, acceptForResolve); + + if (s) { + if (DebugControl) { + char buffer[256]; + s->toString(c, buffer, 256); + fprintf(stderr, + "resolve source %s from %p local %d frame %d\n", + buffer, + v, + el.localIndex, + el.frameIndex(c)); + } + + freeze(c, frozen, s, v); + + sites[el.localIndex] = s->copy(c); + } else { + complete = false; + } + } + } + + return complete; +} + +void resolveTargetSites(Context* c, + Event* e, + SiteRecordList* frozen, + Site** sites) +{ + for (FrameIterator it(c, e->stackAfter, e->localsAfter); it.hasMore();) { + FrameIterator::Element el = it.next(c); + Value* v = el.value; + Read* r = live(c, v); + + if (r and sites[el.localIndex] == 0) { + SiteMask mask(lir::Operand::RegisterPairMask | lir::Operand::MemoryMask, + c->regFile->generalRegisters, + AnyFrameIndex); + + Site* s = pickSourceSite( + c, r, 0, 0, &mask, false, true, true, acceptForResolve); + + if (s == 0) { + s = maybeMove(c, v, mask, false, true, ResolveRegisterReserveCount); + } + + freeze(c, frozen, s, v); + + sites[el.localIndex] = s->copy(c); + + if (DebugControl) { + char buffer[256]; + sites[el.localIndex]->toString(c, buffer, 256); + fprintf(stderr, + "resolve target %s for %p local %d frame %d\n", + buffer, + el.value, + el.localIndex, + el.frameIndex(c)); + } + } + } +} + +void resolveJunctionSites(Context* c, Event* e, SiteRecordList* frozen) +{ + bool complete; + if (e->junctionSites) { + complete = resolveOriginalSites(c, e, frozen, e->junctionSites); + } else { + propagateJunctionSites(c, e); + complete = false; + } + + if (e->junctionSites) { + if (not complete) { + complete = resolveSourceSites(c, e, frozen, e->junctionSites); + if (not complete) { + resolveTargetSites(c, e, frozen, e->junctionSites); + } + } + + if (DebugControl) { + fprintf(stderr, + "resolved junction sites %p at %d\n", + e->junctionSites, + e->logicalInstruction->index); + } + } +} + +void resolveBranchSites(Context* c, Event* e, SiteRecordList* frozen) +{ + if (e->successors->nextSuccessor and e->junctionSites == 0) { + unsigned footprint = frameFootprint(c, e->stackAfter); + RUNTIME_ARRAY(Site*, branchSites, footprint); + memset(RUNTIME_ARRAY_BODY(branchSites), 0, sizeof(Site*) * footprint); + + if (not resolveSourceSites(c, e, frozen, RUNTIME_ARRAY_BODY(branchSites))) { + resolveTargetSites(c, e, frozen, RUNTIME_ARRAY_BODY(branchSites)); + } + } +} + +void captureBranchSnapshots(Context* c, Event* e) +{ + if (e->successors->nextSuccessor) { + for (FrameIterator it(c, e->stackAfter, e->localsAfter); it.hasMore();) { + FrameIterator::Element el = it.next(c); + e->snapshots = makeSnapshots(c, el.value, e->snapshots); + } + + for (List* sv = e->successors->forkState->saved; sv; + sv = sv->next) { + e->snapshots = makeSnapshots(c, sv->item, e->snapshots); + } + + if (DebugControl) { + fprintf(stderr, + "captured snapshots %p at %d\n", + e->snapshots, + e->logicalInstruction->index); + } + } +} + +void populateSiteTables(Context* c, Event* e, SiteRecordList* frozen) +{ + resolveJunctionSites(c, e, frozen); + + resolveBranchSites(c, e, frozen); +} + +void setSites(Context* c, Value* v, Site* s) +{ + assertT(c, live(c, v)); + + for (; s; s = s->next) { + v->addSite(c, s->copy(c)); + } + + if (DebugControl) { + char buffer[256]; + sitesToString(c, v->sites, buffer, 256); + fprintf(stderr, "set sites %s for %p\n", buffer, v); + } +} + +void resetFrame(Context* c, Event* e) +{ + for (FrameIterator it(c, e->stackBefore, e->localsBefore); it.hasMore();) { + FrameIterator::Element el = it.next(c); + el.value->clearSites(c); + } + + while (c->acquiredResources) { + c->acquiredResources->value->clearSites(c); + } +} + +void setSites(Context* c, Event* e, Site** sites) +{ + resetFrame(c, e); + + for (FrameIterator it(c, e->stackBefore, e->localsBefore); it.hasMore();) { + FrameIterator::Element el = it.next(c); + if (sites[el.localIndex]) { + if (live(c, el.value)) { + setSites(c, el.value, sites[el.localIndex]); + } else if (DebugControl) { + char buffer[256]; + sitesToString(c, sites[el.localIndex], buffer, 256); + fprintf(stderr, + "skip sites %s for %p local %d frame %d\n", + buffer, + el.value, + el.localIndex, + el.frameIndex(c)); + } + } else if (DebugControl) { + fprintf(stderr, + "no sites for %p local %d frame %d\n", + el.value, + el.localIndex, + el.frameIndex(c)); + } + } +} + +void removeBuddies(Context* c) +{ + for (FrameIterator it(c, c->stack, c->locals); it.hasMore();) { + FrameIterator::Element el = it.next(c); + removeBuddy(c, el.value); + } +} + +void restore(Context* c, Event* e, Snapshot* snapshots) +{ + for (Snapshot* s = snapshots; s; s = s->next) { + Value* v = s->value; + Value* next = v->buddy; + if (v != next) { + v->buddy = v; + Value* p = next; + while (p->buddy != v) + p = p->buddy; + p->buddy = next; + } + } + + for (Snapshot* s = snapshots; s; s = s->next) { + assertT(c, s->buddy); + + s->value->buddy = s->buddy; + } + + resetFrame(c, e); + + for (Snapshot* s = snapshots; s; s = s->next) { + if (live(c, s->value)) { + if (live(c, s->value) and s->sites and s->value->sites == 0) { + setSites(c, s->value, s->sites); + } + } + + if (false) { + char buffer[256]; + sitesToString(c, s->sites, buffer, 256); + fprintf(stderr, + "restore %p buddy %p sites %s live %p\n", + s->value, + s->value->buddy, + buffer, + live(c, s->value)); + } + } +} + +void populateSources(Context* c, Event* e) +{ + RUNTIME_ARRAY(SiteRecord, frozenRecords, e->readCount); + SiteRecordList frozen(RUNTIME_ARRAY_BODY(frozenRecords), e->readCount); + + for (Read* r = e->reads; r; r = r->eventNext) { + r->value->source = readSource(c, r); + if (r->value->source) { + if (DebugReads) { + char buffer[256]; + r->value->source->toString(c, buffer, 256); + fprintf(stderr, "freeze source %s for %p\n", buffer, r->value); + } + + freeze(c, &frozen, r->value->source, r->value); + } + } + + thaw(c, &frozen); +} + +void setStubRead(Context* c, StubReadPair* p, Value* v) +{ + if (v) { + StubRead* r = stubRead(c); + if (DebugReads) { + fprintf(stderr, "add stub read %p to %p\n", r, v); + } + finishAddRead(c, v, r); + + p->value = v; + p->read = r; + } +} + +void populateJunctionReads(Context* c, Link* link) +{ + JunctionState* state = new ( + c->zone->allocate(sizeof(JunctionState) + + (sizeof(StubReadPair) * frameFootprint(c, c->stack)))) + JunctionState(frameFootprint(c, c->stack)); + + memset(state->reads, 0, sizeof(StubReadPair) * frameFootprint(c, c->stack)); + + link->junctionState = state; + + for (FrameIterator it(c, c->stack, c->locals); it.hasMore();) { + FrameIterator::Element e = it.next(c); + setStubRead(c, state->reads + e.localIndex, e.value); + } +} + +void updateJunctionReads(Context* c, JunctionState* state) +{ + for (FrameIterator it(c, c->stack, c->locals); it.hasMore();) { + FrameIterator::Element e = it.next(c); + StubReadPair* p = state->reads + e.localIndex; + if (p->value and p->read->read == 0) { + Read* r = live(c, e.value); + if (r) { + if (DebugReads) { + fprintf( + stderr, "stub read %p for %p valid: %p\n", p->read, p->value, r); + } + p->read->read = r; + } + } + } + + for (unsigned i = 0; i < frameFootprint(c, c->stack); ++i) { + StubReadPair* p = state->reads + i; + if (p->value and p->read->read == 0) { + if (DebugReads) { + fprintf(stderr, "stub read %p for %p invalid\n", p->read, p->value); + } + p->read->valid_ = false; + } + } +} + +void compile(Context* c, + uintptr_t stackOverflowHandler, + unsigned stackLimitOffset) +{ + if (c->logicalCode[c->logicalIp]->lastEvent == 0) { + appendDummy(c); + } + + Assembler* a = c->assembler; + + Block* firstBlock = block(c, c->firstEvent); + Block* block = firstBlock; + + if (stackOverflowHandler) { + a->checkStackOverflow(stackOverflowHandler, stackLimitOffset); + } + + a->allocateFrame(c->alignedFrameSize); + + for (Event* e = c->firstEvent; e; e = e->next) { + if (DebugCompile) { + fprintf(stderr, + " -- compile %s at %d with %d preds %d succs %d stack\n", + e->name(), + e->logicalInstruction->index, + e->predecessors->countPredecessors(), + e->successors->countSuccessors(), + e->stackBefore ? e->stackBefore->index + 1 : 0); + } + + e->block = block; + + c->stack = e->stackBefore; + c->locals = e->localsBefore; + + if (e->logicalInstruction->machineOffset == 0) { + e->logicalInstruction->machineOffset = a->offset(); + } + + if (e->predecessors) { + visit(c, e->predecessors->lastPredecessor()); + + Event* first = e->predecessors->predecessor; + if (e->predecessors->nextPredecessor) { + for (Link* pl = e->predecessors; pl->nextPredecessor; + pl = pl->nextPredecessor) { + updateJunctionReads(c, pl->junctionState); + } + + if (DebugControl) { + fprintf(stderr, + "set sites to junction sites %p at %d\n", + first->junctionSites, + first->logicalInstruction->index); + } + + setSites(c, e, first->junctionSites); + removeBuddies(c); + } else if (first->successors->nextSuccessor) { + if (DebugControl) { + fprintf(stderr, + "restore snapshots %p at %d\n", + first->snapshots, + first->logicalInstruction->index); + } + + restore(c, e, first->snapshots); + } + } + + unsigned footprint = frameFootprint(c, e->stackAfter); + RUNTIME_ARRAY(SiteRecord, frozenRecords, footprint); + SiteRecordList frozen(RUNTIME_ARRAY_BODY(frozenRecords), footprint); + + bool branch = e->isBranch(); + if (branch and e->successors) { + populateSiteTables(c, e, &frozen); + } + + populateSources(c, e); + + if (branch and e->successors) { + captureBranchSnapshots(c, e); + } + + thaw(c, &frozen); + + e->compile(c); + + if ((not branch) and e->successors) { + populateSiteTables(c, e, &frozen); + captureBranchSnapshots(c, e); + thaw(c, &frozen); + } + + if (e->visitLinks) { + for (List* cell = reverseDestroy(e->visitLinks); cell; + cell = cell->next) { + visit(c, cell->item); + } + e->visitLinks = 0; + } + + for (CodePromise* p = e->promises; p; p = p->next) { + p->offset = a->offset(); + } + + a->endEvent(); + + LogicalInstruction* nextInstruction = e->logicalInstruction->next(c); + if (e->next == 0 or (e->next->logicalInstruction != e->logicalInstruction + and (e->next->logicalInstruction != nextInstruction + or e != e->logicalInstruction->lastEvent))) { + Block* b = e->logicalInstruction->firstEvent->block; + + while (b->nextBlock) { + b = b->nextBlock; + } + + if (b != block) { + b->nextBlock = block; + } + + block->nextInstruction = nextInstruction; + block->assemblerBlock = a->endBlock(e->next != 0); + + if (e->next) { + block = compiler::block(c, e->next); + } + } + } + + c->firstBlock = firstBlock; +} + +void restore(Context* c, ForkState* state) +{ + for (unsigned i = 0; i < state->readCount; ++i) { + ForkElement* p = state->elements + i; + p->value->lastRead = p->read; + p->read->allocateTarget(c); + } +} + +void addForkElement(Context* c, Value* v, ForkState* state, unsigned index) +{ + MultiRead* r = multiRead(c); + if (DebugReads) { + fprintf(stderr, "add multi read %p to %p\n", r, v); + } + finishAddRead(c, v, r); + + ForkElement* p = state->elements + index; + p->value = v; + p->read = r; +} + +ForkState* saveState(Context* c) +{ + if (c->logicalCode[c->logicalIp]->lastEvent == 0) { + appendDummy(c); + } + + unsigned elementCount = frameFootprint(c, c->stack) + c->saved->count(); + + ForkState* state = new (c->zone->allocate( + sizeof(ForkState) + (sizeof(ForkElement) * elementCount))) + ForkState(c->stack, c->locals, c->saved, c->predecessor, c->logicalIp); + + if (c->predecessor) { + c->forkState = state; + + unsigned count = 0; + + for (FrameIterator it(c, c->stack, c->locals); it.hasMore();) { + FrameIterator::Element e = it.next(c); + addForkElement(c, e.value, state, count++); + } + + for (List* sv = c->saved; sv; sv = sv->next) { + addForkElement(c, sv->item, state, count++); + } + + state->readCount = count; + } + + c->saved = 0; + + return state; +} + +void restoreState(Context* c, ForkState* s) +{ + if (c->logicalCode[c->logicalIp]->lastEvent == 0) { + appendDummy(c); + } + + c->stack = s->stack; + c->locals = s->locals; + c->predecessor = s->predecessor; + c->logicalIp = s->logicalIp; + + if (c->predecessor) { + c->forkState = s; + restore(c, s); + } +} + +Value* maybeBuddy(Context* c, Value* v) +{ + if (v->home >= 0) { + Value* n = value(c, v->type); + appendBuddy(c, v, n); + return n; + } else { + return v; + } +} + +void linkLocals(Context* c, Local* oldLocals, Local* newLocals) +{ + for (int i = 0; i < static_cast(c->localFootprint); ++i) { + Local* local = oldLocals + i; + if (local->value) { + int highOffset = c->arch->bigEndian() ? 1 : -1; + + if (i + highOffset >= 0 + and i + highOffset < static_cast(c->localFootprint) + and local->value->nextWord == local[highOffset].value) { + Value* v = newLocals[i].value; + Value* next = newLocals[i + highOffset].value; + v->nextWord = next; + next->nextWord = v; + next->wordIndex = 1; + } + } + } +} + +class Client : public Assembler::Client { + public: + Client(Context* c) : c(c) + { + } + + virtual Register acquireTemporary(RegisterMask mask) + { + unsigned cost; + Register r = pickRegisterTarget(c, 0, mask, &cost); + expect(c, cost < Target::Impossible); + save(r); + c->registerResources[r.index()].increment(c); + return r; + } + + virtual void releaseTemporary(Register r) + { + c->registerResources[r.index()].decrement(c); + } + + virtual void save(Register r) + { + RegisterResource* reg = c->registerResources + r.index(); + + assertT(c, reg->referenceCount == 0); + assertT(c, reg->freezeCount == 0); + assertT(c, not reg->reserved); + + if (reg->value) { + steal(c, reg, 0); + } + } + + Context* c; +}; + +class MyCompiler : public Compiler { + public: + MyCompiler(System* s, + Assembler* assembler, + Zone* zone, + Compiler::Client* compilerClient) + : c(s, assembler, zone, compilerClient), client(&c) + { + assembler->setClient(&client); + } + + virtual State* saveState() + { + State* s = compiler::saveState(&c); + restoreState(s); + return s; + } + + virtual void restoreState(State* state) + { + compiler::restoreState(&c, static_cast(state)); + } + + virtual void init(unsigned logicalCodeLength, + unsigned parameterFootprint, + unsigned localFootprint, + unsigned alignedFrameSize) + { + c.parameterFootprint = parameterFootprint; + c.localFootprint = localFootprint; + c.alignedFrameSize = alignedFrameSize; + + unsigned frameResourceCount = totalFrameSize(&c); + + c.frameResources = static_cast( + c.zone->allocate(sizeof(FrameResource) * frameResourceCount)); + + for (unsigned i = 0; i < frameResourceCount; ++i) { + new (c.frameResources + i) FrameResource; + } + + unsigned base = frameBase(&c); + c.frameResources[base + c.arch->returnAddressOffset()].reserved = true; + c.frameResources[base + c.arch->framePointerOffset()].reserved + = UseFramePointer; + + c.logicalCode.init(c.zone, logicalCodeLength); + + c.logicalCode[-1] = new (c.zone) LogicalInstruction(-1, c.stack, c.locals); + + c.locals + = static_cast(c.zone->allocate(sizeof(Local) * localFootprint)); + + memset(c.locals, 0, sizeof(Local) * localFootprint); + } + + virtual void extendLogicalCode(unsigned more) + { + c.logicalCode.extend(c.zone, more); + } + + virtual void visitLogicalIp(unsigned logicalIp) + { + assertT(&c, logicalIp < c.logicalCode.count()); + + if (c.logicalCode[c.logicalIp]->lastEvent == 0) { + appendDummy(&c); + } + + Event* e = c.logicalCode[logicalIp]->firstEvent; + + Event* p = c.predecessor; + if (p) { + if (DebugAppend) { + fprintf(stderr, + "visit %d pred %d\n", + logicalIp, + p->logicalInstruction->index); + } + + p->stackAfter = c.stack; + p->localsAfter = c.locals; + + Link* link = compiler::link( + &c, p, e->predecessors, e, p->successors, c.forkState); + e->predecessors = link; + p->successors = link; + c.lastEvent->visitLinks = cons(&c, link, c.lastEvent->visitLinks); + + if (DebugAppend) { + fprintf(stderr, + "populate junction reads for %d to %d\n", + p->logicalInstruction->index, + logicalIp); + } + + populateJunctionReads(&c, link); + } + + c.forkState = 0; + } + + virtual void startLogicalIp(unsigned logicalIp) + { + assertT(&c, logicalIp < c.logicalCode.count()); + assertT(&c, c.logicalCode[logicalIp] == 0); + + if (c.logicalCode[c.logicalIp]->lastEvent == 0) { + appendDummy(&c); + } + + Event* p = c.predecessor; + if (p) { + p->stackAfter = c.stack; + p->localsAfter = c.locals; + } + + c.logicalCode[logicalIp] = new (c.zone) + LogicalInstruction(logicalIp, c.stack, c.locals); + + c.logicalIp = logicalIp; + } + + virtual Promise* machineIp(unsigned logicalIp) + { + return ipPromise(&c, logicalIp); + } + + virtual Promise* poolAppend(intptr_t value) + { + return poolAppendPromise(resolvedPromise(&c, value)); + } + + virtual Promise* poolAppendPromise(Promise* value) + { + Promise* p = poolPromise(&c, c.constantCount); + + ConstantPoolNode* constant = new (c.zone) ConstantPoolNode(value); + + if (c.firstConstant) { + c.lastConstant->next = constant; + } else { + c.firstConstant = constant; + } + c.lastConstant = constant; + ++c.constantCount; + + return p; + } + + virtual ir::Value* constant(int64_t value, ir::Type type) + { + return promiseConstant(resolvedPromise(&c, value), type); + } + + virtual ir::Value* promiseConstant(Promise* value, ir::Type type) + { + return compiler::value(&c, type, compiler::constantSite(&c, value)); + } + + virtual ir::Value* address(ir::Type type, Promise* address) + { + return value(&c, type, compiler::addressSite(&c, address)); + } + + virtual ir::Value* memory(ir::Value* base, + ir::Type type, + int displacement = 0, + ir::Value* index = 0) + { + Value* result = value(&c, type); + + appendMemory(&c, + static_cast(base), + displacement, + static_cast(index), + index == 0 ? 1 : type.size(c.targetInfo), + result); + + return result; + } + + virtual ir::Value* threadRegister() + { + return compiler::threadRegister(&c); + } + + Promise* machineIp() + { + return c.logicalCode[c.logicalIp]->lastEvent->makeCodePromise(&c); + } + + virtual void push(ir::Type type, ir::Value* value) + { + // TODO: once type information is flowed properly, enable this assertT. + // Some time later, we can remove the parameter. + // assertT(&c, value->type == type); + compiler::push(&c, typeFootprint(&c, type), static_cast(value)); + } + + virtual void save(ir::Type type, ir::Value* value) + { + // TODO: once type information is flowed properly, enable this assertT. + // Some time later, we can remove the parameter. + // assertT(&c, value->type == type); + unsigned footprint = typeFootprint(&c, type); + c.saved = cons(&c, static_cast(value), c.saved); + if (TargetBytesPerWord == 4 and footprint > 1) { + assertT(&c, footprint == 2); + assertT(&c, static_cast(value)->nextWord); + + save(ir::Type::i4(), static_cast(value)->nextWord); + } + } + + virtual ir::Value* pop(ir::Type type) + { + ir::Value* value = compiler::pop(&c, typeFootprint(&c, type)); + // TODO: once type information is flowed properly, enable this assertT. + // Some time later, we can remove the parameter. + // assertT(&c, static_cast(value)->type == type); + return value; + } + + virtual void pushed(ir::Type type) + { + Value* v = value(&c, type); + appendFrameSite( + &c, + v, + frameIndex(&c, (c.stack ? c.stack->index : 0) + c.localFootprint)); + + Stack* s = compiler::stack(&c, v, c.stack); + v->home = frameIndex(&c, s->index + c.localFootprint); + c.stack = s; + } + + virtual void popped(unsigned footprint) + { + for (; footprint; --footprint) { + assertT(&c, c.stack->value == 0 or c.stack->value->home >= 0); + + if (DebugFrame) { + fprintf(stderr, "popped %p\n", c.stack->value); + } + + c.stack = c.stack->next; + } + } + + virtual unsigned topOfStack() + { + return c.stack->index; + } + + virtual ir::Value* peek(unsigned footprint, unsigned index) + { + Stack* s = c.stack; + for (unsigned i = index; i > 0; --i) { + s = s->next; + } + + if (footprint > 1) { + assertT(&c, footprint == 2); + + bool bigEndian = c.arch->bigEndian(); + +#ifndef NDEBUG + Stack* low; + Stack* high; + if (bigEndian) { + high = s; + low = s->next; + } else { + low = s; + high = s->next; + } + + assertT( + &c, + (TargetBytesPerWord == 8 and low->value->nextWord == low->value + and high->value == 0) + or (TargetBytesPerWord == 4 and low->value->nextWord == high->value)); +#endif // not NDEBUG + + if (bigEndian) { + s = s->next; + } + } + + return s->value; + } + + virtual ir::Value* nativeCall(ir::Value* address, + unsigned flags, + TraceHandler* traceHandler, + ir::Type resultType, + util::Slice arguments) + { + bool bigEndian = c.arch->bigEndian(); + + unsigned footprint = 0; + unsigned size = TargetBytesPerWord; + RUNTIME_ARRAY(ir::Value*, args, arguments.count); + int index = 0; + for (unsigned i = 0; i < arguments.count; ++i) { + Value* o = static_cast(arguments[i]); + if (o) { + if (bigEndian and size > TargetBytesPerWord) { + RUNTIME_ARRAY_BODY(args)[index++] = o->nextWord; + } + RUNTIME_ARRAY_BODY(args)[index] = o; + if ((not bigEndian) and size > TargetBytesPerWord) { + RUNTIME_ARRAY_BODY(args)[++index] = o->nextWord; + } + size = TargetBytesPerWord; + ++index; + } else { + size = 8; + } + ++footprint; + } + + Value* result = value(&c, resultType); + appendCall(&c, + static_cast(address), + ir::CallingConvention::Native, + flags, + traceHandler, + result, + util::Slice(RUNTIME_ARRAY_BODY(args), index)); + + return result; + } + + virtual ir::Value* stackCall(ir::Value* address, + unsigned flags, + TraceHandler* traceHandler, + ir::Type resultType, + Slice arguments) + { + Value* result = value(&c, resultType); + Stack* b UNUSED = c.stack; + appendCall(&c, + static_cast(address), + ir::CallingConvention::Avian, + flags, + traceHandler, + result, + arguments); + assertT(&c, c.stack == b); + return result; + } + + virtual void return_(ir::Value* a) + { + assertT(&c, a); + appendReturn(&c, static_cast(a)); + } + + virtual void return_() + { + appendReturn(&c, 0); + } + + void initLocalPart(unsigned index, ir::Type type) + { + Value* v = value(&c, type); + + if (DebugFrame) { + fprintf(stderr, + "init local %p at %d (%d)\n", + v, + index, + frameIndex(&c, index)); + } + + appendFrameSite(&c, v, frameIndex(&c, index)); + + Local* local = c.locals + index; + local->value = v; + v->home = frameIndex(&c, index); + } + + virtual void initLocal(unsigned index, ir::Type type) + { + unsigned footprint = typeFootprint(&c, type); + + assertT(&c, index + footprint <= c.localFootprint); + + Value* v = value(&c, type); + + if (footprint > 1) { + assertT(&c, footprint == 2); + + unsigned highIndex; + unsigned lowIndex; + if (c.arch->bigEndian()) { + highIndex = index + 1; + lowIndex = index; + } else { + lowIndex = index + 1; + highIndex = index; + } + + if (TargetBytesPerWord == 4) { + initLocalPart(highIndex, type); + Value* next = c.locals[highIndex].value; + v->nextWord = next; + next->nextWord = v; + next->wordIndex = 1; + } + + index = lowIndex; + } + + if (DebugFrame) { + fprintf(stderr, + "init local %p at %d (%d)\n", + v, + index, + frameIndex(&c, index)); + } + + appendFrameSite(&c, v, frameIndex(&c, index)); + + Local* local = c.locals + index; + local->value = v; + v->home = frameIndex(&c, index); + } + + virtual void initLocalsFromLogicalIp(unsigned logicalIp) + { + assertT(&c, logicalIp < c.logicalCode.count()); + + unsigned footprint = sizeof(Local) * c.localFootprint; + Local* newLocals = static_cast(c.zone->allocate(footprint)); + memset(newLocals, 0, footprint); + c.locals = newLocals; + + Event* e = c.logicalCode[logicalIp]->firstEvent; + for (int i = 0; i < static_cast(c.localFootprint); ++i) { + Local* local = e->locals() + i; + if (local->value) { + initLocalPart(i, local->value->type); + } + } + + linkLocals(&c, e->locals(), newLocals); + } + + virtual void storeLocal(ir::Value* src, unsigned index) + { + compiler::storeLocal(&c, + typeFootprint(&c, src->type), + static_cast(src), + index, + true); + } + + virtual ir::Value* loadLocal(ir::Type type, unsigned index) + { + return compiler::loadLocal(&c, type, index); + } + + virtual void saveLocals() + { + int oldIp UNUSED = c.logicalIp; + appendSaveLocals(&c); + assertT(&c, oldIp == c.logicalIp); + } + + virtual void checkBounds(ir::Value* object, + unsigned lengthOffset, + ir::Value* index, + intptr_t handler) + { + appendBoundsCheck(&c, + static_cast(object), + lengthOffset, + static_cast(index), + handler); + } + + virtual ir::Value* truncate(ir::Type type, ir::Value* src) + { + assertT(&c, src->type.flavor() == type.flavor()); + assertT(&c, type.flavor() != ir::Type::Float); + assertT(&c, type.rawSize() < src->type.rawSize()); + Value* dst = value(&c, type); + appendMove(&c, + lir::Move, + src->type.size(c.targetInfo), + src->type.size(c.targetInfo), + static_cast(src), + type.size(c.targetInfo), + dst); + return dst; + } + + virtual ir::Value* truncateThenExtend(ir::ExtendMode extendMode, + ir::Type extendType, + ir::Type truncateType, + ir::Value* src) + { + Value* dst = value(&c, extendType); + appendMove(&c, + extendMode == ir::ExtendMode::Signed ? lir::Move : lir::MoveZ, + TargetBytesPerWord, + truncateType.size(c.targetInfo), + static_cast(src), + extendType.size(c.targetInfo) < TargetBytesPerWord + ? TargetBytesPerWord + : extendType.size(c.targetInfo), + dst); + return dst; + } + + virtual void store(ir::Value* src, ir::Value* dst) + { + assertT(&c, src->type.flavor() == dst->type.flavor()); + + appendMove(&c, + lir::Move, + src->type.size(c.targetInfo), + src->type.size(c.targetInfo), + static_cast(src), + dst->type.size(c.targetInfo), + static_cast(dst)); + } + + virtual ir::Value* load(ir::ExtendMode extendMode, + ir::Value* src, + ir::Type dstType) + { + assertT(&c, src->type.flavor() == dstType.flavor()); + + Value* dst = value(&c, dstType); + appendMove(&c, + extendMode == ir::ExtendMode::Signed ? lir::Move : lir::MoveZ, + src->type.size(c.targetInfo), + src->type.size(c.targetInfo), + static_cast(src), + dstType.size(c.targetInfo) < TargetBytesPerWord + ? TargetBytesPerWord + : dstType.size(c.targetInfo), + dst); + return dst; + } + + virtual void condJump(lir::TernaryOperation op, + ir::Value* a, + ir::Value* b, + ir::Value* addr) + { + assertT(&c, + (isGeneralBranch(op) and isGeneralValue(a) and isGeneralValue(b)) + or (isFloatBranch(op) and isFloatValue(a) and isFloatValue(b))); + + assertT(&c, a->type == b->type); + assertT(&c, addr->type == ir::Type::iptr()); + + appendBranch(&c, + op, + static_cast(a), + static_cast(b), + static_cast(addr)); + } + + virtual void jmp(ir::Value* addr) + { + appendJump(&c, lir::Jump, static_cast(addr)); + } + + virtual void exit(ir::Value* addr) + { + appendJump(&c, lir::Jump, static_cast(addr), true); + } + + virtual ir::Value* binaryOp(lir::TernaryOperation op, + ir::Type type, + ir::Value* a, + ir::Value* b) + { + assertT(&c, + (isGeneralBinaryOp(op) and isGeneralValue(a) and isGeneralValue(b)) + or (isFloatBinaryOp(op) and isFloatValue(a) and isFloatValue(b))); + + Value* result = value(&c, type); + + appendCombine( + &c, op, static_cast(a), static_cast(b), result); + return result; + } + + virtual ir::Value* unaryOp(lir::BinaryOperation op, ir::Value* a) + { + assertT(&c, + (isGeneralUnaryOp(op) and isGeneralValue(a)) + or (isFloatUnaryOp(op) and isFloatValue(a))); + Value* result = value(&c, a->type); + appendTranslate(&c, op, static_cast(a), result); + return result; + } + + virtual ir::Value* f2f(ir::Type resType, ir::Value* a) + { + assertT(&c, isFloatValue(a)); + assertT(&c, resType.flavor() == ir::Type::Float); + Value* result = value(&c, resType); + appendTranslate(&c, lir::Float2Float, static_cast(a), result); + return result; + } + + virtual ir::Value* f2i(ir::Type resType, ir::Value* a) + { + assertT(&c, isFloatValue(a)); + assertT(&c, resType.flavor() != ir::Type::Float); + Value* result = value(&c, resType); + appendTranslate(&c, lir::Float2Int, static_cast(a), result); + return result; + } + + virtual ir::Value* i2f(ir::Type resType, ir::Value* a) + { + assertT(&c, isGeneralValue(a)); + assertT(&c, resType.flavor() == ir::Type::Float); + Value* result = value(&c, resType); + appendTranslate(&c, lir::Int2Float, static_cast(a), result); + return result; + } + + virtual void nullaryOp(lir::Operation op) + { + appendOperation(&c, op); + } + + virtual void compile(uintptr_t stackOverflowHandler, + unsigned stackLimitOffset) + { + compiler::compile(&c, stackOverflowHandler, stackLimitOffset); + } + + virtual unsigned resolve(uint8_t* dst) + { + c.machineCode = dst; + c.assembler->setDestination(dst); + + Block* block = c.firstBlock; + while (block->nextBlock or block->nextInstruction) { + Block* next = block->nextBlock + ? block->nextBlock + : block->nextInstruction->firstEvent->block; + + next->start + = block->assemblerBlock->resolve(block->start, next->assemblerBlock); + + block = next; + } + + return c.machineCodeSize = block->assemblerBlock->resolve(block->start, 0) + + c.assembler->footerSize(); + } + + virtual unsigned poolSize() + { + return c.constantCount * TargetBytesPerWord; + } + + virtual void write() + { + c.assembler->write(); + + int i = 0; + for (ConstantPoolNode* n = c.firstConstant; n; n = n->next) { + target_intptr_t* target = reinterpret_cast( + c.machineCode + pad(c.machineCodeSize, TargetBytesPerWord) + i); + + if (n->promise->resolved()) { + *target = targetVW(n->promise->value()); + } else { + class Listener : public Promise::Listener { + public: + Listener(target_intptr_t* target) : target(target) + { + } + + virtual bool resolve(int64_t value, void** location) + { + *target = targetVW(value); + if (location) + *location = target; + return true; + } + + target_intptr_t* target; + }; + new (n->promise->listen(sizeof(Listener))) Listener(target); + } + + i += TargetBytesPerWord; + } + } + + virtual void dispose() + { + // ignore + } + + Context c; + compiler::Client client; +}; + +} // namespace compiler + +Compiler* makeCompiler(System* system, + Assembler* assembler, + Zone* zone, + Compiler::Client* client) +{ + return new (zone) compiler::MyCompiler(system, assembler, zone, client); +} + +} // namespace codegen +} // namespace avian diff --git a/sgx-jvm/avian/src/codegen/compiler/context.cpp b/sgx-jvm/avian/src/codegen/compiler/context.cpp new file mode 100644 index 0000000000..3027d72568 --- /dev/null +++ b/sgx-jvm/avian/src/codegen/compiler/context.cpp @@ -0,0 +1,70 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#include "codegen/compiler/context.h" +#include "codegen/compiler/resource.h" + +#include + +namespace avian { +namespace codegen { +namespace compiler { + +Context::Context(vm::System* system, + Assembler* assembler, + vm::Zone* zone, + Compiler::Client* client) + : system(system), + assembler(assembler), + arch(assembler->arch()), + zone(zone), + client(client), + stack(0), + locals(0), + saved(0), + predecessor(0), + regFile(arch->registerFile()), + regAlloc(system, arch->registerFile()), + registerResources(static_cast(zone->allocate( + sizeof(RegisterResource) * regFile->allRegisters.limit))), + frameResources(0), + acquiredResources(0), + firstConstant(0), + lastConstant(0), + machineCode(0), + firstEvent(0), + lastEvent(0), + forkState(0), + firstBlock(0), + logicalIp(-1), + constantCount(0), + parameterFootprint(0), + localFootprint(0), + machineCodeSize(0), + alignedFrameSize(0), + availableGeneralRegisterCount(regFile->generalRegisters.limit + - regFile->generalRegisters.start), + targetInfo(arch->targetInfo()) +{ + for (Register i : regFile->generalRegisters) { + new (registerResources + i.index()) RegisterResource(arch->reserved(i)); + + if (registerResources[i.index()].reserved) { + --availableGeneralRegisterCount; + } + } + for (Register i : regFile->floatRegisters) { + new (registerResources + i.index()) RegisterResource(arch->reserved(i)); + } +} + +} // namespace compiler +} // namespace codegen +} // namespace avian diff --git a/sgx-jvm/avian/src/codegen/compiler/context.h b/sgx-jvm/avian/src/codegen/compiler/context.h new file mode 100644 index 0000000000..c6ca6ece73 --- /dev/null +++ b/sgx-jvm/avian/src/codegen/compiler/context.h @@ -0,0 +1,149 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#ifndef AVIAN_CODEGEN_COMPILER_CONTEXT_H +#define AVIAN_CODEGEN_COMPILER_CONTEXT_H + +#include +#include +#include + +#include "regalloc.h" + +using namespace avian::util; + +namespace avian { +namespace codegen { +namespace compiler { + +class Stack; +class Local; +class Event; +class LogicalInstruction; + +class Resource; +class RegisterResource; +class FrameResource; + +class ConstantPoolNode; + +class ForkState; +class Block; + +template +List* reverseDestroy(List* cell) +{ + List* previous = 0; + while (cell) { + List* next = cell->next; + cell->next = previous; + previous = cell; + cell = next; + } + return previous; +} + +class LogicalCode { + private: + util::Slice logicalCode; + + public: + LogicalCode() : logicalCode(0, 0) + { + } + + void init(vm::Zone* zone, size_t count) + { + // leave room for logical instruction -1 + size_t realCount = count + 1; + + logicalCode + = util::Slice::allocAndSet(zone, realCount, 0); + } + + void extend(vm::Zone* zone, size_t more) + { + util::Slice newCode + = logicalCode.cloneAndSet(zone, logicalCode.count + more, 0); + + for (size_t i = 0; i < logicalCode.count; i++) { + assertT((vm::System*)0, logicalCode[i] == newCode[i]); + } + + logicalCode = newCode; + } + + size_t count() + { + return logicalCode.count - 1; + } + + LogicalInstruction*& operator[](int index) + { + // leave room for logical instruction -1 + return logicalCode[index + 1]; + } +}; + +class Context { + public: + Context(vm::System* system, + Assembler* assembler, + vm::Zone* zone, + Compiler::Client* client); + + vm::System* system; + Assembler* assembler; + Architecture* arch; + vm::Zone* zone; + Compiler::Client* client; + Stack* stack; + Local* locals; + List* saved; + Event* predecessor; + LogicalCode logicalCode; + const RegisterFile* regFile; + RegisterAllocator regAlloc; + RegisterResource* registerResources; + FrameResource* frameResources; + Resource* acquiredResources; + ConstantPoolNode* firstConstant; + ConstantPoolNode* lastConstant; + uint8_t* machineCode; + Event* firstEvent; + Event* lastEvent; + ForkState* forkState; + Block* firstBlock; + int logicalIp; + unsigned constantCount; + unsigned parameterFootprint; + unsigned localFootprint; + unsigned machineCodeSize; + unsigned alignedFrameSize; + unsigned availableGeneralRegisterCount; + ir::TargetInfo targetInfo; +}; + +inline Aborter* getAborter(Context* c) +{ + return c->system; +} + +template +List* cons(Context* c, const T& value, List* next) +{ + return new (c->zone) List(value, next); +} + +} // namespace compiler +} // namespace codegen +} // namespace avian + +#endif // AVIAN_CODEGEN_COMPILER_CONTEXT_H diff --git a/sgx-jvm/avian/src/codegen/compiler/event.cpp b/sgx-jvm/avian/src/codegen/compiler/event.cpp new file mode 100644 index 0000000000..575bede6ac --- /dev/null +++ b/sgx-jvm/avian/src/codegen/compiler/event.cpp @@ -0,0 +1,2193 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#include "avian/target.h" +#include +#include + +#include "codegen/compiler/context.h" +#include "codegen/compiler/event.h" +#include "codegen/compiler/site.h" +#include "codegen/compiler/read.h" +#include "codegen/compiler/value.h" +#include "codegen/compiler/promise.h" +#include "codegen/compiler/frame.h" +#include "codegen/compiler/ir.h" + +using namespace avian::util; + +namespace avian { +namespace codegen { +namespace compiler { + +SiteMask generalRegisterMask(Context* c); +SiteMask generalRegisterOrConstantMask(Context* c); + +CodePromise* codePromise(Context* c, Promise* offset); + +void saveLocals(Context* c, Event* e); + +void apply(Context* c, + lir::UnaryOperation op, + unsigned s1Size, + Site* s1Low, + Site* s1High); + +void apply(Context* c, + lir::BinaryOperation op, + unsigned s1Size, + Site* s1Low, + Site* s1High, + unsigned s2Size, + Site* s2Low, + Site* s2High); + +void apply(Context* c, + lir::TernaryOperation op, + unsigned s1Size, + Site* s1Low, + Site* s1High, + unsigned s2Size, + Site* s2Low, + Site* s2High, + unsigned s3Size, + Site* s3Low, + Site* s3High); + +void append(Context* c, Event* e); + +void clean(Context* c, + Event* e, + Stack* stack, + Local* locals, + Read* reads, + unsigned popIndex); + +Read* live(Context* c UNUSED, Value* v); + +void popRead(Context* c, Event* e UNUSED, Value* v); + +void maybeMove(Context* c, + lir::BinaryOperation op, + unsigned srcSize, + unsigned srcSelectSize, + Value* src, + unsigned dstSize, + Value* dst, + const SiteMask& dstMask); + +Site* maybeMove(Context* c, + Value* v, + const SiteMask& mask, + bool intersectMask, + bool includeNextWord, + unsigned registerReserveCount = 0); + +Site* maybeMove(Context* c, + Read* read, + bool intersectRead, + bool includeNextWord, + unsigned registerReserveCount = 0); +Site* pickSiteOrMove(Context* c, + Value* src, + Value* dst, + Site* nextWord, + unsigned index); + +Site* pickTargetSite(Context* c, + Read* read, + bool intersectRead = false, + unsigned registerReserveCount = 0, + CostCalculator* costCalculator = 0); +Value* threadRegister(Context* c); + +Event::Event(Context* c) + : next(0), + stackBefore(c->stack), + localsBefore(c->locals), + stackAfter(0), + localsAfter(0), + promises(0), + reads(0), + junctionSites(0), + snapshots(0), + predecessors(0), + successors(0), + visitLinks(0), + block(0), + logicalInstruction(c->logicalCode[c->logicalIp]), + readCount(0) +{ +} + +void Event::addRead(Context* c, Value* v, Read* r) +{ + if (DebugReads) { + fprintf(stderr, + "add read %p to %p last %p event %p (%s)\n", + r, + v, + v->lastRead, + this, + this->name()); + } + + r->event = this; + r->eventNext = this->reads; + this->reads = r; + ++this->readCount; + + finishAddRead(c, v, r); +} + +void finishAddRead(Context* c, Value* v, Read* r) +{ + r->value = v; + + if (v->lastRead) { + if (DebugReads) { + fprintf(stderr, "append %p to %p for %p\n", r, v->lastRead, v); + } + + v->lastRead->append(c, r); + } else { + v->reads = r; + } + v->lastRead = r; +} + +void Event::addRead(Context* c, + Value* v, + const SiteMask& mask, + Value* successor) +{ + this->addRead(c, v, read(c, mask, successor)); +} + +void Event::addReads(Context* c, + Value* v, + unsigned size, + const SiteMask& lowMask, + Value* lowSuccessor, + const SiteMask& highMask, + Value* highSuccessor) +{ + SingleRead* r = read(c, lowMask, lowSuccessor); + this->addRead(c, v, r); + if (size > c->targetInfo.pointerSize) { + r->high_ = v->nextWord; + this->addRead(c, v->nextWord, highMask, highSuccessor); + } +} + +void Event::addReads(Context* c, + Value* v, + unsigned size, + const SiteMask& lowMask, + const SiteMask& highMask) +{ + this->addReads(c, v, size, lowMask, 0, highMask, 0); +} + +CodePromise* Event::makeCodePromise(Context* c) +{ + return this->promises = new (c->zone) CodePromise(c, this->promises); +} + +bool Event::isUnreachable() +{ + for (Link* p = this->predecessors; p; p = p->nextPredecessor) { + if (not p->predecessor->allExits()) + return false; + } + return this->predecessors != 0; +} + +unsigned Link::countPredecessors() +{ + Link* link = this; + unsigned c = 0; + for (; link; link = link->nextPredecessor) { + ++c; + } + return c; +} + +Link* Link::lastPredecessor() +{ + Link* link = this; + while (link->nextPredecessor) { + link = link->nextPredecessor; + } + return link; +} + +unsigned Link::countSuccessors() +{ + Link* link = this; + unsigned c = 0; + for (; link; link = link->nextSuccessor) { + ++c; + } + return c; +} + +Link* link(Context* c, + Event* predecessor, + Link* nextPredecessor, + Event* successor, + Link* nextSuccessor, + ForkState* forkState) +{ + return new (c->zone) + Link(predecessor, nextPredecessor, successor, nextSuccessor, forkState); +} + +Value* maybeBuddySlice(Context* c, Value* v) +{ + if (v->home >= 0) { + Value* n = value(c, v->type); + appendBuddy(c, v, n); + return n; + } else { + return v; + } +} + +template +struct SliceStack : public Slice { + size_t capacity; + + SliceStack(T* items, size_t capacity) + : Slice(items + capacity, 0), capacity(capacity) + { + } + + void push(const T& item) + { + ASSERT(Slice::count < capacity); + --Slice::items; + ++Slice::count; + *Slice::items = item; + } +}; + +template +struct FixedSliceStack : public SliceStack { + T itemArray[Capacity]; + + FixedSliceStack() : SliceStack(&itemArray[0], Capacity) + { + } +}; + +Value* slicePushWord(Context* c, + Value* v, + size_t stackBase UNUSED, + SliceStack& slice) +{ + if (v) { + v = maybeBuddySlice(c, v); + } + + size_t index UNUSED = slice.count; + + assertT(c, slice.count < slice.capacity); + slice.push(v); + + if (false) { + fprintf(stderr, "push %p\n", v); + } + + if (v) { + v->home = frameIndex(c, index + stackBase + c->localFootprint); + } + + return v; +} + +void slicePush(Context* c, + unsigned footprint, + Value* v, + size_t stackBase, + SliceStack& slice) +{ + assertT(c, footprint); + + bool bigEndian = c->arch->bigEndian(); + + Value* low = v; + + if (bigEndian) { + v = slicePushWord(c, v, stackBase, slice); + } + + Value* high; + if (footprint > 1) { + assertT(c, footprint == 2); + + if (c->targetInfo.pointerSize == 4) { + low->maybeSplit(c); + high = slicePushWord(c, low->nextWord, stackBase, slice); + } else { + high = slicePushWord(c, 0, stackBase, slice); + } + } else { + high = 0; + } + + if (not bigEndian) { + v = slicePushWord(c, v, stackBase, slice); + } + + if (high) { + v->nextWord = high; + high->nextWord = v; + high->wordIndex = 1; + } +} + +class CallEvent : public Event { + public: + CallEvent(Context* c, + Value* address, + ir::CallingConvention callingConvention, + unsigned flags, + TraceHandler* traceHandler, + Value* resultValue, + util::Slice arguments) + : Event(c), + address(address), + traceHandler(traceHandler), + resultValue(resultValue), + returnAddressSurrogate(0), + framePointerSurrogate(0), + popIndex(0), + stackArgumentIndex(0), + flags(flags), + stackArgumentFootprint(callingConvention == ir::CallingConvention::Avian + ? arguments.count + : 0) + { + RegisterMask registerMask = c->regFile->generalRegisters; + + if (callingConvention == ir::CallingConvention::Native) { + assertT(c, (flags & Compiler::TailJump) == 0); + assertT(c, stackArgumentFootprint == 0); + + unsigned index = 0; + unsigned argumentIndex = 0; + + while (true) { + Value* v = static_cast(arguments[argumentIndex]); + + unsigned footprint = (argumentIndex + 1 < arguments.count + and v->nextWord == arguments[argumentIndex + 1]) + ? 2 + : 1; + + if (index % (c->arch->argumentAlignment() ? footprint : 1)) { + ++index; + } + + SiteMask targetMask; + if (index + (c->arch->argumentRegisterAlignment() ? footprint : 1) + <= c->arch->argumentRegisterCount()) { + Register number = c->arch->argumentRegister(index); + + if (DebugReads) { + fprintf(stderr, "reg %d arg read %p\n", number.index(), v); + } + + targetMask = SiteMask::fixedRegisterMask(number); + registerMask = registerMask.excluding(number); + } else { + if (index < c->arch->argumentRegisterCount()) { + index = c->arch->argumentRegisterCount(); + } + + unsigned frameIndex = index - c->arch->argumentRegisterCount(); + + if (DebugReads) { + fprintf(stderr, "stack %d arg read %p\n", frameIndex, v); + } + + targetMask = SiteMask(lir::Operand::MemoryMask, 0, frameIndex); + } + + this->addRead(c, v, targetMask); + + ++index; + + if ((++argumentIndex) >= arguments.count) { + break; + } + } + } + + if (DebugReads) { + fprintf(stderr, "address read %p\n", address); + } + + { + bool thunk; + OperandMask op; + c->arch->plan((flags & Compiler::Aligned) ? lir::AlignedCall : lir::Call, + c->targetInfo.pointerSize, + op, + &thunk); + + assertT(c, not thunk); + + this->addRead( + c, + address, + SiteMask(op.typeMask, registerMask & op.lowRegisterMask, AnyFrameIndex)); + } + + Stack* stack = stackBefore; + + if (callingConvention == ir::CallingConvention::Avian) { + for (size_t i = 0; i < arguments.count; i++) { + stack = stack->next; + } + for (int i = stackArgumentFootprint - 1; i >= 0; --i) { + Value* v = static_cast(arguments[i]); + + if ((c->targetInfo.pointerSize == 8 + && (v == 0 || (i >= 1 && arguments[i - 1] == 0))) + || (c->targetInfo.pointerSize == 4 && v->nextWord != v)) { + assertT(c, + c->targetInfo.pointerSize == 8 + or v->nextWord == arguments[i - 1]); + + arguments[i] = arguments[i - 1]; + --i; + } + arguments[i] = v; + } + + int returnAddressIndex; + int framePointerIndex; + int frameOffset; + + if (TailCalls and (flags & Compiler::TailJump)) { + int base = frameBase(c); + returnAddressIndex = base + c->arch->returnAddressOffset(); + if (UseFramePointer) { + framePointerIndex = base + c->arch->framePointerOffset(); + } else { + framePointerIndex = -1; + } + + frameOffset = totalFrameSize(c) + - c->arch->argumentFootprint(stackArgumentFootprint); + } else { + returnAddressIndex = -1; + framePointerIndex = -1; + frameOffset = 0; + } + + for (unsigned i = 0; i < stackArgumentFootprint; ++i) { + Value* v = static_cast(arguments[i]); + if (v) { + int frameIndex = i + frameOffset; + + if (DebugReads) { + fprintf(stderr, + "stack arg read %p at %d of %d\n", + v, + frameIndex, + totalFrameSize(c)); + } + + if (static_cast(frameIndex) == returnAddressIndex) { + returnAddressSurrogate = v; + this->addRead(c, v, generalRegisterMask(c)); + } else if (static_cast(frameIndex) == framePointerIndex) { + framePointerSurrogate = v; + this->addRead(c, v, generalRegisterMask(c)); + } else { + this->addRead( + c, v, SiteMask(lir::Operand::MemoryMask, 0, frameIndex)); + } + } + } + } + + if ((not TailCalls) or (flags & Compiler::TailJump) == 0) { + stackArgumentIndex = c->localFootprint; + if (stackBefore) { + stackArgumentIndex += stackBefore->index + 1 - stackArgumentFootprint; + } + + popIndex = c->alignedFrameSize + c->parameterFootprint + - c->arch->frameFooterSize() - stackArgumentIndex; + + assertT(c, static_cast(popIndex) >= 0); + + while (stack) { + if (stack->value) { + unsigned logicalIndex + = compiler::frameIndex(c, stack->index + c->localFootprint); + + if (DebugReads) { + fprintf(stderr, + "stack save read %p at %d of %d\n", + stack->value, + logicalIndex, + totalFrameSize(c)); + } + + this->addRead(c, + stack->value, + SiteMask(lir::Operand::MemoryMask, 0, logicalIndex)); + } + + stack = stack->next; + } + + saveLocals(c, this); + } + } + + virtual const char* name() + { + return "CallEvent"; + } + + virtual void compile(Context* c) + { + lir::UnaryOperation op; + + unsigned footprint = c->arch->argumentFootprint(stackArgumentFootprint); + + if (TailCalls and (flags & Compiler::TailJump)) { + if (flags & Compiler::LongJumpOrCall) { + if (flags & Compiler::Aligned) { + op = lir::AlignedLongJump; + } else { + op = lir::LongJump; + } + } else if (flags & Compiler::Aligned) { + op = lir::AlignedJump; + } else { + op = lir::Jump; + } + + assertT( + c, + returnAddressSurrogate == 0 + or returnAddressSurrogate->source->type(c) == lir::Operand::Type::RegisterPair); + assertT( + c, + framePointerSurrogate == 0 + or framePointerSurrogate->source->type(c) == lir::Operand::Type::RegisterPair); + + Register ras; + if (returnAddressSurrogate) { + returnAddressSurrogate->source->freeze(c, returnAddressSurrogate); + + ras = static_cast(returnAddressSurrogate->source) + ->number; + } else { + ras = NoRegister; + } + + Register fps; + if (framePointerSurrogate) { + framePointerSurrogate->source->freeze(c, framePointerSurrogate); + + fps = static_cast(framePointerSurrogate->source)->number; + } else { + fps = NoRegister; + } + + int offset = static_cast(footprint) + - static_cast( + c->arch->argumentFootprint(c->parameterFootprint)); + + c->assembler->popFrameForTailCall(c->alignedFrameSize, offset, ras, fps); + } else if (flags & Compiler::LongJumpOrCall) { + if (flags & Compiler::Aligned) { + op = lir::AlignedLongCall; + } else { + op = lir::LongCall; + } + } else if (flags & Compiler::Aligned) { + op = lir::AlignedCall; + } else { + op = lir::Call; + } + + apply(c, op, c->targetInfo.pointerSize, address->source, address->source); + + if (traceHandler) { + traceHandler->handleTrace(codePromise(c, c->assembler->offset(true)), + stackArgumentIndex); + } + + if (TailCalls) { + if (flags & Compiler::TailJump) { + if (returnAddressSurrogate) { + returnAddressSurrogate->source->thaw(c, returnAddressSurrogate); + } + + if (framePointerSurrogate) { + framePointerSurrogate->source->thaw(c, framePointerSurrogate); + } + } else if (footprint > c->arch->stackAlignmentInWords()) { + c->assembler->adjustFrame(footprint - c->arch->stackAlignmentInWords()); + } + } + + clean(c, this, stackBefore, localsBefore, reads, popIndex); + + if (resultValue->type.size(c->targetInfo) and live(c, resultValue)) { + resultValue->addSite(c, registerSite(c, c->arch->returnLow())); + if (resultValue->type.size(c->targetInfo) > c->targetInfo.pointerSize + and live(c, resultValue->nextWord)) { + resultValue->nextWord->addSite(c, + registerSite(c, c->arch->returnHigh())); + } + } + } + + virtual bool allExits() + { + return (flags & Compiler::TailJump) != 0; + } + + Value* address; + TraceHandler* traceHandler; + Value* resultValue; + Value* returnAddressSurrogate; + Value* framePointerSurrogate; + unsigned popIndex; + unsigned stackArgumentIndex; + unsigned flags; + unsigned stackArgumentFootprint; +}; + +void appendCall(Context* c, + Value* address, + ir::CallingConvention callingConvention, + unsigned flags, + TraceHandler* traceHandler, + Value* result, + util::Slice arguments) +{ + append(c, + new (c->zone) CallEvent(c, + address, + callingConvention, + flags, + traceHandler, + result, + arguments)); +} + +class ReturnEvent : public Event { + public: + ReturnEvent(Context* c, Value* value) : Event(c), value(value) + { + if (value) { + this->addReads(c, + value, + value->type.size(c->targetInfo), + SiteMask::fixedRegisterMask(c->arch->returnLow()), + SiteMask::fixedRegisterMask(c->arch->returnHigh())); + } + } + + virtual const char* name() + { + return "ReturnEvent"; + } + + virtual void compile(Context* c) + { + for (Read* r = reads; r; r = r->eventNext) { + popRead(c, this, r->value); + } + + if (not this->isUnreachable()) { + c->assembler->popFrameAndPopArgumentsAndReturn( + c->alignedFrameSize, + c->arch->argumentFootprint(c->parameterFootprint)); + } + } + + Value* value; +}; + +void appendReturn(Context* c, Value* value) +{ + append(c, new (c->zone) ReturnEvent(c, value)); +} + +class MoveEvent : public Event { + public: + MoveEvent(Context* c, + lir::BinaryOperation op, + unsigned srcSize, + unsigned srcSelectSize, + Value* srcValue, + unsigned dstSize, + Value* dstValue, + const SiteMask& srcLowMask, + const SiteMask& srcHighMask) + : Event(c), + op(op), + srcSize(srcSize), + srcSelectSize(srcSelectSize), + srcValue(srcValue), + dstSize(dstSize), + dstValue(dstValue) + { + assertT(c, srcSelectSize <= srcSize); + + bool noop = srcSelectSize >= dstSize; + + if (dstSize > c->targetInfo.pointerSize) { + dstValue->grow(c); + } + + if (srcSelectSize > c->targetInfo.pointerSize) { + srcValue->maybeSplit(c); + } + + this->addReads( + c, + srcValue, + srcSelectSize, + srcLowMask, + noop ? dstValue : 0, + srcHighMask, + noop and dstSize > c->targetInfo.pointerSize ? dstValue->nextWord : 0); + } + + virtual const char* name() + { + return "MoveEvent"; + } + + virtual void compile(Context* c) + { + OperandMask dst; + + c->arch->planDestination( + op, + srcSelectSize, + OperandMask( + 1 << (unsigned)srcValue->source->type(c), + srcValue->source->registerMask(c), + srcValue->nextWord->source->registerMask(c)), + dstSize, + dst); + + SiteMask dstLowMask = SiteMask::lowPart(dst); + SiteMask dstHighMask = SiteMask::highPart(dst); + + if (srcSelectSize >= c->targetInfo.pointerSize + and dstSize >= c->targetInfo.pointerSize and srcSelectSize >= dstSize) { + if (dstValue->target) { + if (dstSize > c->targetInfo.pointerSize) { + if (srcValue->source->registerSize(c) > c->targetInfo.pointerSize) { + apply(c, + lir::Move, + srcSelectSize, + srcValue->source, + srcValue->source, + dstSize, + dstValue->target, + dstValue->target); + + if (live(c, dstValue) == 0) { + dstValue->removeSite(c, dstValue->target); + if (dstSize > c->targetInfo.pointerSize) { + dstValue->nextWord->removeSite(c, dstValue->nextWord->target); + } + } + } else { + srcValue->nextWord->source->freeze(c, srcValue->nextWord); + + maybeMove(c, + lir::Move, + c->targetInfo.pointerSize, + c->targetInfo.pointerSize, + srcValue, + c->targetInfo.pointerSize, + dstValue, + dstLowMask); + + srcValue->nextWord->source->thaw(c, srcValue->nextWord); + + maybeMove(c, + lir::Move, + c->targetInfo.pointerSize, + c->targetInfo.pointerSize, + srcValue->nextWord, + c->targetInfo.pointerSize, + dstValue->nextWord, + dstHighMask); + } + } else { + maybeMove(c, + lir::Move, + c->targetInfo.pointerSize, + c->targetInfo.pointerSize, + srcValue, + c->targetInfo.pointerSize, + dstValue, + dstLowMask); + } + } else { + Site* low = pickSiteOrMove(c, srcValue, dstValue, 0, 0); + if (dstSize > c->targetInfo.pointerSize) { + pickSiteOrMove(c, srcValue->nextWord, dstValue->nextWord, low, 1); + } + } + } else if (srcSelectSize <= c->targetInfo.pointerSize + and dstSize <= c->targetInfo.pointerSize) { + maybeMove(c, + op, + srcSize, + srcSelectSize, + srcValue, + dstSize, + dstValue, + dstLowMask); + } else { + assertT(c, srcSize == c->targetInfo.pointerSize); + assertT(c, srcSelectSize == c->targetInfo.pointerSize); + + if (dstValue->nextWord->target or live(c, dstValue->nextWord)) { + assertT(c, dstLowMask.typeMask & lir::Operand::RegisterPairMask); + + Site* low = freeRegisterSite(c, dstLowMask.registerMask); + + srcValue->source->freeze(c, srcValue); + + dstValue->addSite(c, low); + + low->freeze(c, dstValue); + + if (DebugMoves) { + char srcb[256]; + srcValue->source->toString(c, srcb, 256); + char dstb[256]; + low->toString(c, dstb, 256); + fprintf(stderr, "move %s to %s for %p\n", srcb, dstb, srcValue); + } + + apply(c, + lir::Move, + c->targetInfo.pointerSize, + srcValue->source, + srcValue->source, + c->targetInfo.pointerSize, + low, + low); + + low->thaw(c, dstValue); + + srcValue->source->thaw(c, srcValue); + + assertT(c, dstHighMask.typeMask & lir::Operand::RegisterPairMask); + + Site* high = freeRegisterSite(c, dstHighMask.registerMask); + + low->freeze(c, dstValue); + + dstValue->nextWord->addSite(c, high); + + high->freeze(c, dstValue->nextWord); + + if (DebugMoves) { + char srcb[256]; + low->toString(c, srcb, 256); + char dstb[256]; + high->toString(c, dstb, 256); + fprintf(stderr, + "extend %s to %s for %p %p\n", + srcb, + dstb, + dstValue, + dstValue->nextWord); + } + + apply(c, + lir::Move, + c->targetInfo.pointerSize, + low, + low, + dstSize, + low, + high); + + high->thaw(c, dstValue->nextWord); + + low->thaw(c, dstValue); + } else { + pickSiteOrMove(c, srcValue, dstValue, 0, 0); + } + } + + for (Read* r = reads; r; r = r->eventNext) { + popRead(c, this, r->value); + } + } + + lir::BinaryOperation op; + unsigned srcSize; + unsigned srcSelectSize; + Value* srcValue; + unsigned dstSize; + Value* dstValue; +}; + +void appendMove(Context* c, + lir::BinaryOperation op, + unsigned srcSize, + unsigned srcSelectSize, + Value* srcValue, + unsigned dstSize, + Value* dstValue) +{ + bool thunk; + OperandMask src; + + c->arch->planSource(op, srcSelectSize, src, dstSize, &thunk); + + assertT(c, not thunk); + + append(c, + new (c->zone) MoveEvent(c, + op, + srcSize, + srcSelectSize, + srcValue, + dstSize, + dstValue, + SiteMask::lowPart(src), + SiteMask::highPart(src))); +} + +void freezeSource(Context* c, unsigned size, Value* v) +{ + v->source->freeze(c, v); + if (size > c->targetInfo.pointerSize) { + v->nextWord->source->freeze(c, v->nextWord); + } +} + +void thawSource(Context* c, unsigned size, Value* v) +{ + v->source->thaw(c, v); + if (size > c->targetInfo.pointerSize) { + v->nextWord->source->thaw(c, v->nextWord); + } +} + +Read* liveNext(Context* c, Value* v) +{ + assertT(c, v->buddy->hasBuddy(c, v)); + + Read* r = v->reads->next(c); + if (valid(r)) + return r; + + for (Value* p = v->buddy; p != v; p = p->buddy) { + if (valid(p->reads)) + return p->reads; + } + + return 0; +} + +void preserve(Context* c, Value* v, Read* r, Site* s) +{ + s->freeze(c, v); + + maybeMove(c, r, false, true, 0); + + s->thaw(c, v); +} + +Site* getTarget(Context* c, + Value* value, + Value* result, + const SiteMask& resultMask) +{ + Site* s; + Value* v; + Read* r = liveNext(c, value); + if (value->source->match(c, static_cast(resultMask)) + and (r == 0 + or value->source->loneMatch( + c, static_cast(resultMask)))) { + s = value->source; + v = value; + if (r and v->uniqueSite(c, s)) { + preserve(c, v, r, s); + } + } else { + SingleRead r(resultMask, 0); + r.value = result; + r.successor_ = result; + s = pickTargetSite(c, &r, true); + v = result; + result->addSite(c, s); + } + + v->removeSite(c, s); + + s->freeze(c, v); + + return s; +} + +class CombineEvent : public Event { + public: + CombineEvent(Context* c, + lir::TernaryOperation op, + Value* firstValue, + Value* secondValue, + Value* resultValue, + const SiteMask& firstLowMask, + const SiteMask& firstHighMask, + const SiteMask& secondLowMask, + const SiteMask& secondHighMask) + : Event(c), + op(op), + firstValue(firstValue), + secondValue(secondValue), + resultValue(resultValue) + { + this->addReads(c, + firstValue, + firstValue->type.size(c->targetInfo), + firstLowMask, + firstHighMask); + + if (resultValue->type.size(c->targetInfo) > c->targetInfo.pointerSize) { + resultValue->grow(c); + } + + bool condensed = c->arch->alwaysCondensed(op); + + this->addReads(c, + secondValue, + secondValue->type.size(c->targetInfo), + secondLowMask, + condensed ? resultValue : 0, + secondHighMask, + condensed ? resultValue->nextWord : 0); + } + + virtual const char* name() + { + return "CombineEvent"; + } + + virtual void compile(Context* c) + { + assertT( + c, + firstValue->source->type(c) == firstValue->nextWord->source->type(c)); + + if (false) { + if (secondValue->source->type(c) + != secondValue->nextWord->source->type(c)) { + fprintf(stderr, + "%p %p %d : %p %p %d\n", + secondValue, + secondValue->source, + static_cast(secondValue->source->type(c)), + secondValue->nextWord, + secondValue->nextWord->source, + static_cast(secondValue->nextWord->source->type(c))); + } + } + + assertT( + c, + secondValue->source->type(c) == secondValue->nextWord->source->type(c)); + + freezeSource(c, firstValue->type.size(c->targetInfo), firstValue); + + OperandMask cMask; + + c->arch->planDestination( + op, + firstValue->type.size(c->targetInfo), + OperandMask( + 1 << (unsigned)firstValue->source->type(c), + firstValue->source->registerMask(c), + firstValue->nextWord->source->registerMask(c)), + secondValue->type.size(c->targetInfo), + OperandMask( + 1 << (unsigned)secondValue->source->type(c), + secondValue->source->registerMask(c), + secondValue->nextWord->source->registerMask(c)), + resultValue->type.size(c->targetInfo), + cMask); + + SiteMask resultLowMask = SiteMask::lowPart(cMask); + SiteMask resultHighMask = SiteMask::highPart(cMask); + + Site* low = getTarget(c, secondValue, resultValue, resultLowMask); + unsigned lowSize = low->registerSize(c); + Site* high = (resultValue->type.size(c->targetInfo) > lowSize + ? getTarget(c, + secondValue->nextWord, + resultValue->nextWord, + resultHighMask) + : low); + + if (false) { + fprintf(stderr, + "combine %p:%p and %p:%p into %p:%p\n", + firstValue, + firstValue->nextWord, + secondValue, + secondValue->nextWord, + resultValue, + resultValue->nextWord); + } + + apply(c, + op, + firstValue->type.size(c->targetInfo), + firstValue->source, + firstValue->nextWord->source, + secondValue->type.size(c->targetInfo), + secondValue->source, + secondValue->nextWord->source, + resultValue->type.size(c->targetInfo), + low, + high); + + thawSource(c, firstValue->type.size(c->targetInfo), firstValue); + + for (Read* r = reads; r; r = r->eventNext) { + popRead(c, this, r->value); + } + + low->thaw(c, secondValue); + if (resultValue->type.size(c->targetInfo) > lowSize) { + high->thaw(c, secondValue->nextWord); + } + + if (live(c, resultValue)) { + resultValue->addSite(c, low); + if (resultValue->type.size(c->targetInfo) > lowSize + and live(c, resultValue->nextWord)) { + resultValue->nextWord->addSite(c, high); + } + } + } + + lir::TernaryOperation op; + Value* firstValue; + Value* secondValue; + Value* resultValue; +}; + +void appendCombine(Context* c, + lir::TernaryOperation op, + Value* firstValue, + Value* secondValue, + Value* resultValue) +{ + bool thunk; + OperandMask firstMask; + OperandMask secondMask; + c->arch->planSource(op, + firstValue->type.size(c->targetInfo), + firstMask, + secondValue->type.size(c->targetInfo), + secondMask, + resultValue->type.size(c->targetInfo), + &thunk); + + if (thunk) { + const size_t MaxValueCount = 6; + FixedSliceStack slice; + size_t stackBase = c->stack ? c->stack->index + 1 : 0; + + bool threadParameter; + intptr_t handler + = c->client->getThunk(op, + firstValue->type.size(c->targetInfo), + resultValue->type.size(c->targetInfo), + &threadParameter); + + unsigned stackSize = ceilingDivide(secondValue->type.size(c->targetInfo), + c->targetInfo.pointerSize) + + ceilingDivide(firstValue->type.size(c->targetInfo), + c->targetInfo.pointerSize); + + slicePush(c, + ceilingDivide(secondValue->type.size(c->targetInfo), + c->targetInfo.pointerSize), + secondValue, + stackBase, + slice); + slicePush(c, + ceilingDivide(firstValue->type.size(c->targetInfo), + c->targetInfo.pointerSize), + firstValue, + stackBase, + slice); + + if (threadParameter) { + ++stackSize; + + slicePush(c, 1, threadRegister(c), stackBase, slice); + } + + appendCall(c, + value(c, ir::Type::addr(), constantSite(c, handler)), + ir::CallingConvention::Native, + 0, + 0, + resultValue, + slice); + } else { + append(c, + new (c->zone) CombineEvent(c, + op, + firstValue, + secondValue, + resultValue, + SiteMask::lowPart(firstMask), + SiteMask::highPart(firstMask), + SiteMask::lowPart(secondMask), + SiteMask::highPart(secondMask))); + } +} + +class TranslateEvent : public Event { + public: + TranslateEvent(Context* c, + lir::BinaryOperation op, + Value* firstValue, + Value* resultValue, + const SiteMask& valueLowMask, + const SiteMask& valueHighMask) + : Event(c), op(op), firstValue(firstValue), resultValue(resultValue) + { + bool condensed = c->arch->alwaysCondensed(op); + + if (resultValue->type.size(c->targetInfo) > c->targetInfo.pointerSize) { + resultValue->grow(c); + } + + this->addReads(c, + firstValue, + firstValue->type.size(c->targetInfo), + valueLowMask, + condensed ? resultValue : 0, + valueHighMask, + condensed ? resultValue->nextWord : 0); + } + + virtual const char* name() + { + return "TranslateEvent"; + } + + virtual void compile(Context* c) + { + assertT( + c, + firstValue->source->type(c) == firstValue->nextWord->source->type(c)); + + OperandMask bMask; + + c->arch->planDestination( + op, + firstValue->type.size(c->targetInfo), + OperandMask( + 1 << (unsigned)firstValue->source->type(c), + firstValue->source->registerMask(c), + firstValue->nextWord->source->registerMask(c)), + resultValue->type.size(c->targetInfo), + bMask); + + SiteMask resultLowMask = SiteMask::lowPart(bMask); + SiteMask resultHighMask = SiteMask::highPart(bMask); + + Site* low = getTarget(c, firstValue, resultValue, resultLowMask); + unsigned lowSize = low->registerSize(c); + Site* high = (resultValue->type.size(c->targetInfo) > lowSize + ? getTarget(c, + firstValue->nextWord, + resultValue->nextWord, + resultHighMask) + : low); + + apply(c, + op, + firstValue->type.size(c->targetInfo), + firstValue->source, + firstValue->nextWord->source, + resultValue->type.size(c->targetInfo), + low, + high); + + for (Read* r = reads; r; r = r->eventNext) { + popRead(c, this, r->value); + } + + low->thaw(c, firstValue); + if (resultValue->type.size(c->targetInfo) > lowSize) { + high->thaw(c, firstValue->nextWord); + } + + if (live(c, resultValue)) { + resultValue->addSite(c, low); + if (resultValue->type.size(c->targetInfo) > lowSize + and live(c, resultValue->nextWord)) { + resultValue->nextWord->addSite(c, high); + } + } + } + + lir::BinaryOperation op; + Value* firstValue; + Value* resultValue; + Read* resultRead; + SiteMask resultLowMask; + SiteMask resultHighMask; +}; + +void appendTranslate(Context* c, + lir::BinaryOperation op, + Value* firstValue, + Value* resultValue) +{ + assertT(c, + firstValue->type.size(c->targetInfo) + == firstValue->type.size(c->targetInfo)); + assertT(c, + resultValue->type.size(c->targetInfo) + == resultValue->type.size(c->targetInfo)); + + bool thunk; + OperandMask first; + + c->arch->planSource(op, + firstValue->type.size(c->targetInfo), + first, + resultValue->type.size(c->targetInfo), + &thunk); + + if (thunk) { + size_t stackBase = c->stack ? c->stack->index + 1 : 0; + FixedSliceStack slice; + + slicePush(c, + ceilingDivide(firstValue->type.size(c->targetInfo), + c->targetInfo.pointerSize), + firstValue, + stackBase, + slice); + + appendCall(c, + value(c, + ir::Type::addr(), + constantSite(c, + c->client->getThunk( + op, + firstValue->type.size(c->targetInfo), + resultValue->type.size(c->targetInfo)))), + ir::CallingConvention::Native, + 0, + 0, + resultValue, + slice); + } else { + append(c, + new (c->zone) TranslateEvent(c, + op, + firstValue, + resultValue, + SiteMask::lowPart(first), + SiteMask::highPart(first))); + } +} + +class OperationEvent : public Event { + public: + OperationEvent(Context* c, lir::Operation op) : Event(c), op(op) + { + } + + virtual const char* name() + { + return "OperationEvent"; + } + + virtual void compile(Context* c) + { + c->assembler->apply(op); + } + + lir::Operation op; +}; + +void appendOperation(Context* c, lir::Operation op) +{ + append(c, new (c->zone) OperationEvent(c, op)); +} + +ConstantSite* findConstantSite(Context* c, Value* v) +{ + for (SiteIterator it(c, v); it.hasMore();) { + Site* s = it.next(); + if (s->type(c) == lir::Operand::Type::Constant) { + return static_cast(s); + } + } + return 0; +} + +void moveIfConflict(Context* c, Value* v, MemorySite* s) +{ + if (v->reads) { + SiteMask mask(lir::Operand::RegisterPairMask, ~0, AnyFrameIndex); + v->reads->intersect(&mask); + if (s->conflicts(mask)) { + maybeMove(c, v->reads, true, false); + v->removeSite(c, s); + } + } +} + +class MemoryEvent : public Event { + public: + MemoryEvent(Context* c, + Value* base, + int displacement, + Value* index, + unsigned scale, + Value* result) + : Event(c), + base(base), + displacement(displacement), + index(index), + scale(scale), + result(result) + { + this->addRead(c, base, generalRegisterMask(c)); + if (index) { + this->addRead(c, index, generalRegisterOrConstantMask(c)); + } + } + + virtual const char* name() + { + return "MemoryEvent"; + } + + virtual void compile(Context* c) + { + Register indexRegister; + int displacement = this->displacement; + unsigned scale = this->scale; + if (index) { + ConstantSite* constant = findConstantSite(c, index); + + if (constant) { + indexRegister = NoRegister; + displacement += (constant->value->value() * scale); + scale = 1; + } else { + assertT(c, index->source->type(c) == lir::Operand::Type::RegisterPair); + indexRegister = static_cast(index->source)->number; + } + } else { + indexRegister = NoRegister; + } + assertT(c, base->source->type(c) == lir::Operand::Type::RegisterPair); + Register baseRegister = static_cast(base->source)->number; + + popRead(c, this, base); + if (index) { + if (c->targetInfo.pointerSize == 8 and indexRegister != NoRegister) { + apply(c, + lir::Move, + 4, + index->source, + index->source, + 8, + index->source, + index->source); + } + + popRead(c, this, index); + } + + MemorySite* site + = memorySite(c, baseRegister, displacement, indexRegister, scale); + + MemorySite* low; + if (result->nextWord != result) { + MemorySite* high = static_cast(site->copyHigh(c)); + low = static_cast(site->copyLow(c)); + + result->nextWord->target = high; + result->nextWord->addSite(c, high); + moveIfConflict(c, result->nextWord, high); + } else { + low = site; + } + + result->target = low; + result->addSite(c, low); + moveIfConflict(c, result, low); + } + + Value* base; + int displacement; + Value* index; + unsigned scale; + Value* result; +}; + +void appendMemory(Context* c, + Value* base, + int displacement, + Value* index, + unsigned scale, + Value* result) +{ + append(c, + new (c->zone) + MemoryEvent(c, base, displacement, index, scale, result)); +} + +double asFloat(unsigned size, int64_t v) +{ + if (size == 4) { + return vm::bitsToFloat(v); + } else { + return vm::bitsToDouble(v); + } +} + +bool unordered(double a, double b) +{ + return not(a >= b or a < b); +} + +bool shouldJump(Context* c, + lir::TernaryOperation op, + unsigned size, + int64_t b, + int64_t a) +{ + switch (op) { + case lir::JumpIfEqual: + return a == b; + + case lir::JumpIfNotEqual: + return a != b; + + case lir::JumpIfLess: + return a < b; + + case lir::JumpIfGreater: + return a > b; + + case lir::JumpIfLessOrEqual: + return a <= b; + + case lir::JumpIfGreaterOrEqual: + return a >= b; + + case lir::JumpIfFloatEqual: + return asFloat(size, a) == asFloat(size, b); + + case lir::JumpIfFloatNotEqual: + return asFloat(size, a) != asFloat(size, b); + + case lir::JumpIfFloatLess: + return asFloat(size, a) < asFloat(size, b); + + case lir::JumpIfFloatGreater: + return asFloat(size, a) > asFloat(size, b); + + case lir::JumpIfFloatLessOrEqual: + return asFloat(size, a) <= asFloat(size, b); + + case lir::JumpIfFloatGreaterOrEqual: + return asFloat(size, a) >= asFloat(size, b); + + case lir::JumpIfFloatLessOrUnordered: + return asFloat(size, a) < asFloat(size, b) + or unordered(asFloat(size, a), asFloat(size, b)); + + case lir::JumpIfFloatGreaterOrUnordered: + return asFloat(size, a) > asFloat(size, b) + or unordered(asFloat(size, a), asFloat(size, b)); + + case lir::JumpIfFloatLessOrEqualOrUnordered: + return asFloat(size, a) <= asFloat(size, b) + or unordered(asFloat(size, a), asFloat(size, b)); + + case lir::JumpIfFloatGreaterOrEqualOrUnordered: + return asFloat(size, a) >= asFloat(size, b) + or unordered(asFloat(size, a), asFloat(size, b)); + + default: + abort(c); + } +} + +lir::TernaryOperation thunkBranch(Context* c, lir::TernaryOperation op) +{ + switch (op) { + case lir::JumpIfFloatEqual: + return lir::JumpIfEqual; + + case lir::JumpIfFloatNotEqual: + return lir::JumpIfNotEqual; + + case lir::JumpIfFloatLess: + case lir::JumpIfFloatLessOrUnordered: + return lir::JumpIfLess; + + case lir::JumpIfFloatGreater: + case lir::JumpIfFloatGreaterOrUnordered: + return lir::JumpIfGreater; + + case lir::JumpIfFloatLessOrEqual: + case lir::JumpIfFloatLessOrEqualOrUnordered: + return lir::JumpIfLessOrEqual; + + case lir::JumpIfFloatGreaterOrEqual: + case lir::JumpIfFloatGreaterOrEqualOrUnordered: + return lir::JumpIfGreaterOrEqual; + + default: + abort(c); + } +} + +class BranchEvent : public Event { + public: + BranchEvent(Context* c, + lir::TernaryOperation op, + Value* firstValue, + Value* secondValue, + Value* addressValue, + const SiteMask& firstLowMask, + const SiteMask& firstHighMask, + const SiteMask& secondLowMask, + const SiteMask& secondHighMask) + : Event(c), + op(op), + firstValue(firstValue), + secondValue(secondValue), + addressValue(addressValue) + { + this->addReads(c, + firstValue, + firstValue->type.size(c->targetInfo), + firstLowMask, + firstHighMask); + this->addReads(c, + secondValue, + firstValue->type.size(c->targetInfo), + secondLowMask, + secondHighMask); + + OperandMask dstMask; + c->arch->planDestination(op, + firstValue->type.size(c->targetInfo), + OperandMask(0, 0, 0), + firstValue->type.size(c->targetInfo), + OperandMask(0, 0, 0), + c->targetInfo.pointerSize, + dstMask); + + this->addRead(c, addressValue, SiteMask::lowPart(dstMask)); + } + + virtual const char* name() + { + return "BranchEvent"; + } + + virtual void compile(Context* c) + { + ConstantSite* firstConstant = findConstantSite(c, firstValue); + ConstantSite* secondConstant = findConstantSite(c, secondValue); + + if (not this->isUnreachable()) { + if (firstConstant and secondConstant and firstConstant->value->resolved() + and secondConstant->value->resolved()) { + int64_t firstConstVal = firstConstant->value->value(); + int64_t secondConstVal = secondConstant->value->value(); + + if (firstValue->type.size(c->targetInfo) > c->targetInfo.pointerSize) { + firstConstVal + |= findConstantSite(c, firstValue->nextWord)->value->value() + << 32; + secondConstVal + |= findConstantSite(c, secondValue->nextWord)->value->value() + << 32; + } + + if (shouldJump(c, + op, + firstValue->type.size(c->targetInfo), + firstConstVal, + secondConstVal)) { + apply(c, + lir::Jump, + c->targetInfo.pointerSize, + addressValue->source, + addressValue->source); + } + } else { + freezeSource(c, firstValue->type.size(c->targetInfo), firstValue); + freezeSource(c, firstValue->type.size(c->targetInfo), secondValue); + freezeSource(c, c->targetInfo.pointerSize, addressValue); + + apply(c, + op, + firstValue->type.size(c->targetInfo), + firstValue->source, + firstValue->nextWord->source, + firstValue->type.size(c->targetInfo), + secondValue->source, + secondValue->nextWord->source, + c->targetInfo.pointerSize, + addressValue->source, + addressValue->source); + + thawSource(c, c->targetInfo.pointerSize, addressValue); + thawSource(c, firstValue->type.size(c->targetInfo), secondValue); + thawSource(c, firstValue->type.size(c->targetInfo), firstValue); + } + } + + for (Read* r = reads; r; r = r->eventNext) { + popRead(c, this, r->value); + } + } + + virtual bool isBranch() + { + return true; + } + + lir::TernaryOperation op; + Value* firstValue; + Value* secondValue; + Value* addressValue; +}; + +void appendBranch(Context* c, + lir::TernaryOperation op, + Value* firstValue, + Value* secondValue, + Value* addressValue) +{ + bool thunk; + OperandMask firstMask; + OperandMask secondMask; + + c->arch->planSource(op, + firstValue->type.size(c->targetInfo), + firstMask, + firstValue->type.size(c->targetInfo), + secondMask, + c->targetInfo.pointerSize, + &thunk); + + if (thunk) { + const size_t MaxValueCount = 4; + FixedSliceStack slice; + size_t stackBase = c->stack ? c->stack->index + 1 : 0; + + bool threadParameter; + intptr_t handler = c->client->getThunk(op, + firstValue->type.size(c->targetInfo), + firstValue->type.size(c->targetInfo), + &threadParameter); + + assertT(c, not threadParameter); + + slicePush(c, + ceilingDivide(firstValue->type.size(c->targetInfo), + c->targetInfo.pointerSize), + secondValue, + stackBase, + slice); + slicePush(c, + ceilingDivide(firstValue->type.size(c->targetInfo), + c->targetInfo.pointerSize), + firstValue, + stackBase, + slice); + + Value* result = value(c, ir::Type::addr()); + appendCall(c, + value(c, ir::Type::addr(), constantSite(c, handler)), + ir::CallingConvention::Native, + 0, + 0, + result, + slice); + + appendBranch( + c, + thunkBranch(c, op), + value(c, ir::Type::addr(), constantSite(c, static_cast(0))), + result, + addressValue); + } else { + append(c, + new (c->zone) BranchEvent(c, + op, + firstValue, + secondValue, + addressValue, + SiteMask::lowPart(firstMask), + SiteMask::highPart(firstMask), + SiteMask::lowPart(secondMask), + SiteMask::highPart(secondMask))); + } +} + +void clean(Context* c, Value* v, unsigned popIndex) +{ + for (SiteIterator it(c, v); it.hasMore();) { + Site* s = it.next(); + if (not(s->match(c, SiteMask(lir::Operand::MemoryMask, 0, AnyFrameIndex)) + and offsetToFrameIndex(c, static_cast(s)->offset) + >= popIndex)) { + if (false + and s->match(c, + SiteMask(lir::Operand::MemoryMask, 0, AnyFrameIndex))) { + char buffer[256]; + s->toString(c, buffer, 256); + fprintf(stderr, + "remove %s from %p at %d pop offset 0x%x\n", + buffer, + v, + offsetToFrameIndex(c, static_cast(s)->offset), + frameIndexToOffset(c, popIndex)); + } + it.remove(c); + } + } +} + +void clean(Context* c, + Event* e, + Stack* stack, + Local* locals, + Read* reads, + unsigned popIndex) +{ + for (FrameIterator it(c, stack, locals); it.hasMore();) { + FrameIterator::Element e = it.next(c); + clean(c, e.value, popIndex); + } + + for (Read* r = reads; r; r = r->eventNext) { + popRead(c, e, r->value); + } +} + +class JumpEvent : public Event { + public: + JumpEvent(Context* c, + lir::UnaryOperation op, + Value* address, + bool exit, + bool cleanLocals) + : Event(c), op(op), address(address), exit(exit), cleanLocals(cleanLocals) + { + bool thunk; + OperandMask mask; + c->arch->plan(op, c->targetInfo.pointerSize, mask, &thunk); + + assertT(c, not thunk); + + this->addRead(c, address, SiteMask::lowPart(mask)); + } + + virtual const char* name() + { + return "JumpEvent"; + } + + virtual void compile(Context* c) + { + if (not this->isUnreachable()) { + apply(c, op, c->targetInfo.pointerSize, address->source, address->source); + } + + for (Read* r = reads; r; r = r->eventNext) { + popRead(c, this, r->value); + } + + if (cleanLocals) { + for (FrameIterator it(c, 0, c->locals); it.hasMore();) { + FrameIterator::Element e = it.next(c); + clean(c, e.value, 0); + } + } + } + + virtual bool isBranch() + { + return true; + } + + virtual bool allExits() + { + return exit or this->isUnreachable(); + } + + lir::UnaryOperation op; + Value* address; + bool exit; + bool cleanLocals; +}; + +void appendJump(Context* c, + lir::UnaryOperation op, + Value* address, + bool exit, + bool cleanLocals) +{ + append(c, new (c->zone) JumpEvent(c, op, address, exit, cleanLocals)); +} + +class BoundsCheckEvent : public Event { + public: + BoundsCheckEvent(Context* c, + Value* object, + unsigned lengthOffset, + Value* index, + intptr_t handler) + : Event(c), + object(object), + lengthOffset(lengthOffset), + index(index), + handler(handler) + { + this->addRead(c, object, generalRegisterMask(c)); + this->addRead(c, index, generalRegisterOrConstantMask(c)); + } + + virtual const char* name() + { + return "BoundsCheckEvent"; + } + + virtual void compile(Context* c) + { + Assembler* a = c->assembler; + + ConstantSite* constant = findConstantSite(c, index); + CodePromise* outOfBoundsPromise = 0; + + if (constant) { + if (constant->value->value() < 0) { + lir::Constant handlerConstant(resolvedPromise(c, handler)); + a->apply(lir::Call, + OperandInfo(c->targetInfo.pointerSize, + lir::Operand::Type::Constant, + &handlerConstant)); + } + } else { + outOfBoundsPromise = compiler::codePromise(c, static_cast(0)); + + ConstantSite zero(resolvedPromise(c, 0)); + ConstantSite oob(outOfBoundsPromise); + apply(c, + lir::JumpIfLess, + 4, + &zero, + &zero, + 4, + index->source, + index->source, + c->targetInfo.pointerSize, + &oob, + &oob); + } + + if (constant == 0 or constant->value->value() >= 0) { + assertT(c, object->source->type(c) == lir::Operand::Type::RegisterPair); + MemorySite length(static_cast(object->source)->number, + lengthOffset, + NoRegister, + 1); + length.acquired = true; + + CodePromise* nextPromise + = compiler::codePromise(c, static_cast(0)); + + freezeSource(c, c->targetInfo.pointerSize, index); + + ConstantSite next(nextPromise); + apply(c, + lir::JumpIfGreater, + 4, + index->source, + index->source, + 4, + &length, + &length, + c->targetInfo.pointerSize, + &next, + &next); + + thawSource(c, c->targetInfo.pointerSize, index); + + if (constant == 0) { + outOfBoundsPromise->offset = a->offset(); + } + + lir::Constant handlerConstant(resolvedPromise(c, handler)); + a->apply(lir::Call, + OperandInfo(c->targetInfo.pointerSize, + lir::Operand::Type::Constant, + &handlerConstant)); + + nextPromise->offset = a->offset(); + } + + popRead(c, this, object); + popRead(c, this, index); + } + + Value* object; + unsigned lengthOffset; + Value* index; + intptr_t handler; +}; + +void appendBoundsCheck(Context* c, + Value* object, + unsigned lengthOffset, + Value* index, + intptr_t handler) +{ + append(c, + new (c->zone) + BoundsCheckEvent(c, object, lengthOffset, index, handler)); +} + +class FrameSiteEvent : public Event { + public: + FrameSiteEvent(Context* c, Value* value, int index) + : Event(c), value(value), index(index) + { + } + + virtual const char* name() + { + return "FrameSiteEvent"; + } + + virtual void compile(Context* c) + { + if (live(c, value)) { + value->addSite(c, frameSite(c, index)); + } + } + + Value* value; + int index; +}; + +void appendFrameSite(Context* c, Value* value, int index) +{ + append(c, new (c->zone) FrameSiteEvent(c, value, index)); +} + +class SaveLocalsEvent : public Event { + public: + SaveLocalsEvent(Context* c) : Event(c) + { + saveLocals(c, this); + } + + virtual const char* name() + { + return "SaveLocalsEvent"; + } + + virtual void compile(Context* c) + { + for (Read* r = reads; r; r = r->eventNext) { + popRead(c, this, r->value); + } + } +}; + +void appendSaveLocals(Context* c) +{ + append(c, new (c->zone) SaveLocalsEvent(c)); +} + +class DummyEvent : public Event { + public: + DummyEvent(Context* c, Local* locals) : Event(c), locals_(locals) + { + } + + virtual const char* name() + { + return "DummyEvent"; + } + + virtual void compile(Context*) + { + } + + virtual Local* locals() + { + return locals_; + } + + Local* locals_; +}; + +void appendDummy(Context* c) +{ + Stack* stack = c->stack; + Local* locals = c->locals; + LogicalInstruction* i = c->logicalCode[c->logicalIp]; + + c->stack = i->stack; + c->locals = i->locals; + + append(c, new (c->zone) DummyEvent(c, locals)); + + c->stack = stack; + c->locals = locals; +} + +} // namespace compiler +} // namespace codegen +} // namespace avian diff --git a/sgx-jvm/avian/src/codegen/compiler/event.h b/sgx-jvm/avian/src/codegen/compiler/event.h new file mode 100644 index 0000000000..8aa68bec11 --- /dev/null +++ b/sgx-jvm/avian/src/codegen/compiler/event.h @@ -0,0 +1,214 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#ifndef AVIAN_CODEGEN_COMPILER_EVENT_H +#define AVIAN_CODEGEN_COMPILER_EVENT_H + +namespace avian { +namespace codegen { +namespace compiler { + +class Context; +class CodePromise; +class Snapshot; +class Link; +class Site; +class StubRead; + +const bool DebugReads = false; +const bool DebugMoves = false; + +class Event { + public: + Event(Context* c); + + virtual const char* name() = 0; + + virtual void compile(Context* c) = 0; + + virtual bool isBranch() + { + return false; + } + + virtual bool allExits() + { + return false; + } + + virtual Local* locals() + { + return localsBefore; + } + + void addRead(Context* c, Value* v, Read* r); + + void addRead(Context* c, + Value* v, + const SiteMask& mask, + Value* successor = 0); + + void addReads(Context* c, + Value* v, + unsigned size, + const SiteMask& lowMask, + Value* lowSuccessor, + const SiteMask& highMask, + Value* highSuccessor); + + void addReads(Context* c, + Value* v, + unsigned size, + const SiteMask& lowMask, + const SiteMask& highMask); + + CodePromise* makeCodePromise(Context* c); + + bool isUnreachable(); + + Event* next; + Stack* stackBefore; + Local* localsBefore; + Stack* stackAfter; + Local* localsAfter; + CodePromise* promises; + Read* reads; + Site** junctionSites; + Snapshot* snapshots; + Link* predecessors; + Link* successors; + List* visitLinks; + Block* block; + LogicalInstruction* logicalInstruction; + unsigned readCount; +}; + +void finishAddRead(Context* c, Value* v, Read* r); + +class StubReadPair { + public: + Value* value; + StubRead* read; +}; + +class JunctionState { + public: + JunctionState(unsigned frameFootprint) : frameFootprint(frameFootprint) + { + } + + unsigned frameFootprint; + StubReadPair reads[0]; +}; + +class Link { + public: + Link(Event* predecessor, + Link* nextPredecessor, + Event* successor, + Link* nextSuccessor, + ForkState* forkState) + : predecessor(predecessor), + nextPredecessor(nextPredecessor), + successor(successor), + nextSuccessor(nextSuccessor), + forkState(forkState), + junctionState(0) + { + } + + unsigned countPredecessors(); + Link* lastPredecessor(); + unsigned countSuccessors(); + + Event* predecessor; + Link* nextPredecessor; + Event* successor; + Link* nextSuccessor; + ForkState* forkState; + JunctionState* junctionState; +}; + +Link* link(Context* c, + Event* predecessor, + Link* nextPredecessor, + Event* successor, + Link* nextSuccessor, + ForkState* forkState); + +void appendCall(Context* c, + Value* address, + ir::CallingConvention callingConvention, + unsigned flags, + TraceHandler* traceHandler, + Value* result, + util::Slice arguments); + +void appendReturn(Context* c, Value* value); + +void appendMove(Context* c, + lir::BinaryOperation op, + unsigned srcSize, + unsigned srcSelectSize, + Value* src, + unsigned dstSize, + Value* dst); + +void appendCombine(Context* c, + lir::TernaryOperation op, + Value* first, + Value* second, + Value* result); + +void appendTranslate(Context* c, + lir::BinaryOperation op, + Value* first, + Value* result); + +void appendOperation(Context* c, lir::Operation op); + +void appendMemory(Context* c, + Value* base, + int displacement, + Value* index, + unsigned scale, + Value* result); + +void appendBranch(Context* c, + lir::TernaryOperation op, + Value* first, + Value* second, + Value* address); + +void appendJump(Context* c, + lir::UnaryOperation op, + Value* address, + bool exit = false, + bool cleanLocals = false); + +void appendBoundsCheck(Context* c, + Value* object, + unsigned lengthOffset, + Value* index, + intptr_t handler); + +void appendFrameSite(Context* c, Value* value, int index); + +void appendSaveLocals(Context* c); + +void appendDummy(Context* c); + +void appendBuddy(Context* c, Value* original, Value* buddy); + +} // namespace compiler +} // namespace codegen +} // namespace avian + +#endif // AVIAN_CODEGEN_COMPILER_EVENT_H diff --git a/sgx-jvm/avian/src/codegen/compiler/frame.cpp b/sgx-jvm/avian/src/codegen/compiler/frame.cpp new file mode 100644 index 0000000000..e6b6832f9c --- /dev/null +++ b/sgx-jvm/avian/src/codegen/compiler/frame.cpp @@ -0,0 +1,132 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#include "avian/target.h" + +#include "codegen/compiler/context.h" +#include "codegen/compiler/frame.h" + +#include + +namespace avian { +namespace codegen { +namespace compiler { + +unsigned totalFrameSize(Context* c) +{ + return c->alignedFrameSize + c->arch->frameHeaderSize() + + c->arch->argumentFootprint(c->parameterFootprint); +} + +int frameIndex(Context* c, int localIndex) +{ + assertT(c, localIndex >= 0); + + int index = c->alignedFrameSize + c->parameterFootprint - localIndex - 1; + + if (localIndex < static_cast(c->parameterFootprint)) { + index += c->arch->frameHeaderSize(); + } else { + index -= c->arch->frameFooterSize(); + } + + assertT(c, index >= 0); + assertT(c, static_cast(index) < totalFrameSize(c)); + + return index; +} + +unsigned frameIndexToOffset(Context* c, unsigned frameIndex) +{ + assertT(c, frameIndex < totalFrameSize(c)); + + return (frameIndex + c->arch->frameFooterSize()) * c->targetInfo.pointerSize; +} + +unsigned offsetToFrameIndex(Context* c, unsigned offset) +{ + assertT(c, + static_cast((offset / c->targetInfo.pointerSize) + - c->arch->frameFooterSize()) >= 0); + assertT(c, + ((offset / c->targetInfo.pointerSize) - c->arch->frameFooterSize()) + < totalFrameSize(c)); + + return (offset / c->targetInfo.pointerSize) - c->arch->frameFooterSize(); +} + +unsigned frameBase(Context* c) +{ + return c->alignedFrameSize - c->arch->frameReturnAddressSize() + - c->arch->frameFooterSize() + c->arch->frameHeaderSize(); +} + +FrameIterator::Element::Element(Value* value, unsigned localIndex) + : value(value), localIndex(localIndex) +{ +} + +int FrameIterator::Element::frameIndex(Context* c) +{ + return compiler::frameIndex(c, this->localIndex); +} + +FrameIterator::FrameIterator(Context* c, + Stack* stack, + Local* locals, + bool includeEmpty) + : stack(stack), + locals(locals), + localIndex(c->localFootprint - 1), + includeEmpty(includeEmpty) +{ +} + +bool FrameIterator::hasMore() +{ + if (not includeEmpty) { + while (stack and stack->value == 0) { + stack = stack->next; + } + + while (localIndex >= 0 and locals[localIndex].value == 0) { + --localIndex; + } + } + + return stack != 0 or localIndex >= 0; +} + +FrameIterator::Element FrameIterator::next(Context* c) +{ + Value* v; + unsigned li; + if (stack) { + Stack* s = stack; + v = s->value; + li = s->index + c->localFootprint; + stack = stack->next; + } else { + Local* l = locals + localIndex; + v = l->value; + li = localIndex; + --localIndex; + } + return Element(v, li); +} + +Stack* stack(Context* c, Value* value, Stack* next) +{ + return new (c->zone) Stack(next ? next->index + 1 : 0, value, next); +} + +} // namespace compiler +} // namespace codegen +} // namespace avian diff --git a/sgx-jvm/avian/src/codegen/compiler/frame.h b/sgx-jvm/avian/src/codegen/compiler/frame.h new file mode 100644 index 0000000000..2f4bdb58a5 --- /dev/null +++ b/sgx-jvm/avian/src/codegen/compiler/frame.h @@ -0,0 +1,78 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#ifndef AVIAN_CODEGEN_COMPILER_FRAME_H +#define AVIAN_CODEGEN_COMPILER_FRAME_H + +namespace avian { +namespace codegen { +namespace compiler { + +unsigned totalFrameSize(Context* c); + +int frameIndex(Context* c, int localIndex); + +unsigned frameIndexToOffset(Context* c, unsigned frameIndex); + +unsigned offsetToFrameIndex(Context* c, unsigned offset); + +unsigned frameBase(Context* c); + +class FrameIterator { + public: + class Element { + public: + Element(Value* value, unsigned localIndex); + + int frameIndex(Context* c); + + Value* const value; + const unsigned localIndex; + }; + + FrameIterator(Context* c, + Stack* stack, + Local* locals, + bool includeEmpty = false); + + bool hasMore(); + + Element next(Context* c); + + Stack* stack; + Local* locals; + int localIndex; + bool includeEmpty; +}; + +class Local { + public: + Value* value; +}; + +class Stack { + public: + Stack(unsigned index, Value* value, Stack* next) + : index(index), value(value), next(next) + { + } + + unsigned index; + Value* value; + Stack* next; +}; + +Stack* stack(Context* c, Value* value, Stack* next); + +} // namespace compiler +} // namespace codegen +} // namespace avian + +#endif // AVIAN_CODEGEN_COMPILER_FRAME_H diff --git a/sgx-jvm/avian/src/codegen/compiler/ir.cpp b/sgx-jvm/avian/src/codegen/compiler/ir.cpp new file mode 100644 index 0000000000..fe7b58a5de --- /dev/null +++ b/sgx-jvm/avian/src/codegen/compiler/ir.cpp @@ -0,0 +1,57 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#include "codegen/compiler/context.h" +#include "codegen/compiler/ir.h" + +namespace avian { +namespace codegen { +namespace compiler { + +LogicalInstruction::LogicalInstruction(int index, Stack* stack, Local* locals) + : firstEvent(0), + lastEvent(0), + immediatePredecessor(0), + stack(stack), + locals(locals), + machineOffset(0), + /*subroutine(0), */ index(index) +{ +} + +LogicalInstruction* LogicalInstruction::next(Context* c) +{ + LogicalInstruction* i = this; + for (size_t n = i->index + 1; n < c->logicalCode.count(); ++n) { + i = c->logicalCode[n]; + if (i) + return i; + } + return 0; +} + +unsigned machineOffset(Context* c, int logicalIp) +{ + return c->logicalCode[logicalIp]->machineOffset->value(); +} + +Block::Block(Event* head) + : head(head), nextBlock(0), nextInstruction(0), assemblerBlock(0), start(0) +{ +} + +Block* block(Context* c, Event* head) +{ + return new (c->zone) Block(head); +} + +} // namespace compiler +} // namespace codegen +} // namespace avian diff --git a/sgx-jvm/avian/src/codegen/compiler/ir.h b/sgx-jvm/avian/src/codegen/compiler/ir.h new file mode 100644 index 0000000000..cd52fe063e --- /dev/null +++ b/sgx-jvm/avian/src/codegen/compiler/ir.h @@ -0,0 +1,86 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#ifndef AVIAN_CODEGEN_COMPILER_IR_H +#define AVIAN_CODEGEN_COMPILER_IR_H + +namespace avian { +namespace codegen { +namespace compiler { + +class MultiRead; + +class ForkElement { + public: + Value* value; + MultiRead* read; + bool local; +}; + +class ForkState : public Compiler::State { + public: + ForkState(Stack* stack, + Local* locals, + List* saved, + Event* predecessor, + unsigned logicalIp) + : stack(stack), + locals(locals), + saved(saved), + predecessor(predecessor), + logicalIp(logicalIp), + readCount(0) + { + } + + Stack* stack; + Local* locals; + List* saved; + Event* predecessor; + unsigned logicalIp; + unsigned readCount; + ForkElement elements[0]; +}; + +class LogicalInstruction { + public: + LogicalInstruction(int index, Stack* stack, Local* locals); + + LogicalInstruction* next(Context* c); + + Event* firstEvent; + Event* lastEvent; + LogicalInstruction* immediatePredecessor; + Stack* stack; + Local* locals; + Promise* machineOffset; + int index; +}; + +class Block { + public: + Block(Event* head); + + Event* head; + Block* nextBlock; + LogicalInstruction* nextInstruction; + Assembler::Block* assemblerBlock; + unsigned start; +}; + +Block* block(Context* c, Event* head); + +unsigned machineOffset(Context* c, int logicalIp); + +} // namespace compiler +} // namespace codegen +} // namespace avian + +#endif // AVIAN_CODEGEN_COMPILER_IR_H diff --git a/sgx-jvm/avian/src/codegen/compiler/promise.cpp b/sgx-jvm/avian/src/codegen/compiler/promise.cpp new file mode 100644 index 0000000000..3fff9d6afa --- /dev/null +++ b/sgx-jvm/avian/src/codegen/compiler/promise.cpp @@ -0,0 +1,133 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#include "avian/target.h" + +#include "codegen/compiler/context.h" +#include "codegen/compiler/promise.h" +#include "codegen/compiler/ir.h" + +namespace avian { +namespace codegen { +namespace compiler { + +CodePromise::CodePromise(Context* c, CodePromise* next) + : c(c), offset(0), next(next) +{ +} + +CodePromise::CodePromise(Context* c, Promise* offset) + : c(c), offset(offset), next(0) +{ +} + +int64_t CodePromise::value() +{ + if (resolved()) { + return reinterpret_cast(c->machineCode + offset->value()); + } + + abort(c); +} + +bool CodePromise::resolved() +{ + return c->machineCode != 0 and offset and offset->resolved(); +} + +CodePromise* codePromise(Context* c, Promise* offset) +{ + return new (c->zone) CodePromise(c, offset); +} + +Promise* shiftMaskPromise(Context* c, + Promise* base, + unsigned shift, + int64_t mask) +{ + return new (c->zone) ShiftMaskPromise(base, shift, mask); +} + +Promise* combinedPromise(Context* c, Promise* low, Promise* high) +{ + return new (c->zone) CombinedPromise(low, high); +} + +Promise* resolvedPromise(Context* c, int64_t value) +{ + return new (c->zone) ResolvedPromise(value); +} + +class IpPromise : public Promise { + public: + IpPromise(Context* c, int logicalIp) : c(c), logicalIp(logicalIp) + { + } + + virtual int64_t value() + { + if (resolved()) { + return reinterpret_cast(c->machineCode + + machineOffset(c, logicalIp)); + } + + abort(c); + } + + virtual bool resolved() + { + return c->machineCode != 0 + and c->logicalCode[logicalIp]->machineOffset->resolved(); + } + + Context* c; + int logicalIp; +}; + +Promise* ipPromise(Context* c, int logicalIp) +{ + return new (c->zone) IpPromise(c, logicalIp); +} + +class PoolPromise : public Promise { + public: + PoolPromise(Context* c, int key) : c(c), key(key) + { + } + + virtual int64_t value() + { + if (resolved()) { + return reinterpret_cast( + c->machineCode + + vm::pad(c->machineCodeSize, c->targetInfo.pointerSize) + + (key * c->targetInfo.pointerSize)); + } + + abort(c); + } + + virtual bool resolved() + { + return c->machineCode != 0; + } + + Context* c; + int key; +}; + +Promise* poolPromise(Context* c, int key) +{ + return new (c->zone) PoolPromise(c, key); +} + +} // namespace compiler +} // namespace codegen +} // namespace avian diff --git a/sgx-jvm/avian/src/codegen/compiler/promise.h b/sgx-jvm/avian/src/codegen/compiler/promise.h new file mode 100644 index 0000000000..928b7cd11e --- /dev/null +++ b/sgx-jvm/avian/src/codegen/compiler/promise.h @@ -0,0 +1,52 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#ifndef AVIAN_CODEGEN_COMPILER_PROMISE_H +#define AVIAN_CODEGEN_COMPILER_PROMISE_H + +namespace avian { +namespace codegen { +namespace compiler { + +class CodePromise : public Promise { + public: + CodePromise(Context* c, CodePromise* next); + + CodePromise(Context* c, Promise* offset); + + virtual int64_t value(); + + virtual bool resolved(); + + Context* c; + Promise* offset; + CodePromise* next; +}; + +CodePromise* codePromise(Context* c, Promise* offset); + +Promise* shiftMaskPromise(Context* c, + Promise* base, + unsigned shift, + int64_t mask); + +Promise* combinedPromise(Context* c, Promise* low, Promise* high); + +Promise* resolvedPromise(Context* c, int64_t value); + +Promise* ipPromise(Context* c, int logicalIp); + +Promise* poolPromise(Context* c, int key); + +} // namespace compiler +} // namespace codegen +} // namespace avian + +#endif // AVIAN_CODEGEN_COMPILER_PROMISE_H diff --git a/sgx-jvm/avian/src/codegen/compiler/read.cpp b/sgx-jvm/avian/src/codegen/compiler/read.cpp new file mode 100644 index 0000000000..5dfaba2777 --- /dev/null +++ b/sgx-jvm/avian/src/codegen/compiler/read.cpp @@ -0,0 +1,215 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#include "avian/target.h" + +#include "codegen/compiler/context.h" +#include "codegen/compiler/value.h" +#include "codegen/compiler/site.h" +#include "codegen/compiler/resource.h" +#include "codegen/compiler/read.h" + +namespace avian { +namespace codegen { +namespace compiler { + +SingleRead::SingleRead(const SiteMask& mask, Value* successor) + : next_(0), mask(mask), high_(0), successor_(successor) +{ +} + +bool SingleRead::intersect(SiteMask* mask, unsigned) +{ + *mask = mask->intersectionWith(this->mask); + + return true; +} + +Value* SingleRead::high(Context*) +{ + return high_; +} + +Value* SingleRead::successor() +{ + return successor_; +} + +bool SingleRead::valid() +{ + return true; +} + +void SingleRead::append(Context* c UNUSED, Read* r) +{ + assertT(c, next_ == 0); + next_ = r; +} + +Read* SingleRead::next(Context*) +{ + return next_; +} + +MultiRead::MultiRead() + : reads(0), lastRead(0), firstTarget(0), lastTarget(0), visited(false) +{ +} + +bool MultiRead::intersect(SiteMask* mask, unsigned depth) +{ + if (depth > 0) { + // short-circuit recursion to avoid poor performance in + // deeply-nested branches + return reads != 0; + } + + bool result = false; + if (not visited) { + visited = true; + for (List** cell = &reads; *cell;) { + Read* r = (*cell)->item; + bool valid = r->intersect(mask, depth + 1); + if (valid) { + result = true; + cell = &((*cell)->next); + } else { + *cell = (*cell)->next; + } + } + visited = false; + } + return result; +} + +Value* MultiRead::successor() +{ + return 0; +} + +bool MultiRead::valid() +{ + bool result = false; + if (not visited) { + visited = true; + for (List** cell = &reads; *cell;) { + Read* r = (*cell)->item; + if (r->valid()) { + result = true; + cell = &((*cell)->next); + } else { + *cell = (*cell)->next; + } + } + visited = false; + } + return result; +} + +void MultiRead::append(Context* c, Read* r) +{ + List* cell = cons(c, r, 0); + if (lastRead == 0) { + reads = cell; + } else { + lastRead->next = cell; + } + lastRead = cell; + + if (false) { + fprintf(stderr, "append %p to %p for %p\n", r, lastTarget, this); + } + + lastTarget->item = r; +} + +Read* MultiRead::next(Context* c) +{ + abort(c); +} + +void MultiRead::allocateTarget(Context* c) +{ + List* cell = cons(c, 0, 0); + + if (false) { + fprintf(stderr, "allocate target for %p: %p\n", this, cell); + } + + if (lastTarget) { + lastTarget->next = cell; + } else { + firstTarget = cell; + } + lastTarget = cell; +} + +Read* MultiRead::nextTarget() +{ + if (false) { + fprintf(stderr, "next target for %p: %p\n", this, firstTarget); + } + + Read* r = firstTarget->item; + firstTarget = firstTarget->next; + return r; +} + +StubRead::StubRead() : next_(0), read(0), visited(false), valid_(true) +{ +} + +bool StubRead::intersect(SiteMask* mask, unsigned depth) +{ + if (not visited) { + visited = true; + if (read) { + bool valid = read->intersect(mask, depth); + if (not valid) { + read = 0; + } + } + visited = false; + } + return valid_; +} + +Value* StubRead::successor() +{ + return 0; +} + +bool StubRead::valid() +{ + return valid_; +} + +void StubRead::append(Context* c UNUSED, Read* r) +{ + assertT(c, next_ == 0); + next_ = r; +} + +Read* StubRead::next(Context*) +{ + return next_; +} + +SingleRead* read(Context* c, const SiteMask& mask, Value* successor) +{ + assertT(c, + (mask.typeMask != lir::Operand::MemoryMask) or mask.frameIndex >= 0); + + return new (c->zone) SingleRead(mask, successor); +} + +} // namespace compiler +} // namespace codegen +} // namespace avian diff --git a/sgx-jvm/avian/src/codegen/compiler/read.h b/sgx-jvm/avian/src/codegen/compiler/read.h new file mode 100644 index 0000000000..80b8983a2f --- /dev/null +++ b/sgx-jvm/avian/src/codegen/compiler/read.h @@ -0,0 +1,127 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#ifndef AVIAN_CODEGEN_COMPILER_READ_H +#define AVIAN_CODEGEN_COMPILER_READ_H + +namespace avian { +namespace codegen { +namespace compiler { + +class Context; +class SiteMask; +class Value; +class Event; + +class Read { + public: + Read() : value(0), event(0), eventNext(0) + { + } + + virtual bool intersect(SiteMask* mask, unsigned depth = 0) = 0; + + virtual Value* high(Context* c) + { + abort(c); + } + + virtual Value* successor() = 0; + + virtual bool valid() = 0; + + virtual void append(Context* c, Read* r) = 0; + + virtual Read* next(Context* c) = 0; + + Value* value; + Event* event; + Read* eventNext; +}; + +inline bool valid(Read* r) +{ + return r and r->valid(); +} + +class SingleRead : public Read { + public: + SingleRead(const SiteMask& mask, Value* successor); + + virtual bool intersect(SiteMask* mask, unsigned); + + virtual Value* high(Context*); + + virtual Value* successor(); + + virtual bool valid(); + + virtual void append(Context* c UNUSED, Read* r); + + virtual Read* next(Context*); + + Read* next_; + SiteMask mask; + Value* high_; + Value* successor_; +}; + +class MultiRead : public Read { + public: + MultiRead(); + + virtual bool intersect(SiteMask* mask, unsigned depth); + + virtual Value* successor(); + + virtual bool valid(); + + virtual void append(Context* c, Read* r); + + virtual Read* next(Context* c); + + void allocateTarget(Context* c); + + Read* nextTarget(); + + List* reads; + List* lastRead; + List* firstTarget; + List* lastTarget; + bool visited; +}; + +class StubRead : public Read { + public: + StubRead(); + + virtual bool intersect(SiteMask* mask, unsigned depth); + + virtual Value* successor(); + + virtual bool valid(); + + virtual void append(Context* c UNUSED, Read* r); + + virtual Read* next(Context*); + + Read* next_; + Read* read; + bool visited; + bool valid_; +}; + +SingleRead* read(Context* c, const SiteMask& mask, Value* successor = 0); + +} // namespace compiler +} // namespace codegen +} // namespace avian + +#endif // AVIAN_CODEGEN_COMPILER_READ_H diff --git a/sgx-jvm/avian/src/codegen/compiler/regalloc.cpp b/sgx-jvm/avian/src/codegen/compiler/regalloc.cpp new file mode 100644 index 0000000000..788cab3dd3 --- /dev/null +++ b/sgx-jvm/avian/src/codegen/compiler/regalloc.cpp @@ -0,0 +1,320 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#include "avian/target.h" + +#include "codegen/compiler/regalloc.h" +#include "codegen/compiler/context.h" +#include "codegen/compiler/site.h" +#include "codegen/compiler/resource.h" +#include "codegen/compiler/read.h" + +namespace avian { +namespace codegen { +namespace compiler { + +RegisterAllocator::RegisterAllocator(Aborter* a, + const RegisterFile* registerFile) + : a(a), registerFile(registerFile) +{ +} + +unsigned totalFrameSize(Context* c); +Read* live(Context* c UNUSED, Value* v); + +unsigned resourceCost(Context* c, + Value* v, + Resource* r, + SiteMask mask, + CostCalculator* costCalculator) +{ + if (r->reserved or r->freezeCount or r->referenceCount) { + return Target::Impossible; + } else { + unsigned baseCost = costCalculator ? costCalculator->cost(c, mask) : 0; + + if (r->value) { + assertT(c, r->value->findSite(r->site)); + + if (v and r->value->isBuddyOf(v)) { + return baseCost; + } else if (r->value->uniqueSite(c, r->site)) { + return baseCost + Target::StealUniquePenalty; + } else { + return baseCost = Target::StealPenalty; + } + } else { + return baseCost; + } + } +} + +bool pickRegisterTarget(Context* c, + Register i, + Value* v, + RegisterMask mask, + Register* target, + unsigned* cost, + CostCalculator* costCalculator) +{ + if (mask.contains(i)) { + RegisterResource* r = c->registerResources + i.index(); + unsigned myCost + = resourceCost( + c, + v, + r, + SiteMask(lir::Operand::RegisterPairMask, RegisterMask(i), NoFrameIndex), + costCalculator) + Target::MinimumRegisterCost; + + if (mask.containsExactly(i)) { + *cost = myCost; + return true; + } else if (myCost < *cost) { + *cost = myCost; + *target = i; + } + } + return false; +} + +Register pickRegisterTarget(Context* c, + Value* v, + RegisterMask mask, + unsigned* cost, + CostCalculator* costCalculator) +{ + Register target = NoRegister; + *cost = Target::Impossible; + + if (mask & c->regFile->generalRegisters) { + for (Register i : c->regFile->generalRegisters) { + if (pickRegisterTarget(c, i, v, mask, &target, cost, costCalculator)) { + return i; + } + } + } + + if (mask & c->regFile->floatRegisters) { + for (Register i : c->regFile->floatRegisters) { + if (pickRegisterTarget(c, i, v, mask, &target, cost, costCalculator)) { + return i; + } + } + } + + return target; +} + +Target pickRegisterTarget(Context* c, + Value* v, + RegisterMask mask, + CostCalculator* costCalculator) +{ + unsigned cost; + Register number = pickRegisterTarget(c, v, mask, &cost, costCalculator); + return Target(number, cost); +} + +unsigned frameCost(Context* c, + Value* v, + int frameIndex, + CostCalculator* costCalculator) +{ + return resourceCost(c, + v, + c->frameResources + frameIndex, + SiteMask(lir::Operand::MemoryMask, 0, frameIndex), + costCalculator) + Target::MinimumFrameCost; +} + +Target pickFrameTarget(Context* c, Value* v, CostCalculator* costCalculator) +{ + Target best; + + Value* p = v; + do { + if (p->home >= 0) { + Target mine(p->home, + lir::Operand::Type::Memory, + frameCost(c, v, p->home, costCalculator)); + + if (mine.cost == Target::MinimumFrameCost) { + return mine; + } else if (mine.cost < best.cost) { + best = mine; + } + } + p = p->buddy; + } while (p != v); + + return best; +} + +Target pickAnyFrameTarget(Context* c, Value* v, CostCalculator* costCalculator) +{ + Target best; + + unsigned count = totalFrameSize(c); + for (unsigned i = 0; i < count; ++i) { + Target mine(i, lir::Operand::Type::Memory, frameCost(c, v, i, costCalculator)); + if (mine.cost == Target::MinimumFrameCost) { + return mine; + } else if (mine.cost < best.cost) { + best = mine; + } + } + + return best; +} + +Target pickTarget(Context* c, + Value* value, + const SiteMask& mask, + unsigned registerPenalty, + Target best, + CostCalculator* costCalculator) +{ + if (mask.typeMask & lir::Operand::RegisterPairMask) { + Target mine + = pickRegisterTarget(c, value, mask.registerMask, costCalculator); + + mine.cost += registerPenalty; + if (mine.cost == Target::MinimumRegisterCost) { + return mine; + } else if (mine.cost < best.cost) { + best = mine; + } + } + + if (mask.typeMask & lir::Operand::MemoryMask) { + if (mask.frameIndex >= 0) { + Target mine(mask.frameIndex, + lir::Operand::Type::Memory, + frameCost(c, value, mask.frameIndex, costCalculator)); + if (mine.cost == Target::MinimumFrameCost) { + return mine; + } else if (mine.cost < best.cost) { + best = mine; + } + } else if (mask.frameIndex == AnyFrameIndex) { + Target mine = pickFrameTarget(c, value, costCalculator); + if (mine.cost == Target::MinimumFrameCost) { + return mine; + } else if (mine.cost < best.cost) { + best = mine; + } + } + } + + return best; +} + +Target pickTarget(Context* c, + Read* read, + bool intersectRead, + unsigned registerReserveCount, + CostCalculator* costCalculator) +{ + unsigned registerPenalty + = (c->availableGeneralRegisterCount > registerReserveCount + ? 0 + : Target::LowRegisterPenalty); + + Value* value = read->value; + + RegisterMask registerMask + = (isFloatValue(value) ? AnyRegisterMask : (RegisterMask)c->regFile->generalRegisters); + + SiteMask mask(~0, registerMask, AnyFrameIndex); + read->intersect(&mask); + + if (isFloatValue(value)) { + RegisterMask floatMask = mask.registerMask & c->regFile->floatRegisters; + if (floatMask) { + mask.registerMask = floatMask; + } + } + + Target best; + + Value* successor = read->successor(); + if (successor) { + Read* r = live(c, successor); + if (r) { + SiteMask intersection = mask; + if (r->intersect(&intersection)) { + best = pickTarget( + c, value, intersection, registerPenalty, best, costCalculator); + + if (best.cost <= Target::MinimumFrameCost) { + return best; + } + } + } + } + + best = pickTarget(c, value, mask, registerPenalty, best, costCalculator); + if (best.cost <= Target::MinimumFrameCost) { + return best; + } + + if (intersectRead) { + if (best.cost == Target::Impossible) { + fprintf(stderr, + "mask type %d reg %" LLD " frame %d\n", + mask.typeMask, + (uint64_t)mask.registerMask, + mask.frameIndex); + abort(c); + } + return best; + } + + { + Target mine = pickRegisterTarget(c, value, registerMask, costCalculator); + + mine.cost += registerPenalty; + + if (mine.cost == Target::MinimumRegisterCost) { + return mine; + } else if (mine.cost < best.cost) { + best = mine; + } + } + + { + Target mine = pickFrameTarget(c, value, costCalculator); + if (mine.cost == Target::MinimumFrameCost) { + return mine; + } else if (mine.cost < best.cost) { + best = mine; + } + } + + if (best.cost >= Target::StealUniquePenalty + and c->availableGeneralRegisterCount == 0) { + // there are no free registers left, so moving from memory to + // memory isn't an option - try harder to find an available frame + // site: + best = pickAnyFrameTarget(c, value, costCalculator); + assertT(c, best.cost <= 3); + } + + if (best.cost == Target::Impossible) { + abort(c); + } + + return best; +} + +} // namespace regalloc +} // namespace codegen +} // namespace avian diff --git a/sgx-jvm/avian/src/codegen/compiler/regalloc.h b/sgx-jvm/avian/src/codegen/compiler/regalloc.h new file mode 100644 index 0000000000..a50b2e1ccc --- /dev/null +++ b/sgx-jvm/avian/src/codegen/compiler/regalloc.h @@ -0,0 +1,129 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#ifndef AVIAN_CODEGEN_COMPILER_REGALLOC_H +#define AVIAN_CODEGEN_COMPILER_REGALLOC_H + +#include "avian/common.h" + +#include +#include + +namespace avian { + +namespace util { +class Aborter; +} // namespace util + +namespace codegen { +namespace compiler { + +using namespace avian::util; + +class Context; +class Value; +class SiteMask; +class Resource; +class Read; + +class RegisterAllocator { + public: + Aborter* a; + const RegisterFile* registerFile; + + RegisterAllocator(Aborter* a, const RegisterFile* registerFile); +}; + +class Target { + public: + static const unsigned MinimumRegisterCost = 0; + static const unsigned MinimumFrameCost = 1; + static const unsigned StealPenalty = 2; + static const unsigned StealUniquePenalty = 4; + static const unsigned IndirectMovePenalty = 4; + static const unsigned LowRegisterPenalty = 10; + static const unsigned Impossible = 20; + + Target() : cost(Impossible) + { + } + + Target(int16_t index, lir::Operand::Type type, unsigned cost) + : index(index), type(type), cost(cost) + { + } + + Target(Register reg, unsigned cost) + : index(reg.index()), type(lir::Operand::Type::RegisterPair), cost(cost) + { + } + + int16_t index; + lir::Operand::Type type; + uint8_t cost; +}; + +class CostCalculator { + public: + virtual unsigned cost(Context* c, SiteMask mask) = 0; +}; + +unsigned resourceCost(Context* c, + Value* v, + Resource* r, + SiteMask mask, + CostCalculator* costCalculator); + +bool pickRegisterTarget(Context* c, + Register i, + Value* v, + RegisterMask mask, + Register* target, + unsigned* cost, + CostCalculator* costCalculator = 0); + +Register pickRegisterTarget(Context* c, + Value* v, + RegisterMask mask, + unsigned* cost, + CostCalculator* costCalculator = 0); + +Target pickRegisterTarget(Context* c, + Value* v, + RegisterMask mask, + CostCalculator* costCalculator = 0); + +unsigned frameCost(Context* c, + Value* v, + int frameIndex, + CostCalculator* costCalculator); + +Target pickFrameTarget(Context* c, Value* v, CostCalculator* costCalculator); + +Target pickAnyFrameTarget(Context* c, Value* v, CostCalculator* costCalculator); + +Target pickTarget(Context* c, + Value* value, + const SiteMask& mask, + unsigned registerPenalty, + Target best, + CostCalculator* costCalculator); + +Target pickTarget(Context* c, + Read* read, + bool intersectRead, + unsigned registerReserveCount, + CostCalculator* costCalculator); + +} // namespace regalloc +} // namespace codegen +} // namespace avian + +#endif // AVIAN_CODEGEN_COMPILER_REGALLOC_H diff --git a/sgx-jvm/avian/src/codegen/compiler/resource.cpp b/sgx-jvm/avian/src/codegen/compiler/resource.cpp new file mode 100644 index 0000000000..85b49d604c --- /dev/null +++ b/sgx-jvm/avian/src/codegen/compiler/resource.cpp @@ -0,0 +1,249 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#include "codegen/compiler/context.h" +#include "codegen/compiler/resource.h" +#include "codegen/compiler/value.h" + +namespace avian { +namespace codegen { +namespace compiler { + +const bool DebugResources = false; + +void steal(Context* c, Resource* r, Value* thief); + +void decrementAvailableGeneralRegisterCount(Context* c) +{ + assertT(c, c->availableGeneralRegisterCount); + --c->availableGeneralRegisterCount; + + if (DebugResources) { + fprintf( + stderr, "%d registers available\n", c->availableGeneralRegisterCount); + } +} + +void incrementAvailableGeneralRegisterCount(Context* c) +{ + ++c->availableGeneralRegisterCount; + + if (DebugResources) { + fprintf( + stderr, "%d registers available\n", c->availableGeneralRegisterCount); + } +} + +void freezeResource(Context* c, Resource* r, Value* v) +{ + if (DebugResources) { + char buffer[256]; + r->toString(c, buffer, 256); + fprintf(stderr, "%p freeze %s to %d\n", v, buffer, r->freezeCount + 1); + } + + ++r->freezeCount; +} + +void thawResource(Context* c, Resource* r, Value* v) +{ + if (not r->reserved) { + if (DebugResources) { + char buffer[256]; + r->toString(c, buffer, 256); + fprintf(stderr, "%p thaw %s to %d\n", v, buffer, r->freezeCount - 1); + } + + assertT(c, r->freezeCount); + + --r->freezeCount; + } +} + +Resource::Resource(bool reserved) + : value(0), + site(0), + previousAcquired(0), + nextAcquired(0), + freezeCount(0), + referenceCount(0), + reserved(reserved) +{ +} + +RegisterResource::RegisterResource(bool reserved) : Resource(reserved) +{ +} + +void RegisterResource::freeze(Context* c, Value* v) +{ + if (not reserved) { + freezeResource(c, this, v); + + if (freezeCount == 1 + and c->regFile->generalRegisters.contains(index(c))) { + decrementAvailableGeneralRegisterCount(c); + } + } +} + +void RegisterResource::thaw(Context* c, Value* v) +{ + if (not reserved) { + thawResource(c, this, v); + + if (freezeCount == 0 + and c->regFile->generalRegisters.contains(index(c))) { + incrementAvailableGeneralRegisterCount(c); + } + } +} + +unsigned RegisterResource::toString(Context* c, + char* buffer, + unsigned bufferSize) +{ + return vm::snprintf(buffer, bufferSize, "register %d", index(c)); +} + +Register RegisterResource::index(Context* c) +{ + return Register(this - c->registerResources); +} + +void RegisterResource::increment(Context* c) +{ + if (not this->reserved) { + if (DebugResources) { + char buffer[256]; + this->toString(c, buffer, 256); + fprintf(stderr, "increment %s to %d\n", buffer, this->referenceCount + 1); + } + + ++this->referenceCount; + + if (this->referenceCount == 1 + and c->regFile->generalRegisters.contains(this->index(c))) { + decrementAvailableGeneralRegisterCount(c); + } + } +} + +void RegisterResource::decrement(Context* c) +{ + if (not this->reserved) { + if (DebugResources) { + char buffer[256]; + this->toString(c, buffer, 256); + fprintf(stderr, "decrement %s to %d\n", buffer, this->referenceCount - 1); + } + + assertT(c, this->referenceCount > 0); + + --this->referenceCount; + + if (this->referenceCount == 0 + and c->regFile->generalRegisters.contains(this->index(c))) { + incrementAvailableGeneralRegisterCount(c); + } + } +} + +void FrameResource::freeze(Context* c, Value* v) +{ + freezeResource(c, this, v); +} + +void FrameResource::thaw(Context* c, Value* v) +{ + thawResource(c, this, v); +} + +unsigned FrameResource::toString(Context* c, char* buffer, unsigned bufferSize) +{ + return vm::snprintf(buffer, bufferSize, "frame %d", index(c)); +} + +unsigned FrameResource::index(Context* c) +{ + return this - c->frameResources; +} + +void acquire(Context* c, Resource* resource, Value* value, Site* site) +{ + assertT(c, value); + assertT(c, site); + + if (not resource->reserved) { + if (DebugResources) { + char buffer[256]; + resource->toString(c, buffer, 256); + fprintf(stderr, "%p acquire %s\n", value, buffer); + } + + if (resource->value) { + assertT(c, resource->value->findSite(resource->site)); + assertT(c, not value->findSite(resource->site)); + + steal(c, resource, value); + } + + if (c->acquiredResources) { + c->acquiredResources->previousAcquired = resource; + resource->nextAcquired = c->acquiredResources; + } + c->acquiredResources = resource; + + resource->value = value; + resource->site = site; + } +} + +void release(Context* c, + Resource* resource, + Value* value UNUSED, + Site* site UNUSED) +{ + if (not resource->reserved) { + if (DebugResources) { + char buffer[256]; + resource->toString(c, buffer, 256); + fprintf(stderr, "%p release %s\n", resource->value, buffer); + } + + assertT(c, resource->value); + assertT(c, resource->site); + + assertT(c, resource->value->isBuddyOf(value)); + assertT(c, site == resource->site); + + Resource* next = resource->nextAcquired; + if (next) { + next->previousAcquired = resource->previousAcquired; + resource->nextAcquired = 0; + } + + Resource* previous = resource->previousAcquired; + if (previous) { + previous->nextAcquired = next; + resource->previousAcquired = 0; + } else { + assertT(c, c->acquiredResources == resource); + c->acquiredResources = next; + } + + resource->value = 0; + resource->site = 0; + } +} + +} // namespace compiler +} // namespace codegen +} // namespace avian diff --git a/sgx-jvm/avian/src/codegen/compiler/resource.h b/sgx-jvm/avian/src/codegen/compiler/resource.h new file mode 100644 index 0000000000..e74543e376 --- /dev/null +++ b/sgx-jvm/avian/src/codegen/compiler/resource.h @@ -0,0 +1,77 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#ifndef AVIAN_CODEGEN_COMPILER_RESOURCE_H +#define AVIAN_CODEGEN_COMPILER_RESOURCE_H + +namespace avian { +namespace codegen { +namespace compiler { + +class Context; +class Value; +class Site; + +class Resource { + public: + Resource(bool reserved = false); + + virtual void freeze(Context*, Value*) = 0; + + virtual void thaw(Context*, Value*) = 0; + + virtual unsigned toString(Context*, char*, unsigned) = 0; + + Value* value; + Site* site; + Resource* previousAcquired; + Resource* nextAcquired; + uint8_t freezeCount; + uint8_t referenceCount; + bool reserved; +}; + +class RegisterResource : public Resource { + public: + RegisterResource(bool reserved); + + virtual void freeze(Context*, Value*); + + virtual void thaw(Context*, Value*); + + virtual unsigned toString(Context* c, char* buffer, unsigned bufferSize); + + virtual Register index(Context*); + + void increment(Context*); + + void decrement(Context*); +}; + +class FrameResource : public Resource { + public: + virtual void freeze(Context*, Value*); + + virtual void thaw(Context*, Value*); + + virtual unsigned toString(Context* c, char* buffer, unsigned bufferSize); + + virtual unsigned index(Context*); +}; + +void acquire(Context* c, Resource* resource, Value* value, Site* site); + +void release(Context* c, Resource* resource, Value* value, Site* site); + +} // namespace compiler +} // namespace codegen +} // namespace avian + +#endif // AVIAN_CODEGEN_COMPILER_RESOURCE_H diff --git a/sgx-jvm/avian/src/codegen/compiler/site.cpp b/sgx-jvm/avian/src/codegen/compiler/site.cpp new file mode 100644 index 0000000000..d3c59065b4 --- /dev/null +++ b/sgx-jvm/avian/src/codegen/compiler/site.cpp @@ -0,0 +1,706 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#include "avian/target.h" + +#include "codegen/compiler/context.h" +#include "codegen/compiler/value.h" +#include "codegen/compiler/site.h" +#include "codegen/compiler/resource.h" +#include "codegen/compiler/frame.h" +#include "codegen/compiler/promise.h" + +namespace avian { +namespace codegen { +namespace compiler { + +int intersectFrameIndexes(int a, int b) +{ + if (a == NoFrameIndex or b == NoFrameIndex) + return NoFrameIndex; + if (a == AnyFrameIndex) + return b; + if (b == AnyFrameIndex) + return a; + if (a == b) + return a; + return NoFrameIndex; +} + +SiteMask SiteMask::intersectionWith(const SiteMask& b) +{ + return SiteMask(typeMask & b.typeMask, + registerMask & b.registerMask, + intersectFrameIndexes(frameIndex, b.frameIndex)); +} + +SiteIterator::SiteIterator(Context* c, + Value* v, + bool includeBuddies, + bool includeNextWord) + : c(c), + originalValue(v), + currentValue(v), + includeBuddies(includeBuddies), + includeNextWord(includeNextWord), + pass(0), + next_(findNext(&(v->sites))), + previous(0) +{ +} + +Site** SiteIterator::findNext(Site** p) +{ + while (true) { + if (*p) { + if (pass == 0 or (*p)->registerSize(c) > c->targetInfo.pointerSize) { + return p; + } else { + p = &((*p)->next); + } + } else { + if (includeBuddies) { + Value* v = currentValue->buddy; + if (v != originalValue) { + currentValue = v; + p = &(v->sites); + continue; + } + } + + if (includeNextWord and pass == 0) { + Value* v = originalValue->nextWord; + if (v != originalValue) { + pass = 1; + originalValue = v; + currentValue = v; + p = &(v->sites); + continue; + } + } + + return 0; + } + } +} + +bool SiteIterator::hasMore() +{ + if (previous) { + next_ = findNext(&((*previous)->next)); + previous = 0; + } + return next_ != 0; +} + +Site* SiteIterator::next() +{ + previous = next_; + return *previous; +} + +void SiteIterator::remove(Context* c) +{ + (*previous)->release(c, originalValue); + *previous = (*previous)->next; + next_ = findNext(previous); + previous = 0; +} + +unsigned Site::registerSize(Context* c) +{ + return c->targetInfo.pointerSize; +} + +Site* constantSite(Context* c, Promise* value) +{ + return new (c->zone) ConstantSite(value); +} + +Site* constantSite(Context* c, int64_t value) +{ + return constantSite(c, resolvedPromise(c, value)); +} + +class AddressSite : public Site { + public: + AddressSite(Promise* address) : address(address) + { + } + + virtual unsigned toString(Context*, char* buffer, unsigned bufferSize) + { + if (address->resolved()) { + return vm::snprintf( + buffer, bufferSize, "address %" LLD, address->value()); + } else { + return vm::snprintf(buffer, bufferSize, "address unresolved"); + } + } + + virtual unsigned copyCost(Context*, Site* s) + { + return (s == this ? 0 : AddressCopyCost); + } + + virtual bool match(Context*, const SiteMask& mask) + { + return mask.typeMask & lir::Operand::AddressMask; + } + + virtual bool loneMatch(Context*, const SiteMask&) + { + return false; + } + + virtual bool matchNextWord(Context* c, Site*, unsigned) + { + abort(c); + } + + virtual lir::Operand::Type type(Context*) + { + return lir::Operand::Type::Address; + } + + virtual void asAssemblerOperand(Context* c UNUSED, + Site* high UNUSED, + lir::Operand* result) + { + assertT(c, high == this); + + new (result) lir::Address(address); + } + + virtual Site* copy(Context* c) + { + return addressSite(c, address); + } + + virtual Site* copyLow(Context* c) + { + abort(c); + } + + virtual Site* copyHigh(Context* c) + { + abort(c); + } + + virtual Site* makeNextWord(Context* c, unsigned) + { + abort(c); + } + + virtual SiteMask mask(Context*) + { + return SiteMask(lir::Operand::AddressMask, 0, NoFrameIndex); + } + + virtual SiteMask nextWordMask(Context* c, unsigned) + { + abort(c); + } + + Promise* address; +}; + +Site* addressSite(Context* c, Promise* address) +{ + return new (c->zone) AddressSite(address); +} + +RegisterSite::RegisterSite(RegisterMask mask, Register number) + : mask_(mask), number(number) +{ +} + +unsigned RegisterSite::toString(Context*, char* buffer, unsigned bufferSize) +{ + if (number != NoRegister) { + return vm::snprintf(buffer, bufferSize, "%p register %d", this, number); + } else { + return vm::snprintf( + buffer, bufferSize, "%p register unacquired (mask %d)", this, mask_); + } +} + +unsigned RegisterSite::copyCost(Context* c, Site* s) +{ + assertT(c, number != NoRegister); + + if (s and (this == s + or (s->type(c) == lir::Operand::Type::RegisterPair + and (static_cast(s)->mask_.contains(number))))) { + return 0; + } else { + return RegisterCopyCost; + } +} + +bool RegisterSite::match(Context* c UNUSED, const SiteMask& mask) +{ + assertT(c, number != NoRegister); + + if ((mask.typeMask & lir::Operand::RegisterPairMask)) { + return mask.registerMask.contains(number); + } else { + return false; + } +} + +bool RegisterSite::loneMatch(Context* c UNUSED, const SiteMask& mask) +{ + assertT(c, number != NoRegister); + + if ((mask.typeMask & lir::Operand::RegisterPairMask)) { + return mask.registerMask.containsExactly(number); + } else { + return false; + } +} + +bool RegisterSite::matchNextWord(Context* c, Site* s, unsigned) +{ + assertT(c, number != NoRegister); + + if (s->type(c) != lir::Operand::Type::RegisterPair) { + return false; + } + + RegisterSite* rs = static_cast(s); + unsigned size = rs->registerSize(c); + if (size > c->targetInfo.pointerSize) { + assertT(c, number != NoRegister); + return number == rs->number; + } else { + RegisterMask mask = c->regFile->generalRegisters; + return mask.contains(number) and mask.contains(rs->number); + } +} + +void RegisterSite::acquire(Context* c, Value* v) +{ + Target target; + if (number != NoRegister) { + target = Target(number, 0); + } else { + target = pickRegisterTarget(c, v, mask_); + expect(c, target.cost < Target::Impossible); + } + + RegisterResource* resource = c->registerResources + target.index; + compiler::acquire(c, resource, v, this); + + number = Register(target.index); +} + +void RegisterSite::release(Context* c, Value* v) +{ + assertT(c, number != NoRegister); + + compiler::release(c, c->registerResources + number.index(), v, this); +} + +void RegisterSite::freeze(Context* c, Value* v) +{ + assertT(c, number != NoRegister); + + c->registerResources[number.index()].freeze(c, v); +} + +void RegisterSite::thaw(Context* c, Value* v) +{ + assertT(c, number != NoRegister); + + c->registerResources[number.index()].thaw(c, v); +} + +bool RegisterSite::frozen(Context* c UNUSED) +{ + assertT(c, number != NoRegister); + + return c->registerResources[number.index()].freezeCount != 0; +} + +lir::Operand::Type RegisterSite::type(Context*) +{ + return lir::Operand::Type::RegisterPair; +} + +void RegisterSite::asAssemblerOperand(Context* c UNUSED, + Site* high, + lir::Operand* result) +{ + assertT(c, number != NoRegister); + + Register highNumber; + if (high != this) { + highNumber = static_cast(high)->number; + assertT(c, highNumber != NoRegister); + } else { + highNumber = NoRegister; + } + + new (result) lir::RegisterPair(number, highNumber); +} + +Site* RegisterSite::copy(Context* c) +{ + RegisterMask mask; + + if (number != NoRegister) { + mask = RegisterMask(number); + } else { + mask = mask_; + } + + return freeRegisterSite(c, mask); +} + +Site* RegisterSite::copyLow(Context* c) +{ + abort(c); +} + +Site* RegisterSite::copyHigh(Context* c) +{ + abort(c); +} + +Site* RegisterSite::makeNextWord(Context* c, unsigned) +{ + assertT(c, number != NoRegister); + assertT(c, c->regFile->generalRegisters.contains(number)); + + return freeRegisterSite(c, c->regFile->generalRegisters); +} + +SiteMask RegisterSite::mask(Context* c UNUSED) +{ + return SiteMask(lir::Operand::RegisterPairMask, mask_, NoFrameIndex); +} + +SiteMask RegisterSite::nextWordMask(Context* c, unsigned) +{ + assertT(c, number != NoRegister); + + if (registerSize(c) > c->targetInfo.pointerSize) { + return SiteMask(lir::Operand::RegisterPairMask, number, NoFrameIndex); + } else { + return SiteMask(lir::Operand::RegisterPairMask, + c->regFile->generalRegisters, + NoFrameIndex); + } +} + +unsigned RegisterSite::registerSize(Context* c) +{ + assertT(c, number != NoRegister); + + if (c->regFile->floatRegisters.contains(number)) { + return c->arch->floatRegisterSize(); + } else { + return c->targetInfo.pointerSize; + } +} + +RegisterMask RegisterSite::registerMask(Context* c UNUSED) +{ + assertT(c, number != NoRegister); + + return RegisterMask(number); +} + +Site* registerSite(Context* c, Register number) +{ + assertT(c, number != NoRegister); + assertT(c, + (c->regFile->generalRegisters + | c->regFile->floatRegisters).contains(number)); + + return new (c->zone) RegisterSite(RegisterMask(number), number); +} + +Site* freeRegisterSite(Context* c, RegisterMask mask) +{ + return new (c->zone) RegisterSite(mask, NoRegister); +} + +MemorySite::MemorySite(Register base, int offset, Register index, unsigned scale) + : acquired(false), base(base), offset(offset), index(index), scale(scale) +{ +} + +unsigned MemorySite::toString(Context*, char* buffer, unsigned bufferSize) +{ + if (acquired) { + return vm::snprintf( + buffer, bufferSize, "memory %d 0x%x %d %d", base, offset, index, scale); + } else { + return vm::snprintf(buffer, bufferSize, "memory unacquired"); + } +} + +unsigned MemorySite::copyCost(Context* c, Site* s) +{ + assertT(c, acquired); + + if (s and (this == s or (s->type(c) == lir::Operand::Type::Memory + and static_cast(s)->base == base + and static_cast(s)->offset == offset + and static_cast(s)->index == index + and static_cast(s)->scale == scale))) { + return 0; + } else { + return MemoryCopyCost; + } +} + +bool MemorySite::conflicts(const SiteMask& mask) +{ + return (mask.typeMask & lir::Operand::RegisterPairMask) != 0 + and (!mask.registerMask.contains(base) + or (index != NoRegister + and !mask.registerMask.contains(index))); +} + +bool MemorySite::match(Context* c, const SiteMask& mask) +{ + assertT(c, acquired); + + if (mask.typeMask & lir::Operand::MemoryMask) { + if (mask.frameIndex >= 0) { + if (base == c->arch->stack()) { + assertT(c, index == NoRegister); + return static_cast(frameIndexToOffset(c, mask.frameIndex)) + == offset; + } else { + return false; + } + } else { + return true; + } + } else { + return false; + } +} + +bool MemorySite::loneMatch(Context* c, const SiteMask& mask) +{ + assertT(c, acquired); + + if (mask.typeMask & lir::Operand::MemoryMask) { + if (base == c->arch->stack()) { + assertT(c, index == NoRegister); + + if (mask.frameIndex == AnyFrameIndex) { + return false; + } else { + return true; + } + } + } + return false; +} + +bool MemorySite::matchNextWord(Context* c, Site* s, unsigned index) +{ + if (s->type(c) == lir::Operand::Type::Memory) { + MemorySite* ms = static_cast(s); + return ms->base == this->base + and ((index == 1 + and ms->offset + == static_cast(this->offset + + c->targetInfo.pointerSize)) + or (index == 0 + and this->offset + == static_cast(ms->offset + + c->targetInfo.pointerSize))) + and ms->index == this->index and ms->scale == this->scale; + } else { + return false; + } +} + +void MemorySite::acquire(Context* c, Value* v) +{ + c->registerResources[base.index()].increment(c); + if (index != NoRegister) { + c->registerResources[index.index()].increment(c); + } + + if (base == c->arch->stack()) { + assertT(c, index == NoRegister); + assertT(c, not c->frameResources[offsetToFrameIndex(c, offset)].reserved); + + compiler::acquire( + c, c->frameResources + offsetToFrameIndex(c, offset), v, this); + } + + acquired = true; +} + +void MemorySite::release(Context* c, Value* v) +{ + if (base == c->arch->stack()) { + assertT(c, index == NoRegister); + assertT(c, not c->frameResources[offsetToFrameIndex(c, offset)].reserved); + + compiler::release( + c, c->frameResources + offsetToFrameIndex(c, offset), v, this); + } + + c->registerResources[base.index()].decrement(c); + if (index != NoRegister) { + c->registerResources[index.index()].decrement(c); + } + + acquired = false; +} + +void MemorySite::freeze(Context* c, Value* v) +{ + if (base == c->arch->stack()) { + c->frameResources[offsetToFrameIndex(c, offset)].freeze(c, v); + } else { + c->registerResources[base.index()].increment(c); + if (index != NoRegister) { + c->registerResources[index.index()].increment(c); + } + } +} + +void MemorySite::thaw(Context* c, Value* v) +{ + if (base == c->arch->stack()) { + c->frameResources[offsetToFrameIndex(c, offset)].thaw(c, v); + } else { + c->registerResources[base.index()].decrement(c); + if (index != NoRegister) { + c->registerResources[index.index()].decrement(c); + } + } +} + +bool MemorySite::frozen(Context* c) +{ + return base == c->arch->stack() + and c->frameResources[offsetToFrameIndex(c, offset)].freezeCount != 0; +} + +lir::Operand::Type MemorySite::type(Context*) +{ + return lir::Operand::Type::Memory; +} + +void MemorySite::asAssemblerOperand(Context* c UNUSED, + Site* high UNUSED, + lir::Operand* result) +{ + // todo: endianness? + assertT(c, + high == this + or (static_cast(high)->base == base + and static_cast(high)->offset + == static_cast(offset + c->targetInfo.pointerSize) + and static_cast(high)->index == index + and static_cast(high)->scale == scale)); + + assertT(c, acquired); + + new (result) lir::Memory(base, offset, index, scale); +} + +Site* MemorySite::copy(Context* c) +{ + return memorySite(c, base, offset, index, scale); +} + +Site* MemorySite::copyHalf(Context* c, bool add) +{ + if (add) { + return memorySite( + c, base, offset + c->targetInfo.pointerSize, index, scale); + } else { + return copy(c); + } +} + +Site* MemorySite::copyLow(Context* c) +{ + return copyHalf(c, c->arch->bigEndian()); +} + +Site* MemorySite::copyHigh(Context* c) +{ + return copyHalf(c, not c->arch->bigEndian()); +} + +Site* MemorySite::makeNextWord(Context* c, unsigned index) +{ + return memorySite(c, + base, + offset + ((index == 1) xor c->arch->bigEndian() + ? c->targetInfo.pointerSize + : -c->targetInfo.pointerSize), + this->index, + scale); +} + +SiteMask MemorySite::mask(Context* c) +{ + return SiteMask(lir::Operand::MemoryMask, + 0, + (base == c->arch->stack()) + ? static_cast(offsetToFrameIndex(c, offset)) + : NoFrameIndex); +} + +SiteMask MemorySite::nextWordMask(Context* c, unsigned index) +{ + int frameIndex; + if (base == c->arch->stack()) { + assertT(c, this->index == NoRegister); + frameIndex = static_cast(offsetToFrameIndex(c, offset)) + + ((index == 1) xor c->arch->bigEndian() ? 1 : -1); + } else { + frameIndex = NoFrameIndex; + } + return SiteMask(lir::Operand::MemoryMask, 0, frameIndex); +} + +bool MemorySite::isVolatile(Context* c) +{ + return base != c->arch->stack(); +} + +MemorySite* memorySite(Context* c, + Register base, + int offset, + Register index, + unsigned scale) +{ + return new (c->zone) MemorySite(base, offset, index, scale); +} + +MemorySite* frameSite(Context* c, int frameIndex) +{ + assertT(c, frameIndex >= 0); + return memorySite(c, + c->arch->stack(), + frameIndexToOffset(c, frameIndex), + NoRegister, + 0); +} + +} // namespace compiler +} // namespace codegen +} // namespace avian diff --git a/sgx-jvm/avian/src/codegen/compiler/site.h b/sgx-jvm/avian/src/codegen/compiler/site.h new file mode 100644 index 0000000000..9629455c88 --- /dev/null +++ b/sgx-jvm/avian/src/codegen/compiler/site.h @@ -0,0 +1,371 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#ifndef AVIAN_CODEGEN_COMPILER_SITE_H +#define AVIAN_CODEGEN_COMPILER_SITE_H + +#include + +#include "codegen/compiler/value.h" +#include "codegen/compiler/context.h" + +namespace avian { +namespace codegen { +namespace compiler { + +class Context; + +const unsigned RegisterCopyCost = 1; +const unsigned AddressCopyCost = 2; +const unsigned ConstantCopyCost = 3; +const unsigned MemoryCopyCost = 4; +const unsigned CopyPenalty = 10; + +class SiteMask { + public: + SiteMask() : typeMask(~0), registerMask(~0), frameIndex(AnyFrameIndex) + { + } + + SiteMask(uint8_t typeMask, RegisterMask registerMask, int frameIndex) + : typeMask(typeMask), registerMask(registerMask), frameIndex(frameIndex) + { + } + + SiteMask intersectionWith(const SiteMask& b); + + static SiteMask fixedRegisterMask(Register number) + { + return SiteMask(lir::Operand::RegisterPairMask, 1 << number.index(), NoFrameIndex); + } + + static SiteMask lowPart(const OperandMask& mask) + { + return SiteMask(mask.typeMask, mask.lowRegisterMask, AnyFrameIndex); + } + + static SiteMask highPart(const OperandMask& mask) + { + return SiteMask(mask.typeMask, mask.highRegisterMask, AnyFrameIndex); + } + + uint8_t typeMask; + RegisterMask registerMask; + int frameIndex; +}; + +class Site { + public: + Site() : next(0) + { + } + + virtual Site* readTarget(Context*, Read*) + { + return this; + } + + virtual unsigned toString(Context*, char*, unsigned) = 0; + + virtual unsigned copyCost(Context*, Site*) = 0; + + virtual bool match(Context*, const SiteMask&) = 0; + + virtual bool loneMatch(Context*, const SiteMask&) = 0; + + virtual bool matchNextWord(Context*, Site*, unsigned) = 0; + + virtual void acquire(Context*, Value*) + { + } + + virtual void release(Context*, Value*) + { + } + + virtual void freeze(Context*, Value*) + { + } + + virtual void thaw(Context*, Value*) + { + } + + virtual bool frozen(Context*) + { + return false; + } + + virtual lir::Operand::Type type(Context*) = 0; + + virtual void asAssemblerOperand(Context*, Site*, lir::Operand*) = 0; + + virtual Site* copy(Context*) = 0; + + virtual Site* copyLow(Context*) = 0; + + virtual Site* copyHigh(Context*) = 0; + + virtual Site* makeNextWord(Context*, unsigned) = 0; + + virtual SiteMask mask(Context*) = 0; + + virtual SiteMask nextWordMask(Context*, unsigned) = 0; + + virtual unsigned registerSize(Context*); + + virtual RegisterMask registerMask(Context*) + { + return RegisterMask(0); + } + + virtual bool isVolatile(Context*) + { + return false; + } + + Site* next; +}; + +class SiteIterator { + public: + SiteIterator(Context* c, + Value* v, + bool includeBuddies = true, + bool includeNextWord = true); + + Site** findNext(Site** p); + bool hasMore(); + Site* next(); + void remove(Context* c); + + Context* c; + Value* originalValue; + Value* currentValue; + bool includeBuddies; + bool includeNextWord; + uint8_t pass; + Site** next_; + Site** previous; +}; + +Site* constantSite(Context* c, Promise* value); +Site* constantSite(Context* c, int64_t value); + +Promise* combinedPromise(Context* c, Promise* low, Promise* high); +Promise* shiftMaskPromise(Context* c, + Promise* base, + unsigned shift, + int64_t mask); + +class ConstantSite : public Site { + public: + ConstantSite(Promise* value) : value(value) + { + } + + virtual unsigned toString(Context*, char* buffer, unsigned bufferSize) + { + if (value->resolved()) { + return vm::snprintf(buffer, bufferSize, "constant %" LLD, value->value()); + } else { + return vm::snprintf(buffer, bufferSize, "constant unresolved"); + } + } + + virtual unsigned copyCost(Context*, Site* s) + { + return (s == this ? 0 : ConstantCopyCost); + } + + virtual bool match(Context*, const SiteMask& mask) + { + return mask.typeMask & lir::Operand::ConstantMask; + } + + virtual bool loneMatch(Context*, const SiteMask&) + { + return true; + } + + virtual bool matchNextWord(Context* c, Site* s, unsigned) + { + return s->type(c) == lir::Operand::Type::Constant; + } + + virtual lir::Operand::Type type(Context*) + { + return lir::Operand::Type::Constant; + } + + virtual void asAssemblerOperand(Context* c, Site* high, lir::Operand* result) + { + Promise* v = value; + if (high != this) { + v = combinedPromise(c, value, static_cast(high)->value); + } + new (result) lir::Constant(v); + } + + virtual Site* copy(Context* c) + { + return constantSite(c, value); + } + + virtual Site* copyLow(Context* c) + { + return constantSite(c, shiftMaskPromise(c, value, 0, 0xFFFFFFFF)); + } + + virtual Site* copyHigh(Context* c) + { + return constantSite(c, shiftMaskPromise(c, value, 32, 0xFFFFFFFF)); + } + + virtual Site* makeNextWord(Context* c, unsigned) + { + abort(c); + } + + virtual SiteMask mask(Context*) + { + return SiteMask(lir::Operand::ConstantMask, 0, NoFrameIndex); + } + + virtual SiteMask nextWordMask(Context*, unsigned) + { + return SiteMask(lir::Operand::ConstantMask, 0, NoFrameIndex); + } + + Promise* value; +}; + +Site* addressSite(Context* c, Promise* address); + +class RegisterSite : public Site { + public: + RegisterSite(RegisterMask mask, Register number); + + virtual unsigned toString(Context*, char* buffer, unsigned bufferSize); + + virtual unsigned copyCost(Context* c, Site* s); + + virtual bool match(Context* c UNUSED, const SiteMask& mask); + + virtual bool loneMatch(Context* c UNUSED, const SiteMask& mask); + + virtual bool matchNextWord(Context* c, Site* s, unsigned); + + virtual void acquire(Context* c, Value* v); + + virtual void release(Context* c, Value* v); + + virtual void freeze(Context* c, Value* v); + + virtual void thaw(Context* c, Value* v); + + virtual bool frozen(Context* c UNUSED); + + virtual lir::Operand::Type type(Context*); + + virtual void asAssemblerOperand(Context* c UNUSED, + Site* high, + lir::Operand* result); + + virtual Site* copy(Context* c); + + virtual Site* copyLow(Context* c); + + virtual Site* copyHigh(Context* c); + + virtual Site* makeNextWord(Context* c, unsigned); + + virtual SiteMask mask(Context* c UNUSED); + + virtual SiteMask nextWordMask(Context* c, unsigned); + + virtual unsigned registerSize(Context* c); + + virtual RegisterMask registerMask(Context* c UNUSED); + + RegisterMask mask_; + Register number; +}; + +Site* registerSite(Context* c, Register number); +Site* freeRegisterSite(Context* c, RegisterMask mask); + +class MemorySite : public Site { + public: + MemorySite(Register base, int offset, Register index, unsigned scale); + + virtual unsigned toString(Context*, char* buffer, unsigned bufferSize); + + virtual unsigned copyCost(Context* c, Site* s); + + bool conflicts(const SiteMask& mask); + + virtual bool match(Context* c, const SiteMask& mask); + + virtual bool loneMatch(Context* c, const SiteMask& mask); + + virtual bool matchNextWord(Context* c, Site* s, unsigned index); + + virtual void acquire(Context* c, Value* v); + + virtual void release(Context* c, Value* v); + + virtual void freeze(Context* c, Value* v); + + virtual void thaw(Context* c, Value* v); + + virtual bool frozen(Context* c); + + virtual lir::Operand::Type type(Context*); + + virtual void asAssemblerOperand(Context* c UNUSED, + Site* high UNUSED, + lir::Operand* result); + + virtual Site* copy(Context* c); + + Site* copyHalf(Context* c, bool add); + + virtual Site* copyLow(Context* c); + + virtual Site* copyHigh(Context* c); + + virtual Site* makeNextWord(Context* c, unsigned index); + + virtual SiteMask mask(Context* c); + + virtual SiteMask nextWordMask(Context* c, unsigned index); + + virtual bool isVolatile(Context* c); + + bool acquired; + Register base; + int offset; + Register index; + unsigned scale; +}; + +MemorySite* memorySite(Context* c, + Register base, + int offset = 0, + Register index = NoRegister, + unsigned scale = 1); +MemorySite* frameSite(Context* c, int frameIndex); + +} // namespace compiler +} // namespace codegen +} // namespace avian + +#endif // AVIAN_CODEGEN_COMPILER_SITE_H diff --git a/sgx-jvm/avian/src/codegen/compiler/value.cpp b/sgx-jvm/avian/src/codegen/compiler/value.cpp new file mode 100644 index 0000000000..b4c44e8837 --- /dev/null +++ b/sgx-jvm/avian/src/codegen/compiler/value.cpp @@ -0,0 +1,187 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#include "avian/target.h" + +#include "codegen/compiler/regalloc.h" +#include "codegen/compiler/site.h" + +namespace avian { +namespace codegen { +namespace compiler { + +Value::Value(Site* site, Site* target, ir::Type type) + : ir::Value(type), + reads(0), + lastRead(0), + sites(site), + source(0), + target(target), + buddy(this), + nextWord(this), + home(NoFrameIndex), + wordIndex(0) +{ +} + +bool Value::findSite(Site* site) +{ + for (Site* s = this->sites; s; s = s->next) { + if (s == site) + return true; + } + return false; +} + +bool Value::isBuddyOf(Value* b) +{ + Value* a = this; + if (a == b) + return true; + for (Value* p = a->buddy; p != a; p = p->buddy) { + if (p == b) + return true; + } + return false; +} + +void Value::addSite(Context* c, Site* s) +{ + if (not this->findSite(s)) { + if (DebugSites) { + char buffer[256]; + s->toString(c, buffer, 256); + fprintf(stderr, "add site %s to %p\n", buffer, this); + } + s->acquire(c, this); + s->next = this->sites; + this->sites = s; + } +} + +void Value::grow(Context* c) +{ + assertT(c, this->nextWord == this); + + Value* next = value(c, this->type); + this->nextWord = next; + next->nextWord = this; + next->wordIndex = 1; +} + +void Value::maybeSplit(Context* c) +{ + if (this->nextWord == this) { + this->split(c); + } +} + +void Value::split(Context* c) +{ + this->grow(c); + for (SiteIterator it(c, this); it.hasMore();) { + Site* s = it.next(); + this->removeSite(c, s); + + this->addSite(c, s->copyLow(c)); + this->nextWord->addSite(c, s->copyHigh(c)); + } +} + +void Value::removeSite(Context* c, Site* s) +{ + for (SiteIterator it(c, this); it.hasMore();) { + if (s == it.next()) { + if (DebugSites) { + char buffer[256]; + s->toString(c, buffer, 256); + fprintf(stderr, "remove site %s from %p\n", buffer, this); + } + it.remove(c); + break; + } + } + if (DebugSites) { + fprintf(stderr, "%p has more: %d\n", this, this->hasSite(c)); + } + assertT(c, not this->findSite(s)); +} + +bool Value::hasSite(Context* c) +{ + SiteIterator it(c, this); + return it.hasMore(); +} + +bool Value::uniqueSite(Context* c, Site* s) +{ + SiteIterator it(c, this); + Site* p UNUSED = it.next(); + if (it.hasMore()) { + // the site is not this word's only site, but if the site is + // shared with the next word, it may be that word's only site + if (this->nextWord != this + and s->registerSize(c) > c->targetInfo.pointerSize) { + SiteIterator nit(c, this->nextWord); + Site* p = nit.next(); + if (nit.hasMore()) { + return false; + } else { + return p == s; + } + } else { + return false; + } + } else { + assertT(c, p == s); + return true; + } +} + +void Value::clearSites(Context* c) +{ + if (DebugSites) { + fprintf(stderr, "clear sites for %p\n", this); + } + for (SiteIterator it(c, this); it.hasMore();) { + it.next(); + it.remove(c); + } +} + +#ifndef NDEBUG +bool Value::hasBuddy(Context* c, Value* b) +{ + Value* a = this; + if (a == b) { + return true; + } + + int i = 0; + for (Value* p = a->buddy; p != a; p = p->buddy) { + if (p == b) { + return true; + } + if (++i > 1000) { + abort(c); + } + } + return false; +} +#endif // not NDEBUG + +Value* value(Context* c, ir::Type type, Site* site, Site* target) +{ + return new (c->zone) Value(site, target, type); +} + +} // namespace regalloc +} // namespace codegen +} // namespace avian diff --git a/sgx-jvm/avian/src/codegen/compiler/value.h b/sgx-jvm/avian/src/codegen/compiler/value.h new file mode 100644 index 0000000000..76f67987b9 --- /dev/null +++ b/sgx-jvm/avian/src/codegen/compiler/value.h @@ -0,0 +1,84 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#ifndef AVIAN_CODEGEN_COMPILER_VALUE_H +#define AVIAN_CODEGEN_COMPILER_VALUE_H + +#include +#include + +namespace avian { +namespace codegen { +namespace compiler { + +class Read; +class Site; + +const int AnyFrameIndex = -2; +const int NoFrameIndex = -1; + +const bool DebugSites = false; + +class Value : public ir::Value { + public: + Read* reads; + Read* lastRead; + Site* sites; + Site* source; + Site* target; + Value* buddy; + Value* nextWord; + int16_t home; + uint8_t wordIndex; + + Value(Site* site, Site* target, ir::Type type); + + bool findSite(Site* site); + + bool isBuddyOf(Value* b); + + void addSite(Context* c, Site* s); + + void grow(Context* c); + + void maybeSplit(Context* c); + + void split(Context* c); + + void removeSite(Context* c, Site* s); + + bool hasSite(Context* c); + + bool uniqueSite(Context* c, Site* s); + + void clearSites(Context* c); + +#ifndef NDEBUG + bool hasBuddy(Context* c, Value* b); +#endif // not NDEBUG +}; + +inline bool isFloatValue(ir::Value* a) +{ + return static_cast(a)->type.flavor() == ir::Type::Float; +} + +inline bool isGeneralValue(ir::Value* a) +{ + return !isFloatValue(a); +} + +Value* value(Context* c, ir::Type type, Site* site = 0, Site* target = 0); + +} // namespace compiler +} // namespace codegen +} // namespace avian + +#endif // AVIAN_CODEGEN_COMPILER_VALUE_H diff --git a/sgx-jvm/avian/src/codegen/runtime.cpp b/sgx-jvm/avian/src/codegen/runtime.cpp new file mode 100644 index 0000000000..b868464492 --- /dev/null +++ b/sgx-jvm/avian/src/codegen/runtime.cpp @@ -0,0 +1,282 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#include + +namespace avian { +namespace codegen { +namespace runtime { + +static bool isNaN(double v) +{ + return fpclassify(v) == FP_NAN; +} + +static bool isNaN(float v) +{ + return fpclassify(v) == FP_NAN; +} + +int64_t compareDoublesG(uint64_t bi, uint64_t ai) +{ + double a = vm::bitsToDouble(ai); + double b = vm::bitsToDouble(bi); + + if (isNaN(a) or isNaN(b)) { + return 1; + } else if (a < b) { + return -1; + } else if (a > b) { + return 1; + } else if (a == b) { + return 0; + } else { + return 1; + } +} + +int64_t compareDoublesL(uint64_t bi, uint64_t ai) +{ + double a = vm::bitsToDouble(ai); + double b = vm::bitsToDouble(bi); + + if (isNaN(a) or isNaN(b)) { + return -1; + } else if (a < b) { + return -1; + } else if (a > b) { + return 1; + } else if (a == b) { + return 0; + } else { + return -1; + } +} + +int64_t compareFloatsG(uint32_t bi, uint32_t ai) +{ + float a = vm::bitsToFloat(ai); + float b = vm::bitsToFloat(bi); + + if (isNaN(a) or isNaN(b)) { + return 1; + } + if (a < b) { + return -1; + } else if (a > b) { + return 1; + } else if (a == b) { + return 0; + } else { + return 1; + } +} + +int64_t compareFloatsL(uint32_t bi, uint32_t ai) +{ + float a = vm::bitsToFloat(ai); + float b = vm::bitsToFloat(bi); + + if (isNaN(a) or isNaN(b)) { + return -1; + } + if (a < b) { + return -1; + } else if (a > b) { + return 1; + } else if (a == b) { + return 0; + } else { + return -1; + } +} + +int64_t compareLongs(uint64_t b, uint64_t a) +{ + if (a < b) { + return -1; + } else if (a > b) { + return 1; + } else { + return 0; + } +} + +uint64_t addDouble(uint64_t b, uint64_t a) +{ + return vm::doubleToBits(vm::bitsToDouble(a) + vm::bitsToDouble(b)); +} + +uint64_t subtractDouble(uint64_t b, uint64_t a) +{ + return vm::doubleToBits(vm::bitsToDouble(a) - vm::bitsToDouble(b)); +} + +uint64_t multiplyDouble(uint64_t b, uint64_t a) +{ + return vm::doubleToBits(vm::bitsToDouble(a) * vm::bitsToDouble(b)); +} + +uint64_t divideDouble(uint64_t b, uint64_t a) +{ + return vm::doubleToBits(vm::bitsToDouble(a) / vm::bitsToDouble(b)); +} + +uint64_t moduloDouble(uint64_t b, uint64_t a) +{ + return vm::doubleToBits(fmod(vm::bitsToDouble(a), vm::bitsToDouble(b))); +} + +uint64_t negateDouble(uint64_t a) +{ + return vm::doubleToBits(-vm::bitsToDouble(a)); +} + +uint64_t squareRootDouble(uint64_t a) +{ + return vm::doubleToBits(sqrt(vm::bitsToDouble(a))); +} + +uint64_t doubleToFloat(int64_t a) +{ + return vm::floatToBits(static_cast(vm::bitsToDouble(a))); +} + +int64_t doubleToInt(int64_t a) +{ + double f = vm::bitsToDouble(a); + switch (fpclassify(f)) { + case FP_NAN: + return 0; + case FP_INFINITE: + return signbit(f) ? INT32_MIN : INT32_MAX; + default: + return f >= INT32_MAX + ? INT32_MAX + : (f <= INT32_MIN ? INT32_MIN : static_cast(f)); + } +} + +int64_t doubleToLong(int64_t a) +{ + double f = vm::bitsToDouble(a); + switch (fpclassify(f)) { + case FP_NAN: + return 0; + case FP_INFINITE: + return signbit(f) ? INT64_MIN : INT64_MAX; + default: + return f >= INT64_MAX + ? INT64_MAX + : (f <= INT64_MIN ? INT64_MIN : static_cast(f)); + } +} + +uint64_t addFloat(uint32_t b, uint32_t a) +{ + return vm::floatToBits(vm::bitsToFloat(a) + vm::bitsToFloat(b)); +} + +uint64_t subtractFloat(uint32_t b, uint32_t a) +{ + return vm::floatToBits(vm::bitsToFloat(a) - vm::bitsToFloat(b)); +} + +uint64_t multiplyFloat(uint32_t b, uint32_t a) +{ + return vm::floatToBits(vm::bitsToFloat(a) * vm::bitsToFloat(b)); +} + +uint64_t divideFloat(uint32_t b, uint32_t a) +{ + return vm::floatToBits(vm::bitsToFloat(a) / vm::bitsToFloat(b)); +} + +uint64_t moduloFloat(uint32_t b, uint32_t a) +{ + return vm::floatToBits(fmod(vm::bitsToFloat(a), vm::bitsToFloat(b))); +} + +uint64_t negateFloat(uint32_t a) +{ + return vm::floatToBits(-vm::bitsToFloat(a)); +} + +uint64_t absoluteFloat(uint32_t a) +{ + return vm::floatToBits(fabsf(vm::bitsToFloat(a))); +} + +int64_t absoluteLong(int64_t a) +{ + return a > 0 ? a : -a; +} + +int64_t absoluteInt(int32_t a) +{ + return a > 0 ? a : -a; +} + +uint64_t floatToDouble(int32_t a) +{ + return vm::doubleToBits(static_cast(vm::bitsToFloat(a))); +} + +int64_t floatToInt(int32_t a) +{ + float f = vm::bitsToFloat(a); + switch (fpclassify(f)) { + case FP_NAN: + return 0; + case FP_INFINITE: + return signbit(f) ? INT32_MIN : INT32_MAX; + default: + return f >= INT32_MAX + ? INT32_MAX + : (f <= INT32_MIN ? INT32_MIN : static_cast(f)); + } +} + +int64_t floatToLong(int32_t a) +{ + float f = vm::bitsToFloat(a); + switch (fpclassify(f)) { + case FP_NAN: + return 0; + case FP_INFINITE: + return signbit(f) ? INT64_MIN : INT64_MAX; + default: + return static_cast(f); + } +} + +uint64_t intToDouble(int32_t a) +{ + return vm::doubleToBits(static_cast(a)); +} + +uint64_t intToFloat(int32_t a) +{ + return vm::floatToBits(static_cast(a)); +} + +uint64_t longToDouble(int64_t a) +{ + return vm::doubleToBits(static_cast(a)); +} + +uint64_t longToFloat(int64_t a) +{ + return vm::floatToBits(static_cast(a)); +} + +} // namespace runtime +} // namespace codegen +} // namespace avian diff --git a/sgx-jvm/avian/src/codegen/target/CMakeLists.txt b/sgx-jvm/avian/src/codegen/target/CMakeLists.txt new file mode 100644 index 0000000000..55edb6b112 --- /dev/null +++ b/sgx-jvm/avian/src/codegen/target/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(arm) +add_subdirectory(x86) diff --git a/sgx-jvm/avian/src/codegen/target/arm/CMakeLists.txt b/sgx-jvm/avian/src/codegen/target/arm/CMakeLists.txt new file mode 100644 index 0000000000..23faf6694f --- /dev/null +++ b/sgx-jvm/avian/src/codegen/target/arm/CMakeLists.txt @@ -0,0 +1,9 @@ +add_library(avian_codegen_arm + assembler.cpp + block.cpp + context.cpp + fixup.cpp + multimethod.cpp + operations32.cpp + operations64.cpp +) diff --git a/sgx-jvm/avian/src/codegen/target/arm/assembler.cpp b/sgx-jvm/avian/src/codegen/target/arm/assembler.cpp new file mode 100644 index 0000000000..a72bd5edf5 --- /dev/null +++ b/sgx-jvm/avian/src/codegen/target/arm/assembler.cpp @@ -0,0 +1,1178 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#include + +#include +#include +#include + +#include "context.h" +#include "block.h" +#include "fixup.h" +#include "multimethod.h" +#include "encode.h" +#include "operations.h" +#include "registers.h" +#include "../multimethod.h" + +#include "avian/alloc-vector.h" +#include + +using namespace vm; +using namespace avian::codegen; +using namespace avian::util; + +namespace avian { +namespace codegen { +namespace arm { + +namespace isa { +// HARDWARE FLAGS +bool vfpSupported() +{ +// TODO: Use at runtime detection +#if (defined __ARM_PCS_VFP) || (defined ARCH_arm64) + // armhf + return true; +#else + // armel + // TODO: allow VFP use for -mfloat-abi=softfp armel builds. + // GCC -mfloat-abi=softfp flag allows use of VFP while remaining compatible + // with soft-float code. + return false; +#endif +} +} // namespace isa + +const RegisterFile MyRegisterFileWithoutFloats(GPR_MASK, 0); +const RegisterFile MyRegisterFileWithFloats(GPR_MASK, FPR_MASK); + +const unsigned FrameHeaderSize = TargetBytesPerWord / 4; + +const unsigned StackAlignmentInBytes = TargetBytesPerWord * 2; +const unsigned StackAlignmentInWords = StackAlignmentInBytes + / TargetBytesPerWord; + +void resolve(MyBlock*); + +unsigned padding(MyBlock*, unsigned); + +class ConstantPoolEntry; + +// BEGIN OPERATION COMPILERS + +using namespace isa; + +// END OPERATION COMPILERS + +unsigned argumentFootprint(unsigned footprint) +{ + return max(pad(footprint, StackAlignmentInWords), StackAlignmentInWords); +} + +void nextFrame(ArchitectureContext* con, + uint32_t* start, + unsigned size UNUSED, + unsigned footprint, + void* link, + bool, + int targetParameterFootprint UNUSED, + void** ip, + void** stack) +{ + assertT(con, *ip >= start); + assertT(con, *ip <= start + (size / 4)); + + uint32_t* instruction = static_cast(*ip); + + if ((*start >> 20) == (TargetBytesPerWord == 8 ? 0xf94 : 0xe59)) { + // skip stack overflow check + start += TargetBytesPerWord == 8 ? 4 : 3; + } + + if (instruction <= start) { + *ip = link; + return; + } + + unsigned offset = footprint + FrameHeaderSize; + + if (instruction <= start + 2) { + *ip = link; + *stack = static_cast(*stack) + offset; + return; + } + + if (*instruction == (TargetBytesPerWord == 8 ? 0xd61f03c0 : 0xe12fff1e)) { + // return + *ip = link; + return; + } + + if (TailCalls and targetParameterFootprint >= 0) { + if (argumentFootprint(targetParameterFootprint) > StackAlignmentInWords) { + offset += argumentFootprint(targetParameterFootprint) + - StackAlignmentInWords; + } + + // check for post-non-tail-call stack adjustment of the form "sub + // sp, sp, #offset": + if (TargetBytesPerWord == 8 and (*instruction & 0xff0003ff) == 0xd10003ff) { + unsigned value = (*instruction >> 10) & 0xfff; + unsigned shift = (*instruction >> 22) & 1; + switch (shift) { + case 0: + offset -= value / TargetBytesPerWord; + break; + case 1: + offset -= (value << 12) / TargetBytesPerWord; + break; + default: + abort(con); + } + } else if (TargetBytesPerWord == 4 and (*instruction >> 12) == 0xe24dd) { + unsigned value = *instruction & 0xff; + unsigned rotation = (*instruction >> 8) & 0xf; + switch (rotation) { + case 0: + offset -= value / TargetBytesPerWord; + break; + case 15: + offset -= value; + break; + default: + abort(con); + } + } + + // todo: check for and handle tail calls + } + + *ip = static_cast(*stack)[offset - 1]; + *stack = static_cast(*stack) + offset; +} + +class MyArchitecture : public Architecture { + public: + MyArchitecture(System* system) : con(system), referenceCount(0) + { + populateTables(&con); + } + + virtual unsigned floatRegisterSize() + { + return vfpSupported() ? 8 : 0; + } + + virtual const RegisterFile* registerFile() + { + return vfpSupported() ? &MyRegisterFileWithFloats + : &MyRegisterFileWithoutFloats; + } + + virtual Register scratch() + { + return Register(5); + } + + virtual Register stack() + { + return StackRegister; + } + + virtual Register thread() + { + return ThreadRegister; + } + + virtual Register returnLow() + { + return Register(0); + } + + virtual Register returnHigh() + { + return Register(1); + } + + virtual Register virtualCallTarget() + { + return Register(4); + } + + virtual Register virtualCallIndex() + { + return Register(3); + } + + virtual ir::TargetInfo targetInfo() + { + return ir::TargetInfo(TargetBytesPerWord); + } + + virtual bool bigEndian() + { + return false; + } + + virtual uintptr_t maximumImmediateJump() + { + return 0x1FFFFFF; + } + + virtual bool reserved(Register register_) + { + switch (register_.index()) { + case LinkRegister.index(): + case FrameRegister.index(): + case StackRegister.index(): + case ThreadRegister.index(): + case ProgramCounter.index(): + return true; + case 18: + // x18 is a reserved platform register on arm64 + return TargetBytesPerWord == 8; + + default: + return false; + } + } + + virtual unsigned frameFootprint(unsigned footprint) + { + return max(footprint, StackAlignmentInWords); + } + + virtual unsigned argumentFootprint(unsigned footprint) + { + return arm::argumentFootprint(footprint); + } + + virtual bool argumentAlignment() + { +#ifdef __APPLE__ + return false; +#else + return true; +#endif + } + + virtual bool argumentRegisterAlignment() + { +#ifdef __APPLE__ + return false; +#else + return true; +#endif + } + + virtual unsigned argumentRegisterCount() + { + return TargetBytesPerWord; + } + + virtual Register argumentRegister(unsigned index) + { + assertT(&con, index < argumentRegisterCount()); + + return Register(index); + } + + virtual bool hasLinkRegister() + { + return true; + } + + virtual unsigned stackAlignmentInWords() + { + return StackAlignmentInWords; + } + + virtual bool matchCall(void* returnAddress, void* target) + { + uint32_t* instruction = static_cast(returnAddress) - 1; + + return *instruction == static_cast( + bl(static_cast(target) + - reinterpret_cast(instruction))); + } + + virtual void updateCall(lir::UnaryOperation op UNUSED, + void* returnAddress, + void* newTarget) + { + switch (op) { + case lir::Call: + case lir::Jump: + case lir::AlignedCall: + case lir::AlignedJump: { + updateOffset(con.s, + static_cast(returnAddress) - 4, + reinterpret_cast(newTarget)); + } break; + + case lir::LongCall: + case lir::LongJump: + case lir::AlignedLongCall: + case lir::AlignedLongJump: { + uint32_t* p = static_cast(returnAddress) - 2; + if (TargetBytesPerWord == 8) { + const int32_t mask = (PoolOffsetMask >> 2) << 5; + *reinterpret_cast(p + ((*p & mask) >> 5)) = newTarget; + } else { + *reinterpret_cast(p + (((*p & PoolOffsetMask) + 8) / 4)) + = newTarget; + } + } break; + + default: + abort(&con); + } + } + + virtual unsigned constantCallSize() + { + return 4; + } + + virtual void setConstant(void* dst, uint64_t constant) + { + *static_cast(dst) = constant; + } + + virtual unsigned alignFrameSize(unsigned sizeInWords) + { + return pad(sizeInWords + FrameHeaderSize, StackAlignmentInWords) + - FrameHeaderSize; + } + + virtual void nextFrame(void* start, + unsigned size, + unsigned footprint, + void* link, + bool mostRecent, + int targetParameterFootprint, + void** ip, + void** stack) + { + arm::nextFrame(&con, + static_cast(start), + size, + footprint, + link, + mostRecent, + targetParameterFootprint, + ip, + stack); + } + + virtual void* frameIp(void* stack) + { + return stack ? static_cast(stack)[returnAddressOffset()] : 0; + } + + virtual unsigned frameHeaderSize() + { + return FrameHeaderSize; + } + + virtual unsigned frameReturnAddressSize() + { + return 0; + } + + virtual unsigned frameFooterSize() + { + return 0; + } + + virtual int returnAddressOffset() + { + return -1; + } + + virtual int framePointerOffset() + { + return 0; + } + + virtual bool alwaysCondensed(lir::BinaryOperation) + { + return false; + } + + virtual bool alwaysCondensed(lir::TernaryOperation) + { + return false; + } + + virtual void plan(lir::UnaryOperation, + unsigned, + OperandMask& aMask, + bool* thunk) + { + aMask.typeMask = lir::Operand::RegisterPairMask | lir::Operand::ConstantMask; + aMask.setLowHighRegisterMasks(AnyRegisterMask, AnyRegisterMask); + *thunk = false; + } + + virtual void planSource(lir::BinaryOperation op, + unsigned aSize, + OperandMask& aMask, + unsigned bSize, + bool* thunk) + { + *thunk = false; + aMask.typeMask = ~0; + aMask.setLowHighRegisterMasks(GPR_MASK, GPR_MASK); + + switch (op) { + case lir::Negate: + aMask.typeMask = lir::Operand::RegisterPairMask; + aMask.setLowHighRegisterMasks(GPR_MASK, GPR_MASK); + break; + + case lir::Absolute: + *thunk = true; + break; + + case lir::FloatAbsolute: + case lir::FloatSquareRoot: + case lir::FloatNegate: + case lir::Float2Float: + if (vfpSupported()) { + aMask.typeMask = lir::Operand::RegisterPairMask; + aMask.setLowHighRegisterMasks(FPR_MASK, FPR_MASK); + } else { + *thunk = true; + } + break; + + case lir::Float2Int: + // todo: Java requires different semantics than VFP for + // converting floats to integers, we we need to either use + // thunks or produce inline machine code which handles edge + // cases properly. + if (false && vfpSupported() && bSize <= TargetBytesPerWord) { + aMask.typeMask = lir::Operand::RegisterPairMask; + aMask.setLowHighRegisterMasks(FPR_MASK, FPR_MASK); + } else { + *thunk = true; + } + break; + + case lir::Int2Float: + if (vfpSupported() && aSize <= TargetBytesPerWord) { + aMask.typeMask = lir::Operand::RegisterPairMask; + aMask.setLowHighRegisterMasks(GPR_MASK, GPR_MASK); + } else { + *thunk = true; + } + break; + + default: + break; + } + } + + virtual void planDestination(lir::BinaryOperation op, + unsigned, + const OperandMask& aMask, + unsigned, + OperandMask& bMask) + { + bMask.typeMask = lir::Operand::RegisterPairMask | lir::Operand::MemoryMask; + bMask.setLowHighRegisterMasks(GPR_MASK, GPR_MASK); + + switch (op) { + case lir::Negate: + bMask.typeMask = lir::Operand::RegisterPairMask; + bMask.setLowHighRegisterMasks(GPR_MASK, GPR_MASK); + break; + + case lir::FloatAbsolute: + case lir::FloatSquareRoot: + case lir::FloatNegate: + case lir::Float2Float: + case lir::Int2Float: + bMask.typeMask = lir::Operand::RegisterPairMask; + bMask.setLowHighRegisterMasks(FPR_MASK, FPR_MASK); + break; + + case lir::Float2Int: + bMask.typeMask = lir::Operand::RegisterPairMask; + bMask.setLowHighRegisterMasks(GPR_MASK, GPR_MASK); + break; + + case lir::Move: + if (!(aMask.typeMask & lir::Operand::RegisterPairMask)) { + bMask.typeMask = lir::Operand::RegisterPairMask; + } + break; + + default: + break; + } + } + + virtual void planMove(unsigned, + OperandMask& srcMask, + OperandMask& tmpMask, + const OperandMask& dstMask) + { + srcMask.typeMask = ~0; + srcMask.setLowHighRegisterMasks(AnyRegisterMask, AnyRegisterMask); + + tmpMask.typeMask = 0; + tmpMask.setLowHighRegisterMasks(0, 0); + + if (dstMask.typeMask & lir::Operand::MemoryMask) { + // can't move directly from memory or constant to memory + srcMask.typeMask = lir::Operand::RegisterPairMask; + tmpMask.typeMask = lir::Operand::RegisterPairMask; + tmpMask.setLowHighRegisterMasks(GPR_MASK, GPR_MASK); + } else if (vfpSupported() && dstMask.typeMask & lir::Operand::RegisterPairMask + && dstMask.lowRegisterMask & FPR_MASK) { + srcMask.typeMask = tmpMask.typeMask = lir::Operand::RegisterPairMask + | lir::Operand::MemoryMask; + tmpMask.setLowHighRegisterMasks(AnyRegisterMask, AnyRegisterMask); + } + } + + virtual void planSource(lir::TernaryOperation op, + unsigned, + OperandMask& aMask, + unsigned bSize, + OperandMask& bMask, + unsigned, + bool* thunk) + { + aMask.typeMask = lir::Operand::RegisterPairMask | lir::Operand::ConstantMask; + aMask.setLowHighRegisterMasks(GPR_MASK, GPR_MASK); + + bMask.typeMask = lir::Operand::RegisterPairMask; + bMask.setLowHighRegisterMasks(GPR_MASK, GPR_MASK); + + *thunk = false; + + switch (op) { + case lir::ShiftLeft: + case lir::ShiftRight: + case lir::UnsignedShiftRight: + if (bSize > TargetBytesPerWord) + aMask.typeMask = bMask.typeMask = lir::Operand::RegisterPairMask; + break; + + case lir::Add: + case lir::Subtract: + case lir::Or: + case lir::Xor: + case lir::Multiply: + aMask.typeMask = bMask.typeMask = lir::Operand::RegisterPairMask; + break; + + // todo: Although ARM has instructions for integer division and + // remainder, they don't trap on division by zero, which is why + // we use thunks. Alternatively, we could generate inline code + // with an explicit zero check, which would probably be a bit + // faster. + case lir::Divide: + case lir::Remainder: + case lir::FloatRemainder: + *thunk = true; + break; + + case lir::FloatAdd: + case lir::FloatSubtract: + case lir::FloatMultiply: + case lir::FloatDivide: + if (vfpSupported()) { + aMask.typeMask = lir::Operand::RegisterPairMask; + aMask.setLowHighRegisterMasks(FPR_MASK, FPR_MASK); + bMask = aMask; + } else { + *thunk = true; + } + break; + + case lir::JumpIfFloatEqual: + case lir::JumpIfFloatNotEqual: + case lir::JumpIfFloatLess: + case lir::JumpIfFloatGreater: + case lir::JumpIfFloatLessOrEqual: + case lir::JumpIfFloatGreaterOrEqual: + case lir::JumpIfFloatLessOrUnordered: + case lir::JumpIfFloatGreaterOrUnordered: + case lir::JumpIfFloatLessOrEqualOrUnordered: + case lir::JumpIfFloatGreaterOrEqualOrUnordered: + if (vfpSupported()) { + aMask.typeMask = lir::Operand::RegisterPairMask; + aMask.setLowHighRegisterMasks(FPR_MASK, FPR_MASK); + bMask = aMask; + } else { + *thunk = true; + } + break; + + default: + break; + } + } + + virtual void planDestination(lir::TernaryOperation op, + unsigned, + const OperandMask& aMask UNUSED, + unsigned, + const OperandMask& bMask, + unsigned, + OperandMask& cMask) + { + if (isBranch(op)) { + cMask.typeMask = lir::Operand::ConstantMask; + cMask.setLowHighRegisterMasks(0, 0); + } else { + cMask.typeMask = lir::Operand::RegisterPairMask; + cMask.lowRegisterMask = bMask.lowRegisterMask; + cMask.highRegisterMask = bMask.highRegisterMask; + } + } + + virtual Assembler* makeAssembler(Alloc* allocator, Zone* zone); + + virtual void acquire() + { + ++referenceCount; + } + + virtual void release() + { + if (--referenceCount == 0) { + con.s->free(this); + } + } + + ArchitectureContext con; + unsigned referenceCount; +}; + +class MyAssembler : public Assembler { + public: + MyAssembler(System* s, Alloc* a, Zone* zone, MyArchitecture* arch) + : con(s, a, zone), arch_(arch) + { + } + + virtual void setClient(Client* client) + { + assertT(&con, con.client == 0); + con.client = client; + } + + virtual Architecture* arch() + { + return arch_; + } + + virtual void checkStackOverflow(uintptr_t handler, + unsigned stackLimitOffsetFromThread) + { + lir::RegisterPair stack(StackRegister); + lir::Memory stackLimit(ThreadRegister, stackLimitOffsetFromThread); + lir::Constant handlerConstant(new (con.zone) ResolvedPromise(handler)); + branchRM(&con, + lir::JumpIfGreaterOrEqual, + TargetBytesPerWord, + &stack, + &stackLimit, + &handlerConstant); + } + + virtual void saveFrame(unsigned stackOffset, unsigned ipOffset) + { + lir::RegisterPair link(LinkRegister); + lir::Memory linkDst(ThreadRegister, ipOffset); + moveRM(&con, TargetBytesPerWord, &link, TargetBytesPerWord, &linkDst); + + lir::RegisterPair stack(StackRegister); + lir::Memory stackDst(ThreadRegister, stackOffset); + moveRM(&con, TargetBytesPerWord, &stack, TargetBytesPerWord, &stackDst); + } + + virtual void pushFrame(unsigned argumentCount, ...) + { + struct Argument { + unsigned size; + lir::Operand::Type type; + lir::Operand* operand; + }; + RUNTIME_ARRAY(Argument, arguments, argumentCount); + + va_list a; + va_start(a, argumentCount); + unsigned footprint = 0; + for (unsigned i = 0; i < argumentCount; ++i) { + RUNTIME_ARRAY_BODY(arguments)[i].size = va_arg(a, unsigned); + RUNTIME_ARRAY_BODY(arguments)[i].type + = static_cast(va_arg(a, int)); + RUNTIME_ARRAY_BODY(arguments)[i].operand = va_arg(a, lir::Operand*); + footprint += ceilingDivide(RUNTIME_ARRAY_BODY(arguments)[i].size, + TargetBytesPerWord); + } + va_end(a); + + allocateFrame(arch_->alignFrameSize(footprint)); + + unsigned offset = 0; + for (unsigned i = 0; i < argumentCount; ++i) { + if (i < arch_->argumentRegisterCount()) { + lir::RegisterPair dst(arch_->argumentRegister(i)); + + apply(lir::Move, + OperandInfo(RUNTIME_ARRAY_BODY(arguments)[i].size, + RUNTIME_ARRAY_BODY(arguments)[i].type, + RUNTIME_ARRAY_BODY(arguments)[i].operand), + OperandInfo(pad(RUNTIME_ARRAY_BODY(arguments)[i].size, + TargetBytesPerWord), + lir::Operand::Type::RegisterPair, + &dst)); + + offset += ceilingDivide(RUNTIME_ARRAY_BODY(arguments)[i].size, + TargetBytesPerWord); + } else { + lir::Memory dst(StackRegister, offset * TargetBytesPerWord); + + apply(lir::Move, + OperandInfo(RUNTIME_ARRAY_BODY(arguments)[i].size, + RUNTIME_ARRAY_BODY(arguments)[i].type, + RUNTIME_ARRAY_BODY(arguments)[i].operand), + OperandInfo(pad(RUNTIME_ARRAY_BODY(arguments)[i].size, + TargetBytesPerWord), + lir::Operand::Type::Memory, + &dst)); + + offset += ceilingDivide(RUNTIME_ARRAY_BODY(arguments)[i].size, + TargetBytesPerWord); + } + } + } + + virtual void allocateFrame(unsigned footprint) + { + footprint += FrameHeaderSize; + + // larger frames may require multiple subtract/add instructions + // to allocate/deallocate, and nextFrame will need to be taught + // how to handle them: + assertT(&con, footprint < 256); + + // todo: the ARM ABI says the frame preamble should be of the form + // + // stp x29, x30, [sp,#-footprint]! + // mov x29, sp + // + // and the frame should be popped with e.g. + // + // ldp x29, x30, [sp],#footprint + // br x30 + // + // However, that will invalidate a lot of assumptions elsewhere + // about the return address being stored at the opposite end of + // the frame, so lots of other code will need to change before we + // can do that. The code below can be enabled as a starting point + // when we're ready to tackle that. + if (false and TargetBytesPerWord == 8) { + // stp x29, x30, [sp,#-footprint]! + con.code.append4(0xa9800000 | ((-footprint & 0x7f) << 15) + | (StackRegister.index() << 5) + | (LinkRegister.index() << 10) | FrameRegister.index()); + + lir::RegisterPair stack(StackRegister); + lir::RegisterPair frame(FrameRegister); + moveRR(&con, TargetBytesPerWord, &stack, TargetBytesPerWord, &frame); + } else { + lir::RegisterPair stack(StackRegister); + ResolvedPromise footprintPromise(footprint * TargetBytesPerWord); + lir::Constant footprintConstant(&footprintPromise); + subC(&con, TargetBytesPerWord, &footprintConstant, &stack, &stack); + + lir::RegisterPair returnAddress(LinkRegister); + lir::Memory returnAddressDst(StackRegister, + (footprint - 1) * TargetBytesPerWord); + moveRM(&con, + TargetBytesPerWord, + &returnAddress, + TargetBytesPerWord, + &returnAddressDst); + } + } + + virtual void adjustFrame(unsigned difference) + { + lir::RegisterPair stack(StackRegister); + ResolvedPromise differencePromise(difference * TargetBytesPerWord); + lir::Constant differenceConstant(&differencePromise); + subC(&con, TargetBytesPerWord, &differenceConstant, &stack, &stack); + } + + virtual void popFrame(unsigned footprint) + { + footprint += FrameHeaderSize; + + // see comment regarding the ARM64 ABI in allocateFrame + if (false and TargetBytesPerWord == 8) { + // ldp x29, x30, [sp],#footprint + con.code.append4(0xa8c00000 | (footprint << 15) | (31 << 5) | (30 << 10) + | 29); + } else { + lir::RegisterPair returnAddress(LinkRegister); + lir::Memory returnAddressSrc(StackRegister, + (footprint - 1) * TargetBytesPerWord); + moveMR(&con, + TargetBytesPerWord, + &returnAddressSrc, + TargetBytesPerWord, + &returnAddress); + + lir::RegisterPair stack(StackRegister); + ResolvedPromise footprintPromise(footprint * TargetBytesPerWord); + lir::Constant footprintConstant(&footprintPromise); + addC(&con, TargetBytesPerWord, &footprintConstant, &stack, &stack); + } + } + + virtual void popFrameForTailCall(unsigned footprint, + int offset, + Register returnAddressSurrogate, + Register framePointerSurrogate UNUSED) + { + assertT(&con, framePointerSurrogate == NoRegister); + + if (TailCalls) { + if (offset) { + footprint += FrameHeaderSize; + + lir::RegisterPair link(LinkRegister); + lir::Memory returnAddressSrc(StackRegister, + (footprint - 1) * TargetBytesPerWord); + moveMR(&con, + TargetBytesPerWord, + &returnAddressSrc, + TargetBytesPerWord, + &link); + + lir::RegisterPair stack(StackRegister); + ResolvedPromise footprintPromise((footprint - offset) + * TargetBytesPerWord); + lir::Constant footprintConstant(&footprintPromise); + addC(&con, TargetBytesPerWord, &footprintConstant, &stack, &stack); + + if (returnAddressSurrogate != NoRegister) { + assertT(&con, offset > 0); + + lir::RegisterPair ras(returnAddressSurrogate); + lir::Memory dst(StackRegister, (offset - 1) * TargetBytesPerWord); + moveRM(&con, TargetBytesPerWord, &ras, TargetBytesPerWord, &dst); + } + } else { + popFrame(footprint); + } + } else { + abort(&con); + } + } + + virtual void popFrameAndPopArgumentsAndReturn(unsigned frameFootprint, + unsigned argumentFootprint) + { + popFrame(frameFootprint); + + assertT(&con, argumentFootprint >= StackAlignmentInWords); + assertT(&con, (argumentFootprint % StackAlignmentInWords) == 0); + + unsigned offset; + if (TailCalls and argumentFootprint > StackAlignmentInWords) { + offset = argumentFootprint - StackAlignmentInWords; + + lir::RegisterPair stack(StackRegister); + ResolvedPromise adjustmentPromise(offset * TargetBytesPerWord); + lir::Constant adjustment(&adjustmentPromise); + addC(&con, TargetBytesPerWord, &adjustment, &stack, &stack); + } else { + offset = 0; + } + + return_(&con); + } + + virtual void popFrameAndUpdateStackAndReturn(unsigned footprint, + unsigned stackOffsetFromThread) + { + footprint += FrameHeaderSize; + + // see comment regarding the ARM64 ABI in allocateFrame + if (false and TargetBytesPerWord == 8) { + // ldp x29, x30, [sp],#footprint + con.code.append4(0xa8c00000 | (footprint << 15) | (31 << 5) | (30 << 10) + | 29); + } else { + lir::RegisterPair returnAddress(LinkRegister); + lir::Memory returnAddressSrc(StackRegister, + (footprint - 1) * TargetBytesPerWord); + moveMR(&con, + TargetBytesPerWord, + &returnAddressSrc, + TargetBytesPerWord, + &returnAddress); + } + + lir::RegisterPair stack(StackRegister); + lir::Memory newStackSrc(ThreadRegister, stackOffsetFromThread); + moveMR(&con, TargetBytesPerWord, &newStackSrc, TargetBytesPerWord, &stack); + + return_(&con); + } + + virtual void apply(lir::Operation op) + { + arch_->con.operations[op](&con); + } + + virtual void apply(lir::UnaryOperation op, OperandInfo a) + { + arch_->con.unaryOperations[Multimethod::index(op, a.type)]( + &con, a.size, a.operand); + } + + virtual void apply(lir::BinaryOperation op, OperandInfo a, OperandInfo b) + { + arch_->con.binaryOperations[index(&(arch_->con), op, a.type, b.type)]( + &con, a.size, a.operand, b.size, b.operand); + } + + virtual void apply(lir::TernaryOperation op, + OperandInfo a, + OperandInfo b, + OperandInfo c) + { + if (isBranch(op)) { + assertT(&con, a.size == b.size); + assertT(&con, c.size == TargetBytesPerWord); + assertT(&con, c.type == lir::Operand::Type::Constant); + + arch_->con.branchOperations[branchIndex(&(arch_->con), a.type, b.type)]( + &con, op, a.size, a.operand, b.operand, c.operand); + } else { + assertT(&con, b.size == c.size); + assertT(&con, b.type == lir::Operand::Type::RegisterPair); + assertT(&con, c.type == lir::Operand::Type::RegisterPair); + + arch_->con.ternaryOperations[index(&(arch_->con), op, a.type)]( + &con, b.size, a.operand, b.operand, c.operand); + } + } + + virtual void setDestination(uint8_t* dst) + { + con.result = dst; + } + + virtual void write() + { + uint8_t* dst = con.result; + unsigned dstOffset = 0; + for (MyBlock* b = con.firstBlock; b; b = b->next) { + if (DebugPool) { + fprintf(stderr, "write block %p\n", b); + } + + unsigned blockOffset = 0; + for (PoolEvent* e = b->poolEventHead; e; e = e->next) { + unsigned size = e->offset - blockOffset; + memcpy(dst + dstOffset, + con.code.data.begin() + b->offset + blockOffset, + size); + blockOffset = e->offset; + dstOffset += size; + + unsigned poolSize = 0; + for (PoolOffset* o = e->poolOffsetHead; o; o = o->next) { + if (DebugPool) { + fprintf(stderr, + "visit pool offset %p %d in block %p\n", + o, + o->offset, + b); + } + + unsigned entry = dstOffset + poolSize; + + if (needJump(b)) { + entry += TargetBytesPerWord; + } + + o->entry->address = dst + entry; + + unsigned instruction = o->block->start + padding(o->block, o->offset) + + o->offset; + + int32_t* p = reinterpret_cast(dst + instruction); + + if (TargetBytesPerWord == 8) { + int32_t v = entry - instruction; + expect(&con, v == (v & PoolOffsetMask)); + + const int32_t mask = (PoolOffsetMask >> 2) << 5; + *p = (((v >> 2) << 5) & mask) | ((~mask) & *p); + } else { + int32_t v = (entry - 8) - instruction; + expect(&con, v == (v & PoolOffsetMask)); + + *p = (v & PoolOffsetMask) | ((~PoolOffsetMask) & *p); + } + + poolSize += TargetBytesPerWord; + } + + bool jump = needJump(b); + if (jump) { + expect(&con, TargetBytesPerWord == 4); + + write4(dst + dstOffset, + isa::b((poolSize + TargetBytesPerWord - 8) >> 2)); + } + + dstOffset += poolSize + (jump ? TargetBytesPerWord : 0); + } + + unsigned size = b->size - blockOffset; + + memcpy(dst + dstOffset, + con.code.data.begin() + b->offset + blockOffset, + size); + + dstOffset += size; + } + + for (Task* t = con.tasks; t; t = t->next) { + t->run(&con); + } + + for (ConstantPoolEntry* e = con.constantPool; e; e = e->next) { + if (e->constant->resolved()) { + *static_cast(e->address) = e->constant->value(); + } else { + new (e->constant->listen(sizeof(ConstantPoolListener))) + ConstantPoolListener( + con.s, + static_cast(e->address), + e->callOffset ? dst + e->callOffset->value() + 8 : 0); + } + if (false) { + fprintf(stderr, + "constant %p at %p\n", + reinterpret_cast(e->constant->value()), + e->address); + } + } + } + + virtual Promise* offset(bool forTrace) + { + return arm::offsetPromise(&con, forTrace); + } + + virtual Block* endBlock(bool startNew) + { + MyBlock* b = con.lastBlock; + b->size = con.code.length() - b->offset; + if (startNew) { + con.lastBlock = new (con.zone) MyBlock(&con, con.code.length()); + } else { + con.lastBlock = 0; + } + return b; + } + + virtual void endEvent() + { + MyBlock* b = con.lastBlock; + unsigned thisEventOffset = con.code.length() - b->offset; + if (b->poolOffsetHead) { + int32_t v = (thisEventOffset + TargetBytesPerWord - 8) + - b->poolOffsetHead->offset; + + if (v > 0 and v != (v & PoolOffsetMask)) { + appendPoolEvent(&con, + b, + b->lastEventOffset, + b->poolOffsetHead, + b->lastPoolOffsetTail); + + if (DebugPool) { + for (PoolOffset* o = b->poolOffsetHead; + o != b->lastPoolOffsetTail->next; + o = o->next) { + fprintf(stderr, + "in endEvent, include %p %d in pool event %p at offset %d " + "in block %p\n", + o, + o->offset, + b->poolEventTail, + b->lastEventOffset, + b); + } + } + + b->poolOffsetHead = b->lastPoolOffsetTail->next; + b->lastPoolOffsetTail->next = 0; + if (b->poolOffsetHead == 0) { + b->poolOffsetTail = 0; + } + } + } + b->lastEventOffset = thisEventOffset; + b->lastPoolOffsetTail = b->poolOffsetTail; + } + + virtual unsigned length() + { + return con.code.length(); + } + + virtual unsigned footerSize() + { + return 0; + } + + virtual void dispose() + { + con.code.dispose(); + } + + Context con; + MyArchitecture* arch_; +}; + +Assembler* MyArchitecture::makeAssembler(Alloc* allocator, Zone* zone) +{ + return new (zone) MyAssembler(this->con.s, allocator, zone, this); +} + +} // namespace arm + +Architecture* makeArchitectureArm(System* system, bool) +{ + return new (allocate(system, sizeof(arm::MyArchitecture))) + arm::MyArchitecture(system); +} + +} // namespace codegen +} // namespace avian diff --git a/sgx-jvm/avian/src/codegen/target/arm/block.cpp b/sgx-jvm/avian/src/codegen/target/arm/block.cpp new file mode 100644 index 0000000000..fe2805e143 --- /dev/null +++ b/sgx-jvm/avian/src/codegen/target/arm/block.cpp @@ -0,0 +1,49 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#include "context.h" +#include "block.h" + +namespace avian { +namespace codegen { +namespace arm { + +void resolve(MyBlock*); + +unsigned padding(MyBlock*, unsigned); + +MyBlock::MyBlock(Context* context, unsigned offset) + : context(context), + next(0), + poolOffsetHead(0), + poolOffsetTail(0), + lastPoolOffsetTail(0), + poolEventHead(0), + poolEventTail(0), + lastEventOffset(0), + offset(offset), + start(~0), + size(0) +{ +} + +unsigned MyBlock::resolve(unsigned start, Assembler::Block* next) +{ + this->start = start; + this->next = static_cast(next); + + arm::resolve(this); + + return start + size + padding(this, size); +} + +} // namespace arm +} // namespace codegen +} // namespace avian diff --git a/sgx-jvm/avian/src/codegen/target/arm/block.h b/sgx-jvm/avian/src/codegen/target/arm/block.h new file mode 100644 index 0000000000..55f383c78f --- /dev/null +++ b/sgx-jvm/avian/src/codegen/target/arm/block.h @@ -0,0 +1,46 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#ifndef AVIAN_CODEGEN_ASSEMBLER_ARM_BLOCK_H +#define AVIAN_CODEGEN_ASSEMBLER_ARM_BLOCK_H + +#include +#include + +namespace avian { +namespace codegen { +namespace arm { + +class PoolEvent; + +class MyBlock : public Assembler::Block { + public: + MyBlock(Context* context, unsigned offset); + + virtual unsigned resolve(unsigned start, Assembler::Block* next); + + Context* context; + MyBlock* next; + PoolOffset* poolOffsetHead; + PoolOffset* poolOffsetTail; + PoolOffset* lastPoolOffsetTail; + PoolEvent* poolEventHead; + PoolEvent* poolEventTail; + unsigned lastEventOffset; + unsigned offset; + unsigned start; + unsigned size; +}; + +} // namespace arm +} // namespace codegen +} // namespace avian + +#endif // AVIAN_CODEGEN_ASSEMBLER_ARM_BLOCK_H diff --git a/sgx-jvm/avian/src/codegen/target/arm/context.cpp b/sgx-jvm/avian/src/codegen/target/arm/context.cpp new file mode 100644 index 0000000000..fa455fa622 --- /dev/null +++ b/sgx-jvm/avian/src/codegen/target/arm/context.cpp @@ -0,0 +1,36 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#include "context.h" +#include "block.h" + +namespace avian { +namespace codegen { +namespace arm { + +Context::Context(vm::System* s, util::Alloc* a, vm::Zone* zone) + : s(s), + zone(zone), + client(0), + code(s, a, 1024), + tasks(0), + result(0), + firstBlock(new (zone) MyBlock(this, 0)), + lastBlock(firstBlock), + poolOffsetHead(0), + poolOffsetTail(0), + constantPool(0), + constantPoolCount(0) +{ +} + +} // namespace arm +} // namespace codegen +} // namespace avian diff --git a/sgx-jvm/avian/src/codegen/target/arm/context.h b/sgx-jvm/avian/src/codegen/target/arm/context.h new file mode 100644 index 0000000000..d5eb90b8c6 --- /dev/null +++ b/sgx-jvm/avian/src/codegen/target/arm/context.h @@ -0,0 +1,113 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#ifndef AVIAN_CODEGEN_ASSEMBLER_ARM_CONTEXT_H +#define AVIAN_CODEGEN_ASSEMBLER_ARM_CONTEXT_H + +#include +#include +#include "avian/alloc-vector.h" + +namespace vm { +class System; +class Zone; +} // namespace vm + +namespace avian { + +namespace util { +class Aborter; +class Alloc; +} // namespace util + +namespace codegen { +namespace arm { + +class Task; +class MyBlock; +class PoolOffset; +class ConstantPoolEntry; + +class Context { + public: + Context(vm::System* s, util::Alloc* a, vm::Zone* zone); + + vm::System* s; + vm::Zone* zone; + Assembler::Client* client; + vm::Vector code; + Task* tasks; + uint8_t* result; + MyBlock* firstBlock; + MyBlock* lastBlock; + PoolOffset* poolOffsetHead; + PoolOffset* poolOffsetTail; + ConstantPoolEntry* constantPool; + unsigned constantPoolCount; +}; + +typedef void (*OperationType)(Context*); + +typedef void (*UnaryOperationType)(Context*, unsigned, lir::Operand*); + +typedef void (*BinaryOperationType)(Context*, + unsigned, + lir::Operand*, + unsigned, + lir::Operand*); + +typedef void (*TernaryOperationType)(Context*, + unsigned, + lir::Operand*, + lir::Operand*, + lir::Operand*); + +typedef void (*BranchOperationType)(Context*, + lir::TernaryOperation, + unsigned, + lir::Operand*, + lir::Operand*, + lir::Operand*); + +class ArchitectureContext { + public: + ArchitectureContext(vm::System* s) : s(s) + { + } + + vm::System* s; + OperationType operations[lir::OperationCount]; + UnaryOperationType + unaryOperations[lir::UnaryOperationCount * lir::Operand::TypeCount]; + BinaryOperationType binaryOperations[lir::BinaryOperationCount + * lir::Operand::TypeCount + * lir::Operand::TypeCount]; + TernaryOperationType ternaryOperations[lir::NonBranchTernaryOperationCount + * lir::Operand::TypeCount]; + BranchOperationType branchOperations[lir::BranchOperationCount + * lir::Operand::TypeCount + * lir::Operand::TypeCount]; +}; + +inline avian::util::Aborter* getAborter(Context* c) +{ + return c->s; +} + +inline avian::util::Aborter* getAborter(ArchitectureContext* c) +{ + return c->s; +} + +} // namespace arm +} // namespace codegen +} // namespace avian + +#endif // AVIAN_CODEGEN_ASSEMBLER_ARM_CONTEXT_H diff --git a/sgx-jvm/avian/src/codegen/target/arm/encode.h b/sgx-jvm/avian/src/codegen/target/arm/encode.h new file mode 100644 index 0000000000..b6ea050fe2 --- /dev/null +++ b/sgx-jvm/avian/src/codegen/target/arm/encode.h @@ -0,0 +1,692 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#ifndef AVIAN_CODEGEN_ASSEMBLER_ARM_ENCODE_H +#define AVIAN_CODEGEN_ASSEMBLER_ARM_ENCODE_H + +#include +#include + +namespace avian { +namespace codegen { +namespace arm { + +namespace isa { + +// SYSTEM REGISTERS +const int FPSID = 0x0; +const int FPSCR = 0x1; +const int FPEXC = 0x8; +// INSTRUCTION OPTIONS +enum CONDITION { + EQ, + NE, + CS, + CC, + MI, + PL, + VS, + VC, + HI, + LS, + GE, + LT, + GT, + LE, + AL, + NV +}; +enum SHIFTOP { LSL, LSR, ASR, ROR }; +// INSTRUCTION FORMATS +inline int + DATA(int cond, int opcode, int S, Register Rn, Register Rd, int shift, int Sh, Register Rm) +{ + return cond << 28 | opcode << 21 | S << 20 | Rn.index() << 16 | Rd.index() << 12 | shift << 7 + | Sh << 5 | Rm.index(); +} +inline int + DATAS(int cond, int opcode, int S, Register Rn, Register Rd, Register Rs, int Sh, Register Rm) +{ + return cond << 28 | opcode << 21 | S << 20 | Rn.index() << 16 | Rd.index() << 12 | Rs.index() << 8 + | Sh << 5 | 1 << 4 | Rm.index(); +} +inline int DATAI(int cond, int opcode, int S, Register Rn, Register Rd, int rot, int imm) +{ + return cond << 28 | 1 << 25 | opcode << 21 | S << 20 | Rn.index() << 16 | Rd.index() << 12 + | rot << 8 | (imm & 0xff); +} +inline int BRANCH(int cond, int L, int offset) +{ + return cond << 28 | 5 << 25 | L << 24 | (offset & 0xffffff); +} +inline int BRANCHX(int cond, int L, Register Rm) +{ + return cond << 28 | 0x4bffc << 6 | L << 5 | 1 << 4 | Rm.index(); +} +inline int MULTIPLY(int cond, int mul, int S, Register Rd, Register Rn, Register Rs, Register Rm) +{ + return cond << 28 | mul << 21 | S << 20 | Rd.index() << 16 | Rn.index() << 12 | Rs.index() << 8 + | 9 << 4 | Rm.index(); +} +inline int XFER(int cond, + int P, + int U, + int B, + int W, + int L, + Register Rn, + Register Rd, + int shift, + int Sh, + Register Rm) +{ + return cond << 28 | 3 << 25 | P << 24 | U << 23 | B << 22 | W << 21 | L << 20 + | Rn.index() << 16 | Rd.index() << 12 | shift << 7 | Sh << 5 | Rm.index(); +} +inline int XFERI(int cond, + int P, + int U, + int B, + int W, + int L, + Register Rn, + Register Rd, + int offset) +{ + return cond << 28 | 2 << 25 | P << 24 | U << 23 | B << 22 | W << 21 | L << 20 + | Rn.index() << 16 | Rd.index() << 12 | (offset & 0xfff); +} +inline int XFER2(int cond, + int P, + int U, + int W, + int L, + Register Rn, + Register Rd, + int S, + int H, + Register Rm) +{ + return cond << 28 | P << 24 | U << 23 | W << 21 | L << 20 | Rn.index() << 16 + | Rd.index() << 12 | 1 << 7 | S << 6 | H << 5 | 1 << 4 | Rm.index(); +} +inline int XFER2I(int cond, + int P, + int U, + int W, + int L, + Register Rn, + Register Rd, + int offsetH, + int S, + int H, + int offsetL) +{ + return cond << 28 | P << 24 | U << 23 | 1 << 22 | W << 21 | L << 20 | Rn.index() << 16 + | Rd.index() << 12 | offsetH << 8 | 1 << 7 | S << 6 | H << 5 | 1 << 4 + | (offsetL & 0xf); +} +inline int COOP(int cond, + int opcode_1, + int CRn, + int CRd, + int cp_num, + int opcode_2, + int CRm) +{ + return cond << 28 | 0xe << 24 | opcode_1 << 20 | CRn << 16 | CRd << 12 + | cp_num << 8 | opcode_2 << 5 | CRm; +} +inline int COXFER(int cond, + int P, + int U, + int N, + int W, + int L, + Register Rn, + int CRd, + int cp_num, + int offset) // offset is in words, not bytes +{ + return cond << 28 | 0x6 << 25 | P << 24 | U << 23 | N << 22 | W << 21 + | L << 20 | Rn.index() << 16 | CRd << 12 | cp_num << 8 | (offset & 0xff) >> 2; +} +inline int COREG(int cond, + int opcode_1, + int L, + int CRn, + Register Rd, + int cp_num, + int opcode_2, + int CRm) +{ + return cond << 28 | 0xe << 24 | opcode_1 << 21 | L << 20 | CRn << 16 + | Rd.index() << 12 | cp_num << 8 | opcode_2 << 5 | 1 << 4 | CRm; +} +inline int + COREG2(int cond, int L, Register Rn, Register Rd, int cp_num, int opcode, int CRm) +{ + return cond << 28 | 0xc4 << 20 | L << 20 | Rn.index() << 16 | Rd.index() << 12 | cp_num << 8 + | opcode << 4 | CRm; +} +// FIELD CALCULATORS +inline int calcU(int imm) +{ + return imm >= 0 ? 1 : 0; +} +// INSTRUCTIONS +// The "cond" and "S" fields are set using the SETCOND() and SETS() functions +inline int b(int offset) +{ + return BRANCH(AL, 0, offset); +} +inline int bl(int offset) +{ + return BRANCH(AL, 1, offset); +} +inline int bx(Register Rm) +{ + return BRANCHX(AL, 0, Rm); +} +inline int blx(Register Rm) +{ + return BRANCHX(AL, 1, Rm); +} +inline int and_(Register Rd, Register Rn, Register Rm, int Sh = 0, int shift = 0) +{ + return DATA(AL, 0x0, 0, Rn, Rd, shift, Sh, Rm); +} +inline int eor(Register Rd, Register Rn, Register Rm, int Sh = 0, int shift = 0) +{ + return DATA(AL, 0x1, 0, Rn, Rd, shift, Sh, Rm); +} +inline int rsb(Register Rd, Register Rn, Register Rm, int Sh = 0, int shift = 0) +{ + return DATA(AL, 0x3, 0, Rn, Rd, shift, Sh, Rm); +} +inline int add(Register Rd, Register Rn, Register Rm, int Sh = 0, int shift = 0) +{ + return DATA(AL, 0x4, 0, Rn, Rd, shift, Sh, Rm); +} +inline int adc(Register Rd, Register Rn, Register Rm, int Sh = 0, int shift = 0) +{ + return DATA(AL, 0x5, 0, Rn, Rd, shift, Sh, Rm); +} +inline int rsc(Register Rd, Register Rn, Register Rm, int Sh = 0, int shift = 0) +{ + return DATA(AL, 0x7, 0, Rn, Rd, shift, Sh, Rm); +} +inline int cmp(Register Rn, Register Rm, int Sh = 0, int shift = 0) +{ + return DATA(AL, 0xa, 1, Rn, Register(0), shift, Sh, Rm); +} +inline int orr(Register Rd, Register Rn, Register Rm, int Sh = 0, int shift = 0) +{ + return DATA(AL, 0xc, 0, Rn, Rd, shift, Sh, Rm); +} +inline int mov(Register Rd, Register Rm, int Sh = 0, int shift = 0) +{ + return DATA(AL, 0xd, 0, Register(0), Rd, shift, Sh, Rm); +} +inline int mvn(Register Rd, Register Rm, int Sh = 0, int shift = 0) +{ + return DATA(AL, 0xf, 0, Register(0), Rd, shift, Sh, Rm); +} +inline int andi(Register Rd, Register Rn, int imm, int rot = 0) +{ + return DATAI(AL, 0x0, 0, Rn, Rd, rot, imm); +} +inline int subi(Register Rd, Register Rn, int imm, int rot = 0) +{ + return DATAI(AL, 0x2, 0, Rn, Rd, rot, imm); +} +inline int rsbi(Register Rd, Register Rn, int imm, int rot = 0) +{ + return DATAI(AL, 0x3, 0, Rn, Rd, rot, imm); +} +inline int addi(Register Rd, Register Rn, int imm, int rot = 0) +{ + return DATAI(AL, 0x4, 0, Rn, Rd, rot, imm); +} +inline int adci(Register Rd, Register Rn, int imm, int rot = 0) +{ + return DATAI(AL, 0x5, 0, Rn, Rd, rot, imm); +} +inline int bici(Register Rd, Register Rn, int imm, int rot = 0) +{ + return DATAI(AL, 0xe, 0, Rn, Rd, rot, imm); +} +inline int cmpi(Register Rn, int imm, int rot = 0) +{ + return DATAI(AL, 0xa, 1, Rn, Register(0), rot, imm); +} +inline int movi(Register Rd, int imm, int rot = 0) +{ + return DATAI(AL, 0xd, 0, Register(0), Rd, rot, imm); +} +inline int orrsh(Register Rd, Register Rn, Register Rm, Register Rs, int Sh) +{ + return DATAS(AL, 0xc, 0, Rn, Rd, Rs, Sh, Rm); +} +inline int movsh(Register Rd, Register Rm, Register Rs, int Sh) +{ + return DATAS(AL, 0xd, 0, Register(0), Rd, Rs, Sh, Rm); +} +inline int mul(Register Rd, Register Rm, Register Rs) +{ + return MULTIPLY(AL, 0, 0, Rd, Register(0), Rs, Rm); +} +inline int mla(Register Rd, Register Rm, Register Rs, Register Rn) +{ + return MULTIPLY(AL, 1, 0, Rd, Rn, Rs, Rm); +} +inline int umull(Register RdLo, Register RdHi, Register Rm, Register Rs) +{ + return MULTIPLY(AL, 4, 0, RdHi, RdLo, Rs, Rm); +} +inline int ldr(Register Rd, Register Rn, Register Rm, int W = 0) +{ + return XFER(AL, 1, 1, 0, W, 1, Rn, Rd, 0, 0, Rm); +} +inline int ldri(Register Rd, Register Rn, int imm, int W = 0) +{ + return XFERI(AL, 1, calcU(imm), 0, W, 1, Rn, Rd, abs(imm)); +} +inline int ldrb(Register Rd, Register Rn, Register Rm) +{ + return XFER(AL, 1, 1, 1, 0, 1, Rn, Rd, 0, 0, Rm); +} +inline int ldrbi(Register Rd, Register Rn, int imm) +{ + return XFERI(AL, 1, calcU(imm), 1, 0, 1, Rn, Rd, abs(imm)); +} +inline int str(Register Rd, Register Rn, Register Rm, int W = 0) +{ + return XFER(AL, 1, 1, 0, W, 0, Rn, Rd, 0, 0, Rm); +} +inline int stri(Register Rd, Register Rn, int imm, int W = 0) +{ + return XFERI(AL, 1, calcU(imm), 0, W, 0, Rn, Rd, abs(imm)); +} +inline int strb(Register Rd, Register Rn, Register Rm) +{ + return XFER(AL, 1, 1, 1, 0, 0, Rn, Rd, 0, 0, Rm); +} +inline int strbi(Register Rd, Register Rn, int imm) +{ + return XFERI(AL, 1, calcU(imm), 1, 0, 0, Rn, Rd, abs(imm)); +} +inline int ldrh(Register Rd, Register Rn, Register Rm) +{ + return XFER2(AL, 1, 1, 0, 1, Rn, Rd, 0, 1, Rm); +} +inline int ldrhi(Register Rd, Register Rn, int imm) +{ + return XFER2I(AL, + 1, + calcU(imm), + 0, + 1, + Rn, + Rd, + abs(imm) >> 4 & 0xf, + 0, + 1, + abs(imm) & 0xf); +} +inline int strh(Register Rd, Register Rn, Register Rm) +{ + return XFER2(AL, 1, 1, 0, 0, Rn, Rd, 0, 1, Rm); +} +inline int strhi(Register Rd, Register Rn, int imm) +{ + return XFER2I(AL, + 1, + calcU(imm), + 0, + 0, + Rn, + Rd, + abs(imm) >> 4 & 0xf, + 0, + 1, + abs(imm) & 0xf); +} +inline int ldrsh(Register Rd, Register Rn, Register Rm) +{ + return XFER2(AL, 1, 1, 0, 1, Rn, Rd, 1, 1, Rm); +} +inline int ldrshi(Register Rd, Register Rn, int imm) +{ + return XFER2I(AL, + 1, + calcU(imm), + 0, + 1, + Rn, + Rd, + abs(imm) >> 4 & 0xf, + 1, + 1, + abs(imm) & 0xf); +} +inline int ldrsb(Register Rd, Register Rn, Register Rm) +{ + return XFER2(AL, 1, 1, 0, 1, Rn, Rd, 1, 0, Rm); +} +inline int ldrsbi(Register Rd, Register Rn, int imm) +{ + return XFER2I(AL, + 1, + calcU(imm), + 0, + 1, + Rn, + Rd, + abs(imm) >> 4 & 0xf, + 1, + 0, + abs(imm) & 0xf); +} +// breakpoint instruction, this really has its own instruction format +inline int bkpt(int16_t immed) +{ + return 0xe1200070 | (((unsigned)immed & 0xffff) >> 4 << 8) | (immed & 0xf); +} +// COPROCESSOR INSTRUCTIONS +inline int mcr(int coproc, + int opcode_1, + Register Rd, + int CRn, + int CRm, + int opcode_2 = 0) +{ + return COREG(AL, opcode_1, 0, CRn, Rd, coproc, opcode_2, CRm); +} +inline int mcrr(int coproc, int opcode, Register Rd, Register Rn, int CRm) +{ + return COREG2(AL, 0, Rn, Rd, coproc, opcode, CRm); +} +inline int mrc(int coproc, + int opcode_1, + Register Rd, + int CRn, + int CRm, + int opcode_2 = 0) +{ + return COREG(AL, opcode_1, 1, CRn, Rd, coproc, opcode_2, CRm); +} +inline int mrrc(int coproc, int opcode, Register Rd, Register Rn, int CRm) +{ + return COREG2(AL, 1, Rn, Rd, coproc, opcode, CRm); +} +// VFP FLOATING-POINT INSTRUCTIONS +inline int fmuls(int Sd, int Sn, int Sm) +{ + return COOP(AL, + (Sd & 1) << 2 | 2, + Sn >> 1, + Sd >> 1, + 10, + (Sn & 1) << 2 | (Sm & 1), + Sm >> 1); +} +inline int fadds(int Sd, int Sn, int Sm) +{ + return COOP(AL, + (Sd & 1) << 2 | 3, + Sn >> 1, + Sd >> 1, + 10, + (Sn & 1) << 2 | (Sm & 1), + Sm >> 1); +} +inline int fsubs(int Sd, int Sn, int Sm) +{ + return COOP(AL, + (Sd & 1) << 2 | 3, + Sn >> 1, + Sd >> 1, + 10, + (Sn & 1) << 2 | (Sm & 1) | 2, + Sm >> 1); +} +inline int fdivs(int Sd, int Sn, int Sm) +{ + return COOP(AL, + (Sd & 1) << 2 | 8, + Sn >> 1, + Sd >> 1, + 10, + (Sn & 1) << 2 | (Sm & 1), + Sm >> 1); +} +inline int fmuld(int Dd, int Dn, int Dm) +{ + return COOP(AL, 2, Dn, Dd, 11, 0, Dm); +} +inline int faddd(int Dd, int Dn, int Dm) +{ + return COOP(AL, 3, Dn, Dd, 11, 0, Dm); +} +inline int fsubd(int Dd, int Dn, int Dm) +{ + return COOP(AL, 3, Dn, Dd, 11, 2, Dm); +} +inline int fdivd(int Dd, int Dn, int Dm) +{ + return COOP(AL, 8, Dn, Dd, 11, 0, Dm); +} +inline int fcpys(int Sd, int Sm) +{ + return COOP(AL, 0xb | (Sd & 1) << 2, 0, Sd >> 1, 10, 2 | (Sm & 1), Sm >> 1); +} +inline int fabss(int Sd, int Sm) +{ + return COOP(AL, 0xb | (Sd & 1) << 2, 0, Sd >> 1, 10, 6 | (Sm & 1), Sm >> 1); +} +inline int fnegs(int Sd, int Sm) +{ + return COOP(AL, 0xb | (Sd & 1) << 2, 1, Sd >> 1, 10, 2 | (Sm & 1), Sm >> 1); +} +inline int fsqrts(int Sd, int Sm) +{ + return COOP(AL, 0xb | (Sd & 1) << 2, 1, Sd >> 1, 10, 6 | (Sm & 1), Sm >> 1); +} +inline int fcmps(int Sd, int Sm) +{ + return COOP(AL, 0xb | (Sd & 1) << 2, 4, Sd >> 1, 10, 2 | (Sm & 1), Sm >> 1); +} +inline int fcvtds(int Dd, int Sm) +{ + return COOP(AL, 0xb, 7, Dd, 10, 6 | (Sm & 1), Sm >> 1); +} +inline int fsitos(int Sd, int Sm) +{ + return COOP(AL, 0xb | (Sd & 1) << 2, 8, Sd >> 1, 10, 6 | (Sm & 1), Sm >> 1); +} +inline int ftosizs(int Sd, int Sm) +{ + return COOP(AL, 0xb | (Sd & 1) << 2, 0xd, Sd >> 1, 10, 6 | (Sm & 1), Sm >> 1); +} +inline int fcpyd(int Dd, int Dm) +{ + return COOP(AL, 0xb, 0, Dd, 11, 2, Dm); +} +inline int fabsd(int Dd, int Dm) +{ + return COOP(AL, 0xb, 0, Dd, 11, 6, Dm); +} +inline int fnegd(int Dd, int Dm) +{ + return COOP(AL, 0xb, 1, Dd, 11, 2, Dm); +} +inline int fsqrtd(int Dd, int Dm) +{ + return COOP(AL, 0xb, 1, Dd, 11, 6, Dm); +} +// double-precision comparison instructions +inline int fcmpd(int Dd, int Dm) +{ + return COOP(AL, 0xb, 4, Dd, 11, 2, Dm); +} +// double-precision conversion instructions +inline int fcvtsd(int Sd, int Dm) +{ + return COOP(AL, 0xb | (Sd & 1) << 2, 7, Sd >> 1, 11, 6, Dm); +} +inline int fsitod(int Dd, int Sm) +{ + return COOP(AL, 0xb, 8, Dd, 11, 6 | (Sm & 1), Sm >> 1); +} +inline int ftosizd(int Sd, int Dm) +{ + return COOP(AL, 0xb | (Sd & 1) << 2, 0xd, Sd >> 1, 11, 6, Dm); +} +// single load/store instructions for both precision types +inline int flds(int Sd, Register Rn, int offset = 0) +{ + return COXFER(AL, 1, 1, Sd & 1, 0, 1, Rn, Sd >> 1, 10, offset); +}; +inline int fldd(int Dd, Register Rn, int offset = 0) +{ + return COXFER(AL, 1, 1, 0, 0, 1, Rn, Dd, 11, offset); +}; +inline int fsts(int Sd, Register Rn, int offset = 0) +{ + return COXFER(AL, 1, 1, Sd & 1, 0, 0, Rn, Sd >> 1, 10, offset); +}; +inline int fstd(int Dd, Register Rn, int offset = 0) +{ + return COXFER(AL, 1, 1, 0, 0, 0, Rn, Dd, 11, offset); +}; +// move between GPRs and FPRs +inline int fmsr(int Sn, Register Rd) +{ + return mcr(10, 0, Rd, Sn >> 1, 0, (Sn & 1) << 2); +} +inline int fmrs(Register Rd, int Sn) +{ + return mrc(10, 0, Rd, Sn >> 1, 0, (Sn & 1) << 2); +} +// move to/from VFP system registers +inline int fmrx(Register Rd, int reg) +{ + return mrc(10, 7, Rd, reg, 0); +} +// these move around pairs of single-precision registers +inline int fmdrr(int Dm, Register Rd, Register Rn) +{ + return mcrr(11, 1, Rd, Rn, Dm); +} +inline int fmrrd(Register Rd, Register Rn, int Dm) +{ + return mrrc(11, 1, Rd, Rn, Dm); +} +// FLAG SETTERS +inline int SETCOND(int ins, int cond) +{ + return ((ins & 0x0fffffff) | (cond << 28)); +} +inline int SETS(int ins) +{ + return ins | 1 << 20; +} +// PSEUDO-INSTRUCTIONS +inline int lsl(Register Rd, Register Rm, Register Rs) +{ + return movsh(Rd, Rm, Rs, LSL); +} +inline int lsli(Register Rd, Register Rm, int imm) +{ + return mov(Rd, Rm, LSL, imm); +} +inline int lsr(Register Rd, Register Rm, Register Rs) +{ + return movsh(Rd, Rm, Rs, LSR); +} +inline int lsri(Register Rd, Register Rm, int imm) +{ + return mov(Rd, Rm, LSR, imm); +} +inline int asr(Register Rd, Register Rm, Register Rs) +{ + return movsh(Rd, Rm, Rs, ASR); +} +inline int asri(Register Rd, Register Rm, int imm) +{ + return mov(Rd, Rm, ASR, imm); +} +inline int beq(int offset) +{ + return SETCOND(b(offset), EQ); +} +inline int bne(int offset) +{ + return SETCOND(b(offset), NE); +} +inline int bls(int offset) +{ + return SETCOND(b(offset), LS); +} +inline int bhi(int offset) +{ + return SETCOND(b(offset), HI); +} +inline int blt(int offset) +{ + return SETCOND(b(offset), LT); +} +inline int bgt(int offset) +{ + return SETCOND(b(offset), GT); +} +inline int ble(int offset) +{ + return SETCOND(b(offset), LE); +} +inline int bge(int offset) +{ + return SETCOND(b(offset), GE); +} +inline int blo(int offset) +{ + return SETCOND(b(offset), CC); +} +inline int bhs(int offset) +{ + return SETCOND(b(offset), CS); +} +inline int bpl(int offset) +{ + return SETCOND(b(offset), PL); +} +inline int fmstat() +{ + return fmrx(Register(15), FPSCR); +} +// todo: make this pretty: +inline int dmb() +{ + return 0xf57ff05f; +} + +} // namespace isa + +inline void emit(Context* con, int code) +{ + con->code.append4(code); +} + +} // namespace arm +} // namespace codegen +} // namespace avian + +#endif // AVIAN_CODEGEN_ASSEMBLER_ARM_ENCODE_H diff --git a/sgx-jvm/avian/src/codegen/target/arm/fixup.cpp b/sgx-jvm/avian/src/codegen/target/arm/fixup.cpp new file mode 100644 index 0000000000..d345ae3cba --- /dev/null +++ b/sgx-jvm/avian/src/codegen/target/arm/fixup.cpp @@ -0,0 +1,333 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#include "context.h" +#include "fixup.h" +#include "block.h" + +namespace { + +const unsigned InstructionSize = 4; + +} // namespace + +namespace avian { +namespace codegen { +namespace arm { + +using namespace util; + +unsigned padding(MyBlock*, unsigned); + +OffsetPromise::OffsetPromise(Context* con, + MyBlock* block, + unsigned offset, + bool forTrace) + : con(con), block(block), offset(offset), forTrace(forTrace) +{ +} + +bool OffsetPromise::resolved() +{ + return block->start != static_cast(~0); +} + +int64_t OffsetPromise::value() +{ + assertT(con, resolved()); + + unsigned o = offset - block->offset; + return block->start + padding(block, forTrace ? o - InstructionSize : o) + o; +} + +Promise* offsetPromise(Context* con, bool forTrace) +{ + return new (con->zone) + OffsetPromise(con, con->lastBlock, con->code.length(), forTrace); +} + +OffsetListener::OffsetListener(vm::System* s, uint8_t* instruction) + : s(s), instruction(instruction) +{ +} + +bool OffsetListener::resolve(int64_t value, void** location) +{ + void* p = updateOffset(s, instruction, value); + if (location) + *location = p; + return false; +} + +OffsetTask::OffsetTask(Task* next, Promise* promise, Promise* instructionOffset) + : Task(next), promise(promise), instructionOffset(instructionOffset) +{ +} + +void OffsetTask::run(Context* con) +{ + if (promise->resolved()) { + updateOffset( + con->s, con->result + instructionOffset->value(), promise->value()); + } else { + new (promise->listen(sizeof(OffsetListener))) + OffsetListener(con->s, con->result + instructionOffset->value()); + } +} + +void appendOffsetTask(Context* con, + Promise* promise, + Promise* instructionOffset) +{ + con->tasks = new (con->zone) + OffsetTask(con->tasks, promise, instructionOffset); +} + +bool bounded(int right, int left, int32_t v) +{ + return ((v << left) >> left) == v and ((v >> right) << right) == v; +} + +void* updateOffset(vm::System* s, uint8_t* instruction, int64_t value) +{ + int32_t* p = reinterpret_cast(instruction); + + int32_t v; + int32_t mask; + if (vm::TargetBytesPerWord == 8) { + if ((*p >> 24) == 0x54) { + // conditional branch + v = ((reinterpret_cast(value) - instruction) >> 2) << 5; + mask = 0xFFFFE0; + expect(s, bounded(5, 8, v)); + } else { + // unconditional branch + v = (reinterpret_cast(value) - instruction) >> 2; + mask = 0x3FFFFFF; + expect(s, bounded(0, 6, v)); + } + } else { + v = (reinterpret_cast(value) - (instruction + 8)) >> 2; + mask = 0xFFFFFF; + expect(s, bounded(0, 8, v)); + } + + *p = (v & mask) | ((~mask) & *p); + + return instruction + InstructionSize; +} + +ConstantPoolEntry::ConstantPoolEntry(Context* con, + Promise* constant, + ConstantPoolEntry* next, + Promise* callOffset) + : con(con), + constant(constant), + next(next), + callOffset(callOffset), + address(0) +{ +} + +int64_t ConstantPoolEntry::value() +{ + assertT(con, resolved()); + + return reinterpret_cast(address); +} + +bool ConstantPoolEntry::resolved() +{ + return address != 0; +} + +ConstantPoolListener::ConstantPoolListener(vm::System* s, + vm::target_uintptr_t* address, + uint8_t* returnAddress) + : s(s), address(address), returnAddress(returnAddress) +{ +} + +bool ConstantPoolListener::resolve(int64_t value, void** location) +{ + *address = value; + if (location) { + *location = returnAddress ? static_cast(returnAddress) : address; + } + return true; +} + +PoolOffset::PoolOffset(MyBlock* block, + ConstantPoolEntry* entry, + unsigned offset) + : block(block), entry(entry), next(0), offset(offset) +{ +} + +PoolEvent::PoolEvent(PoolOffset* poolOffsetHead, + PoolOffset* poolOffsetTail, + unsigned offset) + : poolOffsetHead(poolOffsetHead), + poolOffsetTail(poolOffsetTail), + next(0), + offset(offset) +{ +} + +void appendConstantPoolEntry(Context* con, + Promise* constant, + Promise* callOffset) +{ + if (constant->resolved()) { + // make a copy, since the original might be allocated on the + // stack, and we need our copy to live until assembly is complete + constant = new (con->zone) ResolvedPromise(constant->value()); + } + + con->constantPool = new (con->zone) + ConstantPoolEntry(con, constant, con->constantPool, callOffset); + + ++con->constantPoolCount; + + PoolOffset* o = new (con->zone) + PoolOffset(con->lastBlock, + con->constantPool, + con->code.length() - con->lastBlock->offset); + + if (DebugPool) { + fprintf(stderr, + "add pool offset %p %d to block %p\n", + o, + o->offset, + con->lastBlock); + } + + if (con->lastBlock->poolOffsetTail) { + con->lastBlock->poolOffsetTail->next = o; + } else { + con->lastBlock->poolOffsetHead = o; + } + con->lastBlock->poolOffsetTail = o; +} + +void appendPoolEvent(Context* con, + MyBlock* b, + unsigned offset, + PoolOffset* head, + PoolOffset* tail) +{ + PoolEvent* e = new (con->zone) PoolEvent(head, tail, offset); + + if (b->poolEventTail) { + b->poolEventTail->next = e; + } else { + b->poolEventHead = e; + } + b->poolEventTail = e; +} + +bool needJump(MyBlock* b) +{ + return b->next or b->size != (b->size & PoolOffsetMask); +} + +unsigned padding(MyBlock* b, unsigned offset) +{ + unsigned total = 0; + for (PoolEvent* e = b->poolEventHead; e; e = e->next) { + if (e->offset <= offset) { + if (needJump(b)) { + total += vm::TargetBytesPerWord; + } + for (PoolOffset* o = e->poolOffsetHead; o; o = o->next) { + total += vm::TargetBytesPerWord; + } + } else { + break; + } + } + return total; +} + +void resolve(MyBlock* b) +{ + Context* con = b->context; + + if (b->poolOffsetHead) { + if (con->poolOffsetTail) { + con->poolOffsetTail->next = b->poolOffsetHead; + } else { + con->poolOffsetHead = b->poolOffsetHead; + } + con->poolOffsetTail = b->poolOffsetTail; + } + + if (con->poolOffsetHead) { + bool append; + if (b->next == 0 or b->next->poolEventHead) { + append = true; + } else { + int32_t v + = (b->start + b->size + b->next->size + vm::TargetBytesPerWord - 8) + - (con->poolOffsetHead->offset + con->poolOffsetHead->block->start); + + append = (v != (v & PoolOffsetMask)); + + if (DebugPool) { + fprintf(stderr, + "current %p %d %d next %p %d %d\n", + b, + b->start, + b->size, + b->next, + b->start + b->size, + b->next->size); + fprintf(stderr, + "offset %p %d is of distance %d to next block; append? %d\n", + con->poolOffsetHead, + con->poolOffsetHead->offset, + v, + append); + } + } + + if (append) { +#ifndef NDEBUG + int32_t v + = (b->start + b->size - 8) + - (con->poolOffsetHead->offset + con->poolOffsetHead->block->start); + + expect(con, v == (v & PoolOffsetMask)); +#endif // not NDEBUG + + appendPoolEvent( + con, b, b->size, con->poolOffsetHead, con->poolOffsetTail); + + if (DebugPool) { + for (PoolOffset* o = con->poolOffsetHead; o; o = o->next) { + fprintf(stderr, + "include %p %d in pool event %p at offset %d in block %p\n", + o, + o->offset, + b->poolEventTail, + b->size, + b); + } + } + + con->poolOffsetHead = 0; + con->poolOffsetTail = 0; + } + } +} + +} // namespace arm +} // namespace codegen +} // namespace avian diff --git a/sgx-jvm/avian/src/codegen/target/arm/fixup.h b/sgx-jvm/avian/src/codegen/target/arm/fixup.h new file mode 100644 index 0000000000..31340ed4bd --- /dev/null +++ b/sgx-jvm/avian/src/codegen/target/arm/fixup.h @@ -0,0 +1,153 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#ifndef AVIAN_CODEGEN_ASSEMBLER_ARM_PROMISE_H +#define AVIAN_CODEGEN_ASSEMBLER_ARM_PROMISE_H + +#include "avian/target.h" + +#include +#include +#include "avian/alloc-vector.h" + +namespace vm { +class System; +} + +namespace avian { +namespace codegen { +namespace arm { + +const bool DebugPool = false; + +const int32_t PoolOffsetMask = vm::TargetBytesPerWord == 8 ? 0x1FFFFF : 0xFFF; + +class Task { + public: + Task(Task* next) : next(next) + { + } + + virtual void run(Context* con) = 0; + + Task* next; +}; + +class OffsetPromise : public Promise { + public: + OffsetPromise(Context* con, MyBlock* block, unsigned offset, bool forTrace); + + virtual bool resolved(); + + virtual int64_t value(); + + Context* con; + MyBlock* block; + unsigned offset; + bool forTrace; +}; + +Promise* offsetPromise(Context* con, bool forTrace = false); + +class OffsetListener : public Promise::Listener { + public: + OffsetListener(vm::System* s, uint8_t* instruction); + + virtual bool resolve(int64_t value, void** location); + + vm::System* s; + uint8_t* instruction; +}; + +class OffsetTask : public Task { + public: + OffsetTask(Task* next, Promise* promise, Promise* instructionOffset); + + virtual void run(Context* con); + + Promise* promise; + Promise* instructionOffset; +}; + +void appendOffsetTask(Context* con, + Promise* promise, + Promise* instructionOffset); + +void* updateOffset(vm::System* s, uint8_t* instruction, int64_t value); + +class ConstantPoolEntry : public Promise { + public: + ConstantPoolEntry(Context* con, + Promise* constant, + ConstantPoolEntry* next, + Promise* callOffset); + + virtual int64_t value(); + + virtual bool resolved(); + + Context* con; + Promise* constant; + ConstantPoolEntry* next; + Promise* callOffset; + void* address; + unsigned constantPoolCount; +}; + +class ConstantPoolListener : public Promise::Listener { + public: + ConstantPoolListener(vm::System* s, + vm::target_uintptr_t* address, + uint8_t* returnAddress); + + virtual bool resolve(int64_t value, void** location); + + vm::System* s; + vm::target_uintptr_t* address; + uint8_t* returnAddress; +}; + +class PoolOffset { + public: + PoolOffset(MyBlock* block, ConstantPoolEntry* entry, unsigned offset); + + MyBlock* block; + ConstantPoolEntry* entry; + PoolOffset* next; + unsigned offset; +}; + +class PoolEvent { + public: + PoolEvent(PoolOffset* poolOffsetHead, + PoolOffset* poolOffsetTail, + unsigned offset); + + PoolOffset* poolOffsetHead; + PoolOffset* poolOffsetTail; + PoolEvent* next; + unsigned offset; +}; + +void appendConstantPoolEntry(Context* con, + Promise* constant, + Promise* callOffset); + +void appendPoolEvent(Context* con, + MyBlock* b, + unsigned offset, + PoolOffset* head, + PoolOffset* tail); + +} // namespace arm +} // namespace codegen +} // namespace avian + +#endif // AVIAN_CODEGEN_ASSEMBLER_ARM_PROMISE_H diff --git a/sgx-jvm/avian/src/codegen/target/arm/multimethod.cpp b/sgx-jvm/avian/src/codegen/target/arm/multimethod.cpp new file mode 100644 index 0000000000..94e3d6f3fb --- /dev/null +++ b/sgx-jvm/avian/src/codegen/target/arm/multimethod.cpp @@ -0,0 +1,142 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#include "context.h" +#include "operations.h" + +#include "multimethod.h" +#include "../multimethod.h" + +namespace avian { +namespace codegen { +namespace arm { + +using namespace util; + +unsigned index(ArchitectureContext*, + lir::BinaryOperation operation, + lir::Operand::Type operand1, + lir::Operand::Type operand2) +{ + return operation + (lir::BinaryOperationCount * (unsigned)operand1) + + (lir::BinaryOperationCount * lir::Operand::TypeCount * (unsigned)operand2); +} + +unsigned index(ArchitectureContext* con UNUSED, + lir::TernaryOperation operation, + lir::Operand::Type operand1) +{ + assertT(con, not isBranch(operation)); + + return operation + (lir::NonBranchTernaryOperationCount * (unsigned)operand1); +} + +unsigned branchIndex(ArchitectureContext* con UNUSED, + lir::Operand::Type operand1, + lir::Operand::Type operand2) +{ + return (unsigned)operand1 + (lir::Operand::TypeCount * (unsigned)operand2); +} + +void populateTables(ArchitectureContext* con) +{ + const lir::Operand::Type C = lir::Operand::Type::Constant; + const lir::Operand::Type A = lir::Operand::Type::Address; + const lir::Operand::Type R = lir::Operand::Type::RegisterPair; + const lir::Operand::Type M = lir::Operand::Type::Memory; + + OperationType* zo = con->operations; + UnaryOperationType* uo = con->unaryOperations; + BinaryOperationType* bo = con->binaryOperations; + TernaryOperationType* to = con->ternaryOperations; + BranchOperationType* bro = con->branchOperations; + + zo[lir::Return] = return_; + zo[lir::LoadBarrier] = loadBarrier; + zo[lir::StoreStoreBarrier] = storeStoreBarrier; + zo[lir::StoreLoadBarrier] = storeLoadBarrier; + zo[lir::Trap] = trap; + + uo[Multimethod::index(lir::LongCall, C)] = CAST1(longCallC); + + uo[Multimethod::index(lir::AlignedLongCall, C)] = CAST1(longCallC); + + uo[Multimethod::index(lir::LongJump, C)] = CAST1(longJumpC); + + uo[Multimethod::index(lir::AlignedLongJump, C)] = CAST1(longJumpC); + + uo[Multimethod::index(lir::Jump, R)] = CAST1(jumpR); + uo[Multimethod::index(lir::Jump, C)] = CAST1(jumpC); + + uo[Multimethod::index(lir::AlignedJump, R)] = CAST1(jumpR); + uo[Multimethod::index(lir::AlignedJump, C)] = CAST1(jumpC); + + uo[Multimethod::index(lir::Call, C)] = CAST1(callC); + uo[Multimethod::index(lir::Call, R)] = CAST1(callR); + + uo[Multimethod::index(lir::AlignedCall, C)] = CAST1(callC); + uo[Multimethod::index(lir::AlignedCall, R)] = CAST1(callR); + + bo[index(con, lir::Move, R, R)] = CAST2(moveRR); + bo[index(con, lir::Move, C, R)] = CAST2(moveCR); + bo[index(con, lir::Move, C, M)] = CAST2(moveCM); + bo[index(con, lir::Move, M, R)] = CAST2(moveMR); + bo[index(con, lir::Move, R, M)] = CAST2(moveRM); + bo[index(con, lir::Move, A, R)] = CAST2(moveAR); + + bo[index(con, lir::MoveZ, R, R)] = CAST2(moveZRR); + bo[index(con, lir::MoveZ, M, R)] = CAST2(moveZMR); + bo[index(con, lir::MoveZ, C, R)] = CAST2(moveCR); + + bo[index(con, lir::Negate, R, R)] = CAST2(negateRR); + + bo[index(con, lir::FloatAbsolute, R, R)] = CAST2(floatAbsoluteRR); + bo[index(con, lir::FloatNegate, R, R)] = CAST2(floatNegateRR); + bo[index(con, lir::Float2Float, R, R)] = CAST2(float2FloatRR); + bo[index(con, lir::Float2Int, R, R)] = CAST2(float2IntRR); + bo[index(con, lir::Int2Float, R, R)] = CAST2(int2FloatRR); + bo[index(con, lir::FloatSquareRoot, R, R)] = CAST2(floatSqrtRR); + + to[index(con, lir::Add, R)] = CAST3(addR); + + to[index(con, lir::Subtract, R)] = CAST3(subR); + + to[index(con, lir::Multiply, R)] = CAST3(multiplyR); + + to[index(con, lir::FloatAdd, R)] = CAST3(floatAddR); + to[index(con, lir::FloatSubtract, R)] = CAST3(floatSubtractR); + to[index(con, lir::FloatMultiply, R)] = CAST3(floatMultiplyR); + to[index(con, lir::FloatDivide, R)] = CAST3(floatDivideR); + + to[index(con, lir::ShiftLeft, R)] = CAST3(shiftLeftR); + to[index(con, lir::ShiftLeft, C)] = CAST3(shiftLeftC); + + to[index(con, lir::ShiftRight, R)] = CAST3(shiftRightR); + to[index(con, lir::ShiftRight, C)] = CAST3(shiftRightC); + + to[index(con, lir::UnsignedShiftRight, R)] = CAST3(unsignedShiftRightR); + to[index(con, lir::UnsignedShiftRight, C)] = CAST3(unsignedShiftRightC); + + to[index(con, lir::And, R)] = CAST3(andR); + to[index(con, lir::And, C)] = CAST3(andC); + + to[index(con, lir::Or, R)] = CAST3(orR); + + to[index(con, lir::Xor, R)] = CAST3(xorR); + + bro[branchIndex(con, R, R)] = CAST_BRANCH(branchRR); + bro[branchIndex(con, C, R)] = CAST_BRANCH(branchCR); + bro[branchIndex(con, C, M)] = CAST_BRANCH(branchCM); + bro[branchIndex(con, R, M)] = CAST_BRANCH(branchRM); +} + +} // namespace arm +} // namespace codegen +} // namespace avian diff --git a/sgx-jvm/avian/src/codegen/target/arm/multimethod.h b/sgx-jvm/avian/src/codegen/target/arm/multimethod.h new file mode 100644 index 0000000000..2459b8bef6 --- /dev/null +++ b/sgx-jvm/avian/src/codegen/target/arm/multimethod.h @@ -0,0 +1,45 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#ifndef AVIAN_CODEGEN_ASSEMBLER_ARM_MULTIMETHOD_H +#define AVIAN_CODEGEN_ASSEMBLER_ARM_MULTIMETHOD_H + +#include +#include + +#define CAST1(x) reinterpret_cast(x) +#define CAST2(x) reinterpret_cast(x) +#define CAST3(x) reinterpret_cast(x) +#define CAST_BRANCH(x) reinterpret_cast(x) + +namespace avian { +namespace codegen { +namespace arm { + +unsigned index(ArchitectureContext*, + lir::BinaryOperation operation, + lir::Operand::Type operand1, + lir::Operand::Type operand2); + +unsigned index(ArchitectureContext* con UNUSED, + lir::TernaryOperation operation, + lir::Operand::Type operand1); + +unsigned branchIndex(ArchitectureContext* con UNUSED, + lir::Operand::Type operand1, + lir::Operand::Type operand2); + +void populateTables(ArchitectureContext* con); + +} // namespace arm +} // namespace codegen +} // namespace avian + +#endif // AVIAN_CODEGEN_ASSEMBLER_ARM_MULTIMETHOD_H diff --git a/sgx-jvm/avian/src/codegen/target/arm/operations.h b/sgx-jvm/avian/src/codegen/target/arm/operations.h new file mode 100644 index 0000000000..08603bcd73 --- /dev/null +++ b/sgx-jvm/avian/src/codegen/target/arm/operations.h @@ -0,0 +1,434 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#ifndef AVIAN_CODEGEN_ASSEMBLER_ARM_OPERATIONS_H +#define AVIAN_CODEGEN_ASSEMBLER_ARM_OPERATIONS_H + +#include "registers.h" + +namespace vm { +class System; +} + +namespace avian { +namespace codegen { +namespace arm { + +class Context; + +// shortcut functions + +inline Register newTemp(Context* con) +{ + return con->client->acquireTemporary(GPR_MASK); +} + +inline Register newTemp(Context* con, RegisterMask mask) +{ + return con->client->acquireTemporary(mask); +} + +inline void freeTemp(Context* con, Register r) +{ + con->client->releaseTemporary(r); +} + +inline int64_t getValue(lir::Constant* con) +{ + return con->value->value(); +} + +inline lir::RegisterPair makeTemp(Context* con) +{ + lir::RegisterPair tmp(newTemp(con)); + return tmp; +} + +inline lir::RegisterPair makeTemp64(Context* con) +{ + lir::RegisterPair tmp(newTemp(con), newTemp(con)); + return tmp; +} + +inline void freeTemp(Context* con, const lir::RegisterPair& tmp) +{ + if (tmp.low != NoRegister) + freeTemp(con, tmp.low); + if (tmp.high != NoRegister) + freeTemp(con, tmp.high); +} + +void shiftLeftR(Context* con, + unsigned size, + lir::RegisterPair* a, + lir::RegisterPair* b, + lir::RegisterPair* t); + +void moveRR(Context* con, + unsigned srcSize, + lir::RegisterPair* src, + unsigned dstSize, + lir::RegisterPair* dst); + +void shiftLeftC(Context* con, + unsigned size UNUSED, + lir::Constant* a, + lir::RegisterPair* b, + lir::RegisterPair* t); + +void shiftRightR(Context* con, + unsigned size, + lir::RegisterPair* a, + lir::RegisterPair* b, + lir::RegisterPair* t); + +void shiftRightC(Context* con, + unsigned size UNUSED, + lir::Constant* a, + lir::RegisterPair* b, + lir::RegisterPair* t); + +void unsignedShiftRightR(Context* con, + unsigned size, + lir::RegisterPair* a, + lir::RegisterPair* b, + lir::RegisterPair* t); + +void unsignedShiftRightC(Context* con, + unsigned size UNUSED, + lir::Constant* a, + lir::RegisterPair* b, + lir::RegisterPair* t); + +bool needJump(MyBlock* b); + +unsigned padding(MyBlock* b, unsigned offset); + +void resolve(MyBlock* b); + +void jumpR(Context* con, unsigned size UNUSED, lir::RegisterPair* target); + +void swapRR(Context* con, + unsigned aSize, + lir::RegisterPair* a, + unsigned bSize, + lir::RegisterPair* b); + +void moveRR(Context* con, + unsigned srcSize, + lir::RegisterPair* src, + unsigned dstSize, + lir::RegisterPair* dst); + +void moveZRR(Context* con, + unsigned srcSize, + lir::RegisterPair* src, + unsigned, + lir::RegisterPair* dst); + +void moveCR(Context* con, + unsigned size, + lir::Constant* src, + unsigned, + lir::RegisterPair* dst); + +void moveCR2(Context* con, + unsigned size, + lir::Constant* src, + lir::RegisterPair* dst, + Promise* callOffset); + +void moveCR(Context* con, + unsigned size, + lir::Constant* src, + unsigned, + lir::RegisterPair* dst); + +void addR(Context* con, + unsigned size, + lir::RegisterPair* a, + lir::RegisterPair* b, + lir::RegisterPair* t); + +void subR(Context* con, + unsigned size, + lir::RegisterPair* a, + lir::RegisterPair* b, + lir::RegisterPair* t); + +void addC(Context* con, + unsigned size, + lir::Constant* a, + lir::RegisterPair* b, + lir::RegisterPair* dst); + +void subC(Context* con, + unsigned size, + lir::Constant* a, + lir::RegisterPair* b, + lir::RegisterPair* dst); + +void multiplyR(Context* con, + unsigned size, + lir::RegisterPair* a, + lir::RegisterPair* b, + lir::RegisterPair* t); + +void floatAbsoluteRR(Context* con, + unsigned size, + lir::RegisterPair* a, + unsigned, + lir::RegisterPair* b); + +void floatNegateRR(Context* con, + unsigned size, + lir::RegisterPair* a, + unsigned, + lir::RegisterPair* b); + +void float2FloatRR(Context* con, + unsigned size, + lir::RegisterPair* a, + unsigned, + lir::RegisterPair* b); + +void float2IntRR(Context* con, + unsigned size, + lir::RegisterPair* a, + unsigned, + lir::RegisterPair* b); + +void int2FloatRR(Context* con, + unsigned, + lir::RegisterPair* a, + unsigned size, + lir::RegisterPair* b); + +void floatSqrtRR(Context* con, + unsigned size, + lir::RegisterPair* a, + unsigned, + lir::RegisterPair* b); + +void floatAddR(Context* con, + unsigned size, + lir::RegisterPair* a, + lir::RegisterPair* b, + lir::RegisterPair* t); + +void floatSubtractR(Context* con, + unsigned size, + lir::RegisterPair* a, + lir::RegisterPair* b, + lir::RegisterPair* t); + +void floatMultiplyR(Context* con, + unsigned size, + lir::RegisterPair* a, + lir::RegisterPair* b, + lir::RegisterPair* t); + +void floatDivideR(Context* con, + unsigned size, + lir::RegisterPair* a, + lir::RegisterPair* b, + lir::RegisterPair* t); + +int normalize(Context* con, + int offset, + int index, + unsigned scale, + bool* preserveIndex, + bool* release); + +void store(Context* con, + unsigned size, + lir::RegisterPair* src, + int base, + int offset, + int index, + unsigned scale, + bool preserveIndex); + +void moveRM(Context* con, + unsigned srcSize, + lir::RegisterPair* src, + unsigned dstSize UNUSED, + lir::Memory* dst); + +void load(Context* con, + unsigned srcSize, + int base, + int offset, + int index, + unsigned scale, + unsigned dstSize, + lir::RegisterPair* dst, + bool preserveIndex, + bool signExtend); + +void moveMR(Context* con, + unsigned srcSize, + lir::Memory* src, + unsigned dstSize, + lir::RegisterPair* dst); + +void moveZMR(Context* con, + unsigned srcSize, + lir::Memory* src, + unsigned dstSize, + lir::RegisterPair* dst); + +void andR(Context* con, + unsigned size, + lir::RegisterPair* a, + lir::RegisterPair* b, + lir::RegisterPair* dst); + +void andC(Context* con, + unsigned size, + lir::Constant* a, + lir::RegisterPair* b, + lir::RegisterPair* dst); + +void orR(Context* con, + unsigned size, + lir::RegisterPair* a, + lir::RegisterPair* b, + lir::RegisterPair* dst); + +void xorR(Context* con, + unsigned size, + lir::RegisterPair* a, + lir::RegisterPair* b, + lir::RegisterPair* dst); + +void moveAR2(Context* con, + unsigned srcSize, + lir::Address* src, + unsigned dstSize, + lir::RegisterPair* dst); + +void moveAR(Context* con, + unsigned srcSize, + lir::Address* src, + unsigned dstSize, + lir::RegisterPair* dst); + +void compareRR(Context* con, + unsigned aSize, + lir::RegisterPair* a, + unsigned bSize UNUSED, + lir::RegisterPair* b); + +void compareCR(Context* con, + unsigned aSize, + lir::Constant* a, + unsigned bSize, + lir::RegisterPair* b); + +void compareCM(Context* con, + unsigned aSize, + lir::Constant* a, + unsigned bSize, + lir::Memory* b); + +void compareRM(Context* con, + unsigned aSize, + lir::RegisterPair* a, + unsigned bSize, + lir::Memory* b); + +int32_t branch(Context* con, lir::TernaryOperation op); + +void conditional(Context* con, int32_t branch, lir::Constant* target); + +void branch(Context* con, lir::TernaryOperation op, lir::Constant* target); + +void branchLong(Context* con, + lir::TernaryOperation op, + lir::Operand* al, + lir::Operand* ah, + lir::Operand* bl, + lir::Operand* bh, + lir::Constant* target, + BinaryOperationType compareSigned, + BinaryOperationType compareUnsigned); + +void branchRR(Context* con, + lir::TernaryOperation op, + unsigned size, + lir::RegisterPair* a, + lir::RegisterPair* b, + lir::Constant* target); + +void branchCR(Context* con, + lir::TernaryOperation op, + unsigned size, + lir::Constant* a, + lir::RegisterPair* b, + lir::Constant* target); + +void branchRM(Context* con, + lir::TernaryOperation op, + unsigned size, + lir::RegisterPair* a, + lir::Memory* b, + lir::Constant* target); + +void branchCM(Context* con, + lir::TernaryOperation op, + unsigned size, + lir::Constant* a, + lir::Memory* b, + lir::Constant* target); + +ShiftMaskPromise* shiftMaskPromise(Context* con, + Promise* base, + unsigned shift, + int64_t mask); + +void moveCM(Context* con, + unsigned srcSize, + lir::Constant* src, + unsigned dstSize, + lir::Memory* dst); + +void negateRR(Context* con, + unsigned srcSize, + lir::RegisterPair* src, + unsigned dstSize UNUSED, + lir::RegisterPair* dst); + +void callR(Context* con, unsigned size UNUSED, lir::RegisterPair* target); + +void callC(Context* con, unsigned size UNUSED, lir::Constant* target); + +void longCallC(Context* con, unsigned size UNUSED, lir::Constant* target); + +void longJumpC(Context* con, unsigned size UNUSED, lir::Constant* target); + +void jumpC(Context* con, unsigned size UNUSED, lir::Constant* target); + +void return_(Context* con); + +void trap(Context* con); + +void loadBarrier(Context*); + +void storeStoreBarrier(Context*); + +void storeLoadBarrier(Context*); + +} // namespace arm +} // namespace codegen +} // namespace avian + +#endif // AVIAN_CODEGEN_ASSEMBLER_ARM_OPERATIONS_H diff --git a/sgx-jvm/avian/src/codegen/target/arm/operations32.cpp b/sgx-jvm/avian/src/codegen/target/arm/operations32.cpp new file mode 100644 index 0000000000..5572dcae87 --- /dev/null +++ b/sgx-jvm/avian/src/codegen/target/arm/operations32.cpp @@ -0,0 +1,1459 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#include "context.h" +#include "operations.h" +#include "encode.h" +#include "block.h" +#include "fixup.h" +#include "multimethod.h" + +#if TARGET_BYTES_PER_WORD == 4 + +namespace avian { +namespace codegen { +namespace arm { + +using namespace isa; +using namespace avian::util; + +inline bool isOfWidth(int64_t i, int size) +{ + return static_cast(i) >> size == 0; +} + +inline unsigned lo8(int64_t i) +{ + return (unsigned)(i & MASK_LO8); +} + +void andC(Context* con, + unsigned size, + lir::Constant* a, + lir::RegisterPair* b, + lir::RegisterPair* dst); + +void shiftLeftR(Context* con, + unsigned size, + lir::RegisterPair* a, + lir::RegisterPair* b, + lir::RegisterPair* t) +{ + if (size == 8) { + Register tmp1 = newTemp(con), tmp2 = newTemp(con), tmp3 = newTemp(con); + ResolvedPromise maskPromise(0x3F); + lir::Constant mask(&maskPromise); + lir::RegisterPair dst(tmp3); + andC(con, 4, &mask, a, &dst); + emit(con, lsl(tmp1, b->high, tmp3)); + emit(con, rsbi(tmp2, tmp3, 32)); + emit(con, orrsh(tmp1, tmp1, b->low, tmp2, LSR)); + emit(con, SETS(subi(t->high, tmp3, 32))); + emit(con, SETCOND(mov(t->high, tmp1), MI)); + emit(con, SETCOND(lsl(t->high, b->low, t->high), PL)); + emit(con, lsl(t->low, b->low, tmp3)); + freeTemp(con, tmp1); + freeTemp(con, tmp2); + freeTemp(con, tmp3); + } else { + Register tmp = newTemp(con); + ResolvedPromise maskPromise(0x1F); + lir::Constant mask(&maskPromise); + lir::RegisterPair dst(tmp); + andC(con, size, &mask, a, &dst); + emit(con, lsl(t->low, b->low, tmp)); + freeTemp(con, tmp); + } +} + +void moveRR(Context* con, + unsigned srcSize, + lir::RegisterPair* src, + unsigned dstSize, + lir::RegisterPair* dst); + +void shiftLeftC(Context* con, + unsigned size UNUSED, + lir::Constant* a, + lir::RegisterPair* b, + lir::RegisterPair* t) +{ + assertT(con, size == vm::TargetBytesPerWord); + if (getValue(a) & 0x1F) { + emit(con, lsli(t->low, b->low, getValue(a) & 0x1F)); + } else { + moveRR(con, size, b, size, t); + } +} + +void shiftRightR(Context* con, + unsigned size, + lir::RegisterPair* a, + lir::RegisterPair* b, + lir::RegisterPair* t) +{ + if (size == 8) { + Register tmp1 = newTemp(con), tmp2 = newTemp(con), tmp3 = newTemp(con); + ResolvedPromise maskPromise(0x3F); + lir::Constant mask(&maskPromise); + lir::RegisterPair dst(tmp3); + andC(con, 4, &mask, a, &dst); + emit(con, lsr(tmp1, b->low, tmp3)); + emit(con, rsbi(tmp2, tmp3, 32)); + emit(con, orrsh(tmp1, tmp1, b->high, tmp2, LSL)); + emit(con, SETS(subi(t->low, tmp3, 32))); + emit(con, SETCOND(mov(t->low, tmp1), MI)); + emit(con, SETCOND(asr(t->low, b->high, t->low), PL)); + emit(con, asr(t->high, b->high, tmp3)); + freeTemp(con, tmp1); + freeTemp(con, tmp2); + freeTemp(con, tmp3); + } else { + Register tmp = newTemp(con); + ResolvedPromise maskPromise(0x1F); + lir::Constant mask(&maskPromise); + lir::RegisterPair dst(tmp); + andC(con, size, &mask, a, &dst); + emit(con, asr(t->low, b->low, tmp)); + freeTemp(con, tmp); + } +} + +void shiftRightC(Context* con, + unsigned size UNUSED, + lir::Constant* a, + lir::RegisterPair* b, + lir::RegisterPair* t) +{ + assertT(con, size == vm::TargetBytesPerWord); + if (getValue(a) & 0x1F) { + emit(con, asri(t->low, b->low, getValue(a) & 0x1F)); + } else { + moveRR(con, size, b, size, t); + } +} + +void unsignedShiftRightR(Context* con, + unsigned size, + lir::RegisterPair* a, + lir::RegisterPair* b, + lir::RegisterPair* t) +{ + Register tmpShift = newTemp(con); + ResolvedPromise maskPromise(size == 8 ? 0x3F : 0x1F); + lir::Constant mask(&maskPromise); + lir::RegisterPair dst(tmpShift); + andC(con, 4, &mask, a, &dst); + emit(con, lsr(t->low, b->low, tmpShift)); + if (size == 8) { + Register tmpHi = newTemp(con), tmpLo = newTemp(con); + emit(con, SETS(rsbi(tmpHi, tmpShift, 32))); + emit(con, lsl(tmpLo, b->high, tmpHi)); + emit(con, orr(t->low, t->low, tmpLo)); + emit(con, addi(tmpHi, tmpShift, -32)); + emit(con, lsr(tmpLo, b->high, tmpHi)); + emit(con, orr(t->low, t->low, tmpLo)); + emit(con, lsr(t->high, b->high, tmpShift)); + freeTemp(con, tmpHi); + freeTemp(con, tmpLo); + } + freeTemp(con, tmpShift); +} + +void unsignedShiftRightC(Context* con, + unsigned size UNUSED, + lir::Constant* a, + lir::RegisterPair* b, + lir::RegisterPair* t) +{ + assertT(con, size == vm::TargetBytesPerWord); + if (getValue(a) & 0x1F) { + emit(con, lsri(t->low, b->low, getValue(a) & 0x1F)); + } else { + moveRR(con, size, b, size, t); + } +} + +void jumpR(Context* con, unsigned size UNUSED, lir::RegisterPair* target) +{ + assertT(con, size == vm::TargetBytesPerWord); + emit(con, bx(target->low)); +} + +void swapRR(Context* con, + unsigned aSize, + lir::RegisterPair* a, + unsigned bSize, + lir::RegisterPair* b) +{ + assertT(con, aSize == vm::TargetBytesPerWord); + assertT(con, bSize == vm::TargetBytesPerWord); + + lir::RegisterPair tmp(con->client->acquireTemporary(GPR_MASK)); + moveRR(con, aSize, a, bSize, &tmp); + moveRR(con, bSize, b, aSize, a); + moveRR(con, bSize, &tmp, bSize, b); + con->client->releaseTemporary(tmp.low); +} + +void moveRR(Context* con, + unsigned srcSize, + lir::RegisterPair* src, + unsigned dstSize, + lir::RegisterPair* dst) +{ + bool srcIsFpr = isFpr(src); + bool dstIsFpr = isFpr(dst); + if (srcIsFpr || dstIsFpr) { // FPR(s) involved + assertT(con, srcSize == dstSize); + const bool dprec = srcSize == 8; + if (srcIsFpr && dstIsFpr) { // FPR to FPR + if (dprec) + emit(con, fcpyd(fpr64(dst), fpr64(src))); // double + else + emit(con, fcpys(fpr32(dst), fpr32(src))); // single + } else if (srcIsFpr) { // FPR to GPR + if (dprec) + emit(con, fmrrd(dst->low, dst->high, fpr64(src))); + else + emit(con, fmrs(dst->low, fpr32(src))); + } else { // GPR to FPR + if (dprec) + emit(con, fmdrr(fpr64(dst->low), src->low, src->high)); + else + emit(con, fmsr(fpr32(dst), src->low)); + } + return; + } + + switch (srcSize) { + case 1: + emit(con, lsli(dst->low, src->low, 24)); + emit(con, asri(dst->low, dst->low, 24)); + break; + + case 2: + emit(con, lsli(dst->low, src->low, 16)); + emit(con, asri(dst->low, dst->low, 16)); + break; + + case 4: + case 8: + if (srcSize == 4 and dstSize == 8) { + moveRR(con, 4, src, 4, dst); + emit(con, asri(dst->high, src->low, 31)); + } else if (srcSize == 8 and dstSize == 8) { + lir::RegisterPair srcHigh(src->high); + lir::RegisterPair dstHigh(dst->high); + + if (src->high == dst->low) { + if (src->low == dst->high) { + swapRR(con, 4, src, 4, dst); + } else { + moveRR(con, 4, &srcHigh, 4, &dstHigh); + moveRR(con, 4, src, 4, dst); + } + } else { + moveRR(con, 4, src, 4, dst); + moveRR(con, 4, &srcHigh, 4, &dstHigh); + } + } else if (src->low != dst->low) { + emit(con, mov(dst->low, src->low)); + } + break; + + default: + abort(con); + } +} + +void moveZRR(Context* con, + unsigned srcSize, + lir::RegisterPair* src, + unsigned, + lir::RegisterPair* dst) +{ + switch (srcSize) { + case 2: + emit(con, lsli(dst->low, src->low, 16)); + emit(con, lsri(dst->low, dst->low, 16)); + break; + + default: + abort(con); + } +} + +void moveCR(Context* con, + unsigned size, + lir::Constant* src, + unsigned, + lir::RegisterPair* dst); + +void moveCR2(Context* con, + unsigned size, + lir::Constant* src, + lir::RegisterPair* dst, + Promise* callOffset) +{ + if (isFpr(dst)) { // floating-point + lir::RegisterPair tmp = size > 4 ? makeTemp64(con) : makeTemp(con); + moveCR(con, size, src, size, &tmp); + moveRR(con, size, &tmp, size, dst); + freeTemp(con, tmp); + } else if (size > 4) { + uint64_t value = (uint64_t)src->value->value(); + ResolvedPromise loBits(value & MASK_LO32); + lir::Constant srcLo(&loBits); + ResolvedPromise hiBits(value >> 32); + lir::Constant srcHi(&hiBits); + lir::RegisterPair dstHi(dst->high); + moveCR(con, 4, &srcLo, 4, dst); + moveCR(con, 4, &srcHi, 4, &dstHi); + } else if (callOffset == 0 and src->value->resolved() + and isOfWidth(getValue(src), 8)) { + emit(con, movi(dst->low, lo8(getValue(src)))); // fits in immediate + } else { + appendConstantPoolEntry(con, src->value, callOffset); + emit(con, ldri(dst->low, ProgramCounter, 0)); // load 32 bits + } +} + +void moveCR(Context* con, + unsigned size, + lir::Constant* src, + unsigned, + lir::RegisterPair* dst) +{ + moveCR2(con, size, src, dst, 0); +} + +void addR(Context* con, + unsigned size, + lir::RegisterPair* a, + lir::RegisterPair* b, + lir::RegisterPair* t) +{ + if (size == 8) { + emit(con, SETS(add(t->low, a->low, b->low))); + emit(con, adc(t->high, a->high, b->high)); + } else { + emit(con, add(t->low, a->low, b->low)); + } +} + +void subR(Context* con, + unsigned size, + lir::RegisterPair* a, + lir::RegisterPair* b, + lir::RegisterPair* t) +{ + if (size == 8) { + emit(con, SETS(rsb(t->low, a->low, b->low))); + emit(con, rsc(t->high, a->high, b->high)); + } else { + emit(con, rsb(t->low, a->low, b->low)); + } +} + +void addC(Context* con, + unsigned size, + lir::Constant* a, + lir::RegisterPair* b, + lir::RegisterPair* dst) +{ + assertT(con, size == vm::TargetBytesPerWord); + + int32_t v = a->value->value(); + if (v) { + if (v > 0 and v < 256) { + emit(con, addi(dst->low, b->low, v)); + } else if (v > 0 and v < 1024 and v % 4 == 0) { + emit(con, addi(dst->low, b->low, v >> 2, 15)); + } else { + // todo + abort(con); + } + } else { + moveRR(con, size, b, size, dst); + } +} + +void subC(Context* con, + unsigned size, + lir::Constant* a, + lir::RegisterPair* b, + lir::RegisterPair* dst) +{ + assertT(con, size == vm::TargetBytesPerWord); + + int32_t v = a->value->value(); + if (v) { + if (v > 0 and v < 256) { + emit(con, subi(dst->low, b->low, v)); + } else if (v > 0 and v < 1024 and v % 4 == 0) { + emit(con, subi(dst->low, b->low, v >> 2, 15)); + } else { + // todo + abort(con); + } + } else { + moveRR(con, size, b, size, dst); + } +} + +void multiplyR(Context* con, + unsigned size, + lir::RegisterPair* a, + lir::RegisterPair* b, + lir::RegisterPair* t) +{ + if (size == 8) { + bool useTemporaries = b->low == t->low; + Register tmpLow = useTemporaries ? con->client->acquireTemporary(GPR_MASK) + : t->low; + Register tmpHigh = useTemporaries ? con->client->acquireTemporary(GPR_MASK) + : t->high; + + emit(con, umull(tmpLow, tmpHigh, a->low, b->low)); + emit(con, mla(tmpHigh, a->low, b->high, tmpHigh)); + emit(con, mla(tmpHigh, a->high, b->low, tmpHigh)); + + if (useTemporaries) { + emit(con, mov(t->low, tmpLow)); + emit(con, mov(t->high, tmpHigh)); + con->client->releaseTemporary(tmpLow); + con->client->releaseTemporary(tmpHigh); + } + } else { + emit(con, mul(t->low, a->low, b->low)); + } +} + +void floatAbsoluteRR(Context* con, + unsigned size, + lir::RegisterPair* a, + unsigned, + lir::RegisterPair* b) +{ + if (size == 8) { + emit(con, fabsd(fpr64(b), fpr64(a))); + } else { + emit(con, fabss(fpr32(b), fpr32(a))); + } +} + +void floatNegateRR(Context* con, + unsigned size, + lir::RegisterPair* a, + unsigned, + lir::RegisterPair* b) +{ + if (size == 8) { + emit(con, fnegd(fpr64(b), fpr64(a))); + } else { + emit(con, fnegs(fpr32(b), fpr32(a))); + } +} + +void float2FloatRR(Context* con, + unsigned size, + lir::RegisterPair* a, + unsigned, + lir::RegisterPair* b) +{ + if (size == 8) { + emit(con, fcvtsd(fpr32(b), fpr64(a))); + } else { + emit(con, fcvtds(fpr64(b), fpr32(a))); + } +} + +void float2IntRR(Context* con, + unsigned size, + lir::RegisterPair* a, + unsigned, + lir::RegisterPair* b) +{ + Register tmp = newTemp(con, FPR_MASK); + int ftmp = fpr32(tmp); + if (size == 8) { // double to int + emit(con, ftosizd(ftmp, fpr64(a))); + } else { // float to int + emit(con, ftosizs(ftmp, fpr32(a))); + } // else thunked + emit(con, fmrs(b->low, ftmp)); + freeTemp(con, tmp); +} + +void int2FloatRR(Context* con, + unsigned, + lir::RegisterPair* a, + unsigned size, + lir::RegisterPair* b) +{ + emit(con, fmsr(fpr32(b), a->low)); + if (size == 8) { // int to double + emit(con, fsitod(fpr64(b), fpr32(b))); + } else { // int to float + emit(con, fsitos(fpr32(b), fpr32(b))); + } // else thunked +} + +void floatSqrtRR(Context* con, + unsigned size, + lir::RegisterPair* a, + unsigned, + lir::RegisterPair* b) +{ + if (size == 8) { + emit(con, fsqrtd(fpr64(b), fpr64(a))); + } else { + emit(con, fsqrts(fpr32(b), fpr32(a))); + } +} + +void floatAddR(Context* con, + unsigned size, + lir::RegisterPair* a, + lir::RegisterPair* b, + lir::RegisterPair* t) +{ + if (size == 8) { + emit(con, faddd(fpr64(t), fpr64(a), fpr64(b))); + } else { + emit(con, fadds(fpr32(t), fpr32(a), fpr32(b))); + } +} + +void floatSubtractR(Context* con, + unsigned size, + lir::RegisterPair* a, + lir::RegisterPair* b, + lir::RegisterPair* t) +{ + if (size == 8) { + emit(con, fsubd(fpr64(t), fpr64(b), fpr64(a))); + } else { + emit(con, fsubs(fpr32(t), fpr32(b), fpr32(a))); + } +} + +void floatMultiplyR(Context* con, + unsigned size, + lir::RegisterPair* a, + lir::RegisterPair* b, + lir::RegisterPair* t) +{ + if (size == 8) { + emit(con, fmuld(fpr64(t), fpr64(a), fpr64(b))); + } else { + emit(con, fmuls(fpr32(t), fpr32(a), fpr32(b))); + } +} + +void floatDivideR(Context* con, + unsigned size, + lir::RegisterPair* a, + lir::RegisterPair* b, + lir::RegisterPair* t) +{ + if (size == 8) { + emit(con, fdivd(fpr64(t), fpr64(b), fpr64(a))); + } else { + emit(con, fdivs(fpr32(t), fpr32(b), fpr32(a))); + } +} + +Register normalize(Context* con, + int offset, + Register index, + unsigned scale, + bool* preserveIndex, + bool* release) +{ + if (offset != 0 or scale != 1) { + lir::RegisterPair normalizedIndex( + *preserveIndex ? con->client->acquireTemporary(GPR_MASK) : index); + + if (*preserveIndex) { + *release = true; + *preserveIndex = false; + } else { + *release = false; + } + + Register scaled; + + if (scale != 1) { + lir::RegisterPair unscaledIndex(index); + + ResolvedPromise scalePromise(log(scale)); + lir::Constant scaleConstant(&scalePromise); + + shiftLeftC(con, + vm::TargetBytesPerWord, + &scaleConstant, + &unscaledIndex, + &normalizedIndex); + + scaled = normalizedIndex.low; + } else { + scaled = index; + } + + if (offset != 0) { + lir::RegisterPair untranslatedIndex(scaled); + + ResolvedPromise offsetPromise(offset); + lir::Constant offsetConstant(&offsetPromise); + + lir::RegisterPair tmp(con->client->acquireTemporary(GPR_MASK)); + moveCR(con, + vm::TargetBytesPerWord, + &offsetConstant, + vm::TargetBytesPerWord, + &tmp); + addR(con, + vm::TargetBytesPerWord, + &tmp, + &untranslatedIndex, + &normalizedIndex); + con->client->releaseTemporary(tmp.low); + } + + return normalizedIndex.low; + } else { + *release = false; + return index; + } +} + +void store(Context* con, + unsigned size, + lir::RegisterPair* src, + Register base, + int offset, + Register index, + unsigned scale, + bool preserveIndex) +{ + if (index != NoRegister) { + bool release; + Register normalized + = normalize(con, offset, index, scale, &preserveIndex, &release); + + if (!isFpr(src)) { // GPR store + switch (size) { + case 1: + emit(con, strb(src->low, base, normalized)); + break; + + case 2: + emit(con, strh(src->low, base, normalized)); + break; + + case 4: + emit(con, str(src->low, base, normalized)); + break; + + case 8: { // split into 2 32-bit stores + lir::RegisterPair srcHigh(src->high); + store(con, 4, &srcHigh, base, 0, normalized, 1, preserveIndex); + store(con, 4, src, base, 4, normalized, 1, preserveIndex); + } break; + + default: + abort(con); + } + } else { // FPR store + lir::RegisterPair base_(base), normalized_(normalized), + absAddr = makeTemp(con); + // FPR stores have only bases, so we must add the index + addR(con, vm::TargetBytesPerWord, &base_, &normalized_, &absAddr); + // double-precision + if (size == 8) + emit(con, fstd(fpr64(src), absAddr.low)); + // single-precision + else + emit(con, fsts(fpr32(src), absAddr.low)); + freeTemp(con, absAddr); + } + + if (release) + con->client->releaseTemporary(normalized); + } else if (size == 8 or abs(offset) == (abs(offset) & 0xFF) + or (size != 2 and abs(offset) == (abs(offset) & 0xFFF))) { + if (!isFpr(src)) { // GPR store + switch (size) { + case 1: + emit(con, strbi(src->low, base, offset)); + break; + + case 2: + emit(con, strhi(src->low, base, offset)); + break; + + case 4: + emit(con, stri(src->low, base, offset)); + break; + + case 8: { // split into 2 32-bit stores + lir::RegisterPair srcHigh(src->high); + store(con, 4, &srcHigh, base, offset, NoRegister, 1, false); + store(con, 4, src, base, offset + 4, NoRegister, 1, false); + } break; + + default: + abort(con); + } + } else { // FPR store + // double-precision + if (size == 8) + emit(con, fstd(fpr64(src), base, offset)); + // single-precision + else + emit(con, fsts(fpr32(src), base, offset)); + } + } else { + lir::RegisterPair tmp(con->client->acquireTemporary(GPR_MASK)); + ResolvedPromise offsetPromise(offset); + lir::Constant offsetConstant(&offsetPromise); + moveCR(con, + vm::TargetBytesPerWord, + &offsetConstant, + vm::TargetBytesPerWord, + &tmp); + + store(con, size, src, base, 0, tmp.low, 1, false); + + con->client->releaseTemporary(tmp.low); + } +} + +void moveRM(Context* con, + unsigned srcSize, + lir::RegisterPair* src, + unsigned dstSize UNUSED, + lir::Memory* dst) +{ + assertT(con, srcSize == dstSize); + + store( + con, srcSize, src, dst->base, dst->offset, dst->index, dst->scale, true); +} + +void load(Context* con, + unsigned srcSize, + Register base, + int offset, + Register index, + unsigned scale, + unsigned dstSize, + lir::RegisterPair* dst, + bool preserveIndex, + bool signExtend) +{ + if (index != NoRegister) { + bool release; + Register normalized + = normalize(con, offset, index, scale, &preserveIndex, &release); + + if (!isFpr(dst)) { // GPR load + switch (srcSize) { + case 1: + if (signExtend) { + emit(con, ldrsb(dst->low, base, normalized)); + } else { + emit(con, ldrb(dst->low, base, normalized)); + } + break; + + case 2: + if (signExtend) { + emit(con, ldrsh(dst->low, base, normalized)); + } else { + emit(con, ldrh(dst->low, base, normalized)); + } + break; + + case 4: + case 8: { + if (srcSize == 4 and dstSize == 8) { + load(con, 4, base, 0, normalized, 1, 4, dst, preserveIndex, false); + moveRR(con, 4, dst, 8, dst); + } else if (srcSize == 8 and dstSize == 8) { + lir::RegisterPair dstHigh(dst->high); + load(con, + 4, + base, + 0, + normalized, + 1, + 4, + &dstHigh, + preserveIndex, + false); + load(con, 4, base, 4, normalized, 1, 4, dst, preserveIndex, false); + } else { + emit(con, ldr(dst->low, base, normalized)); + } + } break; + + default: + abort(con); + } + } else { // FPR load + lir::RegisterPair base_(base), normalized_(normalized), + absAddr = makeTemp(con); + // VFP loads only have bases, so we must add the index + addR(con, vm::TargetBytesPerWord, &base_, &normalized_, &absAddr); + // double-precision + if (srcSize == 8) + emit(con, fldd(fpr64(dst), absAddr.low)); + // single-precision + else + emit(con, flds(fpr32(dst), absAddr.low)); + freeTemp(con, absAddr); + } + + if (release) + con->client->releaseTemporary(normalized); + } else if ((srcSize == 8 and dstSize == 8) + or abs(offset) == (abs(offset) & 0xFF) + or (srcSize != 2 and (srcSize != 1 or not signExtend) + and abs(offset) == (abs(offset) & 0xFFF))) { + if (!isFpr(dst)) { // GPR load + switch (srcSize) { + case 1: + if (signExtend) { + emit(con, ldrsbi(dst->low, base, offset)); + } else { + emit(con, ldrbi(dst->low, base, offset)); + } + break; + + case 2: + if (signExtend) { + emit(con, ldrshi(dst->low, base, offset)); + } else { + emit(con, ldrhi(dst->low, base, offset)); + } + break; + + case 4: + emit(con, ldri(dst->low, base, offset)); + break; + + case 8: { + if (dstSize == 8) { + lir::RegisterPair dstHigh(dst->high); + load(con, 4, base, offset, NoRegister, 1, 4, &dstHigh, false, false); + load(con, 4, base, offset + 4, NoRegister, 1, 4, dst, false, false); + } else { + emit(con, ldri(dst->low, base, offset)); + } + } break; + + default: + abort(con); + } + } else { // FPR load + // double-precision + if (srcSize == 8) + emit(con, fldd(fpr64(dst), base, offset)); + // single-precision + else + emit(con, flds(fpr32(dst), base, offset)); + } + } else { + lir::RegisterPair tmp(con->client->acquireTemporary(GPR_MASK)); + ResolvedPromise offsetPromise(offset); + lir::Constant offsetConstant(&offsetPromise); + moveCR(con, + vm::TargetBytesPerWord, + &offsetConstant, + vm::TargetBytesPerWord, + &tmp); + + load(con, srcSize, base, 0, tmp.low, 1, dstSize, dst, false, signExtend); + + con->client->releaseTemporary(tmp.low); + } +} + +void moveMR(Context* con, + unsigned srcSize, + lir::Memory* src, + unsigned dstSize, + lir::RegisterPair* dst) +{ + load(con, + srcSize, + src->base, + src->offset, + src->index, + src->scale, + dstSize, + dst, + true, + true); +} + +void moveZMR(Context* con, + unsigned srcSize, + lir::Memory* src, + unsigned dstSize, + lir::RegisterPair* dst) +{ + load(con, + srcSize, + src->base, + src->offset, + src->index, + src->scale, + dstSize, + dst, + true, + false); +} + +void andR(Context* con, + unsigned size, + lir::RegisterPair* a, + lir::RegisterPair* b, + lir::RegisterPair* dst) +{ + if (size == 8) + emit(con, and_(dst->high, a->high, b->high)); + emit(con, and_(dst->low, a->low, b->low)); +} + +void andC(Context* con, + unsigned size, + lir::Constant* a, + lir::RegisterPair* b, + lir::RegisterPair* dst) +{ + int64_t v = a->value->value(); + + if (size == 8) { + ResolvedPromise high((v >> 32) & 0xFFFFFFFF); + lir::Constant ah(&high); + + ResolvedPromise low(v & 0xFFFFFFFF); + lir::Constant al(&low); + + lir::RegisterPair bh(b->high); + lir::RegisterPair dh(dst->high); + + andC(con, 4, &al, b, dst); + andC(con, 4, &ah, &bh, &dh); + } else { + uint32_t v32 = static_cast(v); + if (v32 != 0xFFFFFFFF) { + if ((v32 & 0xFFFFFF00) == 0xFFFFFF00) { + emit(con, bici(dst->low, b->low, (~(v32 & 0xFF)) & 0xFF)); + } else if ((v32 & 0xFFFFFF00) == 0) { + emit(con, andi(dst->low, b->low, v32 & 0xFF)); + } else { + // todo: there are other cases we can handle in one + // instruction + + bool useTemporary = b->low == dst->low; + lir::RegisterPair tmp(dst->low); + if (useTemporary) { + tmp.low = con->client->acquireTemporary(GPR_MASK); + } + + moveCR(con, 4, a, 4, &tmp); + andR(con, 4, b, &tmp, dst); + + if (useTemporary) { + con->client->releaseTemporary(tmp.low); + } + } + } else { + moveRR(con, size, b, size, dst); + } + } +} + +void orR(Context* con, + unsigned size, + lir::RegisterPair* a, + lir::RegisterPair* b, + lir::RegisterPair* dst) +{ + if (size == 8) + emit(con, orr(dst->high, a->high, b->high)); + emit(con, orr(dst->low, a->low, b->low)); +} + +void xorR(Context* con, + unsigned size, + lir::RegisterPair* a, + lir::RegisterPair* b, + lir::RegisterPair* dst) +{ + if (size == 8) + emit(con, eor(dst->high, a->high, b->high)); + emit(con, eor(dst->low, a->low, b->low)); +} + +void moveAR2(Context* con, + unsigned srcSize, + lir::Address* src, + unsigned dstSize, + lir::RegisterPair* dst) +{ + assertT(con, srcSize == 4 and dstSize == 4); + + lir::Constant constant(src->address); + moveCR(con, srcSize, &constant, dstSize, dst); + + lir::Memory memory(dst->low, 0, NoRegister, 0); + moveMR(con, dstSize, &memory, dstSize, dst); +} + +void moveAR(Context* con, + unsigned srcSize, + lir::Address* src, + unsigned dstSize, + lir::RegisterPair* dst) +{ + moveAR2(con, srcSize, src, dstSize, dst); +} + +void compareRR(Context* con, + unsigned aSize, + lir::RegisterPair* a, + unsigned bSize UNUSED, + lir::RegisterPair* b) +{ + assertT(con, !(isFpr(a) ^ isFpr(b))); // regs must be of the same type + + if (!isFpr(a)) { // GPR compare + assertT(con, aSize == 4 && bSize == 4); + /**/ // assertT(con, b->low != a->low); + emit(con, cmp(b->low, a->low)); + } else { // FPR compare + assertT(con, aSize == bSize); + if (aSize == 8) + emit(con, fcmpd(fpr64(b), fpr64(a))); // double + else + emit(con, fcmps(fpr32(b), fpr32(a))); // single + emit(con, fmstat()); + } +} + +void compareCR(Context* con, + unsigned aSize, + lir::Constant* a, + unsigned bSize, + lir::RegisterPair* b) +{ + assertT(con, aSize == 4 and bSize == 4); + + if (!isFpr(b) && a->value->resolved() && isOfWidth(a->value->value(), 8)) { + emit(con, cmpi(b->low, a->value->value())); + } else { + lir::RegisterPair tmp(con->client->acquireTemporary(GPR_MASK)); + moveCR(con, aSize, a, bSize, &tmp); + compareRR(con, bSize, &tmp, bSize, b); + con->client->releaseTemporary(tmp.low); + } +} + +void compareCM(Context* con, + unsigned aSize, + lir::Constant* a, + unsigned bSize, + lir::Memory* b) +{ + assertT(con, aSize == 4 and bSize == 4); + + lir::RegisterPair tmp(con->client->acquireTemporary(GPR_MASK)); + moveMR(con, bSize, b, bSize, &tmp); + compareCR(con, aSize, a, bSize, &tmp); + con->client->releaseTemporary(tmp.low); +} + +void compareRM(Context* con, + unsigned aSize, + lir::RegisterPair* a, + unsigned bSize, + lir::Memory* b) +{ + assertT(con, aSize == 4 and bSize == 4); + + lir::RegisterPair tmp(con->client->acquireTemporary(GPR_MASK)); + moveMR(con, bSize, b, bSize, &tmp); + compareRR(con, aSize, a, bSize, &tmp); + con->client->releaseTemporary(tmp.low); +} + +int32_t branch(Context* con, lir::TernaryOperation op) +{ + switch (op) { + case lir::JumpIfEqual: + case lir::JumpIfFloatEqual: + return beq(0); + + case lir::JumpIfNotEqual: + case lir::JumpIfFloatNotEqual: + return bne(0); + + case lir::JumpIfLess: + case lir::JumpIfFloatLess: + case lir::JumpIfFloatLessOrUnordered: + return blt(0); + + case lir::JumpIfGreater: + case lir::JumpIfFloatGreater: + return bgt(0); + + case lir::JumpIfLessOrEqual: + case lir::JumpIfFloatLessOrEqual: + case lir::JumpIfFloatLessOrEqualOrUnordered: + return ble(0); + + case lir::JumpIfGreaterOrEqual: + case lir::JumpIfFloatGreaterOrEqual: + return bge(0); + + case lir::JumpIfFloatGreaterOrUnordered: + return bhi(0); + + case lir::JumpIfFloatGreaterOrEqualOrUnordered: + return bpl(0); + + default: + abort(con); + } +} + +void conditional(Context* con, int32_t branch, lir::Constant* target) +{ + appendOffsetTask(con, target->value, offsetPromise(con)); + emit(con, branch); +} + +void branch(Context* con, lir::TernaryOperation op, lir::Constant* target) +{ + conditional(con, branch(con, op), target); +} + +void branchLong(Context* con, + lir::TernaryOperation op, + lir::Operand* al, + lir::Operand* ah, + lir::Operand* bl, + lir::Operand* bh, + lir::Constant* target, + BinaryOperationType compareSigned, + BinaryOperationType compareUnsigned) +{ + compareSigned(con, 4, ah, 4, bh); + + unsigned next = 0; + + switch (op) { + case lir::JumpIfEqual: + case lir::JumpIfFloatEqual: + next = con->code.length(); + emit(con, bne(0)); + + compareSigned(con, 4, al, 4, bl); + conditional(con, beq(0), target); + break; + + case lir::JumpIfNotEqual: + case lir::JumpIfFloatNotEqual: + conditional(con, bne(0), target); + + compareSigned(con, 4, al, 4, bl); + conditional(con, bne(0), target); + break; + + case lir::JumpIfLess: + case lir::JumpIfFloatLess: + conditional(con, blt(0), target); + + next = con->code.length(); + emit(con, bgt(0)); + + compareUnsigned(con, 4, al, 4, bl); + conditional(con, blo(0), target); + break; + + case lir::JumpIfGreater: + case lir::JumpIfFloatGreater: + conditional(con, bgt(0), target); + + next = con->code.length(); + emit(con, blt(0)); + + compareUnsigned(con, 4, al, 4, bl); + conditional(con, bhi(0), target); + break; + + case lir::JumpIfLessOrEqual: + case lir::JumpIfFloatLessOrEqual: + conditional(con, blt(0), target); + + next = con->code.length(); + emit(con, bgt(0)); + + compareUnsigned(con, 4, al, 4, bl); + conditional(con, bls(0), target); + break; + + case lir::JumpIfGreaterOrEqual: + case lir::JumpIfFloatGreaterOrEqual: + conditional(con, bgt(0), target); + + next = con->code.length(); + emit(con, blt(0)); + + compareUnsigned(con, 4, al, 4, bl); + conditional(con, bhs(0), target); + break; + + default: + abort(con); + } + + if (next) { + updateOffset(con->s, + con->code.data.begin() + next, + reinterpret_cast(con->code.data.begin() + + con->code.length())); + } +} + +void branchRR(Context* con, + lir::TernaryOperation op, + unsigned size, + lir::RegisterPair* a, + lir::RegisterPair* b, + lir::Constant* target) +{ + if (!isFpr(a) && size > vm::TargetBytesPerWord) { + lir::RegisterPair ah(a->high); + lir::RegisterPair bh(b->high); + + branchLong( + con, op, a, &ah, b, &bh, target, CAST2(compareRR), CAST2(compareRR)); + } else { + compareRR(con, size, a, size, b); + branch(con, op, target); + } +} + +void branchCR(Context* con, + lir::TernaryOperation op, + unsigned size, + lir::Constant* a, + lir::RegisterPair* b, + lir::Constant* target) +{ + assertT(con, !isFloatBranch(op)); + + if (size > vm::TargetBytesPerWord) { + int64_t v = a->value->value(); + + ResolvedPromise low(v & ~static_cast(0)); + lir::Constant al(&low); + + ResolvedPromise high((v >> 32) & ~static_cast(0)); + lir::Constant ah(&high); + + lir::RegisterPair bh(b->high); + + branchLong( + con, op, &al, &ah, b, &bh, target, CAST2(compareCR), CAST2(compareCR)); + } else { + compareCR(con, size, a, size, b); + branch(con, op, target); + } +} + +void branchRM(Context* con, + lir::TernaryOperation op, + unsigned size, + lir::RegisterPair* a, + lir::Memory* b, + lir::Constant* target) +{ + assertT(con, !isFloatBranch(op)); + assertT(con, size <= vm::TargetBytesPerWord); + + compareRM(con, size, a, size, b); + branch(con, op, target); +} + +void branchCM(Context* con, + lir::TernaryOperation op, + unsigned size, + lir::Constant* a, + lir::Memory* b, + lir::Constant* target) +{ + assertT(con, !isFloatBranch(op)); + assertT(con, size <= vm::TargetBytesPerWord); + + compareCM(con, size, a, size, b); + branch(con, op, target); +} + +ShiftMaskPromise* shiftMaskPromise(Context* con, + Promise* base, + unsigned shift, + int64_t mask) +{ + return new (con->zone) ShiftMaskPromise(base, shift, mask); +} + +void moveCM(Context* con, + unsigned srcSize, + lir::Constant* src, + unsigned dstSize, + lir::Memory* dst) +{ + switch (dstSize) { + case 8: { + lir::Constant srcHigh(shiftMaskPromise(con, src->value, 32, 0xFFFFFFFF)); + lir::Constant srcLow(shiftMaskPromise(con, src->value, 0, 0xFFFFFFFF)); + + lir::Memory dstLow(dst->base, dst->offset + 4, dst->index, dst->scale); + + moveCM(con, 4, &srcLow, 4, &dstLow); + moveCM(con, 4, &srcHigh, 4, dst); + } break; + + default: + lir::RegisterPair tmp(con->client->acquireTemporary(GPR_MASK)); + moveCR(con, srcSize, src, dstSize, &tmp); + moveRM(con, dstSize, &tmp, dstSize, dst); + con->client->releaseTemporary(tmp.low); + } +} + +void negateRR(Context* con, + unsigned srcSize, + lir::RegisterPair* src, + unsigned dstSize UNUSED, + lir::RegisterPair* dst) +{ + assertT(con, srcSize == dstSize); + + emit(con, mvn(dst->low, src->low)); + emit(con, SETS(addi(dst->low, dst->low, 1))); + if (srcSize == 8) { + emit(con, mvn(dst->high, src->high)); + emit(con, adci(dst->high, dst->high, 0)); + } +} + +void callR(Context* con, unsigned size UNUSED, lir::RegisterPair* target) +{ + assertT(con, size == vm::TargetBytesPerWord); + emit(con, blx(target->low)); +} + +void callC(Context* con, unsigned size UNUSED, lir::Constant* target) +{ + assertT(con, size == vm::TargetBytesPerWord); + + appendOffsetTask(con, target->value, offsetPromise(con)); + emit(con, bl(0)); +} + +void longCallC(Context* con, unsigned size UNUSED, lir::Constant* target) +{ + assertT(con, size == vm::TargetBytesPerWord); + + lir::RegisterPair tmp(Register(4)); + moveCR2(con, vm::TargetBytesPerWord, target, &tmp, offsetPromise(con)); + callR(con, vm::TargetBytesPerWord, &tmp); +} + +void alignedLongCallC(Context* con, unsigned size, lir::Constant* target) +{ + longCallC(con, size, target); +} + +void longJumpC(Context* con, unsigned size UNUSED, lir::Constant* target) +{ + assertT(con, size == vm::TargetBytesPerWord); + + lir::RegisterPair tmp( + Register(4)); // a non-arg reg that we don't mind clobbering + moveCR2(con, vm::TargetBytesPerWord, target, &tmp, offsetPromise(con)); + jumpR(con, vm::TargetBytesPerWord, &tmp); +} + +void alignedLongJumpC(Context* con, unsigned size, lir::Constant* target) +{ + longJumpC(con, size, target); +} + +void jumpC(Context* con, unsigned size UNUSED, lir::Constant* target) +{ + assertT(con, size == vm::TargetBytesPerWord); + + appendOffsetTask(con, target->value, offsetPromise(con)); + emit(con, b(0)); +} + +void return_(Context* con) +{ + emit(con, bx(LinkRegister)); +} + +void trap(Context* con) +{ + emit(con, bkpt(0)); +} + +// todo: determine the minimal operation types and domains needed to +// implement the following barriers (see +// http://community.arm.com/groups/processors/blog/2011/10/19/memory-access-ordering-part-3--memory-access-ordering-in-the-arm-architecture). +// For now, we just use DMB SY as a conservative but not necessarily +// performant choice. + +void memoryBarrier(Context* con UNUSED) +{ +#ifndef AVIAN_ASSUME_ARMV6 + emit(con, dmb()); +#endif +} + +void loadBarrier(Context* con) +{ + memoryBarrier(con); +} + +void storeStoreBarrier(Context* con) +{ + memoryBarrier(con); +} + +void storeLoadBarrier(Context* con) +{ + memoryBarrier(con); +} + +} // namespace arm +} // namespace codegen +} // namespace avian + +#endif // TARGET_BYTES_PER_WORD == 4 diff --git a/sgx-jvm/avian/src/codegen/target/arm/operations64.cpp b/sgx-jvm/avian/src/codegen/target/arm/operations64.cpp new file mode 100644 index 0000000000..9bd905c472 --- /dev/null +++ b/sgx-jvm/avian/src/codegen/target/arm/operations64.cpp @@ -0,0 +1,1630 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#include "context.h" +#include "operations.h" +#include "block.h" +#include "fixup.h" +#include "multimethod.h" + +#if TARGET_BYTES_PER_WORD == 8 + +namespace { + +using namespace avian::codegen; +using namespace avian::codegen::arm; + +Register fpr(Register reg) +{ + return Register(reg.index() - N_GPRS); +} + +Register fpr(lir::RegisterPair* reg) +{ + return fpr(reg->low); +} + +void append(Context* c, uint32_t instruction) +{ + c->code.append4(instruction); +} + +uint32_t lslv(Register Rd, Register Rn, Register Rm, unsigned size) +{ + return (size == 8 ? 0x9ac02000 : 0x1ac02000) | (Rm.index() << 16) + | (Rn.index() << 5) | Rd.index(); +} + +uint32_t ubfm(Register Rd, Register Rn, int r, int s, unsigned size) +{ + return (size == 8 ? 0xd3400000 : 0x53000000) | (r << 16) | (s << 10) + | (Rn.index() << 5) | Rd.index(); +} + +uint32_t sbfm(Register Rd, Register Rn, int r, int s, unsigned size) +{ + return (size == 8 ? 0x93400000 : 0x13000000) | (r << 16) | (s << 10) + | (Rn.index() << 5) | Rd.index(); +} + +uint32_t lsli(Register Rd, Register Rn, int shift, unsigned size) +{ + if (size == 4) { + return ubfm(Rd, Rn, (32 - shift) & 0x1f, 31 - shift, size); + } else { + return ubfm(Rd, Rn, (64 - shift) & 0x3f, 63 - shift, size); + } +} + +uint32_t asrv(Register Rd, Register Rn, Register Rm, unsigned size) +{ + return (size == 8 ? 0x9ac02800 : 0x1ac02800) | (Rm.index() << 16) + | (Rn.index() << 5) | Rd.index(); +} + +uint32_t lsrv(Register Rd, Register Rn, Register Rm, unsigned size) +{ + return (size == 8 ? 0x9ac02400 : 0x1ac02400) | (Rm.index() << 16) + | (Rn.index() << 5) | Rd.index(); +} + +uint32_t lsri(Register Rd, Register Rn, int shift, unsigned size) +{ + return ubfm(Rd, Rn, shift, size == 8 ? 63 : 31, size); +} + +uint32_t asri(Register Rd, Register Rn, int shift, unsigned size) +{ + return sbfm(Rd, Rn, shift, size == 8 ? 63 : 31, size); +} + +uint32_t sxtb(Register Rd, Register Rn) +{ + return sbfm(Rd, Rn, 0, 7, 8); +} + +uint32_t sxth(Register Rd, Register Rn) +{ + return sbfm(Rd, Rn, 0, 15, 8); +} + +uint32_t uxth(Register Rd, Register Rn) +{ + return ubfm(Rd, Rn, 0, 15, 4); +} + +uint32_t sxtw(Register Rd, Register Rn) +{ + return sbfm(Rd, Rn, 0, 31, 8); +} + +uint32_t br(Register Rn) +{ + return 0xd61f0000 | (Rn.index() << 5); +} + +uint32_t fmovFdFn(Register Fd, Register Fn, unsigned size) +{ + return (size == 8 ? 0x1e604000 : 0x1e204000) | (Fn.index() << 5) | Fd.index(); +} + +uint32_t fmovRdFn(Register Rd, Register Fn, unsigned size) +{ + return (size == 8 ? 0x9e660000 : 0x1e260000) | (Fn.index() << 5) | Rd.index(); +} + +uint32_t fmovFdRn(Register Fd, Register Rn, unsigned size) +{ + return (size == 8 ? 0x9e670000 : 0x1e270000) | (Rn.index() << 5) | Fd.index(); +} + +uint32_t orr(Register Rd, Register Rn, Register Rm, unsigned size) +{ + return (size == 8 ? 0xaa000000 : 0x2a000000) | (Rm.index() << 16) + | (Rn.index() << 5) | Rd.index(); +} + +uint32_t addi(Register Rd, Register Rn, int value, int shift, unsigned size) +{ + return (size == 8 ? 0x91000000 : 0x11000000) | (shift ? 0x400000 : 0) + | (value << 10) | (Rn.index() << 5) | Rd.index(); +} + +uint32_t mov(Register Rd, Register Rn, unsigned size) +{ + return Rn.index() == 31 or Rd.index() == 31 ? addi(Rd, Rn, 0, 0, size) + : orr(Rd, Register(31), Rn, size); +} + +uint32_t movz(Register Rd, int value, unsigned shift, unsigned size) +{ + return (size == 8 ? 0xd2800000 : 0x52800000) | ((shift >> 4) << 21) + | (value << 5) | Rd.index(); +} + +uint32_t movn(Register Rd, int value, unsigned shift, unsigned size) +{ + return (size == 8 ? 0x92800000 : 0x12800000) | ((shift >> 4) << 21) + | (value << 5) | Rd.index(); +} + +uint32_t movk(Register Rd, int value, unsigned shift, unsigned size) +{ + return (size == 8 ? 0xf2800000 : 0x72800000) | ((shift >> 4) << 21) + | (value << 5) | Rd.index(); +} + +uint32_t ldrPCRel(Register Rd, int offset, unsigned size) +{ + return (size == 8 ? 0x58000000 : 0x18000000) | ((offset >> 2) << 5) + | Rd.index(); +} + +uint32_t add(Register Rd, Register Rn, Register Rm, unsigned size) +{ + return (size == 8 ? 0x8b000000 : 0x0b000000) | (Rm.index() << 16) + | (Rn.index() << 5) | Rd.index(); +} + +uint32_t sub(Register Rd, Register Rn, Register Rm, unsigned size) +{ + return (size == 8 ? 0xcb000000 : 0x4b000000) | (Rm.index() << 16) + | (Rn.index() << 5) | Rd.index(); +} + +uint32_t and_(Register Rd, Register Rn, Register Rm, unsigned size) +{ + return (size == 8 ? 0x8a000000 : 0x0a000000) | (Rm.index() << 16) + | (Rn.index() << 5) | Rd.index(); +} + +uint32_t eor(Register Rd, Register Rn, Register Rm, unsigned size) +{ + return (size == 8 ? 0xca000000 : 0x4a000000) | (Rm.index() << 16) + | (Rn.index() << 5) | Rd.index(); +} + +uint32_t madd(Register Rd, Register Rn, Register Rm, Register Ra, unsigned size) +{ + return (size == 8 ? 0x9b000000 : 0x1b000000) | (Rm.index() << 16) + | (Ra.index() << 10) | (Rn.index() << 5) | Rd.index(); +} + +uint32_t mul(Register Rd, Register Rn, Register Rm, unsigned size) +{ + return madd(Rd, Rn, Rm, Register(31), size); +} + +uint32_t subi(Register Rd, Register Rn, int value, int shift, unsigned size) +{ + return (size == 8 ? 0xd1000000 : 0x51000000) | (shift ? 0x400000 : 0) + | (value << 10) | (Rn.index() << 5) | Rd.index(); +} + +uint32_t fabs_(Register Fd, Register Fn, unsigned size) +{ + return (size == 8 ? 0x1e60c000 : 0x1e20c000) | (Fn.index() << 5) | Fd.index(); +} + +uint32_t fneg(Register Fd, Register Fn, unsigned size) +{ + return (size == 8 ? 0x1e614000 : 0x1e214000) | (Fn.index() << 5) | Fd.index(); +} + +uint32_t fsqrt(Register Fd, Register Fn, unsigned size) +{ + return (size == 8 ? 0x1e61c000 : 0x1e21c000) | (Fn.index() << 5) | Fd.index(); +} + +uint32_t fadd(Register Fd, Register Fn, Register Fm, unsigned size) +{ + return (size == 8 ? 0x1e602800 : 0x1e202800) | (Fm.index() << 16) + | (Fn.index() << 5) | Fd.index(); +} + +uint32_t fsub(Register Fd, Register Fn, Register Fm, unsigned size) +{ + return (size == 8 ? 0x1e603800 : 0x1e203800) | (Fm.index() << 16) + | (Fn.index() << 5) | Fd.index(); +} + +uint32_t fmul(Register Fd, Register Fn, Register Fm, unsigned size) +{ + return (size == 8 ? 0x1e600800 : 0x1e200800) | (Fm.index() << 16) + | (Fn.index() << 5) | Fd.index(); +} + +uint32_t fdiv(Register Fd, Register Fn, Register Fm, unsigned size) +{ + return (size == 8 ? 0x1e601800 : 0x1e201800) | (Fm.index() << 16) + | (Fn.index() << 5) | Fd.index(); +} + +uint32_t fcvtSdDn(Register Fd, Register Fn) +{ + return 0x1e624000 | (Fn.index() << 5) | Fd.index(); +} + +uint32_t fcvtDdSn(Register Fd, Register Fn) +{ + return 0x1e22c000 | (Fn.index() << 5) | Fd.index(); +} + +uint32_t fcvtasXdDn(Register Rd, Register Fn) +{ + return 0x9e640000 | (Fn.index() << 5) | Rd.index(); +} + +uint32_t fcvtasWdSn(Register Rd, Register Fn) +{ + return 0x1e240000 | (Fn.index() << 5) | Rd.index(); +} + +uint32_t scvtfDdXn(Register Fd, Register Rn) +{ + return 0x9e620000 | (Rn.index() << 5) | Fd.index(); +} + +uint32_t scvtfSdWn(Register Fd, Register Rn) +{ + return 0x1e220000 | (Rn.index() << 5) | Fd.index(); +} + +uint32_t strFs(Register Fs, Register Rn, Register Rm, unsigned size) +{ + return (size == 8 ? 0xfc206800 : 0xbc206800) | (Rm.index() << 16) + | (Rn.index() << 5) | Fs.index(); +} + +uint32_t strb(Register Rs, Register Rn, Register Rm) +{ + return 0x38206800 | (Rm.index() << 16) | (Rn.index() << 5) | Rs.index(); +} + +uint32_t strh(Register Rs, Register Rn, Register Rm) +{ + return 0x78206800 | (Rm.index() << 16) | (Rn.index() << 5) | Rs.index(); +} + +uint32_t striFs(Register Fs, Register Rn, int offset, unsigned size) +{ + return (size == 8 ? 0xfd000000 : 0xbd000000) + | ((offset >> (size == 8 ? 3 : 2)) << 10) | (Rn.index() << 5) + | Fs.index(); +} + +uint32_t str(Register Rs, Register Rn, Register Rm, unsigned size) +{ + return (size == 8 ? 0xf8206800 : 0xb8206800) | (Rm.index() << 16) + | (Rn.index() << 5) | Rs.index(); +} + +uint32_t strbi(Register Rs, Register Rn, int offset) +{ + return 0x39000000 | (offset << 10) | (Rn.index() << 5) | Rs.index(); +} + +uint32_t strhi(Register Rs, Register Rn, int offset) +{ + return 0x79000000 | ((offset >> 1) << 10) | (Rn.index() << 5) | Rs.index(); +} + +uint32_t stri(Register Rs, Register Rn, int offset, unsigned size) +{ + return (size == 8 ? 0xf9000000 : 0xb9000000) + | ((offset >> (size == 8 ? 3 : 2)) << 10) | (Rn.index() << 5) + | Rs.index(); +} + +uint32_t ldrFd(Register Fd, Register Rn, Register Rm, unsigned size) +{ + return (size == 8 ? 0xfc606800 : 0xbc606800) | (Rm.index() << 16) + | (Rn.index() << 5) | Fd.index(); +} + +uint32_t ldrb(Register Rd, Register Rn, Register Rm) +{ + return 0x38606800 | (Rm.index() << 16) | (Rn.index() << 5) | Rd.index(); +} + +uint32_t ldrsb(Register Rd, Register Rn, Register Rm) +{ + return 0x38e06800 | (Rm.index() << 16) | (Rn.index() << 5) | Rd.index(); +} + +uint32_t ldrh(Register Rd, Register Rn, Register Rm) +{ + return 0x78606800 | (Rm.index() << 16) | (Rn.index() << 5) | Rd.index(); +} + +uint32_t ldrsh(Register Rd, Register Rn, Register Rm) +{ + return 0x78e06800 | (Rm.index() << 16) | (Rn.index() << 5) | Rd.index(); +} + +uint32_t ldrsw(Register Rd, Register Rn, Register Rm) +{ + return 0xb8a06800 | (Rm.index() << 16) | (Rn.index() << 5) | Rd.index(); +} + +uint32_t ldr(Register Rd, Register Rn, Register Rm, unsigned size) +{ + return (size == 8 ? 0xf8606800 : 0xb8606800) | (Rm.index() << 16) + | (Rn.index() << 5) | Rd.index(); +} + +uint32_t ldriFd(Register Fd, Register Rn, int offset, unsigned size) +{ + return (size == 8 ? 0xfd400000 : 0xbd400000) + | ((offset >> (size == 8 ? 3 : 2)) << 10) | (Rn.index() << 5) + | Fd.index(); +} + +uint32_t ldrbi(Register Rd, Register Rn, int offset) +{ + return 0x39400000 | (offset << 10) | (Rn.index() << 5) | Rd.index(); +} + +uint32_t ldrsbi(Register Rd, Register Rn, int offset) +{ + return 0x39c00000 | (offset << 10) | (Rn.index() << 5) | Rd.index(); +} + +uint32_t ldrhi(Register Rd, Register Rn, int offset) +{ + return 0x79400000 | ((offset >> 1) << 10) | (Rn.index() << 5) | Rd.index(); +} + +uint32_t ldrshi(Register Rd, Register Rn, int offset) +{ + return 0x79c00000 | ((offset >> 1) << 10) | (Rn.index() << 5) | Rd.index(); +} + +uint32_t ldrswi(Register Rd, Register Rn, int offset) +{ + return 0xb9800000 | ((offset >> 2) << 10) | (Rn.index() << 5) | Rd.index(); +} + +uint32_t ldri(Register Rd, Register Rn, int offset, unsigned size) +{ + return (size == 8 ? 0xf9400000 : 0xb9400000) + | ((offset >> (size == 8 ? 3 : 2)) << 10) | (Rn.index() << 5) + | Rd.index(); +} + +uint32_t fcmp(Register Fn, Register Fm, unsigned size) +{ + return (size == 8 ? 0x1e602000 : 0x1e202000) | (Fm.index() << 16) + | (Fn.index() << 5); +} + +uint32_t neg(Register Rd, Register Rm, unsigned size) +{ + return (size == 8 ? 0xcb0003e0 : 0x4b0003e0) | (Rm.index() << 16) + | Rd.index(); +} + +uint32_t cmp(Register Rn, Register Rm, unsigned size) +{ + return (size == 8 ? 0xeb00001f : 0x6b00001f) | (Rm.index() << 16) + | (Rn.index() == 31 ? 0x2063ff : (Rn.index() << 5)); +} + +uint32_t cmpi(Register Rn, int value, unsigned shift, unsigned size) +{ + return (size == 8 ? 0xf100001f : 0x7100001f) | (shift == 12 ? 0x400000 : 0) + | (value << 10) | (Rn.index() << 5); +} + +uint32_t b(int offset) +{ + return 0x14000000 | (offset >> 2); +} + +uint32_t bl(int offset) +{ + return 0x94000000 | (offset >> 2); +} + +uint32_t blr(Register Rn) +{ + return 0xd63f0000 | (Rn.index() << 5); +} + +uint32_t beq(int offset) +{ + return 0x54000000 | ((offset >> 2) << 5); +} + +uint32_t bne(int offset) +{ + return 0x54000001 | ((offset >> 2) << 5); +} + +uint32_t blt(int offset) +{ + return 0x5400000b | ((offset >> 2) << 5); +} + +uint32_t bgt(int offset) +{ + return 0x5400000c | ((offset >> 2) << 5); +} + +uint32_t ble(int offset) +{ + return 0x5400000d | ((offset >> 2) << 5); +} + +uint32_t bge(int offset) +{ + return 0x5400000a | ((offset >> 2) << 5); +} + +uint32_t bhi(int offset) +{ + return 0x54000008 | ((offset >> 2) << 5); +} + +uint32_t bpl(int offset) +{ + return 0x54000005 | ((offset >> 2) << 5); +} + +uint32_t brk(int flag) +{ + return 0xd4200020 | (flag << 5); +} + +uint32_t dmb(int flag) +{ + return 0xd50330bf | (flag << 8); +} + +} // namespace + +namespace avian { +namespace codegen { +namespace arm { + +using namespace avian::util; + +void shiftLeftR(Context* c, + unsigned size, + lir::RegisterPair* a, + lir::RegisterPair* b, + lir::RegisterPair* dst) +{ + append(c, lslv(dst->low, b->low, a->low, size)); +} + +void shiftLeftC(Context* c, + unsigned size, + lir::Constant* a, + lir::RegisterPair* b, + lir::RegisterPair* dst) +{ + uint64_t value = a->value->value(); + if (size == 4 and (value & 0x1F)) { + append(c, lsli(dst->low, b->low, value & 0x1F, 4)); + } else if (size == 8 and (value & 0x3F)) { + append(c, lsli(dst->low, b->low, value & 0x3F, 8)); + } else { + moveRR(c, size, b, size, dst); + } +} + +void shiftRightR(Context* c, + unsigned size, + lir::RegisterPair* a, + lir::RegisterPair* b, + lir::RegisterPair* dst) +{ + append(c, asrv(dst->low, b->low, a->low, size)); +} + +void shiftRightC(Context* c, + unsigned size UNUSED, + lir::Constant* a, + lir::RegisterPair* b, + lir::RegisterPair* dst) +{ + uint64_t value = a->value->value(); + if (size == 4 and (value & 0x1F)) { + append(c, asri(dst->low, b->low, value & 0x1F, 4)); + } else if (size == 8 and (value & 0x3F)) { + append(c, asri(dst->low, b->low, value & 0x3F, 8)); + } else { + moveRR(c, size, b, size, dst); + } +} + +void unsignedShiftRightR(Context* c, + unsigned size, + lir::RegisterPair* a, + lir::RegisterPair* b, + lir::RegisterPair* dst) +{ + append(c, lsrv(dst->low, b->low, a->low, size)); +} + +void unsignedShiftRightC(Context* c, + unsigned size UNUSED, + lir::Constant* a, + lir::RegisterPair* b, + lir::RegisterPair* dst) +{ + uint64_t value = a->value->value(); + if (size == 4 and (value & 0x1F)) { + append(c, lsri(dst->low, b->low, value & 0x1F, 4)); + } else if (size == 8 and (value & 0x3F)) { + append(c, lsri(dst->low, b->low, value & 0x3F, 8)); + } else { + moveRR(c, size, b, size, dst); + } +} + +void jumpR(Context* c, unsigned size UNUSED, lir::RegisterPair* target) +{ + assertT(c, size == vm::TargetBytesPerWord); + append(c, br(target->low)); +} + +void moveRR(Context* c, + unsigned srcSize, + lir::RegisterPair* src, + unsigned dstSize, + lir::RegisterPair* dst) +{ + bool srcIsFpr = isFpr(src); + bool dstIsFpr = isFpr(dst); + if (srcIsFpr or dstIsFpr) { + assertT(c, srcSize == dstSize); + + if (srcIsFpr and dstIsFpr) { + append(c, fmovFdFn(fpr(dst), fpr(src), srcSize)); + } else if (srcIsFpr) { + append(c, fmovRdFn(dst->low, fpr(src), srcSize)); + } else { + append(c, fmovFdRn(fpr(dst), src->low, srcSize)); + } + } else { + switch (srcSize) { + case 1: + append(c, sxtb(dst->low, src->low)); + break; + + case 2: + append(c, sxth(dst->low, src->low)); + break; + + case 4: + if (dstSize == 4) { + append(c, mov(dst->low, src->low, srcSize)); + } else { + append(c, sxtw(dst->low, src->low)); + } + break; + + case 8: + append(c, mov(dst->low, src->low, srcSize)); + break; + + default: + abort(c); + } + } +} + +void moveZRR(Context* c, + unsigned srcSize, + lir::RegisterPair* src, + unsigned, + lir::RegisterPair* dst) +{ + switch (srcSize) { + case 2: + append(c, uxth(dst->low, src->low)); + break; + + default: + abort(c); + } +} + +void moveCR2(Context* c, + unsigned size, + lir::Constant* src, + lir::RegisterPair* dst, + Promise* callOffset) +{ + if (isFpr(dst)) { + // todo: could use a single fmov here and avoid the temporary for + // constants that fit + lir::RegisterPair tmp(c->client->acquireTemporary(GPR_MASK)); + moveCR(c, size, src, size, &tmp); + moveRR(c, size, &tmp, size, dst); + c->client->releaseTemporary(tmp.low); + } else if (callOffset == 0 and src->value->resolved()) { + // todo: Is it better performance-wise to load using immediate + // moves or via a PC-relative constant pool? Does it depend on + // how many significant bits there are? + + int64_t value = src->value->value(); + if (value >= 0) { + append(c, movz(dst->low, value & 0xFFFF, 0, size)); + if (value >> 16) { + if ((value >> 16) & 0xFFFF) { + append(c, movk(dst->low, (value >> 16) & 0xFFFF, 16, size)); + } + if (value >> 32) { + if ((value >> 32) & 0xFFFF) { + append(c, movk(dst->low, (value >> 32) & 0xFFFF, 32, size)); + } + if (value >> 48) { + append(c, movk(dst->low, (value >> 48) & 0xFFFF, 48, size)); + } + } + } + } else { + append(c, movn(dst->low, (~value) & 0xFFFF, 0, size)); + if (~(value >> 16)) { + if (((value >> 16) & 0xFFFF) != 0xFFFF) { + append(c, movk(dst->low, (value >> 16) & 0xFFFF, 16, size)); + } + if (~(value >> 32)) { + if (((value >> 32) & 0xFFFF) != 0xFFFF) { + append(c, movk(dst->low, (value >> 32) & 0xFFFF, 32, size)); + } + if (~(value >> 48)) { + append(c, movk(dst->low, (value >> 48) & 0xFFFF, 48, size)); + } + } + } + } + } else { + appendConstantPoolEntry(c, src->value, callOffset); + append(c, ldrPCRel(dst->low, 0, size)); + } +} + +void moveCR(Context* c, + unsigned size, + lir::Constant* src, + unsigned, + lir::RegisterPair* dst) +{ + moveCR2(c, size, src, dst, 0); +} + +void addR(Context* c, + unsigned size, + lir::RegisterPair* a, + lir::RegisterPair* b, + lir::RegisterPair* dst) +{ + append(c, add(dst->low, a->low, b->low, size)); +} + +void subR(Context* c, + unsigned size, + lir::RegisterPair* a, + lir::RegisterPair* b, + lir::RegisterPair* dst) +{ + append(c, sub(dst->low, b->low, a->low, size)); +} + +void addC(Context* c, + unsigned size, + lir::Constant* a, + lir::RegisterPair* b, + lir::RegisterPair* dst) +{ + int64_t v = a->value->value(); + if (v) { + if (v > 0 and v < 0x1000) { + append(c, addi(dst->low, b->low, v, 0, size)); + } else if (v > 0 and v < 0x1000000 and v % 0x1000 == 0) { + append(c, addi(dst->low, b->low, v >> 12, 12, size)); + } else { + // todo + abort(c); + } + } else { + moveRR(c, size, b, size, dst); + } +} + +void subC(Context* c, + unsigned size, + lir::Constant* a, + lir::RegisterPair* b, + lir::RegisterPair* dst) +{ + int64_t v = a->value->value(); + if (v) { + if (v > 0 and v < 0x1000) { + append(c, subi(dst->low, b->low, v, 0, size)); + } else if (v > 0 and v < 0x1000000 and v % 0x1000 == 0) { + append(c, subi(dst->low, b->low, v >> 12, 12, size)); + } else { + // todo + abort(c); + } + } else { + moveRR(c, size, b, size, dst); + } +} + +void multiplyR(Context* c, + unsigned size, + lir::RegisterPair* a, + lir::RegisterPair* b, + lir::RegisterPair* dst) +{ + append(c, mul(dst->low, a->low, b->low, size)); +} + +void floatAbsoluteRR(Context* c, + unsigned size, + lir::RegisterPair* a, + unsigned, + lir::RegisterPair* b) +{ + append(c, fabs_(fpr(b), fpr(a), size)); +} + +void floatNegateRR(Context* c, + unsigned size, + lir::RegisterPair* a, + unsigned, + lir::RegisterPair* b) +{ + append(c, fneg(fpr(b), fpr(a), size)); +} + +void float2FloatRR(Context* c, + unsigned size, + lir::RegisterPair* a, + unsigned, + lir::RegisterPair* b) +{ + if (size == 8) { + append(c, fcvtSdDn(fpr(b), fpr(a))); + } else { + append(c, fcvtDdSn(fpr(b), fpr(a))); + } +} + +void float2IntRR(Context* c, + unsigned size, + lir::RegisterPair* a, + unsigned, + lir::RegisterPair* b) +{ + if (size == 8) { + append(c, fcvtasXdDn(b->low, fpr(a))); + } else { + append(c, fcvtasWdSn(b->low, fpr(a))); + } +} + +void int2FloatRR(Context* c, + unsigned, + lir::RegisterPair* a, + unsigned size, + lir::RegisterPair* b) +{ + if (size == 8) { + append(c, scvtfDdXn(fpr(b), a->low)); + } else { + append(c, scvtfSdWn(fpr(b), a->low)); + } +} + +void floatSqrtRR(Context* c, + unsigned size, + lir::RegisterPair* a, + unsigned, + lir::RegisterPair* b) +{ + append(c, fsqrt(fpr(b), fpr(a), size)); +} + +void floatAddR(Context* c, + unsigned size, + lir::RegisterPair* a, + lir::RegisterPair* b, + lir::RegisterPair* dst) +{ + append(c, fadd(fpr(dst), fpr(b), fpr(a), size)); +} + +void floatSubtractR(Context* c, + unsigned size, + lir::RegisterPair* a, + lir::RegisterPair* b, + lir::RegisterPair* dst) +{ + append(c, fsub(fpr(dst), fpr(b), fpr(a), size)); +} + +void floatMultiplyR(Context* c, + unsigned size, + lir::RegisterPair* a, + lir::RegisterPair* b, + lir::RegisterPair* dst) +{ + append(c, fmul(fpr(dst), fpr(b), fpr(a), size)); +} + +void floatDivideR(Context* c, + unsigned size, + lir::RegisterPair* a, + lir::RegisterPair* b, + lir::RegisterPair* dst) +{ + append(c, fdiv(fpr(dst), fpr(b), fpr(a), size)); +} + +Register normalize(Context* c, + int offset, + Register index, + unsigned scale, + bool* preserveIndex, + bool* release) +{ + if (offset != 0 or scale != 1) { + lir::RegisterPair normalizedIndex( + *preserveIndex ? c->client->acquireTemporary(GPR_MASK) : index); + + if (*preserveIndex) { + *release = true; + *preserveIndex = false; + } else { + *release = false; + } + + Register scaled; + + if (scale != 1) { + lir::RegisterPair unscaledIndex(index); + + ResolvedPromise scalePromise(log(scale)); + lir::Constant scaleConstant(&scalePromise); + + shiftLeftC(c, + vm::TargetBytesPerWord, + &scaleConstant, + &unscaledIndex, + &normalizedIndex); + + scaled = normalizedIndex.low; + } else { + scaled = index; + } + + if (offset != 0) { + lir::RegisterPair untranslatedIndex(scaled); + + ResolvedPromise offsetPromise(offset); + lir::Constant offsetConstant(&offsetPromise); + + lir::RegisterPair tmp(c->client->acquireTemporary(GPR_MASK)); + moveCR(c, + vm::TargetBytesPerWord, + &offsetConstant, + vm::TargetBytesPerWord, + &tmp); + addR(c, + vm::TargetBytesPerWord, + &tmp, + &untranslatedIndex, + &normalizedIndex); + c->client->releaseTemporary(tmp.low); + } + + return normalizedIndex.low; + } else { + *release = false; + return index; + } +} + +void store(Context* c, + unsigned size, + lir::RegisterPair* src, + Register base, + int offset, + Register index, + unsigned scale, + bool preserveIndex) +{ + if (index != NoRegister) { + bool release; + + // todo: browsing the instruction set, it looks like we could do a + // scaled store or load in a single instruction if the offset is + // zero, and we could simplify things for the case of non-zero + // offsets also + + Register normalized + = normalize(c, offset, index, scale, &preserveIndex, &release); + + if (isFpr(src)) { + switch (size) { + case 4: + case 8: + append(c, strFs(fpr(src->low), base, normalized, size)); + break; + + default: + abort(c); + } + } else { + switch (size) { + case 1: + append(c, strb(src->low, base, normalized)); + break; + + case 2: + append(c, strh(src->low, base, normalized)); + break; + + case 4: + case 8: + append(c, str(src->low, base, normalized, size)); + break; + + default: + abort(c); + } + } + + if (release) { + c->client->releaseTemporary(normalized); + } + } else if (abs(offset) == (abs(offset) & 0xFFF)) { + if (isFpr(src)) { + switch (size) { + case 4: + case 8: + assertT(c, offset == (offset & (size == 8 ? (~7) : (~3)))); + append(c, striFs(fpr(src->low), base, offset, size)); + break; + + default: + abort(c); + } + } else { // FPR store + switch (size) { + case 1: + append(c, strbi(src->low, base, offset)); + break; + + case 2: + assertT(c, offset == (offset & (~1))); + append(c, strhi(src->low, base, offset)); + break; + + case 4: + assertT(c, offset == (offset & (~3))); + append(c, stri(src->low, base, offset, size)); + break; + + case 8: + assertT(c, offset == (offset & (~7))); + append(c, stri(src->low, base, offset, size)); + break; + + default: + abort(c); + } + } + } else { + lir::RegisterPair tmp(c->client->acquireTemporary(GPR_MASK)); + ResolvedPromise offsetPromise(offset); + lir::Constant offsetConstant(&offsetPromise); + moveCR(c, + vm::TargetBytesPerWord, + &offsetConstant, + vm::TargetBytesPerWord, + &tmp); + + store(c, size, src, base, 0, tmp.low, 1, false); + + c->client->releaseTemporary(tmp.low); + } +} + +void moveRM(Context* c, + unsigned srcSize, + lir::RegisterPair* src, + unsigned dstSize UNUSED, + lir::Memory* dst) +{ + assertT(c, srcSize == dstSize); + + if (src->low.index() == 31) { + assertT(c, c->client == 0); // the compiler should never ask us to + // store the SP; we'll only get here + // when assembling a thunk + + lir::RegisterPair tmp(Register(9)); // we're in a thunk, so we can + // clobber this + + moveRR(c, srcSize, src, srcSize, &tmp); + store( + c, srcSize, &tmp, dst->base, dst->offset, dst->index, dst->scale, true); + } else { + store( + c, srcSize, src, dst->base, dst->offset, dst->index, dst->scale, true); + } +} + +void load(Context* c, + unsigned srcSize, + Register base, + int offset, + Register index, + unsigned scale, + unsigned dstSize, + lir::RegisterPair* dst, + bool preserveIndex, + bool signExtend) +{ + if (index != NoRegister) { + bool release; + Register normalized + = normalize(c, offset, index, scale, &preserveIndex, &release); + + if (isFpr(dst)) { // FPR load + switch (srcSize) { + case 4: + case 8: + append(c, ldrFd(fpr(dst->low), base, normalized, srcSize)); + break; + + default: + abort(c); + } + } else { + switch (srcSize) { + case 1: + if (signExtend) { + append(c, ldrsb(dst->low, base, normalized)); + } else { + append(c, ldrb(dst->low, base, normalized)); + } + break; + + case 2: + if (signExtend) { + append(c, ldrsh(dst->low, base, normalized)); + } else { + append(c, ldrh(dst->low, base, normalized)); + } + break; + + case 4: + case 8: + if (signExtend and srcSize == 4 and dstSize == 8) { + append(c, ldrsw(dst->low, base, normalized)); + } else { + append(c, ldr(dst->low, base, normalized, srcSize)); + } + break; + + default: + abort(c); + } + } + + if (release) { + c->client->releaseTemporary(normalized); + } + } else if (abs(offset) == (abs(offset) & 0xFFF)) { + if (isFpr(dst)) { + switch (srcSize) { + case 4: + case 8: + assertT(c, offset == (offset & (srcSize == 8 ? (~7) : (~3)))); + append(c, ldriFd(fpr(dst->low), base, offset, srcSize)); + break; + + default: + abort(c); + } + } else { + switch (srcSize) { + case 1: + if (signExtend) { + append(c, ldrsbi(dst->low, base, offset)); + } else { + append(c, ldrbi(dst->low, base, offset)); + } + break; + + case 2: + assertT(c, offset == (offset & (~1))); + if (signExtend) { + append(c, ldrshi(dst->low, base, offset)); + } else { + append(c, ldrhi(dst->low, base, offset)); + } + break; + + case 4: + case 8: + if (signExtend and srcSize == 4 and dstSize == 8) { + assertT(c, offset == (offset & (~3))); + append(c, ldrswi(dst->low, base, offset)); + } else { + assertT(c, offset == (offset & (srcSize == 8 ? (~7) : (~3)))); + append(c, ldri(dst->low, base, offset, srcSize)); + } + break; + + default: + abort(c); + } + } + } else { + lir::RegisterPair tmp(c->client->acquireTemporary(GPR_MASK)); + ResolvedPromise offsetPromise(offset); + lir::Constant offsetConstant(&offsetPromise); + moveCR(c, + vm::TargetBytesPerWord, + &offsetConstant, + vm::TargetBytesPerWord, + &tmp); + + load(c, srcSize, base, 0, tmp.low, 1, dstSize, dst, false, signExtend); + + c->client->releaseTemporary(tmp.low); + } +} + +void moveMR(Context* c, + unsigned srcSize, + lir::Memory* src, + unsigned dstSize, + lir::RegisterPair* dst) +{ + if (dst->low.index() == 31) { + assertT(c, c->client == 0); // the compiler should never ask us to + // load the SP; we'll only get here + // when assembling a thunk + + lir::RegisterPair tmp(Register(9)); // we're in a thunk, so we can + // clobber this + + load(c, srcSize, src->base, src->offset, src->index, src->scale, dstSize, &tmp, true, true); + moveRR(c, dstSize, &tmp, dstSize, dst); + } else { + load(c, + srcSize, + src->base, + src->offset, + src->index, + src->scale, + dstSize, + dst, + true, + true); + } +} + +void moveZMR(Context* c, + unsigned srcSize, + lir::Memory* src, + unsigned dstSize, + lir::RegisterPair* dst) +{ + load(c, + srcSize, + src->base, + src->offset, + src->index, + src->scale, + dstSize, + dst, + true, + false); +} + +void andR(Context* c, + unsigned size, + lir::RegisterPair* a, + lir::RegisterPair* b, + lir::RegisterPair* dst) +{ + append(c, and_(dst->low, a->low, b->low, size)); +} + +void andC(Context* c, + unsigned size, + lir::Constant* a, + lir::RegisterPair* b, + lir::RegisterPair* dst) +{ + int64_t v = a->value->value(); + + if (~v) { + bool useTemporary = b->low == dst->low; + lir::RegisterPair tmp(dst->low); + if (useTemporary) { + tmp.low = c->client->acquireTemporary(GPR_MASK); + } + + moveCR(c, size, a, size, &tmp); + andR(c, size, b, &tmp, dst); + + if (useTemporary) { + c->client->releaseTemporary(tmp.low); + } + } else { + moveRR(c, size, b, size, dst); + } +} + +void orR(Context* c, + unsigned size, + lir::RegisterPair* a, + lir::RegisterPair* b, + lir::RegisterPair* dst) +{ + append(c, orr(dst->low, a->low, b->low, size)); +} + +void xorR(Context* c, + unsigned size, + lir::RegisterPair* a, + lir::RegisterPair* b, + lir::RegisterPair* dst) +{ + append(c, eor(dst->low, a->low, b->low, size)); +} + +void moveAR(Context* c, + unsigned srcSize, + lir::Address* src, + unsigned dstSize, + lir::RegisterPair* dst) +{ + assertT( + c, + srcSize == vm::TargetBytesPerWord and dstSize == vm::TargetBytesPerWord); + + lir::Constant constant(src->address); + moveCR(c, srcSize, &constant, dstSize, dst); + + lir::Memory memory(dst->low, 0, NoRegister, 0); + moveMR(c, dstSize, &memory, dstSize, dst); +} + +void compareRR(Context* c, + unsigned aSize, + lir::RegisterPair* a, + unsigned bSize UNUSED, + lir::RegisterPair* b) +{ + assertT(c, not(isFpr(a) xor isFpr(b))); + assertT(c, aSize == bSize); + + if (isFpr(a)) { + append(c, fcmp(fpr(b), fpr(a), aSize)); + } else { + append(c, cmp(b->low, a->low, aSize)); + } +} + +void compareCR(Context* c, + unsigned aSize, + lir::Constant* a, + unsigned bSize UNUSED, + lir::RegisterPair* b) +{ + assertT(c, aSize == bSize); + + if (!isFpr(b) && a->value->resolved()) { + int64_t v = a->value->value(); + if (v == 0) { + append(c, cmp(b->low, Register(31), aSize)); + return; + } else if (v > 0 and v < 0x1000) { + append(c, cmpi(b->low, v, 0, aSize)); + return; + } else if (v > 0 and v < 0x1000000 and v % 0x1000 == 0) { + append(c, cmpi(b->low, v >> 12, 12, aSize)); + return; + } + } + + lir::RegisterPair tmp(c->client->acquireTemporary(GPR_MASK)); + moveCR(c, aSize, a, bSize, &tmp); + compareRR(c, bSize, &tmp, bSize, b); + c->client->releaseTemporary(tmp.low); +} + +void compareCM(Context* c, + unsigned aSize, + lir::Constant* a, + unsigned bSize, + lir::Memory* b) +{ + assertT(c, aSize == bSize); + + lir::RegisterPair tmp(c->client->acquireTemporary(GPR_MASK)); + moveMR(c, bSize, b, bSize, &tmp); + compareCR(c, aSize, a, bSize, &tmp); + c->client->releaseTemporary(tmp.low); +} + +void compareRM(Context* c, + unsigned aSize, + lir::RegisterPair* a, + unsigned bSize, + lir::Memory* b) +{ + assertT(c, aSize == bSize); + + lir::RegisterPair tmp(c->client->acquireTemporary(GPR_MASK)); + moveMR(c, bSize, b, bSize, &tmp); + compareRR(c, aSize, a, bSize, &tmp); + c->client->releaseTemporary(tmp.low); +} + +void compareMR(Context* c, + unsigned aSize, + lir::Memory* a, + unsigned bSize, + lir::RegisterPair* b) +{ + assertT(c, aSize == bSize); + + lir::RegisterPair tmp(c->client->acquireTemporary(GPR_MASK)); + moveMR(c, aSize, a, aSize, &tmp); + compareRR(c, aSize, &tmp, bSize, b); + c->client->releaseTemporary(tmp.low); +} + +int32_t branch(Context* c, lir::TernaryOperation op) +{ + switch (op) { + case lir::JumpIfEqual: + case lir::JumpIfFloatEqual: + return beq(0); + + case lir::JumpIfNotEqual: + case lir::JumpIfFloatNotEqual: + return bne(0); + + case lir::JumpIfLess: + case lir::JumpIfFloatLess: + case lir::JumpIfFloatLessOrUnordered: + return blt(0); + + case lir::JumpIfGreater: + case lir::JumpIfFloatGreater: + return bgt(0); + + case lir::JumpIfLessOrEqual: + case lir::JumpIfFloatLessOrEqual: + case lir::JumpIfFloatLessOrEqualOrUnordered: + return ble(0); + + case lir::JumpIfGreaterOrEqual: + case lir::JumpIfFloatGreaterOrEqual: + return bge(0); + + case lir::JumpIfFloatGreaterOrUnordered: + return bhi(0); + + case lir::JumpIfFloatGreaterOrEqualOrUnordered: + return bpl(0); + + default: + abort(c); + } +} + +void conditional(Context* c, int32_t branch, lir::Constant* target) +{ + appendOffsetTask(c, target->value, offsetPromise(c)); + append(c, branch); +} + +void branch(Context* c, lir::TernaryOperation op, lir::Constant* target) +{ + conditional(c, branch(c, op), target); +} + +void branchRR(Context* c, + lir::TernaryOperation op, + unsigned size, + lir::RegisterPair* a, + lir::RegisterPair* b, + lir::Constant* target) +{ + compareRR(c, size, a, size, b); + branch(c, op, target); +} + +void branchCR(Context* c, + lir::TernaryOperation op, + unsigned size, + lir::Constant* a, + lir::RegisterPair* b, + lir::Constant* target) +{ + assertT(c, not isFloatBranch(op)); + + compareCR(c, size, a, size, b); + branch(c, op, target); +} + +void branchRM(Context* c, + lir::TernaryOperation op, + unsigned size, + lir::RegisterPair* a, + lir::Memory* b, + lir::Constant* target) +{ + assertT(c, not isFloatBranch(op)); + assertT(c, size <= vm::TargetBytesPerWord); + + if (a->low.index() == 31) { + // Stack overflow checks need to compare to the stack pointer, but + // we can only encode that in the opposite operand order we're + // given, so we need to reverse everything. Also, we can't do a + // conditional jump further than 2^19 instructions away, which can + // cause trouble with large code, so we branch past an + // unconditional branch which can jump further, which reverses the + // logic again. Confused? Good. + assertT(c, op == lir::JumpIfGreaterOrEqual); + compareMR(c, size, b, size, a); + append(c, bge(8)); + jumpC(c, vm::TargetBytesPerWord, target); + } else { + compareRM(c, size, a, size, b); + branch(c, op, target); + } +} + +void branchCM(Context* c, + lir::TernaryOperation op, + unsigned size, + lir::Constant* a, + lir::Memory* b, + lir::Constant* target) +{ + assertT(c, not isFloatBranch(op)); + assertT(c, size <= vm::TargetBytesPerWord); + + compareCM(c, size, a, size, b); + branch(c, op, target); +} + +ShiftMaskPromise* shiftMaskPromise(Context* c, + Promise* base, + unsigned shift, + int64_t mask) +{ + return new (c->zone) ShiftMaskPromise(base, shift, mask); +} + +void moveCM(Context* c, + unsigned srcSize, + lir::Constant* src, + unsigned dstSize, + lir::Memory* dst) +{ + lir::RegisterPair tmp(c->client->acquireTemporary(GPR_MASK)); + moveCR(c, srcSize, src, dstSize, &tmp); + moveRM(c, dstSize, &tmp, dstSize, dst); + c->client->releaseTemporary(tmp.low); +} + +void negateRR(Context* c, + unsigned srcSize, + lir::RegisterPair* src, + unsigned dstSize UNUSED, + lir::RegisterPair* dst) +{ + assertT(c, srcSize == dstSize); + + append(c, neg(dst->low, src->low, srcSize)); +} + +void callR(Context* c, unsigned size UNUSED, lir::RegisterPair* target) +{ + assertT(c, size == vm::TargetBytesPerWord); + append(c, blr(target->low)); +} + +void callC(Context* c, unsigned size UNUSED, lir::Constant* target) +{ + assertT(c, size == vm::TargetBytesPerWord); + + appendOffsetTask(c, target->value, offsetPromise(c)); + append(c, bl(0)); +} + +void longCallC(Context* c, unsigned size UNUSED, lir::Constant* target) +{ + assertT(c, size == vm::TargetBytesPerWord); + + lir::RegisterPair tmp( + Register(9)); // a non-arg reg that we don't mind clobbering + moveCR2(c, vm::TargetBytesPerWord, target, &tmp, offsetPromise(c)); + callR(c, vm::TargetBytesPerWord, &tmp); +} + +void longJumpC(Context* c, unsigned size UNUSED, lir::Constant* target) +{ + assertT(c, size == vm::TargetBytesPerWord); + + lir::RegisterPair tmp( + Register(9)); // a non-arg reg that we don't mind clobbering + moveCR2(c, vm::TargetBytesPerWord, target, &tmp, offsetPromise(c)); + jumpR(c, vm::TargetBytesPerWord, &tmp); +} + +void jumpC(Context* c, unsigned size UNUSED, lir::Constant* target) +{ + assertT(c, size == vm::TargetBytesPerWord); + + appendOffsetTask(c, target->value, offsetPromise(c)); + append(c, b(0)); +} + +void return_(Context* c) +{ + append(c, br(LinkRegister)); +} + +void trap(Context* c) +{ + append(c, brk(0)); +} + +// todo: determine the minimal operation types and domains needed to +// implement the following barriers (see +// http://community.arm.com/groups/processors/blog/2011/10/19/memory-access-ordering-part-3--memory-access-ordering-in-the-arm-architecture). +// For now, we just use DMB SY as a conservative but not necessarily +// performant choice. + +void memoryBarrier(Context* c) +{ + append(c, dmb(0xF)); +} + +void loadBarrier(Context* c) +{ + memoryBarrier(c); +} + +void storeStoreBarrier(Context* c) +{ + memoryBarrier(c); +} + +void storeLoadBarrier(Context* c) +{ + memoryBarrier(c); +} + +} // namespace arm +} // namespace codegen +} // namespace avian + +#endif // TARGET_BYTES_PER_WORD == 8 diff --git a/sgx-jvm/avian/src/codegen/target/arm/registers.h b/sgx-jvm/avian/src/codegen/target/arm/registers.h new file mode 100644 index 0000000000..07e377bd76 --- /dev/null +++ b/sgx-jvm/avian/src/codegen/target/arm/registers.h @@ -0,0 +1,77 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#ifndef AVIAN_CODEGEN_ASSEMBLER_ARM_REGISTERS_H +#define AVIAN_CODEGEN_ASSEMBLER_ARM_REGISTERS_H + +#include +#include + +#include "avian/environment.h" + +namespace avian { +namespace codegen { +namespace arm { + +const uint64_t MASK_LO32 = 0xffffffff; +const unsigned MASK_LO8 = 0xff; + +#if TARGET_BYTES_PER_WORD == 8 +constexpr Register ThreadRegister(19); +constexpr Register StackRegister(31); +constexpr Register LinkRegister(30); +constexpr Register FrameRegister(29); +constexpr Register ProgramCounter(0xFE); // i.e. unaddressable + +const int N_GPRS = 32; +const int N_FPRS = 32; +const RegisterMask GPR_MASK = 0xffffffff; +const RegisterMask FPR_MASK = 0xffffffff00000000; + +#else +constexpr Register ThreadRegister(8); +constexpr Register StackRegister(13); +constexpr Register LinkRegister(14); +constexpr Register FrameRegister(0xFE); // i.e. there is none +constexpr Register ProgramCounter(15); + +const int N_GPRS = 16; +const int N_FPRS = 16; +const RegisterMask GPR_MASK = 0xffff; +const RegisterMask FPR_MASK = 0xffff0000; + +inline int fpr64(Register reg) +{ + return reg.index() - N_GPRS; +} +inline int fpr64(lir::RegisterPair* reg) +{ + return fpr64(reg->low); +} +inline int fpr32(Register reg) +{ + return fpr64(reg) << 1; +} +inline int fpr32(lir::RegisterPair* reg) +{ + return fpr64(reg) << 1; +} +#endif + +inline bool isFpr(lir::RegisterPair* reg) +{ + return reg->low.index() >= N_GPRS; +} + +} // namespace arm +} // namespace codegen +} // namespace avian + +#endif // AVIAN_CODEGEN_ASSEMBLER_ARM_REGISTERS_H diff --git a/sgx-jvm/avian/src/codegen/target/multimethod.h b/sgx-jvm/avian/src/codegen/target/multimethod.h new file mode 100644 index 0000000000..61f7a72318 --- /dev/null +++ b/sgx-jvm/avian/src/codegen/target/multimethod.h @@ -0,0 +1,29 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#ifndef AVIAN_CODEGEN_TARGET_MULTIMETHOD_H +#define AVIAN_CODEGEN_TARGET_MULTIMETHOD_H + +namespace avian { +namespace codegen { + +class Multimethod { + public: + inline static unsigned index(lir::UnaryOperation operation, + lir::Operand::Type operand) + { + return operation + (lir::UnaryOperationCount * (unsigned)operand); + } +}; + +} // namespace codegen +} // namespace avian + +#endif // AVIAN_CODEGEN_TARGET_MULTIMETHOD_H diff --git a/sgx-jvm/avian/src/codegen/target/x86/CMakeLists.txt b/sgx-jvm/avian/src/codegen/target/x86/CMakeLists.txt new file mode 100644 index 0000000000..eb5d5b1554 --- /dev/null +++ b/sgx-jvm/avian/src/codegen/target/x86/CMakeLists.txt @@ -0,0 +1,11 @@ +add_library(avian_codegen_x86 + assembler.cpp + block.cpp + context.cpp + detect.cpp + encode.cpp + fixup.cpp + multimethod.cpp + operations.cpp + padding.cpp +) diff --git a/sgx-jvm/avian/src/codegen/target/x86/assembler.cpp b/sgx-jvm/avian/src/codegen/target/x86/assembler.cpp new file mode 100644 index 0000000000..c8412dbc04 --- /dev/null +++ b/sgx-jvm/avian/src/codegen/target/x86/assembler.cpp @@ -0,0 +1,1263 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#include +#include + +#include "avian/environment.h" +#include "avian/target.h" +#include "avian/alloc-vector.h" +#include "avian/common.h" +#include "avian/util/allocator.h" +#include "avian/zone.h" + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +#include "context.h" +#include "block.h" +#include "fixup.h" +#include "padding.h" +#include "registers.h" +#include "operations.h" +#include "detect.h" +#include "multimethod.h" +#include "../multimethod.h" + +#define CAST1(x) reinterpret_cast(x) +#define CAST2(x) reinterpret_cast(x) +#define CAST_BRANCH(x) reinterpret_cast(x) + +using namespace vm; +using namespace avian::util; + +namespace avian { +namespace codegen { +namespace x86 { + +const unsigned FrameHeaderSize = (UseFramePointer ? 2 : 1); + +const unsigned StackAlignmentInBytes = 16; +const unsigned StackAlignmentInWords = StackAlignmentInBytes + / TargetBytesPerWord; + +unsigned argumentFootprint(unsigned footprint) +{ + return max(pad(footprint, StackAlignmentInWords), StackAlignmentInWords); +} + +uint32_t read4(uint8_t* p) +{ + uint32_t v; + memcpy(&v, p, 4); + return v; +} + +void nextFrame(ArchitectureContext* c UNUSED, + uint8_t* start, + unsigned size UNUSED, + unsigned footprint, + void*, + bool mostRecent, + int targetParameterFootprint, + void** ip, + void** stack) +{ + assertT(c, *ip >= start); + assertT(c, *ip <= start + size); + + uint8_t* instruction = static_cast(*ip); + + // skip stack overflow check, if present: + if (TargetBytesPerWord == 4) { + if (*start == 0x39) { + start += 12; + } + } else if (*start == 0x48 and start[1] == 0x39) { + start += 13; + } + + if (instruction <= start) { + assertT(c, mostRecent); + *ip = static_cast(*stack)[0]; + return; + } + + if (UseFramePointer) { + // skip preamble + start += (TargetBytesPerWord == 4 ? 3 : 4); + + if (instruction <= start or *instruction == 0x5d) { + assertT(c, mostRecent); + + *ip = static_cast(*stack)[1]; + *stack = static_cast(*stack) + 1; + return; + } + } + + if (*instruction == 0xc3) { // return + *ip = static_cast(*stack)[0]; + return; + } + + unsigned offset = footprint + FrameHeaderSize - (mostRecent ? 1 : 0); + + if (TailCalls and targetParameterFootprint >= 0) { + if (argumentFootprint(targetParameterFootprint) > StackAlignmentInWords) { + offset += argumentFootprint(targetParameterFootprint) + - StackAlignmentInWords; + } + + // check for post-non-tail-call stack adjustment of the form "sub + // $offset,%rsp": + if (TargetBytesPerWord == 4) { + if ((*instruction == 0x83 or *instruction == 0x81) + and instruction[1] == 0xec) { + offset + -= (*instruction == 0x83 ? instruction[2] : read4(instruction + 2)) + / TargetBytesPerWord; + } + } else if (*instruction == 0x48 + and (instruction[1] == 0x83 or instruction[1] == 0x81) + and instruction[2] == 0xec) { + offset + -= (instruction[1] == 0x83 ? instruction[3] : read4(instruction + 3)) + / TargetBytesPerWord; + } + + // todo: check for and handle tail calls + } + + if (UseFramePointer and not mostRecent) { + assertT(c, + static_cast(*stack)[-1] + 1 + == static_cast(*stack) + offset); + + assertT(c, + static_cast(*stack)[-1][1] + == static_cast(*stack)[offset]); + } + + *ip = static_cast(*stack)[offset]; + *stack = static_cast(*stack) + offset; +} + +class MyArchitecture : public Architecture { + public: + MyArchitecture(System* system, bool useNativeFeatures) + : c(system, useNativeFeatures), + referenceCount(0), + myRegisterFile(GeneralRegisterMask, useSSE(&c) ? FloatRegisterMask : 0) + { + populateTables(&c); + } + + virtual unsigned floatRegisterSize() + { + if (useSSE(&c)) { + return 8; + } else { + return 0; + } + } + + virtual const RegisterFile* registerFile() + { + return &myRegisterFile; + } + + virtual Register scratch() + { + return rax; + } + + virtual Register stack() + { + return rsp; + } + + virtual Register thread() + { + return rbx; + } + + virtual Register returnLow() + { + return rax; + } + + virtual Register returnHigh() + { + return (TargetBytesPerWord == 4 ? rdx : NoRegister); + } + + virtual Register virtualCallTarget() + { + return rax; + } + + virtual Register virtualCallIndex() + { + return rdx; + } + + virtual ir::TargetInfo targetInfo() + { + return ir::TargetInfo(TargetBytesPerWord); + } + + virtual bool bigEndian() + { + return false; + } + + virtual uintptr_t maximumImmediateJump() + { + return 0x7FFFFFFF; + } + + virtual bool reserved(Register register_) + { + switch (register_.index()) { + case rbp.index(): + return UseFramePointer; + + case rsp.index(): + case rbx.index(): + return true; + + default: + return false; + } + } + + virtual unsigned frameFootprint(unsigned footprint) + { +#if AVIAN_TARGET_FORMAT == AVIAN_FORMAT_PE + return max(footprint, StackAlignmentInWords); +#else + return max(footprint > argumentRegisterCount() + ? footprint - argumentRegisterCount() + : 0, + StackAlignmentInWords); +#endif + } + + virtual unsigned argumentFootprint(unsigned footprint) + { + return x86::argumentFootprint(footprint); + } + + virtual bool argumentAlignment() + { + return false; + } + + virtual bool argumentRegisterAlignment() + { + return false; + } + + virtual unsigned argumentRegisterCount() + { +#if AVIAN_TARGET_FORMAT == AVIAN_FORMAT_PE + if (TargetBytesPerWord == 8) + return 4; + else +#else + if (TargetBytesPerWord == 8) + return 6; + else +#endif + return 0; + } + + virtual Register argumentRegister(unsigned index) + { + assertT(&c, TargetBytesPerWord == 8); + switch (index) { +#if AVIAN_TARGET_FORMAT == AVIAN_FORMAT_PE + case 0: + return rcx; + case 1: + return rdx; + case 2: + return r8; + case 3: + return r9; +#else + case 0: + return rdi; + case 1: + return rsi; + case 2: + return rdx; + case 3: + return rcx; + case 4: + return r8; + case 5: + return r9; +#endif + default: + abort(&c); + } + } + + virtual bool hasLinkRegister() + { + return false; + } + + virtual unsigned stackAlignmentInWords() + { + return StackAlignmentInWords; + } + + virtual bool matchCall(void* returnAddress, void* target) + { + uint8_t* instruction = static_cast(returnAddress) - 5; + int32_t actualOffset; + memcpy(&actualOffset, instruction + 1, 4); + void* actualTarget = static_cast(returnAddress) + actualOffset; + + return *instruction == 0xE8 and actualTarget == target; + } + + virtual void updateCall(lir::UnaryOperation op, + void* returnAddress, + void* newTarget) + { + bool assertTAlignment UNUSED; + switch (op) { + case lir::AlignedCall: + op = lir::Call; + assertTAlignment = true; + break; + + case lir::AlignedJump: + op = lir::Jump; + assertTAlignment = true; + break; + + case lir::AlignedLongCall: + op = lir::LongCall; + assertTAlignment = true; + break; + + case lir::AlignedLongJump: + op = lir::LongJump; + assertTAlignment = true; + break; + + default: + assertTAlignment = false; + } + + if (TargetBytesPerWord == 4 or op == lir::Call or op == lir::Jump) { + uint8_t* instruction = static_cast(returnAddress) - 5; + + assertT( + &c, + ((op == lir::Call or op == lir::LongCall) and *instruction == 0xE8) + or ((op == lir::Jump or op == lir::LongJump) + and *instruction == 0xE9)); + + assertT(&c, + (not assertTAlignment) + or reinterpret_cast(instruction + 1) % 4 == 0); + + intptr_t v = static_cast(newTarget) + - static_cast(returnAddress); + + assertT(&c, vm::fitsInInt32(v)); + + int32_t v32 = v; + + memcpy(instruction + 1, &v32, 4); + } else { + uint8_t* instruction = static_cast(returnAddress) - 13; + + assertT(&c, instruction[0] == 0x49 and instruction[1] == 0xBA); + assertT(&c, instruction[10] == 0x41 and instruction[11] == 0xFF); + assertT(&c, + (op == lir::LongCall and instruction[12] == 0xD2) + or (op == lir::LongJump and instruction[12] == 0xE2)); + + assertT(&c, + (not assertTAlignment) + or reinterpret_cast(instruction + 2) % 8 == 0); + + memcpy(instruction + 2, &newTarget, 8); + } + } + + virtual void setConstant(void* dst, uint64_t constant) + { + target_uintptr_t v = targetVW(constant); + memcpy(dst, &v, TargetBytesPerWord); + } + + virtual unsigned alignFrameSize(unsigned sizeInWords) + { + return pad(sizeInWords + FrameHeaderSize, StackAlignmentInWords) + - FrameHeaderSize; + } + + virtual void nextFrame(void* start, + unsigned size, + unsigned footprint, + void* link, + bool mostRecent, + int targetParameterFootprint, + void** ip, + void** stack) + { + x86::nextFrame(&c, + static_cast(start), + size, + footprint, + link, + mostRecent, + targetParameterFootprint, + ip, + stack); + } + + virtual void* frameIp(void* stack) + { + return stack ? *static_cast(stack) : 0; + } + + virtual unsigned frameHeaderSize() + { + return FrameHeaderSize; + } + + virtual unsigned frameReturnAddressSize() + { + return 1; + } + + virtual unsigned frameFooterSize() + { + return 0; + } + + virtual bool alwaysCondensed(lir::BinaryOperation op) + { + switch (op) { + case lir::Float2Float: + case lir::Float2Int: + case lir::Int2Float: + case lir::FloatAbsolute: + case lir::FloatNegate: + case lir::FloatSquareRoot: + return false; + + case lir::Negate: + case lir::Absolute: + return true; + + default: + abort(&c); + } + } + + virtual bool alwaysCondensed(lir::TernaryOperation) + { + return true; + } + + virtual int returnAddressOffset() + { + return 0; + } + + virtual int framePointerOffset() + { + return UseFramePointer ? -1 : 0; + } + + virtual void plan(lir::UnaryOperation, + unsigned, + OperandMask& aMask, + bool* thunk) + { + aMask.typeMask = lir::Operand::RegisterPairMask | lir::Operand::MemoryMask + | lir::Operand::ConstantMask; + *thunk = false; + } + + virtual void planSource(lir::BinaryOperation op, + unsigned aSize, + OperandMask& aMask, + unsigned bSize, + bool* thunk) + { + aMask.setLowHighRegisterMasks(GeneralRegisterMask, GeneralRegisterMask); + + *thunk = false; + + switch (op) { + case lir::Negate: + aMask.typeMask = lir::Operand::RegisterPairMask; + aMask.setLowHighRegisterMasks(rax, rdx); + break; + + case lir::Absolute: + if (aSize <= TargetBytesPerWord) { + aMask.typeMask = lir::Operand::RegisterPairMask; + aMask.setLowHighRegisterMasks(rax, 0); + } else { + *thunk = true; + } + break; + + case lir::FloatAbsolute: + if (useSSE(&c)) { + aMask.typeMask = lir::Operand::RegisterPairMask; + aMask.setLowHighRegisterMasks(FloatRegisterMask, FloatRegisterMask); + } else { + *thunk = true; + } + break; + + case lir::FloatNegate: + // floatNegateRR does not support doubles + if (useSSE(&c) and aSize == 4 and bSize == 4) { + aMask.typeMask = lir::Operand::RegisterPairMask; + aMask.setLowHighRegisterMasks(FloatRegisterMask, 0); + } else { + *thunk = true; + } + break; + + case lir::FloatSquareRoot: + if (useSSE(&c)) { + aMask.typeMask = lir::Operand::RegisterPairMask + | lir::Operand::MemoryMask; + aMask.setLowHighRegisterMasks(FloatRegisterMask, FloatRegisterMask); + } else { + *thunk = true; + } + break; + + case lir::Float2Float: + if (useSSE(&c)) { + aMask.typeMask = lir::Operand::RegisterPairMask + | lir::Operand::MemoryMask; + aMask.setLowHighRegisterMasks(FloatRegisterMask, FloatRegisterMask); + } else { + *thunk = true; + } + break; + + case lir::Float2Int: + // todo: Java requires different semantics than SSE for + // converting floats to integers, we we need to either use + // thunks or produce inline machine code which handles edge + // cases properly. + if (false and useSSE(&c) and bSize <= TargetBytesPerWord) { + aMask.typeMask = lir::Operand::RegisterPairMask + | lir::Operand::MemoryMask; + aMask.setLowHighRegisterMasks(FloatRegisterMask, FloatRegisterMask); + } else { + *thunk = true; + } + break; + + case lir::Int2Float: + if (useSSE(&c) and aSize <= TargetBytesPerWord) { + aMask.typeMask = lir::Operand::RegisterPairMask + | lir::Operand::MemoryMask; + aMask.setLowHighRegisterMasks(GeneralRegisterMask, GeneralRegisterMask); + } else { + *thunk = true; + } + break; + + case lir::Move: + aMask.typeMask = ~0; + aMask.setLowHighRegisterMasks(AnyRegisterMask, AnyRegisterMask); + + if (TargetBytesPerWord == 4) { + if (aSize == 4 and bSize == 8) { + aMask.typeMask = lir::Operand::RegisterPairMask + | lir::Operand::MemoryMask; + const RegisterMask mask = GeneralRegisterMask + .excluding(rax).excluding(rdx); + aMask.setLowHighRegisterMasks(mask, mask); + } else if (aSize == 1 or bSize == 1) { + aMask.typeMask = lir::Operand::RegisterPairMask + | lir::Operand::MemoryMask; + const RegisterMask mask = rax | rcx | rdx | rbx; + aMask.setLowHighRegisterMasks(mask, mask); + } + } + break; + + default: + break; + } + } + + virtual void planDestination(lir::BinaryOperation op, + unsigned aSize, + const OperandMask& aMask, + unsigned bSize, + OperandMask& bMask) + { + bMask.typeMask = ~0; + bMask.setLowHighRegisterMasks(GeneralRegisterMask, GeneralRegisterMask); + + switch (op) { + case lir::Absolute: + bMask.typeMask = lir::Operand::RegisterPairMask; + bMask.setLowHighRegisterMasks(rax, 0); + break; + + case lir::FloatAbsolute: + bMask.typeMask = lir::Operand::RegisterPairMask; + bMask.lowRegisterMask = aMask.lowRegisterMask; + bMask.highRegisterMask = aMask.highRegisterMask; + break; + + case lir::Negate: + bMask.typeMask = lir::Operand::RegisterPairMask; + bMask.lowRegisterMask = aMask.lowRegisterMask; + bMask.highRegisterMask = aMask.highRegisterMask; + break; + + case lir::FloatNegate: + case lir::FloatSquareRoot: + case lir::Float2Float: + case lir::Int2Float: + bMask.typeMask = lir::Operand::RegisterPairMask; + bMask.setLowHighRegisterMasks(FloatRegisterMask, FloatRegisterMask); + break; + + case lir::Float2Int: + bMask.typeMask = lir::Operand::RegisterPairMask; + break; + + case lir::Move: + if (aMask.typeMask + & (lir::Operand::MemoryMask | lir::Operand::AddressMask)) { + bMask.typeMask = lir::Operand::RegisterPairMask; + bMask.setLowHighRegisterMasks(GeneralRegisterMask | FloatRegisterMask, GeneralRegisterMask); + } else if (aMask.typeMask & lir::Operand::RegisterPairMask) { + bMask.typeMask = lir::Operand::RegisterPairMask + | lir::Operand::MemoryMask; + if (aMask.lowRegisterMask & FloatRegisterMask) { + bMask.setLowHighRegisterMasks(FloatRegisterMask, 0); + } else { + bMask.setLowHighRegisterMasks(GeneralRegisterMask, GeneralRegisterMask); + } + } else { + bMask.typeMask = lir::Operand::RegisterPairMask + | lir::Operand::MemoryMask; + } + + if (TargetBytesPerWord == 4) { + if (aSize == 4 and bSize == 8) { + bMask.setLowHighRegisterMasks(rax, rdx); + } else if (aSize == 1 or bSize == 1) { + const RegisterMask mask = rax | rcx | rdx | rbx; + bMask.setLowHighRegisterMasks(mask, mask); + } + } + break; + + default: + break; + } + } + + virtual void planMove(unsigned size, + OperandMask& srcMask, + OperandMask& tmpMask, + const OperandMask& dstMask) + { + srcMask.typeMask = ~0; + srcMask.setLowHighRegisterMasks(AnyRegisterMask, AnyRegisterMask); + + tmpMask.typeMask = 0; + tmpMask.setLowHighRegisterMasks(0, 0); + + if (dstMask.typeMask & lir::Operand::MemoryMask) { + // can't move directly from memory to memory + srcMask.typeMask = lir::Operand::RegisterPairMask + | lir::Operand::ConstantMask; + tmpMask.typeMask = lir::Operand::RegisterPairMask; + tmpMask.setLowHighRegisterMasks(GeneralRegisterMask, GeneralRegisterMask); + } else if (dstMask.typeMask & lir::Operand::RegisterPairMask) { + if (size > TargetBytesPerWord) { + // can't move directly from FPR to GPR or vice-versa for + // values larger than the GPR size + if (dstMask.lowRegisterMask & FloatRegisterMask) { + srcMask.setLowHighRegisterMasks(FloatRegisterMask, FloatRegisterMask); + tmpMask.typeMask = lir::Operand::MemoryMask; + } else if (dstMask.lowRegisterMask & GeneralRegisterMask) { + srcMask.setLowHighRegisterMasks(GeneralRegisterMask, GeneralRegisterMask); + tmpMask.typeMask = lir::Operand::MemoryMask; + } + } + if (dstMask.lowRegisterMask & FloatRegisterMask) { + // can't move directly from constant to FPR + srcMask.typeMask &= ~lir::Operand::ConstantMask; + if (size > TargetBytesPerWord) { + tmpMask.typeMask = lir::Operand::MemoryMask; + } else { + tmpMask.typeMask = lir::Operand::RegisterPairMask + | lir::Operand::MemoryMask; + tmpMask.setLowHighRegisterMasks(GeneralRegisterMask, GeneralRegisterMask); + } + } + } + } + + virtual void planSource(lir::TernaryOperation op, + unsigned aSize, + OperandMask& aMask, + unsigned bSize, + OperandMask& bMask, + unsigned, + bool* thunk) + { + aMask.typeMask = lir::Operand::RegisterPairMask | lir::Operand::ConstantMask; + aMask.setLowHighRegisterMasks(GeneralRegisterMask, GeneralRegisterMask); + + bMask.typeMask = lir::Operand::RegisterPairMask; + bMask.setLowHighRegisterMasks(GeneralRegisterMask, GeneralRegisterMask); + + *thunk = false; + + switch (op) { + case lir::FloatAdd: + case lir::FloatSubtract: + case lir::FloatMultiply: + case lir::FloatDivide: + if (useSSE(&c)) { + aMask.typeMask = lir::Operand::RegisterPairMask + | lir::Operand::MemoryMask; + bMask.typeMask = lir::Operand::RegisterPairMask; + + aMask.setLowHighRegisterMasks(FloatRegisterMask, FloatRegisterMask); + bMask.setLowHighRegisterMasks(FloatRegisterMask, FloatRegisterMask); + } else { + *thunk = true; + } + break; + + case lir::FloatRemainder: + *thunk = true; + break; + + case lir::Multiply: + if (TargetBytesPerWord == 4 and aSize == 8) { + const RegisterMask mask = GeneralRegisterMask .excluding(rax).excluding(rdx); + aMask.setLowHighRegisterMasks(mask, mask); + bMask.setLowHighRegisterMasks(mask, rdx); + } else { + aMask.setLowHighRegisterMasks(GeneralRegisterMask, 0); + bMask.setLowHighRegisterMasks(GeneralRegisterMask, 0); + } + break; + + case lir::Divide: + if (TargetBytesPerWord == 4 and aSize == 8) { + *thunk = true; + } else { + aMask.typeMask = lir::Operand::RegisterPairMask; + aMask.setLowHighRegisterMasks(GeneralRegisterMask .excluding(rax).excluding(rdx), 0); + bMask.setLowHighRegisterMasks(rax, 0); + } + break; + + case lir::Remainder: + if (TargetBytesPerWord == 4 and aSize == 8) { + *thunk = true; + } else { + aMask.typeMask = lir::Operand::RegisterPairMask; + aMask.setLowHighRegisterMasks(GeneralRegisterMask .excluding(rax).excluding(rdx), 0); + bMask.setLowHighRegisterMasks(rax, 0); + } + break; + + case lir::ShiftLeft: + case lir::ShiftRight: + case lir::UnsignedShiftRight: { + if (TargetBytesPerWord == 4 and bSize == 8) { + const RegisterMask mask = GeneralRegisterMask.excluding(rcx); + aMask.setLowHighRegisterMasks(mask, mask); + bMask.setLowHighRegisterMasks(mask, mask); + } else { + aMask.setLowHighRegisterMasks(rcx, GeneralRegisterMask); + const RegisterMask mask = GeneralRegisterMask.excluding(rcx); + bMask.setLowHighRegisterMasks(mask, mask); + } + } break; + + case lir::JumpIfFloatEqual: + case lir::JumpIfFloatNotEqual: + case lir::JumpIfFloatLess: + case lir::JumpIfFloatGreater: + case lir::JumpIfFloatLessOrEqual: + case lir::JumpIfFloatGreaterOrEqual: + case lir::JumpIfFloatLessOrUnordered: + case lir::JumpIfFloatGreaterOrUnordered: + case lir::JumpIfFloatLessOrEqualOrUnordered: + case lir::JumpIfFloatGreaterOrEqualOrUnordered: + if (useSSE(&c)) { + aMask.typeMask = lir::Operand::RegisterPairMask; + aMask.setLowHighRegisterMasks(FloatRegisterMask, FloatRegisterMask); + bMask.typeMask = aMask.typeMask; + bMask.lowRegisterMask = aMask.lowRegisterMask; + bMask.highRegisterMask = aMask.highRegisterMask; + } else { + *thunk = true; + } + break; + + default: + break; + } + } + + virtual void planDestination(lir::TernaryOperation op, + unsigned, + const OperandMask&, + unsigned, + const OperandMask& bMask, + unsigned, + OperandMask& cMask) + { + if (isBranch(op)) { + cMask.typeMask = lir::Operand::ConstantMask; + cMask.setLowHighRegisterMasks(0, 0); + } else { + cMask.typeMask = lir::Operand::RegisterPairMask; + cMask.lowRegisterMask = bMask.lowRegisterMask; + cMask.highRegisterMask = bMask.highRegisterMask; + } + } + + virtual Assembler* makeAssembler(util::Alloc* allocator, Zone* zone); + + virtual void acquire() + { + ++referenceCount; + } + + virtual void release() + { + if (--referenceCount == 0) { + c.s->free(this); + } + } + + ArchitectureContext c; + unsigned referenceCount; + const RegisterFile myRegisterFile; +}; + +class MyAssembler : public Assembler { + public: + MyAssembler(System* s, util::Alloc* a, Zone* zone, MyArchitecture* arch) + : c(s, a, zone, &(arch->c)), arch_(arch) + { + } + + virtual void setClient(Client* client) + { + assertT(&c, c.client == 0); + c.client = client; + } + + virtual Architecture* arch() + { + return arch_; + } + + virtual void checkStackOverflow(uintptr_t handler, + unsigned stackLimitOffsetFromThread) + { + lir::RegisterPair stack(rsp); + lir::Memory stackLimit(rbx, stackLimitOffsetFromThread); + lir::Constant handlerConstant(resolvedPromise(&c, handler)); + branchRM(&c, + lir::JumpIfGreaterOrEqual, + TargetBytesPerWord, + &stack, + &stackLimit, + &handlerConstant); + } + + virtual void saveFrame(unsigned stackOffset, unsigned) + { + lir::RegisterPair stack(rsp); + lir::Memory stackDst(rbx, stackOffset); + apply(lir::Move, + OperandInfo(TargetBytesPerWord, lir::Operand::Type::RegisterPair, &stack), + OperandInfo(TargetBytesPerWord, lir::Operand::Type::Memory, &stackDst)); + } + + virtual void pushFrame(unsigned argumentCount, ...) + { + // TODO: Argument should be replaced by OperandInfo... + struct Argument { + unsigned size; + lir::Operand::Type type; + lir::Operand* operand; + }; + RUNTIME_ARRAY(Argument, arguments, argumentCount); + va_list a; + va_start(a, argumentCount); + unsigned footprint = 0; + for (unsigned i = 0; i < argumentCount; ++i) { + RUNTIME_ARRAY_BODY(arguments)[i].size = va_arg(a, unsigned); + RUNTIME_ARRAY_BODY(arguments)[i].type + = static_cast(va_arg(a, int)); + RUNTIME_ARRAY_BODY(arguments)[i].operand = va_arg(a, lir::Operand*); + footprint += ceilingDivide(RUNTIME_ARRAY_BODY(arguments)[i].size, + TargetBytesPerWord); + } + va_end(a); + + allocateFrame(arch_->alignFrameSize(footprint)); + + unsigned offset = 0; + for (unsigned i = 0; i < argumentCount; ++i) { + if (i < arch_->argumentRegisterCount()) { + lir::RegisterPair dst(arch_->argumentRegister(i)); + apply(lir::Move, + OperandInfo(RUNTIME_ARRAY_BODY(arguments)[i].size, + RUNTIME_ARRAY_BODY(arguments)[i].type, + RUNTIME_ARRAY_BODY(arguments)[i].operand), + OperandInfo(pad(RUNTIME_ARRAY_BODY(arguments)[i].size, + TargetBytesPerWord), + lir::Operand::Type::RegisterPair, + &dst)); + } else { + lir::Memory dst(rsp, offset * TargetBytesPerWord); + apply(lir::Move, + OperandInfo(RUNTIME_ARRAY_BODY(arguments)[i].size, + RUNTIME_ARRAY_BODY(arguments)[i].type, + RUNTIME_ARRAY_BODY(arguments)[i].operand), + OperandInfo(pad(RUNTIME_ARRAY_BODY(arguments)[i].size, + TargetBytesPerWord), + lir::Operand::Type::Memory, + &dst)); + offset += ceilingDivide(RUNTIME_ARRAY_BODY(arguments)[i].size, + TargetBytesPerWord); + } + } + } + + virtual void allocateFrame(unsigned footprint) + { + lir::RegisterPair stack(rsp); + + if (UseFramePointer) { + lir::RegisterPair base(rbp); + pushR(&c, TargetBytesPerWord, &base); + + apply(lir::Move, + OperandInfo(TargetBytesPerWord, lir::Operand::Type::RegisterPair, &stack), + OperandInfo(TargetBytesPerWord, lir::Operand::Type::RegisterPair, &base)); + } + + lir::Constant footprintConstant( + resolvedPromise(&c, footprint * TargetBytesPerWord)); + apply(lir::Subtract, + OperandInfo( + TargetBytesPerWord, lir::Operand::Type::Constant, &footprintConstant), + OperandInfo(TargetBytesPerWord, lir::Operand::Type::RegisterPair, &stack), + OperandInfo(TargetBytesPerWord, lir::Operand::Type::RegisterPair, &stack)); + } + + virtual void adjustFrame(unsigned difference) + { + lir::RegisterPair stack(rsp); + lir::Constant differenceConstant( + resolvedPromise(&c, difference * TargetBytesPerWord)); + apply(lir::Subtract, + OperandInfo( + TargetBytesPerWord, lir::Operand::Type::Constant, &differenceConstant), + OperandInfo(TargetBytesPerWord, lir::Operand::Type::RegisterPair, &stack), + OperandInfo(TargetBytesPerWord, lir::Operand::Type::RegisterPair, &stack)); + } + + virtual void popFrame(unsigned frameFootprint) + { + if (UseFramePointer) { + lir::RegisterPair base(rbp); + lir::RegisterPair stack(rsp); + apply(lir::Move, + OperandInfo(TargetBytesPerWord, lir::Operand::Type::RegisterPair, &base), + OperandInfo(TargetBytesPerWord, lir::Operand::Type::RegisterPair, &stack)); + + popR(&c, TargetBytesPerWord, &base); + } else { + lir::RegisterPair stack(rsp); + lir::Constant footprint( + resolvedPromise(&c, frameFootprint * TargetBytesPerWord)); + apply(lir::Add, + OperandInfo(TargetBytesPerWord, lir::Operand::Type::Constant, &footprint), + OperandInfo(TargetBytesPerWord, lir::Operand::Type::RegisterPair, &stack), + OperandInfo(TargetBytesPerWord, lir::Operand::Type::RegisterPair, &stack)); + } + } + + virtual void popFrameForTailCall(unsigned frameFootprint, + int offset, + Register returnAddressSurrogate, + Register framePointerSurrogate) + { + if (TailCalls) { + if (offset) { + lir::RegisterPair tmp(c.client->acquireTemporary()); + + unsigned baseSize = UseFramePointer ? 1 : 0; + + lir::Memory returnAddressSrc( + rsp, (frameFootprint + baseSize) * TargetBytesPerWord); + moveMR(&c, + TargetBytesPerWord, + &returnAddressSrc, + TargetBytesPerWord, + &tmp); + + lir::Memory returnAddressDst( + rsp, (frameFootprint - offset + baseSize) * TargetBytesPerWord); + moveRM(&c, + TargetBytesPerWord, + &tmp, + TargetBytesPerWord, + &returnAddressDst); + + c.client->releaseTemporary(tmp.low); + + if (UseFramePointer) { + lir::Memory baseSrc(rsp, frameFootprint * TargetBytesPerWord); + lir::RegisterPair base(rbp); + moveMR(&c, TargetBytesPerWord, &baseSrc, TargetBytesPerWord, &base); + } + + lir::RegisterPair stack(rsp); + lir::Constant footprint(resolvedPromise( + &c, (frameFootprint - offset + baseSize) * TargetBytesPerWord)); + + addCR(&c, TargetBytesPerWord, &footprint, TargetBytesPerWord, &stack); + + if (returnAddressSurrogate != NoRegister) { + assertT(&c, offset > 0); + + lir::RegisterPair ras(returnAddressSurrogate); + lir::Memory dst(rsp, offset * TargetBytesPerWord); + moveRM(&c, TargetBytesPerWord, &ras, TargetBytesPerWord, &dst); + } + + if (framePointerSurrogate != NoRegister) { + assertT(&c, offset > 0); + + lir::RegisterPair fps(framePointerSurrogate); + lir::Memory dst(rsp, (offset - 1) * TargetBytesPerWord); + moveRM(&c, TargetBytesPerWord, &fps, TargetBytesPerWord, &dst); + } + } else { + popFrame(frameFootprint); + } + } else { + abort(&c); + } + } + + virtual void popFrameAndPopArgumentsAndReturn(unsigned frameFootprint, + unsigned argumentFootprint) + { + popFrame(frameFootprint); + + assertT(&c, argumentFootprint >= StackAlignmentInWords); + assertT(&c, (argumentFootprint % StackAlignmentInWords) == 0); + + if (TailCalls and argumentFootprint > StackAlignmentInWords) { + lir::RegisterPair returnAddress(rcx); + popR(&c, TargetBytesPerWord, &returnAddress); + + lir::RegisterPair stack(rsp); + lir::Constant adjustment(resolvedPromise( + &c, + (argumentFootprint - StackAlignmentInWords) * TargetBytesPerWord)); + addCR(&c, TargetBytesPerWord, &adjustment, TargetBytesPerWord, &stack); + + jumpR(&c, TargetBytesPerWord, &returnAddress); + } else { + return_(&c); + } + } + + virtual void popFrameAndUpdateStackAndReturn(unsigned frameFootprint, + unsigned stackOffsetFromThread) + { + popFrame(frameFootprint); + + lir::RegisterPair returnAddress(rcx); + popR(&c, TargetBytesPerWord, &returnAddress); + + lir::RegisterPair stack(rsp); + lir::Memory stackSrc(rbx, stackOffsetFromThread); + moveMR(&c, TargetBytesPerWord, &stackSrc, TargetBytesPerWord, &stack); + + jumpR(&c, TargetBytesPerWord, &returnAddress); + } + + virtual void apply(lir::Operation op) + { + arch_->c.operations[op](&c); + } + + virtual void apply(lir::UnaryOperation op, OperandInfo a) + { + arch_->c.unaryOperations[Multimethod::index(op, a.type)]( + &c, a.size, a.operand); + } + + virtual void apply(lir::BinaryOperation op, OperandInfo a, OperandInfo b) + { + arch_->c.binaryOperations[index(&(arch_->c), op, a.type, b.type)]( + &c, a.size, a.operand, b.size, b.operand); + } + + virtual void apply(lir::TernaryOperation op, + OperandInfo a, + OperandInfo b, + OperandInfo c) + { + if (isBranch(op)) { + assertT(&this->c, a.size == b.size); + assertT(&this->c, c.size == TargetBytesPerWord); + assertT(&this->c, c.type == lir::Operand::Type::Constant); + + arch_->c.branchOperations[branchIndex(&(arch_->c), a.type, b.type)]( + &this->c, op, a.size, a.operand, b.operand, c.operand); + } else { + assertT(&this->c, b.size == c.size); + assertT(&this->c, b.type == c.type); + + arch_->c.binaryOperations[index(&(arch_->c), op, a.type, b.type)]( + &this->c, a.size, a.operand, b.size, b.operand); + } + } + + virtual void setDestination(uint8_t* dst) + { + c.result = dst; + } + + virtual void write() + { + uint8_t* dst = c.result; + for (MyBlock* b = c.firstBlock; b; b = b->next) { + unsigned index = 0; + unsigned padding = 0; + for (AlignmentPadding* p = b->firstPadding; p; p = p->next) { + unsigned size = p->offset - b->offset - index; + + memcpy(dst + b->start + index + padding, + c.code.data.begin() + b->offset + index, + size); + + index += size; + + while ((b->start + index + padding + p->instructionOffset) + % p->alignment) { + *(dst + b->start + index + padding) = 0x90; + ++padding; + } + } + + memcpy(dst + b->start + index + padding, + c.code.data.begin() + b->offset + index, + b->size - index); + } + + for (Task* t = c.tasks; t; t = t->next) { + t->run(&c); + } + } + + virtual Promise* offset(bool) + { + return x86::offsetPromise(&c); + } + + virtual Block* endBlock(bool startNew) + { + MyBlock* b = c.lastBlock; + b->size = c.code.length() - b->offset; + if (startNew) { + c.lastBlock = new (c.zone) MyBlock(c.code.length()); + } else { + c.lastBlock = 0; + } + return b; + } + + virtual void endEvent() + { + // ignore + } + + virtual unsigned length() + { + return c.code.length(); + } + + virtual unsigned footerSize() + { + return 0; + } + + virtual void dispose() + { + c.code.dispose(); + } + + Context c; + MyArchitecture* arch_; +}; + +Assembler* MyArchitecture::makeAssembler(util::Alloc* allocator, Zone* zone) +{ + return new (zone) MyAssembler(c.s, allocator, zone, this); +} + +} // namespace x86 + +Architecture* makeArchitectureX86(System* system, bool useNativeFeatures) +{ + return new (allocate(system, sizeof(x86::MyArchitecture))) + x86::MyArchitecture(system, useNativeFeatures); +} + +} // namespace codegen +} // namespace avian diff --git a/sgx-jvm/avian/src/codegen/target/x86/block.cpp b/sgx-jvm/avian/src/codegen/target/x86/block.cpp new file mode 100644 index 0000000000..5d2d46d6fe --- /dev/null +++ b/sgx-jvm/avian/src/codegen/target/x86/block.cpp @@ -0,0 +1,44 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#include "block.h" + +#include + +namespace avian { +namespace codegen { +namespace x86 { + +unsigned padding(AlignmentPadding* p, + unsigned index, + unsigned offset, + AlignmentPadding* limit); + +MyBlock::MyBlock(unsigned offset) + : next(0), + firstPadding(0), + lastPadding(0), + offset(offset), + start(~0), + size(0) +{ +} + +unsigned MyBlock::resolve(unsigned start, Assembler::Block* next) +{ + this->start = start; + this->next = static_cast(next); + + return start + size + padding(firstPadding, start, offset, lastPadding); +} + +} // namespace x86 +} // namespace codegen +} // namespace avian diff --git a/sgx-jvm/avian/src/codegen/target/x86/block.h b/sgx-jvm/avian/src/codegen/target/x86/block.h new file mode 100644 index 0000000000..6841f5d577 --- /dev/null +++ b/sgx-jvm/avian/src/codegen/target/x86/block.h @@ -0,0 +1,40 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#ifndef AVIAN_CODEGEN_ASSEMBLER_X86_BLOCK_H +#define AVIAN_CODEGEN_ASSEMBLER_X86_BLOCK_H + +#include + +namespace avian { +namespace codegen { +namespace x86 { + +class AlignmentPadding; + +class MyBlock : public Assembler::Block { + public: + MyBlock(unsigned offset); + + virtual unsigned resolve(unsigned start, Assembler::Block* next); + + MyBlock* next; + AlignmentPadding* firstPadding; + AlignmentPadding* lastPadding; + unsigned offset; + unsigned start; + unsigned size; +}; + +} // namespace x86 +} // namespace codegen +} // namespace avian + +#endif // AVIAN_CODEGEN_ASSEMBLER_X86_BLOCK_H diff --git a/sgx-jvm/avian/src/codegen/target/x86/context.cpp b/sgx-jvm/avian/src/codegen/target/x86/context.cpp new file mode 100644 index 0000000000..37d742c47c --- /dev/null +++ b/sgx-jvm/avian/src/codegen/target/x86/context.cpp @@ -0,0 +1,44 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#include "avian/util/allocator.h" +#include "avian/zone.h" + +#include "context.h" +#include "block.h" + +namespace avian { +namespace codegen { +namespace x86 { + +ArchitectureContext::ArchitectureContext(vm::System* s, bool useNativeFeatures) + : s(s), useNativeFeatures(useNativeFeatures) +{ +} + +Context::Context(vm::System* s, + util::Alloc* a, + vm::Zone* zone, + ArchitectureContext* ac) + : s(s), + zone(zone), + client(0), + code(s, a, 1024), + tasks(0), + result(0), + firstBlock(new (zone) MyBlock(0)), + lastBlock(firstBlock), + ac(ac) +{ +} + +} // namespace x86 +} // namespace codegen +} // namespace avian diff --git a/sgx-jvm/avian/src/codegen/target/x86/context.h b/sgx-jvm/avian/src/codegen/target/x86/context.h new file mode 100644 index 0000000000..ac8d267012 --- /dev/null +++ b/sgx-jvm/avian/src/codegen/target/x86/context.h @@ -0,0 +1,112 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#ifndef AVIAN_CODEGEN_ASSEMBLER_X86_CONTEXT_H +#define AVIAN_CODEGEN_ASSEMBLER_X86_CONTEXT_H + +#define CAST1(x) reinterpret_cast(x) +#define CAST2(x) reinterpret_cast(x) +#define CAST_BRANCH(x) reinterpret_cast(x) + +#include + +#include "avian/alloc-vector.h" + +#include +#include + +#include + +namespace vm { +class System; +class Alloc; +class Zone; +} // namespace vm + +namespace avian { + +namespace util { +class Aborter; +} // namespace util + +namespace codegen { +namespace x86 { + +class Context; +class MyBlock; +class Task; + +typedef void (*OperationType)(Context*); + +typedef void (*UnaryOperationType)(Context*, unsigned, lir::Operand*); + +typedef void (*BinaryOperationType)(Context*, + unsigned, + lir::Operand*, + unsigned, + lir::Operand*); + +typedef void (*BranchOperationType)(Context*, + lir::TernaryOperation, + unsigned, + lir::Operand*, + lir::Operand*, + lir::Operand*); + +class ArchitectureContext { + public: + ArchitectureContext(vm::System* s, bool useNativeFeatures); + + vm::System* s; + bool useNativeFeatures; + OperationType operations[lir::OperationCount]; + UnaryOperationType + unaryOperations[lir::UnaryOperationCount * lir::Operand::TypeCount]; + BinaryOperationType binaryOperations + [(lir::BinaryOperationCount + lir::NonBranchTernaryOperationCount) + * lir::Operand::TypeCount * lir::Operand::TypeCount]; + BranchOperationType branchOperations[lir::BranchOperationCount + * lir::Operand::TypeCount + * lir::Operand::TypeCount]; +}; + +class Context { + public: + Context(vm::System* s, + util::Alloc* a, + vm::Zone* zone, + ArchitectureContext* ac); + + vm::System* s; + vm::Zone* zone; + Assembler::Client* client; + vm::Vector code; + Task* tasks; + uint8_t* result; + MyBlock* firstBlock; + MyBlock* lastBlock; + ArchitectureContext* ac; +}; + +inline avian::util::Aborter* getAborter(Context* c) +{ + return c->s; +} + +inline avian::util::Aborter* getAborter(ArchitectureContext* c) +{ + return c->s; +} + +} // namespace x86 +} // namespace codegen +} // namespace avian + +#endif // AVIAN_CODEGEN_ASSEMBLER_X86_CONTEXT_H diff --git a/sgx-jvm/avian/src/codegen/target/x86/detect.cpp b/sgx-jvm/avian/src/codegen/target/x86/detect.cpp new file mode 100644 index 0000000000..52ecc2f293 --- /dev/null +++ b/sgx-jvm/avian/src/codegen/target/x86/detect.cpp @@ -0,0 +1,83 @@ + +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#include "avian/target.h" + +#include "context.h" + +// Note: this is so that we can build the x86 backend(s) on an arm machine. +// This way, we could (in theory) do a bootimage cross-compile from arm to x86 +#ifndef __arm__ + +#ifndef _MSC_VER +#include +#else +// MSVC implementation: +static int __get_cpuid(unsigned int __level, + unsigned int* __eax, + unsigned int* __ebx, + unsigned int* __ecx, + unsigned int* __edx) +{ + _asm + { + mov eax, __level; + cpuid; + mov[__eax], eax; + mov[__ebx], ebx; + mov[__ecx], ecx; + mov[__edx], edx; + } + return 1; +} +#define bit_SSE (1 << 25) +#define bit_SSE2 (1 << 26) + +#endif // ndef _MSC_VER + +#endif // ndef __arm__ + +namespace avian { +namespace codegen { +namespace x86 { + +// TODO: this should be moved such that it's called by the client (e.g. whatever +// allocates the Archivecture). That way, we can link the x86 code generator on +// another architecture (e.g. arm). + +bool useSSE(ArchitectureContext* c) +{ +#ifdef __arm__ + // We can't link in the detection code on arm (DUH!) + return vm::TargetBytesPerWord == 8; +#else + if (vm::TargetBytesPerWord == 8) { + // amd64 implies SSE2 support + return true; + } else if (c->useNativeFeatures) { + static int supported = -1; + if (supported == -1) { + unsigned eax; + unsigned ebx; + unsigned ecx; + unsigned edx; + supported = __get_cpuid(1, &eax, &ebx, &ecx, &edx) && (edx & bit_SSE) && (edx & bit_SSE2); + } + return supported; + } else { + return false; + } +#endif +} + +} // namespace x86 +} // namespace codegen +} // namespace avian diff --git a/sgx-jvm/avian/src/codegen/target/x86/detect.h b/sgx-jvm/avian/src/codegen/target/x86/detect.h new file mode 100644 index 0000000000..f8014ab1da --- /dev/null +++ b/sgx-jvm/avian/src/codegen/target/x86/detect.h @@ -0,0 +1,28 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#ifndef AVIAN_CODEGEN_ASSEMBLER_X86_DETECT_H +#define AVIAN_CODEGEN_ASSEMBLER_X86_DETECT_H + +#include + +namespace avian { +namespace codegen { +namespace x86 { + +class ArchitectureContext; + +bool useSSE(ArchitectureContext* c); + +} // namespace x86 +} // namespace codegen +} // namespace avian + +#endif // AVIAN_CODEGEN_ASSEMBLER_X86_DETECT_H diff --git a/sgx-jvm/avian/src/codegen/target/x86/encode.cpp b/sgx-jvm/avian/src/codegen/target/x86/encode.cpp new file mode 100644 index 0000000000..38313660f8 --- /dev/null +++ b/sgx-jvm/avian/src/codegen/target/x86/encode.cpp @@ -0,0 +1,432 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#include "avian/target.h" +#include "avian/alloc-vector.h" + +#include +#include + +#include +#include + +#include "context.h" +#include "encode.h" +#include "registers.h" +#include "fixup.h" + +using namespace avian::util; + +namespace { + +int64_t signExtend(unsigned size, int64_t v) +{ + if (size == 4) { + return static_cast(v); + } else if (size == 2) { + return static_cast(v); + } else if (size == 1) { + return static_cast(v); + } else { + return v; + } +} + +} // namespace + +namespace avian { +namespace codegen { +namespace x86 { + +#define REX_W 0x48 +#define REX_R 0x44 +#define REX_X 0x42 +#define REX_B 0x41 +#define REX_NONE 0x40 + +void maybeRex(Context* c, + unsigned size, + Register a, + Register index, + Register base, + bool always) +{ + if (vm::TargetBytesPerWord == 8) { + uint8_t byte; + if (size == 8) { + byte = REX_W; + } else { + byte = REX_NONE; + } + if (a != NoRegister and (a.index() & 8)) + byte |= REX_R; + if (index != NoRegister and (index.index() & 8)) + byte |= REX_X; + if (base != NoRegister and (base.index() & 8)) + byte |= REX_B; + if (always or byte != REX_NONE) + c->code.append(byte); + } +} + +void maybeRex(Context* c, unsigned size, lir::RegisterPair* a, lir::RegisterPair* b) +{ + maybeRex(c, size, a->low, NoRegister, b->low, false); +} + +void alwaysRex(Context* c, unsigned size, lir::RegisterPair* a, lir::RegisterPair* b) +{ + maybeRex(c, size, a->low, NoRegister, b->low, true); +} + +void maybeRex(Context* c, unsigned size, lir::RegisterPair* a) +{ + maybeRex(c, size, NoRegister, NoRegister, a->low, false); +} + +void maybeRex(Context* c, unsigned size, lir::RegisterPair* a, lir::Memory* b) +{ + maybeRex(c, size, a->low, b->index, b->base, size == 1 and (a->low.index() & 4)); +} + +void maybeRex(Context* c, unsigned size, lir::Memory* a) +{ + maybeRex(c, size, NoRegister, a->index, a->base, false); +} + +void modrm(Context* c, uint8_t mod, Register a, Register b) +{ + c->code.append(mod | (regCode(b) << 3) | regCode(a)); +} + +void modrm(Context* c, uint8_t mod, lir::RegisterPair* a, lir::RegisterPair* b) +{ + modrm(c, mod, a->low, b->low); +} + +void sib(Context* c, unsigned scale, Register index, Register base) +{ + c->code.append((util::log(scale) << 6) | (regCode(index) << 3) + | regCode(base)); +} + +void modrmSib(Context* c, int width, Register a, int scale, Register index, Register base) +{ + if (index == NoRegister) { + modrm(c, width, base, a); + if (regCode(base) == rsp.index()) { + sib(c, 0x00, rsp, rsp); + } + } else { + modrm(c, width, rsp, a); + sib(c, scale, index, base); + } +} + +void modrmSibImm(Context* c, Register a, int scale, Register index, Register base, int offset) +{ + if (offset == 0 and regCode(base) != rbp.index()) { + modrmSib(c, 0x00, a, scale, index, base); + } else if (vm::fitsInInt8(offset)) { + modrmSib(c, 0x40, a, scale, index, base); + c->code.append(offset); + } else { + modrmSib(c, 0x80, a, scale, index, base); + c->code.append4(offset); + } +} + +void modrmSibImm(Context* c, lir::RegisterPair* a, lir::Memory* b) +{ + modrmSibImm(c, a->low, b->scale, b->index, b->base, b->offset); +} + +void opcode(Context* c, uint8_t op) +{ + c->code.append(op); +} + +void opcode(Context* c, uint8_t op1, uint8_t op2) +{ + c->code.append(op1); + c->code.append(op2); +} + +void unconditional(Context* c, unsigned jump, lir::Constant* a) +{ + appendOffsetTask(c, a->value, offsetPromise(c), 5); + + opcode(c, jump); + c->code.append4(0); +} + +void conditional(Context* c, unsigned condition, lir::Constant* a) +{ + appendOffsetTask(c, a->value, offsetPromise(c), 6); + + opcode(c, 0x0f, condition); + c->code.append4(0); +} + +void sseMoveRR(Context* c, + unsigned aSize, + lir::RegisterPair* a, + unsigned bSize UNUSED, + lir::RegisterPair* b) +{ + assertT(c, aSize >= 4); + assertT(c, aSize == bSize); + + if (isFloatReg(a) and isFloatReg(b)) { + if (aSize == 4) { + opcode(c, 0xf3); + maybeRex(c, 4, a, b); + opcode(c, 0x0f, 0x10); + modrm(c, 0xc0, a, b); + } else { + opcode(c, 0xf2); + maybeRex(c, 4, b, a); + opcode(c, 0x0f, 0x10); + modrm(c, 0xc0, a, b); + } + } else if (isFloatReg(a)) { + opcode(c, 0x66); + maybeRex(c, aSize, a, b); + opcode(c, 0x0f, 0x7e); + modrm(c, 0xc0, b, a); + } else { + opcode(c, 0x66); + maybeRex(c, aSize, b, a); + opcode(c, 0x0f, 0x6e); + modrm(c, 0xc0, a, b); + } +} + +void sseMoveCR(Context* c, + unsigned aSize, + lir::Constant* a, + unsigned bSize, + lir::RegisterPair* b) +{ + assertT(c, aSize <= vm::TargetBytesPerWord); + lir::RegisterPair tmp(c->client->acquireTemporary(GeneralRegisterMask)); + moveCR2(c, aSize, a, aSize, &tmp, 0); + sseMoveRR(c, aSize, &tmp, bSize, b); + c->client->releaseTemporary(tmp.low); +} + +void sseMoveMR(Context* c, + unsigned aSize, + lir::Memory* a, + unsigned bSize UNUSED, + lir::RegisterPair* b) +{ + assertT(c, aSize >= 4); + + if (vm::TargetBytesPerWord == 4 and aSize == 8) { + opcode(c, 0xf3); + opcode(c, 0x0f, 0x7e); + modrmSibImm(c, b, a); + } else { + opcode(c, 0x66); + maybeRex(c, aSize, b, a); + opcode(c, 0x0f, 0x6e); + modrmSibImm(c, b, a); + } +} + +void sseMoveRM(Context* c, + unsigned aSize, + lir::RegisterPair* a, + UNUSED unsigned bSize, + lir::Memory* b) +{ + assertT(c, aSize >= 4); + assertT(c, aSize == bSize); + + if (vm::TargetBytesPerWord == 4 and aSize == 8) { + opcode(c, 0x66); + opcode(c, 0x0f, 0xd6); + modrmSibImm(c, a, b); + } else { + opcode(c, 0x66); + maybeRex(c, aSize, a, b); + opcode(c, 0x0f, 0x7e); + modrmSibImm(c, a, b); + } +} + +void branch(Context* c, lir::TernaryOperation op, lir::Constant* target) +{ + switch (op) { + case lir::JumpIfEqual: + conditional(c, 0x84, target); + break; + + case lir::JumpIfNotEqual: + conditional(c, 0x85, target); + break; + + case lir::JumpIfLess: + conditional(c, 0x8c, target); + break; + + case lir::JumpIfGreater: + conditional(c, 0x8f, target); + break; + + case lir::JumpIfLessOrEqual: + conditional(c, 0x8e, target); + break; + + case lir::JumpIfGreaterOrEqual: + conditional(c, 0x8d, target); + break; + + default: + abort(c); + } +} + +void branchFloat(Context* c, lir::TernaryOperation op, lir::Constant* target) +{ + switch (op) { + case lir::JumpIfFloatEqual: + // jp past the je so we don't jump to the target if unordered: + c->code.append(0x7a); + c->code.append(6); + conditional(c, 0x84, target); + break; + + case lir::JumpIfFloatNotEqual: + conditional(c, 0x85, target); + conditional(c, 0x8a, target); + break; + + case lir::JumpIfFloatLess: + conditional(c, 0x82, target); + break; + + case lir::JumpIfFloatGreater: + conditional(c, 0x87, target); + break; + + case lir::JumpIfFloatLessOrEqual: + conditional(c, 0x86, target); + break; + + case lir::JumpIfFloatGreaterOrEqual: + conditional(c, 0x83, target); + break; + + case lir::JumpIfFloatLessOrUnordered: + conditional(c, 0x82, target); + conditional(c, 0x8a, target); + break; + + case lir::JumpIfFloatGreaterOrUnordered: + conditional(c, 0x87, target); + conditional(c, 0x8a, target); + break; + + case lir::JumpIfFloatLessOrEqualOrUnordered: + conditional(c, 0x86, target); + conditional(c, 0x8a, target); + break; + + case lir::JumpIfFloatGreaterOrEqualOrUnordered: + conditional(c, 0x83, target); + conditional(c, 0x8a, target); + break; + + default: + abort(c); + } +} + +void floatRegOp(Context* c, + unsigned aSize, + lir::RegisterPair* a, + unsigned bSize, + lir::RegisterPair* b, + uint8_t op, + uint8_t mod) +{ + if (aSize == 4) { + opcode(c, 0xf3); + } else { + opcode(c, 0xf2); + } + maybeRex(c, bSize, b, a); + opcode(c, 0x0f, op); + modrm(c, mod, a, b); +} + +void floatMemOp(Context* c, + unsigned aSize, + lir::Memory* a, + unsigned bSize, + lir::RegisterPair* b, + uint8_t op) +{ + if (aSize == 4) { + opcode(c, 0xf3); + } else { + opcode(c, 0xf2); + } + maybeRex(c, bSize, b, a); + opcode(c, 0x0f, op); + modrmSibImm(c, b, a); +} + +void moveCR(Context* c, + unsigned aSize, + lir::Constant* a, + unsigned bSize, + lir::RegisterPair* b); + +void moveCR2(Context* c, + UNUSED unsigned aSize, + lir::Constant* a, + UNUSED unsigned bSize, + lir::RegisterPair* b, + unsigned promiseOffset) +{ + if (vm::TargetBytesPerWord == 4 and bSize == 8) { + int64_t v = signExtend(aSize, a->value->value()); + + ResolvedPromise high((v >> 32) & 0xFFFFFFFF); + lir::Constant ah(&high); + + ResolvedPromise low(v & 0xFFFFFFFF); + lir::Constant al(&low); + + lir::RegisterPair bh(b->high); + + moveCR(c, 4, &al, 4, b); + moveCR(c, 4, &ah, 4, &bh); + } else { + maybeRex(c, vm::TargetBytesPerWord, b); + opcode(c, 0xb8 + regCode(b)); + if (a->value->resolved()) { + c->code.appendTargetAddress(signExtend(aSize, a->value->value())); + } else { + expect(c, aSize == vm::TargetBytesPerWord); + + appendImmediateTask( + c, a->value, offsetPromise(c), vm::TargetBytesPerWord, promiseOffset); + c->code.appendTargetAddress(static_cast(0)); + } + } +} + +} // namespace x86 +} // namespace codegen +} // namespace avian diff --git a/sgx-jvm/avian/src/codegen/target/x86/encode.h b/sgx-jvm/avian/src/codegen/target/x86/encode.h new file mode 100644 index 0000000000..cb107cbbcc --- /dev/null +++ b/sgx-jvm/avian/src/codegen/target/x86/encode.h @@ -0,0 +1,134 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#ifndef AVIAN_CODEGEN_ASSEMBLER_X86_ENCODE_H +#define AVIAN_CODEGEN_ASSEMBLER_X86_ENCODE_H + +#include + +#include "avian/common.h" + +#include + +#include "registers.h" + +namespace avian { +namespace codegen { +namespace x86 { + +class Context; + +void maybeRex(Context* c, + unsigned size, + int a, + int index, + int base, + bool always); + +void maybeRex(Context* c, unsigned size, lir::RegisterPair* a, lir::RegisterPair* b); + +void alwaysRex(Context* c, unsigned size, lir::RegisterPair* a, lir::RegisterPair* b); + +void maybeRex(Context* c, unsigned size, lir::RegisterPair* a); + +void maybeRex(Context* c, unsigned size, lir::RegisterPair* a, lir::Memory* b); + +void maybeRex(Context* c, unsigned size, lir::Memory* a); + +inline int regCode(Register a) +{ + return a.index() & 7; +} + +inline int regCode(lir::RegisterPair* a) +{ + return regCode(a->low); +} + +inline bool isFloatReg(lir::RegisterPair* a) +{ + return a->low >= xmm0; +} + +void modrm(Context* c, uint8_t mod, Register a, Register b); + +void modrm(Context* c, uint8_t mod, lir::RegisterPair* a, lir::RegisterPair* b); + +void sib(Context* c, unsigned scale, Register index, Register base); + +void modrmSib(Context* c, int width, Register a, int scale, Register index, Register base); + +void modrmSibImm(Context* c, Register a, int scale, Register index, Register base, int offset); + +void modrmSibImm(Context* c, lir::RegisterPair* a, lir::Memory* b); + +void opcode(Context* c, uint8_t op); + +void opcode(Context* c, uint8_t op1, uint8_t op2); + +void unconditional(Context* c, unsigned jump, lir::Constant* a); + +void conditional(Context* c, unsigned condition, lir::Constant* a); + +void sseMoveRR(Context* c, + unsigned aSize, + lir::RegisterPair* a, + unsigned bSize UNUSED, + lir::RegisterPair* b); + +void sseMoveCR(Context* c, + unsigned aSize, + lir::Constant* a, + unsigned bSize, + lir::RegisterPair* b); + +void sseMoveMR(Context* c, + unsigned aSize, + lir::Memory* a, + unsigned bSize UNUSED, + lir::RegisterPair* b); + +void sseMoveRM(Context* c, + unsigned aSize, + lir::RegisterPair* a, + UNUSED unsigned bSize, + lir::Memory* b); + +void branch(Context* c, lir::TernaryOperation op, lir::Constant* target); + +void branchFloat(Context* c, lir::TernaryOperation op, lir::Constant* target); + +void floatRegOp(Context* c, + unsigned aSize, + lir::RegisterPair* a, + unsigned bSize, + lir::RegisterPair* b, + uint8_t op, + uint8_t mod = 0xc0); + +void floatMemOp(Context* c, + unsigned aSize, + lir::Memory* a, + unsigned bSize, + lir::RegisterPair* b, + uint8_t op); + +void moveCR2(Context* c, + UNUSED unsigned aSize, + lir::Constant* a, + UNUSED unsigned bSize, + lir::RegisterPair* b, + unsigned promiseOffset); + +} // namespace x86 +} // namespace codegen +} // namespace avian + +#endif // AVIAN_CODEGEN_ASSEMBLER_X86_ENCODE_H diff --git a/sgx-jvm/avian/src/codegen/target/x86/fixup.cpp b/sgx-jvm/avian/src/codegen/target/x86/fixup.cpp new file mode 100644 index 0000000000..788d773afe --- /dev/null +++ b/sgx-jvm/avian/src/codegen/target/x86/fixup.cpp @@ -0,0 +1,209 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#include + +#include "avian/util/allocator.h" +#include "avian/alloc-vector.h" +#include "avian/common.h" +#include "avian/zone.h" + +#include +#include + +#include "context.h" +#include "fixup.h" +#include "padding.h" +#include "block.h" + +namespace avian { +namespace codegen { +namespace x86 { + +using namespace util; + +ResolvedPromise* resolvedPromise(Context* c, int64_t value) +{ + return new (c->zone) ResolvedPromise(value); +} + +OffsetPromise::OffsetPromise(Context* c, + MyBlock* block, + unsigned offset, + AlignmentPadding* limit) + : c(c), block(block), offset(offset), limit(limit), value_(-1) +{ +} + +bool OffsetPromise::resolved() +{ + return block->start != static_cast(~0); +} + +int64_t OffsetPromise::value() +{ + assertT(c, resolved()); + + if (value_ == -1) { + value_ = block->start + (offset - block->offset) + + padding(block->firstPadding, block->start, block->offset, limit); + } + + return value_; +} +Promise* offsetPromise(Context* c) +{ + return new (c->zone) OffsetPromise( + c, c->lastBlock, c->code.length(), c->lastBlock->lastPadding); +} + +void* resolveOffset(vm::System* s, + uint8_t* instruction, + unsigned instructionSize, + int64_t value) +{ + intptr_t v = reinterpret_cast(value) - instruction + - instructionSize; + + expect(s, vm::fitsInInt32(v)); + + int32_t v4 = v; + memcpy(instruction + instructionSize - 4, &v4, 4); + return instruction + instructionSize; +} + +OffsetListener::OffsetListener(vm::System* s, + uint8_t* instruction, + unsigned instructionSize) + : s(s), instruction(instruction), instructionSize(instructionSize) +{ +} + +bool OffsetListener::resolve(int64_t value, void** location) +{ + void* p = resolveOffset(s, instruction, instructionSize, value); + if (location) + *location = p; + return false; +} + +OffsetTask::OffsetTask(Task* next, + Promise* promise, + Promise* instructionOffset, + unsigned instructionSize) + : Task(next), + promise(promise), + instructionOffset(instructionOffset), + instructionSize(instructionSize) +{ +} + +void OffsetTask::run(Context* c) +{ + if (promise->resolved()) { + resolveOffset(c->s, + c->result + instructionOffset->value(), + instructionSize, + promise->value()); + } else { + new (promise->listen(sizeof(OffsetListener))) OffsetListener( + c->s, c->result + instructionOffset->value(), instructionSize); + } +} + +void appendOffsetTask(Context* c, + Promise* promise, + Promise* instructionOffset, + unsigned instructionSize) +{ + OffsetTask* task = new (c->zone) + OffsetTask(c->tasks, promise, instructionOffset, instructionSize); + + c->tasks = task; +} + +ImmediateListener::ImmediateListener(vm::System* s, + void* dst, + unsigned size, + unsigned offset) + : s(s), dst(dst), size(size), offset(offset) +{ +} + +void copy(vm::System* s, void* dst, int64_t src, unsigned size) +{ + switch (size) { + case 4: { + int32_t v = src; + memcpy(dst, &v, 4); + } break; + + case 8: { + int64_t v = src; + memcpy(dst, &v, 8); + } break; + + default: + abort(s); + } +} + +bool ImmediateListener::resolve(int64_t value, void** location) +{ + copy(s, dst, value, size); + if (location) + *location = static_cast(dst) + offset; + return offset == 0; +} + +ImmediateTask::ImmediateTask(Task* next, + Promise* promise, + Promise* offset, + unsigned size, + unsigned promiseOffset) + : Task(next), + promise(promise), + offset(offset), + size(size), + promiseOffset(promiseOffset) +{ +} + +void ImmediateTask::run(Context* c) +{ + if (promise->resolved()) { + copy(c->s, c->result + offset->value(), promise->value(), size); + } else { + new (promise->listen(sizeof(ImmediateListener))) ImmediateListener( + c->s, c->result + offset->value(), size, promiseOffset); + } +} + +void appendImmediateTask(Context* c, + Promise* promise, + Promise* offset, + unsigned size, + unsigned promiseOffset) +{ + c->tasks = new (c->zone) + ImmediateTask(c->tasks, promise, offset, size, promiseOffset); +} + +ShiftMaskPromise* shiftMaskPromise(Context* c, + Promise* base, + unsigned shift, + int64_t mask) +{ + return new (c->zone) ShiftMaskPromise(base, shift, mask); +} + +} // namespace x86 +} // namespace codegen +} // namespace avian diff --git a/sgx-jvm/avian/src/codegen/target/x86/fixup.h b/sgx-jvm/avian/src/codegen/target/x86/fixup.h new file mode 100644 index 0000000000..68c6d1fe0d --- /dev/null +++ b/sgx-jvm/avian/src/codegen/target/x86/fixup.h @@ -0,0 +1,141 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#ifndef AVIAN_CODEGEN_ASSEMBLER_X86_FIXUP_H +#define AVIAN_CODEGEN_ASSEMBLER_X86_FIXUP_H + +#include + +#include + +namespace vm { +class System; +} + +namespace avian { +namespace codegen { +namespace x86 { + +class Context; +class MyBlock; +class AlignmentPadding; + +ResolvedPromise* resolvedPromise(Context* c, int64_t value); + +class Task { + public: + Task(Task* next) : next(next) + { + } + + virtual void run(Context* c) = 0; + + Task* next; +}; + +class OffsetPromise : public Promise { + public: + OffsetPromise(Context* c, + MyBlock* block, + unsigned offset, + AlignmentPadding* limit); + + virtual bool resolved(); + + virtual int64_t value(); + + Context* c; + MyBlock* block; + unsigned offset; + AlignmentPadding* limit; + int value_; +}; + +Promise* offsetPromise(Context* c); + +void* resolveOffset(vm::System* s, + uint8_t* instruction, + unsigned instructionSize, + int64_t value); + +class OffsetListener : public Promise::Listener { + public: + OffsetListener(vm::System* s, uint8_t* instruction, unsigned instructionSize); + + virtual bool resolve(int64_t value, void** location); + + vm::System* s; + uint8_t* instruction; + unsigned instructionSize; +}; + +class OffsetTask : public Task { + public: + OffsetTask(Task* next, + Promise* promise, + Promise* instructionOffset, + unsigned instructionSize); + + virtual void run(Context* c); + + Promise* promise; + Promise* instructionOffset; + unsigned instructionSize; +}; + +void appendOffsetTask(Context* c, + Promise* promise, + Promise* instructionOffset, + unsigned instructionSize); + +class ImmediateListener : public Promise::Listener { + public: + ImmediateListener(vm::System* s, void* dst, unsigned size, unsigned offset); + + virtual bool resolve(int64_t value, void** location); + + vm::System* s; + void* dst; + unsigned size; + unsigned offset; +}; + +class ImmediateTask : public Task { + public: + ImmediateTask(Task* next, + Promise* promise, + Promise* offset, + unsigned size, + unsigned promiseOffset); + + virtual void run(Context* c); + + Promise* promise; + Promise* offset; + unsigned size; + unsigned promiseOffset; +}; + +void appendImmediateTask(Context* c, + Promise* promise, + Promise* offset, + unsigned size, + unsigned promiseOffset = 0); + +ShiftMaskPromise* shiftMaskPromise(Context* c, + Promise* base, + unsigned shift, + int64_t mask); + +} // namespace x86 +} // namespace codegen +} // namespace avian + +#endif // AVIAN_CODEGEN_ASSEMBLER_X86_FIXUP_H diff --git a/sgx-jvm/avian/src/codegen/target/x86/multimethod.cpp b/sgx-jvm/avian/src/codegen/target/x86/multimethod.cpp new file mode 100644 index 0000000000..9eae71bada --- /dev/null +++ b/sgx-jvm/avian/src/codegen/target/x86/multimethod.cpp @@ -0,0 +1,180 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#include "avian/common.h" + +#include + +#include + +#include "context.h" +#include "operations.h" + +#include "multimethod.h" +#include "../multimethod.h" + +namespace avian { +namespace codegen { +namespace x86 { + +using namespace util; + +unsigned index(ArchitectureContext*, + lir::BinaryOperation operation, + lir::Operand::Type operand1, + lir::Operand::Type operand2) +{ + return operation + ((lir::BinaryOperationCount + + lir::NonBranchTernaryOperationCount) * (unsigned)operand1) + + ((lir::BinaryOperationCount + lir::NonBranchTernaryOperationCount) + * lir::Operand::TypeCount * (unsigned)operand2); +} + +unsigned index(ArchitectureContext* c UNUSED, + lir::TernaryOperation operation, + lir::Operand::Type operand1, + lir::Operand::Type operand2) +{ + assertT(c, not isBranch(operation)); + + return lir::BinaryOperationCount + operation + + ((lir::BinaryOperationCount + lir::NonBranchTernaryOperationCount) + * (unsigned)operand1) + + ((lir::BinaryOperationCount + lir::NonBranchTernaryOperationCount) + * lir::Operand::TypeCount * (unsigned)operand2); +} + +unsigned branchIndex(ArchitectureContext* c UNUSED, + lir::Operand::Type operand1, + lir::Operand::Type operand2) +{ + return (unsigned)operand1 + (lir::Operand::TypeCount * (unsigned)operand2); +} + +void populateTables(ArchitectureContext* c) +{ + const lir::Operand::Type C = lir::Operand::Type::Constant; + const lir::Operand::Type A = lir::Operand::Type::Address; + const lir::Operand::Type R = lir::Operand::Type::RegisterPair; + const lir::Operand::Type M = lir::Operand::Type::Memory; + + OperationType* zo = c->operations; + UnaryOperationType* uo = c->unaryOperations; + BinaryOperationType* bo = c->binaryOperations; + BranchOperationType* bro = c->branchOperations; + + zo[lir::Return] = return_; + zo[lir::LoadBarrier] = ignore; + zo[lir::StoreStoreBarrier] = ignore; + zo[lir::StoreLoadBarrier] = storeLoadBarrier; + zo[lir::Trap] = trap; + + uo[Multimethod::index(lir::Call, C)] = CAST1(callC); + uo[Multimethod::index(lir::Call, R)] = CAST1(callR); + uo[Multimethod::index(lir::Call, M)] = CAST1(callM); + + uo[Multimethod::index(lir::AlignedCall, C)] = CAST1(alignedCallC); + + uo[Multimethod::index(lir::LongCall, C)] = CAST1(longCallC); + + uo[Multimethod::index(lir::AlignedLongCall, C)] = CAST1(alignedLongCallC); + + uo[Multimethod::index(lir::Jump, R)] = CAST1(jumpR); + uo[Multimethod::index(lir::Jump, C)] = CAST1(jumpC); + uo[Multimethod::index(lir::Jump, M)] = CAST1(jumpM); + + uo[Multimethod::index(lir::AlignedJump, C)] = CAST1(alignedJumpC); + + uo[Multimethod::index(lir::LongJump, C)] = CAST1(longJumpC); + + uo[Multimethod::index(lir::AlignedLongJump, C)] = CAST1(alignedLongJumpC); + + bo[index(c, lir::Negate, R, R)] = CAST2(negateRR); + + bo[index(c, lir::FloatNegate, R, R)] = CAST2(floatNegateRR); + + bo[index(c, lir::Move, R, R)] = CAST2(moveRR); + bo[index(c, lir::Move, C, R)] = CAST2(moveCR); + bo[index(c, lir::Move, M, R)] = CAST2(moveMR); + bo[index(c, lir::Move, R, M)] = CAST2(moveRM); + bo[index(c, lir::Move, C, M)] = CAST2(moveCM); + bo[index(c, lir::Move, A, R)] = CAST2(moveAR); + + bo[index(c, lir::FloatSquareRoot, R, R)] = CAST2(floatSqrtRR); + bo[index(c, lir::FloatSquareRoot, M, R)] = CAST2(floatSqrtMR); + + bo[index(c, lir::MoveZ, R, R)] = CAST2(moveZRR); + bo[index(c, lir::MoveZ, M, R)] = CAST2(moveZMR); + bo[index(c, lir::MoveZ, C, R)] = CAST2(moveZCR); + + bo[index(c, lir::Add, R, R)] = CAST2(addRR); + bo[index(c, lir::Add, C, R)] = CAST2(addCR); + + bo[index(c, lir::Subtract, C, R)] = CAST2(subtractCR); + bo[index(c, lir::Subtract, R, R)] = CAST2(subtractRR); + + bo[index(c, lir::FloatAdd, R, R)] = CAST2(floatAddRR); + bo[index(c, lir::FloatAdd, M, R)] = CAST2(floatAddMR); + + bo[index(c, lir::FloatSubtract, R, R)] = CAST2(floatSubtractRR); + bo[index(c, lir::FloatSubtract, M, R)] = CAST2(floatSubtractMR); + + bo[index(c, lir::And, R, R)] = CAST2(andRR); + bo[index(c, lir::And, C, R)] = CAST2(andCR); + + bo[index(c, lir::Or, R, R)] = CAST2(orRR); + bo[index(c, lir::Or, C, R)] = CAST2(orCR); + + bo[index(c, lir::Xor, R, R)] = CAST2(xorRR); + bo[index(c, lir::Xor, C, R)] = CAST2(xorCR); + + bo[index(c, lir::Multiply, R, R)] = CAST2(multiplyRR); + bo[index(c, lir::Multiply, C, R)] = CAST2(multiplyCR); + + bo[index(c, lir::Divide, R, R)] = CAST2(divideRR); + + bo[index(c, lir::FloatMultiply, R, R)] = CAST2(floatMultiplyRR); + bo[index(c, lir::FloatMultiply, M, R)] = CAST2(floatMultiplyMR); + + bo[index(c, lir::FloatDivide, R, R)] = CAST2(floatDivideRR); + bo[index(c, lir::FloatDivide, M, R)] = CAST2(floatDivideMR); + + bo[index(c, lir::Remainder, R, R)] = CAST2(remainderRR); + + bo[index(c, lir::ShiftLeft, R, R)] = CAST2(shiftLeftRR); + bo[index(c, lir::ShiftLeft, C, R)] = CAST2(shiftLeftCR); + + bo[index(c, lir::ShiftRight, R, R)] = CAST2(shiftRightRR); + bo[index(c, lir::ShiftRight, C, R)] = CAST2(shiftRightCR); + + bo[index(c, lir::UnsignedShiftRight, R, R)] = CAST2(unsignedShiftRightRR); + bo[index(c, lir::UnsignedShiftRight, C, R)] = CAST2(unsignedShiftRightCR); + + bo[index(c, lir::Float2Float, R, R)] = CAST2(float2FloatRR); + bo[index(c, lir::Float2Float, M, R)] = CAST2(float2FloatMR); + + bo[index(c, lir::Float2Int, R, R)] = CAST2(float2IntRR); + bo[index(c, lir::Float2Int, M, R)] = CAST2(float2IntMR); + + bo[index(c, lir::Int2Float, R, R)] = CAST2(int2FloatRR); + bo[index(c, lir::Int2Float, M, R)] = CAST2(int2FloatMR); + + bo[index(c, lir::Absolute, R, R)] = CAST2(absoluteRR); + bo[index(c, lir::FloatAbsolute, R, R)] = CAST2(floatAbsoluteRR); + + bro[branchIndex(c, R, R)] = CAST_BRANCH(branchRR); + bro[branchIndex(c, C, R)] = CAST_BRANCH(branchCR); + bro[branchIndex(c, C, M)] = CAST_BRANCH(branchCM); + bro[branchIndex(c, R, M)] = CAST_BRANCH(branchRM); +} + +} // namespace x86 +} // namespace codegen +} // namespace avian diff --git a/sgx-jvm/avian/src/codegen/target/x86/multimethod.h b/sgx-jvm/avian/src/codegen/target/x86/multimethod.h new file mode 100644 index 0000000000..46b62300c5 --- /dev/null +++ b/sgx-jvm/avian/src/codegen/target/x86/multimethod.h @@ -0,0 +1,44 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#ifndef AVIAN_CODEGEN_ASSEMBLER_X86_MULTIMETHOD_H +#define AVIAN_CODEGEN_ASSEMBLER_X86_MULTIMETHOD_H + +#include "avian/common.h" + +#include + +namespace avian { +namespace codegen { +namespace x86 { + +class ArchitectureContext; + +unsigned index(ArchitectureContext*, + lir::BinaryOperation operation, + lir::Operand::Type operand1, + lir::Operand::Type operand2); + +unsigned index(ArchitectureContext* c UNUSED, + lir::TernaryOperation operation, + lir::Operand::Type operand1, + lir::Operand::Type operand2); + +unsigned branchIndex(ArchitectureContext* c UNUSED, + lir::Operand::Type operand1, + lir::Operand::Type operand2); + +void populateTables(ArchitectureContext* c); + +} // namespace x86 +} // namespace codegen +} // namespace avian + +#endif // AVIAN_CODEGEN_ASSEMBLER_X86_MULTIMETHOD_H diff --git a/sgx-jvm/avian/src/codegen/target/x86/operations.cpp b/sgx-jvm/avian/src/codegen/target/x86/operations.cpp new file mode 100644 index 0000000000..d9cbde1c04 --- /dev/null +++ b/sgx-jvm/avian/src/codegen/target/x86/operations.cpp @@ -0,0 +1,1759 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#include "avian/target.h" +#include "avian/alloc-vector.h" +#include "avian/util/allocator.h" +#include "avian/zone.h" + +#include + +#include +#include + +#include "context.h" +#include "encode.h" +#include "registers.h" +#include "detect.h" +#include "operations.h" +#include "padding.h" +#include "fixup.h" + +using namespace avian::util; + +namespace avian { +namespace codegen { +namespace x86 { + +void return_(Context* c) +{ + opcode(c, 0xc3); +} + +void trap(Context* c) +{ + opcode(c, 0xcc); +} + +void ignore(Context*) +{ +} + +void storeLoadBarrier(Context* c) +{ + if (useSSE(c->ac)) { + // mfence: + c->code.append(0x0f); + c->code.append(0xae); + c->code.append(0xf0); + } else { + // lock addq $0x0,(%rsp): + c->code.append(0xf0); + if (vm::TargetBytesPerWord == 8) { + c->code.append(0x48); + } + c->code.append(0x83); + c->code.append(0x04); + c->code.append(0x24); + c->code.append(0x00); + } +} + +void callC(Context* c, unsigned size UNUSED, lir::Constant* a) +{ + assertT(c, size == vm::TargetBytesPerWord); + + unconditional(c, 0xe8, a); +} + +void longCallC(Context* c, unsigned size, lir::Constant* a) +{ + assertT(c, size == vm::TargetBytesPerWord); + + if (vm::TargetBytesPerWord == 8) { + lir::RegisterPair r(LongJumpRegister); + moveCR2(c, size, a, size, &r, 11); + callR(c, size, &r); + } else { + callC(c, size, a); + } +} + +void jumpR(Context* c, unsigned size UNUSED, lir::RegisterPair* a) +{ + assertT(c, size == vm::TargetBytesPerWord); + + maybeRex(c, 4, a); + opcode(c, 0xff, 0xe0 + regCode(a)); +} + +void jumpC(Context* c, unsigned size UNUSED, lir::Constant* a) +{ + assertT(c, size == vm::TargetBytesPerWord); + + unconditional(c, 0xe9, a); +} + +void jumpM(Context* c, unsigned size UNUSED, lir::Memory* a) +{ + assertT(c, size == vm::TargetBytesPerWord); + + maybeRex(c, 4, a); + opcode(c, 0xff); + modrmSibImm(c, rsp, a->scale, a->index, a->base, a->offset); +} + +void longJumpC(Context* c, unsigned size, lir::Constant* a) +{ + assertT(c, size == vm::TargetBytesPerWord); + + if (vm::TargetBytesPerWord == 8) { + lir::RegisterPair r(LongJumpRegister); + moveCR2(c, size, a, size, &r, 11); + jumpR(c, size, &r); + } else { + jumpC(c, size, a); + } +} + +void callR(Context* c, unsigned size UNUSED, lir::RegisterPair* a) +{ + assertT(c, size == vm::TargetBytesPerWord); + + // maybeRex.W has no meaning here so we disable it + maybeRex(c, 4, a); + opcode(c, 0xff, 0xd0 + regCode(a)); +} + +void callM(Context* c, unsigned size UNUSED, lir::Memory* a) +{ + assertT(c, size == vm::TargetBytesPerWord); + + maybeRex(c, 4, a); + opcode(c, 0xff); + modrmSibImm(c, rdx, a->scale, a->index, a->base, a->offset); +} + +void alignedCallC(Context* c, unsigned size, lir::Constant* a) +{ + new (c->zone) AlignmentPadding(c, 1, 4); + callC(c, size, a); +} + +void alignedLongCallC(Context* c, unsigned size, lir::Constant* a) +{ + assertT(c, size == vm::TargetBytesPerWord); + + if (vm::TargetBytesPerWord == 8) { + new (c->zone) AlignmentPadding(c, 2, 8); + longCallC(c, size, a); + } else { + alignedCallC(c, size, a); + } +} + +void alignedJumpC(Context* c, unsigned size, lir::Constant* a) +{ + new (c->zone) AlignmentPadding(c, 1, 4); + jumpC(c, size, a); +} + +void alignedLongJumpC(Context* c, unsigned size, lir::Constant* a) +{ + assertT(c, size == vm::TargetBytesPerWord); + + if (vm::TargetBytesPerWord == 8) { + new (c->zone) AlignmentPadding(c, 2, 8); + longJumpC(c, size, a); + } else { + alignedJumpC(c, size, a); + } +} + +void pushR(Context* c, unsigned size, lir::RegisterPair* a) +{ + if (vm::TargetBytesPerWord == 4 and size == 8) { + lir::RegisterPair ah(a->high); + + pushR(c, 4, &ah); + pushR(c, 4, a); + } else { + maybeRex(c, 4, a); + opcode(c, 0x50 + regCode(a)); + } +} + +void popR(Context* c, unsigned size, lir::RegisterPair* a) +{ + if (vm::TargetBytesPerWord == 4 and size == 8) { + lir::RegisterPair ah(a->high); + + popR(c, 4, a); + popR(c, 4, &ah); + } else { + maybeRex(c, 4, a); + opcode(c, 0x58 + regCode(a)); + if (vm::TargetBytesPerWord == 8 and size == 4) { + moveRR(c, 4, a, 8, a); + } + } +} + +void negateR(Context* c, unsigned size, lir::RegisterPair* a) +{ + if (vm::TargetBytesPerWord == 4 and size == 8) { + assertT(c, a->low == rax and a->high == rdx); + + ResolvedPromise zeroPromise(0); + lir::Constant zero(&zeroPromise); + + lir::RegisterPair ah(a->high); + + negateR(c, 4, a); + addCarryCR(c, 4, &zero, &ah); + negateR(c, 4, &ah); + } else { + maybeRex(c, size, a); + opcode(c, 0xf7, 0xd8 + regCode(a)); + } +} + +void negateRR(Context* c, + unsigned aSize, + lir::RegisterPair* a, + unsigned bSize UNUSED, + lir::RegisterPair* b UNUSED) +{ + assertT(c, aSize == bSize); + + negateR(c, aSize, a); +} + +void moveCR(Context* c, + unsigned aSize, + lir::Constant* a, + unsigned bSize, + lir::RegisterPair* b) +{ + if (isFloatReg(b)) { + sseMoveCR(c, aSize, a, bSize, b); + } else { + moveCR2(c, aSize, a, bSize, b, 0); + } +} + +void moveZCR(Context* c, + unsigned aSize UNUSED, + lir::Constant* a, + unsigned bSize UNUSED, + lir::RegisterPair* b) +{ + assertT(c, not isFloatReg(b)); + assertT(c, aSize == 2); + assertT(c, bSize == vm::TargetBytesPerWord); + assertT(c, a->value->resolved()); + + maybeRex(c, vm::TargetBytesPerWord, b); + opcode(c, 0xb8 + regCode(b)); + c->code.appendTargetAddress(static_cast(a->value->value())); +} + +void swapRR(Context* c, + unsigned aSize UNUSED, + lir::RegisterPair* a, + unsigned bSize UNUSED, + lir::RegisterPair* b) +{ + assertT(c, aSize == bSize); + assertT(c, aSize == vm::TargetBytesPerWord); + + alwaysRex(c, aSize, a, b); + opcode(c, 0x87); + modrm(c, 0xc0, b, a); +} + +void moveRR(Context* c, + unsigned aSize, + lir::RegisterPair* a, + UNUSED unsigned bSize, + lir::RegisterPair* b) +{ + if (isFloatReg(a) or isFloatReg(b)) { + sseMoveRR(c, aSize, a, bSize, b); + return; + } + + if (vm::TargetBytesPerWord == 4 and aSize == 8 and bSize == 8) { + lir::RegisterPair ah(a->high); + lir::RegisterPair bh(b->high); + + if (a->high == b->low) { + if (a->low == b->high) { + swapRR(c, 4, a, 4, b); + } else { + moveRR(c, 4, &ah, 4, &bh); + moveRR(c, 4, a, 4, b); + } + } else { + moveRR(c, 4, a, 4, b); + moveRR(c, 4, &ah, 4, &bh); + } + } else { + switch (aSize) { + case 1: + if (vm::TargetBytesPerWord == 4 and a->low > rbx) { + assertT(c, b->low <= rbx); + + moveRR(c, vm::TargetBytesPerWord, a, vm::TargetBytesPerWord, b); + moveRR(c, 1, b, vm::TargetBytesPerWord, b); + } else { + alwaysRex(c, aSize, b, a); + opcode(c, 0x0f, 0xbe); + modrm(c, 0xc0, a, b); + } + break; + + case 2: + alwaysRex(c, aSize, b, a); + opcode(c, 0x0f, 0xbf); + modrm(c, 0xc0, a, b); + break; + + case 4: + if (bSize == 8) { + if (vm::TargetBytesPerWord == 8) { + alwaysRex(c, bSize, b, a); + opcode(c, 0x63); + modrm(c, 0xc0, a, b); + } else { + if (a->low == rax and b->low == rax and b->high == rdx) { + opcode(c, 0x99); // cdq + } else { + assertT(c, b->low == rax and b->high == rdx); + + moveRR(c, 4, a, 4, b); + moveRR(c, 4, b, 8, b); + } + } + } else { + if (a->low != b->low) { + alwaysRex(c, aSize, a, b); + opcode(c, 0x89); + modrm(c, 0xc0, b, a); + } + } + break; + + case 8: + if (a->low != b->low) { + maybeRex(c, aSize, a, b); + opcode(c, 0x89); + modrm(c, 0xc0, b, a); + } + break; + } + } +} + +void moveMR(Context* c, + unsigned aSize, + lir::Memory* a, + unsigned bSize, + lir::RegisterPair* b) +{ + if (isFloatReg(b)) { + sseMoveMR(c, aSize, a, bSize, b); + return; + } + + switch (aSize) { + case 1: + maybeRex(c, bSize, b, a); + opcode(c, 0x0f, 0xbe); + modrmSibImm(c, b, a); + break; + + case 2: + maybeRex(c, bSize, b, a); + opcode(c, 0x0f, 0xbf); + modrmSibImm(c, b, a); + break; + + case 4: + if (vm::TargetBytesPerWord == 8) { + maybeRex(c, bSize, b, a); + opcode(c, 0x63); + modrmSibImm(c, b, a); + } else { + if (bSize == 8) { + assertT(c, b->low == rax and b->high == rdx); + + moveMR(c, 4, a, 4, b); + moveRR(c, 4, b, 8, b); + } else { + maybeRex(c, bSize, b, a); + opcode(c, 0x8b); + modrmSibImm(c, b, a); + } + } + break; + + case 8: + if (vm::TargetBytesPerWord == 4 and bSize == 8) { + lir::Memory ah(a->base, a->offset + 4, a->index, a->scale); + lir::RegisterPair bh(b->high); + + moveMR(c, 4, a, 4, b); + moveMR(c, 4, &ah, 4, &bh); + } else { + maybeRex(c, bSize, b, a); + opcode(c, 0x8b); + modrmSibImm(c, b, a); + } + break; + + default: + abort(c); + } +} + +void moveRM(Context* c, + unsigned aSize, + lir::RegisterPair* a, + unsigned bSize UNUSED, + lir::Memory* b) +{ + assertT(c, aSize == bSize); + + if (isFloatReg(a)) { + sseMoveRM(c, aSize, a, bSize, b); + return; + } + + switch (aSize) { + case 1: + maybeRex(c, bSize, a, b); + opcode(c, 0x88); + modrmSibImm(c, a, b); + break; + + case 2: + opcode(c, 0x66); + maybeRex(c, bSize, a, b); + opcode(c, 0x89); + modrmSibImm(c, a, b); + break; + + case 4: + if (vm::TargetBytesPerWord == 8) { + maybeRex(c, bSize, a, b); + opcode(c, 0x89); + modrmSibImm(c, a, b); + break; + } else { + opcode(c, 0x89); + modrmSibImm(c, a, b); + } + break; + + case 8: + if (vm::TargetBytesPerWord == 8) { + maybeRex(c, bSize, a, b); + opcode(c, 0x89); + modrmSibImm(c, a, b); + } else { + lir::RegisterPair ah(a->high); + lir::Memory bh(b->base, b->offset + 4, b->index, b->scale); + + moveRM(c, 4, a, 4, b); + moveRM(c, 4, &ah, 4, &bh); + } + break; + + default: + abort(c); + } +} + +void moveAR(Context* c, + unsigned aSize, + lir::Address* a, + unsigned bSize, + lir::RegisterPair* b) +{ + assertT(c, vm::TargetBytesPerWord == 8 or (aSize == 4 and bSize == 4)); + + lir::Constant constant(a->address); + lir::Memory memory(b->low, 0, NoRegister, 0); + + moveCR(c, aSize, &constant, bSize, b); + moveMR(c, bSize, &memory, bSize, b); +} + +void moveCM(Context* c, + unsigned aSize UNUSED, + lir::Constant* a, + unsigned bSize, + lir::Memory* b) +{ + switch (bSize) { + case 1: + maybeRex(c, bSize, b); + opcode(c, 0xc6); + modrmSibImm(c, rax, b->scale, b->index, b->base, b->offset); + c->code.append(a->value->value()); + break; + + case 2: + opcode(c, 0x66); + maybeRex(c, bSize, b); + opcode(c, 0xc7); + modrmSibImm(c, rax, b->scale, b->index, b->base, b->offset); + c->code.append2(a->value->value()); + break; + + case 4: + maybeRex(c, bSize, b); + opcode(c, 0xc7); + modrmSibImm(c, rax, b->scale, b->index, b->base, b->offset); + if (a->value->resolved()) { + c->code.append4(a->value->value()); + } else { + appendImmediateTask(c, a->value, offsetPromise(c), 4); + c->code.append4(0); + } + break; + + case 8: { + if (vm::TargetBytesPerWord == 8) { + if (a->value->resolved() and vm::fitsInInt32(a->value->value())) { + maybeRex(c, bSize, b); + opcode(c, 0xc7); + modrmSibImm(c, rax, b->scale, b->index, b->base, b->offset); + c->code.append4(a->value->value()); + } else { + lir::RegisterPair tmp(c->client->acquireTemporary(GeneralRegisterMask)); + moveCR(c, 8, a, 8, &tmp); + moveRM(c, 8, &tmp, 8, b); + c->client->releaseTemporary(tmp.low); + } + } else { + lir::Constant ah(shiftMaskPromise(c, a->value, 32, 0xFFFFFFFF)); + lir::Constant al(shiftMaskPromise(c, a->value, 0, 0xFFFFFFFF)); + + lir::Memory bh(b->base, b->offset + 4, b->index, b->scale); + + moveCM(c, 4, &al, 4, b); + moveCM(c, 4, &ah, 4, &bh); + } + } break; + + default: + abort(c); + } +} + +void moveZRR(Context* c, + unsigned aSize, + lir::RegisterPair* a, + unsigned bSize UNUSED, + lir::RegisterPair* b) +{ + switch (aSize) { + case 2: + alwaysRex(c, aSize, b, a); + opcode(c, 0x0f, 0xb7); + modrm(c, 0xc0, a, b); + break; + + default: + abort(c); + } +} + +void moveZMR(Context* c, + unsigned aSize UNUSED, + lir::Memory* a, + unsigned bSize UNUSED, + lir::RegisterPair* b) +{ + assertT(c, bSize == vm::TargetBytesPerWord); + assertT(c, aSize == 2); + + maybeRex(c, bSize, b, a); + opcode(c, 0x0f, 0xb7); + modrmSibImm(c, b->low, a->scale, a->index, a->base, a->offset); +} + +void addCarryRR(Context* c, unsigned size, lir::RegisterPair* a, lir::RegisterPair* b) +{ + assertT(c, vm::TargetBytesPerWord == 8 or size == 4); + + maybeRex(c, size, a, b); + opcode(c, 0x11); + modrm(c, 0xc0, b, a); +} + +void addRR(Context* c, + unsigned aSize, + lir::RegisterPair* a, + unsigned bSize UNUSED, + lir::RegisterPair* b) +{ + assertT(c, aSize == bSize); + + if (vm::TargetBytesPerWord == 4 and aSize == 8) { + lir::RegisterPair ah(a->high); + lir::RegisterPair bh(b->high); + + addRR(c, 4, a, 4, b); + addCarryRR(c, 4, &ah, &bh); + } else { + maybeRex(c, aSize, a, b); + opcode(c, 0x01); + modrm(c, 0xc0, b, a); + } +} + +void addCarryCR(Context* c, unsigned size, lir::Constant* a, lir::RegisterPair* b) +{ + int64_t v = a->value->value(); + maybeRex(c, size, b); + if (vm::fitsInInt8(v)) { + opcode(c, 0x83, 0xd0 + regCode(b)); + c->code.append(v); + } else { + opcode(c, 0x81, 0xd0 + regCode(b)); + c->code.append4(v); + } +} + +void addCR(Context* c, + unsigned aSize, + lir::Constant* a, + unsigned bSize, + lir::RegisterPair* b) +{ + assertT(c, aSize == bSize); + + int64_t v = a->value->value(); + if (v) { + if (vm::TargetBytesPerWord == 4 and bSize == 8) { + ResolvedPromise high((v >> 32) & 0xFFFFFFFF); + lir::Constant ah(&high); + + ResolvedPromise low(v & 0xFFFFFFFF); + lir::Constant al(&low); + + lir::RegisterPair bh(b->high); + + addCR(c, 4, &al, 4, b); + addCarryCR(c, 4, &ah, &bh); + } else { + if (vm::fitsInInt32(v)) { + maybeRex(c, aSize, b); + if (vm::fitsInInt8(v)) { + opcode(c, 0x83, 0xc0 + regCode(b)); + c->code.append(v); + } else { + opcode(c, 0x81, 0xc0 + regCode(b)); + c->code.append4(v); + } + } else { + lir::RegisterPair tmp(c->client->acquireTemporary(GeneralRegisterMask)); + moveCR(c, aSize, a, aSize, &tmp); + addRR(c, aSize, &tmp, bSize, b); + c->client->releaseTemporary(tmp.low); + } + } + } +} + +void subtractBorrowCR(Context* c, + unsigned size UNUSED, + lir::Constant* a, + lir::RegisterPair* b) +{ + assertT(c, vm::TargetBytesPerWord == 8 or size == 4); + + int64_t v = a->value->value(); + if (vm::fitsInInt8(v)) { + opcode(c, 0x83, 0xd8 + regCode(b)); + c->code.append(v); + } else { + opcode(c, 0x81, 0xd8 + regCode(b)); + c->code.append4(v); + } +} + +void subtractCR(Context* c, + unsigned aSize, + lir::Constant* a, + unsigned bSize, + lir::RegisterPair* b) +{ + assertT(c, aSize == bSize); + + int64_t v = a->value->value(); + if (v) { + if (vm::TargetBytesPerWord == 4 and bSize == 8) { + ResolvedPromise high((v >> 32) & 0xFFFFFFFF); + lir::Constant ah(&high); + + ResolvedPromise low(v & 0xFFFFFFFF); + lir::Constant al(&low); + + lir::RegisterPair bh(b->high); + + subtractCR(c, 4, &al, 4, b); + subtractBorrowCR(c, 4, &ah, &bh); + } else { + if (vm::fitsInInt32(v)) { + maybeRex(c, aSize, b); + if (vm::fitsInInt8(v)) { + opcode(c, 0x83, 0xe8 + regCode(b)); + c->code.append(v); + } else { + opcode(c, 0x81, 0xe8 + regCode(b)); + c->code.append4(v); + } + } else { + lir::RegisterPair tmp(c->client->acquireTemporary(GeneralRegisterMask)); + moveCR(c, aSize, a, aSize, &tmp); + subtractRR(c, aSize, &tmp, bSize, b); + c->client->releaseTemporary(tmp.low); + } + } + } +} + +void subtractBorrowRR(Context* c, + unsigned size, + lir::RegisterPair* a, + lir::RegisterPair* b) +{ + assertT(c, vm::TargetBytesPerWord == 8 or size == 4); + + maybeRex(c, size, a, b); + opcode(c, 0x19); + modrm(c, 0xc0, b, a); +} + +void subtractRR(Context* c, + unsigned aSize, + lir::RegisterPair* a, + unsigned bSize UNUSED, + lir::RegisterPair* b) +{ + assertT(c, aSize == bSize); + + if (vm::TargetBytesPerWord == 4 and aSize == 8) { + lir::RegisterPair ah(a->high); + lir::RegisterPair bh(b->high); + + subtractRR(c, 4, a, 4, b); + subtractBorrowRR(c, 4, &ah, &bh); + } else { + maybeRex(c, aSize, a, b); + opcode(c, 0x29); + modrm(c, 0xc0, b, a); + } +} + +void andRR(Context* c, + unsigned aSize, + lir::RegisterPair* a, + unsigned bSize UNUSED, + lir::RegisterPair* b) +{ + assertT(c, aSize == bSize); + + if (vm::TargetBytesPerWord == 4 and aSize == 8) { + lir::RegisterPair ah(a->high); + lir::RegisterPair bh(b->high); + + andRR(c, 4, a, 4, b); + andRR(c, 4, &ah, 4, &bh); + } else { + maybeRex(c, aSize, a, b); + opcode(c, 0x21); + modrm(c, 0xc0, b, a); + } +} + +void andCR(Context* c, + unsigned aSize, + lir::Constant* a, + unsigned bSize, + lir::RegisterPair* b) +{ + assertT(c, aSize == bSize); + + int64_t v = a->value->value(); + + if (vm::TargetBytesPerWord == 4 and bSize == 8) { + ResolvedPromise high((v >> 32) & 0xFFFFFFFF); + lir::Constant ah(&high); + + ResolvedPromise low(v & 0xFFFFFFFF); + lir::Constant al(&low); + + lir::RegisterPair bh(b->high); + + andCR(c, 4, &al, 4, b); + andCR(c, 4, &ah, 4, &bh); + } else { + if (vm::fitsInInt32(v)) { + maybeRex(c, aSize, b); + if (vm::fitsInInt8(v)) { + opcode(c, 0x83, 0xe0 + regCode(b)); + c->code.append(v); + } else { + opcode(c, 0x81, 0xe0 + regCode(b)); + c->code.append4(v); + } + } else { + lir::RegisterPair tmp(c->client->acquireTemporary(GeneralRegisterMask)); + moveCR(c, aSize, a, aSize, &tmp); + andRR(c, aSize, &tmp, bSize, b); + c->client->releaseTemporary(tmp.low); + } + } +} + +void orRR(Context* c, + unsigned aSize, + lir::RegisterPair* a, + unsigned bSize UNUSED, + lir::RegisterPair* b) +{ + assertT(c, aSize == bSize); + + if (vm::TargetBytesPerWord == 4 and aSize == 8) { + lir::RegisterPair ah(a->high); + lir::RegisterPair bh(b->high); + + orRR(c, 4, a, 4, b); + orRR(c, 4, &ah, 4, &bh); + } else { + maybeRex(c, aSize, a, b); + opcode(c, 0x09); + modrm(c, 0xc0, b, a); + } +} + +void orCR(Context* c, + unsigned aSize, + lir::Constant* a, + unsigned bSize, + lir::RegisterPair* b) +{ + assertT(c, aSize == bSize); + + int64_t v = a->value->value(); + if (v) { + if (vm::TargetBytesPerWord == 4 and bSize == 8) { + ResolvedPromise high((v >> 32) & 0xFFFFFFFF); + lir::Constant ah(&high); + + ResolvedPromise low(v & 0xFFFFFFFF); + lir::Constant al(&low); + + lir::RegisterPair bh(b->high); + + orCR(c, 4, &al, 4, b); + orCR(c, 4, &ah, 4, &bh); + } else { + if (vm::fitsInInt32(v)) { + maybeRex(c, aSize, b); + if (vm::fitsInInt8(v)) { + opcode(c, 0x83, 0xc8 + regCode(b)); + c->code.append(v); + } else { + opcode(c, 0x81, 0xc8 + regCode(b)); + c->code.append4(v); + } + } else { + lir::RegisterPair tmp(c->client->acquireTemporary(GeneralRegisterMask)); + moveCR(c, aSize, a, aSize, &tmp); + orRR(c, aSize, &tmp, bSize, b); + c->client->releaseTemporary(tmp.low); + } + } + } +} + +void xorRR(Context* c, + unsigned aSize, + lir::RegisterPair* a, + unsigned bSize UNUSED, + lir::RegisterPair* b) +{ + if (vm::TargetBytesPerWord == 4 and aSize == 8) { + lir::RegisterPair ah(a->high); + lir::RegisterPair bh(b->high); + + xorRR(c, 4, a, 4, b); + xorRR(c, 4, &ah, 4, &bh); + } else { + maybeRex(c, aSize, a, b); + opcode(c, 0x31); + modrm(c, 0xc0, b, a); + } +} + +void xorCR(Context* c, + unsigned aSize, + lir::Constant* a, + unsigned bSize, + lir::RegisterPair* b) +{ + assertT(c, aSize == bSize); + + int64_t v = a->value->value(); + if (v) { + if (vm::TargetBytesPerWord == 4 and bSize == 8) { + ResolvedPromise high((v >> 32) & 0xFFFFFFFF); + lir::Constant ah(&high); + + ResolvedPromise low(v & 0xFFFFFFFF); + lir::Constant al(&low); + + lir::RegisterPair bh(b->high); + + xorCR(c, 4, &al, 4, b); + xorCR(c, 4, &ah, 4, &bh); + } else { + if (vm::fitsInInt32(v)) { + maybeRex(c, aSize, b); + if (vm::fitsInInt8(v)) { + opcode(c, 0x83, 0xf0 + regCode(b)); + c->code.append(v); + } else { + opcode(c, 0x81, 0xf0 + regCode(b)); + c->code.append4(v); + } + } else { + lir::RegisterPair tmp(c->client->acquireTemporary(GeneralRegisterMask)); + moveCR(c, aSize, a, aSize, &tmp); + xorRR(c, aSize, &tmp, bSize, b); + c->client->releaseTemporary(tmp.low); + } + } + } +} + +void multiplyRR(Context* c, + unsigned aSize, + lir::RegisterPair* a, + unsigned bSize UNUSED, + lir::RegisterPair* b) +{ + assertT(c, aSize == bSize); + + if (vm::TargetBytesPerWord == 4 and aSize == 8) { + assertT(c, b->high == rdx); + assertT(c, b->low != rax); + assertT(c, a->low != rax); + assertT(c, a->high != rax); + + c->client->save(rax); + + lir::RegisterPair axdx(rax, rdx); + lir::RegisterPair ah(a->high); + lir::RegisterPair bh(b->high); + + lir::RegisterPair tmp(NoRegister); + lir::RegisterPair* scratch; + if (a->low == b->low) { + tmp.low = c->client->acquireTemporary(GeneralRegisterMask.excluding(rax)); + scratch = &tmp; + moveRR(c, 4, b, 4, scratch); + } else { + scratch = b; + } + + moveRR(c, 4, b, 4, &axdx); + multiplyRR(c, 4, &ah, 4, scratch); + multiplyRR(c, 4, a, 4, &bh); + addRR(c, 4, &bh, 4, scratch); + + // mul a->low,%eax%edx + opcode(c, 0xf7, 0xe0 + a->low.index()); + + addRR(c, 4, scratch, 4, &bh); + moveRR(c, 4, &axdx, 4, b); + + if (tmp.low != NoRegister) { + c->client->releaseTemporary(tmp.low); + } + } else { + maybeRex(c, aSize, b, a); + opcode(c, 0x0f, 0xaf); + modrm(c, 0xc0, a, b); + } +} + +void compareRR(Context* c, + unsigned aSize, + lir::RegisterPair* a, + unsigned bSize UNUSED, + lir::RegisterPair* b) +{ + assertT(c, aSize == bSize); + assertT(c, aSize <= vm::TargetBytesPerWord); + + maybeRex(c, aSize, a, b); + opcode(c, 0x39); + modrm(c, 0xc0, b, a); +} + +void compareCR(Context* c, + unsigned aSize, + lir::Constant* a, + unsigned bSize, + lir::RegisterPair* b) +{ + assertT(c, aSize == bSize); + assertT(c, vm::TargetBytesPerWord == 8 or aSize == 4); + + if (a->value->resolved() and vm::fitsInInt32(a->value->value())) { + int64_t v = a->value->value(); + maybeRex(c, aSize, b); + if (vm::fitsInInt8(v)) { + opcode(c, 0x83, 0xf8 + regCode(b)); + c->code.append(v); + } else { + opcode(c, 0x81, 0xf8 + regCode(b)); + c->code.append4(v); + } + } else { + lir::RegisterPair tmp(c->client->acquireTemporary(GeneralRegisterMask)); + moveCR(c, aSize, a, aSize, &tmp); + compareRR(c, aSize, &tmp, bSize, b); + c->client->releaseTemporary(tmp.low); + } +} + +void compareRM(Context* c, + unsigned aSize, + lir::RegisterPair* a, + unsigned bSize UNUSED, + lir::Memory* b) +{ + assertT(c, aSize == bSize); + assertT(c, vm::TargetBytesPerWord == 8 or aSize == 4); + + if (vm::TargetBytesPerWord == 8 and aSize == 4) { + moveRR(c, 4, a, 8, a); + } + maybeRex(c, bSize, a, b); + opcode(c, 0x39); + modrmSibImm(c, a, b); +} + +void compareCM(Context* c, + unsigned aSize, + lir::Constant* a, + unsigned bSize, + lir::Memory* b) +{ + assertT(c, aSize == bSize); + assertT(c, vm::TargetBytesPerWord == 8 or aSize == 4); + + if (a->value->resolved()) { + int64_t v = a->value->value(); + maybeRex(c, aSize, b); + opcode(c, vm::fitsInInt8(v) ? 0x83 : 0x81); + modrmSibImm(c, rdi, b->scale, b->index, b->base, b->offset); + + if (vm::fitsInInt8(v)) { + c->code.append(v); + } else if (vm::fitsInInt32(v)) { + c->code.append4(v); + } else { + abort(c); + } + } else { + lir::RegisterPair tmp(c->client->acquireTemporary(GeneralRegisterMask)); + moveCR(c, aSize, a, bSize, &tmp); + compareRM(c, bSize, &tmp, bSize, b); + c->client->releaseTemporary(tmp.low); + } +} + +void compareFloatRR(Context* c, + unsigned aSize, + lir::RegisterPair* a, + unsigned bSize UNUSED, + lir::RegisterPair* b) +{ + assertT(c, aSize == bSize); + + if (aSize == 8) { + opcode(c, 0x66); + } + maybeRex(c, 4, a, b); + opcode(c, 0x0f, 0x2e); + modrm(c, 0xc0, a, b); +} + +void branchLong(Context* c, + lir::TernaryOperation op, + lir::Operand* al, + lir::Operand* ah, + lir::Operand* bl, + lir::Operand* bh, + lir::Constant* target, + BinaryOperationType compare) +{ + compare(c, 4, ah, 4, bh); + + unsigned next = 0; + + switch (op) { + case lir::JumpIfEqual: + opcode(c, 0x75); // jne + next = c->code.length(); + c->code.append(0); + + compare(c, 4, al, 4, bl); + conditional(c, 0x84, target); // je + break; + + case lir::JumpIfNotEqual: + conditional(c, 0x85, target); // jne + + compare(c, 4, al, 4, bl); + conditional(c, 0x85, target); // jne + break; + + case lir::JumpIfLess: + conditional(c, 0x8c, target); // jl + + opcode(c, 0x7f); // jg + next = c->code.length(); + c->code.append(0); + + compare(c, 4, al, 4, bl); + conditional(c, 0x82, target); // jb + break; + + case lir::JumpIfGreater: + conditional(c, 0x8f, target); // jg + + opcode(c, 0x7c); // jl + next = c->code.length(); + c->code.append(0); + + compare(c, 4, al, 4, bl); + conditional(c, 0x87, target); // ja + break; + + case lir::JumpIfLessOrEqual: + conditional(c, 0x8c, target); // jl + + opcode(c, 0x7f); // jg + next = c->code.length(); + c->code.append(0); + + compare(c, 4, al, 4, bl); + conditional(c, 0x86, target); // jbe + break; + + case lir::JumpIfGreaterOrEqual: + conditional(c, 0x8f, target); // jg + + opcode(c, 0x7c); // jl + next = c->code.length(); + c->code.append(0); + + compare(c, 4, al, 4, bl); + conditional(c, 0x83, target); // jae + break; + + default: + abort(c); + } + + if (next) { + int8_t nextOffset = c->code.length() - next - 1; + c->code.set(next, &nextOffset, 1); + } +} + +void branchRR(Context* c, + lir::TernaryOperation op, + unsigned size, + lir::RegisterPair* a, + lir::RegisterPair* b, + lir::Constant* target) +{ + if (isFloatBranch(op)) { + compareFloatRR(c, size, a, size, b); + branchFloat(c, op, target); + } else if (size > vm::TargetBytesPerWord) { + lir::RegisterPair ah(a->high); + lir::RegisterPair bh(b->high); + + branchLong(c, op, a, &ah, b, &bh, target, CAST2(compareRR)); + } else { + compareRR(c, size, a, size, b); + branch(c, op, target); + } +} + +void branchCR(Context* c, + lir::TernaryOperation op, + unsigned size, + lir::Constant* a, + lir::RegisterPair* b, + lir::Constant* target) +{ + assertT(c, not isFloatBranch(op)); + + if (size > vm::TargetBytesPerWord) { + int64_t v = a->value->value(); + + ResolvedPromise low(v & ~static_cast(0)); + lir::Constant al(&low); + + ResolvedPromise high((v >> 32) & ~static_cast(0)); + lir::Constant ah(&high); + + lir::RegisterPair bh(b->high); + + branchLong(c, op, &al, &ah, b, &bh, target, CAST2(compareCR)); + } else { + compareCR(c, size, a, size, b); + branch(c, op, target); + } +} + +void branchRM(Context* c, + lir::TernaryOperation op, + unsigned size, + lir::RegisterPair* a, + lir::Memory* b, + lir::Constant* target) +{ + assertT(c, not isFloatBranch(op)); + assertT(c, size <= vm::TargetBytesPerWord); + + compareRM(c, size, a, size, b); + branch(c, op, target); +} + +void branchCM(Context* c, + lir::TernaryOperation op, + unsigned size, + lir::Constant* a, + lir::Memory* b, + lir::Constant* target) +{ + assertT(c, not isFloatBranch(op)); + assertT(c, size <= vm::TargetBytesPerWord); + + compareCM(c, size, a, size, b); + branch(c, op, target); +} + +void multiplyCR(Context* c, + unsigned aSize, + lir::Constant* a, + unsigned bSize, + lir::RegisterPair* b) +{ + assertT(c, aSize == bSize); + + if (vm::TargetBytesPerWord == 4 and aSize == 8) { + const RegisterMask mask = GeneralRegisterMask.excluding(rax).excluding(rdx); + lir::RegisterPair tmp(c->client->acquireTemporary(mask), + c->client->acquireTemporary(mask)); + + moveCR(c, aSize, a, aSize, &tmp); + multiplyRR(c, aSize, &tmp, bSize, b); + c->client->releaseTemporary(tmp.low); + c->client->releaseTemporary(tmp.high); + } else { + int64_t v = a->value->value(); + if (v != 1) { + if (vm::fitsInInt32(v)) { + maybeRex(c, bSize, b, b); + if (vm::fitsInInt8(v)) { + opcode(c, 0x6b); + modrm(c, 0xc0, b, b); + c->code.append(v); + } else { + opcode(c, 0x69); + modrm(c, 0xc0, b, b); + c->code.append4(v); + } + } else { + lir::RegisterPair tmp(c->client->acquireTemporary(GeneralRegisterMask)); + moveCR(c, aSize, a, aSize, &tmp); + multiplyRR(c, aSize, &tmp, bSize, b); + c->client->releaseTemporary(tmp.low); + } + } + } +} + +void divideRR(Context* c, + unsigned aSize, + lir::RegisterPair* a, + unsigned bSize UNUSED, + lir::RegisterPair* b UNUSED) +{ + assertT(c, aSize == bSize); + + assertT(c, b->low == rax); + assertT(c, a->low != rdx); + + c->client->save(rdx); + + maybeRex(c, aSize, a, b); + opcode(c, 0x99); // cdq + maybeRex(c, aSize, b, a); + opcode(c, 0xf7, 0xf8 + regCode(a)); +} + +void remainderRR(Context* c, + unsigned aSize, + lir::RegisterPair* a, + unsigned bSize UNUSED, + lir::RegisterPair* b) +{ + assertT(c, aSize == bSize); + + assertT(c, b->low == rax); + assertT(c, a->low != rdx); + + c->client->save(rdx); + + maybeRex(c, aSize, a, b); + opcode(c, 0x99); // cdq + maybeRex(c, aSize, b, a); + opcode(c, 0xf7, 0xf8 + regCode(a)); + + lir::RegisterPair dx(rdx); + moveRR(c, vm::TargetBytesPerWord, &dx, vm::TargetBytesPerWord, b); +} + +void doShift(Context* c, + UNUSED void (*shift)(Context*, + unsigned, + lir::RegisterPair*, + unsigned, + lir::RegisterPair*), + int type, + UNUSED unsigned aSize, + lir::Constant* a, + unsigned bSize, + lir::RegisterPair* b) +{ + int64_t v = a->value->value(); + + if (vm::TargetBytesPerWord == 4 and bSize == 8) { + c->client->save(rcx); + + lir::RegisterPair cx(rcx); + ResolvedPromise promise(v & 0x3F); + lir::Constant masked(&promise); + moveCR(c, 4, &masked, 4, &cx); + shift(c, aSize, &cx, bSize, b); + } else { + maybeRex(c, bSize, b); + if (v == 1) { + opcode(c, 0xd1, type + regCode(b)); + } else if (vm::fitsInInt8(v)) { + opcode(c, 0xc1, type + regCode(b)); + c->code.append(v); + } else { + abort(c); + } + } +} + +void shiftLeftRR(Context* c, + UNUSED unsigned aSize, + lir::RegisterPair* a, + unsigned bSize, + lir::RegisterPair* b) +{ + if (vm::TargetBytesPerWord == 4 and bSize == 8) { + lir::RegisterPair cx(rcx); + if (a->low != rcx) { + c->client->save(rcx); + ResolvedPromise promise(0x3F); + lir::Constant mask(&promise); + moveRR(c, 4, a, 4, &cx); + andCR(c, 4, &mask, 4, &cx); + } + + // shld + opcode(c, 0x0f, 0xa5); + modrm(c, 0xc0, b->high, b->low); + + // shl + opcode(c, 0xd3, 0xe0 + b->low.index()); + + ResolvedPromise promise(32); + lir::Constant constant(&promise); + compareCR( + c, vm::TargetBytesPerWord, &constant, vm::TargetBytesPerWord, &cx); + + opcode(c, 0x7c); // jl + c->code.append(2 + 2); + + lir::RegisterPair bh(b->high); + moveRR(c, 4, b, 4, &bh); // 2 bytes + xorRR(c, 4, b, 4, b); // 2 bytes + } else { + assertT(c, a->low == rcx); + + maybeRex(c, bSize, a, b); + opcode(c, 0xd3, 0xe0 + regCode(b)); + } +} + +void shiftLeftCR(Context* c, + unsigned aSize, + lir::Constant* a, + unsigned bSize, + lir::RegisterPair* b) +{ + doShift(c, shiftLeftRR, 0xe0, aSize, a, bSize, b); +} + +void shiftRightRR(Context* c, + UNUSED unsigned aSize, + lir::RegisterPair* a, + unsigned bSize, + lir::RegisterPair* b) +{ + if (vm::TargetBytesPerWord == 4 and bSize == 8) { + lir::RegisterPair cx(rcx); + if (a->low != rcx) { + c->client->save(rcx); + ResolvedPromise promise(0x3F); + lir::Constant mask(&promise); + moveRR(c, 4, a, 4, &cx); + andCR(c, 4, &mask, 4, &cx); + } + + // shrd + opcode(c, 0x0f, 0xad); + modrm(c, 0xc0, b->low, b->high); + + // sar + opcode(c, 0xd3, 0xf8 + b->high.index()); + + ResolvedPromise promise(32); + lir::Constant constant(&promise); + compareCR( + c, vm::TargetBytesPerWord, &constant, vm::TargetBytesPerWord, &cx); + + opcode(c, 0x7c); // jl + c->code.append(2 + 3); + + lir::RegisterPair bh(b->high); + moveRR(c, 4, &bh, 4, b); // 2 bytes + + // sar 31,high + opcode(c, 0xc1, 0xf8 + b->high.index()); + c->code.append(31); + } else { + assertT(c, a->low == rcx); + + maybeRex(c, bSize, a, b); + opcode(c, 0xd3, 0xf8 + regCode(b)); + } +} + +void shiftRightCR(Context* c, + unsigned aSize, + lir::Constant* a, + unsigned bSize, + lir::RegisterPair* b) +{ + doShift(c, shiftRightRR, 0xf8, aSize, a, bSize, b); +} + +void unsignedShiftRightRR(Context* c, + UNUSED unsigned aSize, + lir::RegisterPair* a, + unsigned bSize, + lir::RegisterPair* b) +{ + if (vm::TargetBytesPerWord == 4 and bSize == 8) { + lir::RegisterPair cx(rcx); + if (a->low != rcx) { + c->client->save(rcx); + ResolvedPromise promise(0x3F); + lir::Constant mask(&promise); + moveRR(c, 4, a, 4, &cx); + andCR(c, 4, &mask, 4, &cx); + } + + // shrd + opcode(c, 0x0f, 0xad); + modrm(c, 0xc0, b->low, b->high); + + // shr + opcode(c, 0xd3, 0xe8 + b->high.index()); + + ResolvedPromise promise(32); + lir::Constant constant(&promise); + compareCR( + c, vm::TargetBytesPerWord, &constant, vm::TargetBytesPerWord, &cx); + + opcode(c, 0x7c); // jl + c->code.append(2 + 2); + + lir::RegisterPair bh(b->high); + moveRR(c, 4, &bh, 4, b); // 2 bytes + xorRR(c, 4, &bh, 4, &bh); // 2 bytes + } else { + assertT(c, a->low == rcx); + + maybeRex(c, bSize, a, b); + opcode(c, 0xd3, 0xe8 + regCode(b)); + } +} + +void unsignedShiftRightCR(Context* c, + unsigned aSize UNUSED, + lir::Constant* a, + unsigned bSize, + lir::RegisterPair* b) +{ + doShift(c, unsignedShiftRightRR, 0xe8, aSize, a, bSize, b); +} + +void floatSqrtRR(Context* c, + unsigned aSize, + lir::RegisterPair* a, + unsigned bSize UNUSED, + lir::RegisterPair* b) +{ + floatRegOp(c, aSize, a, 4, b, 0x51); +} + +void floatSqrtMR(Context* c, + unsigned aSize, + lir::Memory* a, + unsigned bSize UNUSED, + lir::RegisterPair* b) +{ + floatMemOp(c, aSize, a, 4, b, 0x51); +} + +void floatAddRR(Context* c, + unsigned aSize, + lir::RegisterPair* a, + unsigned bSize UNUSED, + lir::RegisterPair* b) +{ + floatRegOp(c, aSize, a, 4, b, 0x58); +} + +void floatAddMR(Context* c, + unsigned aSize, + lir::Memory* a, + unsigned bSize UNUSED, + lir::RegisterPair* b) +{ + floatMemOp(c, aSize, a, 4, b, 0x58); +} + +void floatSubtractRR(Context* c, + unsigned aSize, + lir::RegisterPair* a, + unsigned bSize UNUSED, + lir::RegisterPair* b) +{ + floatRegOp(c, aSize, a, 4, b, 0x5c); +} + +void floatSubtractMR(Context* c, + unsigned aSize, + lir::Memory* a, + unsigned bSize UNUSED, + lir::RegisterPair* b) +{ + floatMemOp(c, aSize, a, 4, b, 0x5c); +} + +void floatMultiplyRR(Context* c, + unsigned aSize, + lir::RegisterPair* a, + unsigned bSize UNUSED, + lir::RegisterPair* b) +{ + floatRegOp(c, aSize, a, 4, b, 0x59); +} + +void floatMultiplyMR(Context* c, + unsigned aSize, + lir::Memory* a, + unsigned bSize UNUSED, + lir::RegisterPair* b) +{ + floatMemOp(c, aSize, a, 4, b, 0x59); +} + +void floatDivideRR(Context* c, + unsigned aSize, + lir::RegisterPair* a, + unsigned bSize UNUSED, + lir::RegisterPair* b) +{ + floatRegOp(c, aSize, a, 4, b, 0x5e); +} + +void floatDivideMR(Context* c, + unsigned aSize, + lir::Memory* a, + unsigned bSize UNUSED, + lir::RegisterPair* b) +{ + floatMemOp(c, aSize, a, 4, b, 0x5e); +} + +void float2FloatRR(Context* c, + unsigned aSize, + lir::RegisterPair* a, + unsigned bSize UNUSED, + lir::RegisterPair* b) +{ + floatRegOp(c, aSize, a, 4, b, 0x5a); +} + +void float2FloatMR(Context* c, + unsigned aSize, + lir::Memory* a, + unsigned bSize UNUSED, + lir::RegisterPair* b) +{ + floatMemOp(c, aSize, a, 4, b, 0x5a); +} + +void float2IntRR(Context* c, + unsigned aSize, + lir::RegisterPair* a, + unsigned bSize, + lir::RegisterPair* b) +{ + assertT(c, not isFloatReg(b)); + floatRegOp(c, aSize, a, bSize, b, 0x2c); +} + +void float2IntMR(Context* c, + unsigned aSize, + lir::Memory* a, + unsigned bSize, + lir::RegisterPair* b) +{ + floatMemOp(c, aSize, a, bSize, b, 0x2c); +} + +void int2FloatRR(Context* c, + unsigned aSize, + lir::RegisterPair* a, + unsigned bSize, + lir::RegisterPair* b) +{ + floatRegOp(c, bSize, a, aSize, b, 0x2a); +} + +void int2FloatMR(Context* c, + unsigned aSize, + lir::Memory* a, + unsigned bSize, + lir::RegisterPair* b) +{ + floatMemOp(c, bSize, a, aSize, b, 0x2a); +} + +void floatNegateRR(Context* c, + unsigned aSize, + lir::RegisterPair* a, + unsigned bSize UNUSED, + lir::RegisterPair* b) +{ + assertT(c, isFloatReg(a) and isFloatReg(b)); + // unlike most of the other floating point code, this does NOT + // support doubles: + assertT(c, aSize == 4); + ResolvedPromise pcon(0x80000000); + lir::Constant con(&pcon); + if (a->low == b->low) { + lir::RegisterPair tmp(c->client->acquireTemporary(FloatRegisterMask)); + moveCR(c, 4, &con, 4, &tmp); + maybeRex(c, 4, a, &tmp); + opcode(c, 0x0f, 0x57); + modrm(c, 0xc0, &tmp, a); + c->client->releaseTemporary(tmp.low); + } else { + moveCR(c, 4, &con, 4, b); + if (aSize == 8) + opcode(c, 0x66); + maybeRex(c, 4, a, b); + opcode(c, 0x0f, 0x57); + modrm(c, 0xc0, a, b); + } +} + +void floatAbsoluteRR(Context* c, + unsigned aSize UNUSED, + lir::RegisterPair* a, + unsigned bSize UNUSED, + lir::RegisterPair* b) +{ + assertT(c, isFloatReg(a) and isFloatReg(b)); + // unlike most of the other floating point code, this does NOT + // support doubles: + assertT(c, aSize == 4); + ResolvedPromise pcon(0x7fffffff); + lir::Constant con(&pcon); + if (a->low == b->low) { + lir::RegisterPair tmp(c->client->acquireTemporary(FloatRegisterMask)); + moveCR(c, 4, &con, 4, &tmp); + maybeRex(c, 4, a, &tmp); + opcode(c, 0x0f, 0x54); + modrm(c, 0xc0, &tmp, a); + c->client->releaseTemporary(tmp.low); + } else { + moveCR(c, 4, &con, 4, b); + maybeRex(c, 4, a, b); + opcode(c, 0x0f, 0x54); + modrm(c, 0xc0, a, b); + } +} + +void absoluteRR(Context* c, + unsigned aSize, + lir::RegisterPair* a, + unsigned bSize UNUSED, + lir::RegisterPair* b UNUSED) +{ + assertT(c, aSize == bSize and a->low == rax and b->low == rax); + lir::RegisterPair d(c->client->acquireTemporary(rdx)); + maybeRex(c, aSize, a, b); + opcode(c, 0x99); + xorRR(c, aSize, &d, aSize, a); + subtractRR(c, aSize, &d, aSize, a); + c->client->releaseTemporary(rdx); +} + +} // namespace x86 +} // namespace codegen +} // namespace avian diff --git a/sgx-jvm/avian/src/codegen/target/x86/operations.h b/sgx-jvm/avian/src/codegen/target/x86/operations.h new file mode 100644 index 0000000000..2101231e05 --- /dev/null +++ b/sgx-jvm/avian/src/codegen/target/x86/operations.h @@ -0,0 +1,459 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#ifndef AVIAN_CODEGEN_ASSEMBLER_X86_OPERATIONS_H +#define AVIAN_CODEGEN_ASSEMBLER_X86_OPERATIONS_H + +#include "avian/common.h" + +#include + +#include "context.h" + +namespace avian { +namespace codegen { +namespace x86 { + +void return_(Context* c); + +void trap(Context* c); + +void ignore(Context*); + +void storeLoadBarrier(Context* c); + +void callC(Context* c, unsigned size UNUSED, lir::Constant* a); + +void longCallC(Context* c, unsigned size, lir::Constant* a); + +void jumpR(Context* c, unsigned size UNUSED, lir::RegisterPair* a); + +void jumpC(Context* c, unsigned size UNUSED, lir::Constant* a); + +void jumpM(Context* c, unsigned size UNUSED, lir::Memory* a); + +void longJumpC(Context* c, unsigned size, lir::Constant* a); + +void callR(Context* c, unsigned size UNUSED, lir::RegisterPair* a); + +void callM(Context* c, unsigned size UNUSED, lir::Memory* a); + +void alignedCallC(Context* c, unsigned size, lir::Constant* a); + +void alignedLongCallC(Context* c, unsigned size, lir::Constant* a); + +void alignedJumpC(Context* c, unsigned size, lir::Constant* a); + +void alignedLongJumpC(Context* c, unsigned size, lir::Constant* a); + +void pushR(Context* c, unsigned size, lir::RegisterPair* a); + +void popR(Context* c, unsigned size, lir::RegisterPair* a); + +void negateR(Context* c, unsigned size, lir::RegisterPair* a); + +void negateRR(Context* c, + unsigned aSize, + lir::RegisterPair* a, + unsigned bSize UNUSED, + lir::RegisterPair* b UNUSED); + +void moveCR(Context* c, + unsigned aSize, + lir::Constant* a, + unsigned bSize, + lir::RegisterPair* b); + +void moveZCR(Context* c, + unsigned aSize, + lir::Constant* a, + unsigned bSize, + lir::RegisterPair* b); + +void swapRR(Context* c, + unsigned aSize UNUSED, + lir::RegisterPair* a, + unsigned bSize UNUSED, + lir::RegisterPair* b); + +void moveRR(Context* c, + unsigned aSize, + lir::RegisterPair* a, + UNUSED unsigned bSize, + lir::RegisterPair* b); + +void moveMR(Context* c, + unsigned aSize, + lir::Memory* a, + unsigned bSize, + lir::RegisterPair* b); + +void moveRM(Context* c, + unsigned aSize, + lir::RegisterPair* a, + unsigned bSize UNUSED, + lir::Memory* b); + +void moveAR(Context* c, + unsigned aSize, + lir::Address* a, + unsigned bSize, + lir::RegisterPair* b); + +void moveCM(Context* c, + unsigned aSize UNUSED, + lir::Constant* a, + unsigned bSize, + lir::Memory* b); + +void moveZRR(Context* c, + unsigned aSize, + lir::RegisterPair* a, + unsigned bSize UNUSED, + lir::RegisterPair* b); + +void moveZMR(Context* c, + unsigned aSize UNUSED, + lir::Memory* a, + unsigned bSize UNUSED, + lir::RegisterPair* b); + +void addCarryRR(Context* c, unsigned size, lir::RegisterPair* a, lir::RegisterPair* b); + +void addRR(Context* c, + unsigned aSize, + lir::RegisterPair* a, + unsigned bSize UNUSED, + lir::RegisterPair* b); + +void addCarryCR(Context* c, unsigned size, lir::Constant* a, lir::RegisterPair* b); + +void addCR(Context* c, + unsigned aSize, + lir::Constant* a, + unsigned bSize, + lir::RegisterPair* b); + +void subtractBorrowCR(Context* c, + unsigned size UNUSED, + lir::Constant* a, + lir::RegisterPair* b); + +void subtractCR(Context* c, + unsigned aSize, + lir::Constant* a, + unsigned bSize, + lir::RegisterPair* b); + +void subtractBorrowRR(Context* c, + unsigned size, + lir::RegisterPair* a, + lir::RegisterPair* b); + +void subtractRR(Context* c, + unsigned aSize, + lir::RegisterPair* a, + unsigned bSize UNUSED, + lir::RegisterPair* b); + +void andRR(Context* c, + unsigned aSize, + lir::RegisterPair* a, + unsigned bSize UNUSED, + lir::RegisterPair* b); + +void andCR(Context* c, + unsigned aSize, + lir::Constant* a, + unsigned bSize, + lir::RegisterPair* b); + +void orRR(Context* c, + unsigned aSize, + lir::RegisterPair* a, + unsigned bSize UNUSED, + lir::RegisterPair* b); + +void orCR(Context* c, + unsigned aSize, + lir::Constant* a, + unsigned bSize, + lir::RegisterPair* b); + +void xorRR(Context* c, + unsigned aSize, + lir::RegisterPair* a, + unsigned bSize UNUSED, + lir::RegisterPair* b); + +void xorCR(Context* c, + unsigned aSize, + lir::Constant* a, + unsigned bSize, + lir::RegisterPair* b); + +void multiplyRR(Context* c, + unsigned aSize, + lir::RegisterPair* a, + unsigned bSize UNUSED, + lir::RegisterPair* b); + +void compareRR(Context* c, + unsigned aSize, + lir::RegisterPair* a, + unsigned bSize UNUSED, + lir::RegisterPair* b); + +void compareCR(Context* c, + unsigned aSize, + lir::Constant* a, + unsigned bSize, + lir::RegisterPair* b); + +void compareRM(Context* c, + unsigned aSize, + lir::RegisterPair* a, + unsigned bSize UNUSED, + lir::Memory* b); + +void compareCM(Context* c, + unsigned aSize, + lir::Constant* a, + unsigned bSize, + lir::Memory* b); + +void compareFloatRR(Context* c, + unsigned aSize, + lir::RegisterPair* a, + unsigned bSize UNUSED, + lir::RegisterPair* b); + +void branchLong(Context* c, + lir::TernaryOperation op, + lir::Operand* al, + lir::Operand* ah, + lir::Operand* bl, + lir::Operand* bh, + lir::Constant* target, + BinaryOperationType compare); + +void branchRR(Context* c, + lir::TernaryOperation op, + unsigned size, + lir::RegisterPair* a, + lir::RegisterPair* b, + lir::Constant* target); + +void branchCR(Context* c, + lir::TernaryOperation op, + unsigned size, + lir::Constant* a, + lir::RegisterPair* b, + lir::Constant* target); + +void branchRM(Context* c, + lir::TernaryOperation op, + unsigned size, + lir::RegisterPair* a, + lir::Memory* b, + lir::Constant* target); + +void branchCM(Context* c, + lir::TernaryOperation op, + unsigned size, + lir::Constant* a, + lir::Memory* b, + lir::Constant* target); + +void multiplyCR(Context* c, + unsigned aSize, + lir::Constant* a, + unsigned bSize, + lir::RegisterPair* b); + +void divideRR(Context* c, + unsigned aSize, + lir::RegisterPair* a, + unsigned bSize UNUSED, + lir::RegisterPair* b UNUSED); + +void remainderRR(Context* c, + unsigned aSize, + lir::RegisterPair* a, + unsigned bSize UNUSED, + lir::RegisterPair* b); + +void doShift(Context* c, + UNUSED void (*shift)(Context*, + unsigned, + lir::RegisterPair*, + unsigned, + lir::RegisterPair*), + int type, + UNUSED unsigned aSize, + lir::Constant* a, + unsigned bSize, + lir::RegisterPair* b); + +void shiftLeftRR(Context* c, + UNUSED unsigned aSize, + lir::RegisterPair* a, + unsigned bSize, + lir::RegisterPair* b); + +void shiftLeftCR(Context* c, + unsigned aSize, + lir::Constant* a, + unsigned bSize, + lir::RegisterPair* b); + +void shiftRightRR(Context* c, + UNUSED unsigned aSize, + lir::RegisterPair* a, + unsigned bSize, + lir::RegisterPair* b); + +void shiftRightCR(Context* c, + unsigned aSize, + lir::Constant* a, + unsigned bSize, + lir::RegisterPair* b); + +void unsignedShiftRightRR(Context* c, + UNUSED unsigned aSize, + lir::RegisterPair* a, + unsigned bSize, + lir::RegisterPair* b); + +void unsignedShiftRightCR(Context* c, + unsigned aSize UNUSED, + lir::Constant* a, + unsigned bSize, + lir::RegisterPair* b); + +void floatSqrtRR(Context* c, + unsigned aSize, + lir::RegisterPair* a, + unsigned bSize UNUSED, + lir::RegisterPair* b); + +void floatSqrtMR(Context* c, + unsigned aSize, + lir::Memory* a, + unsigned bSize UNUSED, + lir::RegisterPair* b); + +void floatAddRR(Context* c, + unsigned aSize, + lir::RegisterPair* a, + unsigned bSize UNUSED, + lir::RegisterPair* b); + +void floatAddMR(Context* c, + unsigned aSize, + lir::Memory* a, + unsigned bSize UNUSED, + lir::RegisterPair* b); + +void floatSubtractRR(Context* c, + unsigned aSize, + lir::RegisterPair* a, + unsigned bSize UNUSED, + lir::RegisterPair* b); + +void floatSubtractMR(Context* c, + unsigned aSize, + lir::Memory* a, + unsigned bSize UNUSED, + lir::RegisterPair* b); + +void floatMultiplyRR(Context* c, + unsigned aSize, + lir::RegisterPair* a, + unsigned bSize UNUSED, + lir::RegisterPair* b); + +void floatMultiplyMR(Context* c, + unsigned aSize, + lir::Memory* a, + unsigned bSize UNUSED, + lir::RegisterPair* b); + +void floatDivideRR(Context* c, + unsigned aSize, + lir::RegisterPair* a, + unsigned bSize UNUSED, + lir::RegisterPair* b); + +void floatDivideMR(Context* c, + unsigned aSize, + lir::Memory* a, + unsigned bSize UNUSED, + lir::RegisterPair* b); + +void float2FloatRR(Context* c, + unsigned aSize, + lir::RegisterPair* a, + unsigned bSize UNUSED, + lir::RegisterPair* b); + +void float2FloatMR(Context* c, + unsigned aSize, + lir::Memory* a, + unsigned bSize UNUSED, + lir::RegisterPair* b); + +void float2IntRR(Context* c, + unsigned aSize, + lir::RegisterPair* a, + unsigned bSize, + lir::RegisterPair* b); + +void float2IntMR(Context* c, + unsigned aSize, + lir::Memory* a, + unsigned bSize, + lir::RegisterPair* b); + +void int2FloatRR(Context* c, + unsigned aSize, + lir::RegisterPair* a, + unsigned bSize, + lir::RegisterPair* b); + +void int2FloatMR(Context* c, + unsigned aSize, + lir::Memory* a, + unsigned bSize, + lir::RegisterPair* b); + +void floatNegateRR(Context* c, + unsigned aSize, + lir::RegisterPair* a, + unsigned bSize UNUSED, + lir::RegisterPair* b); + +void floatAbsoluteRR(Context* c, + unsigned aSize UNUSED, + lir::RegisterPair* a, + unsigned bSize UNUSED, + lir::RegisterPair* b); + +void absoluteRR(Context* c, + unsigned aSize, + lir::RegisterPair* a, + unsigned bSize UNUSED, + lir::RegisterPair* b UNUSED); + +} // namespace x86 +} // namespace codegen +} // namespace avian + +#endif // AVIAN_CODEGEN_ASSEMBLER_X86_OPERATIONS_H diff --git a/sgx-jvm/avian/src/codegen/target/x86/padding.cpp b/sgx-jvm/avian/src/codegen/target/x86/padding.cpp new file mode 100644 index 0000000000..930d05903e --- /dev/null +++ b/sgx-jvm/avian/src/codegen/target/x86/padding.cpp @@ -0,0 +1,71 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#include "avian/alloc-vector.h" + +#include "context.h" +#include "padding.h" +#include "block.h" + +namespace avian { +namespace codegen { +namespace x86 { + +AlignmentPadding::AlignmentPadding(Context* c, + unsigned instructionOffset, + unsigned alignment) + : offset(c->code.length()), + instructionOffset(instructionOffset), + alignment(alignment), + next(0), + padding(-1) +{ + if (c->lastBlock->firstPadding) { + c->lastBlock->lastPadding->next = this; + } else { + c->lastBlock->firstPadding = this; + } + c->lastBlock->lastPadding = this; +} + +unsigned padding(AlignmentPadding* p, + unsigned start, + unsigned offset, + AlignmentPadding* limit) +{ + unsigned padding = 0; + if (limit) { + if (limit->padding == -1) { + for (; p; p = p->next) { + if (p->padding == -1) { + unsigned index = p->offset - offset; + while ((start + index + padding + p->instructionOffset) + % p->alignment) { + ++padding; + } + + p->padding = padding; + + if (p == limit) + break; + } else { + padding = p->padding; + } + } + } else { + padding = limit->padding; + } + } + return padding; +} + +} // namespace x86 +} // namespace codegen +} // namespace avian diff --git a/sgx-jvm/avian/src/codegen/target/x86/padding.h b/sgx-jvm/avian/src/codegen/target/x86/padding.h new file mode 100644 index 0000000000..51fde450d7 --- /dev/null +++ b/sgx-jvm/avian/src/codegen/target/x86/padding.h @@ -0,0 +1,40 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#ifndef AVIAN_CODEGEN_ASSEMBLER_X86_PADDING_H +#define AVIAN_CODEGEN_ASSEMBLER_X86_PADDING_H + +namespace avian { +namespace codegen { +namespace x86 { + +class Context; + +class AlignmentPadding { + public: + AlignmentPadding(Context* c, unsigned instructionOffset, unsigned alignment); + + unsigned offset; + unsigned instructionOffset; + unsigned alignment; + AlignmentPadding* next; + int padding; +}; + +unsigned padding(AlignmentPadding* p, + unsigned start, + unsigned offset, + AlignmentPadding* limit); + +} // namespace x86 +} // namespace codegen +} // namespace avian + +#endif // AVIAN_CODEGEN_ASSEMBLER_X86_PADDING_H diff --git a/sgx-jvm/avian/src/codegen/target/x86/registers.h b/sgx-jvm/avian/src/codegen/target/x86/registers.h new file mode 100644 index 0000000000..3e614a552f --- /dev/null +++ b/sgx-jvm/avian/src/codegen/target/x86/registers.h @@ -0,0 +1,63 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#ifndef AVIAN_CODEGEN_ASSEMBLER_X86_REGISTERS_H +#define AVIAN_CODEGEN_ASSEMBLER_X86_REGISTERS_H + +namespace avian { +namespace codegen { +namespace x86 { + +constexpr Register rax((int)0); +constexpr Register rcx(1); +constexpr Register rdx(2); +constexpr Register rbx(3); +constexpr Register rsp(4); +constexpr Register rbp(5); +constexpr Register rsi(6); +constexpr Register rdi(7); +constexpr Register r8(8); +constexpr Register r9(9); +constexpr Register r10(10); +constexpr Register r11(11); +constexpr Register r12(12); +constexpr Register r13(13); +constexpr Register r14(14); +constexpr Register r15(15); +constexpr Register xmm0(16); +constexpr Register xmm1(16 + 1); +constexpr Register xmm2(16 + 2); +constexpr Register xmm3(16 + 3); +constexpr Register xmm4(16 + 4); +constexpr Register xmm5(16 + 5); +constexpr Register xmm6(16 + 6); +constexpr Register xmm7(16 + 7); +constexpr Register xmm8(16 + 8); +constexpr Register xmm9(16 + 9); +constexpr Register xmm10(16 + 10); +constexpr Register xmm11(16 + 11); +constexpr Register xmm12(16 + 12); +constexpr Register xmm13(16 + 13); +constexpr Register xmm14(16 + 14); +constexpr Register xmm15(16 + 15); + +constexpr Register LongJumpRegister = r10; + +constexpr RegisterMask GeneralRegisterMask = vm::TargetBytesPerWord == 4 ? 0x000000ff + : 0x0000ffff; + +constexpr RegisterMask FloatRegisterMask = vm::TargetBytesPerWord == 4 ? 0x00ff0000 + : 0xffff0000; + +} // namespace x86 +} // namespace codegen +} // namespace avian + +#endif // AVIAN_CODEGEN_ASSEMBLER_X86_REGISTERS_H diff --git a/sgx-jvm/avian/src/codegen/targets.cpp b/sgx-jvm/avian/src/codegen/targets.cpp new file mode 100644 index 0000000000..b4eabba5be --- /dev/null +++ b/sgx-jvm/avian/src/codegen/targets.cpp @@ -0,0 +1,42 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#include "avian/common.h" + +#include + +#include "avian/environment.h" + +namespace avian { +namespace codegen { + +Architecture* makeArchitectureNative(vm::System* system, + bool useNativeFeatures UNUSED) +{ +#ifndef AVIAN_TARGET_ARCH +#error "Must specify native target!" +#endif + +#if AVIAN_TARGET_ARCH == AVIAN_ARCH_UNKNOWN + system->abort(); + return 0; +#elif(AVIAN_TARGET_ARCH == AVIAN_ARCH_X86) \ + || (AVIAN_TARGET_ARCH == AVIAN_ARCH_X86_64) + return makeArchitectureX86(system, useNativeFeatures); +#elif (AVIAN_TARGET_ARCH == AVIAN_ARCH_ARM) \ + || (AVIAN_TARGET_ARCH == AVIAN_ARCH_ARM64) + return makeArchitectureArm(system, useNativeFeatures); +#else +#error "Unsupported codegen target" +#endif +} + +} // namespace codegen +} // namespace avian diff --git a/sgx-jvm/avian/src/compile-arm.S b/sgx-jvm/avian/src/compile-arm.S new file mode 100644 index 0000000000..cd44d243a6 --- /dev/null +++ b/sgx-jvm/avian/src/compile-arm.S @@ -0,0 +1,255 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#include "avian/types.h" +#include "avian/target-fields.h" + +.text + +#define BYTES_PER_WORD 4 + +#define LOCAL(x) .L##x + +#ifdef __APPLE__ +# define GLOBAL(x) _##x +#else +# define GLOBAL(x) x +#endif + +#define CONTINUATION_NEXT 4 +#define CONTINUATION_ADDRESS 16 +#define CONTINUATION_RETURN_ADDRESS_OFFSET 20 +#define CONTINUATION_FRAME_POINTER_OFFSET 24 +#define CONTINUATION_LENGTH 28 +#define CONTINUATION_BODY 32 + +.globl GLOBAL(vmInvoke) +.align 2 +GLOBAL(vmInvoke): + /* + arguments + r0 : thread + r1 : function + r2 : arguments + r3 : argumentFootprint + [sp, #0] : frameSize (not used) + [sp, #4] : returnType + */ + + // save all non-volatile registers + stmfd sp!, {r4-r11, lr} + + // save return type + ldr r4, [sp, #4] + str r4, [sp, #-4]! + + str sp, [r0, #TARGET_THREAD_SCRATCH] + + // align stack, if necessary + eor r4, sp, r3 + tst r4, #4 + subne sp, sp, #4 + + // copy arguments into place + sub sp, r3 + mov r4, #0 + b LOCAL(vmInvoke_argumentTest) + +LOCAL(vmInvoke_argumentLoop): + ldr r5, [r2, r4] + str r5, [sp, r4] + add r4, r4, #BYTES_PER_WORD + +LOCAL(vmInvoke_argumentTest): + cmp r4, r3 + blt LOCAL(vmInvoke_argumentLoop) + + // we use r8 to hold the thread pointer, by convention + mov r8, r0 + + // load and call function address +#if defined(__ARM_ARCH_4__) || defined(__ARM_ARCH_4T__) + mov lr, pc + bx r1 +#else + blx r1 +#endif + +.globl GLOBAL(vmInvoke_returnAddress) +.align 2 +GLOBAL(vmInvoke_returnAddress): + // restore stack pointer + ldr sp, [r8, #TARGET_THREAD_SCRATCH] + + // clear MyThread::stack to avoid confusing another thread calling + // java.lang.Thread.getStackTrace on this one. See + // MyProcess::getStackTrace in compile.cpp for details on how we get + // a reliable stack trace from a thread that might be interrupted at + // any point in its execution. + mov r5, #0 + str r5, [r8, #TARGET_THREAD_STACK] + +.globl GLOBAL(vmInvoke_safeStack) +.align 2 +GLOBAL(vmInvoke_safeStack): + +#ifdef AVIAN_CONTINUATIONS + // call the next continuation, if any + ldr r5,[r8,#TARGET_THREAD_CONTINUATION] + cmp r5,#0 + beq LOCAL(vmInvoke_exit) + + ldr r6,[r5,#CONTINUATION_LENGTH] + lsl r6,r6,#2 + neg r7,r6 + add r7,r7,#-80 // 80 bytes for callee-saved register values + mov r4,sp + str r4,[sp,r7]! + + add r7,r5,#CONTINUATION_BODY + + mov r11,#0 + b LOCAL(vmInvoke_continuationTest) + +LOCAL(vmInvoke_continuationLoop): + ldr r9,[r7,r11] + str r9,[sp,r11] + add r11,r11,#4 + +LOCAL(vmInvoke_continuationTest): + cmp r11,r6 + ble LOCAL(vmInvoke_continuationLoop) + + ldr r7,[r5,#CONTINUATION_RETURN_ADDRESS_OFFSET] +#ifdef __APPLE__ + movw r11, :lower16:(GLOBAL(vmInvoke_returnAddress)-(LOCAL(vmInvoke_getAddress)+8)) + movt r11, :upper16:(GLOBAL(vmInvoke_returnAddress)-(LOCAL(vmInvoke_getAddress)+8)) +LOCAL(vmInvoke_getAddress): + add r11, pc, r11 +#else // not __APPLE__ + ldr r10,LOCAL(vmInvoke_returnAddress_word) + ldr r11,LOCAL(vmInvoke_getAddress_word) +LOCAL(vmInvoke_getAddress): + add r11,pc,r11 + ldr r11,[r11,r10] +#endif // not __APPLE__ + str r11,[sp,r7] + + ldr r7,[r5,#CONTINUATION_NEXT] + str r7,[r8,#TARGET_THREAD_CONTINUATION] + + // call the continuation unless we're handling an exception + ldr r7,[r8,#TARGET_THREAD_EXCEPTION] + cmp r7,#0 + bne LOCAL(vmInvoke_handleException) + ldr r7,[r5,#CONTINUATION_ADDRESS] + bx r7 + +LOCAL(vmInvoke_handleException): + // we're handling an exception - call the exception handler instead + mov r11,#0 + str r11,[r8,#TARGET_THREAD_EXCEPTION] + ldr r11,[r8,#TARGET_THREAD_EXCEPTIONSTACKADJUSTMENT] + ldr r9,[sp] + neg r11,r11 + str r9,[sp,r11]! + ldr r11,[r8,#TARGET_THREAD_EXCEPTIONOFFSET] + str r7,[sp,r11] + + ldr r7,[r8,#TARGET_THREAD_EXCEPTIONHANDLER] + bx r7 + +LOCAL(vmInvoke_exit): + + mov ip, #0 + str ip, [r8, #TARGET_THREAD_STACK] +#endif // AVIAN_CONTINUATIONS + + // restore return type + ldr ip, [sp], #4 + + // restore callee-saved registers + ldmfd sp!, {r4-r11, lr} + +LOCAL(vmInvoke_return): + bx lr + +.globl GLOBAL(vmJumpAndInvoke) +.align 2 +GLOBAL(vmJumpAndInvoke): +#ifdef AVIAN_CONTINUATIONS + // r0: thread + // r1: address + // r2: stack + // r3: argumentFootprint + // [sp,#0]: arguments + // [sp,#4]: frameSize + + ldr r5,[sp,#0] + ldr r6,[sp,#4] + + // allocate new frame, adding room for callee-saved registers, plus + // 4 bytes of padding since the calculation of frameSize assumes 4 + // bytes have already been allocated to save the return address, + // which is not true in this case + sub r2,r2,r6 + sub r2,r2,#84 + + mov r8,r0 + + // copy arguments into place + mov r6,#0 + b LOCAL(vmJumpAndInvoke_argumentTest) + +LOCAL(vmJumpAndInvoke_argumentLoop): + ldr r12,[r5,r6] + str r12,[r2,r6] + add r6,r6,#4 + +LOCAL(vmJumpAndInvoke_argumentTest): + cmp r6,r3 + ble LOCAL(vmJumpAndInvoke_argumentLoop) + + // the arguments have been copied, so we can set the real stack + // pointer now + mov sp,r2 + + // set return address to vmInvoke_returnAddress +#ifdef __APPLE__ + movw r11, :lower16:(GLOBAL(vmInvoke_returnAddress)-(LOCAL(vmJumpAndInvoke_getAddress)+8)) + movt r11, :upper16:(GLOBAL(vmInvoke_returnAddress)-(LOCAL(vmJumpAndInvoke_getAddress)+8)) +LOCAL(vmJumpAndInvoke_getAddress): + add r11, pc, r11 +#else // not __APPLE__ + + ldr r10,LOCAL(vmInvoke_returnAddress_word) + ldr r11,LOCAL(vmJumpAndInvoke_getAddress_word) +LOCAL(vmJumpAndInvoke_getAddress): + add r11,pc,r11 +#endif // not __APPLE__ + ldr lr,[r11,r10] + + bx r1 + +#ifndef __APPLE__ +LOCAL(vmInvoke_returnAddress_word): + .word GLOBAL(vmInvoke_returnAddress)(GOT) +LOCAL(vmInvoke_getAddress_word): + .word _GLOBAL_OFFSET_TABLE_-(LOCAL(vmInvoke_getAddress)+8) +LOCAL(vmJumpAndInvoke_getAddress_word): + .word _GLOBAL_OFFSET_TABLE_-(LOCAL(vmJumpAndInvoke_getAddress)+8) +#endif // not __APPLE__ + +#else // not AVIAN_CONTINUATIONS + // vmJumpAndInvoke should only be called when continuations are + // enabled, so we force a crash if we reach here: + mov r1,#0 + ldr r1,[r1] +#endif // not AVIAN_CONTINUATIONS diff --git a/sgx-jvm/avian/src/compile-arm.masm b/sgx-jvm/avian/src/compile-arm.masm new file mode 100644 index 0000000000..ac02048372 --- /dev/null +++ b/sgx-jvm/avian/src/compile-arm.masm @@ -0,0 +1,252 @@ +; Copyright (c) 2008-2015, Avian Contributors +; +; Permission to use, copy, modify, and/or distribute this software +; for any purpose with or without fee is hereby granted, provided +; that the above copyright notice and this permission notice appear +; in all copies. +; +; There is NO WARRANTY for this software. See license.txt for +; details. +; +; ORIGIN: https://github.com/gkvas/avian/tree/wince + +; types.inc +VOID_TYPE equ 0 +INT8_TYPE equ 1 +INT16_TYPE equ 2 +INT32_TYPE equ 3 +INT64_TYPE equ 4 +FLOAT_TYPE equ 5 +DOUBLE_TYPE equ 6 +POINTER_TYPE equ 7 + +; target-fields.inc +;TARGET_BYTES_PER_WORD = 4 + +TARGET_THREAD_EXCEPTION equ 44 +TARGET_THREAD_EXCEPTIONSTACKADJUSTMENT equ 2164 +TARGET_THREAD_EXCEPTIONOFFSET equ 2168 +TARGET_THREAD_EXCEPTIONHANDLER equ 2172 + +TARGET_THREAD_IP equ 2144 +TARGET_THREAD_STACK equ 2148 +TARGET_THREAD_NEWSTACK equ 2152 +TARGET_THREAD_SCRATCH equ 2156 +TARGET_THREAD_CONTINUATION equ 2160 +TARGET_THREAD_TAILADDRESS equ 2176 +TARGET_THREAD_VIRTUALCALLTARGET equ 2180 +TARGET_THREAD_VIRTUALCALLINDEX equ 2184 +TARGET_THREAD_HEAPIMAGE equ 2188 +TARGET_THREAD_CODEIMAGE equ 2192 +TARGET_THREAD_THUNKTABLE equ 2196 +TARGET_THREAD_STACKLIMIT equ 2220 + + AREA text, CODE, ARM + +BYTES_PER_WORD equ 4 + +CONTINUATION_NEXT equ 4 +CONTINUATION_ADDRESS equ 16 +CONTINUATION_RETURN_ADDRESS_OFFSET equ 20 +CONTINUATION_FRAME_POINTER_OFFSET equ 24 +CONTINUATION_LENGTH equ 28 +CONTINUATION_BODY equ 32 + + EXPORT vmInvoke +vmInvoke + + ; arguments + ; r0 : thread + ; r1 : function + ; r2 : arguments + ; r3 : argumentFootprint + ; [sp, #0] : frameSize (not used) + ; [sp, #4] : returnType + + + ; save all non-volatile registers + stmfd sp!, {r4-r11, lr} + + ; save return type + ldr r4, [sp, #4] + str r4, [sp, #-4]! + + str sp, [r0, #TARGET_THREAD_SCRATCH] + + ; align stack, if necessary + eor r4, sp, r3 + tst r4, #4 + subne sp, sp, #4 + + ; copy arguments into place + sub sp, sp, r3 + mov r4, #0 + b vmInvoke_argumentTest + +vmInvoke_argumentLoop + ldr r5, [r2, r4] + str r5, [sp, r4] + add r4, r4, #BYTES_PER_WORD + +vmInvoke_argumentTest + cmp r4, r3 + blt vmInvoke_argumentLoop + + ; we use r8 to hold the thread pointer, by convention + mov r8, r0 + + ; load and call function address + blx r1 + + EXPORT vmInvoke_returnAddress +vmInvoke_returnAddress + ; restore stack pointer + ldr sp, [r8, #TARGET_THREAD_SCRATCH] + + ; clear MyThread::stack to avoid confusing another thread calling + ; java.lang.Thread.getStackTrace on this one. See + ; MyProcess::getStackTrace in compile.cpp for details on how we get + ; a reliable stack trace from a thread that might be interrupted at + ; any point in its execution. + mov r5, #0 + str r5, [r8, #TARGET_THREAD_STACK] + + EXPORT vmInvoke_safeStack +vmInvoke_safeStack + +;if AVIAN_CONTINUATIONS +; ; call the next continuation, if any +; ldr r5,[r8,#TARGET_THREAD_CONTINUATION] +; cmp r5,#0 +; beq vmInvoke_exit) +; +; ldr r6,[r5,#CONTINUATION_LENGTH] +; lsl r6,r6,#2 +; neg r7,r6 +; add r7,r7,#-80 +; mov r4,sp +; str r4,[sp,r7]! +; +; add r7,r5,#CONTINUATION_BODY +; +; mov r11,#0 +; b vmInvoke_continuationTest +; +;vmInvoke_continuationLoop +; ldr r9,[r7,r11] +; str r9,[sp,r11] +; add r11,r11,#4 +; +;vmInvoke_continuationTest +; cmp r11,r6 +; ble vmInvoke_continuationLoop) +; +; ldr r7,[r5,#CONTINUATION_RETURN_ADDRESS_OFFSET] +; ldr r10,vmInvoke_returnAddress_word +; ldr r11,vmInvoke_getAddress_word +;vmInvoke_getAddress +; add r11,pc,r11 +; ldr r11,[r11,r10] +; str r11,[sp,r7] +; +; ldr r7,[r5,#CONTINUATION_NEXT] +; str r7,[r8,#TARGET_THREAD_CONTINUATION] +; +; ; call the continuation unless we're handling an exception +; ldr r7,[r8,#TARGET_THREAD_EXCEPTION] +; cmp r7,#0 +; bne vmInvoke_handleException) +; ldr r7,[r5,#CONTINUATION_ADDRESS] +; bx r7 +; +;vmInvoke_handleException +; ; we're handling an exception - call the exception handler instead +; mov r11,#0 +; str r11,[r8,#TARGET_THREAD_EXCEPTION] +; ldr r11,[r8,#TARGET_THREAD_EXCEPTIONSTACKADJUSTMENT] +; ldr r9,[sp] +; neg r11,r11 +; str r9,[sp,r11]! +; ldr r11,[r8,#TARGET_THREAD_EXCEPTIONOFFSET] +; str r7,[sp,r11] +; +; ldr r7,[r8,#TARGET_THREAD_EXCEPTIONHANDLER] +; bx r7 +; +;vmInvoke_exit +;endif ; AVIAN_CONTINUATIONS + + mov ip, #0 + str ip, [r8, #TARGET_THREAD_STACK] + + ; restore return type + ldr ip, [sp], #4 + + ; restore callee-saved registers + ldmfd sp!, {r4-r11, lr} + +vmInvoke_return + bx lr + + EXPORT vmJumpAndInvoke +vmJumpAndInvoke +;if :DEF:AVIAN_CONTINUATIONS +; ; r0: thread +; ; r1: address +; ; r2: stack +; ; r3: argumentFootprint +; ; [sp,#0]: arguments +; ; [sp,#4]: frameSize +; +; ldr r5,[sp,#0] +; ldr r6,[sp,#4] +; +; ; allocate new frame, adding room for callee-saved registers, plus +; ; 4 bytes of padding since the calculation of frameSize assumes 4 +; ; bytes have already been allocated to save the return address, +; ; which is not true in this case +; sub r2,r2,r6 +; sub r2,r2,#84 +; +; mov r8,r0 +; +; ; copy arguments into place +; mov r6,#0 +; b vmJumpAndInvoke_argumentTest +; +;vmJumpAndInvoke_argumentLoop +; ldr r12,[r5,r6] +; str r12,[r2,r6] +; add r6,r6,#4 +; +;vmJumpAndInvoke_argumentTest +; cmp r6,r3 +; ble vmJumpAndInvoke_argumentLoop +; +; ; the arguments have been copied, so we can set the real stack +; ; pointer now +; mov sp,r2 +; +; ; set return address to vmInvoke_returnAddress +; ldr r10,vmInvoke_returnAddress_word) +; ldr r11,vmJumpAndInvoke_getAddress_word) +;vmJumpAndInvoke_getAddress +; add r11,pc,r11 +; ldr lr,[r11,r10] +; +; bx r1 +; +;vmInvoke_returnAddress_word +; .word GLOBAL(vmInvoke_returnAddress)(GOT) +;vmInvoke_getAddress_word +; .word _GLOBAL_OFFSET_TABLE_-(vmInvoke_getAddress)+8) +;vmJumpAndInvoke_getAddress_word +; .word _GLOBAL_OFFSET_TABLE_-(vmJumpAndInvoke_getAddress)+8) +; +;else ; not AVIAN_CONTINUATIONS + ; vmJumpAndInvoke should only be called when continuations are + ; enabled + bkpt 0 +;endif ; not AVIAN_CONTINUATIONS + + END \ No newline at end of file diff --git a/sgx-jvm/avian/src/compile-arm64.S b/sgx-jvm/avian/src/compile-arm64.S new file mode 100644 index 0000000000..f1b022e860 --- /dev/null +++ b/sgx-jvm/avian/src/compile-arm64.S @@ -0,0 +1,222 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#include "avian/types.h" +#include "avian/target-fields.h" + +.text + +#define BYTES_PER_WORD 8 + +#define LOCAL(x) .L##x + +#ifdef __APPLE__ +# define GLOBAL(x) _##x +#else +# define GLOBAL(x) x +#endif + +#define CONTINUATION_NEXT 8 +#define CONTINUATION_ADDRESS 32 +#define CONTINUATION_RETURN_ADDRESS_OFFSET 40 +#define CONTINUATION_FRAME_POINTER_OFFSET 48 +#define CONTINUATION_LENGTH 56 +#define CONTINUATION_BODY 64 + +.globl GLOBAL(vmInvoke) +.align 2 +GLOBAL(vmInvoke): + // arguments: + // x0 : thread + // x1 : function + // x2 : arguments + // w3 : argumentFootprint + // w4 : frameSize (not used) + // w5 : returnType + + // allocate frame + stp x29, x30, [sp,#-96]! + mov x29, sp + + // save callee-saved register values + stp x19, x20, [sp,#16] + stp x21, x22, [sp,#32] + stp x23, x24, [sp,#48] + stp x25, x26, [sp,#64] + stp x27, x28, [sp,#80] + + // save return type + str w5, [sp,#-16]! + + mov x5, sp + str x5, [x0,#TARGET_THREAD_SCRATCH] + + // copy arguments into place, reserving enough space for them, plus + // alignment padding + sub x5, sp, w3, uxtw + and sp, x5, #-16 + + mov x4, #0 + b LOCAL(vmInvoke_argumentTest) + +LOCAL(vmInvoke_argumentLoop): + ldr x5, [x2, x4] + str x5, [sp, x4] + add x4, x4, #BYTES_PER_WORD + +LOCAL(vmInvoke_argumentTest): + cmp x4, x3 + b.lt LOCAL(vmInvoke_argumentLoop) + + // we use x19 to hold the thread pointer, by convention + mov x19, x0 + + // load and call function address + blr x1 + +.globl GLOBAL(vmInvoke_returnAddress) +.align 2 +GLOBAL(vmInvoke_returnAddress): + // restore stack pointer + ldr x5, [x19, #TARGET_THREAD_SCRATCH] + mov sp, x5 + + // clear MyThread::stack to avoid confusing another thread calling + // java.lang.Thread.getStackTrace on this one. See + // MyProcess::getStackTrace in compile.cpp for details on how we get + // a reliable stack trace from a thread that might be interrupted at + // any point in its execution. + str xzr, [x19, #TARGET_THREAD_STACK] + +.globl GLOBAL(vmInvoke_safeStack) +.align 2 +GLOBAL(vmInvoke_safeStack): + +#ifdef AVIAN_CONTINUATIONS + // call the next continuation, if any + ldr x5, [x19,#TARGET_THREAD_CONTINUATION] + cmp x5, xzr + b.eq LOCAL(vmInvoke_exit) + + ldr x6, [x5,#CONTINUATION_LENGTH] + lsl x6, x6, #3 + neg x7, x6 + add x7, x7, #-128 // 128 bytes for callee-saved register values + mov x4, sp + add sp, sp, x7 + str x4, [sp] + + add x7, x5, #CONTINUATION_BODY + mov x11, xzr + b LOCAL(vmInvoke_continuationTest) + +LOCAL(vmInvoke_continuationLoop): + ldr x9, [x7,x11] + str x9, [sp,x11] + add x11, x11, #8 + +LOCAL(vmInvoke_continuationTest): + cmp x11, x6 + b.le LOCAL(vmInvoke_continuationLoop) + + ldr x7, [x5,#CONTINUATION_RETURN_ADDRESS_OFFSET] + adr x11, GLOBAL(vmInvoke_returnAddress) + str x11, [sp,x7] + + ldr x7, [x5,#CONTINUATION_NEXT] + str x7, [x19,#TARGET_THREAD_CONTINUATION] + + // call the continuation unless we're handling an exception + ldr x7, [x19,#TARGET_THREAD_EXCEPTION] + cmp x7, xzr + b.ne LOCAL(vmInvoke_handleException) + ldr x7, [x5,#CONTINUATION_ADDRESS] + br x7 + +LOCAL(vmInvoke_handleException): + // we're handling an exception - call the exception handler instead + str xzr, [x19,#TARGET_THREAD_EXCEPTION] + ldr x11, [x19,#TARGET_THREAD_EXCEPTIONSTACKADJUSTMENT] + ldr x9, [sp] + neg x11, x11 + add sp, sp, x11 + str x9, [sp] + ldr x11, [x19,#TARGET_THREAD_EXCEPTIONOFFSET] + str x7, [sp,x11] + + ldr x7, [x19,#TARGET_THREAD_EXCEPTIONHANDLER] + br x7 + +LOCAL(vmInvoke_exit): + str xzr, [x19, #TARGET_THREAD_STACK] + +#endif // AVIAN_CONTINUATIONS + + // restore return type + ldr w5, [sp],#16 + + // restore callee-saved register values + ldp x19, x20, [sp,#16] + ldp x21, x22, [sp,#32] + ldp x23, x24, [sp,#48] + ldp x25, x26, [sp,#64] + ldp x27, x28, [sp,#80] + ldp x29, x30, [sp],#96 + +LOCAL(vmInvoke_return): + br x30 + +.globl GLOBAL(vmJumpAndInvoke) +.align 2 +GLOBAL(vmJumpAndInvoke): +#ifdef AVIAN_CONTINUATIONS + // x0: thread + // x1: address + // x2: stack + // x3: argumentFootprint + // x4: arguments + // x5: frameSize + + // allocate new frame, adding room for callee-saved registers, plus + // 8 bytes of padding since the calculation of frameSize assumes 8 + // bytes have already been allocated to save the return address, + // which is not true in this case + sub x2, x2, x5 + sub x2, x2, #136 + + mov x19, x0 + + // copy arguments into place + mov x6, xzr + b LOCAL(vmJumpAndInvoke_argumentTest) + +LOCAL(vmJumpAndInvoke_argumentLoop): + ldr x12, [x4,x6] + str x12, [x2,x6] + add x6, x6, #4 + +LOCAL(vmJumpAndInvoke_argumentTest): + cmp x6, x3 + ble LOCAL(vmJumpAndInvoke_argumentLoop) + + // the arguments have been copied, so we can set the real stack + // pointer now + mov sp, x2 + + // set return address to vmInvoke_returnAddress + adr x30, GLOBAL(vmInvoke_returnAddress) + + br x1 + +#else // not AVIAN_CONTINUATIONS + // vmJumpAndInvoke should only be called when continuations are + // enabled, so we force a crash if we reach here: + brk 0 +#endif // not AVIAN_CONTINUATIONS diff --git a/sgx-jvm/avian/src/compile-i386.S b/sgx-jvm/avian/src/compile-i386.S new file mode 100644 index 0000000000..d6ddd2052f --- /dev/null +++ b/sgx-jvm/avian/src/compile-i386.S @@ -0,0 +1,455 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#include "avian/types.h" +#include "avian/target-fields.h" + +#define LOCAL(x) .L##x + +#if defined __APPLE__ \ + || ((defined __MINGW32__ || defined __CYGWIN32__) && ! defined __x86_64__) +# define GLOBAL(x) _##x +#else +# define GLOBAL(x) x +#endif + +.text + +#ifdef __x86_64__ + +#ifdef AVIAN_USE_FRAME_POINTER +# define ALIGNMENT_ADJUSTMENT 0 +#else +# define ALIGNMENT_ADJUSTMENT 8 +#endif + +#if defined __MINGW32__ || defined __CYGWIN32__ + +#define CALLEE_SAVED_REGISTER_FOOTPRINT 64 + ALIGNMENT_ADJUSTMENT + +.globl GLOBAL(vmInvoke) +GLOBAL(vmInvoke): + pushq %rbp + movq %rsp,%rbp + + // %rcx: thread + // %rdx: function + // %r8 : arguments + // %r9 : argumentsFootprint + // 48(%rbp) : frameSize + // 56(%rbp) : returnType (ignored) + + // allocate stack space for callee-saved registers + subq $CALLEE_SAVED_REGISTER_FOOTPRINT,%rsp + + // remember this stack position, since we won't be able to rely on + // %rbp being restored when the call returns + movq %rsp,TARGET_THREAD_SCRATCH(%rcx) + + // save callee-saved registers + movq %rbx,0(%rsp) + movq %r12,8(%rsp) + movq %r13,16(%rsp) + movq %r14,24(%rsp) + movq %r15,32(%rsp) + movq %rsi,40(%rsp) + movq %rdi,48(%rsp) + + // allocate stack space for arguments + movl 48(%rbp),%eax + subq %rax,%rsp + + // we use rbx to hold the thread pointer, by convention + mov %rcx,%rbx + + // copy arguments into place + movq $0,%r11 + jmp LOCAL(vmInvoke_argumentTest) + +LOCAL(vmInvoke_argumentLoop): + movq (%r8,%r11,1),%rsi + movq %rsi,(%rsp,%r11,1) + addq $8,%r11 + +LOCAL(vmInvoke_argumentTest): + cmpq %r9,%r11 + jb LOCAL(vmInvoke_argumentLoop) + + // call function + call *%rdx + +.globl GLOBAL(vmInvoke_returnAddress) +GLOBAL(vmInvoke_returnAddress): + // restore stack pointer + movq TARGET_THREAD_SCRATCH(%rbx),%rsp + + // clear MyThread::stack to avoid confusing another thread calling + // java.lang.Thread.getStackTrace on this one. See + // MyProcess::getStackTrace in compile.cpp for details on how we get + // a reliable stack trace from a thread that might be interrupted at + // any point in its execution. + movq $0,TARGET_THREAD_STACK(%rbx) + +.globl GLOBAL(vmInvoke_safeStack) +GLOBAL(vmInvoke_safeStack): + +#ifdef AVIAN_CONTINUATIONS +# include "continuations-x86.S" +#endif // AVIAN_CONTINUATIONS + + // restore callee-saved registers + movq 0(%rsp),%rbx + movq 8(%rsp),%r12 + movq 16(%rsp),%r13 + movq 24(%rsp),%r14 + movq 32(%rsp),%r15 + movq 40(%rsp),%rsi + movq 48(%rsp),%rdi + + addq $CALLEE_SAVED_REGISTER_FOOTPRINT,%rsp + + // return + popq %rbp + ret + +.globl GLOBAL(vmJumpAndInvoke) +GLOBAL(vmJumpAndInvoke): +#ifdef AVIAN_CONTINUATIONS + // %rcx: thread + // %rdx: address + // %r8 : stack + // %r9 : argumentFootprint + // 40(%rsp): arguments + // 48(%rsp): frameSize + + // allocate new frame, adding room for callee-saved registers + movl 48(%rsp),%eax + subq %rax,%r8 + subq $CALLEE_SAVED_REGISTER_FOOTPRINT,%r8 + + movq %rcx,%rbx + + // set return address + leaq GLOBAL(vmInvoke_returnAddress)(%rip),%r10 + movq %r10,(%r8) + + // copy arguments into place + movq $0,%r11 + movl 40(%rsp),%eax + jmp LOCAL(vmJumpAndInvoke_argumentTest) + +LOCAL(vmJumpAndInvoke_argumentLoop): + movq (%rax,%r11,1),%r10 + movq %r10,8(%r8,%r11,1) + addq $8,%r11 + +LOCAL(vmJumpAndInvoke_argumentTest): + cmpq %r9,%r11 + jb LOCAL(vmJumpAndInvoke_argumentLoop) + + // the arguments have been copied, so we can set the real stack + // pointer now + movq %r8,%rsp + + jmp *%rdx +#else // not AVIAN_CONTINUATIONS + // vmJumpAndInvoke should only be called when continuations are + // enabled + int3 +#endif // not AVIAN_CONTINUATIONS + +#else // not __MINGW32__ || __CYGWIN32__ + +#define CALLEE_SAVED_REGISTER_FOOTPRINT 48 + ALIGNMENT_ADJUSTMENT + +.globl GLOBAL(vmInvoke) +GLOBAL(vmInvoke): + pushq %rbp + movq %rsp,%rbp + + // %rdi: thread + // %rsi: function + // %rdx: arguments + // %rcx: argumentFootprint + // %r8 : frameSize + // %r9 : returnType (ignored) + + // allocate stack space for callee-saved registers + subq $CALLEE_SAVED_REGISTER_FOOTPRINT,%rsp + + // remember this stack position, since we won't be able to rely on + // %rbp being restored when the call returns + movq %rsp,TARGET_THREAD_SCRATCH(%rdi) + + // save callee-saved registers + movq %rbx,0(%rsp) + movq %r12,8(%rsp) + movq %r13,16(%rsp) + movq %r14,24(%rsp) + movq %r15,32(%rsp) + + // allocate stack space for arguments + subq %r8,%rsp + + // we use rbx to hold the thread pointer, by convention + mov %rdi,%rbx + + // copy arguments into place + movq $0,%r9 + jmp LOCAL(vmInvoke_argumentTest) + +LOCAL(vmInvoke_argumentLoop): + movq (%rdx,%r9,1),%r8 + movq %r8,(%rsp,%r9,1) + addq $8,%r9 + +LOCAL(vmInvoke_argumentTest): + cmpq %rcx,%r9 + jb LOCAL(vmInvoke_argumentLoop) + + // call function + call *%rsi + +.globl GLOBAL(vmInvoke_returnAddress) +GLOBAL(vmInvoke_returnAddress): + // restore stack pointer + movq TARGET_THREAD_SCRATCH(%rbx),%rsp + + // clear MyThread::stack to avoid confusing another thread calling + // java.lang.Thread.getStackTrace on this one. See + // MyProcess::getStackTrace in compile.cpp for details on how we get + // a reliable stack trace from a thread that might be interrupted at + // any point in its execution. + movq $0,TARGET_THREAD_STACK(%rbx) + +.globl GLOBAL(vmInvoke_safeStack) +GLOBAL(vmInvoke_safeStack): + +#ifdef AVIAN_CONTINUATIONS +# include "continuations-x86.S" +#endif // AVIAN_CONTINUATIONS + + // restore callee-saved registers + movq 0(%rsp),%rbx + movq 8(%rsp),%r12 + movq 16(%rsp),%r13 + movq 24(%rsp),%r14 + movq 32(%rsp),%r15 + + addq $CALLEE_SAVED_REGISTER_FOOTPRINT,%rsp + + // return + popq %rbp + ret + +.globl GLOBAL(vmJumpAndInvoke) +GLOBAL(vmJumpAndInvoke): +#ifdef AVIAN_CONTINUATIONS + // %rdi: thread + // %rsi: address + // %rdx: stack + // %rcx: argumentFootprint + // %r8 : arguments + // %r9 : frameSize + + // allocate new frame, adding room for callee-saved registers + subq %r9,%rdx + subq $CALLEE_SAVED_REGISTER_FOOTPRINT,%rdx + + movq %rdi,%rbx + + // set return address + movq GLOBAL(vmInvoke_returnAddress)@GOTPCREL(%rip),%r10 + movq %r10,(%rdx) + + // copy arguments into place + movq $0,%r11 + jmp LOCAL(vmJumpAndInvoke_argumentTest) + +LOCAL(vmJumpAndInvoke_argumentLoop): + movq (%r8,%r11,1),%r10 + movq %r10,8(%rdx,%r11,1) + addq $8,%r11 + +LOCAL(vmJumpAndInvoke_argumentTest): + cmpq %rcx,%r11 + jb LOCAL(vmJumpAndInvoke_argumentLoop) + + // the arguments have been copied, so we can set the real stack + // pointer now + movq %rdx,%rsp + + jmp *%rsi +#else // not AVIAN_CONTINUATIONS + // vmJumpAndInvoke should only be called when continuations are + // enabled + int3 +#endif // not AVIAN_CONTINUATIONS + +#endif // not __MINGW32__ || __CYGWIN32__ + +#elif defined __i386__ + +#ifdef AVIAN_USE_FRAME_POINTER +# define ALIGNMENT_ADJUSTMENT 0 +#else +# define ALIGNMENT_ADJUSTMENT 12 +#endif + +#define CALLEE_SAVED_REGISTER_FOOTPRINT 16 + ALIGNMENT_ADJUSTMENT + +.globl GLOBAL(vmInvoke) +GLOBAL(vmInvoke): + pushl %ebp + movl %esp,%ebp + + // 8(%ebp): thread + // 12(%ebp): function + // 16(%ebp): arguments + // 20(%ebp): argumentFootprint + // 24(%ebp): frameSize + // 28(%ebp): returnType + + // allocate stack space for callee-saved registers + subl $CALLEE_SAVED_REGISTER_FOOTPRINT,%esp + + // remember this stack position, since we won't be able to rely on + // %rbp being restored when the call returns + movl 8(%ebp),%eax + movl %esp,TARGET_THREAD_SCRATCH(%eax) + + movl %ebx,0(%esp) + movl %esi,4(%esp) + movl %edi,8(%esp) + + // allocate stack space for arguments + subl 24(%ebp),%esp + + // we use ebx to hold the thread pointer, by convention + mov %eax,%ebx + + // copy arguments into place + movl $0,%ecx + movl 16(%ebp),%edx + jmp LOCAL(vmInvoke_argumentTest) + +LOCAL(vmInvoke_argumentLoop): + movl (%edx,%ecx,1),%eax + movl %eax,(%esp,%ecx,1) + addl $4,%ecx + +LOCAL(vmInvoke_argumentTest): + cmpl 20(%ebp),%ecx + jb LOCAL(vmInvoke_argumentLoop) + + // call function + call *12(%ebp) + +.globl GLOBAL(vmInvoke_returnAddress) +GLOBAL(vmInvoke_returnAddress): + // restore stack pointer + movl TARGET_THREAD_SCRATCH(%ebx),%esp + + // clear MyThread::stack to avoid confusing another thread calling + // java.lang.Thread.getStackTrace on this one. See + // MyProcess::getStackTrace in compile.cpp for details on how we get + // a reliable stack trace from a thread that might be interrupted at + // any point in its execution. + movl $0,TARGET_THREAD_STACK(%ebx) + +.globl GLOBAL(vmInvoke_safeStack) +GLOBAL(vmInvoke_safeStack): + +#ifdef AVIAN_CONTINUATIONS +# include "continuations-x86.S" +#endif // AVIAN_CONTINUATIONS + + // restore callee-saved registers + movl 0(%esp),%ebx + movl 4(%esp),%esi + movl 8(%esp),%edi + + addl $CALLEE_SAVED_REGISTER_FOOTPRINT,%esp + + // handle return value based on expected type + movl 28(%esp),%ecx + + popl %ebp + ret + +LOCAL(getPC): + movl (%esp),%esi + ret + +.globl GLOBAL(vmJumpAndInvoke) +GLOBAL(vmJumpAndInvoke): +#ifdef AVIAN_CONTINUATIONS + // 4(%esp): thread + // 8(%esp): address + // 12(%esp): stack + // 16(%esp): argumentFootprint + // 20(%esp): arguments + // 24(%esp): frameSize + + movl 12(%esp),%ecx + + // allocate new frame, adding room for callee-saved registers, + // return address, and frame pointer + subl 24(%esp),%ecx + subl $CALLEE_SAVED_REGISTER_FOOTPRINT+8,%ecx + + movl 4(%esp),%ebx + + // set return address +#if defined __MINGW32__ || defined __CYGWIN32__ + movl $GLOBAL(vmInvoke_returnAddress),%esi +#else + call LOCAL(getPC) +# if defined __APPLE__ +LOCAL(vmJumpAndInvoke_offset): + leal GLOBAL(vmInvoke_returnAddress)-LOCAL(vmJumpAndInvoke_offset)(%esi),%esi +# else + addl $_GLOBAL_OFFSET_TABLE_,%esi + movl GLOBAL(vmInvoke_returnAddress)@GOT(%esi),%esi +# endif +#endif + movl %esi,(%ecx) + + // copy arguments into place + movl $0,%esi + movl 16(%esp),%edx + movl 20(%esp),%eax + jmp LOCAL(vmJumpAndInvoke_argumentTest) + +LOCAL(vmJumpAndInvoke_argumentLoop): + movl (%eax,%esi,1),%edi + movl %edi,4(%ecx,%esi,1) + addl $4,%esi + +LOCAL(vmJumpAndInvoke_argumentTest): + cmpl %edx,%esi + jb LOCAL(vmJumpAndInvoke_argumentLoop) + + movl 8(%esp),%esi + + // the arguments have been copied, so we can set the real stack + // pointer now + movl %ecx,%esp + + jmp *%esi +#else // not AVIAN_CONTINUATIONS + // vmJumpAndInvoke should only be called when continuations are + // enabled + int3 +#endif // AVIAN_CONTINUATIONS + +#else +#error unsupported architecture +#endif //def __x86_64__ diff --git a/sgx-jvm/avian/src/compile-i386.masm b/sgx-jvm/avian/src/compile-i386.masm new file mode 100644 index 0000000000..aff4cabb94 --- /dev/null +++ b/sgx-jvm/avian/src/compile-i386.masm @@ -0,0 +1,173 @@ +comment # + Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. + + ORIGIN: https://github.com/gkvas/avian/tree/wince +# + +.586 +.MODEL FLAT, C + +comment # types.h # +VOID_TYPE equ 0 +INT8_TYPE equ 1 +INT16_TYPE equ 2 +INT32_TYPE equ 3 +INT64_TYPE equ 4 +FLOAT_TYPE equ 5 +DOUBLE_TYPE equ 6 +POINTER_TYPE equ 7 + +comment # target-fields.h # +ifdef TARGET_BYTES_PER_WORD + if TARGET_BYTES_PER_WORD eq 8 + +TARGET_THREAD_EXCEPTION equ 80 +TARGET_THREAD_EXCEPTIONSTACKADJUSTMENT equ 2256 +TARGET_THREAD_EXCEPTIONOFFSET equ 2264 +TARGET_THREAD_EXCEPTIONHANDLER equ 2272 + +TARGET_THREAD_IP equ 2216 +TARGET_THREAD_STACK equ 2224 +TARGET_THREAD_NEWSTACK equ 2232 +TARGET_THREAD_SCRATCH equ 2240 +TARGET_THREAD_CONTINUATION equ 2248 +TARGET_THREAD_TAILADDRESS equ 2280 +TARGET_THREAD_VIRTUALCALLTARGET equ 2288 +TARGET_THREAD_VIRTUALCALLINDEX equ 2296 +TARGET_THREAD_HEAPIMAGE equ 2304 +TARGET_THREAD_CODEIMAGE equ 2312 +TARGET_THREAD_THUNKTABLE equ 2320 +TARGET_THREAD_STACKLIMIT equ 2368 + + elseif TARGET_BYTES_PER_WORD eq 4 + +TARGET_THREAD_EXCEPTION equ 44 +TARGET_THREAD_EXCEPTIONSTACKADJUSTMENT equ 2164 +TARGET_THREAD_EXCEPTIONOFFSET equ 2168 +TARGET_THREAD_EXCEPTIONHANDLER equ 2172 + +TARGET_THREAD_IP equ 2144 +TARGET_THREAD_STACK equ 2148 +TARGET_THREAD_NEWSTACK equ 2152 +TARGET_THREAD_SCRATCH equ 2156 +TARGET_THREAD_CONTINUATION equ 2160 +TARGET_THREAD_TAILADDRESS equ 2176 +TARGET_THREAD_VIRTUALCALLTARGET equ 2180 +TARGET_THREAD_VIRTUALCALLINDEX equ 2184 +TARGET_THREAD_HEAPIMAGE equ 2188 +TARGET_THREAD_CODEIMAGE equ 2192 +TARGET_THREAD_THUNKTABLE equ 2196 +TARGET_THREAD_STACKLIMIT equ 2220 + + else + error + endif +else + error +endif + +ifdef AVIAN_USE_FRAME_POINTER + ALIGNMENT_ADJUSTMENT equ 0 +else + ALIGNMENT_ADJUSTMENT equ 12 +endif + +CALLEE_SAVED_REGISTER_FOOTPRINT equ 16 + ALIGNMENT_ADJUSTMENT + +_TEXT SEGMENT + +public C vmInvoke +vmInvoke: + push ebp + mov ebp,esp + + ; 8(%ebp): thread + ; 12(%ebp): function + ; 16(%ebp): arguments + ; 20(%ebp): argumentFootprint + ; 24(%ebp): frameSize + ; 28(%ebp): returnType + + ; allocate stack space for callee-saved registers + sub esp,offset CALLEE_SAVED_REGISTER_FOOTPRINT + + ; remember this stack position, since we won't be able to rely on + ; %rbp being restored when the call returns + mov eax,ds:dword ptr[8+ebp] + mov ds:dword ptr[TARGET_THREAD_SCRATCH+eax],esp + + mov ds:dword ptr[0+esp],ebx + mov ds:dword ptr[4+esp],esi + mov ds:dword ptr[8+esp],edi + + ; allocate stack space for arguments + sub esp,ds:dword ptr[24+ebp] + + ; we use ebx to hold the thread pointer, by convention + mov ebx,eax + + ; copy arguments into place + mov ecx,0 + mov edx,ds:dword ptr[16+ebp] + jmp LvmInvoke_argumentTest + +LvmInvoke_argumentLoop: + mov eax,ds:dword ptr[edx+ecx*1] + mov ds:dword ptr[esp+ecx*1],eax + add ecx,4 + +LvmInvoke_argumentTest: + cmp ecx,ds:dword ptr[20+ebp] + jb LvmInvoke_argumentLoop + + ; call function + call dword ptr[12+ebp] + +public vmInvoke_returnAddress +vmInvoke_returnAddress: + ; restore stack pointer + mov esp,ds:dword ptr[TARGET_THREAD_SCRATCH+ebx] + + ; clear MyThread::stack to avoid confusing another thread calling + ; java.lang.Thread.getStackTrace on this one. See + ; MyProcess::getStackTrace in compile.cpp for details on how we get + ; a reliable stack trace from a thread that might be interrupted at + ; any point in its execution. + mov ds:dword ptr[TARGET_THREAD_STACK+ebx],0 + +public vmInvoke_safeStack +vmInvoke_safeStack: + + ; restore callee-saved registers + mov ebx,ds:dword ptr[0+esp] + mov esi,ds:dword ptr[4+esp] + mov edi,ds:dword ptr[8+esp] + + add esp,offset CALLEE_SAVED_REGISTER_FOOTPRINT + + mov ecx,ds:dword ptr[28+esp] + + pop ebp + ret + +LgetPC: + mov esi,ds:dword ptr[esp] + ret + +public vmJumpAndInvoke +vmJumpAndInvoke: + ; vmJumpAndInvoke should only be called when continuations are + ; enabled + int 3 + +_TEXT ENDS + +END diff --git a/sgx-jvm/avian/src/compile-x86_64.S b/sgx-jvm/avian/src/compile-x86_64.S new file mode 100644 index 0000000000..d6ddd2052f --- /dev/null +++ b/sgx-jvm/avian/src/compile-x86_64.S @@ -0,0 +1,455 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#include "avian/types.h" +#include "avian/target-fields.h" + +#define LOCAL(x) .L##x + +#if defined __APPLE__ \ + || ((defined __MINGW32__ || defined __CYGWIN32__) && ! defined __x86_64__) +# define GLOBAL(x) _##x +#else +# define GLOBAL(x) x +#endif + +.text + +#ifdef __x86_64__ + +#ifdef AVIAN_USE_FRAME_POINTER +# define ALIGNMENT_ADJUSTMENT 0 +#else +# define ALIGNMENT_ADJUSTMENT 8 +#endif + +#if defined __MINGW32__ || defined __CYGWIN32__ + +#define CALLEE_SAVED_REGISTER_FOOTPRINT 64 + ALIGNMENT_ADJUSTMENT + +.globl GLOBAL(vmInvoke) +GLOBAL(vmInvoke): + pushq %rbp + movq %rsp,%rbp + + // %rcx: thread + // %rdx: function + // %r8 : arguments + // %r9 : argumentsFootprint + // 48(%rbp) : frameSize + // 56(%rbp) : returnType (ignored) + + // allocate stack space for callee-saved registers + subq $CALLEE_SAVED_REGISTER_FOOTPRINT,%rsp + + // remember this stack position, since we won't be able to rely on + // %rbp being restored when the call returns + movq %rsp,TARGET_THREAD_SCRATCH(%rcx) + + // save callee-saved registers + movq %rbx,0(%rsp) + movq %r12,8(%rsp) + movq %r13,16(%rsp) + movq %r14,24(%rsp) + movq %r15,32(%rsp) + movq %rsi,40(%rsp) + movq %rdi,48(%rsp) + + // allocate stack space for arguments + movl 48(%rbp),%eax + subq %rax,%rsp + + // we use rbx to hold the thread pointer, by convention + mov %rcx,%rbx + + // copy arguments into place + movq $0,%r11 + jmp LOCAL(vmInvoke_argumentTest) + +LOCAL(vmInvoke_argumentLoop): + movq (%r8,%r11,1),%rsi + movq %rsi,(%rsp,%r11,1) + addq $8,%r11 + +LOCAL(vmInvoke_argumentTest): + cmpq %r9,%r11 + jb LOCAL(vmInvoke_argumentLoop) + + // call function + call *%rdx + +.globl GLOBAL(vmInvoke_returnAddress) +GLOBAL(vmInvoke_returnAddress): + // restore stack pointer + movq TARGET_THREAD_SCRATCH(%rbx),%rsp + + // clear MyThread::stack to avoid confusing another thread calling + // java.lang.Thread.getStackTrace on this one. See + // MyProcess::getStackTrace in compile.cpp for details on how we get + // a reliable stack trace from a thread that might be interrupted at + // any point in its execution. + movq $0,TARGET_THREAD_STACK(%rbx) + +.globl GLOBAL(vmInvoke_safeStack) +GLOBAL(vmInvoke_safeStack): + +#ifdef AVIAN_CONTINUATIONS +# include "continuations-x86.S" +#endif // AVIAN_CONTINUATIONS + + // restore callee-saved registers + movq 0(%rsp),%rbx + movq 8(%rsp),%r12 + movq 16(%rsp),%r13 + movq 24(%rsp),%r14 + movq 32(%rsp),%r15 + movq 40(%rsp),%rsi + movq 48(%rsp),%rdi + + addq $CALLEE_SAVED_REGISTER_FOOTPRINT,%rsp + + // return + popq %rbp + ret + +.globl GLOBAL(vmJumpAndInvoke) +GLOBAL(vmJumpAndInvoke): +#ifdef AVIAN_CONTINUATIONS + // %rcx: thread + // %rdx: address + // %r8 : stack + // %r9 : argumentFootprint + // 40(%rsp): arguments + // 48(%rsp): frameSize + + // allocate new frame, adding room for callee-saved registers + movl 48(%rsp),%eax + subq %rax,%r8 + subq $CALLEE_SAVED_REGISTER_FOOTPRINT,%r8 + + movq %rcx,%rbx + + // set return address + leaq GLOBAL(vmInvoke_returnAddress)(%rip),%r10 + movq %r10,(%r8) + + // copy arguments into place + movq $0,%r11 + movl 40(%rsp),%eax + jmp LOCAL(vmJumpAndInvoke_argumentTest) + +LOCAL(vmJumpAndInvoke_argumentLoop): + movq (%rax,%r11,1),%r10 + movq %r10,8(%r8,%r11,1) + addq $8,%r11 + +LOCAL(vmJumpAndInvoke_argumentTest): + cmpq %r9,%r11 + jb LOCAL(vmJumpAndInvoke_argumentLoop) + + // the arguments have been copied, so we can set the real stack + // pointer now + movq %r8,%rsp + + jmp *%rdx +#else // not AVIAN_CONTINUATIONS + // vmJumpAndInvoke should only be called when continuations are + // enabled + int3 +#endif // not AVIAN_CONTINUATIONS + +#else // not __MINGW32__ || __CYGWIN32__ + +#define CALLEE_SAVED_REGISTER_FOOTPRINT 48 + ALIGNMENT_ADJUSTMENT + +.globl GLOBAL(vmInvoke) +GLOBAL(vmInvoke): + pushq %rbp + movq %rsp,%rbp + + // %rdi: thread + // %rsi: function + // %rdx: arguments + // %rcx: argumentFootprint + // %r8 : frameSize + // %r9 : returnType (ignored) + + // allocate stack space for callee-saved registers + subq $CALLEE_SAVED_REGISTER_FOOTPRINT,%rsp + + // remember this stack position, since we won't be able to rely on + // %rbp being restored when the call returns + movq %rsp,TARGET_THREAD_SCRATCH(%rdi) + + // save callee-saved registers + movq %rbx,0(%rsp) + movq %r12,8(%rsp) + movq %r13,16(%rsp) + movq %r14,24(%rsp) + movq %r15,32(%rsp) + + // allocate stack space for arguments + subq %r8,%rsp + + // we use rbx to hold the thread pointer, by convention + mov %rdi,%rbx + + // copy arguments into place + movq $0,%r9 + jmp LOCAL(vmInvoke_argumentTest) + +LOCAL(vmInvoke_argumentLoop): + movq (%rdx,%r9,1),%r8 + movq %r8,(%rsp,%r9,1) + addq $8,%r9 + +LOCAL(vmInvoke_argumentTest): + cmpq %rcx,%r9 + jb LOCAL(vmInvoke_argumentLoop) + + // call function + call *%rsi + +.globl GLOBAL(vmInvoke_returnAddress) +GLOBAL(vmInvoke_returnAddress): + // restore stack pointer + movq TARGET_THREAD_SCRATCH(%rbx),%rsp + + // clear MyThread::stack to avoid confusing another thread calling + // java.lang.Thread.getStackTrace on this one. See + // MyProcess::getStackTrace in compile.cpp for details on how we get + // a reliable stack trace from a thread that might be interrupted at + // any point in its execution. + movq $0,TARGET_THREAD_STACK(%rbx) + +.globl GLOBAL(vmInvoke_safeStack) +GLOBAL(vmInvoke_safeStack): + +#ifdef AVIAN_CONTINUATIONS +# include "continuations-x86.S" +#endif // AVIAN_CONTINUATIONS + + // restore callee-saved registers + movq 0(%rsp),%rbx + movq 8(%rsp),%r12 + movq 16(%rsp),%r13 + movq 24(%rsp),%r14 + movq 32(%rsp),%r15 + + addq $CALLEE_SAVED_REGISTER_FOOTPRINT,%rsp + + // return + popq %rbp + ret + +.globl GLOBAL(vmJumpAndInvoke) +GLOBAL(vmJumpAndInvoke): +#ifdef AVIAN_CONTINUATIONS + // %rdi: thread + // %rsi: address + // %rdx: stack + // %rcx: argumentFootprint + // %r8 : arguments + // %r9 : frameSize + + // allocate new frame, adding room for callee-saved registers + subq %r9,%rdx + subq $CALLEE_SAVED_REGISTER_FOOTPRINT,%rdx + + movq %rdi,%rbx + + // set return address + movq GLOBAL(vmInvoke_returnAddress)@GOTPCREL(%rip),%r10 + movq %r10,(%rdx) + + // copy arguments into place + movq $0,%r11 + jmp LOCAL(vmJumpAndInvoke_argumentTest) + +LOCAL(vmJumpAndInvoke_argumentLoop): + movq (%r8,%r11,1),%r10 + movq %r10,8(%rdx,%r11,1) + addq $8,%r11 + +LOCAL(vmJumpAndInvoke_argumentTest): + cmpq %rcx,%r11 + jb LOCAL(vmJumpAndInvoke_argumentLoop) + + // the arguments have been copied, so we can set the real stack + // pointer now + movq %rdx,%rsp + + jmp *%rsi +#else // not AVIAN_CONTINUATIONS + // vmJumpAndInvoke should only be called when continuations are + // enabled + int3 +#endif // not AVIAN_CONTINUATIONS + +#endif // not __MINGW32__ || __CYGWIN32__ + +#elif defined __i386__ + +#ifdef AVIAN_USE_FRAME_POINTER +# define ALIGNMENT_ADJUSTMENT 0 +#else +# define ALIGNMENT_ADJUSTMENT 12 +#endif + +#define CALLEE_SAVED_REGISTER_FOOTPRINT 16 + ALIGNMENT_ADJUSTMENT + +.globl GLOBAL(vmInvoke) +GLOBAL(vmInvoke): + pushl %ebp + movl %esp,%ebp + + // 8(%ebp): thread + // 12(%ebp): function + // 16(%ebp): arguments + // 20(%ebp): argumentFootprint + // 24(%ebp): frameSize + // 28(%ebp): returnType + + // allocate stack space for callee-saved registers + subl $CALLEE_SAVED_REGISTER_FOOTPRINT,%esp + + // remember this stack position, since we won't be able to rely on + // %rbp being restored when the call returns + movl 8(%ebp),%eax + movl %esp,TARGET_THREAD_SCRATCH(%eax) + + movl %ebx,0(%esp) + movl %esi,4(%esp) + movl %edi,8(%esp) + + // allocate stack space for arguments + subl 24(%ebp),%esp + + // we use ebx to hold the thread pointer, by convention + mov %eax,%ebx + + // copy arguments into place + movl $0,%ecx + movl 16(%ebp),%edx + jmp LOCAL(vmInvoke_argumentTest) + +LOCAL(vmInvoke_argumentLoop): + movl (%edx,%ecx,1),%eax + movl %eax,(%esp,%ecx,1) + addl $4,%ecx + +LOCAL(vmInvoke_argumentTest): + cmpl 20(%ebp),%ecx + jb LOCAL(vmInvoke_argumentLoop) + + // call function + call *12(%ebp) + +.globl GLOBAL(vmInvoke_returnAddress) +GLOBAL(vmInvoke_returnAddress): + // restore stack pointer + movl TARGET_THREAD_SCRATCH(%ebx),%esp + + // clear MyThread::stack to avoid confusing another thread calling + // java.lang.Thread.getStackTrace on this one. See + // MyProcess::getStackTrace in compile.cpp for details on how we get + // a reliable stack trace from a thread that might be interrupted at + // any point in its execution. + movl $0,TARGET_THREAD_STACK(%ebx) + +.globl GLOBAL(vmInvoke_safeStack) +GLOBAL(vmInvoke_safeStack): + +#ifdef AVIAN_CONTINUATIONS +# include "continuations-x86.S" +#endif // AVIAN_CONTINUATIONS + + // restore callee-saved registers + movl 0(%esp),%ebx + movl 4(%esp),%esi + movl 8(%esp),%edi + + addl $CALLEE_SAVED_REGISTER_FOOTPRINT,%esp + + // handle return value based on expected type + movl 28(%esp),%ecx + + popl %ebp + ret + +LOCAL(getPC): + movl (%esp),%esi + ret + +.globl GLOBAL(vmJumpAndInvoke) +GLOBAL(vmJumpAndInvoke): +#ifdef AVIAN_CONTINUATIONS + // 4(%esp): thread + // 8(%esp): address + // 12(%esp): stack + // 16(%esp): argumentFootprint + // 20(%esp): arguments + // 24(%esp): frameSize + + movl 12(%esp),%ecx + + // allocate new frame, adding room for callee-saved registers, + // return address, and frame pointer + subl 24(%esp),%ecx + subl $CALLEE_SAVED_REGISTER_FOOTPRINT+8,%ecx + + movl 4(%esp),%ebx + + // set return address +#if defined __MINGW32__ || defined __CYGWIN32__ + movl $GLOBAL(vmInvoke_returnAddress),%esi +#else + call LOCAL(getPC) +# if defined __APPLE__ +LOCAL(vmJumpAndInvoke_offset): + leal GLOBAL(vmInvoke_returnAddress)-LOCAL(vmJumpAndInvoke_offset)(%esi),%esi +# else + addl $_GLOBAL_OFFSET_TABLE_,%esi + movl GLOBAL(vmInvoke_returnAddress)@GOT(%esi),%esi +# endif +#endif + movl %esi,(%ecx) + + // copy arguments into place + movl $0,%esi + movl 16(%esp),%edx + movl 20(%esp),%eax + jmp LOCAL(vmJumpAndInvoke_argumentTest) + +LOCAL(vmJumpAndInvoke_argumentLoop): + movl (%eax,%esi,1),%edi + movl %edi,4(%ecx,%esi,1) + addl $4,%esi + +LOCAL(vmJumpAndInvoke_argumentTest): + cmpl %edx,%esi + jb LOCAL(vmJumpAndInvoke_argumentLoop) + + movl 8(%esp),%esi + + // the arguments have been copied, so we can set the real stack + // pointer now + movl %ecx,%esp + + jmp *%esi +#else // not AVIAN_CONTINUATIONS + // vmJumpAndInvoke should only be called when continuations are + // enabled + int3 +#endif // AVIAN_CONTINUATIONS + +#else +#error unsupported architecture +#endif //def __x86_64__ diff --git a/sgx-jvm/avian/src/compile.cpp b/sgx-jvm/avian/src/compile.cpp new file mode 100644 index 0000000000..4b3969a9e5 --- /dev/null +++ b/sgx-jvm/avian/src/compile.cpp @@ -0,0 +1,10778 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#include "avian/machine.h" +#include "avian/util.h" +#include "avian/alloc-vector.h" +#include "avian/process.h" +#include "avian/target.h" +#include "avian/arch.h" + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "debug-util.h" + +using namespace vm; + +extern "C" uint64_t vmInvoke(void* thread, + void* function, + void* arguments, + unsigned argumentFootprint, + unsigned frameSize, + unsigned returnType); + +extern "C" void vmInvoke_returnAddress(); + +extern "C" void vmInvoke_safeStack(); + +extern "C" void vmJumpAndInvoke(void* thread, + void* function, + void* stack, + unsigned argumentFootprint, + uintptr_t* arguments, + unsigned frameSize); + +using namespace avian::codegen; +using namespace avian::system; + +namespace { + +namespace local { + +const bool DebugCompile = false; +const bool DebugNatives = false; +const bool DebugCallTable = false; +const bool DebugMethodTree = false; +const bool DebugInstructions = false; + +#ifndef AVIAN_AOT_ONLY +const bool DebugFrameMaps = false; +const bool CheckArrayBounds = true; +const unsigned ExecutableAreaSizeInBytes = 30 * 1024 * 1024; +#endif + +#ifdef AVIAN_CONTINUATIONS +const bool Continuations = true; +#else +const bool Continuations = false; +#endif + +const unsigned MaxNativeCallFootprint = TargetBytesPerWord == 8 ? 4 : 5; + +const unsigned InitialZoneCapacityInBytes = 64 * 1024; + +enum ThunkIndex { + compileMethodIndex, + compileVirtualMethodIndex, + linkDynamicMethodIndex, + invokeNativeIndex, + throwArrayIndexOutOfBoundsIndex, + throwStackOverflowIndex, + +#define THUNK(s) s##Index, +#include "thunks.cpp" +#undef THUNK + dummyIndex +}; + +inline bool isVmInvokeUnsafeStack(void* ip) +{ + return reinterpret_cast(ip) + >= reinterpret_cast(voidPointer(vmInvoke_returnAddress)) + and reinterpret_cast(ip) + < reinterpret_cast(voidPointer(vmInvoke_safeStack)); +} + +class MyThread; + +void* getIp(MyThread*); + +class MyThread : public Thread { + public: + class CallTrace { + public: + CallTrace(MyThread* t, GcMethod* method) + : t(t), + ip(getIp(t)), + stack(t->stack), + scratch(t->scratch), + continuation(t->continuation), + nativeMethod((method->flags() & ACC_NATIVE) ? method : 0), + targetMethod(0), + originalMethod(method), + next(t->trace) + { + doTransition(t, 0, 0, 0, this); + } + + ~CallTrace() + { + assertT(t, t->stack == 0); + + t->scratch = scratch; + + doTransition(t, ip, stack, continuation, next); + } + + MyThread* t; + void* ip; + void* stack; + void* scratch; + GcContinuation* continuation; + GcMethod* nativeMethod; + GcMethod* targetMethod; + GcMethod* originalMethod; + CallTrace* next; + }; + + class Context { + public: + class MyProtector : public Thread::Protector { + public: + MyProtector(MyThread* t, Context* context) + : Protector(t), context(context) + { + } + + virtual void visit(Heap::Visitor* v) + { + v->visit(&(context->continuation)); + } + + Context* context; + }; + + Context(MyThread* t, + void* ip, + void* stack, + GcContinuation* continuation, + CallTrace* trace) + : ip(ip), + stack(stack), + continuation(continuation), + trace(trace), + protector(t, this) + { + } + + void* ip; + void* stack; + GcContinuation* continuation; + CallTrace* trace; + MyProtector protector; + }; + + class TraceContext : public Context { + public: + TraceContext(MyThread* t, + void* ip, + void* stack, + GcContinuation* continuation, + CallTrace* trace) + : Context(t, ip, stack, continuation, trace), + t(t), + link(0), + next(t->traceContext), + methodIsMostRecent(false) + { + t->traceContext = this; + } + + TraceContext(MyThread* t, void* link) + : Context(t, t->ip, t->stack, t->continuation, t->trace), + t(t), + link(link), + next(t->traceContext), + methodIsMostRecent(false) + { + t->traceContext = this; + } + + ~TraceContext() + { + t->traceContext = next; + } + + MyThread* t; + void* link; + TraceContext* next; + bool methodIsMostRecent; + }; + + static void doTransition(MyThread* t, + void* ip, + void* stack, + GcContinuation* continuation, + MyThread::CallTrace* trace) + { + // in this function, we "atomically" update the thread context + // fields in such a way to ensure that another thread may + // interrupt us at any time and still get a consistent, accurate + // stack trace. See MyProcessor::getStackTrace for details. + + assertT(t, t->transition == 0); + + Context c(t, ip, stack, continuation, trace); + + compileTimeMemoryBarrier(); + + t->transition = &c; + + compileTimeMemoryBarrier(); + + t->ip = ip; + t->stack = stack; + t->continuation = continuation; + t->trace = trace; + + compileTimeMemoryBarrier(); + + t->transition = 0; + } + + MyThread(Machine* m, + GcThread* javaThread, + MyThread* parent, + bool useNativeFeatures) + : Thread(m, javaThread, parent), + ip(0), + stack(0), + newStack(0), + scratch(0), + continuation(0), + exceptionStackAdjustment(0), + exceptionOffset(0), + exceptionHandler(0), + tailAddress(0), + virtualCallTarget(0), + virtualCallIndex(0), + heapImage(0), + codeImage(0), + thunkTable(0), + dynamicTable(0), + trace(0), + reference(0), + arch(parent ? parent->arch : avian::codegen::makeArchitectureNative( + m->system, + useNativeFeatures)), + transition(0), + traceContext(0), + stackLimit(0), + referenceFrame(0), + methodLockIsClean(true) + { + arch->acquire(); + } + + void* ip; + void* stack; + void* newStack; + void* scratch; + GcContinuation* continuation; + uintptr_t exceptionStackAdjustment; + uintptr_t exceptionOffset; + void* exceptionHandler; + void* tailAddress; + void* virtualCallTarget; + uintptr_t virtualCallIndex; + uintptr_t* heapImage; + uint8_t* codeImage; + void** thunkTable; + void** dynamicTable; + CallTrace* trace; + Reference* reference; + avian::codegen::Architecture* arch; + Context* transition; + TraceContext* traceContext; + uintptr_t stackLimit; + List* referenceFrame; + bool methodLockIsClean; +}; + +void transition(MyThread* t, + void* ip, + void* stack, + GcContinuation* continuation, + MyThread::CallTrace* trace) +{ + MyThread::doTransition(t, ip, stack, continuation, trace); +} + +object resolveThisPointer(MyThread* t, void* stack) +{ + return reinterpret_cast( + stack)[t->arch->frameFooterSize() + t->arch->frameReturnAddressSize()]; +} + +GcMethod* findMethod(Thread* t, GcMethod* method, object instance) +{ + if ((method->flags() & ACC_STATIC) == 0) { + if (method->class_()->flags() & ACC_INTERFACE) { + return findInterfaceMethod(t, method, objectClass(t, instance)); + } else if (methodVirtual(t, method)) { + return findVirtualMethod(t, method, objectClass(t, instance)); + } + } + return method; +} + +GcMethod* resolveTarget(MyThread* t, void* stack, GcMethod* method) +{ + GcClass* class_ = objectClass(t, resolveThisPointer(t, stack)); + + if (class_->vmFlags() & BootstrapFlag) { + PROTECT(t, method); + PROTECT(t, class_); + + resolveSystemClass(t, roots(t)->bootLoader(), class_->name()); + } + + if (method->class_()->flags() & ACC_INTERFACE) { + return findInterfaceMethod(t, method, class_); + } else { + return findVirtualMethod(t, method, class_); + } +} + +GcMethod* resolveTarget(MyThread* t, GcClass* class_, unsigned index) +{ + if (class_->vmFlags() & BootstrapFlag) { + PROTECT(t, class_); + + resolveSystemClass(t, roots(t)->bootLoader(), class_->name()); + } + + return cast( + t, cast(t, class_->virtualTable())->body()[index]); +} + +GcCompileRoots* compileRoots(Thread* t); + +intptr_t methodCompiled(Thread* t UNUSED, GcMethod* method) +{ + return method->code()->compiled(); +} + +unsigned methodCompiledSize(Thread* t UNUSED, GcMethod* method) +{ + return method->code()->compiledSize(); +} + +intptr_t compareIpToMethodBounds(Thread* t, intptr_t ip, object om) +{ + GcMethod* method = cast(t, om); + intptr_t start = methodCompiled(t, method); + + if (DebugMethodTree) { + fprintf(stderr, + "find %p in (%p,%p)\n", + reinterpret_cast(ip), + reinterpret_cast(start), + reinterpret_cast(start + methodCompiledSize(t, method))); + } + + if (ip < start) { + return -1; + } else if (ip < start + + static_cast(methodCompiledSize(t, method))) { + return 0; + } else { + return 1; + } +} + +GcMethod* methodForIp(MyThread* t, void* ip) +{ + if (DebugMethodTree) { + fprintf(stderr, "query for method containing %p\n", ip); + } + + // we must use a version of the method tree at least as recent as the + // compiled form of the method containing the specified address (see + // compile(MyThread*, FixedAllocator*, BootContext*, object)): + loadMemoryBarrier(); + + return cast(t, + treeQuery(t, + compileRoots(t)->methodTree(), + reinterpret_cast(ip), + compileRoots(t)->methodTreeSentinal(), + compareIpToMethodBounds)); +} + +unsigned localSize(MyThread* t UNUSED, GcMethod* method) +{ + unsigned size = method->code()->maxLocals(); + if ((method->flags() & (ACC_SYNCHRONIZED | ACC_STATIC)) == ACC_SYNCHRONIZED) { + ++size; + } + return size; +} + +unsigned alignedFrameSize(MyThread* t, GcMethod* method) +{ + return t->arch->alignFrameSize( + localSize(t, method) - method->parameterFootprint() + + method->code()->maxStack() + + t->arch->frameFootprint(MaxNativeCallFootprint)); +} + +void nextFrame(MyThread* t, + void** ip, + void** sp, + GcMethod* method, + GcMethod* target, + bool mostRecent) +{ + GcCode* code = method->code(); + intptr_t start = code->compiled(); + void* link; + bool methodIsMostRecent; + + if (t->traceContext) { + link = t->traceContext->link; + methodIsMostRecent = mostRecent and t->traceContext->methodIsMostRecent; + } else { + link = 0; + methodIsMostRecent = false; + } + + if (false) { + fprintf(stderr, + "nextFrame %s.%s%s target %s.%s%s ip %p sp %p\n", + method->class_()->name()->body().begin(), + method->name()->body().begin(), + method->spec()->body().begin(), + target ? target->class_()->name()->body().begin() : 0, + target ? target->name()->body().begin() : 0, + target ? target->spec()->body().begin() : 0, + *ip, + *sp); + } + + t->arch->nextFrame(reinterpret_cast(start), + code->compiledSize(), + alignedFrameSize(t, method), + link, + methodIsMostRecent, + target ? target->parameterFootprint() : -1, + ip, + sp); + + if (false) { + fprintf(stderr, "next frame ip %p sp %p\n", *ip, *sp); + } +} + +void* getIp(MyThread* t, void* ip, void* stack) +{ + // Here we use the convention that, if the return address is neither + // pushed on to the stack automatically as part of the call nor + // stored in the caller's frame, it will be saved in MyThread::ip + // instead of on the stack. See the various implementations of + // Assembler::saveFrame for details on how this is done. + return t->arch->returnAddressOffset() < 0 ? ip : t->arch->frameIp(stack); +} + +void* getIp(MyThread* t) +{ + return getIp(t, t->ip, t->stack); +} + +class MyStackWalker : public Processor::StackWalker { + public: + enum State { Start, Next, Trace, Continuation, Method, NativeMethod, Finish }; + + class MyProtector : public Thread::Protector { + public: + MyProtector(MyStackWalker* walker) : Protector(walker->t), walker(walker) + { + } + + virtual void visit(Heap::Visitor* v) + { + v->visit(&(walker->method_)); + v->visit(&(walker->target)); + v->visit(&(walker->continuation)); + } + + MyStackWalker* walker; + }; + + MyStackWalker(MyThread* t) + : t(t), state(Start), method_(0), target(0), count_(0), protector(this) + { + if (t->traceContext) { + ip_ = t->traceContext->ip; + stack = t->traceContext->stack; + trace = t->traceContext->trace; + continuation = t->traceContext->continuation; + } else { + ip_ = getIp(t); + stack = t->stack; + trace = t->trace; + continuation = t->continuation; + } + } + + MyStackWalker(MyStackWalker* w) + : t(w->t), + state(w->state), + ip_(w->ip_), + stack(w->stack), + trace(w->trace), + method_(w->method_), + target(w->target), + continuation(w->continuation), + count_(w->count_), + protector(this) + { + } + + virtual void walk(Processor::StackVisitor* v) + { + for (MyStackWalker it(this); it.valid();) { + MyStackWalker walker(&it); + if (not v->visit(&walker)) { + break; + } + it.next(); + } + } + + bool valid() + { + while (true) { + if (false) { + fprintf(stderr, "state: %d\n", state); + } + switch (state) { + case Start: + if (trace and trace->nativeMethod) { + method_ = trace->nativeMethod; + state = NativeMethod; + } else { + state = Next; + } + break; + + case Next: + if (stack) { + target = method_; + method_ = methodForIp(t, ip_); + if (method_) { + state = Method; + } else if (continuation) { + method_ = continuation->method(); + state = Continuation; + } else { + state = Trace; + } + } else { + state = Trace; + } + break; + + case Trace: { + if (trace) { + continuation = trace->continuation; + stack = trace->stack; + ip_ = trace->ip; + trace = trace->next; + + state = Start; + } else { + state = Finish; + } + } break; + + case Continuation: + case Method: + case NativeMethod: + return true; + + case Finish: + return false; + + default: + abort(t); + } + } + } + + void next() + { + expect(t, count_ <= stackSizeInWords(t)); + + switch (state) { + case Continuation: + continuation = continuation->next(); + break; + + case Method: + nextFrame(t, &ip_, &stack, method_, target, count_ == 0); + break; + + case NativeMethod: + break; + + default: + abort(t); + } + + ++count_; + + state = Next; + } + + virtual GcMethod* method() + { + if (false) { + fprintf(stderr, + "method %s.%s\n", + method_->class_()->name()->body().begin(), + method_->name()->body().begin()); + } + return method_; + } + + virtual int ip() + { + switch (state) { + case Continuation: + return reinterpret_cast(continuation->address()) + - methodCompiled(t, continuation->method()); + + case Method: + return reinterpret_cast(ip_) - methodCompiled(t, method_); + + case NativeMethod: + return 0; + + default: + abort(t); + } + } + + virtual unsigned count() + { + unsigned count = 0; + + for (MyStackWalker walker(this); walker.valid();) { + walker.next(); + ++count; + } + + return count; + } + + MyThread* t; + State state; + void* ip_; + void* stack; + MyThread::CallTrace* trace; + GcMethod* method_; + GcMethod* target; + GcContinuation* continuation; + unsigned count_; + MyProtector protector; +}; + +int localOffset(MyThread* t, int v, GcMethod* method) +{ + int parameterFootprint = method->parameterFootprint(); + int frameSize = alignedFrameSize(t, method); + + int offset + = ((v < parameterFootprint) + ? (frameSize + parameterFootprint + t->arch->frameFooterSize() + + t->arch->frameHeaderSize() - v - 1) + : (frameSize + parameterFootprint - v - 1)); + + assertT(t, offset >= 0); + return offset; +} + +int localOffsetFromStack(MyThread* t, int index, GcMethod* method) +{ + return localOffset(t, index, method) + t->arch->frameReturnAddressSize(); +} + +object* localObject(MyThread* t, void* stack, GcMethod* method, unsigned index) +{ + return static_cast(stack) + localOffsetFromStack(t, index, method); +} + +int stackOffsetFromFrame(MyThread* t, GcMethod* method) +{ + return alignedFrameSize(t, method) + t->arch->frameHeaderSize(); +} + +void* stackForFrame(MyThread* t, void* frame, GcMethod* method) +{ + return static_cast(frame) - stackOffsetFromFrame(t, method); +} + +class PoolElement : public avian::codegen::Promise { + public: + PoolElement(Thread* t, object target, PoolElement* next) + : t(t), target(target), address(0), next(next) + { + } + + virtual int64_t value() + { + assertT(t, resolved()); + return address; + } + + virtual bool resolved() + { + return address != 0; + } + + Thread* t; + object target; + intptr_t address; + PoolElement* next; +}; + +class Subroutine { + public: + Subroutine(unsigned index, + unsigned returnAddress, + unsigned methodSize, + Subroutine* outer) + : index(index), + outer(outer), + returnAddress(returnAddress), + duplicatedBaseIp(methodSize * index), + visited(false) + { + } + + // Index of this subroutine, in the (unmaterialized) list of subroutines in + // this method. + // Note that in the presence of nested finallys, this could theoretically end + // up being greater than the number of jsr instructions (but this will be + // extremely rare - I don't think we've seen this in practice). + const unsigned index; + + // Subroutine outer to this one (if, for instance, we have nested finallys) + Subroutine* const outer; + + // Starting ip in the original bytecode (always < original bytecode size) + const unsigned returnAddress; + + // Starting ip for this subroutine's copy of the method bytecode + const unsigned duplicatedBaseIp; + + bool visited; +}; + +class Context; + +class TraceElement : public avian::codegen::TraceHandler { + public: + static const unsigned VirtualCall = 1 << 0; + static const unsigned TailCall = 1 << 1; + static const unsigned LongCall = 1 << 2; + + TraceElement(Context* context, + unsigned ip, + GcMethod* target, + unsigned flags, + TraceElement* next, + unsigned mapSize) + : context(context), + address(0), + next(next), + target(target), + ip(ip), + argumentIndex(0), + flags(flags), + watch(false) + { + memset(map, 0xFF, mapSize * BytesPerWord); + } + + virtual void handleTrace(avian::codegen::Promise* address, + unsigned argumentIndex) + { + if (this->address == 0) { + this->address = address; + this->argumentIndex = argumentIndex; + } + } + + Context* context; + avian::codegen::Promise* address; + TraceElement* next; + GcMethod* target; + unsigned ip; + unsigned argumentIndex; + unsigned flags; + bool watch; + uintptr_t map[0]; +}; + +class TraceElementPromise : public avian::codegen::Promise { + public: + TraceElementPromise(System* s, TraceElement* trace) : s(s), trace(trace) + { + } + + virtual int64_t value() + { + assertT(s, resolved()); + return trace->address->value(); + } + + virtual bool resolved() + { + return trace->address != 0 and trace->address->resolved(); + } + + System* s; + TraceElement* trace; +}; + +enum Event { + PushContextEvent, + PopContextEvent, + IpEvent, + MarkEvent, + ClearEvent, + PushExceptionHandlerEvent, + TraceEvent, +}; + +unsigned frameMapSizeInBits(MyThread* t, GcMethod* method) +{ + return localSize(t, method) + method->code()->maxStack(); +} + +unsigned frameMapSizeInWords(MyThread* t, GcMethod* method) +{ + return ceilingDivide(frameMapSizeInBits(t, method), BitsPerWord); +} + +enum Thunk { +#define THUNK(s) s##Thunk, + +#include "thunks.cpp" + +#undef THUNK +}; + +const unsigned ThunkCount = idleIfNecessaryThunk + 1; + +intptr_t getThunk(MyThread* t, Thunk thunk); + +class BootContext { + public: + class MyProtector : public Thread::Protector { + public: + MyProtector(Thread* t, BootContext* c) : Protector(t), c(c) + { + } + + virtual void visit(Heap::Visitor* v) + { + v->visit(&(c->constants)); + v->visit(&(c->calls)); + } + + BootContext* c; + }; + + BootContext(Thread* t, + GcTriple* constants, + GcTriple* calls, + avian::codegen::DelayedPromise* addresses, + Zone* zone, + OffsetResolver* resolver, + JavaVM* hostVM) + : protector(t, this), + constants(constants), + calls(calls), + addresses(addresses), + addressSentinal(addresses), + zone(zone), + resolver(resolver), + hostVM(hostVM) + { + } + + MyProtector protector; + GcTriple* constants; + GcTriple* calls; + avian::codegen::DelayedPromise* addresses; + avian::codegen::DelayedPromise* addressSentinal; + Zone* zone; + OffsetResolver* resolver; + JavaVM* hostVM; +}; + +class Context { + public: + class MyResource : public Thread::AutoResource { + public: + MyResource(Context* c) : AutoResource(c->thread), c(c) + { + } + + virtual void release() + { + c->dispose(); + } + + Context* c; + }; + + class MyProtector : public Thread::Protector { + public: + MyProtector(Context* c) : Protector(c->thread), c(c) + { + } + + virtual void visit(Heap::Visitor* v) + { + v->visit(&(c->method)); + + for (PoolElement* p = c->objectPool; p; p = p->next) { + v->visit(&(p->target)); + } + + for (TraceElement* p = c->traceLog; p; p = p->next) { + v->visit(&(p->target)); + } + } + + Context* c; + }; + + class MyClient : public Compiler::Client { + public: + MyClient(MyThread* t) : t(t) + { + } + + virtual intptr_t getThunk(avian::codegen::lir::UnaryOperation, unsigned) + { + abort(t); + } + + virtual intptr_t getThunk(avian::codegen::lir::BinaryOperation op, + unsigned size, + unsigned resultSize) + { + if (size == 8) { + switch (op) { + case avian::codegen::lir::Absolute: + assertT(t, resultSize == 8); + return local::getThunk(t, absoluteLongThunk); + + case avian::codegen::lir::FloatNegate: + assertT(t, resultSize == 8); + return local::getThunk(t, negateDoubleThunk); + + case avian::codegen::lir::FloatSquareRoot: + assertT(t, resultSize == 8); + return local::getThunk(t, squareRootDoubleThunk); + + case avian::codegen::lir::Float2Float: + assertT(t, resultSize == 4); + return local::getThunk(t, doubleToFloatThunk); + + case avian::codegen::lir::Float2Int: + if (resultSize == 8) { + return local::getThunk(t, doubleToLongThunk); + } else { + assertT(t, resultSize == 4); + return local::getThunk(t, doubleToIntThunk); + } + + case avian::codegen::lir::Int2Float: + if (resultSize == 8) { + return local::getThunk(t, longToDoubleThunk); + } else { + assertT(t, resultSize == 4); + return local::getThunk(t, longToFloatThunk); + } + + default: + abort(t); + } + } else { + assertT(t, size == 4); + + switch (op) { + case avian::codegen::lir::Absolute: + assertT(t, resultSize == 4); + return local::getThunk(t, absoluteIntThunk); + + case avian::codegen::lir::FloatNegate: + assertT(t, resultSize == 4); + return local::getThunk(t, negateFloatThunk); + + case avian::codegen::lir::FloatAbsolute: + assertT(t, resultSize == 4); + return local::getThunk(t, absoluteFloatThunk); + + case avian::codegen::lir::Float2Float: + assertT(t, resultSize == 8); + return local::getThunk(t, floatToDoubleThunk); + + case avian::codegen::lir::Float2Int: + if (resultSize == 4) { + return local::getThunk(t, floatToIntThunk); + } else { + assertT(t, resultSize == 8); + return local::getThunk(t, floatToLongThunk); + } + + case avian::codegen::lir::Int2Float: + if (resultSize == 4) { + return local::getThunk(t, intToFloatThunk); + } else { + assertT(t, resultSize == 8); + return local::getThunk(t, intToDoubleThunk); + } + + default: + abort(t); + } + } + } + + virtual intptr_t getThunk(avian::codegen::lir::TernaryOperation op, + unsigned size, + unsigned, + bool* threadParameter) + { + *threadParameter = false; + + if (size == 8) { + switch (op) { + case avian::codegen::lir::Divide: + *threadParameter = true; + return local::getThunk(t, divideLongThunk); + + case avian::codegen::lir::Remainder: + *threadParameter = true; + return local::getThunk(t, moduloLongThunk); + + case avian::codegen::lir::FloatAdd: + return local::getThunk(t, addDoubleThunk); + + case avian::codegen::lir::FloatSubtract: + return local::getThunk(t, subtractDoubleThunk); + + case avian::codegen::lir::FloatMultiply: + return local::getThunk(t, multiplyDoubleThunk); + + case avian::codegen::lir::FloatDivide: + return local::getThunk(t, divideDoubleThunk); + + case avian::codegen::lir::FloatRemainder: + return local::getThunk(t, moduloDoubleThunk); + + case avian::codegen::lir::JumpIfFloatEqual: + case avian::codegen::lir::JumpIfFloatNotEqual: + case avian::codegen::lir::JumpIfFloatLess: + case avian::codegen::lir::JumpIfFloatGreater: + case avian::codegen::lir::JumpIfFloatLessOrEqual: + case avian::codegen::lir::JumpIfFloatGreaterOrUnordered: + case avian::codegen::lir::JumpIfFloatGreaterOrEqualOrUnordered: + return local::getThunk(t, compareDoublesGThunk); + + case avian::codegen::lir::JumpIfFloatGreaterOrEqual: + case avian::codegen::lir::JumpIfFloatLessOrUnordered: + case avian::codegen::lir::JumpIfFloatLessOrEqualOrUnordered: + return local::getThunk(t, compareDoublesLThunk); + + default: + abort(t); + } + } else { + assertT(t, size == 4); + switch (op) { + case avian::codegen::lir::Divide: + *threadParameter = true; + return local::getThunk(t, divideIntThunk); + + case avian::codegen::lir::Remainder: + *threadParameter = true; + return local::getThunk(t, moduloIntThunk); + + case avian::codegen::lir::FloatAdd: + return local::getThunk(t, addFloatThunk); + + case avian::codegen::lir::FloatSubtract: + return local::getThunk(t, subtractFloatThunk); + + case avian::codegen::lir::FloatMultiply: + return local::getThunk(t, multiplyFloatThunk); + + case avian::codegen::lir::FloatDivide: + return local::getThunk(t, divideFloatThunk); + + case avian::codegen::lir::FloatRemainder: + return local::getThunk(t, moduloFloatThunk); + + case avian::codegen::lir::JumpIfFloatEqual: + case avian::codegen::lir::JumpIfFloatNotEqual: + case avian::codegen::lir::JumpIfFloatLess: + case avian::codegen::lir::JumpIfFloatGreater: + case avian::codegen::lir::JumpIfFloatLessOrEqual: + case avian::codegen::lir::JumpIfFloatGreaterOrUnordered: + case avian::codegen::lir::JumpIfFloatGreaterOrEqualOrUnordered: + return local::getThunk(t, compareFloatsGThunk); + + case avian::codegen::lir::JumpIfFloatGreaterOrEqual: + case avian::codegen::lir::JumpIfFloatLessOrUnordered: + case avian::codegen::lir::JumpIfFloatLessOrEqualOrUnordered: + return local::getThunk(t, compareFloatsLThunk); + + default: + abort(t); + } + } + } + + MyThread* t; + }; + + Context(MyThread* t, BootContext* bootContext, GcMethod* method) + : thread(t), + zone(t->m->heap, InitialZoneCapacityInBytes), + assembler(t->arch->makeAssembler(t->m->heap, &zone)), + client(t), + compiler(makeCompiler(t->m->system, assembler, &zone, &client)), + method(method), + bootContext(bootContext), + objectPool(0), + subroutineCount(0), + traceLog(0), + visitTable( + Slice::allocAndSet(&zone, method->code()->length(), 0)), + rootTable(Slice::allocAndSet( + &zone, + method->code()->length() * frameMapSizeInWords(t, method), + ~(uintptr_t)0)), + executableAllocator(0), + executableStart(0), + executableSize(0), + objectPoolCount(0), + traceLogCount(0), + dirtyRoots(false), + leaf(true), + eventLog(t->m->system, t->m->heap, 1024), + protector(this), + resource(this), + argumentBuffer( + (ir::Value**)t->m->heap->allocate(256 * sizeof(ir::Value*)), + 256) // below the maximal allowed parameter count for Java + { + } + + Context(MyThread* t) + : thread(t), + zone(t->m->heap, InitialZoneCapacityInBytes), + assembler(t->arch->makeAssembler(t->m->heap, &zone)), + client(t), + compiler(0), + method(0), + bootContext(0), + objectPool(0), + subroutineCount(0), + traceLog(0), + visitTable(0, 0), + rootTable(0, 0), + executableAllocator(0), + executableStart(0), + executableSize(0), + objectPoolCount(0), + traceLogCount(0), + dirtyRoots(false), + leaf(true), + eventLog(t->m->system, t->m->heap, 0), + protector(this), + resource(this), + argumentBuffer(0, 0) + { + } + + ~Context() + { + dispose(); + } + + void dispose() + { + if (compiler) { + compiler->dispose(); + } + + assembler->dispose(); + + if (executableAllocator) { + executableAllocator->free(executableStart, executableSize); + } + + eventLog.dispose(); + + zone.dispose(); + + if (argumentBuffer.begin()) { + thread->m->heap->free(argumentBuffer.begin(), 256 * sizeof(ir::Value*)); + } + } + + void extendLogicalCode(unsigned more) + { + compiler->extendLogicalCode(more); + visitTable = visitTable.cloneAndSet(&zone, visitTable.count + more, 0); + rootTable = rootTable.cloneAndSet( + &zone, + rootTable.count + more * frameMapSizeInWords(thread, method), + ~(uintptr_t)0); + } + + MyThread* thread; + Zone zone; + avian::codegen::Assembler* assembler; + MyClient client; + avian::codegen::Compiler* compiler; + GcMethod* method; + BootContext* bootContext; + PoolElement* objectPool; + unsigned subroutineCount; + TraceElement* traceLog; + Slice visitTable; + Slice rootTable; + Alloc* executableAllocator; + void* executableStart; + unsigned executableSize; + unsigned objectPoolCount; + unsigned traceLogCount; + bool dirtyRoots; + bool leaf; + Vector eventLog; + MyProtector protector; + MyResource resource; + Slice argumentBuffer; +}; + +unsigned& dynamicIndex(MyThread* t); + +void**& dynamicTable(MyThread* t); + +unsigned& dynamicTableSize(MyThread* t); + +void updateDynamicTable(MyThread* t, MyThread* o) +{ + o->dynamicTable = dynamicTable(t); + if (t->peer) + updateDynamicTable(static_cast(t->peer), o); + if (t->child) + updateDynamicTable(static_cast(t->child), o); +} + +uintptr_t defaultDynamicThunk(MyThread* t); + +uintptr_t compileVirtualThunk(MyThread* t, + unsigned index, + unsigned* size, + uintptr_t thunk, + const char* baseName); + +Allocator* allocator(MyThread* t); + +unsigned addDynamic(MyThread* t, GcInvocation* invocation) +{ + ACQUIRE(t, t->m->classLock); + + int index = invocation->index(); + if (index == -1) { + index = dynamicIndex(t)++; + invocation->index() = index; + + unsigned oldCapacity = roots(t)->invocations() + ? roots(t)->invocations()->length() + : 0; + + if (static_cast(index) >= oldCapacity) { + unsigned newCapacity = oldCapacity ? 2 * oldCapacity : 4096; + + void** newTable = static_cast( + allocator(t)->allocate(newCapacity * BytesPerWord)); + + GcArray* newData = makeArray(t, newCapacity); + PROTECT(t, newData); + + GcWordArray* newThunks = makeWordArray(t, newCapacity * 2); + PROTECT(t, newThunks); + + if (dynamicTable(t)) { + memcpy(newTable, dynamicTable(t), oldCapacity * BytesPerWord); + + for(size_t i = 0; i < oldCapacity; i++) { + newData->setBodyElement(t, i, + roots(t)->invocations()->body()[i]); + } + + + mark(t, newData, ArrayBody, oldCapacity); + + memcpy(newThunks->body().begin(), + compileRoots(t)->dynamicThunks()->body().begin(), + compileRoots(t)->dynamicThunks()->length() * BytesPerWord); + } + + ENTER(t, Thread::ExclusiveState); + + if (dynamicTable(t)) { + allocator(t)->free(dynamicTable(t), dynamicTableSize(t)); + } + dynamicTable(t) = newTable; + dynamicTableSize(t) = newCapacity * BytesPerWord; + roots(t)->setInvocations(t, newData); + + updateDynamicTable(static_cast(t->m->rootThread), t); + + compileRoots(t)->setDynamicThunks(t, newThunks); + } + + unsigned size; + uintptr_t thunk = compileVirtualThunk( + t, index, &size, defaultDynamicThunk(t), "dynamicThunk"); + compileRoots(t)->dynamicThunks()->body()[index * 2] = thunk; + compileRoots(t)->dynamicThunks()->body()[(index * 2) + 1] = size; + + t->dynamicTable[index] = reinterpret_cast(thunk); + + roots(t)->invocations()->setBodyElement(t, index, invocation); + } + + return index; +} + +unsigned translateLocalIndex(Context* context, + unsigned footprint, + unsigned index) +{ + unsigned parameterFootprint = context->method->parameterFootprint(); + + if (index < parameterFootprint) { + return parameterFootprint - index - footprint; + } else { + return index; + } +} + +ir::Value* loadLocal(Context* context, + unsigned footprint, + ir::Type type, + unsigned index) +{ + ir::Value* result = context->compiler->loadLocal( + type, translateLocalIndex(context, footprint, index)); + + assertT(context->thread, type == result->type); + return result; +} + +void storeLocal(Context* context, + unsigned footprint, + ir::Type type UNUSED, + ir::Value* value, + unsigned index) +{ + assertT(context->thread, type == value->type); + context->compiler->storeLocal(value, + translateLocalIndex(context, footprint, index)); +} + +avian::util::FixedAllocator* codeAllocator(MyThread* t); + +ir::Type operandTypeForFieldCode(Thread* t, unsigned code) +{ + switch (code) { + case ByteField: + case BooleanField: + case CharField: + case ShortField: + case IntField: + return ir::Type::i4(); + case LongField: + return ir::Type::i8(); + + case ObjectField: + return ir::Type::object(); + + case FloatField: + return ir::Type::f4(); + case DoubleField: + return ir::Type::f8(); + + case VoidField: + return ir::Type::void_(); + + default: + abort(t); + } +} + +unsigned methodReferenceParameterFootprint(Thread* t, + GcReference* reference, + bool isStatic) +{ + return parameterFootprint( + t, + reinterpret_cast(reference->spec()->body().begin()), + isStatic); +} + +int methodReferenceReturnCode(Thread* t, GcReference* reference) +{ + unsigned parameterCount; + unsigned parameterFootprint; + unsigned returnCode; + scanMethodSpec( + t, + reinterpret_cast(reference->spec()->body().begin()), + true, + ¶meterCount, + ¶meterFootprint, + &returnCode); + + return returnCode; +} + +class Frame { + public: + Frame(Context* context, ir::Type* stackMap) + : context(context), + t(context->thread), + c(context->compiler), + subroutine(0), + stackMap(stackMap), + ip(0), + sp(localSize()), + level(0) + { + memset(stackMap, 0, context->method->code()->maxStack() * sizeof(ir::Type)); + } + + Frame(Frame* f, ir::Type* stackMap) + : context(f->context), + t(context->thread), + c(context->compiler), + subroutine(f->subroutine), + stackMap(stackMap), + ip(f->ip), + sp(f->sp), + level(f->level + 1) + { + memcpy(stackMap, + f->stackMap, + context->method->code()->maxStack() * sizeof(ir::Type)); + + if (level > 1) { + context->eventLog.append(PushContextEvent); + } + } + + ~Frame() + { + dispose(); + } + + void dispose() + { + if (level > 1) { + context->eventLog.append(PopContextEvent); + } + } + + ir::Value* append(object o) + { + BootContext* bc = context->bootContext; + if (bc) { + avian::codegen::Promise* p = new (bc->zone) + avian::codegen::ListenPromise(t->m->system, bc->zone); + + PROTECT(t, o); + object pointer = makePointer(t, p); + bc->constants = makeTriple(t, o, pointer, bc->constants); + + return c->binaryOp( + lir::Add, + ir::Type::object(), + c->memory( + c->threadRegister(), ir::Type::object(), TARGET_THREAD_HEAPIMAGE), + c->promiseConstant(p, ir::Type::object())); + } else { + for (PoolElement* e = context->objectPool; e; e = e->next) { + if (o == e->target) { + return c->address(ir::Type::object(), e); + } + } + + context->objectPool = new (&context->zone) + PoolElement(t, o, context->objectPool); + + ++context->objectPoolCount; + + return c->address(ir::Type::object(), context->objectPool); + } + } + + unsigned localSize() + { + return local::localSize(t, context->method); + } + + unsigned stackSize() + { + return context->method->code()->maxStack(); + } + + unsigned frameSize() + { + return localSize() + stackSize(); + } + + void set(unsigned index, ir::Type type) + { + assertT(t, index < frameSize()); + + if (type == ir::Type::object()) { + context->eventLog.append(MarkEvent); + context->eventLog.append2(index); + } else { + context->eventLog.append(ClearEvent); + context->eventLog.append2(index); + } + + int si = index - localSize(); + if (si >= 0) { + stackMap[si] = type; + } + } + + ir::Type get(unsigned index) + { + assertT(t, index < frameSize()); + int si = index - localSize(); + assertT(t, si >= 0); + return stackMap[si]; + } + + void popped(unsigned count) + { + assertT(t, sp >= count); + assertT(t, sp - count >= localSize()); + while (count) { + set(--sp, ir::Type::i4()); + --count; + } + } + + avian::codegen::Promise* addressPromise(avian::codegen::Promise* p) + { + BootContext* bc = context->bootContext; + if (bc) { + bc->addresses = new (bc->zone) avian::codegen::DelayedPromise( + t->m->system, bc->zone, p, bc->addresses); + return bc->addresses; + } else { + return p; + } + } + + ir::Value* addressOperand(avian::codegen::Promise* p) + { + return c->promiseConstant(p, ir::Type::iptr()); + } + + ir::Value* absoluteAddressOperand(avian::codegen::Promise* p) + { + return context->bootContext + ? c->binaryOp( + lir::Add, + ir::Type::iptr(), + c->memory(c->threadRegister(), + ir::Type::iptr(), + TARGET_THREAD_CODEIMAGE), + c->promiseConstant( + new (&context->zone) avian::codegen::OffsetPromise( + p, + -reinterpret_cast( + codeAllocator(t)->memory.begin())), + ir::Type::iptr())) + : addressOperand(p); + } + + ir::Value* machineIpValue(unsigned logicalIp) + { + return c->promiseConstant(machineIp(logicalIp), ir::Type::iptr()); + } + + unsigned duplicatedIp(unsigned bytecodeIp) + { + if (UNLIKELY(subroutine)) { + return bytecodeIp + subroutine->duplicatedBaseIp; + } else { + return bytecodeIp; + } + } + + Promise* machineIp(unsigned bytecodeIp) + { + return c->machineIp(duplicatedIp(bytecodeIp)); + } + + void visitLogicalIp(unsigned bytecodeIp) + { + unsigned dupIp = duplicatedIp(bytecodeIp); + c->visitLogicalIp(dupIp); + + context->eventLog.append(IpEvent); + context->eventLog.append2(bytecodeIp); + } + + void startLogicalIp(unsigned bytecodeIp) + { + unsigned dupIp = duplicatedIp(bytecodeIp); + c->startLogicalIp(dupIp); + + context->eventLog.append(IpEvent); + context->eventLog.append2(bytecodeIp); + + this->ip = bytecodeIp; + } + + void push(ir::Type type, ir::Value* o) + { + assertT(t, type == o->type); + c->push(o->type, o); + assertT(t, sp + 1 <= frameSize()); + set(sp++, type); + } + + void pushObject() + { + c->pushed(ir::Type::object()); + + assertT(t, sp + 1 <= frameSize()); + set(sp++, ir::Type::object()); + } + + void pushLarge(ir::Type type, ir::Value* o) + { + assertT(t, o->type == type); + c->push(type, o); + assertT(t, sp + 2 <= frameSize()); + set(sp++, type); + set(sp++, type); + } + + void popFootprint(unsigned count) + { + popped(count); + c->popped(count); + } + + ir::Value* pop(ir::Type type) + { + assertT(t, sp >= 1); + assertT(t, sp - 1 >= localSize()); + assertT(t, get(sp - 1) == type); + set(--sp, ir::Type::i4()); + return c->pop(type); + } + + ir::Value* popLarge(ir::Type type) + { + assertT(t, sp >= 1); + assertT(t, sp - 2 >= localSize()); + assertT(t, get(sp - 1) == type); + assertT(t, get(sp - 2) == type); + sp -= 2; + return c->pop(type); + } + + void load(ir::Type type, unsigned index) + { + assertT(t, index < localSize()); + push(type, loadLocal(context, 1, type, index)); + } + + void loadLarge(ir::Type type, unsigned index) + { + assertT(t, index < static_cast(localSize() - 1)); + pushLarge(type, loadLocal(context, 2, type, index)); + } + + void store(ir::Type type, unsigned index) + { + assertT(t, + type == ir::Type::i4() || type == ir::Type::f4() + || type == ir::Type::object()); + storeLocal(context, 1, type, pop(type), index); + unsigned ti = translateLocalIndex(context, 1, index); + assertT(t, ti < localSize()); + set(ti, type); + } + + void storeLarge(ir::Type type, unsigned index) + { + assertT(t, type.rawSize() == 8); + storeLocal(context, 2, type, popLarge(type), index); + unsigned ti = translateLocalIndex(context, 2, index); + assertT(t, ti + 1 < localSize()); + set(ti, type); + set(ti + 1, type); + } + + void dup() + { + c->push(ir::Type::i4(), c->peek(1, 0)); + + assertT(t, sp + 1 <= frameSize()); + assertT(t, sp - 1 >= localSize()); + set(sp, get(sp - 1)); + ++sp; + } + + void dupX1() + { + ir::Value* s0 = c->pop(ir::Type::i4()); + ir::Value* s1 = c->pop(ir::Type::i4()); + + c->push(ir::Type::i4(), s0); + c->push(ir::Type::i4(), s1); + c->push(ir::Type::i4(), s0); + + assertT(t, sp + 1 <= frameSize()); + assertT(t, sp - 2 >= localSize()); + + ir::Type b2 = get(sp - 2); + ir::Type b1 = get(sp - 1); + + set(sp - 1, b2); + set(sp - 2, b1); + set(sp, b1); + + ++sp; + } + + void dupX2() + { + ir::Value* s0 = c->pop(ir::Type::i4()); + + if (get(sp - 2).rawSize() == 8) { + ir::Value* s1 = c->pop(ir::Type::i8()); + + c->push(ir::Type::i4(), s0); + c->push(ir::Type::i8(), s1); + c->push(ir::Type::i4(), s0); + } else { + ir::Value* s1 = c->pop(ir::Type::i4()); + ir::Value* s2 = c->pop(ir::Type::i4()); + + c->push(ir::Type::i4(), s0); + c->push(ir::Type::i4(), s2); + c->push(ir::Type::i4(), s1); + c->push(ir::Type::i4(), s0); + } + + assertT(t, sp + 1 <= frameSize()); + assertT(t, sp - 3 >= localSize()); + + ir::Type b3 = get(sp - 3); + ir::Type b2 = get(sp - 2); + ir::Type b1 = get(sp - 1); + + set(sp - 2, b3); + set(sp - 1, b2); + set(sp - 3, b1); + set(sp, b1); + + ++sp; + } + + void dup2() + { + if (get(sp - 1).rawSize() == 8) { + c->push(ir::Type::i8(), c->peek(2, 0)); + } else { + ir::Value* s0 = c->pop(ir::Type::i4()); + ir::Value* s1 = c->pop(ir::Type::i4()); + + c->push(ir::Type::i4(), s1); + c->push(ir::Type::i4(), s0); + c->push(ir::Type::i4(), s1); + c->push(ir::Type::i4(), s0); + } + + assertT(t, sp + 2 <= frameSize()); + assertT(t, sp - 2 >= localSize()); + + ir::Type b2 = get(sp - 2); + ir::Type b1 = get(sp - 1); + + set(sp, b2); + set(sp + 1, b1); + + sp += 2; + } + + void dup2X1() + { + if (get(sp - 1).rawSize() == 8) { + ir::Value* s0 = c->pop(ir::Type::i8()); + ir::Value* s1 = c->pop(ir::Type::i4()); + + c->push(ir::Type::i8(), s0); + c->push(ir::Type::i4(), s1); + c->push(ir::Type::i8(), s0); + } else { + ir::Value* s0 = c->pop(ir::Type::i4()); + ir::Value* s1 = c->pop(ir::Type::i4()); + ir::Value* s2 = c->pop(ir::Type::i4()); + + c->push(ir::Type::i4(), s1); + c->push(ir::Type::i4(), s0); + c->push(ir::Type::i4(), s2); + c->push(ir::Type::i4(), s1); + c->push(ir::Type::i4(), s0); + } + + assertT(t, sp + 2 <= frameSize()); + assertT(t, sp - 3 >= localSize()); + + ir::Type b3 = get(sp - 3); + ir::Type b2 = get(sp - 2); + ir::Type b1 = get(sp - 1); + + set(sp - 1, b3); + set(sp - 3, b2); + set(sp, b2); + set(sp - 2, b1); + set(sp + 1, b1); + + sp += 2; + } + + void dup2X2() + { + if (get(sp - 1).rawSize() == 8) { + ir::Value* s0 = c->pop(ir::Type::i8()); + + if (get(sp - 3).rawSize() == 8) { + ir::Value* s1 = c->pop(ir::Type::i8()); + + c->push(ir::Type::i8(), s0); + c->push(ir::Type::i8(), s1); + c->push(ir::Type::i8(), s0); + } else { + ir::Value* s1 = c->pop(ir::Type::i4()); + ir::Value* s2 = c->pop(ir::Type::i4()); + + c->push(ir::Type::i8(), s0); + c->push(ir::Type::i4(), s2); + c->push(ir::Type::i4(), s1); + c->push(ir::Type::i8(), s0); + } + } else { + ir::Value* s0 = c->pop(ir::Type::i4()); + ir::Value* s1 = c->pop(ir::Type::i4()); + ir::Value* s2 = c->pop(ir::Type::i4()); + ir::Value* s3 = c->pop(ir::Type::i4()); + + c->push(ir::Type::i4(), s1); + c->push(ir::Type::i4(), s0); + c->push(ir::Type::i4(), s3); + c->push(ir::Type::i4(), s2); + c->push(ir::Type::i4(), s1); + c->push(ir::Type::i4(), s0); + } + + assertT(t, sp + 2 <= frameSize()); + assertT(t, sp - 4 >= localSize()); + + ir::Type b4 = get(sp - 4); + ir::Type b3 = get(sp - 3); + ir::Type b2 = get(sp - 2); + ir::Type b1 = get(sp - 1); + + set(sp - 2, b4); + set(sp - 1, b3); + set(sp - 4, b2); + set(sp, b2); + set(sp - 3, b1); + set(sp + 1, b1); + + sp += 2; + } + + void swap() + { + ir::Value* s0 = c->pop(ir::Type::i4()); + ir::Value* s1 = c->pop(ir::Type::i4()); + + c->push(ir::Type::i4(), s0); + c->push(ir::Type::i4(), s1); + + assertT(t, sp - 2 >= localSize()); + + ir::Type saved = get(sp - 1); + + set(sp - 1, get(sp - 2)); + set(sp - 2, saved); + } + + TraceElement* trace(GcMethod* target, unsigned flags) + { + unsigned mapSize = frameMapSizeInWords(t, context->method); + + TraceElement* e = context->traceLog = new ( + context->zone.allocate(sizeof(TraceElement) + (mapSize * BytesPerWord))) + TraceElement(context, + duplicatedIp(ip), + target, + flags, + context->traceLog, + mapSize); + + ++context->traceLogCount; + + context->eventLog.append(TraceEvent); + context->eventLog.appendAddress(e); + + return e; + } + + void pushReturnValue(unsigned code, ir::Value* result) + { + switch (code) { + case ByteField: + case BooleanField: + case CharField: + case ShortField: + case IntField: + return push(ir::Type::i4(), result); + case FloatField: + return push(ir::Type::f4(), result); + + case ObjectField: + return push(ir::Type::object(), result); + + case LongField: + return pushLarge(ir::Type::i8(), result); + case DoubleField: + return pushLarge(ir::Type::f8(), result); + + default: + abort(t); + } + } + + Slice peekMethodArguments(unsigned footprint) + { + ir::Value** ptr = context->argumentBuffer.items; + + for (unsigned i = 0; i < footprint; i++) { + *(ptr++) = c->peek(1, footprint - i - 1); + } + + return Slice(context->argumentBuffer.items, footprint); + } + + void stackCall(ir::Value* methodValue, + GcMethod* methodObject, + unsigned flags, + TraceElement* trace) + { + unsigned footprint = methodObject->parameterFootprint(); + unsigned returnCode = methodObject->returnCode(); + ir::Value* result = c->stackCall(methodValue, + flags, + trace, + operandTypeForFieldCode(t, returnCode), + peekMethodArguments(footprint)); + + popFootprint(footprint); + + if (returnCode != VoidField) { + pushReturnValue(returnCode, result); + } + } + + void referenceStackCall(bool isStatic, + ir::Value* methodValue, + GcReference* methodReference, + unsigned flags, + TraceElement* trace) + { + unsigned footprint + = methodReferenceParameterFootprint(t, methodReference, isStatic); + unsigned returnCode = methodReferenceReturnCode(t, methodReference); + ir::Value* result = c->stackCall(methodValue, + flags, + trace, + operandTypeForFieldCode(t, returnCode), + peekMethodArguments(footprint)); + + popFootprint(footprint); + + if (returnCode != VoidField) { + pushReturnValue(returnCode, result); + } + } + + void startSubroutine(unsigned ip, unsigned returnAddress) + { + // Push a dummy value to the stack, representing the return address (which + // we don't need, since we're expanding everything statically). + // TODO: in the future, push a value that we can track through type checking + push(ir::Type::object(), c->constant(0, ir::Type::object())); + + if (DebugInstructions) { + fprintf(stderr, "startSubroutine %u %u\n", ip, returnAddress); + } + + Subroutine* subroutine = new (&context->zone) + Subroutine(context->subroutineCount++, + returnAddress, + context->method->code()->length(), + this->subroutine); + + context->extendLogicalCode(context->method->code()->length()); + + this->subroutine = subroutine; + } + + unsigned endSubroutine(unsigned returnAddressLocal UNUSED) + { + // TODO: use returnAddressLocal to decide which subroutine we're returning + // from (in case it's ever not the most recent one entered). I'm unsure of + // whether such a subroutine pattern would pass bytecode verification. + + unsigned returnAddress = subroutine->returnAddress; + + if (DebugInstructions) { + fprintf(stderr, "endSubroutine %u %u\n", ip, returnAddress); + } + + subroutine = subroutine->outer; + + return returnAddress; + } + + Context* context; + MyThread* t; + avian::codegen::Compiler* c; + + // Innermost subroutine we're compiling code for + Subroutine* subroutine; + + ir::Type* stackMap; + unsigned ip; + unsigned sp; + unsigned level; +}; + +unsigned savedTargetIndex(MyThread* t UNUSED, GcMethod* method) +{ + return method->code()->maxLocals(); +} + +GcCallNode* findCallNode(MyThread* t, void* address); + +void* findExceptionHandler(Thread* t, GcMethod* method, void* ip) +{ + if (t->exception) { + GcArray* table = cast(t, method->code()->exceptionHandlerTable()); + if (table) { + GcIntArray* index = cast(t, table->body()[0]); + + uint8_t* compiled = reinterpret_cast(methodCompiled(t, method)); + + for (unsigned i = 0; i < table->length() - 1; ++i) { + unsigned start = index->body()[i * 3]; + unsigned end = index->body()[(i * 3) + 1]; + unsigned key = difference(ip, compiled) - 1; + + if (key >= start and key < end) { + GcClass* catchType = cast(t, table->body()[i + 1]); + + if (exceptionMatch(t, catchType, t->exception)) { + return compiled + index->body()[(i * 3) + 2]; + } + } + } + } + } + + return 0; +} + +void releaseLock(MyThread* t, GcMethod* method, void* stack) +{ + if (method->flags() & ACC_SYNCHRONIZED) { + if (t->methodLockIsClean) { + object lock; + if (method->flags() & ACC_STATIC) { + lock = getJClass(t, method->class_()); + } else { + lock = *localObject(t, + stackForFrame(t, stack, method), + method, + savedTargetIndex(t, method)); + } + + release(t, lock); + } else { + // got an exception while trying to acquire the lock for a + // synchronized method -- don't try to release it, since we + // never succeeded in acquiring it. + t->methodLockIsClean = true; + } + } +} + +void findUnwindTarget(MyThread* t, + void** targetIp, + void** targetFrame, + void** targetStack, + GcContinuation** targetContinuation) +{ + void* ip; + void* stack; + GcContinuation* continuation; + + if (t->traceContext) { + ip = t->traceContext->ip; + stack = t->traceContext->stack; + continuation = t->traceContext->continuation; + } else { + ip = getIp(t); + stack = t->stack; + continuation = t->continuation; + } + + GcMethod* target = t->trace->targetMethod; + bool mostRecent = true; + + *targetIp = 0; + while (*targetIp == 0) { + GcMethod* method = methodForIp(t, ip); + if (method) { + void* handler = findExceptionHandler(t, method, ip); + + if (handler) { + *targetIp = handler; + + nextFrame(t, &ip, &stack, method, target, mostRecent); + + void** sp = static_cast(stackForFrame(t, stack, method)) + + t->arch->frameReturnAddressSize(); + + *targetFrame = static_cast(stack) + + t->arch->framePointerOffset(); + *targetStack = sp; + *targetContinuation = continuation; + + sp[localOffset(t, localSize(t, method), method)] = t->exception; + + t->exception = 0; + } else { + nextFrame(t, &ip, &stack, method, target, mostRecent); + + if (t->exception) { + releaseLock(t, method, stack); + } + + target = method; + } + } else { + expect(t, ip); + *targetIp = ip; + *targetFrame = 0; + *targetStack = static_cast(stack) + + t->arch->frameReturnAddressSize(); + *targetContinuation = continuation; + + while (Continuations and *targetContinuation) { + GcContinuation* c = *targetContinuation; + + GcMethod* method = c->method(); + + void* handler = findExceptionHandler(t, method, c->address()); + + if (handler) { + t->exceptionHandler = handler; + + t->exceptionStackAdjustment + = (stackOffsetFromFrame(t, method) + - ((c->framePointerOffset() / BytesPerWord) + - t->arch->framePointerOffset() + + t->arch->frameReturnAddressSize())) * BytesPerWord; + + t->exceptionOffset = localOffset(t, localSize(t, method), method) + * BytesPerWord; + + break; + } else if (t->exception) { + releaseLock(t, + method, + reinterpret_cast(c) + ContinuationBody + + c->returnAddressOffset() + - t->arch->returnAddressOffset()); + } + + *targetContinuation = c->next(); + } + } + + mostRecent = false; + } +} + +GcContinuation* makeCurrentContinuation(MyThread* t, + void** targetIp, + void** targetStack) +{ + void* ip = getIp(t); + void* stack = t->stack; + + GcContinuationContext* context + = t->continuation + ? t->continuation->context() + : makeContinuationContext(t, 0, 0, 0, 0, t->trace->originalMethod); + PROTECT(t, context); + + GcMethod* target = t->trace->targetMethod; + PROTECT(t, target); + + GcContinuation* first = 0; + PROTECT(t, first); + + GcContinuation* last = 0; + PROTECT(t, last); + + bool mostRecent = true; + + *targetIp = 0; + while (*targetIp == 0) { + assertT(t, ip); + + GcMethod* method = methodForIp(t, ip); + if (method) { + PROTECT(t, method); + + void** top = static_cast(stack) + + t->arch->frameReturnAddressSize() + + t->arch->frameFooterSize(); + unsigned argumentFootprint + = t->arch->argumentFootprint(target->parameterFootprint()); + unsigned alignment = t->arch->stackAlignmentInWords(); + if (avian::codegen::TailCalls and argumentFootprint > alignment) { + top += argumentFootprint - alignment; + } + + void* nextIp = ip; + nextFrame(t, &nextIp, &stack, method, target, mostRecent); + + void** bottom = static_cast(stack) + + t->arch->frameReturnAddressSize(); + unsigned frameSize = bottom - top; + unsigned totalSize + = frameSize + t->arch->frameFooterSize() + + t->arch->argumentFootprint(method->parameterFootprint()); + + GcContinuation* c = makeContinuation( + t, + 0, + context, + method, + ip, + (frameSize + t->arch->frameFooterSize() + + t->arch->returnAddressOffset() - t->arch->frameReturnAddressSize()) + * BytesPerWord, + (frameSize + t->arch->frameFooterSize() + + t->arch->framePointerOffset() - t->arch->frameReturnAddressSize()) + * BytesPerWord, + totalSize); + + memcpy(c->body().begin(), top, totalSize * BytesPerWord); + + if (last) { + last->setNext(t, c); + } else { + first = c; + } + last = c; + + ip = nextIp; + + target = method; + } else { + *targetIp = ip; + *targetStack = static_cast(stack) + + t->arch->frameReturnAddressSize(); + } + + mostRecent = false; + } + + expect(t, last); + last->setNext(t, t->continuation); + + return first; +} + +void NO_RETURN unwind(MyThread* t) +{ + void* ip; + void* frame; + void* stack; + GcContinuation* continuation; + findUnwindTarget(t, &ip, &frame, &stack, &continuation); + + t->trace->targetMethod = 0; + t->trace->nativeMethod = 0; + + transition(t, ip, stack, continuation, t->trace); + + vmJump(ip, frame, stack, t, 0, 0); +} + +class MyCheckpoint : public Thread::Checkpoint { + public: + MyCheckpoint(MyThread* t) : Checkpoint(t) + { + } + + virtual void unwind() + { + local::unwind(static_cast(t)); + } +}; + +uintptr_t defaultThunk(MyThread* t); + +uintptr_t nativeThunk(MyThread* t); + +uintptr_t bootNativeThunk(MyThread* t); + +uintptr_t virtualThunk(MyThread* t, unsigned index); + +bool unresolved(MyThread* t, uintptr_t methodAddress); + +uintptr_t methodAddress(Thread* t, GcMethod* method) +{ + if (method->flags() & ACC_NATIVE) { + return bootNativeThunk(static_cast(t)); + } else { + return methodCompiled(t, method); + } +} + +void tryInitClass(MyThread* t, GcClass* class_) +{ + initClass(t, class_); +} + +void compile(MyThread* t, + FixedAllocator* allocator, + BootContext* bootContext, + GcMethod* method); + +GcMethod* resolveMethod(Thread* t, GcPair* pair) +{ + GcReference* reference = cast(t, pair->second()); + PROTECT(t, reference); + + GcClass* class_ = resolveClassInObject( + t, + cast(t, pair->first())->class_()->loader(), + reference, + ReferenceClass); + + return cast(t, + findInHierarchy(t, + class_, + reference->name(), + reference->spec(), + findMethodInClass, + GcNoSuchMethodError::Type)); +} + +bool methodAbstract(Thread* t UNUSED, GcMethod* method) +{ + return method->code() == 0 and (method->flags() & ACC_NATIVE) == 0; +} + +int64_t prepareMethodForCall(MyThread* t, GcMethod* target) +{ + if (methodAbstract(t, target)) { + throwNew(t, + GcAbstractMethodError::Type, + "%s.%s%s", + target->class_()->name()->body().begin(), + target->name()->body().begin(), + target->spec()->body().begin()); + } else { + if (unresolved(t, methodAddress(t, target))) { + PROTECT(t, target); + + compile(t, codeAllocator(t), 0, target); + } + + if (target->flags() & ACC_NATIVE) { + t->trace->nativeMethod = target; + } + + return methodAddress(t, target); + } +} + +int64_t findInterfaceMethodFromInstance(MyThread* t, + GcMethod* method, + object instance) +{ + if (instance) { + return prepareMethodForCall( + t, findInterfaceMethod(t, method, objectClass(t, instance))); + } else { + throwNew(t, GcNullPointerException::Type); + } +} + +int64_t findInterfaceMethodFromInstanceAndReference(MyThread* t, + GcPair* pair, + object instance) +{ + PROTECT(t, instance); + + GcMethod* method = resolveMethod(t, pair); + + return findInterfaceMethodFromInstance(t, method, instance); +} + +void checkMethod(Thread* t, GcMethod* method, bool shouldBeStatic) +{ + if (((method->flags() & ACC_STATIC) == 0) == shouldBeStatic) { + throwNew(t, + GcIncompatibleClassChangeError::Type, + "expected %s.%s%s to be %s", + method->class_()->name()->body().begin(), + method->name()->body().begin(), + method->spec()->body().begin(), + shouldBeStatic ? "static" : "non-static"); + } +} + +int64_t findSpecialMethodFromReference(MyThread* t, GcPair* pair) +{ + PROTECT(t, pair); + + GcMethod* target = resolveMethod(t, pair); + + GcClass* class_ = cast(t, pair->first())->class_(); + if (isSpecialMethod(t, target, class_)) { + target = findVirtualMethod(t, target, class_->super()); + } + + checkMethod(t, target, false); + + return prepareMethodForCall(t, target); +} + +int64_t findStaticMethodFromReference(MyThread* t, GcPair* pair) +{ + GcMethod* target = resolveMethod(t, pair); + + checkMethod(t, target, true); + + return prepareMethodForCall(t, target); +} + +int64_t findVirtualMethodFromReference(MyThread* t, + GcPair* pair, + object instance) +{ + PROTECT(t, instance); + + GcMethod* target = resolveMethod(t, pair); + + target = findVirtualMethod(t, target, objectClass(t, instance)); + + checkMethod(t, target, false); + + return prepareMethodForCall(t, target); +} + +int64_t getMethodAddress(MyThread* t, GcMethod* target) +{ + return prepareMethodForCall(t, target); +} + +int64_t getJClassFromReference(MyThread* t, GcPair* pair) +{ + return reinterpret_cast(getJClass( + t, + resolveClass(t, + cast(t, pair->first())->class_()->loader(), + cast(t, pair->second())->name()))); +} + +unsigned traceSize(Thread* t) +{ + class Counter : public Processor::StackVisitor { + public: + Counter() : count(0) + { + } + + virtual bool visit(Processor::StackWalker*) + { + ++count; + return true; + } + + unsigned count; + } counter; + + t->m->processor->walkStack(t, &counter); + + return pad(GcArray::FixedSize) + + (counter.count * pad(ArrayElementSizeOfArray)) + + (counter.count * pad(GcTraceElement::FixedSize)); +} + +void NO_RETURN throwArithmetic(MyThread* t) +{ + if (ensure(t, GcArithmeticException::FixedSize + traceSize(t))) { + t->setFlag(Thread::TracingFlag); + THREAD_RESOURCE0(t, t->clearFlag(Thread::TracingFlag)); + + throwNew(t, GcArithmeticException::Type); + } else { + // not enough memory available for a new exception and stack trace + // -- use a preallocated instance instead + throw_(t, roots(t)->arithmeticException()); + } +} + +int64_t divideLong(MyThread* t, int64_t b, int64_t a) +{ + if (LIKELY(b)) { + return a / b; + } else { + throwArithmetic(t); + } +} + +int64_t divideInt(MyThread* t, int32_t b, int32_t a) +{ + if (LIKELY(b)) { + return a / b; + } else { + throwArithmetic(t); + } +} + +int64_t moduloLong(MyThread* t, int64_t b, int64_t a) +{ + if (LIKELY(b)) { + return a % b; + } else { + throwArithmetic(t); + } +} + +int64_t moduloInt(MyThread* t, int32_t b, int32_t a) +{ + if (LIKELY(b)) { + return a % b; + } else { + throwArithmetic(t); + } +} + +uint64_t makeBlankObjectArray(MyThread* t, GcClass* class_, int32_t length) +{ + if (length >= 0) { + return reinterpret_cast(makeObjectArray(t, class_, length)); + } else { + throwNew(t, GcNegativeArraySizeException::Type, "%d", length); + } +} + +uint64_t makeBlankObjectArrayFromReference(MyThread* t, + GcPair* pair, + int32_t length) +{ + return makeBlankObjectArray( + t, + resolveClass(t, + cast(t, pair->first())->class_()->loader(), + cast(t, pair->second())->name()), + length); +} + +uint64_t makeBlankArray(MyThread* t, unsigned type, int32_t length) +{ + if (length >= 0) { + switch (type) { + case T_BOOLEAN: + return reinterpret_cast(makeBooleanArray(t, length)); + case T_CHAR: + return reinterpret_cast(makeCharArray(t, length)); + case T_FLOAT: + return reinterpret_cast(makeFloatArray(t, length)); + case T_DOUBLE: + return reinterpret_cast(makeDoubleArray(t, length)); + case T_BYTE: + return reinterpret_cast(makeByteArray(t, length)); + case T_SHORT: + return reinterpret_cast(makeShortArray(t, length)); + case T_INT: + return reinterpret_cast(makeIntArray(t, length)); + case T_LONG: + return reinterpret_cast(makeLongArray(t, length)); + default: + abort(t); + } + } else { + throwNew(t, GcNegativeArraySizeException::Type, "%d", length); + } +} + +uint64_t lookUpAddress(int32_t key, + uintptr_t* start, + int32_t count, + uintptr_t default_) +{ + int32_t bottom = 0; + int32_t top = count; + for (int32_t span = top - bottom; span; span = top - bottom) { + int32_t middle = bottom + (span / 2); + uintptr_t* p = start + (middle * 2); + int32_t k = *p; + + if (key < k) { + top = middle; + } else if (key > k) { + bottom = middle + 1; + } else { + return p[1]; + } + } + + return default_; +} + +void setMaybeNull(MyThread* t, object o, unsigned offset, object value) +{ + if (LIKELY(o)) { + setField(t, o, offset, value); + } else { + throwNew(t, GcNullPointerException::Type); + } +} + +void acquireMonitorForObject(MyThread* t, object o) +{ + if (LIKELY(o)) { + acquire(t, o); + } else { + throwNew(t, GcNullPointerException::Type); + } +} + +void acquireMonitorForObjectOnEntrance(MyThread* t, object o) +{ + if (LIKELY(o)) { + t->methodLockIsClean = false; + acquire(t, o); + t->methodLockIsClean = true; + } else { + throwNew(t, GcNullPointerException::Type); + } +} + +void releaseMonitorForObject(MyThread* t, object o) +{ + if (LIKELY(o)) { + release(t, o); + } else { + throwNew(t, GcNullPointerException::Type); + } +} + +void acquireMonitorForClassOnEntrance(MyThread* t, GcClass* o) +{ + if (LIKELY(o)) { + t->methodLockIsClean = false; + acquire(t, getJClass(t, o)); + t->methodLockIsClean = true; + } else { + throwNew(t, GcNullPointerException::Type); + } +} + +void releaseMonitorForClass(MyThread* t, GcClass* o) +{ + if (LIKELY(o)) { + release(t, getJClass(t, o)); + } else { + throwNew(t, GcNullPointerException::Type); + } +} + +object makeMultidimensionalArray2(MyThread* t, + GcClass* class_, + uintptr_t* countStack, + int32_t dimensions) +{ + PROTECT(t, class_); + + THREAD_RUNTIME_ARRAY(t, int32_t, counts, dimensions); + for (int i = dimensions - 1; i >= 0; --i) { + RUNTIME_ARRAY_BODY(counts)[i] = countStack[dimensions - i - 1]; + if (UNLIKELY(RUNTIME_ARRAY_BODY(counts)[i] < 0)) { + throwNew(t, + GcNegativeArraySizeException::Type, + "%d", + RUNTIME_ARRAY_BODY(counts)[i]); + return 0; + } + } + + object array = makeArray(t, RUNTIME_ARRAY_BODY(counts)[0]); + setObjectClass(t, array, class_); + PROTECT(t, array); + + populateMultiArray(t, array, RUNTIME_ARRAY_BODY(counts), 0, dimensions); + + return array; +} + +uint64_t makeMultidimensionalArray(MyThread* t, + GcClass* class_, + int32_t dimensions, + int32_t offset) +{ + return reinterpret_cast(makeMultidimensionalArray2( + t, class_, static_cast(t->stack) + offset, dimensions)); +} + +uint64_t makeMultidimensionalArrayFromReference(MyThread* t, + GcPair* pair, + int32_t dimensions, + int32_t offset) +{ + return makeMultidimensionalArray( + t, + resolveClass(t, + cast(t, pair->first())->class_()->loader(), + cast(t, pair->second())->name()), + dimensions, + offset); +} + +void NO_RETURN throwArrayIndexOutOfBounds(MyThread* t) +{ + if (ensure(t, GcArrayIndexOutOfBoundsException::FixedSize + traceSize(t))) { + t->setFlag(Thread::TracingFlag); + THREAD_RESOURCE0(t, t->clearFlag(Thread::TracingFlag)); + + throwNew(t, GcArrayIndexOutOfBoundsException::Type); + } else { + // not enough memory available for a new exception and stack trace + // -- use a preallocated instance instead + throw_(t, roots(t)->arrayIndexOutOfBoundsException()); + } +} + +void NO_RETURN throwStackOverflow(MyThread* t) +{ + throwNew(t, GcStackOverflowError::Type); +} + +void NO_RETURN throw_(MyThread* t, GcThrowable* o) +{ + if (LIKELY(o)) { + vm::throw_(t, o); + } else { + throwNew(t, GcNullPointerException::Type); + } +} + +void checkCast(MyThread* t, GcClass* class_, object o) +{ + if (UNLIKELY(o and not isAssignableFrom(t, class_, objectClass(t, o)))) { + GcByteArray* classNameFrom = objectClass(t, o)->name(); + GcByteArray* classNameTo = class_->name(); + THREAD_RUNTIME_ARRAY(t, char, classFrom, classNameFrom->length()); + THREAD_RUNTIME_ARRAY(t, char, classTo, classNameTo->length()); + replace('/', + '.', + RUNTIME_ARRAY_BODY(classFrom), + reinterpret_cast(classNameFrom->body().begin())); + replace('/', + '.', + RUNTIME_ARRAY_BODY(classTo), + reinterpret_cast(classNameTo->body().begin())); + throwNew(t, + GcClassCastException::Type, + "%s cannot be cast to %s", + RUNTIME_ARRAY_BODY(classFrom), + RUNTIME_ARRAY_BODY(classTo)); + } +} + +void checkCastFromReference(MyThread* t, GcPair* pair, object o) +{ + PROTECT(t, o); + + GcClass* c + = resolveClass(t, + cast(t, pair->first())->class_()->loader(), + cast(t, pair->second())->name()); + + checkCast(t, c, o); +} + +GcField* resolveField(Thread* t, GcPair* pair) +{ + GcReference* reference = cast(t, pair->second()); + PROTECT(t, reference); + + GcClass* class_ = resolveClassInObject( + t, + cast(t, pair->first())->class_()->loader(), + reference, + ReferenceClass); + + return cast(t, + findInHierarchy(t, + class_, + reference->name(), + reference->spec(), + findFieldInClass, + GcNoSuchFieldError::Type)); +} + +uint64_t getFieldValue(Thread* t, object target, GcField* field) +{ + switch (field->code()) { + case ByteField: + case BooleanField: + return fieldAtOffset(target, field->offset()); + + case CharField: + case ShortField: + return fieldAtOffset(target, field->offset()); + + case FloatField: + case IntField: + return fieldAtOffset(target, field->offset()); + + case DoubleField: + case LongField: + return fieldAtOffset(target, field->offset()); + + case ObjectField: + return fieldAtOffset(target, field->offset()); + + default: + abort(t); + } +} + +uint64_t getStaticFieldValueFromReference(MyThread* t, GcPair* pair) +{ + GcField* field = resolveField(t, pair); + PROTECT(t, field); + + initClass(t, field->class_()); + + ACQUIRE_FIELD_FOR_READ(t, field); + + return getFieldValue(t, field->class_()->staticTable(), field); +} + +uint64_t getFieldValueFromReference(MyThread* t, GcPair* pair, object instance) +{ + PROTECT(t, instance); + + GcField* field = resolveField(t, pair); + PROTECT(t, field); + + ACQUIRE_FIELD_FOR_READ(t, field); + + return getFieldValue(t, instance, field); +} + +void setStaticLongFieldValueFromReference(MyThread* t, + GcPair* pair, + uint64_t value) +{ + GcField* field = resolveField(t, pair); + PROTECT(t, field); + + initClass(t, field->class_()); + + ACQUIRE_FIELD_FOR_WRITE(t, field); + + fieldAtOffset(field->class_()->staticTable(), field->offset()) + = value; +} + +void setLongFieldValueFromReference(MyThread* t, + GcPair* pair, + object instance, + uint64_t value) +{ + PROTECT(t, instance); + + GcField* field = resolveField(t, pair); + PROTECT(t, field); + + ACQUIRE_FIELD_FOR_WRITE(t, field); + + fieldAtOffset(instance, field->offset()) = value; +} + +void setStaticObjectFieldValueFromReference(MyThread* t, + GcPair* pair, + object value) +{ + PROTECT(t, value); + + GcField* field = resolveField(t, pair); + PROTECT(t, field); + + initClass(t, field->class_()); + + ACQUIRE_FIELD_FOR_WRITE(t, field); + + setField(t, field->class_()->staticTable(), field->offset(), value); +} + +void setObjectFieldValueFromReference(MyThread* t, + GcPair* pair, + object instance, + object value) +{ + PROTECT(t, instance); + PROTECT(t, value); + + GcField* field = resolveField(t, pair); + PROTECT(t, field); + + ACQUIRE_FIELD_FOR_WRITE(t, field); + + setField(t, instance, field->offset(), value); +} + +void setFieldValue(MyThread* t, object target, GcField* field, uint32_t value) +{ + switch (field->code()) { + case ByteField: + case BooleanField: + fieldAtOffset(target, field->offset()) = value; + break; + + case CharField: + case ShortField: + fieldAtOffset(target, field->offset()) = value; + break; + + case FloatField: + case IntField: + fieldAtOffset(target, field->offset()) = value; + break; + + default: + abort(t); + } +} + +void setStaticFieldValueFromReference(MyThread* t, GcPair* pair, uint32_t value) +{ + GcField* field = resolveField(t, pair); + PROTECT(t, field); + + initClass(t, field->class_()); + + ACQUIRE_FIELD_FOR_WRITE(t, field); + + setFieldValue(t, field->class_()->staticTable(), field, value); +} + +void setFieldValueFromReference(MyThread* t, + GcPair* pair, + object instance, + uint32_t value) +{ + PROTECT(t, instance); + GcField* field = resolveField(t, pair); + PROTECT(t, field); + + ACQUIRE_FIELD_FOR_WRITE(t, field); + + setFieldValue(t, instance, field, value); +} + +uint64_t instanceOf64(Thread* t, GcClass* class_, object o) +{ + return instanceOf(t, class_, o); +} + +uint64_t instanceOfFromReference(Thread* t, GcPair* pair, object o) +{ + PROTECT(t, o); + + GcClass* c + = resolveClass(t, + cast(t, pair->first())->class_()->loader(), + cast(t, pair->second())->name()); + + return instanceOf64(t, c, o); +} + +uint64_t makeNewGeneral64(Thread* t, GcClass* class_) +{ + PROTECT(t, class_); + + initClass(t, class_); + + return reinterpret_cast(makeNewGeneral(t, class_)); +} + +uint64_t makeNew64(Thread* t, GcClass* class_) +{ + PROTECT(t, class_); + + initClass(t, class_); + + return reinterpret_cast(makeNew(t, class_)); +} + +uint64_t makeNewFromReference(Thread* t, GcPair* pair) +{ + GcClass* class_ + = resolveClass(t, + cast(t, pair->first())->class_()->loader(), + cast(t, pair->second())->name()); + + PROTECT(t, class_); + + initClass(t, class_); + + return makeNewGeneral64(t, class_); +} + +uint64_t getJClass64(Thread* t, GcClass* class_) +{ + return reinterpret_cast(getJClass(t, class_)); +} + +void gcIfNecessary(MyThread* t) +{ + stress(t); + + if (UNLIKELY(t->getFlags() & Thread::UseBackupHeapFlag)) { + collect(t, Heap::MinorCollection); + } +} + +void idleIfNecessary(MyThread* t) +{ + if (UNLIKELY(t->m->exclusive)) { + ENTER(t, Thread::IdleState); + } +} + +bool useLongJump(MyThread* t, uintptr_t target) +{ + uintptr_t reach = t->arch->maximumImmediateJump(); + FixedAllocator* a = codeAllocator(t); + uintptr_t start = reinterpret_cast(a->memory.begin()); + uintptr_t end = reinterpret_cast(a->memory.begin()) + + a->memory.count; + assertT(t, end - start < reach); + + return (target > end && (target - start) > reach) + or (target < start && (end - target) > reach); +} + +FILE* compileLog = 0; + +void logCompile(MyThread* t, + const void* code, + unsigned size, + const char* class_, + const char* name, + const char* spec); + +unsigned simpleFrameMapTableSize(MyThread* t, GcMethod* method, GcIntArray* map) +{ + int size = frameMapSizeInBits(t, method); + return ceilingDivide(map->length() * size, 32 + size); +} + +#ifndef AVIAN_AOT_ONLY +unsigned resultSize(MyThread* t, unsigned code) +{ + switch (code) { + case ByteField: + case BooleanField: + case CharField: + case ShortField: + case FloatField: + case IntField: + return 4; + + case ObjectField: + return TargetBytesPerWord; + + case LongField: + case DoubleField: + return 8; + + case VoidField: + return 0; + + default: + abort(t); + } +} + +ir::Value* popField(MyThread* t, Frame* frame, int code) +{ + switch (code) { + case ByteField: + case BooleanField: + case CharField: + case ShortField: + case IntField: + return frame->pop(ir::Type::i4()); + case FloatField: + return frame->pop(ir::Type::f4()); + + case LongField: + return frame->popLarge(ir::Type::i8()); + case DoubleField: + return frame->popLarge(ir::Type::f8()); + + case ObjectField: + return frame->pop(ir::Type::object()); + + default: + abort(t); + } +} + +void compileSafePoint(MyThread* t, Compiler* c, Frame* frame) +{ + c->nativeCall( + c->constant(getThunk(t, idleIfNecessaryThunk), ir::Type::iptr()), + 0, + frame->trace(0, 0), + ir::Type::void_(), + args(c->threadRegister())); +} + +void compileDirectInvoke(MyThread* t, + Frame* frame, + GcMethod* target, + bool tailCall, + bool useThunk, + avian::codegen::Promise* addressPromise) +{ + avian::codegen::Compiler* c = frame->c; + + unsigned flags + = (avian::codegen::TailCalls and tailCall ? Compiler::TailJump : 0); + unsigned traceFlags; + + if (addressPromise == 0 and useLongJump(t, methodAddress(t, target))) { + flags |= Compiler::LongJumpOrCall; + traceFlags = TraceElement::LongCall; + } else { + traceFlags = 0; + } + + if (useThunk or (avian::codegen::TailCalls and tailCall + and (target->flags() & ACC_NATIVE))) { + if (frame->context->bootContext == 0) { + flags |= Compiler::Aligned; + } + + if (avian::codegen::TailCalls and tailCall) { + traceFlags |= TraceElement::TailCall; + + TraceElement* trace = frame->trace(target, traceFlags); + + avian::codegen::Promise* returnAddressPromise + = new (frame->context->zone.allocate(sizeof(TraceElementPromise))) + TraceElementPromise(t->m->system, trace); + + frame->stackCall( + c->promiseConstant(returnAddressPromise, ir::Type::iptr()), + target, + flags, + trace); + + c->store(frame->absoluteAddressOperand(returnAddressPromise), + c->memory(c->threadRegister(), + ir::Type::iptr(), + TARGET_THREAD_TAILADDRESS)); + + c->exit(c->constant( + (target->flags() & ACC_NATIVE) ? nativeThunk(t) : defaultThunk(t), + ir::Type::iptr())); + } else { + return frame->stackCall(c->constant(defaultThunk(t), ir::Type::iptr()), + target, + flags, + frame->trace(target, traceFlags)); + } + } else { + ir::Value* address + = (addressPromise + ? c->promiseConstant(addressPromise, ir::Type::iptr()) + : c->constant(methodAddress(t, target), ir::Type::iptr())); + + frame->stackCall( + address, + target, + flags, + tailCall ? 0 : frame->trace((target->flags() & ACC_NATIVE) ? target : 0, + 0)); + } +} + +bool compileDirectInvoke(MyThread* t, + Frame* frame, + GcMethod* target, + bool tailCall) +{ + // don't bother calling an empty method unless calling it might + // cause the class to be initialized, which may have side effects + if (emptyMethod(t, target) and (not classNeedsInit(t, target->class_()))) { + frame->popFootprint(target->parameterFootprint()); + tailCall = false; + } else { + BootContext* bc = frame->context->bootContext; + if (bc) { + if ((target->class_() == frame->context->method->class_() + or (not classNeedsInit(t, target->class_()))) + and (not(avian::codegen::TailCalls and tailCall + and (target->flags() & ACC_NATIVE)))) { + avian::codegen::Promise* p = new (bc->zone) + avian::codegen::ListenPromise(t->m->system, bc->zone); + + PROTECT(t, target); + object pointer = makePointer(t, p); + bc->calls = makeTriple(t, target, pointer, bc->calls); + + compileDirectInvoke(t, frame, target, tailCall, false, p); + } else { + compileDirectInvoke(t, frame, target, tailCall, true, 0); + } + } else if (unresolved(t, methodAddress(t, target)) + or classNeedsInit(t, target->class_())) { + compileDirectInvoke(t, frame, target, tailCall, true, 0); + } else { + compileDirectInvoke(t, frame, target, tailCall, false, 0); + } + } + + return tailCall; +} + +void compileReferenceInvoke(Frame* frame, + ir::Value* method, + GcReference* reference, + bool isStatic, + bool tailCall) +{ + frame->referenceStackCall(isStatic, + method, + reference, + tailCall ? Compiler::TailJump : 0, + frame->trace(0, 0)); +} + +void compileDirectReferenceInvoke(MyThread* t, + Frame* frame, + Thunk thunk, + GcReference* reference, + bool isStatic, + bool tailCall) +{ + avian::codegen::Compiler* c = frame->c; + + PROTECT(t, reference); + + GcPair* pair = makePair(t, frame->context->method, reference); + + compileReferenceInvoke( + frame, + c->nativeCall(c->constant(getThunk(t, thunk), ir::Type::iptr()), + 0, + frame->trace(0, 0), + ir::Type::iptr(), + args(c->threadRegister(), frame->append(pair))), + reference, + isStatic, + tailCall); +} + +void compileAbstractInvoke(Frame* frame, + ir::Value* method, + GcMethod* target, + bool tailCall) +{ + frame->stackCall( + method, target, tailCall ? Compiler::TailJump : 0, frame->trace(0, 0)); +} + +void compileDirectAbstractInvoke(MyThread* t, + Frame* frame, + Thunk thunk, + GcMethod* target, + bool tailCall) +{ + avian::codegen::Compiler* c = frame->c; + + compileAbstractInvoke( + frame, + c->nativeCall(c->constant(getThunk(t, thunk), ir::Type::iptr()), + 0, + frame->trace(0, 0), + ir::Type::iptr(), + args(c->threadRegister(), frame->append(target))), + target, + tailCall); +} + +void handleMonitorEvent(MyThread* t, Frame* frame, intptr_t function) +{ + avian::codegen::Compiler* c = frame->c; + GcMethod* method = frame->context->method; + + if (method->flags() & ACC_SYNCHRONIZED) { + ir::Value* lock; + if (method->flags() & ACC_STATIC) { + PROTECT(t, method); + + lock = frame->append(method->class_()); + } else { + lock = loadLocal( + frame->context, 1, ir::Type::object(), savedTargetIndex(t, method)); + } + + c->nativeCall(c->constant(function, ir::Type::iptr()), + 0, + frame->trace(0, 0), + ir::Type::void_(), + args(c->threadRegister(), lock)); + } +} + +void handleEntrance(MyThread* t, Frame* frame) +{ + GcMethod* method = frame->context->method; + + if ((method->flags() & (ACC_SYNCHRONIZED | ACC_STATIC)) == ACC_SYNCHRONIZED) { + // save 'this' pointer in case it is overwritten. + unsigned index = savedTargetIndex(t, method); + storeLocal(frame->context, + 1, + ir::Type::object(), + loadLocal(frame->context, 1, ir::Type::object(), 0), + index); + frame->set(index, ir::Type::object()); + } + + handleMonitorEvent(t, + frame, + getThunk(t, + method->flags() & ACC_STATIC + ? acquireMonitorForClassOnEntranceThunk + : acquireMonitorForObjectOnEntranceThunk)); +} + +void handleExit(MyThread* t, Frame* frame) +{ + handleMonitorEvent(t, + frame, + getThunk(t, + frame->context->method->flags() & ACC_STATIC + ? releaseMonitorForClassThunk + : releaseMonitorForObjectThunk)); +} + +bool inTryBlock(MyThread* t UNUSED, GcCode* code, unsigned ip) +{ + GcExceptionHandlerTable* table + = cast(t, code->exceptionHandlerTable()); + if (table) { + unsigned length = table->length(); + for (unsigned i = 0; i < length; ++i) { + uint64_t eh = table->body()[i]; + if (ip >= exceptionHandlerStart(eh) and ip < exceptionHandlerEnd(eh)) { + return true; + } + } + } + return false; +} + +bool needsReturnBarrier(MyThread* t UNUSED, GcMethod* method) +{ + return (method->flags() & ConstructorFlag) + and (method->class_()->vmFlags() & HasFinalMemberFlag); +} + +bool returnsNext(MyThread* t, GcCode* code, unsigned ip) +{ + switch (code->body()[ip]) { + case return_: + case areturn: + case ireturn: + case freturn: + case lreturn: + case dreturn: + return true; + + case goto_: { + uint32_t offset = codeReadInt16(t, code, ++ip); + uint32_t newIp = (ip - 3) + offset; + assertT(t, newIp < code->length()); + + return returnsNext(t, code, newIp); + } + + case goto_w: { + uint32_t offset = codeReadInt32(t, code, ++ip); + uint32_t newIp = (ip - 5) + offset; + assertT(t, newIp < code->length()); + + return returnsNext(t, code, newIp); + } + + default: + return false; + } +} + +bool isTailCall(MyThread* t, + GcCode* code, + unsigned ip, + GcMethod* caller, + int calleeReturnCode, + GcByteArray* calleeClassName, + GcByteArray* calleeMethodName, + GcByteArray* calleeMethodSpec) +{ + return avian::codegen::TailCalls + and ((caller->flags() & ACC_SYNCHRONIZED) == 0) + and (not inTryBlock(t, code, ip - 1)) + and (not needsReturnBarrier(t, caller)) + and (caller->returnCode() == VoidField + or caller->returnCode() == calleeReturnCode) + and returnsNext(t, code, ip) + and t->m->classpath->canTailCall(t, + caller, + calleeClassName, + calleeMethodName, + calleeMethodSpec); +} + +bool isTailCall(MyThread* t, + GcCode* code, + unsigned ip, + GcMethod* caller, + GcMethod* callee) +{ + return isTailCall(t, + code, + ip, + caller, + callee->returnCode(), + callee->class_()->name(), + callee->name(), + callee->spec()); +} + +bool isReferenceTailCall(MyThread* t, + GcCode* code, + unsigned ip, + GcMethod* caller, + GcReference* calleeReference) +{ + return isTailCall(t, + code, + ip, + caller, + methodReferenceReturnCode(t, calleeReference), + calleeReference->class_(), + calleeReference->name(), + calleeReference->spec()); +} + +lir::TernaryOperation toCompilerJumpOp(MyThread* t, unsigned instruction) +{ + switch (instruction) { + case ifeq: + case if_icmpeq: + case if_acmpeq: + case ifnull: + return lir::JumpIfEqual; + case ifne: + case if_icmpne: + case if_acmpne: + case ifnonnull: + return lir::JumpIfNotEqual; + case ifgt: + case if_icmpgt: + return lir::JumpIfGreater; + case ifge: + case if_icmpge: + return lir::JumpIfGreaterOrEqual; + case iflt: + case if_icmplt: + return lir::JumpIfLess; + case ifle: + case if_icmple: + return lir::JumpIfLessOrEqual; + default: + abort(t); + } +} + +bool integerBranch(MyThread* t, + Frame* frame, + GcCode* code, + unsigned& ip, + ir::Value* a, + ir::Value* b, + unsigned* newIpp) +{ + if (ip + 3 > code->length()) { + return false; + } + + avian::codegen::Compiler* c = frame->c; + unsigned instruction = code->body()[ip++]; + uint32_t offset = codeReadInt16(t, code, ip); + uint32_t newIp = (ip - 3) + offset; + assertT(t, newIp < code->length()); + + ir::Value* target = frame->machineIpValue(newIp); + + switch (instruction) { + case ifeq: + case ifne: + case ifgt: + case ifge: + case iflt: + case ifle: + c->condJump(toCompilerJumpOp(t, instruction), a, b, target); + break; + + default: + ip -= 3; + return false; + } + + *newIpp = newIp; + return true; +} + +lir::TernaryOperation toCompilerFloatJumpOp(MyThread* t, + unsigned instruction, + bool lessIfUnordered) +{ + switch (instruction) { + case ifeq: + return lir::JumpIfFloatEqual; + case ifne: + return lir::JumpIfFloatNotEqual; + case ifgt: + if (lessIfUnordered) { + return lir::JumpIfFloatGreater; + } else { + return lir::JumpIfFloatGreaterOrUnordered; + } + case ifge: + if (lessIfUnordered) { + return lir::JumpIfFloatGreaterOrEqual; + } else { + return lir::JumpIfFloatGreaterOrEqualOrUnordered; + } + case iflt: + if (lessIfUnordered) { + return lir::JumpIfFloatLessOrUnordered; + } else { + return lir::JumpIfFloatLess; + } + case ifle: + if (lessIfUnordered) { + return lir::JumpIfFloatLessOrEqualOrUnordered; + } else { + return lir::JumpIfFloatLessOrEqual; + } + default: + abort(t); + } +} + +bool floatBranch(MyThread* t, + Frame* frame, + GcCode* code, + unsigned& ip, + bool lessIfUnordered, + ir::Value* a, + ir::Value* b, + unsigned* newIpp) +{ + if (ip + 3 > code->length()) { + return false; + } + + avian::codegen::Compiler* c = frame->c; + unsigned instruction = code->body()[ip++]; + uint32_t offset = codeReadInt16(t, code, ip); + uint32_t newIp = (ip - 3) + offset; + assertT(t, newIp < code->length()); + + ir::Value* target = frame->machineIpValue(newIp); + + switch (instruction) { + case ifeq: + case ifne: + case ifgt: + case ifge: + case iflt: + case ifle: + c->condJump( + toCompilerFloatJumpOp(t, instruction, lessIfUnordered), a, b, target); + break; + + default: + ip -= 3; + return false; + } + + *newIpp = newIp; + return true; +} + +ir::Value* popLongAddress(Frame* frame) +{ + return TargetBytesPerWord == 8 + ? frame->popLarge(ir::Type::i8()) + : frame->c->load(ir::ExtendMode::Signed, + frame->popLarge(ir::Type::i8()), + ir::Type::iptr()); +} + +bool intrinsic(MyThread* t UNUSED, Frame* frame, GcMethod* target) +{ +#define MATCH(name, constant) \ + (name->length() == sizeof(constant) \ + and ::strcmp(reinterpret_cast(name->body().begin()), constant) == 0) + + GcByteArray* className = target->class_()->name(); + if (UNLIKELY(MATCH(className, "java/lang/Math"))) { + avian::codegen::Compiler* c = frame->c; + if (MATCH(target->name(), "sqrt") and MATCH(target->spec(), "(D)D")) { + frame->pushLarge( + ir::Type::f8(), + c->unaryOp(lir::FloatSquareRoot, frame->popLarge(ir::Type::f8()))); + return true; + } else if (MATCH(target->name(), "abs")) { + if (MATCH(target->spec(), "(I)I")) { + frame->push(ir::Type::i4(), + c->unaryOp(lir::Absolute, frame->pop(ir::Type::i4()))); + return true; + } else if (MATCH(target->spec(), "(J)J")) { + frame->pushLarge( + ir::Type::i8(), + c->unaryOp(lir::Absolute, frame->popLarge(ir::Type::i8()))); + return true; + } else if (MATCH(target->spec(), "(F)F")) { + frame->push(ir::Type::f4(), + c->unaryOp(lir::FloatAbsolute, frame->pop(ir::Type::f4()))); + return true; + } + } + } else if (UNLIKELY(MATCH(className, "sun/misc/Unsafe"))) { + avian::codegen::Compiler* c = frame->c; + if (MATCH(target->name(), "getByte") and MATCH(target->spec(), "(J)B")) { + ir::Value* address = popLongAddress(frame); + frame->pop(ir::Type::object()); + frame->push(ir::Type::i4(), + c->load(ir::ExtendMode::Signed, + c->memory(address, ir::Type::i1()), + ir::Type::i4())); + return true; + } else if (MATCH(target->name(), "putByte") + and MATCH(target->spec(), "(JB)V")) { + ir::Value* value = frame->pop(ir::Type::i4()); + ir::Value* address = popLongAddress(frame); + frame->pop(ir::Type::object()); + c->store(value, c->memory(address, ir::Type::i1())); + return true; + } else if ((MATCH(target->name(), "getShort") + and MATCH(target->spec(), "(J)S")) + or (MATCH(target->name(), "getChar") + and MATCH(target->spec(), "(J)C"))) { + ir::Value* address = popLongAddress(frame); + frame->pop(ir::Type::object()); + frame->push(ir::Type::i4(), + c->load(ir::ExtendMode::Signed, + c->memory(address, ir::Type::i2()), + ir::Type::i4())); + return true; + } else if ((MATCH(target->name(), "putShort") + and MATCH(target->spec(), "(JS)V")) + or (MATCH(target->name(), "putChar") + and MATCH(target->spec(), "(JC)V"))) { + ir::Value* value = frame->pop(ir::Type::i4()); + ir::Value* address = popLongAddress(frame); + frame->pop(ir::Type::object()); + c->store(value, c->memory(address, ir::Type::i2())); + return true; + } else if ((MATCH(target->name(), "getInt") + and MATCH(target->spec(), "(J)I")) + or (MATCH(target->name(), "getFloat") + and MATCH(target->spec(), "(J)F"))) { + ir::Value* address = popLongAddress(frame); + frame->pop(ir::Type::object()); + ir::Type type = MATCH(target->name(), "getInt") ? ir::Type::i4() + : ir::Type::f4(); + frame->push( + type, + c->load(ir::ExtendMode::Signed, c->memory(address, type), type)); + return true; + } else if ((MATCH(target->name(), "putInt") + and MATCH(target->spec(), "(JI)V")) + or (MATCH(target->name(), "putFloat") + and MATCH(target->spec(), "(JF)V"))) { + ir::Type type = MATCH(target->name(), "putInt") ? ir::Type::i4() + : ir::Type::f4(); + ir::Value* value = frame->pop(type); + ir::Value* address = popLongAddress(frame); + frame->pop(ir::Type::object()); + c->store(value, c->memory(address, type)); + return true; + } else if ((MATCH(target->name(), "getLong") + and MATCH(target->spec(), "(J)J")) + or (MATCH(target->name(), "getDouble") + and MATCH(target->spec(), "(J)D"))) { + ir::Value* address = popLongAddress(frame); + frame->pop(ir::Type::object()); + ir::Type type = MATCH(target->name(), "getLong") ? ir::Type::i8() + : ir::Type::f8(); + frame->pushLarge( + type, + c->load(ir::ExtendMode::Signed, c->memory(address, type), type)); + return true; + } else if ((MATCH(target->name(), "putLong") + and MATCH(target->spec(), "(JJ)V")) + or (MATCH(target->name(), "putDouble") + and MATCH(target->spec(), "(JD)V"))) { + ir::Type type = MATCH(target->name(), "putLong") ? ir::Type::i8() + : ir::Type::f8(); + ir::Value* value = frame->popLarge(type); + ir::Value* address = popLongAddress(frame); + frame->pop(ir::Type::object()); + c->store(value, c->memory(address, type)); + return true; + } else if (MATCH(target->name(), "getAddress") + and MATCH(target->spec(), "(J)J")) { + ir::Value* address = popLongAddress(frame); + frame->pop(ir::Type::object()); + frame->pushLarge(ir::Type::i8(), + c->load(ir::ExtendMode::Signed, + c->memory(address, ir::Type::iptr()), + ir::Type::i8())); + return true; + } else if (MATCH(target->name(), "putAddress") + and MATCH(target->spec(), "(JJ)V")) { + ir::Value* value = frame->popLarge(ir::Type::i8()); + ir::Value* address = popLongAddress(frame); + frame->pop(ir::Type::object()); + c->store(value, c->memory(address, ir::Type::iptr())); + return true; + } + } + return false; +} + +unsigned targetFieldOffset(Context* context, GcField* field) +{ + if (context->bootContext) { + return context->bootContext->resolver->fieldOffset(context->thread, field); + } else { + return field->offset(); + } +} + +class Stack { + public: + class MyResource : public Thread::AutoResource { + public: + MyResource(Stack* s) : AutoResource(s->thread), s(s) + { + } + + virtual void release() + { + s->zone.dispose(); + } + + Stack* s; + }; + + Stack(MyThread* t) : thread(t), zone(t->m->heap, 0), resource(this) + { + } + + ~Stack() + { + zone.dispose(); + } + + void pushValue(uintptr_t v) + { + *static_cast(push(BytesPerWord)) = v; + } + + uintptr_t peekValue(unsigned offset) + { + return *static_cast(peek((offset + 1) * BytesPerWord)); + } + + uintptr_t popValue() + { + uintptr_t v = peekValue(0); + pop(BytesPerWord); + return v; + } + + void* push(unsigned size) + { + return zone.allocate(size); + } + + void* peek(unsigned size) + { + return zone.peek(size); + } + + void pop(unsigned size) + { + zone.pop(size); + } + + MyThread* thread; + Zone zone; + MyResource resource; +}; + +class SwitchState { + public: + SwitchState(Compiler::State* state, + unsigned count, + unsigned defaultIp, + ir::Value* key, + avian::codegen::Promise* start, + int bottom, + int top) + : state(state), + count(count), + defaultIp(defaultIp), + key(key), + start(start), + bottom(bottom), + top(top), + index(0) + { + } + + Frame* frame() + { + return reinterpret_cast(reinterpret_cast(this) + - pad(count * 4) - pad(sizeof(Frame))); + } + + uint32_t* ipTable() + { + return reinterpret_cast(reinterpret_cast(this) + - pad(count * 4)); + } + + Compiler::State* state; + unsigned count; + unsigned defaultIp; + ir::Value* key; + avian::codegen::Promise* start; + int bottom; + int top; + unsigned index; +}; + +lir::TernaryOperation toCompilerBinaryOp(MyThread* t, unsigned instruction) +{ + switch (instruction) { + case iadd: + case ladd: + return lir::Add; + case ior: + case lor: + return lir::Or; + case ishl: + case lshl: + return lir::ShiftLeft; + case ishr: + case lshr: + return lir::ShiftRight; + case iushr: + case lushr: + return lir::UnsignedShiftRight; + case fadd: + case dadd: + return lir::FloatAdd; + case fsub: + case dsub: + return lir::FloatSubtract; + case fmul: + case dmul: + return lir::FloatMultiply; + case fdiv: + case ddiv: + return lir::FloatDivide; + case frem: + case vm::drem: + return lir::FloatRemainder; + case iand: + case land: + return lir::And; + case isub: + case lsub: + return lir::Subtract; + case ixor: + case lxor: + return lir::Xor; + case imul: + case lmul: + return lir::Multiply; + default: + abort(t); + } +} + +uintptr_t aioobThunk(MyThread* t); + +uintptr_t stackOverflowThunk(MyThread* t); + +void checkField(Thread* t, GcField* field, bool shouldBeStatic) +{ + if (((field->flags() & ACC_STATIC) == 0) == shouldBeStatic) { + throwNew(t, + GcIncompatibleClassChangeError::Type, + "expected %s.%s to be %s", + field->class_()->name()->body().begin(), + field->name()->body().begin(), + shouldBeStatic ? "static" : "non-static"); + } +} + +bool isLambda(Thread* t, + GcClassLoader* loader, + GcCharArray* bootstrapArray, + GcInvocation* invocation) +{ + GcMethod* bootstrap = cast(t, + resolve(t, + loader, + invocation->pool(), + bootstrapArray->body()[0], + findMethodInClass, + GcNoSuchMethodError::Type)); + PROTECT(t, bootstrap); + + return vm::strcmp(reinterpret_cast( + "java/lang/invoke/LambdaMetafactory"), + bootstrap->class_()->name()->body().begin()) == 0 + and ((vm::strcmp(reinterpret_cast("metafactory"), + bootstrap->name()->body().begin()) == 0 + and vm::strcmp( + reinterpret_cast( + "(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/" + "String;Ljava/lang/invoke/MethodType;Ljava/lang/" + "invoke/" + "MethodType;Ljava/lang/invoke/MethodHandle;Ljava/" + "lang/" + "invoke/MethodType;)Ljava/lang/invoke/CallSite;"), + bootstrap->spec()->body().begin()) == 0) + or (vm::strcmp(reinterpret_cast("altMetafactory"), + bootstrap->name()->body().begin()) == 0 + and vm::strcmp( + reinterpret_cast( + "(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/" + "lang/" + "String;Ljava/lang/invoke/MethodType;[Ljava/lang/" + "Object;)Ljava/lang/invoke/CallSite;"), + bootstrap->spec()->body().begin()) == 0)); +} + +void compile(MyThread* t, + Frame* initialFrame, + unsigned initialIp, + int exceptionHandlerStart = -1) +{ + enum { Return, Unbranch, Unsubroutine, Untable0, Untable1, Unswitch }; + + Frame* frame = initialFrame; + avian::codegen::Compiler* c = frame->c; + Context* context = frame->context; + unsigned stackSize = context->method->code()->maxStack(); + Stack stack(t); + unsigned ip = initialIp; + unsigned newIp; + stack.pushValue(Return); + +start: + ir::Type* stackMap + = static_cast(stack.push(stackSize * sizeof(ir::Type))); + frame = new (stack.push(sizeof(Frame))) Frame(frame, stackMap); + +loop: + GcCode* code = context->method->code(); + PROTECT(t, code); + + while (ip < code->length()) { + if (context->visitTable[frame->duplicatedIp(ip)]++) { + // we've already visited this part of the code + frame->visitLogicalIp(ip); + goto next; + } + + frame->startLogicalIp(ip); + + if (exceptionHandlerStart >= 0) { + c->initLocalsFromLogicalIp(exceptionHandlerStart); + + exceptionHandlerStart = -1; + + frame->pushObject(); + + c->nativeCall( + c->constant(getThunk(t, gcIfNecessaryThunk), ir::Type::iptr()), + 0, + frame->trace(0, 0), + ir::Type::void_(), + args(c->threadRegister())); + } + + if (DebugInstructions) { + unsigned startingIp = ip; + fprintf(stderr, " stack: ["); + for (size_t i = frame->localSize(); i < frame->sp; i++) { + ir::Type ty = frame->get(i); + if (ty == ir::Type::i4()) { + fprintf(stderr, "I"); + } else if (ty == ir::Type::i8()) { + fprintf(stderr, "L"); + } else if (ty == ir::Type::f4()) { + fprintf(stderr, "F"); + } else if (ty == ir::Type::f8()) { + fprintf(stderr, "D"); + } else if (ty == ir::Type::object()) { + fprintf(stderr, "O"); + } else { + fprintf(stderr, "?"); + } + } + fprintf(stderr, "]\n"); + fprintf(stderr, "% 5d: ", startingIp); + avian::jvm::debug::printInstruction(code->body().begin(), startingIp); + fprintf(stderr, "\n"); + } + + unsigned instruction = code->body()[ip++]; + + switch (instruction) { + case aaload: + case baload: + case caload: + case daload: + case faload: + case iaload: + case laload: + case saload: { + ir::Value* index = frame->pop(ir::Type::i4()); + ir::Value* array = frame->pop(ir::Type::object()); + + if (inTryBlock(t, code, ip - 1)) { + c->saveLocals(); + frame->trace(0, 0); + } + + if (CheckArrayBounds) { + c->checkBounds(array, TargetArrayLength, index, aioobThunk(t)); + } + + switch (instruction) { + case aaload: + frame->push( + ir::Type::object(), + c->load( + ir::ExtendMode::Signed, + c->memory(array, ir::Type::object(), TargetArrayBody, index), + ir::Type::object())); + break; + + case faload: + frame->push( + ir::Type::f4(), + c->load(ir::ExtendMode::Signed, + c->memory(array, ir::Type::f4(), TargetArrayBody, index), + ir::Type::f4())); + break; + + case iaload: + frame->push( + ir::Type::i4(), + c->load(ir::ExtendMode::Signed, + c->memory(array, ir::Type::i4(), TargetArrayBody, index), + ir::Type::i4())); + break; + + case baload: + frame->push( + ir::Type::i4(), + c->load(ir::ExtendMode::Signed, + c->memory(array, ir::Type::i1(), TargetArrayBody, index), + ir::Type::i4())); + break; + + case caload: + frame->push( + ir::Type::i4(), + c->load(ir::ExtendMode::Unsigned, + c->memory(array, ir::Type::i2(), TargetArrayBody, index), + ir::Type::i4())); + break; + + case daload: + frame->pushLarge( + ir::Type::f8(), + c->load(ir::ExtendMode::Signed, + c->memory(array, ir::Type::f8(), TargetArrayBody, index), + ir::Type::f8())); + break; + + case laload: + frame->pushLarge( + ir::Type::i8(), + c->load(ir::ExtendMode::Signed, + c->memory(array, ir::Type::i8(), TargetArrayBody, index), + ir::Type::i8())); + break; + + case saload: + frame->push( + ir::Type::i4(), + c->load(ir::ExtendMode::Signed, + c->memory(array, ir::Type::i2(), TargetArrayBody, index), + ir::Type::i4())); + break; + } + } break; + + case aastore: + case bastore: + case castore: + case dastore: + case fastore: + case iastore: + case lastore: + case sastore: { + ir::Value* value; + if (instruction == lastore) { + value = frame->popLarge(ir::Type::i8()); + } else if (instruction == dastore) { + value = frame->popLarge(ir::Type::f8()); + } else if (instruction == aastore) { + value = frame->pop(ir::Type::object()); + } else if (instruction == fastore) { + value = frame->pop(ir::Type::f4()); + } else { + value = frame->pop(ir::Type::i4()); + } + + ir::Value* index = frame->pop(ir::Type::i4()); + ir::Value* array = frame->pop(ir::Type::object()); + + if (inTryBlock(t, code, ip - 1)) { + c->saveLocals(); + frame->trace(0, 0); + } + + if (CheckArrayBounds) { + c->checkBounds(array, TargetArrayLength, index, aioobThunk(t)); + } + + switch (instruction) { + case aastore: { + c->nativeCall( + c->constant(getThunk(t, setMaybeNullThunk), ir::Type::iptr()), + 0, + frame->trace(0, 0), + ir::Type::void_(), + args(c->threadRegister(), + array, + c->binaryOp(lir::Add, + ir::Type::i4(), + c->constant(TargetArrayBody, ir::Type::i4()), + c->binaryOp(lir::ShiftLeft, + ir::Type::i4(), + c->constant(log(TargetBytesPerWord), + ir::Type::i4()), + index)), + value)); + } break; + + case fastore: + c->store(value, + c->memory(array, ir::Type::f4(), TargetArrayBody, index)); + break; + + case iastore: + c->store(value, + c->memory(array, ir::Type::i4(), TargetArrayBody, index)); + break; + + case bastore: + c->store(value, + c->memory(array, ir::Type::i1(), TargetArrayBody, index)); + break; + + case castore: + case sastore: + c->store(value, + c->memory(array, ir::Type::i2(), TargetArrayBody, index)); + break; + + case dastore: + c->store(value, + c->memory(array, ir::Type::f8(), TargetArrayBody, index)); + break; + + case lastore: + c->store(value, + c->memory(array, ir::Type::i8(), TargetArrayBody, index)); + break; + } + } break; + + case aconst_null: + frame->push(ir::Type::object(), c->constant(0, ir::Type::object())); + break; + + case aload: + frame->load(ir::Type::object(), code->body()[ip++]); + break; + + case aload_0: + frame->load(ir::Type::object(), 0); + break; + + case aload_1: + frame->load(ir::Type::object(), 1); + break; + + case aload_2: + frame->load(ir::Type::object(), 2); + break; + + case aload_3: + frame->load(ir::Type::object(), 3); + break; + + case anewarray: { + uint16_t index = codeReadInt16(t, code, ip); + + object reference + = singletonObject(t, context->method->code()->pool(), index - 1); + + PROTECT(t, reference); + + GcClass* class_ + = resolveClassInPool(t, context->method, index - 1, false); + + ir::Value* length = frame->pop(ir::Type::i4()); + + object argument; + Thunk thunk; + if (LIKELY(class_)) { + argument = class_; + thunk = makeBlankObjectArrayThunk; + } else { + argument = makePair(t, context->method, reference); + thunk = makeBlankObjectArrayFromReferenceThunk; + } + + frame->push( + ir::Type::object(), + c->nativeCall( + c->constant(getThunk(t, thunk), ir::Type::iptr()), + 0, + frame->trace(0, 0), + ir::Type::object(), + args(c->threadRegister(), frame->append(argument), length))); + } break; + + case areturn: { + handleExit(t, frame); + c->return_(frame->pop(ir::Type::object())); + } + goto next; + + case arraylength: { + frame->push(ir::Type::i4(), + c->load(ir::ExtendMode::Signed, + c->memory(frame->pop(ir::Type::object()), + ir::Type::iptr(), + TargetArrayLength), + ir::Type::i4())); + } break; + + case astore: + frame->store(ir::Type::object(), code->body()[ip++]); + break; + + case astore_0: + frame->store(ir::Type::object(), 0); + break; + + case astore_1: + frame->store(ir::Type::object(), 1); + break; + + case astore_2: + frame->store(ir::Type::object(), 2); + break; + + case astore_3: + frame->store(ir::Type::object(), 3); + break; + + case athrow: { + ir::Value* target = frame->pop(ir::Type::object()); + c->nativeCall(c->constant(getThunk(t, throw_Thunk), ir::Type::iptr()), + Compiler::NoReturn, + frame->trace(0, 0), + ir::Type::void_(), + args(c->threadRegister(), target)); + + c->nullaryOp(lir::Trap); + } + goto next; + + case bipush: + frame->push( + ir::Type::i4(), + c->constant(static_cast(code->body()[ip++]), ir::Type::i4())); + break; + + case checkcast: { + uint16_t index = codeReadInt16(t, code, ip); + + object reference + = singletonObject(t, context->method->code()->pool(), index - 1); + + PROTECT(t, reference); + + GcClass* class_ + = resolveClassInPool(t, context->method, index - 1, false); + + object argument; + Thunk thunk; + if (LIKELY(class_)) { + argument = class_; + thunk = checkCastThunk; + } else { + argument = makePair(t, context->method, reference); + thunk = checkCastFromReferenceThunk; + } + + ir::Value* instance = c->peek(1, 0); + + c->nativeCall( + c->constant(getThunk(t, thunk), ir::Type::iptr()), + 0, + frame->trace(0, 0), + ir::Type::void_(), + args(c->threadRegister(), frame->append(argument), instance)); + } break; + + case d2f: { + frame->push(ir::Type::f4(), + c->f2f(ir::Type::f4(), frame->popLarge(ir::Type::f8()))); + } break; + + case d2i: { + frame->push(ir::Type::i4(), + c->f2i(ir::Type::i4(), frame->popLarge(ir::Type::f8()))); + } break; + + case d2l: { + frame->pushLarge(ir::Type::i8(), + c->f2i(ir::Type::i8(), frame->popLarge(ir::Type::f8()))); + } break; + + case dadd: + case dsub: + case dmul: + case ddiv: + case vm::drem: { + ir::Value* a = frame->popLarge(ir::Type::f8()); + ir::Value* b = frame->popLarge(ir::Type::f8()); + + frame->pushLarge( + ir::Type::f8(), + c->binaryOp( + toCompilerBinaryOp(t, instruction), ir::Type::f8(), a, b)); + } break; + + case dcmpg: { + ir::Value* a = frame->popLarge(ir::Type::f8()); + ir::Value* b = frame->popLarge(ir::Type::f8()); + + if (floatBranch(t, frame, code, ip, false, a, b, &newIp)) { + goto branch; + } else { + frame->push(ir::Type::i4(), + c->nativeCall(c->constant(getThunk(t, compareDoublesGThunk), + ir::Type::iptr()), + 0, + 0, + ir::Type::i4(), + args(nullptr, a, nullptr, b))); + } + } break; + + case dcmpl: { + ir::Value* a = frame->popLarge(ir::Type::f8()); + ir::Value* b = frame->popLarge(ir::Type::f8()); + + if (floatBranch(t, frame, code, ip, true, a, b, &newIp)) { + goto branch; + } else { + frame->push(ir::Type::i4(), + c->nativeCall(c->constant(getThunk(t, compareDoublesLThunk), + ir::Type::iptr()), + 0, + 0, + ir::Type::i4(), + args(nullptr, a, nullptr, b))); + } + } break; + + case dconst_0: + frame->pushLarge(ir::Type::f8(), + c->constant(doubleToBits(0.0), ir::Type::f8())); + break; + + case dconst_1: + frame->pushLarge(ir::Type::f8(), + c->constant(doubleToBits(1.0), ir::Type::f8())); + break; + + case dneg: { + frame->pushLarge( + ir::Type::f8(), + c->unaryOp(lir::FloatNegate, frame->popLarge(ir::Type::f8()))); + } break; + + case vm::dup: + frame->dup(); + break; + + case dup_x1: + frame->dupX1(); + break; + + case dup_x2: + frame->dupX2(); + break; + + case vm::dup2: + frame->dup2(); + break; + + case dup2_x1: + frame->dup2X1(); + break; + + case dup2_x2: + frame->dup2X2(); + break; + + case f2d: { + frame->pushLarge(ir::Type::f8(), + c->f2f(ir::Type::f8(), frame->pop(ir::Type::f4()))); + } break; + + case f2i: { + frame->push(ir::Type::i4(), + c->f2i(ir::Type::i4(), frame->pop(ir::Type::f4()))); + } break; + + case f2l: { + frame->pushLarge(ir::Type::i8(), + c->f2i(ir::Type::i8(), frame->pop(ir::Type::f4()))); + } break; + + case fadd: + case fsub: + case fmul: + case fdiv: + case frem: { + ir::Value* a = frame->pop(ir::Type::f4()); + ir::Value* b = frame->pop(ir::Type::f4()); + + frame->push( + ir::Type::f4(), + c->binaryOp( + toCompilerBinaryOp(t, instruction), ir::Type::f4(), a, b)); + } break; + + case fcmpg: { + ir::Value* a = frame->pop(ir::Type::f4()); + ir::Value* b = frame->pop(ir::Type::f4()); + + if (floatBranch(t, frame, code, ip, false, a, b, &newIp)) { + goto branch; + } else { + frame->push(ir::Type::i4(), + c->nativeCall(c->constant(getThunk(t, compareFloatsGThunk), + ir::Type::iptr()), + 0, + 0, + ir::Type::i4(), + args(a, b))); + } + } break; + + case fcmpl: { + ir::Value* a = frame->pop(ir::Type::f4()); + ir::Value* b = frame->pop(ir::Type::f4()); + + if (floatBranch(t, frame, code, ip, true, a, b, &newIp)) { + goto branch; + } else { + frame->push(ir::Type::i4(), + c->nativeCall(c->constant(getThunk(t, compareFloatsLThunk), + ir::Type::iptr()), + 0, + 0, + ir::Type::i4(), + args(a, b))); + } + } break; + + case fconst_0: + frame->push(ir::Type::f4(), + c->constant(floatToBits(0.0), ir::Type::f4())); + break; + + case fconst_1: + frame->push(ir::Type::f4(), + c->constant(floatToBits(1.0), ir::Type::f4())); + break; + + case fconst_2: + frame->push(ir::Type::f4(), + c->constant(floatToBits(2.0), ir::Type::f4())); + break; + + case fneg: { + frame->push(ir::Type::f4(), + c->unaryOp(lir::FloatNegate, frame->pop(ir::Type::f4()))); + } break; + + case getfield: + case getstatic: { + uint16_t index = codeReadInt16(t, code, ip); + + object reference + = singletonObject(t, context->method->code()->pool(), index - 1); + + PROTECT(t, reference); + + GcField* field = resolveField(t, context->method, index - 1, false); + + if (LIKELY(field)) { + if ((field->flags() & ACC_VOLATILE) and TargetBytesPerWord == 4 + and (field->code() == DoubleField or field->code() == LongField)) { + PROTECT(t, field); + + c->nativeCall(c->constant(getThunk(t, acquireMonitorForObjectThunk), + ir::Type::iptr()), + 0, + frame->trace(0, 0), + ir::Type::void_(), + args(c->threadRegister(), frame->append(field))); + } + + ir::Value* table; + + if (instruction == getstatic) { + checkField(t, field, true); + + PROTECT(t, field); + + if (classNeedsInit(t, field->class_())) { + c->nativeCall( + c->constant(getThunk(t, tryInitClassThunk), ir::Type::iptr()), + 0, + frame->trace(0, 0), + ir::Type::void_(), + args(c->threadRegister(), frame->append(field->class_()))); + } + + table = frame->append(field->class_()->staticTable()); + } else { + checkField(t, field, false); + + table = frame->pop(ir::Type::object()); + + if (inTryBlock(t, code, ip - 3)) { + c->saveLocals(); + frame->trace(0, 0); + } + } + + switch (field->code()) { + case ByteField: + case BooleanField: + frame->push(ir::Type::i4(), + c->load(ir::ExtendMode::Signed, + c->memory(table, + ir::Type::i1(), + targetFieldOffset(context, field)), + ir::Type::i4())); + break; + + case CharField: + frame->push(ir::Type::i4(), + c->load(ir::ExtendMode::Unsigned, + c->memory(table, + ir::Type::i2(), + targetFieldOffset(context, field)), + ir::Type::i4())); + break; + + case ShortField: + frame->push(ir::Type::i4(), + c->load(ir::ExtendMode::Signed, + c->memory(table, + ir::Type::i2(), + targetFieldOffset(context, field)), + ir::Type::i4())); + break; + + case FloatField: + frame->push(ir::Type::f4(), + c->load(ir::ExtendMode::Signed, + c->memory(table, + ir::Type::f4(), + targetFieldOffset(context, field)), + ir::Type::f4())); + break; + + case IntField: + frame->push(ir::Type::i4(), + c->load(ir::ExtendMode::Signed, + c->memory(table, + ir::Type::i4(), + targetFieldOffset(context, field)), + ir::Type::i4())); + break; + + case DoubleField: + frame->pushLarge(ir::Type::f8(), + c->load(ir::ExtendMode::Signed, + c->memory(table, + ir::Type::f8(), + targetFieldOffset(context, field)), + ir::Type::f8())); + break; + + case LongField: + frame->pushLarge(ir::Type::i8(), + c->load(ir::ExtendMode::Signed, + c->memory(table, + ir::Type::i8(), + targetFieldOffset(context, field)), + ir::Type::i8())); + break; + + case ObjectField: + frame->push(ir::Type::object(), + c->load(ir::ExtendMode::Signed, + c->memory(table, + ir::Type::object(), + targetFieldOffset(context, field)), + ir::Type::object())); + break; + + default: + abort(t); + } + + if (field->flags() & ACC_VOLATILE) { + if (TargetBytesPerWord == 4 and (field->code() == DoubleField + or field->code() == LongField)) { + c->nativeCall(c->constant(getThunk(t, releaseMonitorForObjectThunk), + ir::Type::iptr()), + 0, + frame->trace(0, 0), + ir::Type::void_(), + args(c->threadRegister(), frame->append(field))); + } else { + c->nullaryOp(lir::LoadBarrier); + } + } + } else { + GcReference* ref = cast(t, reference); + PROTECT(t, ref); + int fieldCode = vm::fieldCode(t, ref->spec()->body()[0]); + + GcPair* pair = makePair(t, context->method, reference); + + ir::Type rType = operandTypeForFieldCode(t, fieldCode); + + ir::Value* result; + if (instruction == getstatic) { + result = c->nativeCall( + c->constant(getThunk(t, getStaticFieldValueFromReferenceThunk), + ir::Type::iptr()), + 0, + frame->trace(0, 0), + rType, + args(c->threadRegister(), frame->append(pair))); + } else { + ir::Value* instance = frame->pop(ir::Type::object()); + + result = c->nativeCall( + c->constant(getThunk(t, getFieldValueFromReferenceThunk), + ir::Type::iptr()), + 0, + frame->trace(0, 0), + rType, + args(c->threadRegister(), frame->append(pair), instance)); + } + + frame->pushReturnValue(fieldCode, result); + } + } break; + + case goto_: { + uint32_t offset = codeReadInt16(t, code, ip); + uint32_t newIp = (ip - 3) + offset; + assertT(t, newIp < code->length()); + + if (newIp <= ip) { + compileSafePoint(t, c, frame); + } + + c->jmp(frame->machineIpValue(newIp)); + ip = newIp; + } break; + + case goto_w: { + uint32_t offset = codeReadInt32(t, code, ip); + uint32_t newIp = (ip - 5) + offset; + assertT(t, newIp < code->length()); + + if (newIp <= ip) { + compileSafePoint(t, c, frame); + } + + c->jmp(frame->machineIpValue(newIp)); + ip = newIp; + } break; + + case i2b: { + frame->push(ir::Type::i4(), + c->truncateThenExtend(ir::ExtendMode::Signed, + ir::Type::i4(), + ir::Type::i1(), + frame->pop(ir::Type::i4()))); + } break; + + case i2c: { + frame->push(ir::Type::i4(), + c->truncateThenExtend(ir::ExtendMode::Unsigned, + ir::Type::i4(), + ir::Type::i2(), + frame->pop(ir::Type::i4()))); + } break; + + case i2d: { + frame->pushLarge(ir::Type::f8(), + c->i2f(ir::Type::f8(), frame->pop(ir::Type::i4()))); + } break; + + case i2f: { + frame->push(ir::Type::f4(), + c->i2f(ir::Type::f4(), frame->pop(ir::Type::i4()))); + } break; + + case i2l: + frame->pushLarge(ir::Type::i8(), + c->truncateThenExtend(ir::ExtendMode::Signed, + ir::Type::i8(), + ir::Type::i4(), + frame->pop(ir::Type::i4()))); + break; + + case i2s: { + frame->push(ir::Type::i4(), + c->truncateThenExtend(ir::ExtendMode::Signed, + ir::Type::i4(), + ir::Type::i2(), + frame->pop(ir::Type::i4()))); + } break; + + case iadd: + case iand: + case ior: + case ishl: + case ishr: + case iushr: + case isub: + case ixor: + case imul: { + ir::Value* a = frame->pop(ir::Type::i4()); + ir::Value* b = frame->pop(ir::Type::i4()); + frame->push( + ir::Type::i4(), + c->binaryOp( + toCompilerBinaryOp(t, instruction), ir::Type::i4(), a, b)); + } break; + + case iconst_m1: + frame->push(ir::Type::i4(), c->constant(-1, ir::Type::i4())); + break; + + case iconst_0: + frame->push(ir::Type::i4(), c->constant(0, ir::Type::i4())); + break; + + case iconst_1: + frame->push(ir::Type::i4(), c->constant(1, ir::Type::i4())); + break; + + case iconst_2: + frame->push(ir::Type::i4(), c->constant(2, ir::Type::i4())); + break; + + case iconst_3: + frame->push(ir::Type::i4(), c->constant(3, ir::Type::i4())); + break; + + case iconst_4: + frame->push(ir::Type::i4(), c->constant(4, ir::Type::i4())); + break; + + case iconst_5: + frame->push(ir::Type::i4(), c->constant(5, ir::Type::i4())); + break; + + case idiv: { + ir::Value* a = frame->pop(ir::Type::i4()); + ir::Value* b = frame->pop(ir::Type::i4()); + + if (inTryBlock(t, code, ip - 1)) { + c->saveLocals(); + frame->trace(0, 0); + } + + frame->push(ir::Type::i4(), + c->binaryOp(lir::Divide, ir::Type::i4(), a, b)); + } break; + + case if_acmpeq: + case if_acmpne: { + uint32_t offset = codeReadInt16(t, code, ip); + newIp = (ip - 3) + offset; + assertT(t, newIp < code->length()); + + if (newIp <= ip) { + compileSafePoint(t, c, frame); + } + + ir::Value* a = frame->pop(ir::Type::object()); + ir::Value* b = frame->pop(ir::Type::object()); + ir::Value* target = frame->machineIpValue(newIp); + + c->condJump(toCompilerJumpOp(t, instruction), a, b, target); + } + goto branch; + + case if_icmpeq: + case if_icmpne: + case if_icmpgt: + case if_icmpge: + case if_icmplt: + case if_icmple: { + uint32_t offset = codeReadInt16(t, code, ip); + newIp = (ip - 3) + offset; + assertT(t, newIp < code->length()); + + if (newIp <= ip) { + compileSafePoint(t, c, frame); + } + + ir::Value* a = frame->pop(ir::Type::i4()); + ir::Value* b = frame->pop(ir::Type::i4()); + ir::Value* target = frame->machineIpValue(newIp); + + c->condJump(toCompilerJumpOp(t, instruction), a, b, target); + } + goto branch; + + case ifeq: + case ifne: + case ifgt: + case ifge: + case iflt: + case ifle: { + uint32_t offset = codeReadInt16(t, code, ip); + newIp = (ip - 3) + offset; + assertT(t, newIp < code->length()); + + ir::Value* target = frame->machineIpValue(newIp); + + if (newIp <= ip) { + compileSafePoint(t, c, frame); + } + + ir::Value* a = c->constant(0, ir::Type::i4()); + ir::Value* b = frame->pop(ir::Type::i4()); + + c->condJump(toCompilerJumpOp(t, instruction), a, b, target); + } + goto branch; + + case ifnull: + case ifnonnull: { + uint32_t offset = codeReadInt16(t, code, ip); + newIp = (ip - 3) + offset; + assertT(t, newIp < code->length()); + + if (newIp <= ip) { + compileSafePoint(t, c, frame); + } + + ir::Value* a = c->constant(0, ir::Type::object()); + ir::Value* b = frame->pop(ir::Type::object()); + ir::Value* target = frame->machineIpValue(newIp); + + c->condJump(toCompilerJumpOp(t, instruction), a, b, target); + } + goto branch; + + case iinc: { + uint8_t index = code->body()[ip++]; + int8_t count = code->body()[ip++]; + + storeLocal(context, + 1, + ir::Type::i4(), + c->binaryOp(lir::Add, + ir::Type::i4(), + c->constant(count, ir::Type::i4()), + loadLocal(context, 1, ir::Type::i4(), index)), + index); + } break; + + case iload: + frame->load(ir::Type::i4(), code->body()[ip++]); + break; + case fload: + frame->load(ir::Type::f4(), code->body()[ip++]); + break; + + case iload_0: + frame->load(ir::Type::i4(), 0); + break; + case fload_0: + frame->load(ir::Type::f4(), 0); + break; + + case iload_1: + frame->load(ir::Type::i4(), 1); + break; + case fload_1: + frame->load(ir::Type::f4(), 1); + break; + + case iload_2: + frame->load(ir::Type::i4(), 2); + break; + case fload_2: + frame->load(ir::Type::f4(), 2); + break; + + case iload_3: + frame->load(ir::Type::i4(), 3); + break; + case fload_3: + frame->load(ir::Type::f4(), 3); + break; + + case ineg: { + frame->push(ir::Type::i4(), + c->unaryOp(lir::Negate, frame->pop(ir::Type::i4()))); + } break; + + case instanceof: { + uint16_t index = codeReadInt16(t, code, ip); + + object reference + = singletonObject(t, context->method->code()->pool(), index - 1); + + PROTECT(t, reference); + + GcClass* class_ + = resolveClassInPool(t, context->method, index - 1, false); + + ir::Value* instance = frame->pop(ir::Type::object()); + + object argument; + Thunk thunk; + if (LIKELY(class_)) { + argument = class_; + thunk = instanceOf64Thunk; + } else { + argument = makePair(t, context->method, reference); + thunk = instanceOfFromReferenceThunk; + } + + frame->push( + ir::Type::i4(), + c->nativeCall( + c->constant(getThunk(t, thunk), ir::Type::iptr()), + 0, + frame->trace(0, 0), + ir::Type::i4(), + args(c->threadRegister(), frame->append(argument), instance))); + } break; + + case invokedynamic: { + context->leaf = false; + + uint16_t poolIndex = codeReadInt16(t, code, ip); + ip += 2; + + GcInvocation* invocation = cast( + t, + singletonObject(t, context->method->code()->pool(), poolIndex - 1)); + + PROTECT(t, invocation); + + invocation->setClass(t, context->method->class_()); + + BootContext* bc = context->bootContext; + if (bc) { + // When we're AOT-compiling an application, we can't handle + // invokedynamic in general, since it usually implies runtime + // code generation. However, Java 8 lambda expressions are a + // special case for which we can generate code ahead of time. + // + // The only tricky part about it is that the class synthesis + // code resides in LambdaMetaFactory, which means we need to + // call out to a separate Java VM to execute it (the VM we're + // currently executing in won't work because it only knows how + // to compile code for the target machine, which might not be + // the same as the host; plus we don't want to pollute the + // runtime heap image with stuff that's only needed at compile + // time). + + GcClass* c = context->method->class_(); + PROTECT(t, c); + + GcMethod* target + = c->addendum()->bootstrapLambdaTable() + ? cast( + t, + cast(t, c->addendum()->bootstrapLambdaTable()) + ->body()[invocation->bootstrap()]) + : nullptr; + PROTECT(t, target); + + if (target == nullptr) { + GcCharArray* bootstrapArray = cast( + t, + cast(t, c->addendum()->bootstrapMethodTable()) + ->body()[invocation->bootstrap()]); + PROTECT(t, bootstrapArray); + + if (isLambda(t, c->loader(), bootstrapArray, invocation)) { + if (bc->hostVM == 0) { + throwNew( + t, + GcVirtualMachineError::Type, + "lambda expression encountered, but host VM is not " + "available; use -hostvm option to bootimage-generator to " + "fix this"); + } + + JNIEnv* e; + if (bc->hostVM->vtable->AttachCurrentThread(bc->hostVM, &e, 0) + == 0) { + e->vtable->PushLocalFrame(e, 256); + + jclass lmfClass = e->vtable->FindClass( + e, "java/lang/invoke/LambdaMetafactory"); + jmethodID makeLambda + = e->vtable->GetStaticMethodID(e, + lmfClass, + "makeLambda", + "(Ljava/lang/String;" + "Ljava/lang/String;" + "Ljava/lang/String;" + "Ljava/lang/String;" + "Ljava/lang/String;" + "Ljava/lang/String;" + "I" + ")[B"); + + GcReference* reference = cast( + t, + singletonObject( + t, invocation->pool(), bootstrapArray->body()[2])); + int kind = reference->kind(); + + GcMethod* method + = cast(t, + resolve(t, + c->loader(), + invocation->pool(), + bootstrapArray->body()[2], + findMethodInClass, + GcNoSuchMethodError::Type)); + + jarray lambda = e->vtable->CallStaticObjectMethod( + e, + lmfClass, + makeLambda, + e->vtable->NewStringUTF( + e, + reinterpret_cast( + invocation->template_()->name()->body().begin())), + e->vtable->NewStringUTF( + e, + reinterpret_cast( + invocation->template_()->spec()->body().begin())), + e->vtable->NewStringUTF( + e, + reinterpret_cast( + cast( + t, + singletonObject(t, + invocation->pool(), + bootstrapArray->body()[1])) + ->body() + .begin())), + e->vtable->NewStringUTF( + e, + reinterpret_cast( + method->class_()->name()->body().begin())), + e->vtable->NewStringUTF(e, + reinterpret_cast( + method->name()->body().begin())), + e->vtable->NewStringUTF(e, + reinterpret_cast( + method->spec()->body().begin())), + kind); + + uint8_t* bytes = reinterpret_cast( + e->vtable->GetPrimitiveArrayCritical(e, lambda, 0)); + + GcClass* lambdaClass + = defineClass(t, + roots(t)->appLoader(), + bytes, + e->vtable->GetArrayLength(e, lambda)); + + bc->resolver->addClass( + t, lambdaClass, bytes, e->vtable->GetArrayLength(e, lambda)); + + e->vtable->ReleasePrimitiveArrayCritical(e, lambda, bytes, 0); + + e->vtable->PopLocalFrame(e, 0); + + THREAD_RUNTIME_ARRAY( + t, char, spec, invocation->template_()->spec()->length()); + memcpy(RUNTIME_ARRAY_BODY(spec), + invocation->template_()->spec()->body().begin(), + invocation->template_()->spec()->length()); + + target = resolveMethod( + t, lambdaClass, "make", RUNTIME_ARRAY_BODY(spec)); + + GcArray* table + = cast(t, c->addendum()->bootstrapLambdaTable()); + if (table == nullptr) { + table = makeArray( + t, + cast(t, c->addendum()->bootstrapMethodTable()) + ->length()); + c->addendum()->setBootstrapLambdaTable(t, table); + } + + table->setBodyElement(t, invocation->bootstrap(), target); + } else { + throwNew(t, + GcVirtualMachineError::Type, + "unable to attach to host VM"); + } + } else { + throwNew(t, + GcVirtualMachineError::Type, + "invokedynamic not supported for AOT-compiled code except " + "in the case of lambda expressions"); + } + } + + bool tailCall = isTailCall(t, code, ip, context->method, target); + compileDirectInvoke(t, frame, target, tailCall); + } else { + unsigned index = addDynamic(t, invocation); + + GcMethod* template_ = invocation->template_(); + unsigned returnCode = template_->returnCode(); + unsigned rSize = resultSize(t, returnCode); + unsigned parameterFootprint = template_->parameterFootprint(); + + // TODO: can we allow tailCalls in general? + // e.g. what happens if the call site is later bound to a method that + // can't be tail called? + // NOTE: calling isTailCall right now would cause an segfault, since + // invocation->template_()->class_() will be null. + // bool tailCall + // = isTailCall(t, code, ip, context->method, + // invocation->template_()); + bool tailCall = false; + + // todo: do we need to tell the compiler to add a load barrier + // here for VolatileCallSite instances? + + ir::Value* result + = c->stackCall(c->memory(c->memory(c->threadRegister(), + ir::Type::object(), + TARGET_THREAD_DYNAMICTABLE), + ir::Type::object(), + index * TargetBytesPerWord), + tailCall ? Compiler::TailJump : 0, + frame->trace(0, 0), + operandTypeForFieldCode(t, returnCode), + frame->peekMethodArguments(parameterFootprint)); + + frame->popFootprint(parameterFootprint); + + if (rSize) { + frame->pushReturnValue(returnCode, result); + } + } + } break; + + case invokeinterface: { + context->leaf = false; + + uint16_t index = codeReadInt16(t, code, ip); + ip += 2; + + object reference + = singletonObject(t, context->method->code()->pool(), index - 1); + + PROTECT(t, reference); + + GcMethod* target = resolveMethod(t, context->method, index - 1, false); + + object argument; + Thunk thunk; + unsigned parameterFootprint; + int returnCode; + bool tailCall; + if (LIKELY(target)) { + checkMethod(t, target, false); + + argument = target; + thunk = findInterfaceMethodFromInstanceThunk; + parameterFootprint = target->parameterFootprint(); + returnCode = target->returnCode(); + tailCall = isTailCall(t, code, ip, context->method, target); + } else { + GcReference* ref = cast(t, reference); + PROTECT(t, ref); + argument = makePair(t, context->method, reference); + thunk = findInterfaceMethodFromInstanceAndReferenceThunk; + parameterFootprint = methodReferenceParameterFootprint(t, ref, false); + returnCode = methodReferenceReturnCode(t, ref); + tailCall = isReferenceTailCall(t, code, ip, context->method, ref); + } + + unsigned rSize = resultSize(t, returnCode); + + ir::Value* result = c->stackCall( + c->nativeCall(c->constant(getThunk(t, thunk), ir::Type::iptr()), + 0, + frame->trace(0, 0), + ir::Type::iptr(), + args(c->threadRegister(), + frame->append(argument), + c->peek(1, parameterFootprint - 1))), + tailCall ? Compiler::TailJump : 0, + frame->trace(0, 0), + operandTypeForFieldCode(t, returnCode), + frame->peekMethodArguments(parameterFootprint)); + + frame->popFootprint(parameterFootprint); + + if (rSize) { + frame->pushReturnValue(returnCode, result); + } + } break; + + case invokespecial: { + context->leaf = false; + + uint16_t index = codeReadInt16(t, code, ip); + + object reference + = singletonObject(t, context->method->code()->pool(), index - 1); + + PROTECT(t, reference); + + GcMethod* target = resolveMethod(t, context->method, index - 1, false); + + if (LIKELY(target)) { + GcClass* class_ = context->method->class_(); + if (isSpecialMethod(t, target, class_)) { + target = findVirtualMethod(t, target, class_->super()); + } + + checkMethod(t, target, false); + + bool tailCall = isTailCall(t, code, ip, context->method, target); + + if (UNLIKELY(methodAbstract(t, target))) { + compileDirectAbstractInvoke( + t, frame, getMethodAddressThunk, target, tailCall); + } else { + compileDirectInvoke(t, frame, target, tailCall); + } + } else { + GcReference* ref = cast(t, reference); + PROTECT(t, ref); + compileDirectReferenceInvoke( + t, + frame, + findSpecialMethodFromReferenceThunk, + ref, + false, + isReferenceTailCall(t, code, ip, context->method, ref)); + } + } break; + + case invokestatic: { + context->leaf = false; + + uint16_t index = codeReadInt16(t, code, ip); + + object reference + = singletonObject(t, context->method->code()->pool(), index - 1); + + PROTECT(t, reference); + + GcMethod* target = resolveMethod(t, context->method, index - 1, false); + + if (LIKELY(target)) { + checkMethod(t, target, true); + + if (not intrinsic(t, frame, target)) { + bool tailCall = isTailCall(t, code, ip, context->method, target); + compileDirectInvoke(t, frame, target, tailCall); + } + } else { + GcReference* ref = cast(t, reference); + PROTECT(t, ref); + compileDirectReferenceInvoke( + t, + frame, + findStaticMethodFromReferenceThunk, + ref, + true, + isReferenceTailCall(t, code, ip, context->method, ref)); + } + } break; + + case invokevirtual: { + context->leaf = false; + + uint16_t index = codeReadInt16(t, code, ip); + + object reference + = singletonObject(t, context->method->code()->pool(), index - 1); + + PROTECT(t, reference); + + GcMethod* target = resolveMethod(t, context->method, index - 1, false); + + if (LIKELY(target)) { + checkMethod(t, target, false); + + if (not intrinsic(t, frame, target)) { + bool tailCall = isTailCall(t, code, ip, context->method, target); + + if (LIKELY(methodVirtual(t, target))) { + unsigned parameterFootprint = target->parameterFootprint(); + + unsigned offset = TargetClassVtable + + (target->offset() * TargetBytesPerWord); + + ir::Value* instance = c->peek(1, parameterFootprint - 1); + + frame->stackCall( + c->memory(c->binaryOp( + lir::And, + ir::Type::iptr(), + c->constant(TargetPointerMask, ir::Type::iptr()), + c->memory(instance, ir::Type::object())), + ir::Type::object(), + offset), + target, + tailCall ? Compiler::TailJump : 0, + frame->trace(0, 0)); + } else { + // OpenJDK generates invokevirtual calls to private methods + // (e.g. readObject and writeObject for serialization), so + // we must handle such cases here. + + compileDirectInvoke(t, frame, target, tailCall); + } + } + } else { + GcReference* ref = cast(t, reference); + PROTECT(t, reference); + PROTECT(t, ref); + + GcPair* pair = makePair(t, context->method, reference); + + compileReferenceInvoke( + frame, + c->nativeCall( + c->constant(getThunk(t, findVirtualMethodFromReferenceThunk), + ir::Type::iptr()), + 0, + frame->trace(0, 0), + ir::Type::iptr(), + args(c->threadRegister(), + frame->append(pair), + c->peek(1, + methodReferenceParameterFootprint(t, ref, false) + - 1))), + ref, + false, + isReferenceTailCall(t, code, ip, context->method, ref)); + } + } break; + + case irem: { + ir::Value* a = frame->pop(ir::Type::i4()); + ir::Value* b = frame->pop(ir::Type::i4()); + + if (inTryBlock(t, code, ip - 1)) { + c->saveLocals(); + frame->trace(0, 0); + } + + frame->push(ir::Type::i4(), + c->binaryOp(lir::Remainder, ir::Type::i4(), a, b)); + } break; + + case ireturn: { + handleExit(t, frame); + c->return_(frame->pop(ir::Type::i4())); + } + goto next; + + case freturn: { + handleExit(t, frame); + c->return_(frame->pop(ir::Type::f4())); + } + goto next; + + case istore: + frame->store(ir::Type::i4(), code->body()[ip++]); + break; + case fstore: + frame->store(ir::Type::f4(), code->body()[ip++]); + break; + + case istore_0: + frame->store(ir::Type::i4(), 0); + break; + case fstore_0: + frame->store(ir::Type::f4(), 0); + break; + + case istore_1: + frame->store(ir::Type::i4(), 1); + break; + case fstore_1: + frame->store(ir::Type::f4(), 1); + break; + + case istore_2: + frame->store(ir::Type::i4(), 2); + break; + case fstore_2: + frame->store(ir::Type::f4(), 2); + break; + + case istore_3: + frame->store(ir::Type::i4(), 3); + break; + case fstore_3: + frame->store(ir::Type::f4(), 3); + break; + + case jsr: + case jsr_w: { + uint32_t thisIp; + + if (instruction == jsr) { + uint32_t offset = codeReadInt16(t, code, ip); + thisIp = ip - 3; + newIp = thisIp + offset; + } else { + uint32_t offset = codeReadInt32(t, code, ip); + thisIp = ip - 5; + newIp = thisIp + offset; + } + + assertT(t, newIp < code->length()); + + frame->startSubroutine(newIp, ip); + + c->jmp(frame->machineIpValue(newIp)); + + ip = newIp; + } break; + + case l2d: { + frame->pushLarge(ir::Type::f8(), + c->i2f(ir::Type::f8(), frame->popLarge(ir::Type::i8()))); + } break; + + case l2f: { + frame->push(ir::Type::f4(), + c->i2f(ir::Type::f4(), frame->popLarge(ir::Type::i8()))); + } break; + + case l2i: + frame->push(ir::Type::i4(), + c->truncate(ir::Type::i4(), frame->popLarge(ir::Type::i8()))); + break; + + case ladd: + case land: + case lor: + case lsub: + case lxor: + case lmul: { + ir::Value* a = frame->popLarge(ir::Type::i8()); + ir::Value* b = frame->popLarge(ir::Type::i8()); + frame->pushLarge( + ir::Type::i8(), + c->binaryOp( + toCompilerBinaryOp(t, instruction), ir::Type::i8(), a, b)); + } break; + + case lcmp: { + ir::Value* a = frame->popLarge(ir::Type::i8()); + ir::Value* b = frame->popLarge(ir::Type::i8()); + + if (integerBranch(t, frame, code, ip, a, b, &newIp)) { + goto branch; + } else { + frame->push(ir::Type::i4(), + c->nativeCall(c->constant(getThunk(t, compareLongsThunk), + ir::Type::iptr()), + 0, + 0, + ir::Type::i4(), + args(nullptr, a, nullptr, b))); + } + } break; + + case lconst_0: + frame->pushLarge(ir::Type::i8(), c->constant(0, ir::Type::i8())); + break; + + case lconst_1: + frame->pushLarge(ir::Type::i8(), c->constant(1, ir::Type::i8())); + break; + + case ldc: + case ldc_w: { + uint16_t index; + + if (instruction == ldc) { + index = code->body()[ip++]; + } else { + index = codeReadInt16(t, code, ip); + } + + GcSingleton* pool = code->pool(); + + if (singletonIsObject(t, pool, index - 1)) { + object v = singletonObject(t, pool, index - 1); + + loadMemoryBarrier(); + + if (objectClass(t, v) == type(t, GcReference::Type)) { + GcReference* reference = cast(t, v); + PROTECT(t, reference); + + v = resolveClassInPool(t, context->method, index - 1, false); + + if (UNLIKELY(v == 0)) { + frame->push( + ir::Type::object(), + c->nativeCall( + c->constant(getThunk(t, getJClassFromReferenceThunk), + ir::Type::iptr()), + 0, + frame->trace(0, 0), + ir::Type::object(), + args(c->threadRegister(), + frame->append( + makePair(t, context->method, reference))))); + } + } + + if (v) { + if (objectClass(t, v) == type(t, GcClass::Type)) { + frame->push( + ir::Type::object(), + c->nativeCall(c->constant(getThunk(t, getJClass64Thunk), + ir::Type::iptr()), + 0, + frame->trace(0, 0), + ir::Type::object(), + args(c->threadRegister(), frame->append(v)))); + } else { + frame->push(ir::Type::object(), frame->append(v)); + } + } + } else { + ir::Type type = singletonBit(t, pool, poolSize(t, pool), index - 1) + ? ir::Type::f4() + : ir::Type::i4(); + frame->push(type, + c->constant(singletonValue(t, pool, index - 1), type)); + } + } break; + + case ldc2_w: { + uint16_t index = codeReadInt16(t, code, ip); + + GcSingleton* pool = code->pool(); + + uint64_t v; + memcpy(&v, &singletonValue(t, pool, index - 1), 8); + ir::Type type = singletonBit(t, pool, poolSize(t, pool), index - 1) + ? ir::Type::f8() + : ir::Type::i8(); + frame->pushLarge(type, c->constant(v, type)); + } break; + + case ldiv_: { + ir::Value* a = frame->popLarge(ir::Type::i8()); + ir::Value* b = frame->popLarge(ir::Type::i8()); + + if (inTryBlock(t, code, ip - 1)) { + c->saveLocals(); + frame->trace(0, 0); + } + + frame->pushLarge(ir::Type::i8(), + c->binaryOp(lir::Divide, ir::Type::i8(), a, b)); + } break; + + case lload: + frame->loadLarge(ir::Type::i8(), code->body()[ip++]); + break; + case dload: + frame->loadLarge(ir::Type::f8(), code->body()[ip++]); + break; + + case lload_0: + frame->loadLarge(ir::Type::i8(), 0); + break; + case dload_0: + frame->loadLarge(ir::Type::f8(), 0); + break; + + case lload_1: + frame->loadLarge(ir::Type::i8(), 1); + break; + case dload_1: + frame->loadLarge(ir::Type::f8(), 1); + break; + + case lload_2: + frame->loadLarge(ir::Type::i8(), 2); + break; + case dload_2: + frame->loadLarge(ir::Type::f8(), 2); + break; + + case lload_3: + frame->loadLarge(ir::Type::i8(), 3); + break; + case dload_3: + frame->loadLarge(ir::Type::f8(), 3); + break; + + case lneg: + frame->pushLarge( + ir::Type::i8(), + c->unaryOp(lir::Negate, frame->popLarge(ir::Type::i8()))); + break; + + case lookupswitch: { + int32_t base = ip - 1; + + ip = (ip + 3) & ~3; // pad to four byte boundary + + ir::Value* key = frame->pop(ir::Type::i4()); + + uint32_t defaultIp = base + codeReadInt32(t, code, ip); + assertT(t, defaultIp < code->length()); + + int32_t pairCount = codeReadInt32(t, code, ip); + + if (pairCount) { + ir::Value* default_ = frame->addressOperand( + frame->addressPromise(frame->machineIp(defaultIp))); + + avian::codegen::Promise* start = 0; + uint32_t* ipTable + = static_cast(stack.push(sizeof(uint32_t) * pairCount)); + for (int32_t i = 0; i < pairCount; ++i) { + unsigned index = ip + (i * 8); + int32_t key = codeReadInt32(t, code, index); + uint32_t newIp = base + codeReadInt32(t, code, index); + assertT(t, newIp < code->length()); + + ipTable[i] = newIp; + + avian::codegen::Promise* p = c->poolAppend(key); + if (i == 0) { + start = p; + } + c->poolAppendPromise(frame->addressPromise(frame->machineIp(newIp))); + } + assertT(t, start); + + ir::Value* address = c->nativeCall( + c->constant(getThunk(t, lookUpAddressThunk), ir::Type::iptr()), + 0, + 0, + ir::Type::iptr(), + args(key, + frame->absoluteAddressOperand(start), + c->constant(pairCount, ir::Type::i4()), + default_)); + + c->jmp(context->bootContext + ? c->binaryOp(lir::Add, + ir::Type::iptr(), + c->memory(c->threadRegister(), + ir::Type::iptr(), + TARGET_THREAD_CODEIMAGE), + address) + : address); + + new (stack.push(sizeof(SwitchState))) + SwitchState(c->saveState(), pairCount, defaultIp, 0, 0, 0, 0); + + goto switchloop; + } else { + // a switch statement with no cases, apparently + c->jmp(frame->machineIpValue(defaultIp)); + ip = defaultIp; + } + } break; + + case lrem: { + ir::Value* a = frame->popLarge(ir::Type::i8()); + ir::Value* b = frame->popLarge(ir::Type::i8()); + + if (inTryBlock(t, code, ip - 1)) { + c->saveLocals(); + frame->trace(0, 0); + } + + frame->pushLarge(ir::Type::i8(), + c->binaryOp(lir::Remainder, ir::Type::i8(), a, b)); + } break; + + case lreturn: { + handleExit(t, frame); + c->return_(frame->popLarge(ir::Type::i8())); + } + goto next; + + case dreturn: { + handleExit(t, frame); + c->return_(frame->popLarge(ir::Type::f8())); + } + goto next; + + case lshl: + case lshr: + case lushr: { + ir::Value* a = frame->pop(ir::Type::i4()); + ir::Value* b = frame->popLarge(ir::Type::i8()); + frame->pushLarge( + ir::Type::i8(), + c->binaryOp( + toCompilerBinaryOp(t, instruction), ir::Type::i8(), a, b)); + } break; + + case lstore: + frame->storeLarge(ir::Type::i8(), code->body()[ip++]); + break; + case dstore: + frame->storeLarge(ir::Type::f8(), code->body()[ip++]); + break; + + case lstore_0: + frame->storeLarge(ir::Type::i8(), 0); + break; + case dstore_0: + frame->storeLarge(ir::Type::f8(), 0); + break; + + case lstore_1: + frame->storeLarge(ir::Type::i8(), 1); + break; + case dstore_1: + frame->storeLarge(ir::Type::f8(), 1); + break; + + case lstore_2: + frame->storeLarge(ir::Type::i8(), 2); + break; + case dstore_2: + frame->storeLarge(ir::Type::f8(), 2); + break; + + case lstore_3: + frame->storeLarge(ir::Type::i8(), 3); + break; + case dstore_3: + frame->storeLarge(ir::Type::f8(), 3); + break; + + case monitorenter: { + ir::Value* target = frame->pop(ir::Type::object()); + c->nativeCall(c->constant(getThunk(t, acquireMonitorForObjectThunk), + ir::Type::iptr()), + 0, + frame->trace(0, 0), + ir::Type::void_(), + args(c->threadRegister(), target)); + } break; + + case monitorexit: { + ir::Value* target = frame->pop(ir::Type::object()); + c->nativeCall(c->constant(getThunk(t, releaseMonitorForObjectThunk), + ir::Type::iptr()), + 0, + frame->trace(0, 0), + ir::Type::void_(), + args(c->threadRegister(), target)); + } break; + + case multianewarray: { + uint16_t index = codeReadInt16(t, code, ip); + uint8_t dimensions = code->body()[ip++]; + + object reference + = singletonObject(t, context->method->code()->pool(), index - 1); + + PROTECT(t, reference); + + GcClass* class_ + = resolveClassInPool(t, context->method, index - 1, false); + + object argument; + Thunk thunk; + if (LIKELY(class_)) { + argument = class_; + thunk = makeMultidimensionalArrayThunk; + } else { + argument = makePair(t, context->method, reference); + thunk = makeMultidimensionalArrayFromReferenceThunk; + } + + unsigned offset + = localOffset(t, + localSize(t, context->method) + c->topOfStack(), + context->method) + t->arch->frameReturnAddressSize(); + + ir::Value* result + = c->nativeCall(c->constant(getThunk(t, thunk), ir::Type::iptr()), + 0, + frame->trace(0, 0), + ir::Type::object(), + args(c->threadRegister(), + frame->append(argument), + c->constant(dimensions, ir::Type::i4()), + c->constant(offset, ir::Type::i4()))); + + frame->popFootprint(dimensions); + frame->push(ir::Type::object(), result); + } break; + + case new_: { + uint16_t index = codeReadInt16(t, code, ip); + + object reference + = singletonObject(t, context->method->code()->pool(), index - 1); + + PROTECT(t, reference); + + GcClass* class_ + = resolveClassInPool(t, context->method, index - 1, false); + + object argument; + Thunk thunk; + if (LIKELY(class_)) { + argument = class_; + if (class_->vmFlags() & (WeakReferenceFlag | HasFinalizerFlag)) { + thunk = makeNewGeneral64Thunk; + } else { + thunk = makeNew64Thunk; + } + } else { + argument = makePair(t, context->method, reference); + thunk = makeNewFromReferenceThunk; + } + + frame->push( + ir::Type::object(), + c->nativeCall(c->constant(getThunk(t, thunk), ir::Type::iptr()), + 0, + frame->trace(0, 0), + ir::Type::object(), + args(c->threadRegister(), frame->append(argument)))); + } break; + + case newarray: { + uint8_t type = code->body()[ip++]; + + ir::Value* length = frame->pop(ir::Type::i4()); + + frame->push(ir::Type::object(), + c->nativeCall(c->constant(getThunk(t, makeBlankArrayThunk), + ir::Type::iptr()), + 0, + frame->trace(0, 0), + ir::Type::object(), + args(c->threadRegister(), + c->constant(type, ir::Type::i4()), + length))); + } break; + + case nop: + break; + + case pop_: + frame->popFootprint(1); + break; + + case pop2: + frame->popFootprint(2); + break; + + case putfield: + case putstatic: { + uint16_t index = codeReadInt16(t, code, ip); + + object reference + = singletonObject(t, context->method->code()->pool(), index - 1); + + PROTECT(t, reference); + + GcField* field = resolveField(t, context->method, index - 1, false); + + if (LIKELY(field)) { + int fieldCode = field->code(); + + object staticTable = 0; + + if (instruction == putstatic) { + checkField(t, field, true); + + if (classNeedsInit(t, field->class_())) { + PROTECT(t, field); + + c->nativeCall( + c->constant(getThunk(t, tryInitClassThunk), ir::Type::iptr()), + 0, + frame->trace(0, 0), + ir::Type::void_(), + args(c->threadRegister(), frame->append(field->class_()))); + } + + staticTable = field->class_()->staticTable(); + } else { + checkField(t, field, false); + + if (inTryBlock(t, code, ip - 3)) { + c->saveLocals(); + frame->trace(0, 0); + } + } + + if (field->flags() & ACC_VOLATILE) { + if (TargetBytesPerWord == 4 + and (fieldCode == DoubleField or fieldCode == LongField)) { + PROTECT(t, field); + + c->nativeCall(c->constant(getThunk(t, acquireMonitorForObjectThunk), + ir::Type::iptr()), + 0, + frame->trace(0, 0), + ir::Type::void_(), + args(c->threadRegister(), frame->append(field))); + } else { + c->nullaryOp(lir::StoreStoreBarrier); + } + } + + ir::Value* value = popField(t, frame, fieldCode); + + ir::Value* table; + + if (instruction == putstatic) { + PROTECT(t, field); + + table = frame->append(staticTable); + } else { + table = frame->pop(ir::Type::object()); + } + + switch (fieldCode) { + case ByteField: + case BooleanField: + c->store( + value, + c->memory( + table, ir::Type::i1(), targetFieldOffset(context, field))); + break; + + case CharField: + case ShortField: + c->store( + value, + c->memory( + table, ir::Type::i2(), targetFieldOffset(context, field))); + break; + + case FloatField: + c->store( + value, + c->memory( + table, ir::Type::f4(), targetFieldOffset(context, field))); + break; + + case IntField: + c->store( + value, + c->memory( + table, ir::Type::i4(), targetFieldOffset(context, field))); + break; + + case DoubleField: + c->store( + value, + c->memory( + table, ir::Type::f8(), targetFieldOffset(context, field))); + break; + + case LongField: + c->store( + value, + c->memory( + table, ir::Type::i8(), targetFieldOffset(context, field))); + break; + + case ObjectField: + if (instruction == putfield) { + c->nativeCall( + c->constant(getThunk(t, setMaybeNullThunk), ir::Type::iptr()), + 0, + frame->trace(0, 0), + ir::Type::void_(), + args(c->threadRegister(), + table, + c->constant(targetFieldOffset(context, field), + ir::Type::i4()), + value)); + } else { + c->nativeCall( + c->constant(getThunk(t, setObjectThunk), ir::Type::iptr()), + 0, + 0, + ir::Type::void_(), + args(c->threadRegister(), + table, + c->constant(targetFieldOffset(context, field), + ir::Type::i4()), + value)); + } + break; + + default: + abort(t); + } + + if (field->flags() & ACC_VOLATILE) { + if (TargetBytesPerWord == 4 + and (fieldCode == DoubleField or fieldCode == LongField)) { + c->nativeCall(c->constant(getThunk(t, releaseMonitorForObjectThunk), + ir::Type::iptr()), + 0, + frame->trace(0, 0), + ir::Type::void_(), + args(c->threadRegister(), frame->append(field))); + } else { + c->nullaryOp(lir::StoreLoadBarrier); + } + } + } else { + GcReference* ref = cast(t, reference); + PROTECT(t, ref); + int fieldCode = vm::fieldCode(t, ref->spec()->body()[0]); + + ir::Value* value = popField(t, frame, fieldCode); + ir::Type rType = operandTypeForFieldCode(t, fieldCode); + + GcPair* pair = makePair(t, context->method, reference); + + switch (fieldCode) { + case ByteField: + case BooleanField: + case CharField: + case ShortField: + case FloatField: + case IntField: { + if (instruction == putstatic) { + c->nativeCall( + c->constant(getThunk(t, setStaticFieldValueFromReferenceThunk), + ir::Type::iptr()), + 0, + frame->trace(0, 0), + rType, + args(c->threadRegister(), frame->append(pair), value)); + } else { + ir::Value* instance = frame->pop(ir::Type::object()); + + c->nativeCall( + c->constant(getThunk(t, setFieldValueFromReferenceThunk), + ir::Type::iptr()), + 0, + frame->trace(0, 0), + rType, + args( + c->threadRegister(), frame->append(pair), instance, value)); + } + } break; + + case DoubleField: + case LongField: { + if (instruction == putstatic) { + c->nativeCall( + c->constant( + getThunk(t, setStaticLongFieldValueFromReferenceThunk), + ir::Type::iptr()), + 0, + frame->trace(0, 0), + rType, + args(c->threadRegister(), frame->append(pair), nullptr, value)); + } else { + ir::Value* instance = frame->pop(ir::Type::object()); + + c->nativeCall( + c->constant(getThunk(t, setLongFieldValueFromReferenceThunk), + ir::Type::iptr()), + 0, + frame->trace(0, 0), + rType, + args(c->threadRegister(), + frame->append(pair), + instance, + nullptr, + value)); + } + } break; + + case ObjectField: { + if (instruction == putstatic) { + c->nativeCall( + c->constant( + getThunk(t, setStaticObjectFieldValueFromReferenceThunk), + ir::Type::iptr()), + 0, + frame->trace(0, 0), + rType, + args(c->threadRegister(), frame->append(pair), value)); + } else { + ir::Value* instance = frame->pop(ir::Type::object()); + + c->nativeCall( + c->constant(getThunk(t, setObjectFieldValueFromReferenceThunk), + ir::Type::iptr()), + 0, + frame->trace(0, 0), + rType, + args( + c->threadRegister(), frame->append(pair), instance, value)); + } + } break; + + default: + abort(t); + } + } + } break; + + case ret: { + unsigned index = code->body()[ip]; + + unsigned returnAddress = frame->endSubroutine(index); + c->jmp(frame->machineIpValue(returnAddress)); + ip = returnAddress; + } break; + + case return_: + if (needsReturnBarrier(t, context->method)) { + c->nullaryOp(lir::StoreStoreBarrier); + } + + handleExit(t, frame); + c->return_(); + goto next; + + case sipush: + frame->push(ir::Type::i4(), + c->constant(static_cast(codeReadInt16(t, code, ip)), + ir::Type::i4())); + break; + + case swap: + frame->swap(); + break; + + case tableswitch: { + int32_t base = ip - 1; + + ip = (ip + 3) & ~3; // pad to four byte boundary + + uint32_t defaultIp = base + codeReadInt32(t, code, ip); + assertT(t, defaultIp < code->length()); + + int32_t bottom = codeReadInt32(t, code, ip); + int32_t top = codeReadInt32(t, code, ip); + + avian::codegen::Promise* start = 0; + unsigned count = top - bottom + 1; + uint32_t* ipTable + = static_cast(stack.push(sizeof(uint32_t) * count)); + for (int32_t i = 0; i < top - bottom + 1; ++i) { + unsigned index = ip + (i * 4); + uint32_t newIp = base + codeReadInt32(t, code, index); + assertT(t, newIp < code->length()); + + ipTable[i] = newIp; + + avian::codegen::Promise* p = c->poolAppendPromise( + frame->addressPromise(frame->machineIp(newIp))); + if (i == 0) { + start = p; + } + } + assertT(t, start); + + ir::Value* key = frame->pop(ir::Type::i4()); + + c->condJump(lir::JumpIfLess, + c->constant(bottom, ir::Type::i4()), + key, + frame->machineIpValue(defaultIp)); + + c->save(ir::Type::i4(), key); + + new (stack.push(sizeof(SwitchState))) SwitchState( + c->saveState(), count, defaultIp, key, start, bottom, top); + + stack.pushValue(Untable0); + ip = defaultIp; + } + goto start; + + case wide: { + switch (code->body()[ip++]) { + case aload: { + frame->load(ir::Type::object(), codeReadInt16(t, code, ip)); + } break; + + case astore: { + frame->store(ir::Type::object(), codeReadInt16(t, code, ip)); + } break; + + case iinc: { + uint16_t index = codeReadInt16(t, code, ip); + int16_t count = codeReadInt16(t, code, ip); + + storeLocal(context, + 1, + ir::Type::i4(), + c->binaryOp(lir::Add, + ir::Type::i4(), + c->constant(count, ir::Type::i4()), + loadLocal(context, 1, ir::Type::i4(), index)), + index); + } break; + + case iload: { + frame->load(ir::Type::i4(), codeReadInt16(t, code, ip)); + } break; + + case istore: { + frame->store(ir::Type::i4(), codeReadInt16(t, code, ip)); + } break; + + case lload: { + frame->loadLarge(ir::Type::i8(), codeReadInt16(t, code, ip)); + } break; + + case lstore: { + frame->storeLarge(ir::Type::i8(), codeReadInt16(t, code, ip)); + } break; + + case ret: { + unsigned index = codeReadInt16(t, code, ip); + + unsigned returnAddress = frame->endSubroutine(index); + c->jmp(frame->machineIpValue(returnAddress)); + ip = returnAddress; + } break; + + default: + abort(t); + } + } break; + + default: + abort(t); + } + } + +next: + frame->dispose(); + frame = 0; + stack.pop(sizeof(Frame)); + stack.pop(stackSize * sizeof(ir::Type)); + switch (stack.popValue()) { + case Return: + return; + + case Unbranch: + if (DebugInstructions) { + fprintf(stderr, "Unbranch\n"); + } + ip = stack.popValue(); + c->restoreState(reinterpret_cast(stack.popValue())); + frame = static_cast(stack.peek(sizeof(Frame))); + goto loop; + + case Untable0: { + if (DebugInstructions) { + fprintf(stderr, "Untable0\n"); + } + SwitchState* s = static_cast(stack.peek(sizeof(SwitchState))); + + frame = s->frame(); + + c->restoreState(s->state); + + c->condJump(lir::JumpIfGreater, + c->constant(s->top, ir::Type::i4()), + s->key, + frame->machineIpValue(s->defaultIp)); + + c->save(ir::Type::i4(), s->key); + ip = s->defaultIp; + stack.pushValue(Untable1); + } + goto start; + + case Untable1: { + if (DebugInstructions) { + fprintf(stderr, "Untable1\n"); + } + SwitchState* s = static_cast(stack.peek(sizeof(SwitchState))); + + frame = s->frame(); + + c->restoreState(s->state); + + ir::Value* normalizedKey + = (s->bottom + ? c->binaryOp(lir::Subtract, + ir::Type::i4(), + c->constant(s->bottom, ir::Type::i4()), + s->key) + : s->key); + + ir::Value* entry = c->memory(frame->absoluteAddressOperand(s->start), + ir::Type::iptr(), + 0, + normalizedKey); + + c->jmp(c->load(ir::ExtendMode::Signed, + context->bootContext + ? c->binaryOp(lir::Add, + ir::Type::iptr(), + c->memory(c->threadRegister(), + ir::Type::iptr(), + TARGET_THREAD_CODEIMAGE), + entry) + : entry, + ir::Type::iptr())); + + s->state = c->saveState(); + } + goto switchloop; + + case Unswitch: { + if (DebugInstructions) { + fprintf(stderr, "Unswitch\n"); + } + SwitchState* s = static_cast(stack.peek(sizeof(SwitchState))); + + frame = s->frame(); + + c->restoreState( + static_cast(stack.peek(sizeof(SwitchState)))->state); + } + goto switchloop; + + case Unsubroutine: { + if (DebugInstructions) { + fprintf(stderr, "Unsubroutine\n"); + } + ip = stack.popValue(); + unsigned start = stack.popValue(); + frame = reinterpret_cast(stack.peek(sizeof(Frame))); + frame->endSubroutine(start); + } + goto loop; + + default: + abort(t); + } + +switchloop : { + SwitchState* s = static_cast(stack.peek(sizeof(SwitchState))); + + if (s->index < s->count) { + ip = s->ipTable()[s->index++]; + stack.pushValue(Unswitch); + goto start; + } else { + ip = s->defaultIp; + unsigned count = s->count * 4; + stack.pop(sizeof(SwitchState)); + stack.pop(count); + frame = reinterpret_cast(stack.peek(sizeof(Frame))); + goto loop; + } +} + +branch: + stack.pushValue(reinterpret_cast(c->saveState())); + stack.pushValue(ip); + stack.pushValue(Unbranch); + ip = newIp; + goto start; +} + +int resolveIpForwards(Context* context, int start, int end) +{ + if (start < 0) { + start = 0; + } + + while (start < end and context->visitTable[start] == 0) { + ++start; + } + + if (start >= end) { + return -1; + } else { + return start; + } +} + +int resolveIpBackwards(Context* context, int start, int end) +{ + if (start >= static_cast(context->method->code()->length() + * (context->subroutineCount + 1))) { + start = context->method->code()->length(); + } else { + while (start >= end and context->visitTable[start] == 0) { + --start; + } + } + + if (start < end) { + return -1; + } else { + return start; + } +} + +GcIntArray* truncateIntArray(Thread* t, GcIntArray* array, unsigned length) +{ + expect(t, array->length() > length); + + PROTECT(t, array); + + GcIntArray* newArray = makeIntArray(t, length); + if (length) { + memcpy(newArray->body().begin(), array->body().begin(), length * 4); + } + + return newArray; +} + +GcArray* truncateArray(Thread* t, GcArray* array, unsigned length) +{ + expect(t, array->length() > length); + + PROTECT(t, array); + + GcArray* newArray = makeArray(t, length); + if (length) { + for (size_t i = 0; i < length; i++) { + newArray->setBodyElement(t, i, array->body()[i]); + } + } + + return newArray; +} + +GcLineNumberTable* truncateLineNumberTable(Thread* t, + GcLineNumberTable* table, + unsigned length) +{ + expect(t, table->length() > length); + + PROTECT(t, table); + + GcLineNumberTable* newTable = makeLineNumberTable(t, length); + if (length) { + memcpy(newTable->body().begin(), + table->body().begin(), + length * sizeof(uint64_t)); + } + + return newTable; +} + +GcArray* translateExceptionHandlerTable(MyThread* t, + Context* context, + intptr_t start, + intptr_t end) +{ + avian::codegen::Compiler* c = context->compiler; + + GcExceptionHandlerTable* oldTable = cast( + t, context->method->code()->exceptionHandlerTable()); + + if (oldTable) { + PROTECT(t, oldTable); + + unsigned length = oldTable->length(); + + GcIntArray* newIndex + = makeIntArray(t, length * (context->subroutineCount + 1) * 3); + PROTECT(t, newIndex); + + GcArray* newTable + = makeArray(t, length * (context->subroutineCount + 1) + 1); + PROTECT(t, newTable); + + unsigned ni = 0; + for (unsigned subI = 0; subI <= context->subroutineCount; ++subI) { + unsigned duplicatedBaseIp = subI * context->method->code()->length(); + + for (unsigned oi = 0; oi < length; ++oi) { + uint64_t oldHandler = oldTable->body()[oi]; + + int handlerStart = resolveIpForwards( + context, + duplicatedBaseIp + exceptionHandlerStart(oldHandler), + duplicatedBaseIp + exceptionHandlerEnd(oldHandler)); + + if (LIKELY(handlerStart >= 0)) { + assertT(t, + handlerStart + < static_cast(context->method->code()->length() + * (context->subroutineCount + 1))); + + int handlerEnd = resolveIpBackwards( + context, + duplicatedBaseIp + exceptionHandlerEnd(oldHandler), + duplicatedBaseIp + exceptionHandlerStart(oldHandler)); + + assertT(t, handlerEnd >= 0); + assertT( + t, + handlerEnd <= static_cast(context->method->code()->length() + * (context->subroutineCount + 1))); + + newIndex->body()[ni * 3] = c->machineIp(handlerStart)->value() + - start; + + newIndex->body()[(ni * 3) + 1] + = (handlerEnd + == static_cast(context->method->code()->length()) + ? end + : c->machineIp(handlerEnd)->value()) - start; + + newIndex->body()[(ni * 3) + 2] + = c->machineIp(exceptionHandlerIp(oldHandler))->value() - start; + + object type; + if (exceptionHandlerCatchType(oldHandler)) { + type = resolveClassInPool( + t, context->method, exceptionHandlerCatchType(oldHandler) - 1); + } else { + type = 0; + } + + newTable->setBodyElement(t, ni + 1, type); + + ++ni; + } + } + } + + if (UNLIKELY(ni < length)) { + newIndex = truncateIntArray(t, newIndex, ni * 3); + newTable = truncateArray(t, newTable, ni + 1); + } + + newTable->setBodyElement(t, 0, newIndex); + + return newTable; + } else { + return 0; + } +} + +GcLineNumberTable* translateLineNumberTable(MyThread* t, + Context* context, + intptr_t start) +{ + GcLineNumberTable* oldTable = context->method->code()->lineNumberTable(); + if (oldTable) { + PROTECT(t, oldTable); + + unsigned length = oldTable->length(); + GcLineNumberTable* newTable = makeLineNumberTable(t, length); + unsigned ni = 0; + for (unsigned oi = 0; oi < length; ++oi) { + uint64_t oldLine = oldTable->body()[oi]; + + int ip = resolveIpForwards( + context, + lineNumberIp(oldLine), + oi + 1 < length ? lineNumberIp(oldTable->body()[oi + 1]) - 1 + : lineNumberIp(oldLine) + 1); + + if (LIKELY(ip >= 0)) { + newTable->body()[ni++] + = lineNumber(context->compiler->machineIp(ip)->value() - start, + lineNumberLine(oldLine)); + } + } + + if (UNLIKELY(ni < length)) { + newTable = truncateLineNumberTable(t, newTable, ni); + } + + return newTable; + } else { + return 0; + } +} + +void printSet(uintptr_t* m, unsigned limit) +{ + if (limit) { + for (unsigned i = 0; i < 32; ++i) { + if ((*m >> i) & 1) { + fprintf(stderr, "1"); + } else { + fprintf(stderr, "_"); + } + } + } +} + +void calculateTryCatchRoots(Context* context, + uintptr_t* roots, + unsigned mapSize, + unsigned start, + unsigned end) +{ + memset(roots, 0xFF, mapSize * BytesPerWord); + + if (DebugFrameMaps) { + fprintf(stderr, "calculate try/catch roots from %d to %d\n", start, end); + } + + for (TraceElement* te = context->traceLog; te; te = te->next) { + if (te->ip >= start and te->ip < end) { + uintptr_t* traceRoots = 0; + traceRoots = te->map; + te->watch = true; + + if (traceRoots) { + if (DebugFrameMaps) { + fprintf(stderr, " use roots at ip %3d: ", te->ip); + printSet(traceRoots, mapSize); + fprintf(stderr, "\n"); + } + + for (unsigned wi = 0; wi < mapSize; ++wi) { + roots[wi] &= traceRoots[wi]; + } + } else { + if (DebugFrameMaps) { + fprintf(stderr, " skip roots at ip %3d\n", te->ip); + } + } + } + } + + if (DebugFrameMaps) { + fprintf(stderr, "result roots : "); + printSet(roots, mapSize); + fprintf(stderr, "\n"); + } +} + +unsigned calculateFrameMaps(MyThread* t, + Context* context, + uintptr_t* originalRoots, + unsigned eventIndex, + uintptr_t* resultRoots) +{ + // for each instruction with more than one predecessor, and for each + // stack position, determine if there exists a path to that + // instruction such that there is not an object pointer left at that + // stack position (i.e. it is uninitialized or contains primitive + // data). + + unsigned mapSize = frameMapSizeInWords(t, context->method); + + THREAD_RUNTIME_ARRAY(t, uintptr_t, roots, mapSize); + if (originalRoots) { + memcpy(RUNTIME_ARRAY_BODY(roots), originalRoots, mapSize * BytesPerWord); + } else { + memset(RUNTIME_ARRAY_BODY(roots), 0, mapSize * BytesPerWord); + } + + int32_t ip = -1; + + // invariant: for each stack position, roots contains a zero at that + // position if there exists some path to the current instruction + // such that there is definitely not an object pointer at that + // position. Otherwise, roots contains a one at that position, + // meaning either all known paths result in an object pointer at + // that position, or the contents of that position are as yet + // unknown. + + unsigned length = context->eventLog.length(); + while (eventIndex < length) { + Event e = static_cast(context->eventLog.get(eventIndex++)); + switch (e) { + case PushContextEvent: { + eventIndex = calculateFrameMaps(t, + context, + RUNTIME_ARRAY_BODY(roots), + eventIndex, /*subroutinePath,*/ + resultRoots); + } break; + + case PopContextEvent: + goto exit; + + case IpEvent: { + ip = context->eventLog.get2(eventIndex); + eventIndex += 2; + + if (DebugFrameMaps) { + fprintf(stderr, " roots at ip %3d: ", ip); + printSet(RUNTIME_ARRAY_BODY(roots), mapSize); + fprintf(stderr, "\n"); + } + + assertT(context->thread, ip * mapSize <= context->rootTable.count); + uintptr_t* tableRoots = context->rootTable.begin() + (ip * mapSize); + + if (context->visitTable[ip] > 1) { + for (unsigned wi = 0; wi < mapSize; ++wi) { + uintptr_t newRoots = tableRoots[wi] & RUNTIME_ARRAY_BODY(roots)[wi]; + + if ((eventIndex == length + or context->eventLog.get(eventIndex) == PopContextEvent) + and newRoots != tableRoots[wi]) { + if (DebugFrameMaps) { + fprintf(stderr, "dirty roots!\n"); + } + + context->dirtyRoots = true; + } + + tableRoots[wi] = newRoots; + RUNTIME_ARRAY_BODY(roots)[wi] &= tableRoots[wi]; + } + + if (DebugFrameMaps) { + fprintf(stderr, " table roots at ip %3d: ", ip); + printSet(tableRoots, mapSize); + fprintf(stderr, "\n"); + } + } else { + memcpy(tableRoots, RUNTIME_ARRAY_BODY(roots), mapSize * BytesPerWord); + } + } break; + + case MarkEvent: { + unsigned i = context->eventLog.get2(eventIndex); + eventIndex += 2; + + markBit(RUNTIME_ARRAY_BODY(roots), i); + } break; + + case ClearEvent: { + unsigned i = context->eventLog.get2(eventIndex); + eventIndex += 2; + + clearBit(RUNTIME_ARRAY_BODY(roots), i); + } break; + + case PushExceptionHandlerEvent: { + unsigned start = context->eventLog.get2(eventIndex); + eventIndex += 2; + unsigned end = context->eventLog.get2(eventIndex); + eventIndex += 2; + + calculateTryCatchRoots( + context, RUNTIME_ARRAY_BODY(roots), mapSize, start, end); + + eventIndex = calculateFrameMaps( + t, context, RUNTIME_ARRAY_BODY(roots), eventIndex, 0); + } break; + + case TraceEvent: { + TraceElement* te; + context->eventLog.get(eventIndex, &te, BytesPerWord); + if (DebugFrameMaps) { + fprintf(stderr, " trace roots at ip %3d: ", ip); + printSet(RUNTIME_ARRAY_BODY(roots), mapSize); + fprintf(stderr, "\n"); + } + + uintptr_t* map; + bool watch; + map = te->map; + watch = te->watch; + + for (unsigned wi = 0; wi < mapSize; ++wi) { + uintptr_t v = RUNTIME_ARRAY_BODY(roots)[wi]; + + if (watch and map[wi] != v) { + if (DebugFrameMaps) { + fprintf(stderr, "dirty roots due to trace watch!\n"); + } + + context->dirtyRoots = true; + } + + map[wi] = v; + } + + eventIndex += BytesPerWord; + } break; + + default: + abort(t); + } + } + +exit: + if (resultRoots and ip != -1) { + if (DebugFrameMaps) { + fprintf(stderr, "result roots at ip %3d: ", ip); + printSet(RUNTIME_ARRAY_BODY(roots), mapSize); + fprintf(stderr, "\n"); + } + + memcpy(resultRoots, RUNTIME_ARRAY_BODY(roots), mapSize * BytesPerWord); + } + + return eventIndex; +} + +int compareTraceElementPointers(const void* va, const void* vb) +{ + TraceElement* a = *static_cast(va); + TraceElement* b = *static_cast(vb); + if (a->address->value() > b->address->value()) { + return 1; + } else if (a->address->value() < b->address->value()) { + return -1; + } else { + return 0; + } +} + +uint8_t* finish(MyThread* t, + FixedAllocator* allocator, + avian::codegen::Assembler* a, + const char* name, + unsigned length) +{ + uint8_t* start + = static_cast(allocator->allocate(length, TargetBytesPerWord)); + + a->setDestination(start); + a->write(); + + logCompile(t, start, length, 0, name, 0); + + return start; +} + +void setBit(int32_t* dst, unsigned index) +{ + dst[index / 32] |= static_cast(1) << (index % 32); +} + +void clearBit(int32_t* dst, unsigned index) +{ + dst[index / 32] &= ~(static_cast(1) << (index % 32)); +} + +void copyFrameMap(int32_t* dst, + uintptr_t* src, + unsigned mapSizeInBits, + unsigned offset, + TraceElement* p) +{ + if (DebugFrameMaps) { + fprintf(stderr, " orig roots at ip %3d: ", p->ip); + printSet(src, ceilingDivide(mapSizeInBits, BitsPerWord)); + fprintf(stderr, "\n"); + + fprintf(stderr, " final roots at ip %3d: ", p->ip); + } + + for (unsigned j = 0; j < p->argumentIndex; ++j) { + if (getBit(src, j)) { + if (DebugFrameMaps) { + fprintf(stderr, "1"); + } + setBit(dst, offset + j); + } else { + if (DebugFrameMaps) { + fprintf(stderr, "_"); + } + clearBit(dst, offset + j); + } + } + + if (DebugFrameMaps) { + fprintf(stderr, "\n"); + } +} + +class FrameMapTableHeader { + public: + FrameMapTableHeader(unsigned indexCount) : indexCount(indexCount) + { + } + + unsigned indexCount; +}; + +class FrameMapTableIndexElement { + public: + FrameMapTableIndexElement(int offset, unsigned base, unsigned path) + : offset(offset), base(base), path(path) + { + } + + int offset; + unsigned base; + unsigned path; +}; + +class FrameMapTablePath { + public: + FrameMapTablePath(unsigned stackIndex, unsigned elementCount, unsigned next) + : stackIndex(stackIndex), elementCount(elementCount), next(next) + { + } + + unsigned stackIndex; + unsigned elementCount; + unsigned next; + int32_t elements[0]; +}; + +GcIntArray* makeSimpleFrameMapTable(MyThread* t, + Context* context, + uint8_t* start, + TraceElement** elements, + unsigned elementCount) +{ + unsigned mapSize = frameMapSizeInBits(t, context->method); + GcIntArray* table = makeIntArray( + t, elementCount + ceilingDivide(elementCount * mapSize, 32)); + + assertT(t, + table->length() + == elementCount + simpleFrameMapTableSize(t, context->method, table)); + + for (unsigned i = 0; i < elementCount; ++i) { + TraceElement* p = elements[i]; + + table->body()[i] = static_cast(p->address->value()) + - reinterpret_cast(start); + + assertT( + t, + elementCount + ceilingDivide((i + 1) * mapSize, 32) <= table->length()); + + if (mapSize) { + copyFrameMap( + &table->body()[elementCount], p->map, mapSize, i * mapSize, p); + } + } + + return table; +} + +void insertCallNode(MyThread* t, GcCallNode* node); + +void finish(MyThread* t, FixedAllocator* allocator, Context* context) +{ + avian::codegen::Compiler* c = context->compiler; + + if (false) { + logCompile( + t, + 0, + 0, + reinterpret_cast( + context->method->class_()->name()->body().begin()), + reinterpret_cast(context->method->name()->body().begin()), + reinterpret_cast(context->method->spec()->body().begin())); + } + + // for debugging: + if (false + and ::strcmp(reinterpret_cast( + context->method->class_()->name()->body().begin()), + "java/lang/System") == 0 + and ::strcmp(reinterpret_cast( + context->method->name()->body().begin()), + "") == 0) { + trap(); + } + + // todo: this is a CPU-intensive operation, so consider doing it + // earlier before we've acquired the global class lock to improve + // parallelism (the downside being that it may end up being a waste + // of cycles if another thread compiles the same method in parallel, + // which might be mitigated by fine-grained, per-method locking): + c->compile(context->leaf ? 0 : stackOverflowThunk(t), + TARGET_THREAD_STACKLIMIT); + + // we must acquire the class lock here at the latest + + unsigned codeSize = c->resolve(allocator->memory.begin() + allocator->offset); + + unsigned total = pad(codeSize, TargetBytesPerWord) + + pad(c->poolSize(), TargetBytesPerWord); + + target_uintptr_t* code = static_cast( + allocator->allocate(total, TargetBytesPerWord)); + uint8_t* start = reinterpret_cast(code); + + context->executableAllocator = allocator; + context->executableStart = code; + context->executableSize = total; + + if (context->objectPool) { + object pool = allocate3( + t, + allocator, + Machine::ImmortalAllocation, + GcArray::FixedSize + ((context->objectPoolCount + 1) * BytesPerWord), + true); + + context->executableSize = (allocator->memory.begin() + allocator->offset) + - static_cast(context->executableStart); + + initArray( + t, reinterpret_cast(pool), context->objectPoolCount + 1); + mark(t, pool, 0); + + setField(t, pool, ArrayBody, compileRoots(t)->objectPools()); + compileRoots(t)->setObjectPools(t, pool); + + unsigned i = 1; + for (PoolElement* p = context->objectPool; p; p = p->next) { + unsigned offset = ArrayBody + ((i++) * BytesPerWord); + + p->address = reinterpret_cast(pool) + offset; + + setField(t, pool, offset, p->target); + } + } + + c->write(); + + BootContext* bc = context->bootContext; + if (bc) { + for (avian::codegen::DelayedPromise* p = bc->addresses; + p != bc->addressSentinal; + p = p->next) { + p->basis = new (bc->zone) + avian::codegen::ResolvedPromise(p->basis->value()); + } + } + + { + GcArray* newExceptionHandlerTable = translateExceptionHandlerTable( + t, + context, + reinterpret_cast(start), + reinterpret_cast(start) + codeSize); + + PROTECT(t, newExceptionHandlerTable); + + GcLineNumberTable* newLineNumberTable = translateLineNumberTable( + t, context, reinterpret_cast(start)); + + GcCode* code = context->method->code(); + + code = makeCode(t, + 0, + 0, + newExceptionHandlerTable, + newLineNumberTable, + reinterpret_cast(start), + codeSize, + code->maxStack(), + code->maxLocals(), + 0); + + context->method->setCode(t, code); + } + + if (context->traceLogCount) { + THREAD_RUNTIME_ARRAY(t, TraceElement*, elements, context->traceLogCount); + unsigned index = 0; + // unsigned pathFootprint = 0; + // unsigned mapCount = 0; + for (TraceElement* p = context->traceLog; p; p = p->next) { + assertT(t, index < context->traceLogCount); + + if (p->address) { + RUNTIME_ARRAY_BODY(elements)[index++] = p; + + if (p->target) { + insertCallNode( + t, makeCallNode(t, p->address->value(), p->target, p->flags, 0)); + } + } + } + + qsort(RUNTIME_ARRAY_BODY(elements), + index, + sizeof(TraceElement*), + compareTraceElementPointers); + + GcIntArray* map = makeSimpleFrameMapTable( + t, context, start, RUNTIME_ARRAY_BODY(elements), index); + + context->method->code()->setStackMap(t, map); + } + + logCompile( + t, + start, + codeSize, + reinterpret_cast( + context->method->class_()->name()->body().begin()), + reinterpret_cast(context->method->name()->body().begin()), + reinterpret_cast(context->method->spec()->body().begin())); + + // for debugging: + if (false + and ::strcmp(reinterpret_cast( + context->method->class_()->name()->body().begin()), + "java/lang/System") == 0 + and ::strcmp(reinterpret_cast( + context->method->name()->body().begin()), + "") == 0) { + trap(); + } + syncInstructionCache(start, codeSize); +} + +void compile(MyThread* t, Context* context) +{ + avian::codegen::Compiler* c = context->compiler; + + if (false) { + fprintf(stderr, + "compiling %s.%s%s\n", + context->method->class_()->name()->body().begin(), + context->method->name()->body().begin(), + context->method->spec()->body().begin()); + } + + unsigned footprint = context->method->parameterFootprint(); + unsigned locals = localSize(t, context->method); + c->init(context->method->code()->length(), + footprint, + locals, + alignedFrameSize(t, context->method)); + + ir::Type* stackMap = (ir::Type*)malloc(sizeof(ir::Type) + * context->method->code()->maxStack()); + Frame frame(context, stackMap); + + unsigned index = context->method->parameterFootprint(); + if ((context->method->flags() & ACC_STATIC) == 0) { + frame.set(--index, ir::Type::object()); + c->initLocal(index, ir::Type::object()); + } + + for (MethodSpecIterator it(t, + reinterpret_cast( + context->method->spec()->body().begin())); + it.hasNext();) { + switch (*it.next()) { + case 'L': + case '[': + frame.set(--index, ir::Type::object()); + c->initLocal(index, ir::Type::object()); + break; + + case 'J': + frame.set(--index, ir::Type::i8()); + frame.set(--index, ir::Type::i8()); + c->initLocal(index, ir::Type::i8()); + break; + + case 'D': + frame.set(--index, ir::Type::f8()); + frame.set(--index, ir::Type::f8()); + c->initLocal(index, ir::Type::f8()); + break; + + case 'F': + frame.set(--index, ir::Type::i4()); + c->initLocal(index, ir::Type::f4()); + break; + + default: + frame.set(--index, ir::Type::i4()); + c->initLocal(index, ir::Type::i4()); + break; + } + } + + handleEntrance(t, &frame); + + Compiler::State* state = c->saveState(); + + compile(t, &frame, 0); + + context->dirtyRoots = false; + unsigned eventIndex = calculateFrameMaps(t, context, 0, 0, 0); + + GcExceptionHandlerTable* eht = cast( + t, context->method->code()->exceptionHandlerTable()); + if (eht) { + PROTECT(t, eht); + + unsigned visitCount = eht->length(); + + THREAD_RUNTIME_ARRAY(t, bool, visited, visitCount); + memset(RUNTIME_ARRAY_BODY(visited), 0, visitCount * sizeof(bool)); + + bool progress = true; + while (progress) { + progress = false; + + for (unsigned subI = 0; subI <= context->subroutineCount; ++subI) { + unsigned duplicatedBaseIp = subI * context->method->code()->length(); + + for (unsigned i = 0; i < eht->length(); ++i) { + uint64_t eh = eht->body()[i]; + int start + = resolveIpForwards(context, + duplicatedBaseIp + exceptionHandlerStart(eh), + duplicatedBaseIp + exceptionHandlerEnd(eh)); + + if ((not RUNTIME_ARRAY_BODY(visited)[i]) and start >= 0 + and context->visitTable[start]) { + RUNTIME_ARRAY_BODY(visited)[i] = true; + progress = true; + + c->restoreState(state); + + ir::Type* stackMap2 = (ir::Type*)malloc( + sizeof(ir::Type) * context->method->code()->maxStack()); + Frame frame2(&frame, stackMap2); + + unsigned end = duplicatedBaseIp + exceptionHandlerEnd(eh); + if (exceptionHandlerIp(eh) >= static_cast(start) + and exceptionHandlerIp(eh) < end) { + end = duplicatedBaseIp + exceptionHandlerIp(eh); + } + + context->eventLog.append(PushExceptionHandlerEvent); + context->eventLog.append2(start); + context->eventLog.append2(end); + + for (unsigned i = 1; i < context->method->code()->maxStack(); ++i) { + frame2.set(localSize(t, context->method) + i, ir::Type::i4()); + } + + compile(t, &frame2, exceptionHandlerIp(eh), start); + + context->eventLog.append(PopContextEvent); + + eventIndex = calculateFrameMaps(t, context, 0, eventIndex, 0); + free(stackMap2); + } + } + } + } + } + + while (context->dirtyRoots) { + context->dirtyRoots = false; + calculateFrameMaps(t, context, 0, 0, 0); + } + free(stackMap); +} +#endif // not AVIAN_AOT_ONLY + +void updateCall(MyThread* t, + avian::codegen::lir::UnaryOperation op, + void* returnAddress, + void* target) +{ + t->arch->updateCall(op, returnAddress, target); +} + +void* compileMethod2(MyThread* t, void* ip); + +uint64_t compileMethod(MyThread* t) +{ + void* ip; + if (t->tailAddress) { + ip = t->tailAddress; + t->tailAddress = 0; + } else { + ip = getIp(t); + } + + return reinterpret_cast(compileMethod2(t, ip)); +} + +void* compileVirtualMethod2(MyThread* t, GcClass* class_, unsigned index) +{ + // If class_ has BootstrapFlag set, that means its vtable is not yet + // available. However, we must set t->trace->targetMethod to an + // appropriate method to ensure we can accurately scan the stack for + // GC roots. We find such a method by looking for a superclass with + // a vtable and using it instead: + + GcClass* c = class_; + while (c->vmFlags() & BootstrapFlag) { + c = c->super(); + } + t->trace->targetMethod + = cast(t, cast(t, c->virtualTable())->body()[index]); + + THREAD_RESOURCE0(t, static_cast(t)->trace->targetMethod = 0;); + + PROTECT(t, class_); + + GcMethod* target = resolveTarget(t, class_, index); + PROTECT(t, target); + + compile(t, codeAllocator(t), 0, target); + + void* address = reinterpret_cast(methodAddress(t, target)); + if (target->flags() & ACC_NATIVE) { + t->trace->nativeMethod = target; + } else { + class_->vtable()[target->offset()] = address; + } + return address; +} + +uint64_t compileVirtualMethod(MyThread* t) +{ + GcClass* class_ = objectClass(t, static_cast(t->virtualCallTarget)); + t->virtualCallTarget = 0; + + unsigned index = t->virtualCallIndex; + t->virtualCallIndex = 0; + + return reinterpret_cast(compileVirtualMethod2(t, class_, index)); +} + +void* linkDynamicMethod2(MyThread* t, unsigned index) +{ + GcInvocation* invocation + = cast(t, roots(t)->invocations()->body()[index]); + + GcCallSite* site = invocation->site(); + + loadMemoryBarrier(); + + if (site == 0) { + t->trace->targetMethod = invocation->template_(); + + THREAD_RESOURCE0(t, static_cast(t)->trace->targetMethod = 0;); + + PROTECT(t, invocation); + + site = resolveDynamic(t, invocation); + PROTECT(t, site); + + compile(t, codeAllocator(t), 0, site->target()->method()); + + ACQUIRE(t, t->m->classLock); + + if (invocation->site() == 0) { + void* address + = reinterpret_cast(methodAddress(t, site->target()->method())); + + if ((site->target()->method()->flags() & ACC_NATIVE) == 0) { + t->dynamicTable[index] = address; + } + } + + storeStoreMemoryBarrier(); + + invocation->setSite(t, site); + site->setInvocation(t, invocation); + } + + GcMethod* target = invocation->site()->target()->method(); + + if (target->flags() & ACC_NATIVE) { + t->trace->nativeMethod = target; + } + + return reinterpret_cast(methodAddress(t, target)); +} + +uint64_t linkDynamicMethod(MyThread* t) +{ + unsigned index = t->virtualCallIndex; + t->virtualCallIndex = 0; + + return reinterpret_cast(linkDynamicMethod2(t, index)); +} + +uint64_t invokeNativeFast(MyThread* t, GcMethod* method, void* function) +{ + FastNativeFunction f; + memcpy(&f, &function, sizeof(void*)); + return f(t, + method, + static_cast(t->stack) + t->arch->frameFooterSize() + + t->arch->frameReturnAddressSize()); +} + +uint64_t invokeNativeSlow(MyThread* t, GcMethod* method, void* function) +{ + PROTECT(t, method); + + unsigned footprint = method->parameterFootprint() + 1; + if (method->flags() & ACC_STATIC) { + ++footprint; + } + unsigned count = method->parameterCount() + 2; + + THREAD_RUNTIME_ARRAY(t, uintptr_t, args, footprint); + unsigned argOffset = 0; + THREAD_RUNTIME_ARRAY(t, uint8_t, types, count); + unsigned typeOffset = 0; + + RUNTIME_ARRAY_BODY(args)[argOffset++] = reinterpret_cast(t); + RUNTIME_ARRAY_BODY(types)[typeOffset++] = POINTER_TYPE; + + uintptr_t* sp = static_cast(t->stack) + t->arch->frameFooterSize() + + t->arch->frameReturnAddressSize(); + + GcJclass* jclass = 0; + PROTECT(t, jclass); + + if (method->flags() & ACC_STATIC) { + jclass = getJClass(t, method->class_()); + RUNTIME_ARRAY_BODY(args)[argOffset++] + = reinterpret_cast(&jclass); + } else { + RUNTIME_ARRAY_BODY(args)[argOffset++] = reinterpret_cast(sp++); + } + RUNTIME_ARRAY_BODY(types)[typeOffset++] = POINTER_TYPE; + + MethodSpecIterator it( + t, reinterpret_cast(method->spec()->body().begin())); + + while (it.hasNext()) { + unsigned type = RUNTIME_ARRAY_BODY(types)[typeOffset++] + = fieldType(t, fieldCode(t, *it.next())); + + switch (type) { + case INT8_TYPE: + case INT16_TYPE: + case INT32_TYPE: + case FLOAT_TYPE: + RUNTIME_ARRAY_BODY(args)[argOffset++] = *(sp++); + break; + + case INT64_TYPE: + case DOUBLE_TYPE: { + memcpy(RUNTIME_ARRAY_BODY(args) + argOffset, sp, 8); + argOffset += (8 / BytesPerWord); + sp += 2; + } break; + + case POINTER_TYPE: { + if (*sp) { + RUNTIME_ARRAY_BODY(args)[argOffset++] = reinterpret_cast(sp); + } else { + RUNTIME_ARRAY_BODY(args)[argOffset++] = 0; + } + ++sp; + } break; + + default: + abort(t); + } + } + + unsigned returnCode = method->returnCode(); + unsigned returnType = fieldType(t, returnCode); + uint64_t result; + + if (DebugNatives) { + fprintf(stderr, + "invoke native method %s.%s\n", + method->class_()->name()->body().begin(), + method->name()->body().begin()); + } + + if (method->flags() & ACC_SYNCHRONIZED) { + if (method->flags() & ACC_STATIC) { + acquire(t, getJClass(t, method->class_())); + } else { + acquire(t, *reinterpret_cast(RUNTIME_ARRAY_BODY(args)[1])); + } + } + + Reference* reference = t->reference; + + { + ENTER(t, Thread::IdleState); + + bool noThrow = t->checkpoint->noThrow; + t->checkpoint->noThrow = true; + THREAD_RESOURCE(t, bool, noThrow, t->checkpoint->noThrow = noThrow); + + result = vm::dynamicCall(function, + RUNTIME_ARRAY_BODY(args), + RUNTIME_ARRAY_BODY(types), + count, + footprint * BytesPerWord, + returnType); + } + + if (method->flags() & ACC_SYNCHRONIZED) { + if (method->flags() & ACC_STATIC) { + release(t, getJClass(t, method->class_())); + } else { + release(t, *reinterpret_cast(RUNTIME_ARRAY_BODY(args)[1])); + } + } + + if (DebugNatives) { + fprintf(stderr, + "return from native method %s.%s\n", + method->class_()->name()->body().begin(), + method->name()->body().begin()); + } + + if (UNLIKELY(t->exception)) { + GcThrowable* exception = t->exception; + t->exception = 0; + vm::throw_(t, exception); + } + + switch (returnCode) { + case ByteField: + case BooleanField: + result = static_cast(result); + break; + + case CharField: + result = static_cast(result); + break; + + case ShortField: + result = static_cast(result); + break; + + case FloatField: + case IntField: + result = static_cast(result); + break; + + case LongField: + case DoubleField: + break; + + case ObjectField: + result = static_cast(result) + ? *reinterpret_cast(static_cast(result)) + : 0; + break; + + case VoidField: + result = 0; + break; + + default: + abort(t); + } + + while (t->reference != reference) { + dispose(t, t->reference); + } + + return result; +} + +uint64_t invokeNative2(MyThread* t, GcMethod* method) +{ + GcNative* native = getMethodRuntimeData(t, method)->native(); + if (native->fast()) { + return invokeNativeFast(t, method, native->function()); + } else { + return invokeNativeSlow(t, method, native->function()); + } +} + +uint64_t invokeNative(MyThread* t) +{ + if (t->trace->nativeMethod == 0) { + void* ip; + if (t->tailAddress) { + ip = t->tailAddress; + t->tailAddress = 0; + } else { + ip = getIp(t); + } + + GcCallNode* node = findCallNode(t, ip); + GcMethod* target = node->target(); + if (node->flags() & TraceElement::VirtualCall) { + target = resolveTarget(t, t->stack, target); + } + t->trace->nativeMethod = target; + } + + assertT(t, t->tailAddress == 0); + + uint64_t result = 0; + + t->trace->targetMethod = t->trace->nativeMethod; + + t->m->classpath->resolveNative(t, t->trace->nativeMethod); + + result = invokeNative2(t, t->trace->nativeMethod); + + unsigned parameterFootprint = t->trace->targetMethod->parameterFootprint(); + + uintptr_t* stack = static_cast(t->stack); + + if (avian::codegen::TailCalls + and t->arch->argumentFootprint(parameterFootprint) + > t->arch->stackAlignmentInWords()) { + stack += t->arch->argumentFootprint(parameterFootprint) + - t->arch->stackAlignmentInWords(); + } + + stack += t->arch->frameReturnAddressSize(); + + t->trace->targetMethod = 0; + t->trace->nativeMethod = 0; + + t->newStack = stack; + + return result; +} + +void findFrameMapInSimpleTable(MyThread* t, + GcMethod* method, + GcIntArray* table, + int32_t offset, + int32_t** map, + unsigned* start) +{ + unsigned tableSize = simpleFrameMapTableSize(t, method, table); + unsigned indexSize = table->length() - tableSize; + + *map = &table->body()[indexSize]; + + unsigned bottom = 0; + unsigned top = indexSize; + for (unsigned span = top - bottom; span; span = top - bottom) { + unsigned middle = bottom + (span / 2); + int32_t v = table->body()[middle]; + + if (offset == v) { + *start = frameMapSizeInBits(t, method) * middle; + return; + } else if (offset < v) { + top = middle; + } else { + bottom = middle + 1; + } + } + + abort(t); +} + +void findFrameMap(MyThread* t, + void* stack UNUSED, + GcMethod* method, + int32_t offset, + int32_t** map, + unsigned* start) +{ + findFrameMapInSimpleTable( + t, method, method->code()->stackMap(), offset, map, start); +} + +void visitStackAndLocals(MyThread* t, + Heap::Visitor* v, + void* frame, + GcMethod* method, + void* ip) +{ + unsigned count = frameMapSizeInBits(t, method); + + if (count) { + void* stack = stackForFrame(t, frame, method); + + int32_t* map; + unsigned offset; + findFrameMap( + t, + stack, + method, + difference(ip, reinterpret_cast(methodAddress(t, method))), + &map, + &offset); + + for (unsigned i = 0; i < count; ++i) { + int j = offset + i; + if (map[j / 32] & (static_cast(1) << (j % 32))) { + v->visit(localObject(t, stack, method, i)); + } + } + } +} + +void visitArgument(MyThread* t, Heap::Visitor* v, void* stack, unsigned index) +{ + v->visit(static_cast(stack) + index + + t->arch->frameReturnAddressSize() + t->arch->frameFooterSize()); +} + +void visitArguments(MyThread* t, + Heap::Visitor* v, + void* stack, + GcMethod* method) +{ + unsigned index = 0; + + if ((method->flags() & ACC_STATIC) == 0) { + visitArgument(t, v, stack, index++); + } + + for (MethodSpecIterator it( + t, reinterpret_cast(method->spec()->body().begin())); + it.hasNext();) { + switch (*it.next()) { + case 'L': + case '[': + visitArgument(t, v, stack, index++); + break; + + case 'J': + case 'D': + index += 2; + break; + + default: + ++index; + break; + } + } +} + +void visitStack(MyThread* t, Heap::Visitor* v) +{ + void* ip = getIp(t); + void* stack = t->stack; + + MyThread::CallTrace* trace = t->trace; + GcMethod* targetMethod = (trace ? trace->targetMethod : 0); + GcMethod* target = targetMethod; + bool mostRecent = true; + + while (stack) { + if (targetMethod) { + visitArguments(t, v, stack, targetMethod); + targetMethod = 0; + } + + GcMethod* method = methodForIp(t, ip); + if (method) { + PROTECT(t, method); + + void* nextIp = ip; + nextFrame(t, &nextIp, &stack, method, target, mostRecent); + + visitStackAndLocals(t, v, stack, method, ip); + + ip = nextIp; + + target = method; + } else if (trace) { + stack = trace->stack; + ip = trace->ip; + trace = trace->next; + + if (trace) { + targetMethod = trace->targetMethod; + target = targetMethod; + } else { + target = 0; + } + } else { + break; + } + + mostRecent = false; + } +} + +void walkContinuationBody(MyThread* t, + Heap::Walker* w, + GcContinuation* c, + int start) +{ + const int BodyOffset = ContinuationBody / BytesPerWord; + + GcMethod* method = t->m->heap->follow(c->method()); + int count = frameMapSizeInBits(t, method); + + if (count) { + int stack = BodyOffset + (c->framePointerOffset() / BytesPerWord) + - t->arch->framePointerOffset() + - stackOffsetFromFrame(t, method); + + int first = stack + localOffsetFromStack(t, count - 1, method); + if (start > first) { + count -= start - first; + } + + int32_t* map; + unsigned offset; + findFrameMap(t, + reinterpret_cast(c) + stack, + method, + difference(c->address(), + reinterpret_cast(methodAddress(t, method))), + &map, + &offset); + + for (int i = count - 1; i >= 0; --i) { + int j = offset + i; + if (map[j / 32] & (static_cast(1) << (j % 32))) { + if (not w->visit(stack + localOffsetFromStack(t, i, method))) { + return; + } + } + } + } +} + +void callContinuation(MyThread* t, + GcContinuation* continuation, + object result, + GcThrowable* exception, + void* ip, + void* stack) +{ + assertT(t, t->exception == 0); + + if (exception) { + t->exception = exception; + + MyThread::TraceContext c(t, ip, stack, continuation, t->trace); + + void* frame; + findUnwindTarget(t, &ip, &frame, &stack, &continuation); + } + + t->trace->nativeMethod = 0; + t->trace->targetMethod = 0; + + popResources(t); + + transition(t, ip, stack, continuation, t->trace); + + vmJump(ip, 0, stack, t, reinterpret_cast(result), 0); +} + +int8_t* returnSpec(MyThread* t, GcMethod* method) +{ + int8_t* s = method->spec()->body().begin(); + while (*s and *s != ')') + ++s; + expect(t, *s == ')'); + return s + 1; +} + +GcClass* returnClass(MyThread* t, GcMethod* method) +{ + PROTECT(t, method); + + int8_t* spec = returnSpec(t, method); + unsigned length = strlen(reinterpret_cast(spec)); + GcByteArray* name; + if (*spec == '[') { + name = makeByteArray(t, length + 1); + memcpy(name->body().begin(), spec, length); + } else { + assertT(t, *spec == 'L'); + assertT(t, spec[length - 1] == ';'); + name = makeByteArray(t, length - 1); + memcpy(name->body().begin(), spec + 1, length - 2); + } + + return resolveClass(t, method->class_()->loader(), name); +} + +bool compatibleReturnType(MyThread* t, GcMethod* oldMethod, GcMethod* newMethod) +{ + if (oldMethod == newMethod) { + return true; + } else if (oldMethod->returnCode() == newMethod->returnCode()) { + if (oldMethod->returnCode() == ObjectField) { + PROTECT(t, newMethod); + + GcClass* oldClass = returnClass(t, oldMethod); + PROTECT(t, oldClass); + + GcClass* newClass = returnClass(t, newMethod); + + return isAssignableFrom(t, oldClass, newClass); + } else { + return true; + } + } else { + return oldMethod->returnCode() == VoidField; + } +} + +void jumpAndInvoke(MyThread* t, GcMethod* method, void* stack, ...) +{ + t->trace->targetMethod = 0; + + if (method->flags() & ACC_NATIVE) { + t->trace->nativeMethod = method; + } else { + t->trace->nativeMethod = 0; + } + + unsigned argumentCount = method->parameterFootprint(); + THREAD_RUNTIME_ARRAY(t, uintptr_t, arguments, argumentCount); + va_list a; + va_start(a, stack); + for (unsigned i = 0; i < argumentCount; ++i) { + RUNTIME_ARRAY_BODY(arguments)[i] = va_arg(a, uintptr_t); + } + va_end(a); + + assertT(t, t->exception == 0); + + popResources(t); + + vmJumpAndInvoke( + t, + reinterpret_cast(methodAddress(t, method)), + stack, + argumentCount * BytesPerWord, + RUNTIME_ARRAY_BODY(arguments), + (t->arch->alignFrameSize(t->arch->argumentFootprint(argumentCount)) + + t->arch->frameReturnAddressSize()) * BytesPerWord); +} + +void callContinuation(MyThread* t, + GcContinuation* continuation, + object result, + GcThrowable* exception) +{ + enum { Call, Unwind, Rewind } action; + + GcContinuation* nextContinuation = 0; + + if (t->continuation == 0 + or t->continuation->context() != continuation->context()) { + PROTECT(t, continuation); + PROTECT(t, result); + PROTECT(t, exception); + + if (compatibleReturnType( + t, t->trace->originalMethod, continuation->context()->method())) { + GcContinuationContext* oldContext; + GcContinuationContext* unwindContext; + + if (t->continuation) { + oldContext = t->continuation->context(); + unwindContext = oldContext; + } else { + oldContext = 0; + unwindContext = 0; + } + + GcContinuationContext* rewindContext = 0; + + for (GcContinuationContext* newContext = continuation->context(); + newContext; + newContext = newContext->next()) { + if (newContext == oldContext) { + unwindContext = 0; + break; + } else { + rewindContext = newContext; + } + } + + if (unwindContext and unwindContext->continuation()) { + nextContinuation + = cast(t, unwindContext->continuation()); + result = makeUnwindResult(t, continuation, result, exception); + action = Unwind; + } else if (rewindContext and rewindContext->continuation()) { + nextContinuation + = cast(t, rewindContext->continuation()); + action = Rewind; + + if (compileRoots(t)->rewindMethod() == 0) { + PROTECT(t, nextContinuation); + + GcMethod* method = resolveMethod( + t, + roots(t)->bootLoader(), + "avian/Continuations", + "rewind", + "(Ljava/lang/Runnable;Lavian/Callback;Ljava/lang/Object;" + "Ljava/lang/Throwable;)V"); + + PROTECT(t, method); + + compile(t, local::codeAllocator(t), 0, method); + + compileRoots(t)->setRewindMethod(t, method); + } + } else { + action = Call; + } + } else { + throwNew(t, GcIncompatibleContinuationException::Type); + } + } else { + action = Call; + } + + void* ip; + void* frame; + void* stack; + GcContinuation* threadContinuation; + findUnwindTarget(t, &ip, &frame, &stack, &threadContinuation); + + switch (action) { + case Call: { + callContinuation(t, continuation, result, exception, ip, stack); + } break; + + case Unwind: { + callContinuation(t, nextContinuation, result, 0, ip, stack); + } break; + + case Rewind: { + transition(t, 0, 0, nextContinuation, t->trace); + + jumpAndInvoke(t, + compileRoots(t)->rewindMethod(), + stack, + nextContinuation->context()->before(), + continuation, + result, + exception); + } break; + + default: + abort(t); + } +} + +void callWithCurrentContinuation(MyThread* t, object receiver) +{ + GcMethod* method = 0; + void* ip = 0; + void* stack = 0; + + { + PROTECT(t, receiver); + + if (compileRoots(t)->receiveMethod() == 0) { + GcMethod* m = resolveMethod(t, + roots(t)->bootLoader(), + "avian/Function", + "call", + "(Ljava/lang/Object;)Ljava/lang/Object;"); + + if (m) { + compileRoots(t)->setReceiveMethod(t, m); + + GcClass* continuationClass = type(t, GcContinuation::Type); + + if (continuationClass->vmFlags() & BootstrapFlag) { + resolveSystemClass( + t, roots(t)->bootLoader(), continuationClass->name()); + } + } + } + + method = findInterfaceMethod( + t, compileRoots(t)->receiveMethod(), objectClass(t, receiver)); + PROTECT(t, method); + + compile(t, local::codeAllocator(t), 0, method); + + t->continuation = makeCurrentContinuation(t, &ip, &stack); + } + + jumpAndInvoke(t, method, stack, receiver, t->continuation); +} + +void dynamicWind(MyThread* t, object before, object thunk, object after) +{ + void* ip = 0; + void* stack = 0; + + { + PROTECT(t, before); + PROTECT(t, thunk); + PROTECT(t, after); + + if (compileRoots(t)->windMethod() == 0) { + GcMethod* method = resolveMethod( + t, + roots(t)->bootLoader(), + "avian/Continuations", + "wind", + "(Ljava/lang/Runnable;Ljava/util/concurrent/Callable;" + "Ljava/lang/Runnable;)Lavian/Continuations$UnwindResult;"); + + if (method) { + compileRoots(t)->setWindMethod(t, method); + compile(t, local::codeAllocator(t), 0, method); + } + } + + t->continuation = makeCurrentContinuation(t, &ip, &stack); + + GcContinuationContext* newContext + = makeContinuationContext(t, + t->continuation->context(), + before, + after, + t->continuation, + t->trace->originalMethod); + + t->continuation->setContext(t, newContext); + } + + jumpAndInvoke(t, compileRoots(t)->windMethod(), stack, before, thunk, after); +} + +class ArgumentList { + public: + ArgumentList(Thread* t, + uintptr_t* array, + unsigned size, + bool* objectMask, + object this_, + const char* spec, + bool indirectObjects, + va_list arguments) + : t(static_cast(t)), + array(array), + objectMask(objectMask), + size(size), + position(0), + protector(this) + { + if (this_) { + addObject(this_); + } + + for (MethodSpecIterator it(t, spec); it.hasNext();) { + switch (*it.next()) { + case 'L': + case '[': + if (indirectObjects) { + object* v = va_arg(arguments, object*); + addObject(v ? *v : 0); + } else { + addObject(va_arg(arguments, object)); + } + break; + + case 'J': + addLong(va_arg(arguments, uint64_t)); + break; + + case 'D': + addLong(doubleToBits(va_arg(arguments, double))); + break; + + case 'F': + addInt(floatToBits(va_arg(arguments, double))); + break; + + default: + addInt(va_arg(arguments, uint32_t)); + break; + } + } + } + + ArgumentList(Thread* t, + uintptr_t* array, + unsigned size, + bool* objectMask, + object this_, + const char* spec, + const jvalue* arguments) + : t(static_cast(t)), + array(array), + objectMask(objectMask), + size(size), + position(0), + protector(this) + { + if (this_) { + addObject(this_); + } + + unsigned index = 0; + for (MethodSpecIterator it(t, spec); it.hasNext();) { + switch (*it.next()) { + case 'L': + case '[': { + object* v = arguments[index++].l; + addObject(v ? *v : 0); + } break; + + case 'J': + addLong(arguments[index++].j); + break; + + case 'D': + addLong(doubleToBits(arguments[index++].d)); + break; + + case 'F': + addInt(floatToBits(arguments[index++].f)); + break; + + default: + addInt(arguments[index++].i); + break; + } + } + } + + ArgumentList(Thread* t, + uintptr_t* array, + unsigned size, + bool* objectMask, + object this_, + const char* spec, + object arguments) + : t(static_cast(t)), + array(array), + objectMask(objectMask), + size(size), + position(0), + protector(this) + { + if (this_) { + addObject(this_); + } + + unsigned index = 0; + for (MethodSpecIterator it(t, spec); it.hasNext();) { + switch (*it.next()) { + case 'L': + case '[': + addObject(objectArrayBody(t, arguments, index++)); + break; + + case 'J': + case 'D': + addLong( + fieldAtOffset(objectArrayBody(t, arguments, index++), 8)); + break; + + default: + addInt(fieldAtOffset(objectArrayBody(t, arguments, index++), + BytesPerWord)); + break; + } + } + } + + void addObject(object v) + { + assertT(t, position < size); + + array[position] = reinterpret_cast(v); + objectMask[position] = true; + ++position; + } + + void addInt(uintptr_t v) + { + assertT(t, position < size); + + array[position] = v; + objectMask[position] = false; + ++position; + } + + void addLong(uint64_t v) + { + assertT(t, position < size - 1); + + memcpy(array + position, &v, 8); + + objectMask[position] = false; + objectMask[position + 1] = false; + + position += 2; + } + + MyThread* t; + uintptr_t* array; + bool* objectMask; + unsigned size; + unsigned position; + + class MyProtector : public Thread::Protector { + public: + MyProtector(ArgumentList* list) : Protector(list->t), list(list) + { + } + + virtual void visit(Heap::Visitor* v) + { + for (unsigned i = 0; i < list->position; ++i) { + if (list->objectMask[i]) { + v->visit(reinterpret_cast(list->array + i)); + } + } + } + + ArgumentList* list; + } protector; +}; + +object invoke(Thread* thread, GcMethod* method, ArgumentList* arguments) +{ + MyThread* t = static_cast(thread); + + if (false) { + PROTECT(t, method); + + compile( + t, + local::codeAllocator(static_cast(t)), + 0, + resolveMethod( + t, roots(t)->appLoader(), "foo/ClassName", "methodName", "()V")); + } + + uintptr_t stackLimit = t->stackLimit; + uintptr_t stackPosition = reinterpret_cast(&t); + if (stackLimit == 0) { + t->stackLimit = stackPosition - t->m->stackSizeInBytes; + } else if (stackPosition < stackLimit) { + throwNew(t, GcStackOverflowError::Type); + } + + THREAD_RESOURCE(t, + uintptr_t, + stackLimit, + static_cast(t)->stackLimit = stackLimit); + + unsigned returnCode = method->returnCode(); + unsigned returnType = fieldType(t, returnCode); + + uint64_t result; + + { + MyThread::CallTrace trace(t, method); + + MyCheckpoint checkpoint(t); + + assertT(t, arguments->position == arguments->size); + + result = vmInvoke( + t, + reinterpret_cast(methodAddress(t, method)), + arguments->array, + arguments->position * BytesPerWord, + t->arch->alignFrameSize(t->arch->argumentFootprint(arguments->position)) + * BytesPerWord, + returnType); + } + + if (t->exception) { + if (UNLIKELY(t->getFlags() & Thread::UseBackupHeapFlag)) { + collect(t, Heap::MinorCollection); + } + + GcThrowable* exception = t->exception; + t->exception = 0; + vm::throw_(t, exception); + } + + object r; + switch (returnCode) { + case ByteField: + case BooleanField: + case CharField: + case ShortField: + case FloatField: + case IntField: + r = makeInt(t, result); + break; + + case LongField: + case DoubleField: + r = makeLong(t, result); + break; + + case ObjectField: + r = reinterpret_cast(result); + break; + + case VoidField: + r = 0; + break; + + default: + abort(t); + } + + return r; +} + +class SignalHandler : public SignalRegistrar::Handler { + public: + typedef GcThrowable* (GcRoots::*ExceptionGetter)(); + SignalHandler(Gc::Type type, ExceptionGetter exc, unsigned fixedSize) + : m(0), type(type), exc(exc), fixedSize(fixedSize) + { + } + + void setException(MyThread* t) { + if (ensure(t, pad(fixedSize) + traceSize(t))) { + t->setFlag(Thread::TracingFlag); + t->exception = makeThrowable(t, type); + t->clearFlag(Thread::TracingFlag); + } else { + // not enough memory available for a new exception and stack + // trace -- use a preallocated instance instead + t->exception = (vm::roots(t)->*exc)(); + } + } + + virtual bool handleSignal(void** ip, + void** frame, + void** stack, + void** thread) + { + MyThread* t = static_cast(m->localThread->get()); + if (t and t->state == Thread::ActiveState) { + if (t->getFlags() & Thread::TryNativeFlag) { + setException(t); + + popResources(t); + + GcContinuation* continuation; + findUnwindTarget(t, ip, frame, stack, &continuation); + + t->trace->targetMethod = 0; + t->trace->nativeMethod = 0; + + transition(t, *ip, *stack, continuation, t->trace); + + *thread = t; + + return true; + } else if (methodForIp(t, *ip)) { + // add one to the IP since findLineNumber will subtract one + // when we make the trace: + MyThread::TraceContext context( + t, + static_cast(*ip) + 1, + static_cast(*stack) - t->arch->frameReturnAddressSize(), + t->continuation, + t->trace); + + setException(t); + + // printTrace(t, t->exception); + + GcContinuation* continuation; + findUnwindTarget(t, ip, frame, stack, &continuation); + + transition(t, *ip, *stack, continuation, t->trace); + + *thread = t; + + return true; + } + } + + if (compileLog) { + fflush(compileLog); + } + + return false; + } + + Machine* m; + Gc::Type type; + ExceptionGetter exc; + unsigned fixedSize; +}; + +bool isThunk(MyThread* t, void* ip); + +bool isVirtualThunk(MyThread* t, void* ip); + +bool isThunkUnsafeStack(MyThread* t, void* ip); + +void boot(MyThread* t, BootImage* image, uint8_t* code); + +class MyProcessor; + +MyProcessor* processor(MyThread* t); + +#ifndef AVIAN_AOT_ONLY +void compileThunks(MyThread* t, FixedAllocator* allocator); +#endif + +class CompilationHandlerList { + public: + CompilationHandlerList(CompilationHandlerList* next, + Processor::CompilationHandler* handler) + : next(next), handler(handler) + { + } + + void dispose(Allocator* allocator) + { + if (next) { + next->dispose(allocator); + } + handler->dispose(); + allocator->free(this, sizeof(*this)); + } + + CompilationHandlerList* next; + Processor::CompilationHandler* handler; +}; + +template +int checkConstant(MyThread* t, size_t expected, T C::*field, const char* name) +{ + size_t actual = reinterpret_cast(&(t->*field)) + - reinterpret_cast(t); + if (expected != actual) { + fprintf(stderr, + "constant mismatch (%s): \n\tconstant says: %d\n\tc++ compiler " + "says: %d\n", + name, + (unsigned)expected, + (unsigned)actual); + return 1; + } + return 0; +} + +class MyProcessor : public Processor { + public: + class Thunk { + public: + Thunk() : start(0), frameSavedOffset(0), length(0) + { + } + + Thunk(uint8_t* start, unsigned frameSavedOffset, unsigned length) + : start(start), frameSavedOffset(frameSavedOffset), length(length) + { + } + + uint8_t* start; + unsigned frameSavedOffset; + unsigned length; + }; + + class ThunkCollection { + public: + Thunk default_; + Thunk defaultVirtual; + Thunk defaultDynamic; + Thunk native; + Thunk aioob; + Thunk stackOverflow; + Thunk table; + }; + + MyProcessor(System* s, + Allocator* allocator, + const char* crashDumpDirectory, + bool useNativeFeatures) + : s(s), + allocator(allocator), + roots(0), + bootImage(0), + heapImage(0), + codeImage(0), + codeImageSize(0), + segFaultHandler(GcNullPointerException::Type, + &GcRoots::nullPointerException, + GcNullPointerException::FixedSize), + divideByZeroHandler(GcArithmeticException::Type, + &GcRoots::arithmeticException, + GcArithmeticException::FixedSize), + codeAllocator(s, Slice(0, 0)), + callTableSize(0), + dynamicIndex(0), + useNativeFeatures(useNativeFeatures), + compilationHandlers(0), + dynamicTable(0), + dynamicTableSize(0) + { + thunkTable[compileMethodIndex] = voidPointer(local::compileMethod); + thunkTable[compileVirtualMethodIndex] = voidPointer(compileVirtualMethod); + thunkTable[linkDynamicMethodIndex] = voidPointer(linkDynamicMethod); + thunkTable[invokeNativeIndex] = voidPointer(invokeNative); + thunkTable[throwArrayIndexOutOfBoundsIndex] + = voidPointer(throwArrayIndexOutOfBounds); + thunkTable[throwStackOverflowIndex] = voidPointer(throwStackOverflow); + + using namespace avian::codegen::runtime; + +#define THUNK(s) thunkTable[s##Index] = voidPointer(s); +#include "thunks.cpp" +#undef THUNK + // Set the dummyIndex entry to a constant which should require the + // maximum number of bytes to represent in assembly code + // (i.e. can't be represented by a smaller number of bytes and + // implicitly sign- or zero-extended). We'll use this property + // later to determine the maximum size of a thunk in the thunk + // table. + thunkTable[dummyIndex] = reinterpret_cast( + static_cast(UINT64_C(0x5555555555555555))); + + signals.setCrashDumpDirectory(crashDumpDirectory); + } + + virtual Thread* makeThread(Machine* m, GcThread* javaThread, Thread* parent) + { + MyThread* t = new (m->heap->allocate(sizeof(MyThread))) MyThread( + m, javaThread, static_cast(parent), useNativeFeatures); + + t->heapImage = heapImage; + t->codeImage = codeImage; + t->thunkTable = thunkTable; + t->dynamicTable = local::dynamicTable(t); + +#if TARGET_BYTES_PER_WORD == BYTES_PER_WORD + + int mismatches + = checkConstant(t, + TARGET_THREAD_EXCEPTION, + &Thread::exception, + "TARGET_THREAD_EXCEPTION") + + checkConstant(t, + TARGET_THREAD_EXCEPTIONSTACKADJUSTMENT, + &MyThread::exceptionStackAdjustment, + "TARGET_THREAD_EXCEPTIONSTACKADJUSTMENT") + + checkConstant(t, + TARGET_THREAD_EXCEPTIONOFFSET, + &MyThread::exceptionOffset, + "TARGET_THREAD_EXCEPTIONOFFSET") + + checkConstant(t, + TARGET_THREAD_EXCEPTIONHANDLER, + &MyThread::exceptionHandler, + "TARGET_THREAD_EXCEPTIONHANDLER") + + checkConstant( + t, TARGET_THREAD_IP, &MyThread::ip, "TARGET_THREAD_IP") + + checkConstant( + t, TARGET_THREAD_STACK, &MyThread::stack, "TARGET_THREAD_STACK") + + checkConstant(t, + TARGET_THREAD_NEWSTACK, + &MyThread::newStack, + "TARGET_THREAD_NEWSTACK") + + checkConstant(t, + TARGET_THREAD_TAILADDRESS, + &MyThread::tailAddress, + "TARGET_THREAD_TAILADDRESS") + + checkConstant(t, + TARGET_THREAD_VIRTUALCALLTARGET, + &MyThread::virtualCallTarget, + "TARGET_THREAD_VIRTUALCALLTARGET") + + checkConstant(t, + TARGET_THREAD_VIRTUALCALLINDEX, + &MyThread::virtualCallIndex, + "TARGET_THREAD_VIRTUALCALLINDEX") + + checkConstant(t, + TARGET_THREAD_HEAPIMAGE, + &MyThread::heapImage, + "TARGET_THREAD_HEAPIMAGE") + + checkConstant(t, + TARGET_THREAD_CODEIMAGE, + &MyThread::codeImage, + "TARGET_THREAD_CODEIMAGE") + + checkConstant(t, + TARGET_THREAD_THUNKTABLE, + &MyThread::thunkTable, + "TARGET_THREAD_THUNKTABLE") + + checkConstant(t, + TARGET_THREAD_DYNAMICTABLE, + &MyThread::dynamicTable, + "TARGET_THREAD_DYNAMICTABLE") + + checkConstant(t, + TARGET_THREAD_STACKLIMIT, + &MyThread::stackLimit, + "TARGET_THREAD_STACKLIMIT"); + + if (mismatches > 0) { + fprintf(stderr, "%d constant mismatches\n", mismatches); + abort(t); + } + + expect(t, TargetClassArrayElementSize == ClassArrayElementSize); + expect(t, TargetClassFixedSize == ClassFixedSize); + expect(t, TargetClassVtable == ClassVtable); + +#endif + + t->init(); + + return t; + } + + virtual GcMethod* makeMethod(vm::Thread* t, + uint8_t vmFlags, + uint8_t returnCode, + uint8_t parameterCount, + uint8_t parameterFootprint, + uint16_t flags, + uint16_t offset, + GcByteArray* name, + GcByteArray* spec, + GcMethodAddendum* addendum, + GcClass* class_, + GcCode* code) + { + if (code) { + code->compiled() = local::defaultThunk(static_cast(t)); + } + + return vm::makeMethod(t, + vmFlags, + returnCode, + parameterCount, + parameterFootprint, + flags, + offset, + 0, + 0, + name, + spec, + addendum, + class_, + code); + } + + virtual GcClass* makeClass(vm::Thread* t, + uint16_t flags, + uint16_t vmFlags, + uint16_t fixedSize, + uint8_t arrayElementSize, + uint8_t arrayDimensions, + GcClass* arrayElementClass, + GcIntArray* objectMask, + GcByteArray* name, + GcByteArray* sourceFile, + GcClass* super, + object interfaceTable, + object virtualTable, + object fieldTable, + object methodTable, + GcClassAddendum* addendum, + GcSingleton* staticTable, + GcClassLoader* loader, + unsigned vtableLength) + { + return vm::makeClass(t, + flags, + vmFlags, + fixedSize, + arrayElementSize, + arrayDimensions, + arrayElementClass, + 0, + objectMask, + name, + sourceFile, + super, + interfaceTable, + virtualTable, + fieldTable, + methodTable, + addendum, + staticTable, + loader, + 0, + vtableLength); + } + + virtual void initVtable(Thread* t, GcClass* c) + { + PROTECT(t, c); + for (int i = c->length() - 1; i >= 0; --i) { + void* thunk + = reinterpret_cast(virtualThunk(static_cast(t), i)); + c->vtable()[i] = thunk; + } + } + + virtual void visitObjects(Thread* vmt, Heap::Visitor* v) + { + MyThread* t = static_cast(vmt); + + if (t == t->m->rootThread) { + v->visit(&roots); + } + + for (MyThread::CallTrace* trace = t->trace; trace; trace = trace->next) { + v->visit(&(trace->continuation)); + v->visit(&(trace->nativeMethod)); + v->visit(&(trace->targetMethod)); + v->visit(&(trace->originalMethod)); + } + + v->visit(&(t->continuation)); + + for (Reference* r = t->reference; r; r = r->next) { + v->visit(&(r->target)); + } + + visitStack(t, v); + } + + virtual void walkStack(Thread* vmt, StackVisitor* v) + { + MyThread* t = static_cast(vmt); + + MyStackWalker walker(t); + walker.walk(v); + } + + virtual int lineNumber(Thread* vmt, GcMethod* method, int ip) + { + return findLineNumber(static_cast(vmt), method, ip); + } + + virtual object* makeLocalReference(Thread* vmt, object o) + { + if (o) { + MyThread* t = static_cast(vmt); + + for (Reference* r = t->reference; r; r = r->next) { + if (r->target == o) { + acquire(t, r); + + return &(r->target); + } + } + + Reference* r = new (t->m->heap->allocate(sizeof(Reference))) + Reference(o, &(t->reference), false); + + acquire(t, r); + + return &(r->target); + } else { + return 0; + } + } + + virtual void disposeLocalReference(Thread* t, object* r) + { + if (r) { + release(t, reinterpret_cast(r)); + } + } + + virtual bool pushLocalFrame(Thread* vmt, unsigned) + { + MyThread* t = static_cast(vmt); + + t->referenceFrame = new (t->m->heap->allocate(sizeof(List))) + List(t->reference, t->referenceFrame); + + return true; + } + + virtual void popLocalFrame(Thread* vmt) + { + MyThread* t = static_cast(vmt); + + List* f = t->referenceFrame; + t->referenceFrame = f->next; + while (t->reference != f->item) { + vm::dispose(t, t->reference); + } + + t->m->heap->free(f, sizeof(List)); + } + + virtual object invokeArray(Thread* t, + GcMethod* method, + object this_, + object arguments) + { + assertT(t, t->exception == 0); + + assertT( + t, + t->state == Thread::ActiveState or t->state == Thread::ExclusiveState); + + assertT(t, ((method->flags() & ACC_STATIC) == 0) xor (this_ == 0)); + + const char* spec = reinterpret_cast(method->spec()->body().begin()); + + unsigned size = method->parameterFootprint(); + THREAD_RUNTIME_ARRAY(t, uintptr_t, array, size); + THREAD_RUNTIME_ARRAY(t, bool, objectMask, size); + ArgumentList list(t, + RUNTIME_ARRAY_BODY(array), + size, + RUNTIME_ARRAY_BODY(objectMask), + this_, + spec, + arguments); + + PROTECT(t, method); + + method = findMethod(t, method, this_); + + compile(static_cast(t), + local::codeAllocator(static_cast(t)), + 0, + method); + + return local::invoke(t, method, &list); + } + + virtual object invokeArray(Thread* t, + GcMethod* method, + object this_, + const jvalue* arguments) + { + assertT(t, t->exception == 0); + + assertT( + t, + t->state == Thread::ActiveState or t->state == Thread::ExclusiveState); + + assertT(t, ((method->flags() & ACC_STATIC) == 0) xor (this_ == 0)); + + const char* spec = reinterpret_cast(method->spec()->body().begin()); + + unsigned size = method->parameterFootprint(); + THREAD_RUNTIME_ARRAY(t, uintptr_t, array, size); + THREAD_RUNTIME_ARRAY(t, bool, objectMask, size); + ArgumentList list(t, + RUNTIME_ARRAY_BODY(array), + size, + RUNTIME_ARRAY_BODY(objectMask), + this_, + spec, + arguments); + + PROTECT(t, method); + + method = findMethod(t, method, this_); + + compile(static_cast(t), + local::codeAllocator(static_cast(t)), + 0, + method); + + return local::invoke(t, method, &list); + } + + virtual object invokeList(Thread* t, + GcMethod* method, + object this_, + bool indirectObjects, + va_list arguments) + { + assertT(t, t->exception == 0); + + assertT( + t, + t->state == Thread::ActiveState or t->state == Thread::ExclusiveState); + + assertT(t, ((method->flags() & ACC_STATIC) == 0) xor (this_ == 0)); + + const char* spec = reinterpret_cast(method->spec()->body().begin()); + + unsigned size = method->parameterFootprint(); + THREAD_RUNTIME_ARRAY(t, uintptr_t, array, size); + THREAD_RUNTIME_ARRAY(t, bool, objectMask, size); + ArgumentList list(t, + RUNTIME_ARRAY_BODY(array), + size, + RUNTIME_ARRAY_BODY(objectMask), + this_, + spec, + indirectObjects, + arguments); + + PROTECT(t, method); + + method = findMethod(t, method, this_); + + compile(static_cast(t), + local::codeAllocator(static_cast(t)), + 0, + method); + + return local::invoke(t, method, &list); + } + + virtual object invokeList(Thread* t, + GcClassLoader* loader, + const char* className, + const char* methodName, + const char* methodSpec, + object this_, + va_list arguments) + { + assertT(t, t->exception == 0); + + assertT( + t, + t->state == Thread::ActiveState or t->state == Thread::ExclusiveState); + + unsigned size = parameterFootprint(t, methodSpec, this_ == 0); + THREAD_RUNTIME_ARRAY(t, uintptr_t, array, size); + THREAD_RUNTIME_ARRAY(t, bool, objectMask, size); + ArgumentList list(t, + RUNTIME_ARRAY_BODY(array), + size, + RUNTIME_ARRAY_BODY(objectMask), + this_, + methodSpec, + false, + arguments); + + GcMethod* method + = resolveMethod(t, loader, className, methodName, methodSpec); + + assertT(t, ((method->flags() & ACC_STATIC) == 0) xor (this_ == 0)); + + PROTECT(t, method); + + compile(static_cast(t), + local::codeAllocator(static_cast(t)), + 0, + method); + + return local::invoke(t, method, &list); + } + + virtual void dispose(Thread* vmt) + { + MyThread* t = static_cast(vmt); + + while (t->reference) { + vm::dispose(t, t->reference); + } + + t->arch->release(); + + t->m->heap->free(t, sizeof(*t)); + } + + virtual void dispose() + { + if (codeAllocator.memory.begin()) { +#ifndef AVIAN_AOT_ONLY + Memory::free(codeAllocator.memory); +#endif + } + + if(compilationHandlers) { + compilationHandlers->dispose(allocator); + } + + signals.unregisterHandler(SignalRegistrar::SegFault); + signals.unregisterHandler(SignalRegistrar::DivideByZero); + signals.setCrashDumpDirectory(0); + + if (dynamicTable) { + allocator->free(dynamicTable, dynamicTableSize); + } + + this->~MyProcessor(); + + allocator->free(this, sizeof(*this)); + } + + virtual object getStackTrace(Thread* vmt, Thread* vmTarget) + { + MyThread* t = static_cast(vmt); + MyThread* target = static_cast(vmTarget); + MyProcessor* p = this; + + class Visitor : public System::ThreadVisitor { + public: + Visitor(MyThread* t, MyProcessor* p, MyThread* target) + : t(t), p(p), target(target), trace(0) + { + } + + virtual void visit(void* ip, void* stack, void* link) + { + MyThread::TraceContext c(target, link); + + if (methodForIp(t, ip)) { + // we caught the thread in Java code - use the register values + c.ip = ip; + c.stack = stack; + c.methodIsMostRecent = true; + } else if (target->transition) { + // we caught the thread in native code while in the middle + // of updating the context fields (MyThread::stack, etc.) + static_cast(c) = *(target->transition); + } else if (isVmInvokeUnsafeStack(ip)) { + // we caught the thread in native code just after returning + // from java code, but before clearing MyThread::stack + // (which now contains a garbage value), and the most recent + // Java frame, if any, can be found in + // MyThread::continuation or MyThread::trace + c.ip = 0; + c.stack = 0; + } else if (target->stack and (not isThunkUnsafeStack(t, ip)) + and (not isVirtualThunk(t, ip))) { + // we caught the thread in a thunk or native code, and the + // saved stack pointer indicates the most recent Java frame + // on the stack + c.ip = getIp(target); + c.stack = target->stack; + } else if (isThunk(t, ip) or isVirtualThunk(t, ip)) { + // we caught the thread in a thunk where the stack register + // indicates the most recent Java frame on the stack + + // On e.g. x86, the return address will have already been + // pushed onto the stack, in which case we use getIp to + // retrieve it. On e.g. ARM, it will be in the + // link register. Note that we can't just check if the link + // argument is null here, since we use ecx/rcx as a + // pseudo-link register on x86 for the purpose of tail + // calls. + c.ip = t->arch->hasLinkRegister() ? link : getIp(t, link, stack); + c.stack = stack; + } else { + // we caught the thread in native code, and the most recent + // Java frame, if any, can be found in + // MyThread::continuation or MyThread::trace + c.ip = 0; + c.stack = 0; + } + + if (ensure(t, traceSize(target))) { + t->setFlag(Thread::TracingFlag); + trace = makeTrace(t, target); + t->clearFlag(Thread::TracingFlag); + } + } + + MyThread* t; + MyProcessor* p; + MyThread* target; + object trace; + } visitor(t, p, target); + + t->m->system->visit(t->systemThread, target->systemThread, &visitor); + + if (UNLIKELY(t->getFlags() & Thread::UseBackupHeapFlag)) { + PROTECT(t, visitor.trace); + + collect(t, Heap::MinorCollection); + } + + return visitor.trace ? visitor.trace : makeObjectArray(t, 0); + } + + virtual void initialize(BootImage* image, Slice code) + { + bootImage = image; + codeAllocator.memory = code; + } + + virtual void addCompilationHandler(CompilationHandler* handler) + { + compilationHandlers + = new (allocator->allocate(sizeof(CompilationHandlerList))) + CompilationHandlerList(compilationHandlers, handler); + } + + virtual void compileMethod(Thread* vmt, + Zone* zone, + GcTriple** constants, + GcTriple** calls, + avian::codegen::DelayedPromise** addresses, + GcMethod* method, + OffsetResolver* resolver, + JavaVM* hostVM) + { + MyThread* t = static_cast(vmt); + BootContext bootContext( + t, *constants, *calls, *addresses, zone, resolver, hostVM); + + compile(t, &codeAllocator, &bootContext, method); + + *constants = bootContext.constants; + *calls = bootContext.calls; + *addresses = bootContext.addresses; + } + + virtual void visitRoots(Thread* t, HeapWalker* w) + { + bootImage->methodTree = w->visitRoot(compileRoots(t)->methodTree()); + bootImage->methodTreeSentinal + = w->visitRoot(compileRoots(t)->methodTreeSentinal()); + bootImage->virtualThunks = w->visitRoot(compileRoots(t)->virtualThunks()); + } + + virtual void normalizeVirtualThunks(Thread* t) + { + GcWordArray* a = compileRoots(t)->virtualThunks(); + for (unsigned i = 0; i < a->length(); i += 2) { + if (a->body()[i]) { + a->body()[i] + -= reinterpret_cast(codeAllocator.memory.begin()); + } + } + } + + virtual unsigned* makeCallTable(Thread* t, HeapWalker* w) + { + bootImage->codeSize = codeAllocator.offset; + bootImage->callCount = callTableSize; + + unsigned* table = static_cast( + t->m->heap->allocate(callTableSize * sizeof(unsigned) * 2)); + + unsigned index = 0; + GcArray* callTable = compileRoots(t)->callTable(); + for (unsigned i = 0; i < callTable->length(); ++i) { + for (GcCallNode* p = cast(t, callTable->body()[i]); p; + p = p->next()) { + table[index++] + = targetVW(p->address() - reinterpret_cast( + codeAllocator.memory.begin())); + table[index++] = targetVW( + w->map()->find(p->target()) + | (static_cast(p->flags()) << TargetBootShift)); + } + } + + return table; + } + + virtual void boot(Thread* t, BootImage* image, uint8_t* code) + { +#ifndef AVIAN_AOT_ONLY + if (codeAllocator.memory.begin() == 0) { + codeAllocator.memory = Memory::allocate(ExecutableAreaSizeInBytes, + Memory::ReadWriteExecute); + + expect(t, codeAllocator.memory.begin()); + } +#endif + + if (image and code) { + local::boot(static_cast(t), image, code); + } else { + roots = makeCompileRoots(t, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); + + { + GcArray* ct = makeArray(t, 128); + // sequence point, for gc (don't recombine statements) + compileRoots(t)->setCallTable(t, ct); + } + + GcTreeNode* tree = makeTreeNode(t, 0, 0, 0); + compileRoots(t)->setMethodTreeSentinal(t, tree); + compileRoots(t)->setMethodTree(t, tree); + tree->setLeft(t, tree); + tree->setRight(t, tree); + } + +#ifdef AVIAN_AOT_ONLY + thunks = bootThunks; +#else + local::compileThunks(static_cast(t), &codeAllocator); + + if (not(image and code)) { + bootThunks = thunks; + } +#endif + + segFaultHandler.m = t->m; + expect( + t, + signals.registerHandler(SignalRegistrar::SegFault, &segFaultHandler)); + + divideByZeroHandler.m = t->m; + expect(t, + signals.registerHandler(SignalRegistrar::DivideByZero, + ÷ByZeroHandler)); + } + + virtual void callWithCurrentContinuation(Thread* t, object receiver) + { + if (Continuations) { + local::callWithCurrentContinuation(static_cast(t), receiver); + } else { + abort(t); + } + } + + virtual void dynamicWind(Thread* t, object before, object thunk, object after) + { + if (Continuations) { + local::dynamicWind(static_cast(t), before, thunk, after); + } else { + abort(t); + } + } + + virtual void feedResultToContinuation(Thread* t, + GcContinuation* continuation, + object result) + { + if (Continuations) { + callContinuation(static_cast(t), continuation, result, 0); + } else { + abort(t); + } + } + + virtual void feedExceptionToContinuation(Thread* t, + GcContinuation* continuation, + GcThrowable* exception) + { + if (Continuations) { + callContinuation(static_cast(t), continuation, 0, exception); + } else { + abort(t); + } + } + + virtual void walkContinuationBody(Thread* t, + Heap::Walker* w, + object o, + unsigned start) + { + if (Continuations) { + local::walkContinuationBody( + static_cast(t), w, cast(t, o), start); + } else { + abort(t); + } + } + + System* s; + SignalRegistrar signals; + Allocator* allocator; + GcCompileRoots* roots; + BootImage* bootImage; + uintptr_t* heapImage; + uint8_t* codeImage; + unsigned codeImageSize; + SignalHandler segFaultHandler; + SignalHandler divideByZeroHandler; + FixedAllocator codeAllocator; + ThunkCollection thunks; + ThunkCollection bootThunks; + unsigned callTableSize; + unsigned dynamicIndex; + bool useNativeFeatures; + void* thunkTable[dummyIndex + 1]; + CompilationHandlerList* compilationHandlers; + void** dynamicTable; + unsigned dynamicTableSize; +}; + +unsigned& dynamicIndex(MyThread* t) +{ + return static_cast(t->m->processor)->dynamicIndex; +} + +void**& dynamicTable(MyThread* t) +{ + return static_cast(t->m->processor)->dynamicTable; +} + +unsigned& dynamicTableSize(MyThread* t) +{ + return static_cast(t->m->processor)->dynamicTableSize; +} + +const char* stringOrNull(const char* str) +{ + if (str) { + return str; + } else { + return "(null)"; + } +} + +size_t stringOrNullSize(const char* str) +{ + return strlen(stringOrNull(str)); +} + +void logCompile(MyThread* t, + const void* code, + unsigned size, + const char* class_, + const char* name, + const char* spec) +{ + static bool open = false; + if (not open) { + open = true; + const char* path = findProperty(t, "avian.jit.log"); + if (path) { + compileLog = vm::fopen(path, "wb"); + } else if (DebugCompile) { + compileLog = stderr; + } + } + + if (compileLog) { + fprintf(compileLog, + "%p,%p %s.%s%s\n", + code, + static_cast(code) + size, + class_, + name, + spec); + } + + size_t nameLength = stringOrNullSize(class_) + stringOrNullSize(name) + + stringOrNullSize(spec) + 2; + + THREAD_RUNTIME_ARRAY(t, char, completeName, nameLength); + + sprintf(RUNTIME_ARRAY_BODY(completeName), + "%s.%s%s", + stringOrNull(class_), + stringOrNull(name), + stringOrNull(spec)); + + MyProcessor* p = static_cast(t->m->processor); + for (CompilationHandlerList* h = p->compilationHandlers; h; h = h->next) { + h->handler->compiled(code, 0, 0, RUNTIME_ARRAY_BODY(completeName)); + } +} + +void* compileMethod2(MyThread* t, void* ip) +{ + GcCallNode* node = findCallNode(t, ip); + GcMethod* target = node->target(); + + PROTECT(t, node); + PROTECT(t, target); + + t->trace->targetMethod = target; + + THREAD_RESOURCE0(t, static_cast(t)->trace->targetMethod = 0); + + compile(t, codeAllocator(t), 0, target); + + uint8_t* updateIp = static_cast(ip); + + MyProcessor* p = processor(t); + + bool updateCaller = updateIp < p->codeImage + or updateIp >= p->codeImage + p->codeImageSize; + + uintptr_t address; + if (target->flags() & ACC_NATIVE) { + address = useLongJump(t, reinterpret_cast(ip)) + or (not updateCaller) + ? bootNativeThunk(t) + : nativeThunk(t); + } else { + address = methodAddress(t, target); + } + + if (updateCaller) { + avian::codegen::lir::UnaryOperation op; + if (node->flags() & TraceElement::LongCall) { + if (node->flags() & TraceElement::TailCall) { + op = avian::codegen::lir::AlignedLongJump; + } else { + op = avian::codegen::lir::AlignedLongCall; + } + } else if (node->flags() & TraceElement::TailCall) { + op = avian::codegen::lir::AlignedJump; + } else { + op = avian::codegen::lir::AlignedCall; + } + + updateCall(t, op, updateIp, reinterpret_cast(address)); + } + + return reinterpret_cast(address); +} + +bool isThunk(MyProcessor::ThunkCollection* thunks, void* ip) +{ + uint8_t* thunkStart = thunks->default_.start; + uint8_t* thunkEnd = thunks->table.start + (thunks->table.length * ThunkCount); + + return (reinterpret_cast(ip) + >= reinterpret_cast(thunkStart) + and reinterpret_cast(ip) + < reinterpret_cast(thunkEnd)); +} + +bool isThunk(MyThread* t, void* ip) +{ + MyProcessor* p = processor(t); + + return isThunk(&(p->thunks), ip) or isThunk(&(p->bootThunks), ip); +} + +bool isThunkUnsafeStack(MyProcessor::Thunk* thunk, void* ip) +{ + return reinterpret_cast(ip) + >= reinterpret_cast(thunk->start) + and reinterpret_cast(ip) + < reinterpret_cast(thunk->start + + thunk->frameSavedOffset); +} + +bool isThunkUnsafeStack(MyProcessor::ThunkCollection* thunks, void* ip) +{ + const unsigned NamedThunkCount = 6; + + MyProcessor::Thunk table[NamedThunkCount + ThunkCount]; + + table[0] = thunks->default_; + table[1] = thunks->defaultVirtual; + table[2] = thunks->defaultDynamic; + table[3] = thunks->native; + table[4] = thunks->aioob; + table[5] = thunks->stackOverflow; + + for (unsigned i = 0; i < ThunkCount; ++i) { + new (table + NamedThunkCount + i) + MyProcessor::Thunk(thunks->table.start + (i * thunks->table.length), + thunks->table.frameSavedOffset, + thunks->table.length); + } + + for (unsigned i = 0; i < NamedThunkCount + ThunkCount; ++i) { + if (isThunkUnsafeStack(table + i, ip)) { + return true; + } + } + + return false; +} + +bool isVirtualThunk(MyThread* t, void* ip) +{ + GcWordArray* a = compileRoots(t)->virtualThunks(); + for (unsigned i = 0; i < a->length(); i += 2) { + uintptr_t start = a->body()[i]; + uintptr_t end = start + a->body()[i + 1]; + + if (reinterpret_cast(ip) >= start + and reinterpret_cast(ip) < end) { + return true; + } + } + + return false; +} + +bool isThunkUnsafeStack(MyThread* t, void* ip) +{ + MyProcessor* p = processor(t); + + return isThunk(t, ip) and (isThunkUnsafeStack(&(p->thunks), ip) + or isThunkUnsafeStack(&(p->bootThunks), ip)); +} + +GcCallNode* findCallNode(MyThread* t, void* address) +{ + if (DebugCallTable) { + fprintf(stderr, "find call node %p\n", address); + } + + // we must use a version of the call table at least as recent as the + // compiled form of the method containing the specified address (see + // compile(MyThread*, Allocator*, BootContext*, object)): + loadMemoryBarrier(); + + GcArray* table = compileRoots(t)->callTable(); + + intptr_t key = reinterpret_cast(address); + unsigned index = static_cast(key) & (table->length() - 1); + + for (GcCallNode* n = cast(t, table->body()[index]); n; + n = n->next()) { + intptr_t k = n->address(); + + if (k == key) { + return n; + } + } + + return 0; +} + +GcArray* resizeTable(MyThread* t, GcArray* oldTable, unsigned newLength) +{ + PROTECT(t, oldTable); + + GcCallNode* oldNode = 0; + PROTECT(t, oldNode); + + GcArray* newTable = makeArray(t, newLength); + PROTECT(t, newTable); + + for (unsigned i = 0; i < oldTable->length(); ++i) { + for (oldNode = cast(t, oldTable->body()[i]); oldNode; + oldNode = oldNode->next()) { + intptr_t k = oldNode->address(); + + unsigned index = k & (newLength - 1); + + GcCallNode* newNode + = makeCallNode(t, + oldNode->address(), + oldNode->target(), + oldNode->flags(), + cast(t, newTable->body()[index])); + + newTable->setBodyElement(t, index, newNode); + } + } + + return newTable; +} + +GcArray* insertCallNode(MyThread* t, + GcArray* table, + unsigned* size, + GcCallNode* node) +{ + if (DebugCallTable) { + fprintf(stderr, + "insert call node %p\n", + reinterpret_cast(node->address())); + } + + PROTECT(t, table); + PROTECT(t, node); + + ++(*size); + + if (*size >= table->length() * 2) { + table = resizeTable(t, table, table->length() * 2); + } + + intptr_t key = node->address(); + unsigned index = static_cast(key) & (table->length() - 1); + + node->setNext(t, cast(t, table->body()[index])); + table->setBodyElement(t, index, node); + + return table; +} + +GcHashMap* makeClassMap(Thread* t, + unsigned* table, + unsigned count, + uintptr_t* heap) +{ + GcArray* array = makeArray(t, nextPowerOfTwo(count)); + GcHashMap* map = makeHashMap(t, 0, array); + PROTECT(t, map); + + for (unsigned i = 0; i < count; ++i) { + GcClass* c = cast(t, bootObject(heap, table[i])); + hashMapInsert(t, map, c->name(), c, byteArrayHash); + } + + return map; +} + +GcArray* makeStaticTableArray(Thread* t, + unsigned* bootTable, + unsigned bootCount, + unsigned* appTable, + unsigned appCount, + uintptr_t* heap) +{ + GcArray* array = makeArray(t, bootCount + appCount); + + for (unsigned i = 0; i < bootCount; ++i) { + array->setBodyElement( + t, i, cast(t, bootObject(heap, bootTable[i]))->staticTable()); + } + + for (unsigned i = 0; i < appCount; ++i) { + array->setBodyElement( + t, + (bootCount + i), + cast(t, bootObject(heap, appTable[i]))->staticTable()); + } + + return array; +} + +GcHashMap* makeStringMap(Thread* t, + unsigned* table, + unsigned count, + uintptr_t* heap) +{ + GcArray* array = makeArray(t, nextPowerOfTwo(count)); + GcHashMap* map = makeWeakHashMap(t, 0, array)->as(t); + PROTECT(t, map); + + for (unsigned i = 0; i < count; ++i) { + object s = bootObject(heap, table[i]); + hashMapInsert(t, map, s, 0, stringHash); + } + + return map; +} + +GcArray* makeCallTable(MyThread* t, + uintptr_t* heap, + unsigned* calls, + unsigned count, + uintptr_t base) +{ + GcArray* table = makeArray(t, nextPowerOfTwo(count)); + PROTECT(t, table); + + unsigned size = 0; + for (unsigned i = 0; i < count; ++i) { + unsigned address = calls[i * 2]; + unsigned target = calls[(i * 2) + 1]; + + GcCallNode* node + = makeCallNode(t, + base + address, + cast(t, bootObject(heap, target & BootMask)), + target >> BootShift, + 0); + + table = insertCallNode(t, table, &size, node); + } + + return table; +} + +void fixupHeap(MyThread* t UNUSED, + uintptr_t* map, + unsigned size, + uintptr_t* heap) +{ + for (unsigned word = 0; word < size; ++word) { + uintptr_t w = map[word]; + if (w) { + for (unsigned bit = 0; bit < BitsPerWord; ++bit) { + if (w & (static_cast(1) << bit)) { + unsigned index = indexOf(word, bit); + + uintptr_t* p = heap + index; + assertT(t, *p); + + uintptr_t number = *p & BootMask; + uintptr_t mark = *p >> BootShift; + + if (number) { + *p = reinterpret_cast(heap + (number - 1)) | mark; + if (false) { + fprintf(stderr, + "fixup %d: %d 0x%x\n", + index, + static_cast(number), + static_cast(*p)); + } + } else { + *p = mark; + } + } + } + } + } +} + +void resetClassRuntimeState(Thread* t, + GcClass* c, + uintptr_t* heap, + unsigned heapSize) +{ + c->runtimeDataIndex() = 0; + + if (c->arrayElementSize() == 0) { + GcSingleton* staticTable = c->staticTable()->as(t); + if (staticTable) { + for (unsigned i = 0; i < singletonCount(t, staticTable); ++i) { + if (singletonIsObject(t, staticTable, i) + and (reinterpret_cast( + singletonObject(t, staticTable, i)) < heap + or reinterpret_cast(singletonObject( + t, staticTable, i)) > heap + heapSize)) { + singletonObject(t, staticTable, i) = 0; + } + } + } + } + + if (GcArray* mtable = cast(t, c->methodTable())) { + PROTECT(t, mtable); + for (unsigned i = 0; i < mtable->length(); ++i) { + GcMethod* m = cast(t, mtable->body()[i]); + + m->nativeID() = 0; + m->runtimeDataIndex() = 0; + + if (m->vmFlags() & ClassInitFlag) { + c->vmFlags() |= NeedInitFlag; + c->vmFlags() &= ~InitErrorFlag; + } + } + } + + t->m->processor->initVtable(t, c); +} + +void resetRuntimeState(Thread* t, + GcHashMap* map, + uintptr_t* heap, + unsigned heapSize) +{ + for (HashMapIterator it(t, map); it.hasMore();) { + resetClassRuntimeState( + t, cast(t, it.next()->second()), heap, heapSize); + } +} + +void fixupMethods(Thread* t, + GcHashMap* map, + BootImage* image UNUSED, + uint8_t* code) +{ + for (HashMapIterator it(t, map); it.hasMore();) { + GcClass* c = cast(t, it.next()->second()); + + if (GcArray* mtable = cast(t, c->methodTable())) { + PROTECT(t, mtable); + for (unsigned i = 0; i < mtable->length(); ++i) { + GcMethod* method = cast(t, mtable->body()[i]); + if (method->code()) { + assertT(t, + methodCompiled(t, method) + <= static_cast(image->codeSize)); + + method->code()->compiled() = methodCompiled(t, method) + + reinterpret_cast(code); + + if (DebugCompile) { + logCompile(static_cast(t), + reinterpret_cast(methodCompiled(t, method)), + methodCompiledSize(t, method), + reinterpret_cast( + method->class_()->name()->body().begin()), + reinterpret_cast(method->name()->body().begin()), + reinterpret_cast(method->spec()->body().begin())); + } + } + } + } + + t->m->processor->initVtable(t, c); + } +} + +MyProcessor::Thunk thunkToThunk(const BootImage::Thunk& thunk, uint8_t* base) +{ + return MyProcessor::Thunk( + base + thunk.start, thunk.frameSavedOffset, thunk.length); +} + +void findThunks(MyThread* t, BootImage* image, uint8_t* code) +{ + MyProcessor* p = processor(t); + + p->bootThunks.default_ = thunkToThunk(image->thunks.default_, code); + p->bootThunks.defaultVirtual = thunkToThunk(image->thunks.defaultVirtual, code); + p->bootThunks.defaultDynamic = thunkToThunk(image->thunks.defaultDynamic, code); + p->bootThunks.native = thunkToThunk(image->thunks.native, code); + p->bootThunks.aioob = thunkToThunk(image->thunks.aioob, code); + p->bootThunks.stackOverflow = thunkToThunk(image->thunks.stackOverflow, code); + p->bootThunks.table = thunkToThunk(image->thunks.table, code); +} + +void fixupVirtualThunks(MyThread* t, uint8_t* code) +{ + GcWordArray* a = compileRoots(t)->virtualThunks(); + for (unsigned i = 0; i < a->length(); i += 2) { + if (a->body()[i]) { + a->body()[i] += reinterpret_cast(code); + } + } +} + +void boot(MyThread* t, BootImage* image, uint8_t* code) +{ + assertT(t, image->magic == BootImage::Magic); + + unsigned* bootClassTable = reinterpret_cast(image + 1); + unsigned* appClassTable = bootClassTable + image->bootClassCount; + unsigned* stringTable = appClassTable + image->appClassCount; + unsigned* callTable = stringTable + image->stringCount; + + uintptr_t* heapMap = reinterpret_cast( + padWord(reinterpret_cast(callTable + (image->callCount * 2)))); + + unsigned heapMapSizeInWords + = ceilingDivide(heapMapSize(image->heapSize), BytesPerWord); + uintptr_t* heap = heapMap + heapMapSizeInWords; + + MyProcessor* p = static_cast(t->m->processor); + + t->heapImage = p->heapImage = heap; + + if (false) { + fprintf(stderr, + "heap from %p to %p\n", + heap, + heap + ceilingDivide(image->heapSize, BytesPerWord)); + } + + t->codeImage = p->codeImage = code; + p->codeImageSize = image->codeSize; + + if (false) { + fprintf(stderr, "code from %p to %p\n", code, code + image->codeSize); + } + + if (not image->initialized) { + fixupHeap(t, heapMap, heapMapSizeInWords, heap); + } + + t->m->heap->setImmortalHeap(heap, image->heapSize / BytesPerWord); + + t->m->types = reinterpret_cast(bootObject(heap, image->types)); + + t->m->roots = GcRoots::makeZeroed(t); + + roots(t)->setBootLoader( + t, cast(t, bootObject(heap, image->bootLoader))); + roots(t)->setAppLoader( + t, cast(t, bootObject(heap, image->appLoader))); + + p->roots = GcCompileRoots::makeZeroed(t); + + compileRoots(t)->setMethodTree( + t, cast(t, bootObject(heap, image->methodTree))); + compileRoots(t)->setMethodTreeSentinal( + t, cast(t, bootObject(heap, image->methodTreeSentinal))); + + compileRoots(t)->setVirtualThunks( + t, cast(t, bootObject(heap, image->virtualThunks))); + + { + GcHashMap* map + = makeClassMap(t, bootClassTable, image->bootClassCount, heap); + // sequence point, for gc (don't recombine statements) + roots(t)->bootLoader()->setMap(t, map); + } + + roots(t)->bootLoader()->as(t)->finder() + = t->m->bootFinder; + + { + GcHashMap* map = makeClassMap(t, appClassTable, image->appClassCount, heap); + // sequence point, for gc (don't recombine statements) + roots(t)->appLoader()->setMap(t, map); + } + + roots(t)->appLoader()->as(t)->finder() = t->m->appFinder; + + { + GcHashMap* map = makeStringMap(t, stringTable, image->stringCount, heap); + // sequence point, for gc (don't recombine statements) + roots(t)->setStringMap(t, map); + } + + p->callTableSize = image->callCount; + + { + GcArray* ct = makeCallTable(t, + heap, + callTable, + image->callCount, + reinterpret_cast(code)); + // sequence point, for gc (don't recombine statements) + compileRoots(t)->setCallTable(t, ct); + } + + { + GcArray* staticTableArray = makeStaticTableArray(t, + bootClassTable, + image->bootClassCount, + appClassTable, + image->appClassCount, + heap); + // sequence point, for gc (don't recombine statements) + compileRoots(t)->setStaticTableArray(t, staticTableArray); + } + + findThunks(t, image, code); + + if (image->initialized) { + resetRuntimeState(t, + cast(t, roots(t)->bootLoader()->map()), + heap, + image->heapSize); + + resetRuntimeState(t, + cast(t, roots(t)->appLoader()->map()), + heap, + image->heapSize); + + for (unsigned i = 0; i < t->m->types->length(); ++i) { + resetClassRuntimeState( + t, type(t, static_cast(i)), heap, image->heapSize); + } + } else { + fixupVirtualThunks(t, code); + + fixupMethods( + t, cast(t, roots(t)->bootLoader()->map()), image, code); + + fixupMethods( + t, cast(t, roots(t)->appLoader()->map()), image, code); + } + + image->initialized = true; + + GcHashMap* map = makeHashMap(t, 0, 0); + // sequence point, for gc (don't recombine statements) + roots(t)->setBootstrapClassMap(t, map); +} + +intptr_t getThunk(MyThread* t, Thunk thunk) +{ + MyProcessor* p = processor(t); + + return reinterpret_cast(p->thunks.table.start + + (thunk * p->thunks.table.length)); +} + +#ifndef AVIAN_AOT_ONLY +void insertCallNode(MyThread* t, GcCallNode* node) +{ + GcArray* newArray = insertCallNode( + t, compileRoots(t)->callTable(), &(processor(t)->callTableSize), node); + // sequence point, for gc (don't recombine statements) + compileRoots(t)->setCallTable(t, newArray); +} + +BootImage::Thunk thunkToThunk(const MyProcessor::Thunk& thunk, uint8_t* base) +{ + return BootImage::Thunk( + thunk.start - base, thunk.frameSavedOffset, thunk.length); +} + +using avian::codegen::OperandInfo; +namespace lir = avian::codegen::lir; + +void compileCall(MyThread* t, Context* c, ThunkIndex index, bool call = true) +{ + avian::codegen::Assembler* a = c->assembler; + + if (processor(t)->bootImage) { + lir::Memory table(t->arch->thread(), TARGET_THREAD_THUNKTABLE); + lir::RegisterPair scratch(t->arch->scratch()); + a->apply(lir::Move, + OperandInfo(TargetBytesPerWord, lir::Operand::Type::Memory, &table), + OperandInfo(TargetBytesPerWord, lir::Operand::Type::RegisterPair, &scratch)); + lir::Memory proc(scratch.low, index * TargetBytesPerWord); + a->apply(lir::Move, + OperandInfo(TargetBytesPerWord, lir::Operand::Type::Memory, &proc), + OperandInfo(TargetBytesPerWord, lir::Operand::Type::RegisterPair, &scratch)); + a->apply(call ? lir::Call : lir::Jump, + OperandInfo(TargetBytesPerWord, lir::Operand::Type::RegisterPair, &scratch)); + } else { + lir::Constant proc(new (&c->zone) avian::codegen::ResolvedPromise( + reinterpret_cast(t->thunkTable[index]))); + + a->apply(call ? lir::LongCall : lir::LongJump, + OperandInfo(TargetBytesPerWord, lir::Operand::Type::Constant, &proc)); + } +} + +void compileDefaultThunk(MyThread* t, + FixedAllocator* allocator, + MyProcessor::Thunk* thunk, + const char* name, + ThunkIndex thunkIndex, + bool hasTarget) +{ + Context context(t); + avian::codegen::Assembler* a = context.assembler; + + if(hasTarget) { + lir::RegisterPair class_(t->arch->virtualCallTarget()); + lir::Memory virtualCallTargetSrc( + t->arch->stack(), + (t->arch->frameFooterSize() + t->arch->frameReturnAddressSize()) + * TargetBytesPerWord); + + a->apply(lir::Move, + OperandInfo( + TargetBytesPerWord, lir::Operand::Type::Memory, &virtualCallTargetSrc), + OperandInfo(TargetBytesPerWord, lir::Operand::Type::RegisterPair, &class_)); + + lir::Memory virtualCallTargetDst(t->arch->thread(), + TARGET_THREAD_VIRTUALCALLTARGET); + + a->apply( + lir::Move, + OperandInfo(TargetBytesPerWord, lir::Operand::Type::RegisterPair, &class_), + OperandInfo( + TargetBytesPerWord, lir::Operand::Type::Memory, &virtualCallTargetDst)); + } + + lir::RegisterPair index(t->arch->virtualCallIndex()); + lir::Memory virtualCallIndex(t->arch->thread(), + TARGET_THREAD_VIRTUALCALLINDEX); + + a->apply( + lir::Move, + OperandInfo(TargetBytesPerWord, lir::Operand::Type::RegisterPair, &index), + OperandInfo(TargetBytesPerWord, lir::Operand::Type::Memory, &virtualCallIndex)); + + a->saveFrame(TARGET_THREAD_STACK, TARGET_THREAD_IP); + + thunk->frameSavedOffset = a->length(); + + lir::RegisterPair thread(t->arch->thread()); + a->pushFrame(1, TargetBytesPerWord, lir::Operand::Type::RegisterPair, &thread); + + compileCall(t, &context, thunkIndex); + + a->popFrame(t->arch->alignFrameSize(1)); + + lir::RegisterPair result(t->arch->returnLow()); + a->apply(lir::Jump, + OperandInfo(TargetBytesPerWord, lir::Operand::Type::RegisterPair, &result)); + + thunk->length = a->endBlock(false)->resolve(0, 0); + + thunk->start = finish( + t, allocator, a, name, thunk->length); +} + +void compileThunks(MyThread* t, FixedAllocator* allocator) +{ + MyProcessor* p = processor(t); + + { + Context context(t); + avian::codegen::Assembler* a = context.assembler; + + a->saveFrame(TARGET_THREAD_STACK, TARGET_THREAD_IP); + + p->thunks.default_.frameSavedOffset = a->length(); + + lir::RegisterPair thread(t->arch->thread()); + a->pushFrame(1, TargetBytesPerWord, lir::Operand::Type::RegisterPair, &thread); + + compileCall(t, &context, compileMethodIndex); + + a->popFrame(t->arch->alignFrameSize(1)); + + lir::RegisterPair result(t->arch->returnLow()); + a->apply(lir::Jump, + OperandInfo(TargetBytesPerWord, lir::Operand::Type::RegisterPair, &result)); + + p->thunks.default_.length = a->endBlock(false)->resolve(0, 0); + + p->thunks.default_.start + = finish(t, allocator, a, "default", p->thunks.default_.length); + } + + compileDefaultThunk + (t, allocator, &(p->thunks.defaultVirtual), "defaultVirtual", + compileVirtualMethodIndex, true); + + compileDefaultThunk + (t, allocator, &(p->thunks.defaultDynamic), "defaultDynamic", + linkDynamicMethodIndex, false); + + { + Context context(t); + avian::codegen::Assembler* a = context.assembler; + + a->saveFrame(TARGET_THREAD_STACK, TARGET_THREAD_IP); + + p->thunks.native.frameSavedOffset = a->length(); + + lir::RegisterPair thread(t->arch->thread()); + a->pushFrame(1, TargetBytesPerWord, lir::Operand::Type::RegisterPair, &thread); + + compileCall(t, &context, invokeNativeIndex); + + a->popFrameAndUpdateStackAndReturn(t->arch->alignFrameSize(1), + TARGET_THREAD_NEWSTACK); + + p->thunks.native.length = a->endBlock(false)->resolve(0, 0); + + p->thunks.native.start + = finish(t, allocator, a, "native", p->thunks.native.length); + } + + { + Context context(t); + avian::codegen::Assembler* a = context.assembler; + + a->saveFrame(TARGET_THREAD_STACK, TARGET_THREAD_IP); + + p->thunks.aioob.frameSavedOffset = a->length(); + + lir::RegisterPair thread(t->arch->thread()); + a->pushFrame(1, TargetBytesPerWord, lir::Operand::Type::RegisterPair, &thread); + + compileCall(t, &context, throwArrayIndexOutOfBoundsIndex); + + p->thunks.aioob.length = a->endBlock(false)->resolve(0, 0); + + p->thunks.aioob.start + = finish(t, allocator, a, "aioob", p->thunks.aioob.length); + } + + { + Context context(t); + avian::codegen::Assembler* a = context.assembler; + + a->saveFrame(TARGET_THREAD_STACK, TARGET_THREAD_IP); + + p->thunks.stackOverflow.frameSavedOffset = a->length(); + + lir::RegisterPair thread(t->arch->thread()); + a->pushFrame(1, TargetBytesPerWord, lir::Operand::Type::RegisterPair, &thread); + + compileCall(t, &context, throwStackOverflowIndex); + + p->thunks.stackOverflow.length = a->endBlock(false)->resolve(0, 0); + + p->thunks.stackOverflow.start = finish( + t, allocator, a, "stackOverflow", p->thunks.stackOverflow.length); + } + + { + { + Context context(t); + avian::codegen::Assembler* a = context.assembler; + + a->saveFrame(TARGET_THREAD_STACK, TARGET_THREAD_IP); + + p->thunks.table.frameSavedOffset = a->length(); + + compileCall(t, &context, dummyIndex, false); + + p->thunks.table.length = a->endBlock(false)->resolve(0, 0); + + p->thunks.table.start = static_cast(allocator->allocate( + p->thunks.table.length * ThunkCount, TargetBytesPerWord)); + } + + uint8_t* start = p->thunks.table.start; + +#define THUNK(s) \ + { \ + Context context(t); \ + avian::codegen::Assembler* a = context.assembler; \ + \ + a->saveFrame(TARGET_THREAD_STACK, TARGET_THREAD_IP); \ + \ + p->thunks.table.frameSavedOffset = a->length(); \ + \ + compileCall(t, &context, s##Index, false); \ + \ + expect(t, a->endBlock(false)->resolve(0, 0) <= p->thunks.table.length); \ + \ + a->setDestination(start); \ + a->write(); \ + \ + logCompile(t, start, p->thunks.table.length, 0, #s, 0); \ + \ + start += p->thunks.table.length; \ + } +#include "thunks.cpp" +#undef THUNK + } + + BootImage* image = p->bootImage; + + if (image) { + uint8_t* imageBase = p->codeAllocator.memory.begin(); + + image->thunks.default_ = thunkToThunk(p->thunks.default_, imageBase); + image->thunks.defaultVirtual + = thunkToThunk(p->thunks.defaultVirtual, imageBase); + image->thunks.native = thunkToThunk(p->thunks.native, imageBase); + image->thunks.aioob = thunkToThunk(p->thunks.aioob, imageBase); + image->thunks.stackOverflow + = thunkToThunk(p->thunks.stackOverflow, imageBase); + image->thunks.table = thunkToThunk(p->thunks.table, imageBase); + } +} + +uintptr_t aioobThunk(MyThread* t) +{ + return reinterpret_cast(processor(t)->thunks.aioob.start); +} + +uintptr_t stackOverflowThunk(MyThread* t) +{ + return reinterpret_cast(processor(t)->thunks.stackOverflow.start); +} +#endif // not AVIAN_AOT_ONLY + +MyProcessor* processor(MyThread* t) +{ + return static_cast(t->m->processor); +} + +uintptr_t defaultThunk(MyThread* t) +{ + return reinterpret_cast(processor(t)->thunks.default_.start); +} + +uintptr_t bootDefaultThunk(MyThread* t) +{ + return reinterpret_cast(processor(t)->bootThunks.default_.start); +} + +uintptr_t defaultVirtualThunk(MyThread* t) +{ + return reinterpret_cast(processor(t)->thunks.defaultVirtual.start); +} + +uintptr_t defaultDynamicThunk(MyThread* t) +{ + return reinterpret_cast(processor(t)->thunks.defaultDynamic.start); +} + +uintptr_t nativeThunk(MyThread* t) +{ + return reinterpret_cast(processor(t)->thunks.native.start); +} + +uintptr_t bootNativeThunk(MyThread* t) +{ + return reinterpret_cast(processor(t)->bootThunks.native.start); +} + +bool unresolved(MyThread* t, uintptr_t methodAddress) +{ + return methodAddress == defaultThunk(t) + or methodAddress == bootDefaultThunk(t); +} + +uintptr_t compileVirtualThunk(MyThread* t, + unsigned index, + unsigned* size, + uintptr_t thunk, + const char* baseName) +{ + Context context(t); + avian::codegen::Assembler* a = context.assembler; + + avian::codegen::ResolvedPromise indexPromise(index); + lir::Constant indexConstant(&indexPromise); + lir::RegisterPair indexRegister(t->arch->virtualCallIndex()); + a->apply( + lir::Move, + OperandInfo(TargetBytesPerWord, lir::Operand::Type::Constant, &indexConstant), + OperandInfo(TargetBytesPerWord, lir::Operand::Type::RegisterPair, &indexRegister)); + + avian::codegen::ResolvedPromise promise(thunk); + lir::Constant target(&promise); + a->apply(lir::Jump, + OperandInfo(TargetBytesPerWord, lir::Operand::Type::Constant, &target)); + + *size = a->endBlock(false)->resolve(0, 0); + + uint8_t* start = static_cast( + codeAllocator(t)->allocate(*size, TargetBytesPerWord)); + + a->setDestination(start); + a->write(); + + const size_t virtualThunkBaseNameLength = strlen(baseName); + const size_t maxIntStringLength = 10; + + THREAD_RUNTIME_ARRAY(t, + char, + virtualThunkName, + virtualThunkBaseNameLength + maxIntStringLength); + + sprintf(RUNTIME_ARRAY_BODY(virtualThunkName), + "%s%d", + baseName, + index); + + logCompile(t, start, *size, 0, RUNTIME_ARRAY_BODY(virtualThunkName), 0); + + return reinterpret_cast(start); +} + +uintptr_t virtualThunk(MyThread* t, unsigned index) +{ + ACQUIRE(t, t->m->classLock); + + GcWordArray* oldArray = compileRoots(t)->virtualThunks(); + if (oldArray == 0 or oldArray->length() <= index * 2) { + GcWordArray* newArray = makeWordArray(t, nextPowerOfTwo((index + 1) * 2)); + if (compileRoots(t)->virtualThunks()) { + memcpy(newArray->body().begin(), + oldArray->body().begin(), + oldArray->length() * BytesPerWord); + } + compileRoots(t)->setVirtualThunks(t, newArray); + oldArray = newArray; + } + + if (oldArray->body()[index * 2] == 0) { + unsigned size; + uintptr_t thunk = compileVirtualThunk(t, index, &size, defaultVirtualThunk(t), "virtualThunk"); + oldArray->body()[index * 2] = thunk; + oldArray->body()[(index * 2) + 1] = size; + } + + return oldArray->body()[index * 2]; +} + +void compile(MyThread* t, + FixedAllocator* allocator UNUSED, + BootContext* bootContext, + GcMethod* method) +{ + PROTECT(t, method); + + if (bootContext == 0 and method->flags() & ACC_STATIC) { + initClass(t, method->class_()); + } + + if (methodAddress(t, method) != defaultThunk(t)) { + return; + } + + assertT(t, (method->flags() & ACC_NATIVE) == 0); + +#ifdef AVIAN_AOT_ONLY + abort(t); +#else + + // We must avoid acquiring any locks until after the first pass of + // compilation, since this pass may trigger classloading operations + // involving application classloaders and thus the potential for + // deadlock. To make this safe, we use a private clone of the + // method so that we won't be confused if another thread updates the + // original while we're working. + + GcMethod* clone = methodClone(t, method); + + loadMemoryBarrier(); + + if (methodAddress(t, method) != defaultThunk(t)) { + return; + } + + PROTECT(t, clone); + + Context context(t, bootContext, clone); + compile(t, &context); + + { + GcExceptionHandlerTable* ehTable = cast( + t, clone->code()->exceptionHandlerTable()); + + if (ehTable) { + PROTECT(t, ehTable); + + // resolve all exception handler catch types before we acquire + // the class lock: + for (unsigned i = 0; i < ehTable->length(); ++i) { + uint64_t handler = ehTable->body()[i]; + if (exceptionHandlerCatchType(handler)) { + resolveClassInPool(t, clone, exceptionHandlerCatchType(handler) - 1); + } + } + } + } + + ACQUIRE(t, t->m->classLock); + + if (methodAddress(t, method) != defaultThunk(t)) { + return; + } + + finish(t, allocator, &context); + + if (DebugMethodTree) { + fprintf(stderr, + "insert method at %p\n", + reinterpret_cast(methodCompiled(t, clone))); + } + + // We can't update the MethodCode field on the original method + // before it is placed into the method tree, since another thread + // might call the method, from which stack unwinding would fail + // (since there is not yet an entry in the method tree). However, + // we can't insert the original method into the tree before updating + // the MethodCode field on it since we rely on that field to + // determine its position in the tree. Therefore, we insert the + // clone in its place. Later, we'll replace the clone with the + // original to save memory. + + GcTreeNode* newTree = treeInsert(t, + &(context.zone), + compileRoots(t)->methodTree(), + methodCompiled(t, clone), + clone, + compileRoots(t)->methodTreeSentinal(), + compareIpToMethodBounds); + // sequence point, for gc (don't recombine statements) + compileRoots(t)->setMethodTree(t, newTree); + + storeStoreMemoryBarrier(); + + method->setCode(t, clone->code()); + + if (methodVirtual(t, method)) { + method->class_()->vtable()[method->offset()] + = reinterpret_cast(methodCompiled(t, clone)); + } + + // we've compiled the method and inserted it into the tree without + // error, so we ensure that the executable area not be deallocated + // when we dispose of the context: + context.executableAllocator = 0; + + treeUpdate(t, + compileRoots(t)->methodTree(), + methodCompiled(t, clone), + method, + compileRoots(t)->methodTreeSentinal(), + compareIpToMethodBounds); +#endif // not AVIAN_AOT_ONLY +} + +GcCompileRoots* compileRoots(Thread* t) +{ + return processor(static_cast(t))->roots; +} + +avian::util::FixedAllocator* codeAllocator(MyThread* t) +{ + return &(processor(t)->codeAllocator); +} + +Allocator* allocator(MyThread* t) +{ + return processor(t)->allocator; +} + +} // namespace local + +} // namespace + +namespace vm { + +Processor* makeProcessor(System* system, + Allocator* allocator, + const char* crashDumpDirectory, + bool useNativeFeatures) +{ + return new (allocator->allocate(sizeof(local::MyProcessor))) + local::MyProcessor( + system, allocator, crashDumpDirectory, useNativeFeatures); +} + +} // namespace vm diff --git a/sgx-jvm/avian/src/continuations-x86.S b/sgx-jvm/avian/src/continuations-x86.S new file mode 100644 index 0000000000..3304eddfc1 --- /dev/null +++ b/sgx-jvm/avian/src/continuations-x86.S @@ -0,0 +1,184 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#ifdef __x86_64__ + +#define CONTINUATION_NEXT 8 +#define CONTINUATION_ADDRESS 32 +#define CONTINUATION_RETURN_ADDRESS_OFFSET 40 +#define CONTINUATION_FRAME_POINTER_OFFSET 48 +#define CONTINUATION_LENGTH 56 +#define CONTINUATION_BODY 64 + + // call the next continuation, if any + movq TARGET_THREAD_CONTINUATION(%rbx),%rcx + cmpq $0,%rcx + je LOCAL(vmInvoke_exit) + + // allocate a frame of size (continuation.length * BYTES_PER_WORD) + // + CALLEE_SAVED_REGISTER_FOOTPRINT + movq CONTINUATION_LENGTH(%rcx),%rsi + shlq $3,%rsi + subq %rsi,%rsp + subq $CALLEE_SAVED_REGISTER_FOOTPRINT,%rsp + + // copy the continuation body into the frame + leaq CONTINUATION_BODY(%rcx),%rdi + + movq $0,%r9 + jmp LOCAL(vmInvoke_continuationTest) + +LOCAL(vmInvoke_continuationLoop): + movq (%rdi,%r9,1),%r8 + movq %r8,(%rsp,%r9,1) + addq $8,%r9 + +LOCAL(vmInvoke_continuationTest): + cmpq %rsi,%r9 + jb LOCAL(vmInvoke_continuationLoop) + + // set the return address to vmInvoke_returnAddress + movq CONTINUATION_RETURN_ADDRESS_OFFSET(%rcx),%rdi +#if defined __MINGW32__ || defined __CYGWIN32__ + leaq GLOBAL(vmInvoke_returnAddress)(%rip),%r10 +#else + movq GLOBAL(vmInvoke_returnAddress)@GOTPCREL(%rip),%r10 +#endif + movq %r10,(%rsp,%rdi,1) + +#ifdef AVIAN_USE_FRAME_POINTER + // save the current base pointer in the frame and update it + movq CONTINUATION_FRAME_POINTER_OFFSET(%rcx),%rdi + movq %rbp,(%rsp,%rdi,1) + addq %rsp,%rdi + movq %rdi,%rbp +#endif + + // consume the continuation + movq CONTINUATION_NEXT(%rcx),%rdi + movq %rdi,TARGET_THREAD_CONTINUATION(%rbx) + + // call the continuation unless we're handling an exception + movq TARGET_THREAD_EXCEPTION(%rbx),%rsi + cmpq $0,%rsi + jne LOCAL(vmInvoke_handleException) + jmp *CONTINUATION_ADDRESS(%rcx) + +LOCAL(vmInvoke_handleException): + // we're handling an exception - call the exception handler instead + movq $0,TARGET_THREAD_EXCEPTION(%rbx) + movq TARGET_THREAD_EXCEPTIONSTACKADJUSTMENT(%rbx),%rdi + subq %rdi,%rsp + movq TARGET_THREAD_EXCEPTIONOFFSET(%rbx),%rdi + movq %rsi,(%rsp,%rdi,1) + + jmp *TARGET_THREAD_EXCEPTIONHANDLER(%rbx) + +LOCAL(vmInvoke_exit): + +#elif defined __i386__ + +#define CONTINUATION_NEXT 4 +#define CONTINUATION_ADDRESS 16 +#define CONTINUATION_RETURN_ADDRESS_OFFSET 20 +#define CONTINUATION_FRAME_POINTER_OFFSET 24 +#define CONTINUATION_LENGTH 28 +#define CONTINUATION_BODY 32 + +#ifdef AVIAN_USE_FRAME_POINTER +# define CONTINUATION_ALIGNMENT_PADDING 8 +#else +# define CONTINUATION_ALIGNMENT_PADDING 12 +#endif + + // call the next continuation, if any + movl TARGET_THREAD_CONTINUATION(%ebx),%ecx + cmpl $0,%ecx + je LOCAL(vmInvoke_exit) + + // allocate a frame of size (continuation.length * BYTES_PER_WORD), + // plus stack alignment padding + movl CONTINUATION_LENGTH(%ecx),%esi + shll $2,%esi + leal CONTINUATION_ALIGNMENT_PADDING(%esi),%esi + subl %esi,%esp + + // copy the continuation body into the frame + leal CONTINUATION_BODY(%ecx),%edi + + push %eax + push %edx + + movl $0,%edx + jmp LOCAL(vmInvoke_continuationTest) + +LOCAL(vmInvoke_continuationLoop): + movl (%edi,%edx,1),%eax + movl %eax,8(%esp,%edx,1) + addl $4,%edx + +LOCAL(vmInvoke_continuationTest): + cmpl %esi,%edx + jb LOCAL(vmInvoke_continuationLoop) + + pop %edx + pop %eax + + // set the return address to vmInvoke_returnAddress + movl CONTINUATION_RETURN_ADDRESS_OFFSET(%ecx),%edi +#if defined __MINGW32__ || defined __CYGWIN32__ + movl $GLOBAL(vmInvoke_returnAddress),%esi +#else + call LOCAL(getPC) +# if defined __APPLE__ +LOCAL(vmInvoke_offset): + leal GLOBAL(vmInvoke_returnAddress)-LOCAL(vmInvoke_offset)(%esi),%esi +# else + addl $_GLOBAL_OFFSET_TABLE_,%esi + movl GLOBAL(vmInvoke_returnAddress)@GOT(%esi),%esi +# endif +#endif + movl %esi,(%esp,%edi,1) + +#ifdef AVIAN_USE_FRAME_POINTER + // save the current base pointer in the frame and update it + movl CONTINUATION_FRAME_POINTER_OFFSET(%ecx),%edi + movl %ebp,(%esp,%edi,1) + addl %esp,%edi + movl %edi,%ebp +#endif + + // consume the continuation + movl CONTINUATION_NEXT(%ecx),%edi + movl %edi,TARGET_THREAD_CONTINUATION(%ebx) + + // call the continuation unless we're handling an exception + movl TARGET_THREAD_EXCEPTION(%ebx),%esi + cmpl $0,%esi + jne LOCAL(vmInvoke_handleException) + + jmp *CONTINUATION_ADDRESS(%ecx) + +LOCAL(vmInvoke_handleException): + // we're handling an exception - call the exception handler instead + movl $0,TARGET_THREAD_EXCEPTION(%ebx) + movl TARGET_THREAD_EXCEPTIONSTACKADJUSTMENT(%ebx),%edi + subl %edi,%esp + movl TARGET_THREAD_EXCEPTIONOFFSET(%ebx),%edi + movl %esi,(%esp,%edi,1) + + jmp *TARGET_THREAD_EXCEPTIONHANDLER(%ebx) + +LOCAL(vmInvoke_exit): + +#else +# error unsupported architecture +#endif + diff --git a/sgx-jvm/avian/src/debug-util.cpp b/sgx-jvm/avian/src/debug-util.cpp new file mode 100644 index 0000000000..0cab3e58e8 --- /dev/null +++ b/sgx-jvm/avian/src/debug-util.cpp @@ -0,0 +1,612 @@ +/* Copyright (c) 2008-2013, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#include + +#include "debug-util.h" + +namespace avian { +namespace jvm { +namespace debug { + +uint16_t read16(uint8_t* code, unsigned& ip) +{ + uint16_t a = code[ip++]; + uint16_t b = code[ip++]; + return (a << 8) | b; +} + +uint32_t read32(uint8_t* code, unsigned& ip) +{ + uint32_t b = code[ip++]; + uint32_t a = code[ip++]; + uint32_t c = code[ip++]; + uint32_t d = code[ip++]; + return (a << 24) | (b << 16) | (c << 8) | d; +} + +using namespace vm; + +int printInstruction(uint8_t* code, unsigned& ip, const char* prefix) +{ + unsigned startIp = ip; + + uint8_t instr = code[ip++]; + switch (instr) { + case aaload: + return fprintf(stderr, "aaload"); + case aastore: + return fprintf(stderr, "aastore"); + + case aconst_null: + return fprintf(stderr, "aconst_null"); + + case aload: + return fprintf(stderr, "aload %2d", code[ip++]); + case aload_0: + return fprintf(stderr, "aload_0"); + case aload_1: + return fprintf(stderr, "aload_1"); + case aload_2: + return fprintf(stderr, "aload_2"); + case aload_3: + return fprintf(stderr, "aload_3"); + + case anewarray: + return fprintf(stderr, "anewarray %4d", read16(code, ip)); + case areturn: + return fprintf(stderr, "areturn"); + case arraylength: + return fprintf(stderr, "arraylength"); + + case astore: + return fprintf(stderr, "astore %2d", code[ip++]); + case astore_0: + return fprintf(stderr, "astore_0"); + case astore_1: + return fprintf(stderr, "astore_1"); + case astore_2: + return fprintf(stderr, "astore_2"); + case astore_3: + return fprintf(stderr, "astore_3"); + + case athrow: + return fprintf(stderr, "athrow"); + case baload: + return fprintf(stderr, "baload"); + case bastore: + return fprintf(stderr, "bastore"); + + case bipush: + return fprintf(stderr, "bipush %2d", code[ip++]); + case caload: + return fprintf(stderr, "caload"); + case castore: + return fprintf(stderr, "castore"); + case checkcast: + return fprintf(stderr, "checkcast %4d", read16(code, ip)); + case d2f: + return fprintf(stderr, "d2f"); + case d2i: + return fprintf(stderr, "d2i"); + case d2l: + return fprintf(stderr, "d2l"); + case dadd: + return fprintf(stderr, "dadd"); + case daload: + return fprintf(stderr, "daload"); + case dastore: + return fprintf(stderr, "dastore"); + case dcmpg: + return fprintf(stderr, "dcmpg"); + case dcmpl: + return fprintf(stderr, "dcmpl"); + case dconst_0: + return fprintf(stderr, "dconst_0"); + case dconst_1: + return fprintf(stderr, "dconst_1"); + case ddiv: + return fprintf(stderr, "ddiv"); + case dmul: + return fprintf(stderr, "dmul"); + case dneg: + return fprintf(stderr, "dneg"); + case vm::drem: + return fprintf(stderr, "drem"); + case dsub: + return fprintf(stderr, "dsub"); + case vm::dup: + return fprintf(stderr, "dup"); + case dup_x1: + return fprintf(stderr, "dup_x1"); + case dup_x2: + return fprintf(stderr, "dup_x2"); + case vm::dup2: + return fprintf(stderr, "dup2"); + case dup2_x1: + return fprintf(stderr, "dup2_x1"); + case dup2_x2: + return fprintf(stderr, "dup2_x2"); + case f2d: + return fprintf(stderr, "f2d"); + case f2i: + return fprintf(stderr, "f2i"); + case f2l: + return fprintf(stderr, "f2l"); + case fadd: + return fprintf(stderr, "fadd"); + case faload: + return fprintf(stderr, "faload"); + case fastore: + return fprintf(stderr, "fastore"); + case fcmpg: + return fprintf(stderr, "fcmpg"); + case fcmpl: + return fprintf(stderr, "fcmpl"); + case fconst_0: + return fprintf(stderr, "fconst_0"); + case fconst_1: + return fprintf(stderr, "fconst_1"); + case fconst_2: + return fprintf(stderr, "fconst_2"); + case fdiv: + return fprintf(stderr, "fdiv"); + case fmul: + return fprintf(stderr, "fmul"); + case fneg: + return fprintf(stderr, "fneg"); + case frem: + return fprintf(stderr, "frem"); + case fsub: + return fprintf(stderr, "fsub"); + + case getfield: + return fprintf(stderr, "getfield %4d", read16(code, ip)); + case getstatic: + return fprintf(stderr, "getstatic %4d", read16(code, ip)); + case goto_: { + int16_t offset = read16(code, ip); + return fprintf(stderr, "goto %4d", offset + ip - 3); + } + case goto_w: { + int32_t offset = read32(code, ip); + return fprintf(stderr, "goto_w %08x", offset + ip - 5); + } + + case i2b: + return fprintf(stderr, "i2b"); + case i2c: + return fprintf(stderr, "i2c"); + case i2d: + return fprintf(stderr, "i2d"); + case i2f: + return fprintf(stderr, "i2f"); + case i2l: + return fprintf(stderr, "i2l"); + case i2s: + return fprintf(stderr, "i2s"); + case iadd: + return fprintf(stderr, "iadd"); + case iaload: + return fprintf(stderr, "iaload"); + case iand: + return fprintf(stderr, "iand"); + case iastore: + return fprintf(stderr, "iastore"); + case iconst_m1: + return fprintf(stderr, "iconst_m1"); + case iconst_0: + return fprintf(stderr, "iconst_0"); + case iconst_1: + return fprintf(stderr, "iconst_1"); + case iconst_2: + return fprintf(stderr, "iconst_2"); + case iconst_3: + return fprintf(stderr, "iconst_3"); + case iconst_4: + return fprintf(stderr, "iconst_4"); + case iconst_5: + return fprintf(stderr, "iconst_5"); + case idiv: + return fprintf(stderr, "idiv"); + + case if_acmpeq: { + int16_t offset = read16(code, ip); + return fprintf(stderr, "if_acmpeq %4d", offset + ip - 3); + } + case if_acmpne: { + int16_t offset = read16(code, ip); + return fprintf(stderr, "if_acmpne %4d", offset + ip - 3); + } + case if_icmpeq: { + int16_t offset = read16(code, ip); + return fprintf(stderr, "if_icmpeq %4d", offset + ip - 3); + } + case if_icmpne: { + int16_t offset = read16(code, ip); + return fprintf(stderr, "if_icmpne %4d", offset + ip - 3); + } + + case if_icmpgt: { + int16_t offset = read16(code, ip); + return fprintf(stderr, "if_icmpgt %4d", offset + ip - 3); + } + case if_icmpge: { + int16_t offset = read16(code, ip); + return fprintf(stderr, "if_icmpge %4d", offset + ip - 3); + } + case if_icmplt: { + int16_t offset = read16(code, ip); + return fprintf(stderr, "if_icmplt %4d", offset + ip - 3); + } + case if_icmple: { + int16_t offset = read16(code, ip); + return fprintf(stderr, "if_icmple %4d", offset + ip - 3); + } + + case ifeq: { + int16_t offset = read16(code, ip); + return fprintf(stderr, "ifeq %4d", offset + ip - 3); + } + case ifne: { + int16_t offset = read16(code, ip); + return fprintf(stderr, "ifne %4d", offset + ip - 3); + } + case ifgt: { + int16_t offset = read16(code, ip); + return fprintf(stderr, "ifgt %4d", offset + ip - 3); + } + case ifge: { + int16_t offset = read16(code, ip); + return fprintf(stderr, "ifge %4d", offset + ip - 3); + } + case iflt: { + int16_t offset = read16(code, ip); + return fprintf(stderr, "iflt %4d", offset + ip - 3); + } + case ifle: { + int16_t offset = read16(code, ip); + return fprintf(stderr, "ifle %4d", offset + ip - 3); + } + + case ifnonnull: { + int16_t offset = read16(code, ip); + return fprintf(stderr, "ifnonnull %4d", offset + ip - 3); + } + case ifnull: { + int16_t offset = read16(code, ip); + return fprintf(stderr, "ifnull %4d", offset + ip - 3); + } + + case iinc: { + uint8_t a = code[ip++]; + uint8_t b = code[ip++]; + return fprintf(stderr, "iinc %2d %2d", a, b); + } + + case iload: + return fprintf(stderr, "iload %2d", code[ip++]); + case fload: + return fprintf(stderr, "fload %2d", code[ip++]); + + case iload_0: + return fprintf(stderr, "iload_0"); + case fload_0: + return fprintf(stderr, "fload_0"); + case iload_1: + return fprintf(stderr, "iload_1"); + case fload_1: + return fprintf(stderr, "fload_1"); + + case iload_2: + return fprintf(stderr, "iload_2"); + case fload_2: + return fprintf(stderr, "fload_2"); + case iload_3: + return fprintf(stderr, "iload_3"); + case fload_3: + return fprintf(stderr, "fload_3"); + + case imul: + return fprintf(stderr, "imul"); + case ineg: + return fprintf(stderr, "ineg"); + + case instanceof: + return fprintf(stderr, "instanceof %4d", read16(code, ip)); + case invokeinterface: + return fprintf(stderr, "invokeinterface %4d", read16(code, ip)); + case invokespecial: + return fprintf(stderr, "invokespecial %4d", read16(code, ip)); + case invokestatic: + return fprintf(stderr, "invokestatic %4d", read16(code, ip)); + case invokevirtual: + return fprintf(stderr, "invokevirtual %4d", read16(code, ip)); + + case ior: + return fprintf(stderr, "ior"); + case irem: + return fprintf(stderr, "irem"); + case ireturn: + return fprintf(stderr, "ireturn"); + case freturn: + return fprintf(stderr, "freturn"); + case ishl: + return fprintf(stderr, "ishl"); + case ishr: + return fprintf(stderr, "ishr"); + + case istore: + return fprintf(stderr, "istore %2d", code[ip++]); + case fstore: + return fprintf(stderr, "fstore %2d", code[ip++]); + + case istore_0: + return fprintf(stderr, "istore_0"); + case fstore_0: + return fprintf(stderr, "fstore_0"); + case istore_1: + return fprintf(stderr, "istore_1"); + case fstore_1: + return fprintf(stderr, "fstore_1"); + case istore_2: + return fprintf(stderr, "istore_2"); + case fstore_2: + return fprintf(stderr, "fstore_2"); + case istore_3: + return fprintf(stderr, "istore_3"); + case fstore_3: + return fprintf(stderr, "fstore_3"); + + case isub: + return fprintf(stderr, "isub"); + case iushr: + return fprintf(stderr, "iushr"); + case ixor: + return fprintf(stderr, "ixor"); + + case jsr: + return fprintf(stderr, "jsr %4d", read16(code, ip) + startIp); + case jsr_w: + return fprintf(stderr, "jsr_w %08x", read32(code, ip) + startIp); + + case l2d: + return fprintf(stderr, "l2d"); + case l2f: + return fprintf(stderr, "l2f"); + case l2i: + return fprintf(stderr, "l2i"); + case ladd: + return fprintf(stderr, "ladd"); + case laload: + return fprintf(stderr, "laload"); + + case land: + return fprintf(stderr, "land"); + case lastore: + return fprintf(stderr, "lastore"); + + case lcmp: + return fprintf(stderr, "lcmp"); + case lconst_0: + return fprintf(stderr, "lconst_0"); + case lconst_1: + return fprintf(stderr, "lconst_1"); + + case ldc: + return fprintf(stderr, "ldc %4d", read16(code, ip)); + case ldc_w: + return fprintf(stderr, "ldc_w %08x", read32(code, ip)); + case ldc2_w: + return fprintf(stderr, "ldc2_w %4d", read16(code, ip)); + + case ldiv_: + return fprintf(stderr, "ldiv_"); + + case lload: + return fprintf(stderr, "lload %2d", code[ip++]); + case dload: + return fprintf(stderr, "dload %2d", code[ip++]); + + case lload_0: + return fprintf(stderr, "lload_0"); + case dload_0: + return fprintf(stderr, "dload_0"); + case lload_1: + return fprintf(stderr, "lload_1"); + case dload_1: + return fprintf(stderr, "dload_1"); + case lload_2: + return fprintf(stderr, "lload_2"); + case dload_2: + return fprintf(stderr, "dload_2"); + case lload_3: + return fprintf(stderr, "lload_3"); + case dload_3: + return fprintf(stderr, "dload_3"); + + case lmul: + return fprintf(stderr, "lmul"); + case lneg: + return fprintf(stderr, "lneg"); + + case lookupswitch: { + while (ip & 0x3) { + ip++; + } + int32_t default_ = read32(code, ip) + startIp; + int32_t pairCount = read32(code, ip); + fprintf( + stderr, "lookupswitch default: %d pairCount: %d", default_, pairCount); + + for (int i = 0; i < pairCount; i++) { + int32_t k = read32(code, ip); + int32_t d = read32(code, ip) + startIp; + fprintf(stderr, "\n%s key: %2d dest: %d", prefix, k, d); + } + fprintf(stderr, "\n"); + fflush(stderr); + return 0; + } + + case lor: + return fprintf(stderr, "lor"); + case lrem: + return fprintf(stderr, "lrem"); + case lreturn: + return fprintf(stderr, "lreturn"); + case dreturn: + return fprintf(stderr, "dreturn"); + case lshl: + return fprintf(stderr, "lshl"); + case lshr: + return fprintf(stderr, "lshr"); + + case lstore: + return fprintf(stderr, "lstore %2d", code[ip++]); + case dstore: + return fprintf(stderr, "dstore %2d", code[ip++]); + + case lstore_0: + return fprintf(stderr, "lstore_0"); + case dstore_0: + return fprintf(stderr, "dstore_0"); + case lstore_1: + return fprintf(stderr, "lstore_1"); + case dstore_1: + return fprintf(stderr, "dstore_1"); + case lstore_2: + return fprintf(stderr, "lstore_2"); + case dstore_2: + return fprintf(stderr, "dstore_2"); + case lstore_3: + return fprintf(stderr, "lstore_3"); + case dstore_3: + return fprintf(stderr, "dstore_3"); + + case lsub: + return fprintf(stderr, "lsub"); + case lushr: + return fprintf(stderr, "lushr"); + case lxor: + return fprintf(stderr, "lxor"); + + case monitorenter: + return fprintf(stderr, "monitorenter"); + case monitorexit: + return fprintf(stderr, "monitorexit"); + + case multianewarray: { + unsigned type = read16(code, ip); + return fprintf(stderr, "multianewarray %4d %2d", type, code[ip++]); + } + + case new_: + return fprintf(stderr, "new %4d", read16(code, ip)); + + case newarray: + return fprintf(stderr, "newarray %2d", code[ip++]); + + case nop: + return fprintf(stderr, "nop"); + case pop_: + return fprintf(stderr, "pop"); + case pop2: + return fprintf(stderr, "pop2"); + + case putfield: + return fprintf(stderr, "putfield %4d", read16(code, ip)); + case putstatic: + return fprintf(stderr, "putstatic %4d", read16(code, ip)); + + case ret: + return fprintf(stderr, "ret %2d", code[ip++]); + + case return_: + return fprintf(stderr, "return_"); + case saload: + return fprintf(stderr, "saload"); + case sastore: + return fprintf(stderr, "sastore"); + + case sipush: + return fprintf(stderr, "sipush %4d", read16(code, ip)); + + case swap: + return fprintf(stderr, "swap"); + + case tableswitch: { + while (ip & 0x3) { + ip++; + } + int32_t default_ = read32(code, ip) + startIp; + int32_t bottom = read32(code, ip); + int32_t top = read32(code, ip); + fprintf(stderr, + "tableswitch default: %d bottom: %d top: %d", + default_, + bottom, + top); + + for (int i = 0; i < top - bottom + 1; i++) { + int32_t d = read32(code, ip) + startIp; + fprintf(stderr, "%s key: %d dest: %d", prefix, i + bottom, d); + } + return 0; + } + + case wide: { + switch (code[ip++]) { + case aload: + return fprintf(stderr, "wide aload %4d", read16(code, ip)); + + case astore: + return fprintf(stderr, "wide astore %4d", read16(code, ip)); + case iinc: + fprintf(stderr, "wide iinc %4d %4d", read16(code, ip), read16(code, ip)); + case iload: + return fprintf(stderr, "wide iload %4d", read16(code, ip)); + case istore: + return fprintf(stderr, "wide istore %4d", read16(code, ip)); + case lload: + return fprintf(stderr, "wide lload %4d", read16(code, ip)); + case lstore: + return fprintf(stderr, "wide lstore %4d", read16(code, ip)); + case ret: + return fprintf(stderr, "wide ret %4d", read16(code, ip)); + + default: { + fprintf( + stderr, "unknown wide instruction %2d %4d", instr, read16(code, ip)); + } + } + } + + default: { + return fprintf(stderr, "unknown instruction %2d", instr); + } + } + return ip; +} + +void disassembleCode(const char* prefix, uint8_t* code, unsigned length) +{ + unsigned ip = 0; + + while (ip < length) { + fprintf(stderr, "%s%x:\t", prefix, ip); + printInstruction(code, ip, prefix); + fprintf(stderr, "\n"); + } +} + +} // namespace debug +} // namespace jvm +} // namespace avian diff --git a/sgx-jvm/avian/src/debug-util.h b/sgx-jvm/avian/src/debug-util.h new file mode 100644 index 0000000000..bb981baa10 --- /dev/null +++ b/sgx-jvm/avian/src/debug-util.h @@ -0,0 +1,24 @@ +/* Copyright (c) 2008-2013, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#include + +namespace avian { +namespace jvm { +namespace debug { + +// print out a single instruction (no newline) +// returns number of characters printed +int printInstruction(uint8_t* code, unsigned& ip, const char* prefix = ""); +void disassembleCode(const char* prefix, uint8_t* code, unsigned length); + +} // namespace debug +} // namespace jvm +} // namespace avian diff --git a/sgx-jvm/avian/src/embed.cpp b/sgx-jvm/avian/src/embed.cpp new file mode 100644 index 0000000000..60687d899e --- /dev/null +++ b/sgx-jvm/avian/src/embed.cpp @@ -0,0 +1,146 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#include +#include +#include +#include +#include +#include + +#include "avian/embed.h" + +#ifdef __x86_64__ +#define BINARY_LOADER(x) _binary_loader_##x +#else +#define BINARY_LOADER(x) binary_loader_##x +#endif + +extern "C" const uint8_t BINARY_LOADER(start)[]; +extern "C" const uint8_t BINARY_LOADER(end)[]; + +__declspec(noreturn) void printUsage(const wchar_t* executableName) +{ + wprintf(L"Usage: %s destination.exe classes.jar package.Main\n", + executableName); + exit(0); +} + +void writeDestinationFile(const wchar_t* filename) +{ + if (FILE* file = _wfopen(filename, L"wb")) { + size_t count = BINARY_LOADER(end) - BINARY_LOADER(start); + if (count == fwrite(BINARY_LOADER(start), + sizeof(BINARY_LOADER(start)[0]), + count, + file)) { + fclose(file); + return; + } + } + + fprintf(stderr, "Unable to write to destination file\n"); + exit(EXIT_FAILURE); +} + +void readFile(std::vector* jarFile, const wchar_t* fileName) +{ + if (FILE* file = _wfopen(fileName, L"rb")) { + fseek(file, 0, SEEK_END); + jarFile->resize(ftell(file)); + fseek(file, 0, SEEK_SET); + fread(&jarFile->at(0), 1, jarFile->size(), file); + fclose(file); + } +} + +bool mkStringSection(std::vector* stringSection, + const std::vector& strings, + int first, + int last) +{ + stringSection->clear(); + for (int i = first; i <= last; ++i) { + const std::wstring& s = strings.at(i); + stringSection->push_back(s.size()); + stringSection->insert(stringSection->end(), s.begin(), s.end()); + } + + // pad to 16 entries + for (int i = last - first; i < 15; ++i) + stringSection->push_back(0); + + return stringSection->size() > 16; +} + +void writeStringResources(HANDLE hDest, + const std::vector& strings) +{ + for (unsigned i = 0; i < strings.size(); i += 16) { + std::vector stringSection; + + if (mkStringSection(&stringSection, + strings, + i, + std::min(i + 15, strings.size() - 1))) + UpdateResourceW(hDest, + reinterpret_cast(RT_STRING), + reinterpret_cast(MAKEINTRESOURCE((i >> 4) + 1)), + LANG_NEUTRAL, + &stringSection.at(0), + sizeof(wchar_t) * stringSection.size()); + } +} + +int wmain(int argc, wchar_t* argv[]) +{ + if (argc != 4) + printUsage(argv[0]); + + const wchar_t* destinationName = argv[1]; + const wchar_t* classesName = argv[2]; + const wchar_t* mainClassName = argv[3]; + + writeDestinationFile(destinationName); + + if (HANDLE hDest = BeginUpdateResourceW(destinationName, TRUE)) { + std::vector strings; + strings.resize(RESID_MAIN_CLASS + 1); + strings.at(RESID_MAIN_CLASS) = mainClassName; + + writeStringResources(hDest, strings); + + std::vector jarFile; + readFile(&jarFile, classesName); + UpdateResourceW(hDest, + reinterpret_cast(RT_RCDATA), + RESID_BOOT_JAR, + LANG_NEUTRAL, + &jarFile.at(0), + jarFile.size()); + + EndUpdateResource(hDest, FALSE); + } + + return 0; +} + +#ifndef _MSC_VER +extern "C" int _CRT_glob; +extern "C" void __wgetmainargs(int*, wchar_t***, wchar_t***, int, int*); + +int main() +{ + wchar_t** enpv, **argv; + int argc, si = 0; + __wgetmainargs(&argc, &argv, &enpv, _CRT_glob, &si); + return wmain(argc, argv); +} +#endif diff --git a/sgx-jvm/avian/src/embedded-loader.cpp b/sgx-jvm/avian/src/embedded-loader.cpp new file mode 100644 index 0000000000..7d1df49e47 --- /dev/null +++ b/sgx-jvm/avian/src/embedded-loader.cpp @@ -0,0 +1,104 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#include +#include +#include + +#include "avian/embed.h" +#include "avian/common.h" +#include "jni.h" + +extern "C" { +// since we aren't linking against libstdc++, we must implement this +// ourselves: +void __cxa_pure_virtual(void) +{ + abort(); +} + +AVIAN_EXPORT const uint8_t* bootJar(unsigned* size) +{ + if (HRSRC hResInfo = FindResourceW( + NULL, RESID_BOOT_JAR, reinterpret_cast(RT_RCDATA))) { + if (HGLOBAL hRes = LoadResource(NULL, hResInfo)) { + *size = SizeofResource(NULL, hResInfo); + return (const uint8_t*)LockResource(hRes); + } + } + + fprintf(stderr, "boot.jar resource not found\n"); + + *size = 0; + return NULL; +} +} // extern "C" + +static void getMainClass(char* pName, int maxLen) +{ + if (0 == LoadString(NULL, RESID_MAIN_CLASS, pName, maxLen)) { + fprintf(stderr, "Main class not specified\n"); + strcpy(pName, "Main"); + } +} + +int main(int ac, const char** av) +{ + JavaVMInitArgs vmArgs; + vmArgs.version = JNI_VERSION_1_2; + vmArgs.nOptions = 1; + vmArgs.ignoreUnrecognized = JNI_TRUE; + + JavaVMOption options[1]; + vmArgs.options = options; + + options[0].optionString = const_cast("-Xbootclasspath:[bootJar]"); + + JavaVM* vm; + void* env; + JNI_CreateJavaVM(&vm, &env, &vmArgs); + JNIEnv* e = static_cast(env); + + char mainClass[256]; + getMainClass(mainClass, sizeof(mainClass)); + + jclass c = e->FindClass(mainClass); + if (not e->ExceptionCheck()) { + jmethodID m = e->GetStaticMethodID(c, "main", "([Ljava/lang/String;)V"); + if (not e->ExceptionCheck()) { + jclass stringClass = e->FindClass("java/lang/String"); + if (not e->ExceptionCheck()) { + jobjectArray a = e->NewObjectArray(ac - 1, stringClass, 0); + if (not e->ExceptionCheck()) { + for (int i = 1; i < ac; ++i) { + e->SetObjectArrayElement(a, i - 1, e->NewStringUTF(av[i])); + } + + e->CallStaticVoidMethod(c, m, a); + } else + fprintf(stderr, "Couldn't create array\n"); + } else + fprintf(stderr, "java.lang.String not found\n"); + } else + fprintf(stderr, "main method not found\n"); + } else + fprintf(stderr, "Main class not found\n"); + + int exitCode = 0; + if (e->ExceptionCheck()) { + exitCode = -1; + e->ExceptionDescribe(); + e->ExceptionClear(); + } + + vm->DestroyJavaVM(); + + return exitCode; +} diff --git a/sgx-jvm/avian/src/finder.cpp b/sgx-jvm/avian/src/finder.cpp new file mode 100644 index 0000000000..e16df51184 --- /dev/null +++ b/sgx-jvm/avian/src/finder.cpp @@ -0,0 +1,1104 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#include +#include +#include +#include +#include +#include + +#include "avian/zlib-custom.h" +#include "avian/finder.h" +#include "avian/lzma.h" +#include "avian/append.h" + +using namespace vm; +using namespace avian::util; + +namespace { + +const bool DebugFind = false; +const bool DebugStat = false; + +class Element { + public: + class Iterator { + public: + virtual const char* next(size_t* size) = 0; + virtual void dispose() = 0; + }; + + Element() : next(0) + { + } + + virtual Iterator* iterator() = 0; + virtual System::Region* find(const char* name) = 0; + virtual System::FileType stat(const char* name, + size_t* length, + bool tryDirectory) = 0; + virtual const char* urlPrefix() = 0; + virtual const char* sourceUrl() = 0; + virtual void dispose() = 0; + + Element* next; +}; + +class DirectoryElement : public Element { + public: + class Iterator : public Element::Iterator { + public: + Iterator(System* s, Alloc* allocator, const char* name, unsigned skip) + : s(s), + allocator(allocator), + name(name), + skip(skip), + directory(0), + last(0), + it(0) + { + if (not s->success(s->open(&directory, name))) { + directory = 0; + } + } + + virtual const char* next(size_t* size) + { + if (it) { + const char* v = it->next(size); + if (v) { + return v; + } else { + it->dispose(); + it = 0; + } + } + + if (last) { + allocator->free(last, strlen(last) + 1); + } + + if (directory) { + for (const char* v = directory->next(); v; v = directory->next()) { + if (v[0] != '.') { + last = append(allocator, name, "/", v); + size_t length; + if (s->stat(last, &length) == System::TypeDirectory) { + it = new (allocator->allocate(sizeof(Iterator))) + Iterator(s, allocator, last, skip); + it->name = last; + } + const char* result = last + skip; + *size = strlen(result); + return result; + } + } + } + + return 0; + } + + virtual void dispose() + { + directory->dispose(); + allocator->free(this, sizeof(*this)); + } + + System* s; + Alloc* allocator; + const char* name; + unsigned skip; + System::Directory* directory; + const char* last; + Iterator* it; + }; + + DirectoryElement(System* s, Alloc* allocator, const char* name) + : s(s), + allocator(allocator), + originalName(name), + name(s->toAbsolutePath(allocator, name)), + urlPrefix_(append(allocator, "file:", this->name, "/")), + sourceUrl_(append(allocator, "file:", this->name)) + { + } + + virtual Element::Iterator* iterator() + { + return new (allocator->allocate(sizeof(Iterator))) + Iterator(s, allocator, name, strlen(name) + 1); + } + + virtual System::Region* find(const char* name) + { + const char* file = append(allocator, this->name, "/", name); + System::Region* region; + System::Status status = s->map(®ion, file); + allocator->free(file, strlen(file) + 1); + + if (s->success(status)) { + if (DebugFind) { + fprintf(stderr, "found %s in %s\n", name, this->name); + } + return region; + } else { + if (DebugFind) { + fprintf(stderr, "%s not found in %s\n", name, this->name); + } + return 0; + } + } + + virtual System::FileType stat(const char* name, size_t* length, bool) + { + const char* file = append(allocator, this->name, "/", name); + System::FileType type = s->stat(file, length); + if (DebugStat) { + fprintf(stderr, "stat %s in %s: %d\n", name, this->name, type); + } + allocator->free(file, strlen(file) + 1); + return type; + } + + virtual const char* urlPrefix() + { + return urlPrefix_; + } + + virtual const char* sourceUrl() + { + return sourceUrl_; + } + + virtual void dispose() + { + allocator->free(originalName, strlen(originalName) + 1); + allocator->free(name, strlen(name) + 1); + allocator->free(urlPrefix_, strlen(urlPrefix_) + 1); + allocator->free(sourceUrl_, strlen(sourceUrl_) + 1); + allocator->free(this, sizeof(*this)); + } + + System* s; + Alloc* allocator; + const char* originalName; + const char* name; + const char* urlPrefix_; + const char* sourceUrl_; +}; + +class PointerRegion : public System::Region { + public: + PointerRegion(System* s, + Alloc* allocator, + const uint8_t* start, + size_t length, + bool freePointer = false) + : s(s), + allocator(allocator), + start_(start), + length_(length), + freePointer(freePointer) + { + } + + virtual const uint8_t* start() + { + return start_; + } + + virtual size_t length() + { + return length_; + } + + virtual void dispose() + { + if (freePointer) { + allocator->free(start_, length_); + } + allocator->free(this, sizeof(*this)); + } + + System* s; + Alloc* allocator; + const uint8_t* start_; + size_t length_; + bool freePointer; +}; + +class DataRegion : public System::Region { + public: + DataRegion(System* s, Alloc* allocator, size_t length) + : s(s), allocator(allocator), length_(length) + { + } + + virtual const uint8_t* start() + { + return data; + } + + virtual size_t length() + { + return length_; + } + + virtual void dispose() + { + allocator->free(this, sizeof(*this) + length_); + } + + System* s; + Alloc* allocator; + size_t length_; + uint8_t data[0]; +}; + +class JarIndex { + public: + enum CompressionMethod { Stored = 0, Deflated = 8 }; + + class Entry { + public: + Entry(uint32_t hash, const uint8_t* entry) : hash(hash), entry(entry) + { + } + + uint32_t hash; + const uint8_t* entry; + }; + + JarIndex(System* s, Alloc* allocator, unsigned capacity) + : s(s), + allocator(allocator), + capacity(capacity), + position(0), + nodes(static_cast*>( + allocator->allocate(sizeof(List) * capacity))) + { + memset(table, 0, sizeof(List*) * capacity); + } + + static JarIndex* make(System* s, Alloc* allocator, unsigned capacity) + { + return new (allocator->allocate(sizeof(JarIndex) + + (sizeof(List*) * capacity))) + JarIndex(s, allocator, capacity); + } + + static JarIndex* open(System* s, Alloc* allocator, System::Region* region) + { + JarIndex* index = make(s, allocator, 32); + + const uint8_t* start = region->start(); + const uint8_t* end = start + region->length(); + const uint8_t* p = end - CentralDirectorySearchStart; + // Find end of central directory record + while (p > start) { + if (signature(p) == CentralDirectorySignature) { + p = region->start() + centralDirectoryOffset(p); + + while (p < end) { + if (signature(p) == EntrySignature) { + index = index->add(Entry( + hash(Slice(fileName(p), fileNameLength(p))), p)); + + p = endOfEntry(p); + } else { + return index; + } + } + } else { + p--; + } + } + + return index; + } + + JarIndex* add(const Entry& entry) + { + if (position < capacity) { + unsigned i = entry.hash & (capacity - 1); + table[i] = new (nodes + (position++)) List(entry, table[i]); + return this; + } else { + JarIndex* index = make(s, allocator, capacity * 2); + for (unsigned i = 0; i < capacity; ++i) { + index->add(nodes[i].item); + } + index->add(entry); + dispose(); + return index; + } + } + + List* findNode(const char* name) + { + size_t length = strlen(name); + unsigned i = hash(name) & (capacity - 1); + for (List* n = table[i]; n; n = n->next) { + const uint8_t* p = n->item.entry; + if (equal(name, length, fileName(p), fileNameLength(p))) { + return n; + } + } + return 0; + } + + System::Region* find(const char* name, const uint8_t* start) + { + List* n = findNode(name); + if (n) { + const uint8_t* p = n->item.entry; + switch (compressionMethod(p)) { + case Stored: { + return new (allocator->allocate(sizeof(PointerRegion))) + PointerRegion(s, + allocator, + fileData(start + localHeaderOffset(p)), + compressedSize(p)); + } break; + + case Deflated: { + DataRegion* region = new ( + allocator->allocate(sizeof(DataRegion) + uncompressedSize(p))) + DataRegion(s, allocator, uncompressedSize(p)); + + z_stream zStream; + memset(&zStream, 0, sizeof(z_stream)); + + zStream.next_in + = const_cast(fileData(start + localHeaderOffset(p))); + zStream.avail_in = compressedSize(p); + zStream.next_out = region->data; + zStream.avail_out = region->length(); + + // -15 means max window size and raw deflate (no zlib wrapper) + int r = inflateInit2(&zStream, -15); + expect(s, r == Z_OK); + + r = inflate(&zStream, Z_FINISH); + expect(s, r == Z_STREAM_END); + + inflateEnd(&zStream); + + return region; + } break; + + default: + abort(s); + } + } + + return 0; + } + + System::FileType stat(const char* name, size_t* length, bool tryDirectory) + { + List* node = findNode(name); + if (node) { + *length = uncompressedSize(node->item.entry); + return System::TypeFile; + } else if (tryDirectory) { + *length = 0; + + // try again with '/' appended + size_t length = strlen(name); + RUNTIME_ARRAY(char, n, length + 2); + memcpy(RUNTIME_ARRAY_BODY(n), name, length); + RUNTIME_ARRAY_BODY(n)[length] = '/'; + RUNTIME_ARRAY_BODY(n)[length + 1] = 0; + + node = findNode(RUNTIME_ARRAY_BODY(n)); + if (node) { + return System::TypeDirectory; + } else { + return System::TypeDoesNotExist; + } + } else { + *length = 0; + return System::TypeDoesNotExist; + } + } + + void dispose() + { + allocator->free(nodes, sizeof(List) * capacity); + allocator->free(this, sizeof(*this) + (sizeof(List*) * capacity)); + } + + System* s; + Alloc* allocator; + unsigned capacity; + unsigned position; + + List* nodes; + List* table[0]; +}; + +class JarElement : public Element { + public: + class Iterator : public Element::Iterator { + public: + Iterator(System* s, Alloc* allocator, JarIndex* index) + : s(s), allocator(allocator), index(index), position(0) + { + } + + virtual const char* next(size_t* size) + { + if (position < index->position) { + List* n = index->nodes + (position++); + *size = fileNameLength(n->item.entry); + return reinterpret_cast(fileName(n->item.entry)); + } else { + return 0; + } + } + + virtual void dispose() + { + allocator->free(this, sizeof(*this)); + } + + System* s; + Alloc* allocator; + JarIndex* index; + unsigned position; + }; + + JarElement(System* s, + Alloc* allocator, + const char* name, + bool canonicalizePath = true) + : s(s), + allocator(allocator), + originalName(name), + name(name and canonicalizePath ? s->toAbsolutePath(allocator, name) + : name), + urlPrefix_(this->name ? append(allocator, "jar:file:", this->name, "!/") + : 0), + sourceUrl_(this->name ? append(allocator, "file:", this->name) : 0), + region(0), + index(0) + { + } + + JarElement(System* s, + Alloc* allocator, + const uint8_t* jarData, + unsigned jarLength) + : s(s), + allocator(allocator), + originalName(0), + name(0), + urlPrefix_(name ? append(allocator, "jar:file:", name, "!/") : 0), + sourceUrl_(name ? append(allocator, "file:", name) : 0), + region(new (allocator->allocate(sizeof(PointerRegion))) + PointerRegion(s, allocator, jarData, jarLength)), + index(JarIndex::open(s, allocator, region)) + { + } + + virtual Element::Iterator* iterator() + { + init(); + + return new (allocator->allocate(sizeof(Iterator))) + Iterator(s, allocator, index); + } + + virtual void init() + { + if (index == 0) { + System::Region* r; + if (s->success(s->map(&r, name))) { + region = r; + index = JarIndex::open(s, allocator, r); + } + } + } + + virtual System::Region* find(const char* name) + { + init(); + + while (*name == '/') + name++; + + System::Region* r = (index ? index->find(name, region->start()) : 0); + if (DebugFind) { + if (r) { + fprintf(stderr, "found %s in %s\n", name, this->name); + } else { + fprintf(stderr, "%s not found in %s\n", name, this->name); + } + } + return r; + } + + virtual System::FileType stat(const char* name, + size_t* length, + bool tryDirectory) + { + init(); + + while (*name == '/') + name++; + + System::FileType type = (index ? index->stat(name, length, tryDirectory) + : System::TypeDoesNotExist); + if (DebugStat) { + fprintf(stderr, "stat %s in %s: %d\n", name, this->name, type); + } + return type; + } + + virtual const char* urlPrefix() + { + return urlPrefix_; + } + + virtual const char* sourceUrl() + { + return sourceUrl_; + } + + virtual void dispose() + { + dispose(sizeof(*this)); + } + + virtual void dispose(unsigned size) + { + if (name) { + if (originalName != name) { + allocator->free(originalName, strlen(originalName) + 1); + } + allocator->free(name, strlen(name) + 1); + allocator->free(urlPrefix_, strlen(urlPrefix_) + 1); + allocator->free(sourceUrl_, strlen(sourceUrl_) + 1); + } + if (index) { + index->dispose(); + } + if (region) { + region->dispose(); + } + allocator->free(this, size); + } + + System* s; + Alloc* allocator; + const char* originalName; + const char* name; + const char* urlPrefix_; + const char* sourceUrl_; + System::Region* region; + JarIndex* index; +}; + +class BuiltinElement : public JarElement { + public: + BuiltinElement(System* s, + Alloc* allocator, + const char* name, + const char* libraryName) + : JarElement(s, allocator, name, false), + library(0), + libraryName(libraryName ? copy(allocator, libraryName) : 0) + { + } + + virtual void init() + { + if (index == 0) { + if (s->success(s->load(&library, libraryName))) { + bool lzma = strncmp("lzma.", name, 5) == 0; + const char* symbolName = lzma ? name + 5 : name; + + void* p = library->resolve(symbolName); + if (p) { + uint8_t* (*function)(size_t*); + memcpy(&function, &p, BytesPerWord); + + size_t size = 0; + uint8_t* data = function(&size); + if (data) { + bool freePointer; + if (lzma) { +#ifdef AVIAN_USE_LZMA + size_t outSize; + data = decodeLZMA(s, allocator, data, size, &outSize); + size = outSize; + freePointer = true; +#else + abort(s); +#endif + } else { + freePointer = false; + } + region = new (allocator->allocate(sizeof(PointerRegion))) + PointerRegion(s, allocator, data, size, freePointer); + index = JarIndex::open(s, allocator, region); + } else if (DebugFind) { + fprintf( + stderr, "%s in %s returned null\n", symbolName, libraryName); + } + } else if (DebugFind) { + fprintf(stderr, "unable to find %s in %s\n", symbolName, libraryName); + } + } else if (DebugFind) { + fprintf(stderr, "unable to load %s\n", libraryName); + } + } + } + + virtual const char* urlPrefix() + { + return "avianvmresource:"; + } + + virtual const char* sourceUrl() + { + return 0; + } + + virtual void dispose() + { + if (library) { + library->disposeAll(); + } + if (libraryName) { + allocator->free(libraryName, strlen(libraryName) + 1); + } + JarElement::dispose(sizeof(*this)); + } + + System::Library* library; + const char* libraryName; +}; + +void add(Element** first, Element** last, Element* e) +{ + if (*last) { + (*last)->next = e; + } else { + *first = e; + } + *last = e; +} + +unsigned baseName(const char* name, char fileSeparator) +{ + const char* p = name; + const char* last = 0; + while (*p) { + if (*p == fileSeparator) { + last = p; + } + ++p; + } + + return last ? (last + 1) - name : 0; +} + +void add(System* s, + Element** first, + Element** last, + Alloc* allocator, + const char* name, + unsigned nameLength, + const char* bootLibrary); + +void addTokens(System* s, + Element** first, + Element** last, + Alloc* allocator, + const char* jarName, + unsigned jarNameBase, + const char* tokens, + unsigned tokensLength, + const char* bootLibrary) +{ + for (Tokenizer t(String(tokens, tokensLength), ' '); t.hasMore();) { + String token(t.next()); + + RUNTIME_ARRAY(char, n, jarNameBase + token.length + 1); + memcpy(RUNTIME_ARRAY_BODY(n), jarName, jarNameBase); + memcpy(RUNTIME_ARRAY_BODY(n) + jarNameBase, token.text, token.length); + RUNTIME_ARRAY_BODY(n)[jarNameBase + token.length] = 0; + + add(s, + first, + last, + allocator, + RUNTIME_ARRAY_BODY(n), + jarNameBase + token.length, + bootLibrary); + } +} + +bool continuationLine(const uint8_t* base, + unsigned total, + size_t* start, + size_t* length) +{ + return readLine(base, total, start, length) and *length > 0 + and base[*start] == ' '; +} + +void addJar(System* s, + Element** first, + Element** last, + Alloc* allocator, + const char* name, + const char* bootLibrary) +{ + if (DebugFind) { + fprintf(stderr, "add jar %s\n", name); + } + + JarElement* e = new (allocator->allocate(sizeof(JarElement))) + JarElement(s, allocator, name); + + unsigned nameBase = baseName(name, s->fileSeparator()); + + add(first, last, e); + + System::Region* region = e->find("META-INF/MANIFEST.MF"); + if (region) { + size_t start = 0; + size_t length; + while (readLine(region->start(), region->length(), &start, &length)) { + unsigned multilineTotal = 0; + + const unsigned PrefixLength = 12; + if (length > PrefixLength + and strncmp("Class-Path: ", + reinterpret_cast(region->start() + start), + PrefixLength) == 0) { + { + size_t nextStart = start + length; + size_t nextLength; + while (continuationLine( + region->start(), region->length(), &nextStart, &nextLength)) { + multilineTotal += nextLength; + nextStart += nextLength; + } + } + + const char* line = reinterpret_cast(region->start() + start + + PrefixLength); + + unsigned lineLength = length - PrefixLength; + + if (multilineTotal) { + RUNTIME_ARRAY(char, n, (length - PrefixLength) + multilineTotal + 1); + + memcpy(RUNTIME_ARRAY_BODY(n), line, lineLength); + + unsigned offset = lineLength; + { + size_t nextStart = start + length; + size_t nextLength; + while (continuationLine( + region->start(), region->length(), &nextStart, &nextLength)) { + unsigned continuationLength = nextLength - 1; + + memcpy(RUNTIME_ARRAY_BODY(n) + offset, + region->start() + nextStart + 1, + continuationLength); + + offset += continuationLength; + nextStart += nextLength; + } + } + + addTokens(s, + first, + last, + allocator, + name, + nameBase, + RUNTIME_ARRAY_BODY(n), + offset, + bootLibrary); + } else { + addTokens(s, + first, + last, + allocator, + name, + nameBase, + line, + lineLength, + bootLibrary); + } + } + + start += length + multilineTotal; + } + + region->dispose(); + } +} + +void add(System* s, + Element** first, + Element** last, + Alloc* allocator, + const char* token, + unsigned tokenLength, + const char* bootLibrary) +{ + if (*token == '[' and token[tokenLength - 1] == ']') { + char* name = static_cast(allocator->allocate(tokenLength - 1)); + memcpy(name, token + 1, tokenLength - 1); + name[tokenLength - 2] = 0; + + if (DebugFind) { + fprintf(stderr, "add builtin %s\n", name); + } + + add(first, + last, + new (allocator->allocate(sizeof(BuiltinElement))) + BuiltinElement(s, allocator, name, bootLibrary)); + } else { + char* name = static_cast(allocator->allocate(tokenLength + 1)); + memcpy(name, token, tokenLength); + name[tokenLength] = 0; + + size_t length; + switch (s->stat(name, &length)) { + case System::TypeFile: { + addJar(s, first, last, allocator, name, bootLibrary); + } break; + + case System::TypeDirectory: { + if (DebugFind) { + fprintf(stderr, "add directory %s\n", name); + } + + add(first, + last, + new (allocator->allocate(sizeof(DirectoryElement))) + DirectoryElement(s, allocator, name)); + } break; + + default: { + if (DebugFind) { + fprintf(stderr, "ignore nonexistent %s\n", name); + } + + allocator->free(name, strlen(name) + 1); + } break; + } + } +} + +Element* parsePath(System* s, + Alloc* allocator, + const char* path, + const char* bootLibrary) +{ + Element* first = 0; + Element* last = 0; + for (Tokenizer t(path, s->pathSeparator()); t.hasMore();) { + String token(t.next()); + + add(s, &first, &last, allocator, token.text, token.length, bootLibrary); + } + + return first; +} + +class MyIterator : public Finder::IteratorImp { + public: + MyIterator(System* s, Alloc* allocator, Element* path) + : s(s), + allocator(allocator), + e(path ? path->next : 0), + it(path ? path->iterator() : 0) + { + } + + virtual const char* next(size_t* size) + { + while (it) { + const char* v = it->next(size); + if (v) { + return v; + } else { + it->dispose(); + if (e) { + it = e->iterator(); + e = e->next; + } else { + it = 0; + } + } + } + return 0; + } + + virtual void dispose() + { + if (it) + it->dispose(); + allocator->free(this, sizeof(*this)); + } + + System* s; + Alloc* allocator; + Element* e; + Element::Iterator* it; +}; + +class MyFinder : public Finder { + public: + MyFinder(System* system, + Alloc* allocator, + const char* path, + const char* bootLibrary) + : system(system), + allocator(allocator), + path_(parsePath(system, allocator, path, bootLibrary)), + pathString(copy(allocator, path)) + { + } + + MyFinder(System* system, + Alloc* allocator, + const uint8_t* jarData, + unsigned jarLength) + : system(system), + allocator(allocator), + path_(new (allocator->allocate(sizeof(JarElement))) + JarElement(system, allocator, jarData, jarLength)), + pathString(0) + { + } + + virtual IteratorImp* iterator() + { + return new (allocator->allocate(sizeof(MyIterator))) + MyIterator(system, allocator, path_); + } + + virtual System::Region* find(const char* name) + { + for (Element* e = path_; e; e = e->next) { + System::Region* r = e->find(name); + if (r) { + return r; + } + } + + return 0; + } + + virtual System::FileType stat(const char* name, + size_t* length, + bool tryDirectory) + { + for (Element* e = path_; e; e = e->next) { + System::FileType type = e->stat(name, length, tryDirectory); + if (type != System::TypeDoesNotExist) { + return type; + } + } + + return System::TypeDoesNotExist; + } + + virtual const char* urlPrefix(const char* name) + { + void* finderElementPtr = NULL; + return nextUrlPrefix(name, finderElementPtr); + } + + virtual const char* nextUrlPrefix(const char* name, void*& finderElementPtr) + { + Element*& e = reinterpret_cast(finderElementPtr); + e = e ? e->next : path_; + for (; e; e = e->next) { + size_t length; + System::FileType type = e->stat(name, &length, true); + if (type != System::TypeDoesNotExist) { + return e->urlPrefix(); + } + } + + return 0; + } + + virtual const char* sourceUrl(const char* name) + { + for (Element* e = path_; e; e = e->next) { + size_t length; + System::FileType type = e->stat(name, &length, true); + if (type != System::TypeDoesNotExist) { + return e->sourceUrl(); + } + } + + return 0; + } + + virtual const char* path() + { + return pathString; + } + + virtual void dispose() + { + for (Element* e = path_; e;) { + Element* t = e; + e = e->next; + t->dispose(); + } + if (pathString) { + allocator->free(pathString, strlen(pathString) + 1); + } + allocator->free(this, sizeof(*this)); + } + + System* system; + Alloc* allocator; + Element* path_; + const char* pathString; +}; + +} // namespace + +namespace vm { + +AVIAN_EXPORT Finder* makeFinder(System* s, + Alloc* a, + const char* path, + const char* bootLibrary) +{ + return new (a->allocate(sizeof(MyFinder))) MyFinder(s, a, path, bootLibrary); +} + +Finder* makeFinder(System* s, + Alloc* a, + const uint8_t* jarData, + size_t jarLength) +{ + return new (a->allocate(sizeof(MyFinder))) MyFinder(s, a, jarData, jarLength); +} + +} // namespace vm diff --git a/sgx-jvm/avian/src/heap/CMakeLists.txt b/sgx-jvm/avian/src/heap/CMakeLists.txt new file mode 100644 index 0000000000..5c6ae4177d --- /dev/null +++ b/sgx-jvm/avian/src/heap/CMakeLists.txt @@ -0,0 +1,2 @@ + +add_library(avian_heap heap.cpp) \ No newline at end of file diff --git a/sgx-jvm/avian/src/heap/heap.cpp b/sgx-jvm/avian/src/heap/heap.cpp new file mode 100644 index 0000000000..6799452725 --- /dev/null +++ b/sgx-jvm/avian/src/heap/heap.cpp @@ -0,0 +1,2206 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#include +#include +#include "avian/common.h" +#include "avian/arch.h" + +#include + +using namespace vm; +using namespace avian::util; + +namespace { + +namespace local { + +const unsigned Top = ~static_cast(0); + +const unsigned InitialGen2CapacityInBytes = 4 * 1024 * 1024; +const unsigned InitialTenuredFixieCeilingInBytes = 4 * 1024 * 1024; + +const bool Verbose = false; +const bool Verbose2 = false; +const bool Debug = false; +const bool DebugFixies = false; + +#ifdef NDEBUG +const bool DebugAllocation = false; +#else +const bool DebugAllocation = true; +#endif + +#define ACQUIRE(x) MutexLock MAKE_NAME(monitorLock_)(x) + +class MutexLock { + public: + MutexLock(System::Mutex* m) : m(m) + { + m->acquire(); + } + + ~MutexLock() + { + m->release(); + } + + private: + System::Mutex* m; +}; + +class Context; + +Aborter* getAborter(Context* c); + +void* tryAllocate(Context* c, size_t size); +void* allocate(Context* c, size_t size); +void* allocate(Context* c, size_t size, bool limit); +void free(Context* c, const void* p, size_t size); + +#ifdef USE_ATOMIC_OPERATIONS +inline void markBitAtomic(uintptr_t* map, unsigned i) +{ + uintptr_t* p = map + wordOf(i); + uintptr_t v = static_cast(1) << bitOf(i); + for (uintptr_t old = *p; not atomicCompareAndSwap(p, old, old | v); + old = *p) { + } +} +#endif // USE_ATOMIC_OPERATIONS + +inline void* get(void* o, unsigned offsetInWords) +{ + return maskAlignedPointer( + fieldAtOffset(o, offsetInWords * BytesPerWord)); +} + +inline void** getp(void* o, unsigned offsetInWords) +{ + return &fieldAtOffset(o, offsetInWords * BytesPerWord); +} + +inline void set(void** o, void* value) +{ + *o = reinterpret_cast( + reinterpret_cast(value) + | (reinterpret_cast(*o) & (~PointerMask))); +} + +inline void set(void* o, unsigned offsetInWords, void* value) +{ + set(getp(o, offsetInWords), value); +} + +class Segment { + public: + class Map { + public: + class Iterator { + public: + Map* map; + unsigned index; + unsigned limit; + + Iterator(Map* map, unsigned start, unsigned end) : map(map) + { + assertT(map->segment->context, map->bitsPerRecord == 1); + assertT(map->segment->context, map->segment); + assertT(map->segment->context, start <= map->segment->position()); + + if (end > map->segment->position()) + end = map->segment->position(); + + index = map->indexOf(start); + limit = map->indexOf(end); + + if ((end - start) % map->scale) + ++limit; + } + + bool hasMore() + { + unsigned word = wordOf(index); + unsigned bit = bitOf(index); + unsigned wordLimit = wordOf(limit); + unsigned bitLimit = bitOf(limit); + + for (; word <= wordLimit and (word < wordLimit or bit < bitLimit); + ++word) { + uintptr_t w = map->data[word]; + if (2) { + for (; bit < BitsPerWord and (word < wordLimit or bit < bitLimit); + ++bit) { + if (w & (static_cast(1) << bit)) { + index = ::indexOf(word, bit); + // printf("hit at index %d\n", index); + return true; + } else { + // printf("miss at index %d\n", indexOf(word, + // bit)); + } + } + } + bit = 0; + } + + index = limit; + + return false; + } + + unsigned next() + { + assertT(map->segment->context, hasMore()); + assertT(map->segment->context, map->segment); + + return (index++) * map->scale; + } + }; + + Segment* segment; + Map* child; + uintptr_t* data; + unsigned bitsPerRecord; + unsigned scale; + bool clearNewData; + + Map(Segment* segment, + uintptr_t* data, + unsigned bitsPerRecord, + unsigned scale, + Map* child, + bool clearNewData) + : segment(segment), + child(child), + data(data), + bitsPerRecord(bitsPerRecord), + scale(scale), + clearNewData(clearNewData) + { + } + + Map(Segment* segment, + unsigned bitsPerRecord, + unsigned scale, + Map* child, + bool clearNewData) + : segment(segment), + child(child), + data(0), + bitsPerRecord(bitsPerRecord), + scale(scale), + clearNewData(clearNewData) + { + } + + void init() + { + assertT(segment->context, bitsPerRecord); + assertT(segment->context, scale); + assertT(segment->context, powerOfTwo(scale)); + + if (data == 0) { + data = segment->data + segment->capacity() + + calculateOffset(segment->capacity()); + } + + if (clearNewData) { + memset(data, 0, size() * BytesPerWord); + } + + if (child) { + child->init(); + } + } + + unsigned calculateOffset(unsigned capacity) + { + unsigned n = 0; + if (child) + n += child->calculateFootprint(capacity); + return n; + } + + static unsigned calculateSize(Context* c UNUSED, + unsigned capacity, + unsigned scale, + unsigned bitsPerRecord) + { + unsigned result = ceilingDivide( + ceilingDivide(capacity, scale) * bitsPerRecord, BitsPerWord); + assertT(c, result); + return result; + } + + unsigned calculateSize(unsigned capacity) + { + return calculateSize(segment->context, capacity, scale, bitsPerRecord); + } + + unsigned size() + { + return calculateSize(segment->capacity()); + } + + unsigned calculateFootprint(unsigned capacity) + { + unsigned n = calculateSize(capacity); + if (child) + n += child->calculateFootprint(capacity); + return n; + } + + void replaceWith(Map* m) + { + assertT(segment->context, bitsPerRecord == m->bitsPerRecord); + assertT(segment->context, scale == m->scale); + + data = m->data; + + m->segment = 0; + m->data = 0; + + if (child) + child->replaceWith(m->child); + } + + unsigned indexOf(unsigned segmentIndex) + { + return (segmentIndex / scale) * bitsPerRecord; + } + + unsigned indexOf(void* p) + { + assertT(segment->context, segment->almostContains(p)); + assertT(segment->context, segment->capacity()); + return indexOf(segment->indexOf(p)); + } + + void clearBit(unsigned i) + { + assertT(segment->context, wordOf(i) < size()); + + vm::clearBit(data, i); + } + + void setBit(unsigned i) + { + assertT(segment->context, wordOf(i) < size()); + + vm::markBit(data, i); + } + + void clearOnlyIndex(unsigned index) + { + clearBits(data, bitsPerRecord, index); + } + + void clearOnly(unsigned segmentIndex) + { + clearOnlyIndex(indexOf(segmentIndex)); + } + + void clearOnly(void* p) + { + clearOnlyIndex(indexOf(p)); + } + + void clear(void* p) + { + clearOnly(p); + if (child) + child->clear(p); + } + + void setOnlyIndex(unsigned index, unsigned v = 1) + { + setBits(data, bitsPerRecord, index, v); + } + + void setOnly(unsigned segmentIndex, unsigned v = 1) + { + setOnlyIndex(indexOf(segmentIndex), v); + } + + void setOnly(void* p, unsigned v = 1) + { + setOnlyIndex(indexOf(p), v); + } + + void set(void* p, unsigned v = 1) + { + setOnly(p, v); + assertT(segment->context, get(p) == v); + if (child) + child->set(p, v); + } + +#ifdef USE_ATOMIC_OPERATIONS + void markAtomic(void* p) + { + assertT(segment->context, bitsPerRecord == 1); + markBitAtomic(data, indexOf(p)); + assertT(segment->context, getBit(data, indexOf(p))); + if (child) + child->markAtomic(p); + } +#endif + + unsigned get(void* p) + { + return getBits(data, bitsPerRecord, indexOf(p)); + } + }; + + Context* context; + uintptr_t* data; + unsigned position_; + unsigned capacity_; + Map* map; + + Segment(Context* context, + Map* map, + unsigned desired, + unsigned minimum, + int64_t available = INT64_MAX) + : context(context), data(0), position_(0), capacity_(0), map(map) + { + if (desired) { + if (minimum == 0) { + minimum = 1; + } + + assertT(context, desired >= minimum); + + capacity_ = desired; + + if (static_cast(footprint(capacity_)) > available) { + unsigned top = capacity_; + unsigned bottom = minimum; + unsigned target = available; + while (true) { + if (static_cast(footprint(capacity_)) > target) { + if (bottom == capacity_) { + break; + } else if (static_cast(footprint(capacity_ - 1)) + <= target) { + --capacity_; + break; + } + top = capacity_; + capacity_ = avg(bottom, capacity_); + } else if (static_cast(footprint(capacity_)) < target) { + if (top == capacity_ + or static_cast(footprint(capacity_ + 1)) >= target) { + break; + } + bottom = capacity_; + capacity_ = avg(top, capacity_); + } else { + break; + } + } + } + + while (data == 0) { + data = static_cast(local::allocate( + context, (footprint(capacity_)) * BytesPerWord, false)); + + if (data == 0) { + if (capacity_ > minimum) { + capacity_ = avg(minimum, capacity_); + if (capacity_ == 0) { + break; + } + } else { + data = static_cast(local::allocate( + context, (footprint(capacity_)) * BytesPerWord)); + } + } + } + + if (map) { + map->init(); + } + } + } + + Segment(Context* context, + Map* map, + uintptr_t* data, + unsigned position, + unsigned capacity) + : context(context), + data(data), + position_(position), + capacity_(capacity), + map(map) + { + if (map) { + map->init(); + } + } + + unsigned footprint(unsigned capacity) + { + return capacity + + (map and capacity ? map->calculateFootprint(capacity) : 0); + } + + unsigned capacity() + { + return capacity_; + } + + unsigned position() + { + return position_; + } + + unsigned remaining() + { + return capacity() - position(); + } + + void replaceWith(Segment* s) + { + if (data) { + free(context, data, (footprint(capacity())) * BytesPerWord); + } + data = s->data; + s->data = 0; + + position_ = s->position_; + s->position_ = 0; + + capacity_ = s->capacity_; + s->capacity_ = 0; + + if (s->map) { + if (map) { + map->replaceWith(s->map); + s->map = 0; + } else { + abort(context); + } + } else { + assertT(context, map == 0); + } + } + + bool contains(void* p) + { + return position() and p >= data and p < data + position(); + } + + bool almostContains(void* p) + { + return contains(p) or p == data + position(); + } + + void* get(unsigned offset) + { + assertT(context, offset <= position()); + return data + offset; + } + + unsigned indexOf(void* p) + { + assertT(context, almostContains(p)); + return static_cast(p) - data; + } + + void* allocate(unsigned size) + { + assertT(context, size); + assertT(context, position() + size <= capacity()); + + void* p = data + position(); + position_ += size; + return p; + } + + void dispose() + { + if (data) { + free(context, data, (footprint(capacity())) * BytesPerWord); + } + data = 0; + map = 0; + } +}; + +class Fixie { + public: + static const unsigned HasMask = 1 << 0; + static const unsigned Marked = 1 << 1; + static const unsigned Dirty = 1 << 2; + static const unsigned Dead = 1 << 3; + + Fixie(Context* c, unsigned size, bool hasMask, Fixie** handle, bool immortal) + : age(immortal ? FixieTenureThreshold + 1 : 0), + flags(hasMask ? HasMask : 0), + size(size), + next(0), + handle(0) + { + memset(mask(), 0, maskSize(size, hasMask)); + add(c, handle); + if (DebugFixies) { + fprintf(stderr, "make fixie %p of size %d\n", this, totalSize()); + } + } + + bool immortal() + { + return age == FixieTenureThreshold + 1; + } + + void add(Context* c UNUSED, Fixie** handle) + { + assertT(c, this->handle == 0); + assertT(c, next == 0); + + this->handle = handle; + if (handle) { + next = *handle; + if (next) + next->handle = &next; + *handle = this; + } else { + next = 0; + } + } + + void remove(Context* c UNUSED) + { + if (handle) { + assertT(c, *handle == this); + *handle = next; + } + if (next) { + next->handle = handle; + } + next = 0; + handle = 0; + } + + void move(Context* c, Fixie** handle) + { + if (DebugFixies) { + fprintf(stderr, "move fixie %p\n", this); + } + + remove(c); + add(c, handle); + } + + void** body() + { + return static_cast(static_cast(body_)); + } + + uintptr_t* mask() + { + return body_ + size; + } + + static unsigned maskSize(unsigned size, bool hasMask) + { + return hasMask * ceilingDivide(size, BitsPerWord) * BytesPerWord; + } + + static unsigned totalSize(unsigned size, bool hasMask) + { + return sizeof(Fixie) + (size * BytesPerWord) + maskSize(size, hasMask); + } + + unsigned totalSize() + { + return totalSize(size, hasMask()); + } + + bool hasMask() + { + return (flags & HasMask) != 0; + } + + bool marked() + { + return (flags & Marked) != 0; + } + + void marked(bool v) + { + if (v) { + flags |= Marked; + } else { + flags &= ~Marked; + } + } + + bool dirty() + { + return (flags & Dirty) != 0; + } + + void dirty(bool v) + { + if (v) { + flags |= Dirty; + } else { + flags &= ~Dirty; + } + } + + bool dead() + { + return (flags & Dead) != 0; + } + + void dead(bool v) + { + if (v) { + flags |= Dead; + } else { + flags &= ~Dead; + } + } + + // be sure to update e.g. TargetFixieSizeInBytes in bootimage.cpp if + // you add/remove/change fields in this class: + + uint16_t age; + uint16_t flags; + uint32_t size; + Fixie* next; + Fixie** handle; + uintptr_t body_[0]; +}; + +Fixie* fixie(void* body) +{ + return static_cast(body) - 1; +} + +void free(Context* c, Fixie** fixies, bool resetImmortal = false); + +class Context { + public: + Context(System* system, unsigned limit) + : system(system), + client(0), + count(0), + limit(limit), + lock(0), + immortalHeapStart(0), + immortalHeapEnd(0), + ageMap(&gen1, max(1, log(TenureThreshold)), 1, 0, false), + gen1(this, &ageMap, 0, 0), + nextAgeMap(&nextGen1, max(1, log(TenureThreshold)), 1, 0, false), + nextGen1(this, &nextAgeMap, 0, 0), + pointerMap(&gen2, 1, 1, 0, true), + pageMap(&gen2, + 1, + LikelyPageSizeInBytes / BytesPerWord, + &pointerMap, + true), + heapMap(&gen2, 1, pageMap.scale * 1024, &pageMap, true), + gen2(this, &heapMap, 0, 0), + nextPointerMap(&nextGen2, 1, 1, 0, true), + nextPageMap(&nextGen2, + 1, + LikelyPageSizeInBytes / BytesPerWord, + &nextPointerMap, + true), + nextHeapMap(&nextGen2, 1, nextPageMap.scale * 1024, &nextPageMap, true), + nextGen2(this, &nextHeapMap, 0, 0), + gen2Base(0), + incomingFootprint(0), + pendingAllocation(0), + tenureFootprint(0), + gen1Padding(0), + tenurePadding(0), + gen2Padding(0), + fixieTenureFootprint(0), + untenuredFixieFootprint(0), + tenuredFixieFootprint(0), + tenuredFixieCeiling(InitialTenuredFixieCeilingInBytes), + mode(Heap::MinorCollection), + fixies(0), + tenuredFixies(0), + dirtyTenuredFixies(0), + markedFixies(0), + visitedFixies(0), + lastCollectionTime(system->now()), + totalCollectionTime(0), + totalTime(0), + limitWasExceeded(false) + { + if (not system->success(system->make(&lock))) { + system->abort(); + } + } + + void dispose() + { + gen1.dispose(); + nextGen1.dispose(); + gen2.dispose(); + nextGen2.dispose(); + lock->dispose(); + } + + void disposeFixies() + { + free(this, &tenuredFixies, true); + free(this, &dirtyTenuredFixies, true); + free(this, &fixies, true); + } + + System* system; + Heap::Client* client; + + unsigned count; + unsigned limit; + + System::Mutex* lock; + + uintptr_t* immortalHeapStart; + uintptr_t* immortalHeapEnd; + + Segment::Map ageMap; + Segment gen1; + + Segment::Map nextAgeMap; + Segment nextGen1; + + Segment::Map pointerMap; + Segment::Map pageMap; + Segment::Map heapMap; + Segment gen2; + + Segment::Map nextPointerMap; + Segment::Map nextPageMap; + Segment::Map nextHeapMap; + Segment nextGen2; + + unsigned gen2Base; + + unsigned incomingFootprint; + int pendingAllocation; + unsigned tenureFootprint; + unsigned gen1Padding; + unsigned tenurePadding; + unsigned gen2Padding; + + unsigned fixieTenureFootprint; + unsigned untenuredFixieFootprint; + unsigned tenuredFixieFootprint; + unsigned tenuredFixieCeiling; + + Heap::CollectionType mode; + + Fixie* fixies; + Fixie* tenuredFixies; + Fixie* dirtyTenuredFixies; + Fixie* markedFixies; + Fixie* visitedFixies; + + int64_t lastCollectionTime; + int64_t totalCollectionTime; + int64_t totalTime; + + bool limitWasExceeded; +}; + +const char* segment(Context* c, void* p) +{ + if (c->gen1.contains(p)) { + return "gen1"; + } else if (c->nextGen1.contains(p)) { + return "nextGen1"; + } else if (c->gen2.contains(p)) { + return "gen2"; + } else if (c->nextGen2.contains(p)) { + return "nextGen2"; + } else { + return "none"; + } +} + +inline Aborter* getAborter(Context* c) +{ + return c->system; +} + +inline unsigned minimumNextGen1Capacity(Context* c) +{ + return c->gen1.position() - c->tenureFootprint + c->incomingFootprint + + c->gen1Padding; +} + +inline unsigned minimumNextGen2Capacity(Context* c) +{ + return c->gen2.position() + c->tenureFootprint + c->tenurePadding + + c->gen2Padding; +} + +inline bool oversizedGen2(Context* c) +{ + return c->gen2.capacity() > (InitialGen2CapacityInBytes / BytesPerWord) + and c->gen2.position() < (c->gen2.capacity() / 4); +} + +inline void initNextGen1(Context* c) +{ + new (&(c->nextAgeMap)) + Segment::Map(&(c->nextGen1), max(1, log(TenureThreshold)), 1, 0, false); + + unsigned minimum = minimumNextGen1Capacity(c); + unsigned desired = minimum; + + new (&(c->nextGen1)) Segment(c, &(c->nextAgeMap), desired, minimum); + + if (Verbose2) { + fprintf(stderr, + "init nextGen1 to %d bytes\n", + c->nextGen1.capacity() * BytesPerWord); + } +} + +inline void initNextGen2(Context* c) +{ + new (&(c->nextPointerMap)) Segment::Map(&(c->nextGen2), 1, 1, 0, true); + + new (&(c->nextPageMap)) Segment::Map(&(c->nextGen2), + 1, + LikelyPageSizeInBytes / BytesPerWord, + &(c->nextPointerMap), + true); + + new (&(c->nextHeapMap)) Segment::Map( + &(c->nextGen2), 1, c->pageMap.scale * 1024, &(c->nextPageMap), true); + + unsigned minimum = minimumNextGen2Capacity(c); + unsigned desired = minimum; + + if (not oversizedGen2(c)) { + desired *= 2; + } + + if (desired < InitialGen2CapacityInBytes / BytesPerWord) { + desired = InitialGen2CapacityInBytes / BytesPerWord; + } + + new (&(c->nextGen2)) Segment( + c, + &(c->nextHeapMap), + desired, + minimum, + static_cast(c->limit / BytesPerWord) + - (static_cast(c->count / BytesPerWord) + - c->gen2.footprint(c->gen2.capacity()) + - c->gen1.footprint(c->gen1.capacity()) + c->pendingAllocation)); + + if (Verbose2) { + fprintf(stderr, + "init nextGen2 to %d bytes\n", + c->nextGen2.capacity() * BytesPerWord); + } +} + +inline bool fresh(Context* c, void* o) +{ + return c->nextGen1.contains(o) or c->nextGen2.contains(o) + or (c->gen2.contains(o) and c->gen2.indexOf(o) >= c->gen2Base); +} + +inline bool wasCollected(Context* c, void* o) +{ + return o and (not fresh(c, o)) and fresh(c, get(o, 0)); +} + +inline void* follow(Context* c UNUSED, void* o) +{ + assertT(c, wasCollected(c, o)); + return fieldAtOffset(o, 0); +} + +inline void*& parent(Context* c UNUSED, void* o) +{ + assertT(c, wasCollected(c, o)); + return fieldAtOffset(o, BytesPerWord); +} + +inline uintptr_t* bitset(Context* c UNUSED, void* o) +{ + assertT(c, wasCollected(c, o)); + return &fieldAtOffset(o, BytesPerWord * 2); +} + +void free(Context* c, Fixie** fixies, bool resetImmortal) +{ + for (Fixie** p = fixies; *p;) { + Fixie* f = *p; + + if (f->immortal()) { + if (resetImmortal) { + if (DebugFixies) { + fprintf(stderr, "reset immortal fixie %p\n", f); + } + *p = f->next; + memset(f->mask(), 0, Fixie::maskSize(f->size, f->hasMask())); + f->next = 0; + f->handle = 0; + f->marked(false); + f->dirty(false); + } else { + p = &(f->next); + } + } else { + *p = f->next; + if (DebugFixies) { + fprintf(stderr, "free fixie %p\n", f); + } + free(c, f, f->totalSize()); + } + } +} + +void kill(Fixie* fixies) +{ + for (Fixie* f = fixies; f; f = f->next) { + if (!f->immortal()) { + f->dead(true); + } + } +} + +void killFixies(Context* c) +{ + assertT(c, c->markedFixies == 0); + + if (c->mode == Heap::MajorCollection) { + kill(c->tenuredFixies); + kill(c->dirtyTenuredFixies); + } + kill(c->fixies); +} + +void sweepFixies(Context* c) +{ + assertT(c, c->markedFixies == 0); + + if (c->mode == Heap::MajorCollection) { + free(c, &(c->tenuredFixies), true); + free(c, &(c->dirtyTenuredFixies), true); + + c->tenuredFixieFootprint = 0; + } + free(c, &(c->fixies)); + + c->untenuredFixieFootprint = 0; + + while (c->visitedFixies) { + Fixie* f = c->visitedFixies; + f->remove(c); + + if (not f->immortal()) { + ++f->age; + if (f->age > FixieTenureThreshold) { + f->age = FixieTenureThreshold; + } else if (static_cast(f->age + 1) == FixieTenureThreshold) { + c->fixieTenureFootprint += f->totalSize(); + } + } + + if (f->age >= FixieTenureThreshold) { + if (DebugFixies) { + fprintf(stderr, "tenure fixie %p (dirty: %d)\n", f, f->dirty()); + } + + if (not f->immortal()) { + c->tenuredFixieFootprint += f->totalSize(); + } + + if (f->dirty()) { + f->add(c, &(c->dirtyTenuredFixies)); + } else { + f->add(c, &(c->tenuredFixies)); + } + } else { + c->untenuredFixieFootprint += f->totalSize(); + + f->add(c, &(c->fixies)); + } + + f->marked(false); + } + + c->tenuredFixieCeiling + = max(c->tenuredFixieFootprint * 2, InitialTenuredFixieCeilingInBytes); +} + +inline void* copyTo(Context* c, Segment* s, void* o, unsigned size) +{ + assertT(c, s->remaining() >= size); + void* dst = s->allocate(size); + c->client->copy(o, dst); + return dst; +} + +bool immortalHeapContains(Context* c, void* p) +{ + return p < c->immortalHeapEnd and p >= c->immortalHeapStart; +} + +void* copy2(Context* c, void* o) +{ + unsigned size = c->client->copiedSizeInWords(o); + + if (c->gen2.contains(o)) { + assertT(c, c->mode == Heap::MajorCollection); + + return copyTo(c, &(c->nextGen2), o, size); + } else if (c->gen1.contains(o)) { + unsigned age = c->ageMap.get(o); + if (age == TenureThreshold) { + if (c->mode == Heap::MinorCollection) { + assertT(c, c->gen2.remaining() >= size); + + if (c->gen2Base == Top) { + c->gen2Base = c->gen2.position(); + } + + return copyTo(c, &(c->gen2), o, size); + } else { + return copyTo(c, &(c->nextGen2), o, size); + } + } else { + o = copyTo(c, &(c->nextGen1), o, size); + + c->nextAgeMap.setOnly(o, age + 1); + if (age + 1 == TenureThreshold) { + c->tenureFootprint += size; + } + + return o; + } + } else { + assertT(c, not c->nextGen1.contains(o)); + assertT(c, not c->nextGen2.contains(o)); + assertT(c, not immortalHeapContains(c, o)); + + o = copyTo(c, &(c->nextGen1), o, size); + + c->nextAgeMap.clear(o); + + return o; + } +} + +void* copy(Context* c, void* o) +{ + void* r = copy2(c, o); + + if (Debug) { + fprintf(stderr, + "copy %p (%s) to %p (%s)\n", + o, + segment(c, o), + r, + segment(c, r)); + } + + // leave a pointer to the copy in the original + fieldAtOffset(o, 0) = r; + + return r; +} + +void* update3(Context* c, void* o, bool* needsVisit) +{ + if (c->client->isFixed(o)) { + Fixie* f = fixie(o); + if ((not f->marked()) and (c->mode == Heap::MajorCollection + or f->age < FixieTenureThreshold)) { + if (DebugFixies) { + fprintf(stderr, "mark fixie %p\n", f); + } + f->marked(true); + f->dead(false); + f->move(c, &(c->markedFixies)); + } + *needsVisit = false; + return o; + } else if (immortalHeapContains(c, o)) { + *needsVisit = false; + return o; + } else if (wasCollected(c, o)) { + *needsVisit = false; + return follow(c, o); + } else { + *needsVisit = true; + return copy(c, o); + } +} + +void* update2(Context* c, void* o, bool* needsVisit) +{ + if (c->mode == Heap::MinorCollection and c->gen2.contains(o)) { + *needsVisit = false; + return o; + } + + return update3(c, o, needsVisit); +} + +void markDirty(Context* c, Fixie* f) +{ + if (not f->dirty()) { +#ifdef USE_ATOMIC_OPERATIONS + ACQUIRE(c->lock); +#endif + + if (not f->dirty()) { + f->dirty(true); + f->move(c, &(c->dirtyTenuredFixies)); + } + } +} + +void markClean(Context* c, Fixie* f) +{ + if (f->dirty()) { + f->dirty(false); + if (f->immortal()) { + f->remove(c); + } else { + f->move(c, &(c->tenuredFixies)); + } + } +} + +void updateHeapMap(Context* c, + void* p, + void* target, + unsigned offset, + void* result) +{ + Segment* seg; + Segment::Map* map; + + if (c->mode == Heap::MinorCollection) { + seg = &(c->gen2); + map = &(c->heapMap); + } else { + seg = &(c->nextGen2); + map = &(c->nextHeapMap); + } + + if (not(immortalHeapContains(c, result) + or (c->client->isFixed(result) + and fixie(result)->age >= FixieTenureThreshold) + or seg->contains(result))) { + if (target and c->client->isFixed(target)) { + Fixie* f = fixie(target); + assertT(c, offset == 0 or f->hasMask()); + + if (static_cast(f->age + 1) >= FixieTenureThreshold) { + if (DebugFixies) { + fprintf(stderr, + "dirty fixie %p at %d (%p): %p\n", + f, + offset, + f->body() + offset, + result); + } + + f->dirty(true); + markBit(f->mask(), offset); + } + } else if (seg->contains(p)) { + if (Debug) { + fprintf(stderr, + "mark %p (%s) at %p (%s)\n", + result, + segment(c, result), + p, + segment(c, p)); + } + + map->set(p); + } + } +} + +void* update(Context* c, + void** p, + void* target, + unsigned offset, + bool* needsVisit) +{ + if (maskAlignedPointer(*p) == 0) { + *needsVisit = false; + return 0; + } + + void* result = update2(c, maskAlignedPointer(*p), needsVisit); + + if (result) { + updateHeapMap(c, p, target, offset, result); + } + + return result; +} + +const uintptr_t BitsetExtensionBit + = (static_cast(1) << (BitsPerWord - 1)); + +void bitsetInit(uintptr_t* p) +{ + memset(p, 0, BytesPerWord); +} + +void bitsetClear(uintptr_t* p, unsigned start, unsigned end) +{ + if (end < BitsPerWord - 1) { + // do nothing + } else if (start < BitsPerWord - 1) { + memset(p + 1, 0, (wordOf(end + (BitsPerWord * 2) + 1)) * BytesPerWord); + } else { + unsigned startWord = wordOf(start + (BitsPerWord * 2) + 1); + unsigned endWord = wordOf(end + (BitsPerWord * 2) + 1); + if (endWord > startWord) { + memset(p + startWord + 1, 0, (endWord - startWord) * BytesPerWord); + } + } +} + +void bitsetSet(uintptr_t* p, unsigned i, bool v) +{ + if (i >= BitsPerWord - 1) { + i += (BitsPerWord * 2) + 1; + if (v) { + p[0] |= BitsetExtensionBit; + if (p[2] <= wordOf(i) - 3) + p[2] = wordOf(i) - 2; + } + } + + if (v) { + markBit(p, i); + } else { + clearBit(p, i); + } +} + +bool bitsetHasMore(uintptr_t* p) +{ + switch (*p) { + case 0: + return false; + + case BitsetExtensionBit: { + uintptr_t length = p[2]; + uintptr_t word = wordOf(p[1]); + for (; word < length; ++word) { + if (p[word + 3]) { + p[1] = indexOf(word, 0); + return true; + } + } + p[1] = indexOf(word, 0); + return false; + } + + default: + return true; + } +} + +unsigned bitsetNext(Context* c, uintptr_t* p) +{ + bool more UNUSED = bitsetHasMore(p); + assertT(c, more); + + switch (*p) { + case 0: + abort(c); + + case BitsetExtensionBit: { + uintptr_t i = p[1]; + uintptr_t word = wordOf(i); + assertT(c, word < p[2]); + for (uintptr_t bit = bitOf(i); bit < BitsPerWord; ++bit) { + if (p[word + 3] & (static_cast(1) << bit)) { + p[1] = indexOf(word, bit) + 1; + bitsetSet(p, p[1] + BitsPerWord - 2, false); + return p[1] + BitsPerWord - 2; + } + } + abort(c); + } + + default: { + for (unsigned i = 0; i < BitsPerWord - 1; ++i) { + if (*p & (static_cast(1) << i)) { + bitsetSet(p, i, false); + return i; + } + } + abort(c); + } + } +} + +void collect(Context* c, void** p, void* target, unsigned offset) +{ + void* original = maskAlignedPointer(*p); + void* parent_ = 0; + + if (Debug) { + fprintf(stderr, + "update %p (%s) at %p (%s)\n", + maskAlignedPointer(*p), + segment(c, *p), + p, + segment(c, p)); + } + + bool needsVisit; + local::set(p, update(c, maskAlignedPointer(p), target, offset, &needsVisit)); + + if (Debug) { + fprintf(stderr, + " result: %p (%s) (visit? %d)\n", + maskAlignedPointer(*p), + segment(c, *p), + needsVisit); + } + + if (not needsVisit) + return; + +visit : { + void* copy = follow(c, original); + + class Walker : public Heap::Walker { + public: + Walker(Context* c, void* copy, uintptr_t* bitset) + : c(c), + copy(copy), + bitset(bitset), + first(0), + second(0), + last(0), + visits(0), + total(0) + { + } + + virtual bool visit(unsigned offset) + { + if (Debug) { + fprintf(stderr, + " update %p (%s) at %p - offset %d from %p (%s)\n", + get(copy, offset), + segment(c, get(copy, offset)), + getp(copy, offset), + offset, + copy, + segment(c, copy)); + } + + bool needsVisit; + void* childCopy + = update(c, getp(copy, offset), copy, offset, &needsVisit); + + if (Debug) { + fprintf(stderr, + " result: %p (%s) (visit? %d)\n", + childCopy, + segment(c, childCopy), + needsVisit); + } + + ++total; + + if (total == 3) { + bitsetInit(bitset); + } + + if (needsVisit) { + ++visits; + + if (visits == 1) { + first = offset; + } else if (visits == 2) { + second = offset; + } + } else { + local::set(copy, offset, childCopy); + } + + if (visits > 1 and total > 2 and (second or needsVisit)) { + bitsetClear(bitset, last, offset); + last = offset; + + if (second) { + bitsetSet(bitset, second, true); + second = 0; + } + + if (needsVisit) { + bitsetSet(bitset, offset, true); + } + } + + return true; + } + + Context* c; + void* copy; + uintptr_t* bitset; + unsigned first; + unsigned second; + unsigned last; + unsigned visits; + unsigned total; + } walker(c, copy, bitset(c, original)); + + if (Debug) { + fprintf(stderr, "walk %p (%s)\n", copy, segment(c, copy)); + } + + c->client->walk(copy, &walker); + + if (walker.visits) { + // descend + if (walker.visits > 1) { + parent(c, original) = parent_; + parent_ = original; + } + + original = get(copy, walker.first); + local::set(copy, walker.first, follow(c, original)); + goto visit; + } else { + // ascend + original = parent_; + } +} + + if (original) { + void* copy = follow(c, original); + + class Walker : public Heap::Walker { + public: + Walker(Context* c, uintptr_t* bitset) + : c(c), bitset(bitset), next(0), total(0) + { + } + + virtual bool visit(unsigned offset) + { + switch (++total) { + case 1: + return true; + + case 2: + next = offset; + return true; + + case 3: + next = bitsetNext(c, bitset); + return false; + + default: + abort(c); + } + } + + Context* c; + uintptr_t* bitset; + unsigned next; + unsigned total; + } walker(c, bitset(c, original)); + + if (Debug) { + fprintf(stderr, "scan %p\n", copy); + } + + c->client->walk(copy, &walker); + + assertT(c, walker.total > 1); + + if (walker.total == 3 and bitsetHasMore(bitset(c, original))) { + parent_ = original; + } else { + parent_ = parent(c, original); + } + + if (Debug) { + fprintf(stderr, + " next is %p (%s) at %p - offset %d from %p (%s)\n", + get(copy, walker.next), + segment(c, get(copy, walker.next)), + getp(copy, walker.next), + walker.next, + copy, + segment(c, copy)); + } + + original = get(copy, walker.next); + local::set(copy, walker.next, follow(c, original)); + goto visit; + } else { + return; + } +} + +void collect(Context* c, void** p) +{ + collect(c, p, 0, 0); +} + +void collect(Context* c, void* target, unsigned offset) +{ + collect(c, getp(target, offset), target, offset); +} + +void visitDirtyFixies(Context* c, Fixie** p) +{ + while (*p) { + Fixie* f = *p; + + bool wasDirty UNUSED = false; + bool clean = true; + uintptr_t* mask = f->mask(); + + unsigned word = 0; + unsigned bit = 0; + unsigned wordLimit = wordOf(f->size); + unsigned bitLimit = bitOf(f->size); + + if (DebugFixies) { + fprintf(stderr, "clean fixie %p\n", f); + } + + for (; word <= wordLimit and (word < wordLimit or bit < bitLimit); ++word) { + if (mask[word]) { + for (; bit < BitsPerWord and (word < wordLimit or bit < bitLimit); + ++bit) { + unsigned index = indexOf(word, bit); + + if (getBit(mask, index)) { + wasDirty = true; + + clearBit(mask, index); + + if (DebugFixies) { + fprintf(stderr, + "clean fixie %p at %d (%p)\n", + f, + index, + f->body() + index); + } + + collect(c, f->body(), index); + + if (getBit(mask, index)) { + clean = false; + } + } + } + bit = 0; + } + } + + if (DebugFixies) { + fprintf(stderr, "done cleaning fixie %p\n", f); + } + + assertT(c, wasDirty); + + if (clean) { + markClean(c, f); + } else { + p = &(f->next); + } + } +} + +void visitMarkedFixies(Context* c) +{ + while (c->markedFixies) { + Fixie* f = c->markedFixies; + f->remove(c); + + if (DebugFixies) { + fprintf(stderr, "visit fixie %p\n", f); + } + + class Walker : public Heap::Walker { + public: + Walker(Context* c, void** p) : c(c), p(p) + { + } + + virtual bool visit(unsigned offset) + { + local::collect(c, p, offset); + return true; + } + + Context* c; + void** p; + } w(c, f->body()); + + c->client->walk(f->body(), &w); + + f->move(c, &(c->visitedFixies)); + } +} + +void collect(Context* c, + Segment::Map* map, + unsigned start, + unsigned end, + bool* dirty, + bool expectDirty UNUSED) +{ + bool wasDirty UNUSED = false; + for (Segment::Map::Iterator it(map, start, end); it.hasMore();) { + wasDirty = true; + if (map->child) { + assertT(c, map->scale > 1); + unsigned s = it.next(); + unsigned e = s + map->scale; + + map->clearOnly(s); + bool childDirty = false; + collect(c, map->child, s, e, &childDirty, true); + if (childDirty) { + map->setOnly(s); + *dirty = true; + } + } else { + assertT(c, map->scale == 1); + void** p = reinterpret_cast(map->segment->get(it.next())); + + map->clearOnly(p); + if (c->nextGen1.contains(*p)) { + map->setOnly(p); + *dirty = true; + } else { + collect(c, p); + + if (not c->gen2.contains(*p)) { + map->setOnly(p); + *dirty = true; + } + } + } + } + + assertT(c, wasDirty or not expectDirty); +} + +void collect2(Context* c) +{ + c->gen2Base = Top; + c->tenureFootprint = 0; + c->fixieTenureFootprint = 0; + c->gen1Padding = 0; + c->tenurePadding = 0; + + if (c->mode == Heap::MajorCollection) { + c->gen2Padding = 0; + } + + if (c->mode == Heap::MinorCollection and c->gen2.position()) { + unsigned start = 0; + unsigned end = start + c->gen2.position(); + bool dirty; + collect(c, &(c->heapMap), start, end, &dirty, false); + } + + if (c->mode == Heap::MinorCollection) { + visitDirtyFixies(c, &(c->dirtyTenuredFixies)); + } + + class Visitor : public Heap::Visitor { + public: + Visitor(Context* c) : c(c) + { + } + + virtual void visit(void* p) + { + local::collect(c, static_cast(p)); + visitMarkedFixies(c); + } + + Context* c; + } v(c); + + c->client->visitRoots(&v); +} + +bool limitExceeded(Context* c, int pendingAllocation) +{ + unsigned count = c->count + pendingAllocation + - (c->gen2.remaining() * BytesPerWord); + + if (Verbose) { + if (count > c->limit) { + if (not c->limitWasExceeded) { + c->limitWasExceeded = true; + fprintf(stderr, "heap limit %d exceeded: %d\n", c->limit, count); + } + } else if (c->limitWasExceeded) { + c->limitWasExceeded = false; + fprintf( + stderr, "heap limit %d no longer exceeded: %d\n", c->limit, count); + } + } + + return count > c->limit; +} + +void collect(Context* c) +{ + if (limitExceeded(c, c->pendingAllocation) or oversizedGen2(c) + or c->tenureFootprint + c->tenurePadding > c->gen2.remaining() + or c->fixieTenureFootprint + c->tenuredFixieFootprint + > c->tenuredFixieCeiling) { + if (Verbose) { + if (limitExceeded(c, c->pendingAllocation)) { + fprintf(stderr, "low memory causes "); + } else if (oversizedGen2(c)) { + fprintf(stderr, "oversized gen2 causes "); + } else if (c->tenureFootprint + c->tenurePadding > c->gen2.remaining()) { + fprintf(stderr, "undersized gen2 causes "); + } else { + fprintf(stderr, "fixie ceiling causes "); + } + } + + c->mode = Heap::MajorCollection; + } + + int64_t then; + if (Verbose) { + if (c->mode == Heap::MajorCollection) { + fprintf(stderr, "major collection\n"); + } else { + fprintf(stderr, "minor collection\n"); + } + + then = c->system->now(); + } + + initNextGen1(c); + + if (c->mode == Heap::MajorCollection) { + initNextGen2(c); + } + + collect2(c); + + c->gen1.replaceWith(&(c->nextGen1)); + if (c->mode == Heap::MajorCollection) { + c->gen2.replaceWith(&(c->nextGen2)); + } + + sweepFixies(c); + + if (Verbose) { + int64_t now = c->system->now(); + int64_t collection = now - then; + int64_t run = then - c->lastCollectionTime; + c->totalCollectionTime += collection; + c->totalTime += collection + run; + c->lastCollectionTime = now; + + fprintf(stderr, + " - collect: %4dms; " + "total: %4dms; " + "run: %4dms; " + "total: %4dms\n", + static_cast(collection), + static_cast(c->totalCollectionTime), + static_cast(run), + static_cast(c->totalTime - c->totalCollectionTime)); + + fprintf(stderr, + " - gen1: %8d/%8d bytes\n", + c->gen1.position() * BytesPerWord, + c->gen1.capacity() * BytesPerWord); + + fprintf(stderr, + " - gen2: %8d/%8d bytes\n", + c->gen2.position() * BytesPerWord, + c->gen2.capacity() * BytesPerWord); + + fprintf(stderr, + " - untenured fixies: %8d bytes\n", + c->untenuredFixieFootprint); + + fprintf(stderr, + " - tenured fixies: %8d bytes\n", + c->tenuredFixieFootprint); + } +} + +void* allocate(Context* c, size_t size, bool limit) +{ + ACQUIRE(c->lock); + + if (DebugAllocation) { + size = pad(size) + 2 * BytesPerWord; + } + + if ((not limit) or size + c->count < c->limit) { + void* p = c->system->tryAllocate(size); + if (p) { + c->count += size; + + if (DebugAllocation) { + static_cast(p)[0] = 0x22377322; + static_cast(p)[(size / BytesPerWord) - 1] = 0x22377322; + return static_cast(p) + 1; + } else { + return p; + } + } + } + return 0; +} + +void* tryAllocate(Context* c, size_t size) +{ + return allocate(c, size, true); +} + +void* allocate(Context* c, size_t size) +{ + void* p = allocate(c, size, false); + expect(c->system, p); + + return p; +} + +void free(Context* c, const void* p, size_t size) +{ + ACQUIRE(c->lock); + + if (DebugAllocation) { + size = pad(size) + 2 * BytesPerWord; + + memset(const_cast(p), 0xFE, size - (2 * BytesPerWord)); + + p = static_cast(p) - 1; + + expect(c->system, static_cast(p)[0] == 0x22377322); + + expect(c->system, + static_cast(p)[(size / BytesPerWord) - 1] + == 0x22377322); + } + + expect(c->system, c->count >= size); + + c->system->free(p); + c->count -= size; +} + +void free_(Context* c, const void* p, size_t size) +{ + free(c, p, size); +} + +class MyHeap : public Heap { + public: + MyHeap(System* system, unsigned limit) : c(system, limit) + { + } + + virtual void setClient(Heap::Client* client) + { + assertT(&c, c.client == 0); + c.client = client; + } + + virtual void setImmortalHeap(uintptr_t* start, unsigned sizeInWords) + { + c.immortalHeapStart = start; + c.immortalHeapEnd = start + sizeInWords; + } + + virtual unsigned remaining() + { + return c.limit - c.count; + } + + virtual unsigned limit() + { + return c.limit; + } + + virtual bool limitExceeded(int pendingAllocation = 0) + { + return local::limitExceeded(&c, pendingAllocation); + } + + virtual void* tryAllocate(size_t size) + { + return local::tryAllocate(&c, size); + } + + virtual void* allocate(size_t size) + { + return local::allocate(&c, size); + } + + virtual void free(const void* p, size_t size) + { + free_(&c, p, size); + } + + virtual void collect(CollectionType type, + unsigned incomingFootprint, + int pendingAllocation) + { + c.mode = type; + c.incomingFootprint = incomingFootprint; + c.pendingAllocation = pendingAllocation; + + local::collect(&c); + } + + virtual unsigned fixedFootprint(unsigned sizeInWords, bool objectMask) + { + return Fixie::totalSize(sizeInWords, objectMask); + } + + void* allocateFixed(Alloc* allocator, + unsigned sizeInWords, + bool objectMask, + Fixie** handle, + bool immortal) + { + expect(&c, not limitExceeded()); + + unsigned total = Fixie::totalSize(sizeInWords, objectMask); + void* p = allocator->allocate(total); + + expect(&c, not limitExceeded()); + + return (new (p) Fixie(&c, sizeInWords, objectMask, handle, immortal)) + ->body(); + } + + virtual void* allocateFixed(Alloc* allocator, + unsigned sizeInWords, + bool objectMask) + { + return allocateFixed( + allocator, sizeInWords, objectMask, &(c.fixies), false); + } + + virtual void* allocateImmortalFixed(Alloc* allocator, + unsigned sizeInWords, + bool objectMask) + { + return allocateFixed(allocator, sizeInWords, objectMask, 0, true); + } + + bool needsMark(void* p) + { + assertT(&c, c.client->isFixed(p) or (not immortalHeapContains(&c, p))); + + if (c.client->isFixed(p)) { + return fixie(p)->age >= FixieTenureThreshold; + } else { + return c.gen2.contains(p) or c.nextGen2.contains(p); + } + } + + bool targetNeedsMark(void* target) + { + return target and not c.gen2.contains(target) + and not c.nextGen2.contains(target) + and not immortalHeapContains(&c, target) + and not(c.client->isFixed(target) + and fixie(target)->age >= FixieTenureThreshold); + } + + virtual void mark(void* p, unsigned offset, unsigned count) + { + if (needsMark(p)) { +#ifndef USE_ATOMIC_OPERATIONS + ACQUIRE(c.lock); +#endif + + if (c.client->isFixed(p)) { + Fixie* f = fixie(p); + assertT(&c, offset == 0 or f->hasMask()); + + bool dirty = false; + for (unsigned i = 0; i < count; ++i) { + void** target = static_cast(p) + offset + i; + if (targetNeedsMark(maskAlignedPointer(*target))) { + if (DebugFixies) { + fprintf(stderr, + "dirty fixie %p at %d (%p): %p\n", + f, + offset, + f->body() + offset, + maskAlignedPointer(*target)); + } + + dirty = true; +#ifdef USE_ATOMIC_OPERATIONS + markBitAtomic(f->mask(), offset + i); +#else + markBit(f->mask(), offset + i); +#endif + assertT(&c, getBit(f->mask(), offset + i)); + } + } + + if (dirty) + markDirty(&c, f); + } else { + Segment::Map* map; + if (c.gen2.contains(p)) { + map = &(c.heapMap); + } else { + assertT(&c, c.nextGen2.contains(p)); + map = &(c.nextHeapMap); + } + + for (unsigned i = 0; i < count; ++i) { + void** target = static_cast(p) + offset + i; + if (targetNeedsMark(maskAlignedPointer(*target))) { +#ifdef USE_ATOMIC_OPERATIONS + map->markAtomic(target); +#else + map->set(target); +#endif + } + } + } + } + } + + virtual void pad(void* p) + { + if (c.gen1.contains(p)) { + if (c.ageMap.get(p) == TenureThreshold) { + ++c.tenurePadding; + } else { + ++c.gen1Padding; + } + } else if (c.gen2.contains(p)) { + ++c.gen2Padding; + } else { + ++c.gen1Padding; + } + } + + virtual void* follow(void* p) + { + if (p == 0 or c.client->isFixed(p)) { + return p; + } else if (wasCollected(&c, p)) { + if (Debug) { + fprintf(stderr, + "follow %p (%s) to %p (%s)\n", + p, + segment(&c, p), + local::follow(&c, p), + segment(&c, local::follow(&c, p))); + } + + return local::follow(&c, p); + } else { + return p; + } + } + + virtual void postVisit() + { + killFixies(&c); + } + + virtual Status status(void* p) + { + p = maskAlignedPointer(p); + + if (p == 0) { + return Null; + } else if (c.client->isFixed(p)) { + Fixie* f = fixie(p); + return f->dead() ? Unreachable : (static_cast(f->age + 1) + < FixieTenureThreshold + ? Reachable + : Tenured); + } else if (c.nextGen1.contains(p)) { + return Reachable; + } else if (c.nextGen2.contains(p) or immortalHeapContains(&c, p) + or (c.gen2.contains(p) + and (c.mode == Heap::MinorCollection + or c.gen2.indexOf(p) >= c.gen2Base))) { + return Tenured; + } else if (wasCollected(&c, p)) { + return Reachable; + } else { + return Unreachable; + } + } + + virtual CollectionType collectionType() + { + return c.mode; + } + + virtual void disposeFixies() + { + c.disposeFixies(); + } + + virtual void dispose() + { + c.dispose(); + assertT(&c, c.count == 0); + c.system->free(this); + } + + Context c; +}; + +} // namespace local + +} // namespace + +namespace vm { + +Heap* makeHeap(System* system, unsigned limit) +{ + return new (system->tryAllocate(sizeof(local::MyHeap))) + local::MyHeap(system, limit); +} + +} // namespace vm diff --git a/sgx-jvm/avian/src/heapdump.cpp b/sgx-jvm/avian/src/heapdump.cpp new file mode 100644 index 0000000000..813d8cfd84 --- /dev/null +++ b/sgx-jvm/avian/src/heapdump.cpp @@ -0,0 +1,115 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#include "avian/machine.h" +#include "avian/heapwalk.h" + +using namespace vm; + +namespace { + +namespace local { + +enum { Root, Size, ClassName, Push, Pop }; + +void write1(FILE* out, uint8_t v) +{ + size_t n UNUSED = fwrite(&v, 1, 1, out); +} + +void write4(FILE* out, uint32_t v) +{ + uint8_t b[] = {static_cast(v >> 24), + static_cast((v >> 16) & 0xFF), + static_cast((v >> 8) & 0xFF), + static_cast(v & 0xFF)}; + + size_t n UNUSED = fwrite(b, 4, 1, out); +} + +void writeString(FILE* out, int8_t* p, unsigned size) +{ + write4(out, size); + size_t n UNUSED = fwrite(p, size, 1, out); +} + +unsigned objectSize(Thread* t, object o) +{ + return extendedSize(t, o, baseSize(t, o, objectClass(t, o))); +} + +} // namespace local + +} // namespace + +namespace vm { + +void dumpHeap(Thread* t, FILE* out) +{ + class Visitor : public HeapVisitor { + public: + Visitor(Thread* t, FILE* out) : t(t), out(out), nextNumber(1) + { + } + + virtual void root() + { + write1(out, local::Root); + } + + virtual unsigned visitNew(object p) + { + if (p) { + unsigned number = nextNumber++; + local::write4(out, number); + + local::write1(out, local::Size); + local::write4(out, local::objectSize(t, p)); + + if (objectClass(t, p) == type(t, GcClass::Type)) { + GcByteArray* name = static_cast(p)->name(); + if (name) { + local::write1(out, local::ClassName); + local::writeString(out, name->body().begin(), name->length() - 1); + } + } + + return number; + } else { + return 0; + } + } + + virtual void visitOld(object, unsigned number) + { + local::write4(out, number); + } + + virtual void push(object, unsigned, unsigned) + { + local::write1(out, local::Push); + } + + virtual void pop() + { + local::write1(out, local::Pop); + } + + Thread* t; + FILE* out; + unsigned nextNumber; + } visitor(t, out); + + HeapWalker* w = makeHeapWalker(t, &visitor); + w->visitAllRoots(); + w->dispose(); +} + +} // namespace vm diff --git a/sgx-jvm/avian/src/heapwalk.cpp b/sgx-jvm/avian/src/heapwalk.cpp new file mode 100644 index 0000000000..24efa50246 --- /dev/null +++ b/sgx-jvm/avian/src/heapwalk.cpp @@ -0,0 +1,335 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#include "avian/machine.h" +#include "avian/heapwalk.h" + +using namespace vm; + +namespace { + +namespace local { + +const uintptr_t PointerShift = log(BytesPerWord); + +class Context; + +class Set : public HeapMap { + public: + class Entry { + public: + object value; + uint32_t number; + int next; + }; + + static unsigned footprint(unsigned capacity) + { + return sizeof(Set) + pad(sizeof(int) * capacity) + + pad(sizeof(Set::Entry) * capacity); + } + + Set(Context* context, unsigned capacity) + : context(context), + index(reinterpret_cast(reinterpret_cast(this) + + sizeof(Set))), + entries(reinterpret_cast(reinterpret_cast(index) + + pad(sizeof(int) * capacity))), + size(0), + capacity(capacity) + { + } + + virtual int find(object value); + + virtual void dispose(); + + Context* context; + int* index; + Entry* entries; + unsigned size; + unsigned capacity; +}; + +class Stack { + public: + class Entry { + public: + object value; + int offset; + }; + + static const unsigned Capacity = 4096; + + Stack(Stack* next) : next(next), entryCount(0) + { + } + + Stack* next; + unsigned entryCount; + Entry entries[Capacity]; +}; + +class Context { + public: + Context(Thread* thread) : thread(thread), objects(0), stack(0) + { + } + + void dispose() + { + if (objects) { + objects->dispose(); + } + + while (stack) { + Stack* dead = stack; + stack = dead->next; + thread->m->heap->free(dead, sizeof(Stack)); + } + } + + Thread* thread; + Set* objects; + Stack* stack; +}; + +void push(Context* c, object p, int offset) +{ + if (c->stack == 0 or c->stack->entryCount == Stack::Capacity) { + c->stack = new (c->thread->m->heap->allocate(sizeof(Stack))) + Stack(c->stack); + } + Stack::Entry* e = c->stack->entries + (c->stack->entryCount++); + e->value = p; + e->offset = offset; +} + +bool pop(Context* c, object* p, int* offset) +{ + if (c->stack) { + if (c->stack->entryCount == 0) { + if (c->stack->next) { + Stack* dead = c->stack; + c->stack = dead->next; + c->thread->m->heap->free(dead, sizeof(Stack)); + } else { + return false; + } + } + Stack::Entry* e = c->stack->entries + (--c->stack->entryCount); + *p = e->value; + *offset = e->offset; + return true; + } else { + return false; + } +} + +unsigned hash(object p, unsigned capacity) +{ + return (reinterpret_cast(p) >> PointerShift) & (capacity - 1); +} + +Set::Entry* find(Context* c, object p) +{ + if (c->objects == 0) + return 0; + + for (int i = c->objects->index[hash(p, c->objects->capacity)]; i >= 0;) { + Set::Entry* e = c->objects->entries + i; + if (e->value == p) { + return e; + } + i = e->next; + } + + return 0; +} + +int Set::find(object value) +{ + Set::Entry* e = local::find(context, value); + if (e) { + return e->number; + } else { + return -1; + } +} + +void Set::dispose() +{ + context->thread->m->heap->free(this, footprint(capacity)); +} + +Set::Entry* add(Context* c UNUSED, Set* set, object p, uint32_t number) +{ + assertT(c->thread, set->size < set->capacity); + + unsigned index = hash(p, set->capacity); + + int offset = set->size++; + Set::Entry* e = set->entries + offset; + e->value = p; + e->number = number; + e->next = set->index[index]; + set->index[index] = offset; + return e; +} + +Set::Entry* add(Context* c, object p) +{ + if (c->objects == 0 or c->objects->size == c->objects->capacity) { + unsigned capacity; + if (c->objects) { + capacity = c->objects->capacity * 2; + } else { + capacity = 4096; // must be power of two + } + + Set* set = new (c->thread->m->heap->allocate(Set::footprint(capacity))) + Set(c, capacity); + + memset(set->index, 0xFF, sizeof(int) * capacity); + + if (c->objects) { + for (unsigned i = 0; i < c->objects->capacity; ++i) { + for (int j = c->objects->index[i]; j >= 0;) { + Set::Entry* e = c->objects->entries + j; + add(c, set, e->value, e->number); + j = e->next; + } + } + + c->thread->m->heap->free(c->objects, + Set::footprint(c->objects->capacity)); + } + + c->objects = set; + } + + return add(c, c->objects, p, 0); +} + +inline object get(object o, unsigned offsetInWords) +{ + return static_cast(maskAlignedPointer( + fieldAtOffset(o, offsetInWords * BytesPerWord))); +} + +unsigned walk(Context* c, HeapVisitor* v, object p) +{ + Thread* t = c->thread; + object root = p; + int nextChildOffset; + + v->root(); + +visit : { + Set::Entry* e = find(c, p); + if (e) { + v->visitOld(p, e->number); + } else { + e = add(c, p); + e->number = v->visitNew(p); + + nextChildOffset = walkNext(t, p, -1); + if (nextChildOffset != -1) { + goto children; + } + } +} + + goto pop; + +children : { + v->push(p, find(c, p)->number, nextChildOffset); + push(c, p, nextChildOffset); + p = get(p, nextChildOffset); + goto visit; +} + +pop : { + if (pop(c, &p, &nextChildOffset)) { + v->pop(); + nextChildOffset = walkNext(t, p, nextChildOffset); + if (nextChildOffset >= 0) { + goto children; + } else { + goto pop; + } + } +} + + return find(c, root)->number; +} + +class MyHeapWalker : public HeapWalker { + public: + MyHeapWalker(Thread* t, HeapVisitor* v) : context(t), visitor(v) + { + add(&context, 0)->number = v->visitNew(0); + } + + virtual unsigned visitRoot(object root) + { + return walk(&context, visitor, root); + } + + virtual void visitAllRoots() + { + class Visitor : public Heap::Visitor { + public: + Visitor(Context* c, HeapVisitor* v) : c(c), v(v) + { + } + + virtual void visit(void* p) + { + walk(c, + v, + static_cast(maskAlignedPointer(*static_cast(p)))); + } + + Context* c; + HeapVisitor* v; + } v(&context, visitor); + + visitRoots(context.thread->m, &v); + } + + virtual HeapMap* map() + { + return context.objects; + } + + virtual void dispose() + { + context.dispose(); + context.thread->m->heap->free(this, sizeof(MyHeapWalker)); + } + + Context context; + HeapVisitor* visitor; +}; + +} // namespace local + +} // namespace + +namespace vm { + +HeapWalker* makeHeapWalker(Thread* t, HeapVisitor* v) +{ + return new (t->m->heap->allocate(sizeof(local::MyHeapWalker))) + local::MyHeapWalker(t, v); +} + +} // namespace vm diff --git a/sgx-jvm/avian/src/i386.S b/sgx-jvm/avian/src/i386.S new file mode 100644 index 0000000000..47acd677e3 --- /dev/null +++ b/sgx-jvm/avian/src/i386.S @@ -0,0 +1,145 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#include "avian/types.h" + +#define LOCAL(x) .L##x + +#if defined __APPLE__ \ + || ((defined __MINGW32__ || defined __CYGWIN32__) && ! defined __x86_64__) +# define GLOBAL(x) _##x +#else +# define GLOBAL(x) x +#endif + +.text + +#define CHECKPOINT_THREAD 4 +#define CHECKPOINT_STACK 24 +#define CHECKPOINT_BASE 28 + +.globl GLOBAL(vmNativeCall) +GLOBAL(vmNativeCall): + pushl %ebp + movl %esp,%ebp + + // 8(%ebp): function + // 12(%ebp): stack + // 16(%ebp): stackSize + // 20(%ebp): returnType + + // reserve space for arguments + movl 16(%ebp),%ecx + + subl %ecx,%esp + +//# ifdef __APPLE__ + // align to a 16 byte boundary + andl $0xFFFFFFF0,%esp +//# endif + + // copy arguments into place + movl $0,%ecx + jmp LOCAL(test) + +LOCAL(loop): + movl %ecx,%eax + movl %ecx,%edx + addl %esp,%edx + addl 12(%ebp),%eax + movl (%eax),%eax + movl %eax,(%edx) + addl $4,%ecx + +LOCAL(test): + cmpl 16(%ebp),%ecx + jb LOCAL(loop) + + // call function + call *8(%ebp) + + // handle return value based on expected type + movl 20(%ebp),%ecx + +LOCAL(void): + cmpl $VOID_TYPE,%ecx + jne LOCAL(int64) + jmp LOCAL(exit) + +LOCAL(int64): + cmpl $INT64_TYPE,%ecx + jne LOCAL(float) + jmp LOCAL(exit) + +LOCAL(float): + cmpl $FLOAT_TYPE,%ecx + jne LOCAL(double) + fstps 8(%ebp) + movl 8(%ebp),%eax + jmp LOCAL(exit) + +LOCAL(double): + cmpl $DOUBLE_TYPE,%ecx + jne LOCAL(exit) + fstpl 8(%ebp) + movl 8(%ebp),%eax + movl 12(%ebp),%edx + +LOCAL(exit): + movl %ebp,%esp + popl %ebp + ret + +.globl GLOBAL(vmJump) +GLOBAL(vmJump): + movl 4(%esp),%esi + movl 8(%esp),%ebp + movl 16(%esp),%ebx + movl 20(%esp),%eax + movl 24(%esp),%edx + movl 12(%esp),%esp + jmp *%esi + +#define VMRUN_FRAME_SIZE 24 + +.globl GLOBAL(vmRun) +GLOBAL(vmRun): + // 8(%ebp): function + // 12(%ebp): arguments + // 16(%ebp): checkpoint + pushl %ebp + movl %esp,%ebp + subl $VMRUN_FRAME_SIZE,%esp + + movl %ebx,8(%esp) + movl %esi,12(%esp) + movl %edi,16(%esp) + + movl 12(%ebp),%eax + movl %eax,4(%esp) + + movl 16(%ebp),%ecx + movl CHECKPOINT_THREAD(%ecx),%eax + movl %eax,0(%esp) + + movl %esp,CHECKPOINT_STACK(%ecx) + + call *8(%ebp) + +.globl GLOBAL(vmRun_returnAddress) +GLOBAL(vmRun_returnAddress): + + movl 8(%esp),%ebx + movl 12(%esp),%esi + movl 16(%esp),%edi + + addl $VMRUN_FRAME_SIZE,%esp + popl %ebp + ret diff --git a/sgx-jvm/avian/src/i386.masm b/sgx-jvm/avian/src/i386.masm new file mode 100644 index 0000000000..e44c82c2c5 --- /dev/null +++ b/sgx-jvm/avian/src/i386.masm @@ -0,0 +1,134 @@ +comment # + Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. + + ORIGIN: https://github.com/gkvas/avian/tree/wince +# + +.586 +.MODEL FLAT, C + +VOID_TYPE equ 0 +INT8_TYPE equ 1 +INT16_TYPE equ 2 +INT32_TYPE equ 3 +INT64_TYPE equ 4 +FLOAT_TYPE equ 5 +DOUBLE_TYPE equ 6 +POINTER_TYPE equ 7 + +CHECKPOINT_THREAD equ 4 +CHECKPOINT_STACK equ 24 +CHECKPOINT_BASE equ 28 + +_TEXT SEGMENT + +public C vmNativeCall +vmNativeCall: + push ebp + mov ebp,esp + mov ecx,ds:dword ptr[16+ebp] + sub esp,ecx + mov ecx,0 + jmp Ltest + +Lloop: + mov eax,ecx + mov edx,ecx + add edx,esp + add eax,ds:dword ptr[12+ebp] + mov eax,ds:dword ptr[eax] + mov ds:dword ptr[edx],eax + add ecx,4 + +Ltest: + cmp ecx,ds:dword ptr[16+ebp] + jb Lloop + call dword ptr[8+ebp] + mov ecx,ds:dword ptr[20+ebp] + +Lvoid: + cmp ecx,offset VOID_TYPE + jne Lint64 + jmp Lexit + +Lint64: + cmp ecx,offset INT64_TYPE + jne Lfloat + jmp Lexit + +Lfloat: + cmp ecx,offset FLOAT_TYPE + jne Ldouble + fstp ds:dword ptr[8+ebp] + mov eax,ds:dword ptr[8+ebp] + jmp Lexit + +Ldouble: + cmp ecx,offset DOUBLE_TYPE + jne Lexit + fstp ds:qword ptr[8+ebp] + mov eax,ds:dword ptr[8+ebp] + mov edx,ds:dword ptr[12+ebp] + +Lexit: + mov esp,ebp + pop ebp + ret + +public C vmJump +vmJump: + mov esi,ds:dword ptr[4+esp] + mov ebp,ds:dword ptr[8+esp] + mov ebx,ds:dword ptr[16+esp] + mov eax,ds:dword ptr[20+esp] + mov edx,ds:dword ptr[24+esp] + mov esp,ds:dword ptr[12+esp] + jmp esi + +VMRUN_FRAME_SIZE equ 24 + +public C vmRun_ +vmRun_: + ; 8(%ebp): function + ; 12(%ebp): arguments + ; 16(%ebp): checkpoint + push ebp + mov ebp,esp + sub esp,offset VMRUN_FRAME_SIZE + + mov ds:dword ptr[8+esp],ebx + mov ds:dword ptr[12+esp],esi + mov ds:dword ptr[16+esp],edi + + mov eax,ds:dword ptr[12+ebp] + mov ds:dword ptr[4+esp],eax + + mov ecx,ds:dword ptr[16+ebp] + mov eax,ds:dword ptr[CHECKPOINT_THREAD+ecx] + mov ds:dword ptr[0+esp],eax + + mov ds:dword ptr[CHECKPOINT_STACK+ecx],esp + + call dword ptr[8+ebp] + +public C vmRun_returnAddress +vmRun_returnAddress: + + mov ebx,ds:dword ptr[8+esp] + mov esi,ds:dword ptr[12+esp] + mov edi,ds:dword ptr[16+esp] + + add esp,offset VMRUN_FRAME_SIZE + pop ebp + ret + +_TEXT ENDS +END \ No newline at end of file diff --git a/sgx-jvm/avian/src/interpret.cpp b/sgx-jvm/avian/src/interpret.cpp new file mode 100644 index 0000000000..12ddc9e0bb --- /dev/null +++ b/sgx-jvm/avian/src/interpret.cpp @@ -0,0 +1,3609 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#include "avian/common.h" +#include +#include +#include "avian/constants.h" +#include "avian/machine.h" +#include "avian/processor.h" +#include "avian/process.h" +#include "avian/arch.h" + +#include +#include +#include + +using namespace vm; +using namespace avian::system; + +namespace local { + +const unsigned FrameBaseOffset = 0; +const unsigned FrameNextOffset = 1; +const unsigned FrameMethodOffset = 2; +const unsigned FrameIpOffset = 3; +const unsigned FrameFootprint = 4; + +class Thread : public vm::Thread { + public: + Thread(Machine* m, GcThread* javaThread, vm::Thread* parent) + : vm::Thread(m, javaThread, parent), + ip(0), + sp(0), + frame(-1), + code(0), + stackPointers(0) + { + } + + unsigned ip; + unsigned sp; + int frame; + GcCode* code; + List* stackPointers; + uintptr_t stack[0]; +}; + +inline void pushObject(Thread* t, object o) +{ + if (DebugStack) { + fprintf(stderr, "push object %p at %d\n", o, t->sp); + } + + assertT(t, t->sp + 1 < stackSizeInWords(t) / 2); + t->stack[(t->sp * 2)] = ObjectTag; + t->stack[(t->sp * 2) + 1] = reinterpret_cast(o); + ++t->sp; +} + +inline void pushInt(Thread* t, uint32_t v) +{ + if (DebugStack) { + fprintf(stderr, "push int %d at %d\n", v, t->sp); + } + + assertT(t, t->sp + 1 < stackSizeInWords(t) / 2); + t->stack[(t->sp * 2)] = IntTag; + t->stack[(t->sp * 2) + 1] = v; + ++t->sp; +} + +inline void pushFloat(Thread* t, float v) +{ + pushInt(t, floatToBits(v)); +} + +inline void pushLong(Thread* t, uint64_t v) +{ + if (DebugStack) { + fprintf(stderr, "push long %" LLD " at %d\n", v, t->sp); + } + + pushInt(t, v >> 32); + pushInt(t, v & 0xFFFFFFFF); +} + +inline void pushDouble(Thread* t, double v) +{ + uint64_t w = doubleToBits(v); + pushLong(t, w); +} + +inline object popObject(Thread* t) +{ + if (DebugStack) { + fprintf(stderr, + "pop object %p at %d\n", + reinterpret_cast(t->stack[((t->sp - 1) * 2) + 1]), + t->sp - 1); + } + + assertT(t, t->stack[(t->sp - 1) * 2] == ObjectTag); + return reinterpret_cast(t->stack[((--t->sp) * 2) + 1]); +} + +inline uint32_t popInt(Thread* t) +{ + if (DebugStack) { + fprintf(stderr, + "pop int %" LD " at %d\n", + t->stack[((t->sp - 1) * 2) + 1], + t->sp - 1); + } + + assertT(t, t->stack[(t->sp - 1) * 2] == IntTag); + return t->stack[((--t->sp) * 2) + 1]; +} + +inline float popFloat(Thread* t) +{ + return bitsToFloat(popInt(t)); +} + +inline uint64_t popLong(Thread* t) +{ + if (DebugStack) { + fprintf(stderr, + "pop long %" LLD " at %d\n", + (static_cast(t->stack[((t->sp - 2) * 2) + 1]) << 32) + | static_cast(t->stack[((t->sp - 1) * 2) + 1]), + t->sp - 2); + } + + uint64_t a = popInt(t); + uint64_t b = popInt(t); + return (b << 32) | a; +} + +inline double popDouble(Thread* t) +{ + uint64_t v = popLong(t); + return bitsToDouble(v); +} + +inline object peekObject(Thread* t, unsigned index) +{ + if (DebugStack) { + fprintf(stderr, + "peek object %p at %d\n", + reinterpret_cast(t->stack[(index * 2) + 1]), + index); + } + + assertT(t, index < stackSizeInWords(t) / 2); + assertT(t, t->stack[index * 2] == ObjectTag); + return reinterpret_cast(t->stack[(index * 2) + 1]); +} + +inline uint32_t peekInt(Thread* t, unsigned index) +{ + if (DebugStack) { + fprintf( + stderr, "peek int %" LD " at %d\n", t->stack[(index * 2) + 1], index); + } + + assertT(t, index < stackSizeInWords(t) / 2); + assertT(t, t->stack[index * 2] == IntTag); + return t->stack[(index * 2) + 1]; +} + +inline uint64_t peekLong(Thread* t, unsigned index) +{ + if (DebugStack) { + fprintf(stderr, + "peek long %" LLD " at %d\n", + (static_cast(t->stack[(index * 2) + 1]) << 32) + | static_cast(t->stack[((index + 1) * 2) + 1]), + index); + } + + return (static_cast(peekInt(t, index)) << 32) + | static_cast(peekInt(t, index + 1)); +} + +inline void pokeObject(Thread* t, unsigned index, object value) +{ + if (DebugStack) { + fprintf(stderr, "poke object %p at %d\n", value, index); + } + + t->stack[index * 2] = ObjectTag; + t->stack[(index * 2) + 1] = reinterpret_cast(value); +} + +inline void pokeInt(Thread* t, unsigned index, uint32_t value) +{ + if (DebugStack) { + fprintf(stderr, "poke int %d at %d\n", value, index); + } + + t->stack[index * 2] = IntTag; + t->stack[(index * 2) + 1] = value; +} + +inline void pokeLong(Thread* t, unsigned index, uint64_t value) +{ + if (DebugStack) { + fprintf(stderr, "poke long %" LLD " at %d\n", value, index); + } + + pokeInt(t, index, value >> 32); + pokeInt(t, index + 1, value & 0xFFFFFFFF); +} + +inline object* pushReference(Thread* t, object o) +{ + if (o) { + expect(t, t->sp + 1 < stackSizeInWords(t) / 2); + pushObject(t, o); + return reinterpret_cast(t->stack + ((t->sp - 1) * 2) + 1); + } else { + return 0; + } +} + +inline int frameNext(Thread* t, int frame) +{ + return peekInt(t, frame + FrameNextOffset); +} + +inline GcMethod* frameMethod(Thread* t, int frame) +{ + return cast(t, peekObject(t, frame + FrameMethodOffset)); +} + +inline unsigned frameIp(Thread* t, int frame) +{ + return peekInt(t, frame + FrameIpOffset); +} + +inline unsigned frameBase(Thread* t, int frame) +{ + return peekInt(t, frame + FrameBaseOffset); +} + +inline object localObject(Thread* t, unsigned index) +{ + return peekObject(t, frameBase(t, t->frame) + index); +} + +inline uint32_t localInt(Thread* t, unsigned index) +{ + return peekInt(t, frameBase(t, t->frame) + index); +} + +inline uint64_t localLong(Thread* t, unsigned index) +{ + return peekLong(t, frameBase(t, t->frame) + index); +} + +inline void setLocalObject(Thread* t, unsigned index, object value) +{ + pokeObject(t, frameBase(t, t->frame) + index, value); +} + +inline void setLocalInt(Thread* t, unsigned index, uint32_t value) +{ + pokeInt(t, frameBase(t, t->frame) + index, value); +} + +inline void setLocalLong(Thread* t, unsigned index, uint64_t value) +{ + pokeLong(t, frameBase(t, t->frame) + index, value); +} + +void pushFrame(Thread* t, GcMethod* method) +{ + PROTECT(t, method); + + unsigned parameterFootprint = method->parameterFootprint(); + unsigned base = t->sp - parameterFootprint; + unsigned locals = parameterFootprint; + + if (method->flags() & ACC_SYNCHRONIZED) { + // Try to acquire the monitor before doing anything else. + // Otherwise, if we were to push the frame first, we risk trying + // to release a monitor we never successfully acquired when we try + // to pop the frame back off. + if (method->flags() & ACC_STATIC) { + acquire(t, getJClass(t, method->class_())); + } else { + acquire(t, peekObject(t, base)); + } + } + + if (t->frame >= 0) { + pokeInt(t, t->frame + FrameIpOffset, t->ip); + } + t->ip = 0; + + if ((method->flags() & ACC_NATIVE) == 0) { + t->code = method->code(); + + locals = t->code->maxLocals(); + + memset(t->stack + ((base + parameterFootprint) * 2), + 0, + (locals - parameterFootprint) * BytesPerWord * 2); + } + + unsigned frame = base + locals; + pokeInt(t, frame + FrameNextOffset, t->frame); + t->frame = frame; + + t->sp = frame + FrameFootprint; + + pokeInt(t, frame + FrameBaseOffset, base); + pokeObject(t, frame + FrameMethodOffset, method); + pokeInt(t, t->frame + FrameIpOffset, 0); +} + +void popFrame(Thread* t) +{ + GcMethod* method = frameMethod(t, t->frame); + + if (method->flags() & ACC_SYNCHRONIZED) { + if (method->flags() & ACC_STATIC) { + release(t, getJClass(t, method->class_())); + } else { + release(t, peekObject(t, frameBase(t, t->frame))); + } + } + + t->sp = frameBase(t, t->frame); + t->frame = frameNext(t, t->frame); + if (t->frame >= 0) { + t->code = frameMethod(t, t->frame)->code(); + t->ip = frameIp(t, t->frame); + } else { + t->code = 0; + t->ip = 0; + } +} + +class MyStackWalker : public Processor::StackWalker { + public: + MyStackWalker(Thread* t, int frame) : t(t), frame(frame) + { + } + + virtual void walk(Processor::StackVisitor* v) + { + for (int frame = this->frame; frame >= 0; frame = frameNext(t, frame)) { + MyStackWalker walker(t, frame); + if (not v->visit(&walker)) { + break; + } + } + } + + virtual GcMethod* method() + { + return frameMethod(t, frame); + } + + virtual int ip() + { + return frameIp(t, frame); + } + + virtual unsigned count() + { + unsigned count = 0; + for (int frame = this->frame; frame >= 0; frame = frameNext(t, frame)) { + ++count; + } + return count; + } + + Thread* t; + int frame; +}; + +inline void checkStack(Thread* t, GcMethod* method) +{ + if (UNLIKELY(t->sp + method->parameterFootprint() + + method->code()->maxLocals() + FrameFootprint + + method->code()->maxStack() > stackSizeInWords(t) / 2)) { + throwNew(t, GcStackOverflowError::Type); + } +} + +void pushResult(Thread* t, unsigned returnCode, uint64_t result, bool indirect) +{ + switch (returnCode) { + case ByteField: + case BooleanField: + if (DebugRun) { + fprintf(stderr, "result: %d\n", static_cast(result)); + } + pushInt(t, static_cast(result)); + break; + + case CharField: + if (DebugRun) { + fprintf(stderr, "result: %d\n", static_cast(result)); + } + pushInt(t, static_cast(result)); + break; + + case ShortField: + if (DebugRun) { + fprintf(stderr, "result: %d\n", static_cast(result)); + } + pushInt(t, static_cast(result)); + break; + + case FloatField: + case IntField: + if (DebugRun) { + fprintf(stderr, "result: %d\n", static_cast(result)); + } + pushInt(t, result); + break; + + case DoubleField: + case LongField: + if (DebugRun) { + fprintf(stderr, "result: %" LLD "\n", result); + } + pushLong(t, result); + break; + + case ObjectField: + if (indirect) { + if (DebugRun) { + fprintf( + stderr, + "result: %p at %p\n", + static_cast(result) == 0 + ? 0 + : *reinterpret_cast(static_cast(result)), + reinterpret_cast(static_cast(result))); + } + pushObject( + t, + static_cast(result) == 0 + ? 0 + : *reinterpret_cast(static_cast(result))); + } else { + if (DebugRun) { + fprintf(stderr, "result: %p\n", reinterpret_cast(result)); + } + pushObject(t, reinterpret_cast(result)); + } + break; + + case VoidField: + break; + + default: + abort(t); + } +} + +void marshalArguments(Thread* t, + uintptr_t* args, + uint8_t* types, + unsigned sp, + GcMethod* method, + bool fastCallingConvention) +{ + MethodSpecIterator it( + t, reinterpret_cast(method->spec()->body().begin())); + + unsigned argOffset = 0; + unsigned typeOffset = 0; + + while (it.hasNext()) { + unsigned type = fieldType(t, fieldCode(t, *it.next())); + if (types) { + types[typeOffset++] = type; + } + + switch (type) { + case INT8_TYPE: + case INT16_TYPE: + case INT32_TYPE: + case FLOAT_TYPE: + args[argOffset++] = peekInt(t, sp++); + break; + + case DOUBLE_TYPE: + case INT64_TYPE: { + uint64_t v = peekLong(t, sp); + memcpy(args + argOffset, &v, 8); + argOffset += fastCallingConvention ? 2 : (8 / BytesPerWord); + sp += 2; + } break; + + case POINTER_TYPE: { + if (fastCallingConvention) { + args[argOffset++] = reinterpret_cast(peekObject(t, sp++)); + } else { + object* v = reinterpret_cast(t->stack + ((sp++) * 2) + 1); + if (*v == 0) { + v = 0; + } + args[argOffset++] = reinterpret_cast(v); + } + } break; + + default: + abort(t); + } + } +} + +unsigned invokeNativeSlow(Thread* t, GcMethod* method, void* function) +{ + PROTECT(t, method); + + pushFrame(t, method); + + unsigned footprint = method->parameterFootprint() + 1; + if (method->flags() & ACC_STATIC) { + ++footprint; + } + unsigned count = method->parameterCount() + 2; + + THREAD_RUNTIME_ARRAY(t, uintptr_t, args, footprint); + unsigned argOffset = 0; + THREAD_RUNTIME_ARRAY(t, uint8_t, types, count); + unsigned typeOffset = 0; + + RUNTIME_ARRAY_BODY(args)[argOffset++] = reinterpret_cast(t); + RUNTIME_ARRAY_BODY(types)[typeOffset++] = POINTER_TYPE; + + GcJclass* jclass = 0; + PROTECT(t, jclass); + + unsigned sp; + if (method->flags() & ACC_STATIC) { + sp = frameBase(t, t->frame); + jclass = getJClass(t, method->class_()); + RUNTIME_ARRAY_BODY(args)[argOffset++] + = reinterpret_cast(&jclass); + } else { + sp = frameBase(t, t->frame); + object* v = reinterpret_cast(t->stack + ((sp++) * 2) + 1); + if (*v == 0) { + v = 0; + } + RUNTIME_ARRAY_BODY(args)[argOffset++] = reinterpret_cast(v); + } + RUNTIME_ARRAY_BODY(types)[typeOffset++] = POINTER_TYPE; + + marshalArguments(t, + RUNTIME_ARRAY_BODY(args) + argOffset, + RUNTIME_ARRAY_BODY(types) + typeOffset, + sp, + method, + false); + + unsigned returnCode = method->returnCode(); + unsigned returnType = fieldType(t, returnCode); + uint64_t result; + + if (DebugRun) { + signed char *cname = method->class_() && method->class_()->name() ? method->class_()->name()->body().begin() : (signed char*) "?"; + signed char *mname = method->name() ? method->name()->body().begin() : (signed char*) "?"; + fprintf(stderr, + "invoke native method %s.%s\n", + cname, mname); + } + + { + ENTER(t, Thread::IdleState); + + bool noThrow = t->checkpoint->noThrow; + t->checkpoint->noThrow = true; + THREAD_RESOURCE(t, bool, noThrow, t->checkpoint->noThrow = noThrow); + + result = vm::dynamicCall(function, + RUNTIME_ARRAY_BODY(args), + RUNTIME_ARRAY_BODY(types), + count, + footprint * BytesPerWord, + returnType); + } + + if (DebugRun) { + fprintf(stderr, + "return from native method %s.%s\n", + frameMethod(t, t->frame)->class_()->name()->body().begin(), + frameMethod(t, t->frame)->name()->body().begin()); + } + + popFrame(t); + + if (UNLIKELY(t->exception)) { + GcThrowable* exception = t->exception; + t->exception = 0; + throw_(t, exception); + } + + pushResult(t, returnCode, result, true); + + return returnCode; +} + +unsigned invokeNative(Thread* t, GcMethod* method) +{ + PROTECT(t, method); + + resolveNative(t, method); + + GcNative* native = getMethodRuntimeData(t, method)->native(); + if (native->fast()) { + pushFrame(t, method); + + uint64_t result; + { + THREAD_RESOURCE0(t, popFrame(static_cast(t))); + + unsigned footprint = method->parameterFootprint(); + THREAD_RUNTIME_ARRAY(t, uintptr_t, args, footprint); + unsigned sp = frameBase(t, t->frame); + unsigned argOffset = 0; + if ((method->flags() & ACC_STATIC) == 0) { + RUNTIME_ARRAY_BODY(args)[argOffset++] + = reinterpret_cast(peekObject(t, sp++)); + } + + marshalArguments( + t, RUNTIME_ARRAY_BODY(args) + argOffset, 0, sp, method, true); + + if(method->returnCode() != VoidField) { + result = reinterpret_cast(native->function())( + t, method, RUNTIME_ARRAY_BODY(args)); + } + else { + result = 0; + reinterpret_cast(native->function())( + t, method, RUNTIME_ARRAY_BODY(args)); + } + } + + pushResult(t, method->returnCode(), result, false); + + return method->returnCode(); + } else { + return invokeNativeSlow(t, method, native->function()); + } +} + +inline void store(Thread* t, unsigned index) +{ + memcpy(t->stack + ((frameBase(t, t->frame) + index) * 2), + t->stack + ((--t->sp) * 2), + BytesPerWord * 2); +} + +bool isNaN(double v) +{ + return fpclassify(v) == FP_NAN; +} + +bool isNaN(float v) +{ + return fpclassify(v) == FP_NAN; +} + +uint64_t findExceptionHandler(Thread* t, GcMethod* method, unsigned ip) +{ + PROTECT(t, method); + + GcExceptionHandlerTable* eht = cast( + t, method->code()->exceptionHandlerTable()); + + if (eht) { + for (unsigned i = 0; i < eht->length(); ++i) { + uint64_t eh = eht->body()[i]; + + if (ip - 1 >= exceptionHandlerStart(eh) + and ip - 1 < exceptionHandlerEnd(eh)) { + GcClass* catchType = 0; + if (exceptionHandlerCatchType(eh)) { + GcThrowable* e = t->exception; + t->exception = 0; + PROTECT(t, e); + + PROTECT(t, eht); + catchType = resolveClassInPool( + t, method, exceptionHandlerCatchType(eh) - 1); + + if (catchType) { + eh = eht->body()[i]; + t->exception = e; + } else { + // can't find what we're supposed to catch - move on. + continue; + } + } + + if (exceptionMatch(t, catchType, t->exception)) { + return eh; + } + } + } + } + + return 0; +} + +uint64_t findExceptionHandler(Thread* t, int frame) +{ + return findExceptionHandler(t, frameMethod(t, frame), frameIp(t, frame)); +} + +void pushField(Thread* t, object target, GcField* field) +{ + switch (field->code()) { + case ByteField: + case BooleanField: + pushInt(t, fieldAtOffset(target, field->offset())); + break; + + case CharField: + case ShortField: + pushInt(t, fieldAtOffset(target, field->offset())); + break; + + case FloatField: + case IntField: + pushInt(t, fieldAtOffset(target, field->offset())); + break; + + case DoubleField: + case LongField: + pushLong(t, fieldAtOffset(target, field->offset())); + break; + + case ObjectField: + pushObject(t, fieldAtOffset(target, field->offset())); + break; + + default: + abort(t); + } +} + +void safePoint(Thread* t) +{ + if (UNLIKELY(t->m->exclusive)) { + ENTER(t, Thread::IdleState); + } +} + +object interpret3(Thread* t, const int base) +{ + unsigned instruction = nop; + unsigned& ip = t->ip; + unsigned& sp = t->sp; + int& frame = t->frame; + GcCode*& code = t->code; + GcMethod* method = 0; + PROTECT(t, method); + GcThrowable*& exception = t->exception; + uintptr_t* stack = t->stack; + + code = frameMethod(t, frame)->code(); + + if (UNLIKELY(exception)) { + goto throw_; + } + +loop: + instruction = code->body()[ip++]; + + if (DebugRun) { + GcMethod *method_ = frameMethod(t, frame); + signed char *cname = method_->class_() && method_->class_()->name() ? method_->class_()->name()->body().begin() : (signed char*) "?"; + signed char *mname = method_->name() ? method_->name()->body().begin() : (signed char*) "?"; + fprintf(stderr, + "ip: %d; instruction: 0x%x in %s.%s ", + ip - 1, + instruction, cname, mname); + + int line = findLineNumber(t, frameMethod(t, frame), ip); + switch (line) { + case NativeLine: + fprintf(stderr, "(native)\n"); + break; + case UnknownLine: + fprintf(stderr, "(unknown line)\n"); + break; + default: + fprintf(stderr, "(line %d)\n", line); + } + } + + switch (instruction) { + case aaload: { + int32_t index = popInt(t); + object array = popObject(t); + + if (LIKELY(array)) { + if (LIKELY(index >= 0 + and static_cast(index) + < objectArrayLength(t, array))) { + pushObject(t, objectArrayBody(t, array, index)); + } else { + exception = makeThrowable(t, + GcArrayIndexOutOfBoundsException::Type, + "%d not in [0,%d)", + index, + objectArrayLength(t, array)); + goto throw_; + } + } else { + exception = makeThrowable(t, GcNullPointerException::Type); + goto throw_; + } + } + goto loop; + + case aastore: { + object value = popObject(t); + int32_t index = popInt(t); + object array = popObject(t); + + if (LIKELY(array)) { + if (LIKELY(index >= 0 + and static_cast(index) + < objectArrayLength(t, array))) { + setField(t, array, ArrayBody + (index * BytesPerWord), value); + } else { + exception = makeThrowable(t, + GcArrayIndexOutOfBoundsException::Type, + "%d not in [0,%d)", + index, + objectArrayLength(t, array)); + goto throw_; + } + } else { + exception = makeThrowable(t, GcNullPointerException::Type); + goto throw_; + } + } + goto loop; + + case aconst_null: { + pushObject(t, 0); + } + goto loop; + + case aload: { + pushObject(t, localObject(t, code->body()[ip++])); + } + goto loop; + + case aload_0: { + pushObject(t, localObject(t, 0)); + } + goto loop; + + case aload_1: { + pushObject(t, localObject(t, 1)); + } + goto loop; + + case aload_2: { + pushObject(t, localObject(t, 2)); + } + goto loop; + + case aload_3: { + pushObject(t, localObject(t, 3)); + } + goto loop; + + case anewarray: { + int32_t count = popInt(t); + + if (LIKELY(count >= 0)) { + uint16_t index = codeReadInt16(t, code, ip); + + GcClass* class_ = resolveClassInPool(t, frameMethod(t, frame), index - 1); + + pushObject(t, makeObjectArray(t, class_, count)); + } else { + exception + = makeThrowable(t, GcNegativeArraySizeException::Type, "%d", count); + goto throw_; + } + } + goto loop; + + case areturn: { + object result = popObject(t); + if (frame > base) { + popFrame(t); + pushObject(t, result); + goto loop; + } else { + return result; + } + } + goto loop; + + case arraylength: { + object array = popObject(t); + if (LIKELY(array)) { + pushInt(t, fieldAtOffset(array, BytesPerWord)); + } else { + exception = makeThrowable(t, GcNullPointerException::Type); + goto throw_; + } + } + goto loop; + + case astore: { + store(t, code->body()[ip++]); + } + goto loop; + + case astore_0: { + store(t, 0); + } + goto loop; + + case astore_1: { + store(t, 1); + } + goto loop; + + case astore_2: { + store(t, 2); + } + goto loop; + + case astore_3: { + store(t, 3); + } + goto loop; + + case athrow: { + exception = cast(t, popObject(t)); + if (UNLIKELY(exception == 0)) { + exception = makeThrowable(t, GcNullPointerException::Type); + } + } + goto throw_; + + case baload: { + int32_t index = popInt(t); + object array = popObject(t); + + if (LIKELY(array)) { + if (objectClass(t, array) == type(t, GcBooleanArray::Type)) { + GcBooleanArray* a = cast(t, array); + if (LIKELY(index >= 0 + and static_cast(index) < a->length())) { + pushInt(t, a->body()[index]); + } else { + exception = makeThrowable(t, + GcArrayIndexOutOfBoundsException::Type, + "%d not in [0,%d)", + index, + a->length()); + goto throw_; + } + } else { + GcByteArray* a = cast(t, array); + if (LIKELY(index >= 0 + and static_cast(index) < a->length())) { + pushInt(t, a->body()[index]); + } else { + exception = makeThrowable(t, + GcArrayIndexOutOfBoundsException::Type, + "%d not in [0,%d)", + index, + a->length()); + goto throw_; + } + } + } else { + exception = makeThrowable(t, GcNullPointerException::Type); + goto throw_; + } + } + goto loop; + + case bastore: { + int8_t value = popInt(t); + int32_t index = popInt(t); + object array = popObject(t); + + if (LIKELY(array)) { + if (objectClass(t, array) == type(t, GcBooleanArray::Type)) { + GcBooleanArray* a = cast(t, array); + if (LIKELY(index >= 0 + and static_cast(index) < a->length())) { + a->body()[index] = value; + } else { + exception = makeThrowable(t, + GcArrayIndexOutOfBoundsException::Type, + "%d not in [0,%d)", + index, + a->length()); + goto throw_; + } + } else { + GcByteArray* a = cast(t, array); + if (LIKELY(index >= 0 + and static_cast(index) < a->length())) { + a->body()[index] = value; + } else { + exception = makeThrowable(t, + GcArrayIndexOutOfBoundsException::Type, + "%d not in [0,%d)", + index, + a->length()); + goto throw_; + } + } + } else { + exception = makeThrowable(t, GcNullPointerException::Type); + goto throw_; + } + } + goto loop; + + case bipush: { + pushInt(t, static_cast(code->body()[ip++])); + } + goto loop; + + case caload: { + int32_t index = popInt(t); + object array = popObject(t); + + if (LIKELY(array)) { + GcCharArray* a = cast(t, array); + if (LIKELY(index >= 0 and static_cast(index) < a->length())) { + pushInt(t, a->body()[index]); + } else { + exception = makeThrowable(t, + GcArrayIndexOutOfBoundsException::Type, + "%d not in [0,%d)", + index, + a->length()); + goto throw_; + } + } else { + exception = makeThrowable(t, GcNullPointerException::Type); + goto throw_; + } + } + goto loop; + + case castore: { + uint16_t value = popInt(t); + int32_t index = popInt(t); + object array = popObject(t); + + if (LIKELY(array)) { + GcCharArray* a = cast(t, array); + if (LIKELY(index >= 0 and static_cast(index) < a->length())) { + a->body()[index] = value; + } else { + exception = makeThrowable(t, + GcArrayIndexOutOfBoundsException::Type, + "%d not in [0,%d)", + index, + a->length()); + goto throw_; + } + } else { + exception = makeThrowable(t, GcNullPointerException::Type); + goto throw_; + } + } + goto loop; + + case checkcast: { + uint16_t index = codeReadInt16(t, code, ip); + + if (peekObject(t, sp - 1)) { + GcClass* class_ = resolveClassInPool(t, frameMethod(t, frame), index - 1); + if (UNLIKELY(exception)) + goto throw_; + + if (not instanceOf(t, class_, peekObject(t, sp - 1))) { + exception = makeThrowable( + t, + GcClassCastException::Type, + "%s as %s", + objectClass(t, peekObject(t, sp - 1))->name()->body().begin(), + class_->name()->body().begin()); + goto throw_; + } + } + } + goto loop; + + case d2f: { + pushFloat(t, static_cast(popDouble(t))); + } + goto loop; + + case d2i: { + double f = popDouble(t); + switch (fpclassify(f)) { + case FP_NAN: + pushInt(t, 0); + break; + case FP_INFINITE: + pushInt(t, signbit(f) ? INT32_MIN : INT32_MAX); + break; + default: + pushInt(t, + f >= INT32_MAX + ? INT32_MAX + : (f <= INT32_MIN ? INT32_MIN : static_cast(f))); + break; + } + } + goto loop; + + case d2l: { + double f = popDouble(t); + switch (fpclassify(f)) { + case FP_NAN: + pushLong(t, 0); + break; + case FP_INFINITE: + pushLong(t, signbit(f) ? INT64_MIN : INT64_MAX); + break; + default: + pushLong(t, + f >= INT64_MAX + ? INT64_MAX + : (f <= INT64_MIN ? INT64_MIN : static_cast(f))); + break; + } + } + goto loop; + + case dadd: { + double b = popDouble(t); + double a = popDouble(t); + + pushDouble(t, a + b); + } + goto loop; + + case daload: { + int32_t index = popInt(t); + object array = popObject(t); + + if (LIKELY(array)) { + GcDoubleArray* a = cast(t, array); + if (LIKELY(index >= 0 and static_cast(index) < a->length())) { + pushLong(t, a->body()[index]); + } else { + exception = makeThrowable(t, + GcArrayIndexOutOfBoundsException::Type, + "%d not in [0,%d)", + index, + a->length()); + goto throw_; + } + } else { + exception = makeThrowable(t, GcNullPointerException::Type); + goto throw_; + } + } + goto loop; + + case dastore: { + double value = popDouble(t); + int32_t index = popInt(t); + object array = popObject(t); + + if (LIKELY(array)) { + GcDoubleArray* a = cast(t, array); + if (LIKELY(index >= 0 and static_cast(index) < a->length())) { + memcpy(&a->body()[index], &value, sizeof(uint64_t)); + } else { + exception = makeThrowable(t, + GcArrayIndexOutOfBoundsException::Type, + "%d not in [0,%d)", + index, + a->length()); + goto throw_; + } + } else { + exception = makeThrowable(t, GcNullPointerException::Type); + goto throw_; + } + } + goto loop; + + case dcmpg: { + double b = popDouble(t); + double a = popDouble(t); + + if (isNaN(a) or isNaN(b)) { + pushInt(t, 1); + } + if (a < b) { + pushInt(t, static_cast(-1)); + } else if (a > b) { + pushInt(t, 1); + } else if (a == b) { + pushInt(t, 0); + } else { + pushInt(t, 1); + } + } + goto loop; + + case dcmpl: { + double b = popDouble(t); + double a = popDouble(t); + + if (isNaN(a) or isNaN(b)) { + pushInt(t, static_cast(-1)); + } + if (a < b) { + pushInt(t, static_cast(-1)); + } else if (a > b) { + pushInt(t, 1); + } else if (a == b) { + pushInt(t, 0); + } else { + pushInt(t, static_cast(-1)); + } + } + goto loop; + + case dconst_0: { + pushDouble(t, 0); + } + goto loop; + + case dconst_1: { + pushDouble(t, 1); + } + goto loop; + + case ddiv: { + double b = popDouble(t); + double a = popDouble(t); + + pushDouble(t, a / b); + } + goto loop; + + case dmul: { + double b = popDouble(t); + double a = popDouble(t); + + pushDouble(t, a * b); + } + goto loop; + + case dneg: { + double a = popDouble(t); + + pushDouble(t, -a); + } + goto loop; + + case vm::drem: { + double b = popDouble(t); + double a = popDouble(t); + + pushDouble(t, fmod(a, b)); + } + goto loop; + + case dsub: { + double b = popDouble(t); + double a = popDouble(t); + + pushDouble(t, a - b); + } + goto loop; + + case vm::dup: { + if (DebugStack) { + fprintf(stderr, "dup\n"); + } + + memcpy(stack + ((sp)*2), stack + ((sp - 1) * 2), BytesPerWord * 2); + ++sp; + } + goto loop; + + case dup_x1: { + if (DebugStack) { + fprintf(stderr, "dup_x1\n"); + } + + memcpy(stack + ((sp)*2), stack + ((sp - 1) * 2), BytesPerWord * 2); + memcpy(stack + ((sp - 1) * 2), stack + ((sp - 2) * 2), BytesPerWord * 2); + memcpy(stack + ((sp - 2) * 2), stack + ((sp)*2), BytesPerWord * 2); + ++sp; + } + goto loop; + + case dup_x2: { + if (DebugStack) { + fprintf(stderr, "dup_x2\n"); + } + + memcpy(stack + ((sp)*2), stack + ((sp - 1) * 2), BytesPerWord * 2); + memcpy(stack + ((sp - 1) * 2), stack + ((sp - 2) * 2), BytesPerWord * 2); + memcpy(stack + ((sp - 2) * 2), stack + ((sp - 3) * 2), BytesPerWord * 2); + memcpy(stack + ((sp - 3) * 2), stack + ((sp)*2), BytesPerWord * 2); + ++sp; + } + goto loop; + + case vm::dup2: { + if (DebugStack) { + fprintf(stderr, "dup2\n"); + } + + memcpy(stack + ((sp)*2), stack + ((sp - 2) * 2), BytesPerWord * 4); + sp += 2; + } + goto loop; + + case dup2_x1: { + if (DebugStack) { + fprintf(stderr, "dup2_x1\n"); + } + + memcpy(stack + ((sp + 1) * 2), stack + ((sp - 1) * 2), BytesPerWord * 2); + memcpy(stack + ((sp)*2), stack + ((sp - 2) * 2), BytesPerWord * 2); + memcpy(stack + ((sp - 1) * 2), stack + ((sp - 3) * 2), BytesPerWord * 2); + memcpy(stack + ((sp - 3) * 2), stack + ((sp)*2), BytesPerWord * 4); + sp += 2; + } + goto loop; + + case dup2_x2: { + if (DebugStack) { + fprintf(stderr, "dup2_x2\n"); + } + + memcpy(stack + ((sp + 1) * 2), stack + ((sp - 1) * 2), BytesPerWord * 2); + memcpy(stack + ((sp)*2), stack + ((sp - 2) * 2), BytesPerWord * 2); + memcpy(stack + ((sp - 1) * 2), stack + ((sp - 3) * 2), BytesPerWord * 2); + memcpy(stack + ((sp - 2) * 2), stack + ((sp - 4) * 2), BytesPerWord * 2); + memcpy(stack + ((sp - 4) * 2), stack + ((sp)*2), BytesPerWord * 4); + sp += 2; + } + goto loop; + + case f2d: { + pushDouble(t, popFloat(t)); + } + goto loop; + + case f2i: { + float f = popFloat(t); + switch (fpclassify(f)) { + case FP_NAN: + pushInt(t, 0); + break; + case FP_INFINITE: + pushInt(t, signbit(f) ? INT32_MIN : INT32_MAX); + break; + default: + pushInt(t, + f >= INT32_MAX + ? INT32_MAX + : (f <= INT32_MIN ? INT32_MIN : static_cast(f))); + break; + } + } + goto loop; + + case f2l: { + float f = popFloat(t); + switch (fpclassify(f)) { + case FP_NAN: + pushLong(t, 0); + break; + case FP_INFINITE: + pushLong(t, signbit(f) ? INT64_MIN : INT64_MAX); + break; + default: + pushLong(t, static_cast(f)); + break; + } + } + goto loop; + + case fadd: { + float b = popFloat(t); + float a = popFloat(t); + + pushFloat(t, a + b); + } + goto loop; + + case faload: { + int32_t index = popInt(t); + object array = popObject(t); + + if (LIKELY(array)) { + GcFloatArray* a = cast(t, array); + if (LIKELY(index >= 0 and static_cast(index) < a->length())) { + pushInt(t, a->body()[index]); + } else { + exception = makeThrowable(t, + GcArrayIndexOutOfBoundsException::Type, + "%d not in [0,%d)", + index, + a->length()); + goto throw_; + } + } else { + exception = makeThrowable(t, GcNullPointerException::Type); + goto throw_; + } + } + goto loop; + + case fastore: { + float value = popFloat(t); + int32_t index = popInt(t); + object array = popObject(t); + + if (LIKELY(array)) { + GcFloatArray* a = cast(t, array); + if (LIKELY(index >= 0 and static_cast(index) < a->length())) { + memcpy(&a->body()[index], &value, sizeof(uint32_t)); + } else { + exception = makeThrowable(t, + GcArrayIndexOutOfBoundsException::Type, + "%d not in [0,%d)", + index, + a->length()); + goto throw_; + } + } else { + exception = makeThrowable(t, GcNullPointerException::Type); + goto throw_; + } + } + goto loop; + + case fcmpg: { + float b = popFloat(t); + float a = popFloat(t); + + if (isNaN(a) or isNaN(b)) { + pushInt(t, 1); + } + if (a < b) { + pushInt(t, static_cast(-1)); + } else if (a > b) { + pushInt(t, 1); + } else if (a == b) { + pushInt(t, 0); + } else { + pushInt(t, 1); + } + } + goto loop; + + case fcmpl: { + float b = popFloat(t); + float a = popFloat(t); + + if (isNaN(a) or isNaN(b)) { + pushInt(t, static_cast(-1)); + } + if (a < b) { + pushInt(t, static_cast(-1)); + } else if (a > b) { + pushInt(t, 1); + } else if (a == b) { + pushInt(t, 0); + } else { + pushInt(t, static_cast(-1)); + } + } + goto loop; + + case fconst_0: { + pushFloat(t, 0); + } + goto loop; + + case fconst_1: { + pushFloat(t, 1); + } + goto loop; + + case fconst_2: { + pushFloat(t, 2); + } + goto loop; + + case fdiv: { + float b = popFloat(t); + float a = popFloat(t); + + pushFloat(t, a / b); + } + goto loop; + + case fmul: { + float b = popFloat(t); + float a = popFloat(t); + + pushFloat(t, a * b); + } + goto loop; + + case fneg: { + float a = popFloat(t); + + pushFloat(t, -a); + } + goto loop; + + case frem: { + float b = popFloat(t); + float a = popFloat(t); + + pushFloat(t, fmodf(a, b)); + } + goto loop; + + case fsub: { + float b = popFloat(t); + float a = popFloat(t); + + pushFloat(t, a - b); + } + goto loop; + + case getfield: { + if (LIKELY(peekObject(t, sp - 1))) { + uint16_t index = codeReadInt16(t, code, ip); + + GcField* field = resolveField(t, frameMethod(t, frame), index - 1); + + assertT(t, (field->flags() & ACC_STATIC) == 0); + + PROTECT(t, field); + + ACQUIRE_FIELD_FOR_READ(t, field); + + pushField(t, popObject(t), field); + } else { + exception = makeThrowable(t, GcNullPointerException::Type); + goto throw_; + } + } + goto loop; + + case getstatic: { + uint16_t index = codeReadInt16(t, code, ip); + + GcField* field = resolveField(t, frameMethod(t, frame), index - 1); + + assertT(t, field->flags() & ACC_STATIC); + + PROTECT(t, field); + + initClass(t, field->class_()); + + ACQUIRE_FIELD_FOR_READ(t, field); + + pushField(t, field->class_()->staticTable(), field); + } + goto loop; + + case goto_: { + int16_t offset = codeReadInt16(t, code, ip); + ip = (ip - 3) + offset; + } + goto back_branch; + + case goto_w: { + int32_t offset = codeReadInt32(t, code, ip); + ip = (ip - 5) + offset; + } + goto back_branch; + + case i2b: { + pushInt(t, static_cast(popInt(t))); + } + goto loop; + + case i2c: { + pushInt(t, static_cast(popInt(t))); + } + goto loop; + + case i2d: { + pushDouble(t, static_cast(static_cast(popInt(t)))); + } + goto loop; + + case i2f: { + pushFloat(t, static_cast(static_cast(popInt(t)))); + } + goto loop; + + case i2l: { + pushLong(t, static_cast(popInt(t))); + } + goto loop; + + case i2s: { + pushInt(t, static_cast(popInt(t))); + } + goto loop; + + case iadd: { + int32_t b = popInt(t); + int32_t a = popInt(t); + + pushInt(t, a + b); + } + goto loop; + + case iaload: { + int32_t index = popInt(t); + object array = popObject(t); + + if (LIKELY(array)) { + GcIntArray* a = cast(t, array); + if (LIKELY(index >= 0 and static_cast(index) < a->length())) { + pushInt(t, a->body()[index]); + } else { + exception = makeThrowable(t, + GcArrayIndexOutOfBoundsException::Type, + "%d not in [0,%d)", + index, + a->length()); + goto throw_; + } + } else { + exception = makeThrowable(t, GcNullPointerException::Type); + goto throw_; + } + } + goto loop; + + case iand: { + int32_t b = popInt(t); + int32_t a = popInt(t); + + pushInt(t, a & b); + } + goto loop; + + case iastore: { + int32_t value = popInt(t); + int32_t index = popInt(t); + object array = popObject(t); + + if (LIKELY(array)) { + GcIntArray* a = cast(t, array); + if (LIKELY(index >= 0 and static_cast(index) < a->length())) { + a->body()[index] = value; + } else { + exception = makeThrowable(t, + GcArrayIndexOutOfBoundsException::Type, + "%d not in [0,%d)", + index, + a->length()); + goto throw_; + } + } else { + exception = makeThrowable(t, GcNullPointerException::Type); + goto throw_; + } + } + goto loop; + + case iconst_m1: { + pushInt(t, static_cast(-1)); + } + goto loop; + + case iconst_0: { + pushInt(t, 0); + } + goto loop; + + case iconst_1: { + pushInt(t, 1); + } + goto loop; + + case iconst_2: { + pushInt(t, 2); + } + goto loop; + + case iconst_3: { + pushInt(t, 3); + } + goto loop; + + case iconst_4: { + pushInt(t, 4); + } + goto loop; + + case iconst_5: { + pushInt(t, 5); + } + goto loop; + + case idiv: { + int32_t b = popInt(t); + int32_t a = popInt(t); + + if (UNLIKELY(b == 0)) { + exception = makeThrowable(t, GcArithmeticException::Type); + goto throw_; + } + + pushInt(t, a / b); + } + goto loop; + + case if_acmpeq: { + int16_t offset = codeReadInt16(t, code, ip); + + object b = popObject(t); + object a = popObject(t); + + if (a == b) { + ip = (ip - 3) + offset; + } + } + goto back_branch; + + case if_acmpne: { + int16_t offset = codeReadInt16(t, code, ip); + + object b = popObject(t); + object a = popObject(t); + + if (a != b) { + ip = (ip - 3) + offset; + } + } + goto back_branch; + + case if_icmpeq: { + int16_t offset = codeReadInt16(t, code, ip); + + int32_t b = popInt(t); + int32_t a = popInt(t); + + if (a == b) { + ip = (ip - 3) + offset; + } + } + goto back_branch; + + case if_icmpne: { + int16_t offset = codeReadInt16(t, code, ip); + + int32_t b = popInt(t); + int32_t a = popInt(t); + + if (a != b) { + ip = (ip - 3) + offset; + } + } + goto back_branch; + + case if_icmpgt: { + int16_t offset = codeReadInt16(t, code, ip); + + int32_t b = popInt(t); + int32_t a = popInt(t); + + if (a > b) { + ip = (ip - 3) + offset; + } + } + goto back_branch; + + case if_icmpge: { + int16_t offset = codeReadInt16(t, code, ip); + + int32_t b = popInt(t); + int32_t a = popInt(t); + + if (a >= b) { + ip = (ip - 3) + offset; + } + } + goto back_branch; + + case if_icmplt: { + int16_t offset = codeReadInt16(t, code, ip); + + int32_t b = popInt(t); + int32_t a = popInt(t); + + if (a < b) { + ip = (ip - 3) + offset; + } + } + goto back_branch; + + case if_icmple: { + int16_t offset = codeReadInt16(t, code, ip); + + int32_t b = popInt(t); + int32_t a = popInt(t); + + if (a <= b) { + ip = (ip - 3) + offset; + } + } + goto back_branch; + + case ifeq: { + int16_t offset = codeReadInt16(t, code, ip); + + if (popInt(t) == 0) { + ip = (ip - 3) + offset; + } + } + goto back_branch; + + case ifne: { + int16_t offset = codeReadInt16(t, code, ip); + + if (popInt(t)) { + ip = (ip - 3) + offset; + } + } + goto back_branch; + + case ifgt: { + int16_t offset = codeReadInt16(t, code, ip); + + if (static_cast(popInt(t)) > 0) { + ip = (ip - 3) + offset; + } + } + goto back_branch; + + case ifge: { + int16_t offset = codeReadInt16(t, code, ip); + + if (static_cast(popInt(t)) >= 0) { + ip = (ip - 3) + offset; + } + } + goto back_branch; + + case iflt: { + int16_t offset = codeReadInt16(t, code, ip); + + if (static_cast(popInt(t)) < 0) { + ip = (ip - 3) + offset; + } + } + goto back_branch; + + case ifle: { + int16_t offset = codeReadInt16(t, code, ip); + + if (static_cast(popInt(t)) <= 0) { + ip = (ip - 3) + offset; + } + } + goto back_branch; + + case ifnonnull: { + int16_t offset = codeReadInt16(t, code, ip); + + if (popObject(t)) { + ip = (ip - 3) + offset; + } + } + goto back_branch; + + case ifnull: { + int16_t offset = codeReadInt16(t, code, ip); + + if (popObject(t) == 0) { + ip = (ip - 3) + offset; + } + } + goto back_branch; + + case iinc: { + uint8_t index = code->body()[ip++]; + int8_t c = code->body()[ip++]; + + setLocalInt(t, index, localInt(t, index) + c); + } + goto loop; + + case iload: + case fload: { + pushInt(t, localInt(t, code->body()[ip++])); + } + goto loop; + + case iload_0: + case fload_0: { + pushInt(t, localInt(t, 0)); + } + goto loop; + + case iload_1: + case fload_1: { + pushInt(t, localInt(t, 1)); + } + goto loop; + + case iload_2: + case fload_2: { + pushInt(t, localInt(t, 2)); + } + goto loop; + + case iload_3: + case fload_3: { + pushInt(t, localInt(t, 3)); + } + goto loop; + + case imul: { + int32_t b = popInt(t); + int32_t a = popInt(t); + + pushInt(t, a * b); + } + goto loop; + + case ineg: { + pushInt(t, -popInt(t)); + } + goto loop; + + case instanceof: { + uint16_t index = codeReadInt16(t, code, ip); + + if (peekObject(t, sp - 1)) { + GcClass* class_ = resolveClassInPool(t, frameMethod(t, frame), index - 1); + + if (instanceOf(t, class_, popObject(t))) { + pushInt(t, 1); + } else { + pushInt(t, 0); + } + } else { + popObject(t); + pushInt(t, 0); + } + } + goto loop; + + case invokedynamic: { + uint16_t index = codeReadInt16(t, code, ip); + + ip += 2; + + GcInvocation* invocation = cast(t, singletonObject(t, code->pool(), index - 1)); + + GcCallSite* site = invocation->site(); + + loadMemoryBarrier(); + + if (site == 0) { + PROTECT(t, invocation); + + invocation->setClass(t, frameMethod(t, frame)->class_()); + + site = resolveDynamic(t, invocation); + PROTECT(t, site); + + storeStoreMemoryBarrier(); + + invocation->setSite(t, site); + site->setInvocation(t, invocation); + } + + method = site->target()->method(); + } goto invoke; + + case invokeinterface: { + uint16_t index = codeReadInt16(t, code, ip); + + ip += 2; + + GcMethod* m = resolveMethod(t, frameMethod(t, frame), index - 1); + + unsigned parameterFootprint = m->parameterFootprint(); + if (LIKELY(peekObject(t, sp - parameterFootprint))) { + method = findInterfaceMethod( + t, m, objectClass(t, peekObject(t, sp - parameterFootprint))); + goto invoke; + } else { + exception = makeThrowable(t, GcNullPointerException::Type); + goto throw_; + } + } + goto loop; + + case invokespecial: { + uint16_t index = codeReadInt16(t, code, ip); + + GcMethod* m = resolveMethod(t, frameMethod(t, frame), index - 1); + + unsigned parameterFootprint = m->parameterFootprint(); + if (LIKELY(peekObject(t, sp - parameterFootprint))) { + GcClass* class_ = frameMethod(t, frame)->class_(); + if (isSpecialMethod(t, m, class_)) { + class_ = class_->super(); + PROTECT(t, m); + PROTECT(t, class_); + + initClass(t, class_); + + method = findVirtualMethod(t, m, class_); + } else { + method = m; + } + + goto invoke; + } else { + exception = makeThrowable(t, GcNullPointerException::Type); + goto throw_; + } + } + goto loop; + + case invokestatic: { + uint16_t index = codeReadInt16(t, code, ip); + + GcMethod* m = resolveMethod(t, frameMethod(t, frame), index - 1); + PROTECT(t, m); + + initClass(t, m->class_()); + + method = m; + } + goto invoke; + + case invokevirtual: { + uint16_t index = codeReadInt16(t, code, ip); + + GcMethod* m = resolveMethod(t, frameMethod(t, frame), index - 1); + + unsigned parameterFootprint = m->parameterFootprint(); + if (LIKELY(peekObject(t, sp - parameterFootprint))) { + GcClass* class_ = objectClass(t, peekObject(t, sp - parameterFootprint)); + PROTECT(t, m); + PROTECT(t, class_); + + method = findVirtualMethod(t, m, class_); + goto invoke; + } else { + exception = makeThrowable(t, GcNullPointerException::Type); + goto throw_; + } + } + goto loop; + + case ior: { + int32_t b = popInt(t); + int32_t a = popInt(t); + + pushInt(t, a | b); + } + goto loop; + + case irem: { + int32_t b = popInt(t); + int32_t a = popInt(t); + + if (UNLIKELY(b == 0)) { + exception = makeThrowable(t, GcArithmeticException::Type); + goto throw_; + } + + pushInt(t, a % b); + } + goto loop; + + case ireturn: + case freturn: { + int32_t result = popInt(t); + if (frame > base) { + popFrame(t); + pushInt(t, result); + goto loop; + } else { + return makeInt(t, result); + } + } + goto loop; + + case ishl: { + int32_t b = popInt(t); + int32_t a = popInt(t); + + pushInt(t, a << (b & 0x1F)); + } + goto loop; + + case ishr: { + int32_t b = popInt(t); + int32_t a = popInt(t); + + pushInt(t, a >> (b & 0x1F)); + } + goto loop; + + case istore: + case fstore: { + setLocalInt(t, code->body()[ip++], popInt(t)); + } + goto loop; + + case istore_0: + case fstore_0: { + setLocalInt(t, 0, popInt(t)); + } + goto loop; + + case istore_1: + case fstore_1: { + setLocalInt(t, 1, popInt(t)); + } + goto loop; + + case istore_2: + case fstore_2: { + setLocalInt(t, 2, popInt(t)); + } + goto loop; + + case istore_3: + case fstore_3: { + setLocalInt(t, 3, popInt(t)); + } + goto loop; + + case isub: { + int32_t b = popInt(t); + int32_t a = popInt(t); + + pushInt(t, a - b); + } + goto loop; + + case iushr: { + int32_t b = popInt(t); + uint32_t a = popInt(t); + + pushInt(t, a >> (b & 0x1F)); + } + goto loop; + + case ixor: { + int32_t b = popInt(t); + int32_t a = popInt(t); + + pushInt(t, a ^ b); + } + goto loop; + + case jsr: { + uint16_t offset = codeReadInt16(t, code, ip); + + pushInt(t, ip); + ip = (ip - 3) + static_cast(offset); + } + goto loop; + + case jsr_w: { + uint32_t offset = codeReadInt32(t, code, ip); + + pushInt(t, ip); + ip = (ip - 5) + static_cast(offset); + } + goto loop; + + case l2d: { + pushDouble(t, static_cast(static_cast(popLong(t)))); + } + goto loop; + + case l2f: { + pushFloat(t, static_cast(static_cast(popLong(t)))); + } + goto loop; + + case l2i: { + pushInt(t, static_cast(popLong(t))); + } + goto loop; + + case ladd: { + int64_t b = popLong(t); + int64_t a = popLong(t); + + pushLong(t, a + b); + } + goto loop; + + case laload: { + int32_t index = popInt(t); + object array = popObject(t); + + if (LIKELY(array)) { + GcLongArray* a = cast(t, array); + if (LIKELY(index >= 0 and static_cast(index) < a->length())) { + pushLong(t, a->body()[index]); + } else { + exception = makeThrowable(t, + GcArrayIndexOutOfBoundsException::Type, + "%d not in [0,%d)", + index, + a->length()); + goto throw_; + } + } else { + exception = makeThrowable(t, GcNullPointerException::Type); + goto throw_; + } + } + goto loop; + + case land: { + int64_t b = popLong(t); + int64_t a = popLong(t); + + pushLong(t, a & b); + } + goto loop; + + case lastore: { + int64_t value = popLong(t); + int32_t index = popInt(t); + object array = popObject(t); + + if (LIKELY(array)) { + GcLongArray* a = cast(t, array); + if (LIKELY(index >= 0 and static_cast(index) < a->length())) { + a->body()[index] = value; + } else { + exception = makeThrowable(t, + GcArrayIndexOutOfBoundsException::Type, + "%d not in [0,%d)", + index, + a->length()); + goto throw_; + } + } else { + exception = makeThrowable(t, GcNullPointerException::Type); + goto throw_; + } + } + goto loop; + + case lcmp: { + int64_t b = popLong(t); + int64_t a = popLong(t); + + pushInt(t, a > b ? 1 : a == b ? 0 : -1); + } + goto loop; + + case lconst_0: { + pushLong(t, 0); + } + goto loop; + + case lconst_1: { + pushLong(t, 1); + } + goto loop; + + case ldc: + case ldc_w: { + uint16_t index; + + if (instruction == ldc) { + index = code->body()[ip++]; + } else { + index = codeReadInt16(t, code, ip); + } + + GcSingleton* pool = code->pool(); + + if (singletonIsObject(t, pool, index - 1)) { + object v = singletonObject(t, pool, index - 1); + if (objectClass(t, v) == type(t, GcReference::Type)) { + GcClass* class_ + = resolveClassInPool(t, frameMethod(t, frame), index - 1); + + pushObject(t, reinterpret_cast(getJClass(t, class_))); + } else if (objectClass(t, v) == type(t, GcClass::Type)) { + pushObject(t, + reinterpret_cast(getJClass(t, cast(t, v)))); + } else { + pushObject(t, v); + } + } else { + pushInt(t, singletonValue(t, pool, index - 1)); + } + } + goto loop; + + case ldc2_w: { + uint16_t index = codeReadInt16(t, code, ip); + + GcSingleton* pool = code->pool(); + + uint64_t v; + memcpy(&v, &singletonValue(t, pool, index - 1), 8); + pushLong(t, v); + } + goto loop; + + case ldiv_: { + int64_t b = popLong(t); + int64_t a = popLong(t); + + if (UNLIKELY(b == 0)) { + exception = makeThrowable(t, GcArithmeticException::Type); + goto throw_; + } + + pushLong(t, a / b); + } + goto loop; + + case lload: + case dload: { + pushLong(t, localLong(t, code->body()[ip++])); + } + goto loop; + + case lload_0: + case dload_0: { + pushLong(t, localLong(t, 0)); + } + goto loop; + + case lload_1: + case dload_1: { + pushLong(t, localLong(t, 1)); + } + goto loop; + + case lload_2: + case dload_2: { + pushLong(t, localLong(t, 2)); + } + goto loop; + + case lload_3: + case dload_3: { + pushLong(t, localLong(t, 3)); + } + goto loop; + + case lmul: { + int64_t b = popLong(t); + int64_t a = popLong(t); + + pushLong(t, a * b); + } + goto loop; + + case lneg: { + pushLong(t, -popLong(t)); + } + goto loop; + + case lookupswitch: { + int32_t base = ip - 1; + + ip += 3; + ip -= (ip % 4); + + int32_t default_ = codeReadInt32(t, code, ip); + int32_t pairCount = codeReadInt32(t, code, ip); + + int32_t key = popInt(t); + + int32_t bottom = 0; + int32_t top = pairCount; + for (int32_t span = top - bottom; span; span = top - bottom) { + int32_t middle = bottom + (span / 2); + unsigned index = ip + (middle * 8); + + int32_t k = codeReadInt32(t, code, index); + + if (key < k) { + top = middle; + } else if (key > k) { + bottom = middle + 1; + } else { + ip = base + codeReadInt32(t, code, index); + goto loop; + } + } + + ip = base + default_; + } + goto loop; + + case lor: { + int64_t b = popLong(t); + int64_t a = popLong(t); + + pushLong(t, a | b); + } + goto loop; + + case lrem: { + int64_t b = popLong(t); + int64_t a = popLong(t); + + if (UNLIKELY(b == 0)) { + exception = makeThrowable(t, GcArithmeticException::Type); + goto throw_; + } + + pushLong(t, a % b); + } + goto loop; + + case lreturn: + case dreturn: { + int64_t result = popLong(t); + if (frame > base) { + popFrame(t); + pushLong(t, result); + goto loop; + } else { + return makeLong(t, result); + } + } + goto loop; + + case lshl: { + int32_t b = popInt(t); + int64_t a = popLong(t); + + pushLong(t, a << (b & 0x3F)); + } + goto loop; + + case lshr: { + int32_t b = popInt(t); + int64_t a = popLong(t); + + pushLong(t, a >> (b & 0x3F)); + } + goto loop; + + case lstore: + case dstore: { + setLocalLong(t, code->body()[ip++], popLong(t)); + } + goto loop; + + case lstore_0: + case dstore_0: { + setLocalLong(t, 0, popLong(t)); + } + goto loop; + + case lstore_1: + case dstore_1: { + setLocalLong(t, 1, popLong(t)); + } + goto loop; + + case lstore_2: + case dstore_2: { + setLocalLong(t, 2, popLong(t)); + } + goto loop; + + case lstore_3: + case dstore_3: { + setLocalLong(t, 3, popLong(t)); + } + goto loop; + + case lsub: { + int64_t b = popLong(t); + int64_t a = popLong(t); + + pushLong(t, a - b); + } + goto loop; + + case lushr: { + int64_t b = popInt(t); + uint64_t a = popLong(t); + + pushLong(t, a >> (b & 0x3F)); + } + goto loop; + + case lxor: { + int64_t b = popLong(t); + int64_t a = popLong(t); + + pushLong(t, a ^ b); + } + goto loop; + + case monitorenter: { + object o = popObject(t); + if (LIKELY(o)) { + acquire(t, o); + } else { + exception = makeThrowable(t, GcNullPointerException::Type); + goto throw_; + } + } + goto loop; + + case monitorexit: { + object o = popObject(t); + if (LIKELY(o)) { + release(t, o); + } else { + exception = makeThrowable(t, GcNullPointerException::Type); + goto throw_; + } + } + goto loop; + + case multianewarray: { + uint16_t index = codeReadInt16(t, code, ip); + uint8_t dimensions = code->body()[ip++]; + + GcClass* class_ = resolveClassInPool(t, frameMethod(t, frame), index - 1); + PROTECT(t, class_); + + THREAD_RUNTIME_ARRAY(t, int32_t, counts, dimensions); + for (int i = dimensions - 1; i >= 0; --i) { + RUNTIME_ARRAY_BODY(counts)[i] = popInt(t); + if (UNLIKELY(RUNTIME_ARRAY_BODY(counts)[i] < 0)) { + exception = makeThrowable(t, + GcNegativeArraySizeException::Type, + "%d", + RUNTIME_ARRAY_BODY(counts)[i]); + goto throw_; + } + } + + object array = makeArray(t, RUNTIME_ARRAY_BODY(counts)[0]); + setObjectClass(t, array, class_); + PROTECT(t, array); + + populateMultiArray(t, array, RUNTIME_ARRAY_BODY(counts), 0, dimensions); + + pushObject(t, array); + } + goto loop; + + case new_: { + uint16_t index = codeReadInt16(t, code, ip); + + GcClass* class_ = resolveClassInPool(t, frameMethod(t, frame), index - 1); + PROTECT(t, class_); + + initClass(t, class_); + + pushObject(t, make(t, class_)); + } + goto loop; + + case newarray: { + int32_t count = popInt(t); + + if (LIKELY(count >= 0)) { + uint8_t type = code->body()[ip++]; + + object array; + + switch (type) { + case T_BOOLEAN: + array = makeBooleanArray(t, count); + break; + + case T_CHAR: + array = makeCharArray(t, count); + break; + + case T_FLOAT: + array = makeFloatArray(t, count); + break; + + case T_DOUBLE: + array = makeDoubleArray(t, count); + break; + + case T_BYTE: + array = makeByteArray(t, count); + break; + + case T_SHORT: + array = makeShortArray(t, count); + break; + + case T_INT: + array = makeIntArray(t, count); + break; + + case T_LONG: + array = makeLongArray(t, count); + break; + + default: + abort(t); + } + + pushObject(t, array); + } else { + exception + = makeThrowable(t, GcNegativeArraySizeException::Type, "%d", count); + goto throw_; + } + } + goto loop; + + case nop: + goto loop; + + case pop_: { + --sp; + } + goto loop; + + case pop2: { + sp -= 2; + } + goto loop; + + case putfield: { + uint16_t index = codeReadInt16(t, code, ip); + + GcField* field = resolveField(t, frameMethod(t, frame), index - 1); + + assertT(t, (field->flags() & ACC_STATIC) == 0); + PROTECT(t, field); + + { + ACQUIRE_FIELD_FOR_WRITE(t, field); + + switch (field->code()) { + case ByteField: + case BooleanField: + case CharField: + case ShortField: + case FloatField: + case IntField: { + int32_t value = popInt(t); + object o = popObject(t); + if (LIKELY(o)) { + switch (field->code()) { + case ByteField: + case BooleanField: + fieldAtOffset(o, field->offset()) = value; + break; + + case CharField: + case ShortField: + fieldAtOffset(o, field->offset()) = value; + break; + + case FloatField: + case IntField: + fieldAtOffset(o, field->offset()) = value; + break; + } + } else { + exception = makeThrowable(t, GcNullPointerException::Type); + } + } break; + + case DoubleField: + case LongField: { + int64_t value = popLong(t); + object o = popObject(t); + if (LIKELY(o)) { + fieldAtOffset(o, field->offset()) = value; + } else { + exception = makeThrowable(t, GcNullPointerException::Type); + } + } break; + + case ObjectField: { + object value = popObject(t); + object o = popObject(t); + if (LIKELY(o)) { + setField(t, o, field->offset(), value); + } else { + exception = makeThrowable(t, GcNullPointerException::Type); + } + } break; + + default: + abort(t); + } + } + + if (UNLIKELY(exception)) { + goto throw_; + } + } + goto loop; + + case putstatic: { + uint16_t index = codeReadInt16(t, code, ip); + + GcField* field = resolveField(t, frameMethod(t, frame), index - 1); + + assertT(t, field->flags() & ACC_STATIC); + + PROTECT(t, field); + + ACQUIRE_FIELD_FOR_WRITE(t, field); + + initClass(t, field->class_()); + + GcSingleton* table = field->class_()->staticTable(); + + switch (field->code()) { + case ByteField: + case BooleanField: + case CharField: + case ShortField: + case FloatField: + case IntField: { + int32_t value = popInt(t); + switch (field->code()) { + case ByteField: + case BooleanField: + fieldAtOffset(table, field->offset()) = value; + break; + + case CharField: + case ShortField: + fieldAtOffset(table, field->offset()) = value; + break; + + case FloatField: + case IntField: + fieldAtOffset(table, field->offset()) = value; + break; + } + } break; + + case DoubleField: + case LongField: { + fieldAtOffset(table, field->offset()) = popLong(t); + } break; + + case ObjectField: { + setField(t, table, field->offset(), popObject(t)); + } break; + + default: + abort(t); + } + } + goto loop; + + case ret: { + ip = localInt(t, code->body()[ip]); + } + goto loop; + + case return_: { + GcMethod* method = frameMethod(t, frame); + if ((method->flags() & ConstructorFlag) + and (method->class_()->vmFlags() & HasFinalMemberFlag)) { + storeStoreMemoryBarrier(); + } + + if (frame > base) { + popFrame(t); + goto loop; + } else { + return 0; + } + } + goto loop; + + case saload: { + int32_t index = popInt(t); + object array = popObject(t); + + if (LIKELY(array)) { + GcShortArray* a = cast(t, array); + if (LIKELY(index >= 0 and static_cast(index) < a->length())) { + pushInt(t, a->body()[index]); + } else { + exception = makeThrowable(t, + GcArrayIndexOutOfBoundsException::Type, + "%d not in [0,%d)", + index, + a->length()); + goto throw_; + } + } else { + exception = makeThrowable(t, GcNullPointerException::Type); + goto throw_; + } + } + goto loop; + + case sastore: { + int16_t value = popInt(t); + int32_t index = popInt(t); + object array = popObject(t); + + if (LIKELY(array)) { + GcShortArray* a = cast(t, array); + if (LIKELY(index >= 0 and static_cast(index) < a->length())) { + a->body()[index] = value; + } else { + exception = makeThrowable(t, + GcArrayIndexOutOfBoundsException::Type, + "%d not in [0,%d)", + index, + a->length()); + goto throw_; + } + } else { + exception = makeThrowable(t, GcNullPointerException::Type); + goto throw_; + } + } + goto loop; + + case sipush: { + pushInt(t, static_cast(codeReadInt16(t, code, ip))); + } + goto loop; + + case swap: { + uintptr_t tmp[2]; + memcpy(tmp, stack + ((sp - 1) * 2), BytesPerWord * 2); + memcpy(stack + ((sp - 1) * 2), stack + ((sp - 2) * 2), BytesPerWord * 2); + memcpy(stack + ((sp - 2) * 2), tmp, BytesPerWord * 2); + } + goto loop; + + case tableswitch: { + int32_t base = ip - 1; + + ip += 3; + ip -= (ip % 4); + + int32_t default_ = codeReadInt32(t, code, ip); + int32_t bottom = codeReadInt32(t, code, ip); + int32_t top = codeReadInt32(t, code, ip); + + int32_t key = popInt(t); + + if (key >= bottom and key <= top) { + unsigned index = ip + ((key - bottom) * 4); + ip = base + codeReadInt32(t, code, index); + } else { + ip = base + default_; + } + } + goto loop; + + case wide: + goto wide; + + case impdep1: { + // this means we're invoking a virtual method on an instance of a + // bootstrap class, so we need to load the real class to get the + // real method and call it. + + assertT(t, frameNext(t, frame) >= base); + popFrame(t); + + assertT(t, code->body()[ip - 3] == invokevirtual); + ip -= 2; + + uint16_t index = codeReadInt16(t, code, ip); + GcMethod* method = resolveMethod(t, frameMethod(t, frame), index - 1); + + unsigned parameterFootprint = method->parameterFootprint(); + GcClass* class_ = objectClass(t, peekObject(t, sp - parameterFootprint)); + assertT(t, class_->vmFlags() & BootstrapFlag); + + resolveClass(t, frameMethod(t, frame)->class_()->loader(), class_->name()); + + ip -= 3; + } + goto loop; + + default: + abort(t); + } + +wide: + switch (code->body()[ip++]) { + case aload: { + pushObject(t, localObject(t, codeReadInt16(t, code, ip))); + } + goto loop; + + case astore: { + setLocalObject(t, codeReadInt16(t, code, ip), popObject(t)); + } + goto loop; + + case iinc: { + uint16_t index = codeReadInt16(t, code, ip); + int16_t count = codeReadInt16(t, code, ip); + + setLocalInt(t, index, localInt(t, index) + count); + } + goto loop; + + case iload: { + pushInt(t, localInt(t, codeReadInt16(t, code, ip))); + } + goto loop; + + case istore: { + setLocalInt(t, codeReadInt16(t, code, ip), popInt(t)); + } + goto loop; + + case lload: { + pushLong(t, localLong(t, codeReadInt16(t, code, ip))); + } + goto loop; + + case lstore: { + setLocalLong(t, codeReadInt16(t, code, ip), popLong(t)); + } + goto loop; + + case ret: { + ip = localInt(t, codeReadInt16(t, code, ip)); + } + goto loop; + + default: + abort(t); + } + +back_branch: + safePoint(t); + goto loop; + +invoke : { + if (method->flags() & ACC_NATIVE) { + invokeNative(t, method); + } else { + if (DebugCalls && method) { + printf("invoke %s.%s\n", + method->class_() && method->class_()->name() ? (const char *)method->class_()->name()->body().begin() : "", + method->name() ? (const char *)method->name()->body().begin() : "" + ); + } + checkStack(t, method); + pushFrame(t, method); + } +} + goto loop; + +throw_: + if (DebugRun || DebugCalls) { + fprintf(stderr, "throw @ %s\n", frameMethod(t, frame)->name()->body().begin()); + } + + pokeInt(t, t->frame + FrameIpOffset, t->ip); + for (; frame >= base; popFrame(t)) { + uint64_t eh = findExceptionHandler(t, frame); + if (eh) { + sp = frame + FrameFootprint; + ip = exceptionHandlerIp(eh); + pushObject(t, exception); + exception = 0; + goto loop; + } + } + + return 0; +} + +uint64_t interpret2(vm::Thread* t, uintptr_t* arguments) +{ + int base = arguments[0]; + bool* success = reinterpret_cast(arguments[1]); + + object r = interpret3(static_cast(t), base); + *success = true; + return reinterpret_cast(r); +} + +object interpret(Thread* t) +{ + const int base = t->frame; + + while (true) { + bool success = false; + uintptr_t arguments[] + = {static_cast(base), reinterpret_cast(&success)}; + + uint64_t r = run(t, interpret2, arguments); + if (success) { + if (t->exception) { + GcThrowable* exception = t->exception; + t->exception = 0; + throw_(t, exception); + } else { + return reinterpret_cast(r); + } + } + } +} + +void pushArguments(Thread* t, + object this_, + const char* spec, + bool indirectObjects, + va_list a) +{ + if (this_) { + pushObject(t, this_); + } + + for (MethodSpecIterator it(t, spec); it.hasNext();) { + switch (*it.next()) { + case 'L': + case '[': + if (indirectObjects) { + object* v = va_arg(a, object*); + pushObject(t, v ? *v : 0); + } else { + pushObject(t, va_arg(a, object)); + } + break; + + case 'J': + case 'D': + pushLong(t, va_arg(a, uint64_t)); + break; + + case 'F': { + pushFloat(t, va_arg(a, double)); + } break; + + default: + pushInt(t, va_arg(a, uint32_t)); + break; + } + } +} + +void pushArguments(Thread* t, + object this_, + const char* spec, + const jvalue* arguments) +{ + if (this_) { + pushObject(t, this_); + } + + unsigned index = 0; + for (MethodSpecIterator it(t, spec); it.hasNext();) { + switch (*it.next()) { + case 'L': + case '[': { + jobject v = arguments[index++].l; + pushObject(t, v ? *v : 0); + } break; + + case 'J': + case 'D': + pushLong(t, arguments[index++].j); + break; + + case 'F': { + pushFloat(t, arguments[index++].f); + } break; + + default: + pushInt(t, arguments[index++].i); + break; + } + } +} + +void pushArguments(Thread* t, object this_, const char* spec, object a) +{ + if (this_) { + pushObject(t, this_); + } + + unsigned index = 0; + for (MethodSpecIterator it(t, spec); it.hasNext();) { + switch (*it.next()) { + case 'L': + case '[': + pushObject(t, objectArrayBody(t, a, index++)); + break; + + case 'J': + case 'D': + pushLong(t, fieldAtOffset(objectArrayBody(t, a, index++), 8)); + break; + + default: + pushInt( + t, + fieldAtOffset(objectArrayBody(t, a, index++), BytesPerWord)); + break; + } + } +} + +object invoke(Thread* t, GcMethod* method) +{ + PROTECT(t, method); + + GcClass* class_; + PROTECT(t, class_); + + if (methodVirtual(t, method)) { + unsigned parameterFootprint = method->parameterFootprint(); + class_ = objectClass(t, peekObject(t, t->sp - parameterFootprint)); + + if (class_->vmFlags() & BootstrapFlag) { + resolveClass(t, roots(t)->bootLoader(), class_->name()); + } + + if (method->class_()->flags() & ACC_INTERFACE) { + method = findInterfaceMethod(t, method, class_); + } else { + method = findVirtualMethod(t, method, class_); + } + } else { + class_ = method->class_(); + } + + if (method->flags() & ACC_STATIC) { + initClass(t, class_); + } + + object result = 0; + + if (method->flags() & ACC_NATIVE) { + unsigned returnCode = invokeNative(t, method); + + switch (returnCode) { + case ByteField: + case BooleanField: + case CharField: + case ShortField: + case FloatField: + case IntField: + result = makeInt(t, popInt(t)); + break; + + case LongField: + case DoubleField: + result = makeLong(t, popLong(t)); + break; + + case ObjectField: + result = popObject(t); + break; + + case VoidField: + result = 0; + break; + + default: + abort(t); + }; + } else { + checkStack(t, method); + pushFrame(t, method); + + result = interpret(t); + + if (LIKELY(t->exception == 0)) { + popFrame(t); + } else { + GcThrowable* exception = t->exception; + t->exception = 0; + throw_(t, exception); + } + } + + return result; +} + +class MyProcessor : public Processor { + public: + MyProcessor(System* s, Allocator* allocator, const char* crashDumpDirectory) + : s(s), allocator(allocator) + { + signals.setCrashDumpDirectory(crashDumpDirectory); + } + + virtual vm::Thread* makeThread(Machine* m, + GcThread* javaThread, + vm::Thread* parent) + { + Thread* t = new (m->heap->allocate(sizeof(Thread) + m->stackSizeInBytes)) + Thread(m, javaThread, parent); + t->init(); + return t; + } + + virtual GcMethod* makeMethod(vm::Thread* t, + uint8_t vmFlags, + uint8_t returnCode, + uint8_t parameterCount, + uint8_t parameterFootprint, + uint16_t flags, + uint16_t offset, + GcByteArray* name, + GcByteArray* spec, + GcMethodAddendum* addendum, + GcClass* class_, + GcCode* code) + { + return vm::makeMethod(t, + vmFlags, + returnCode, + parameterCount, + parameterFootprint, + flags, + offset, + 0, + 0, + name, + spec, + addendum, + class_, + code); + } + + virtual GcClass* makeClass(vm::Thread* t, + uint16_t flags, + uint16_t vmFlags, + uint16_t fixedSize, + uint8_t arrayElementSize, + uint8_t arrayDimensions, + GcClass* arrayElementClass, + GcIntArray* objectMask, + GcByteArray* name, + GcByteArray* sourceFile, + GcClass* super, + object interfaceTable, + object virtualTable, + object fieldTable, + object methodTable, + GcClassAddendum* addendum, + GcSingleton* staticTable, + GcClassLoader* loader, + unsigned vtableLength UNUSED) + { + return vm::makeClass(t, + flags, + vmFlags, + fixedSize, + arrayElementSize, + arrayDimensions, + arrayElementClass, + 0, + objectMask, + name, + sourceFile, + super, + interfaceTable, + virtualTable, + fieldTable, + methodTable, + addendum, + staticTable, + loader, + 0, + 0); + } + + virtual void initVtable(vm::Thread*, GcClass*) + { + // ignore + } + + virtual void visitObjects(vm::Thread* vmt, Heap::Visitor* v) + { + Thread* t = static_cast(vmt); + + v->visit(&(t->code)); + + for (unsigned i = 0; i < t->sp; ++i) { + if (t->stack[i * 2] == ObjectTag) { + v->visit(reinterpret_cast(t->stack + (i * 2) + 1)); + } + } + } + + virtual void walkStack(vm::Thread* vmt, StackVisitor* v) + { + Thread* t = static_cast(vmt); + + if (t->frame >= 0) { + pokeInt(t, t->frame + FrameIpOffset, t->ip); + } + + MyStackWalker walker(t, t->frame); + walker.walk(v); + } + + virtual int lineNumber(vm::Thread* t, GcMethod* method, int ip) + { + return findLineNumber(static_cast(t), method, ip); + } + + virtual object* makeLocalReference(vm::Thread* vmt, object o) + { + Thread* t = static_cast(vmt); + + return pushReference(t, o); + } + + virtual void disposeLocalReference(vm::Thread*, object* r) + { + if (r) { + *r = 0; + } + } + + virtual bool pushLocalFrame(vm::Thread* vmt, unsigned capacity) + { + Thread* t = static_cast(vmt); + + if (t->sp + capacity < stackSizeInWords(t) / 2) { + t->stackPointers = new (t->m->heap) + List(t->sp, t->stackPointers); + + return true; + } else { + return false; + } + } + + virtual void popLocalFrame(vm::Thread* vmt) + { + Thread* t = static_cast(vmt); + + List* f = t->stackPointers; + t->stackPointers = f->next; + t->sp = f->item; + + t->m->heap->free(f, sizeof(List)); + } + + virtual object invokeArray(vm::Thread* vmt, + GcMethod* method, + object this_, + object arguments) + { + Thread* t = static_cast(vmt); + + assertT( + t, + t->state == Thread::ActiveState or t->state == Thread::ExclusiveState); + + assertT(t, ((method->flags() & ACC_STATIC) == 0) xor (this_ == 0)); + + if (UNLIKELY(t->sp + method->parameterFootprint() + 1 > stackSizeInWords(t) + / 2)) { + throwNew(t, GcStackOverflowError::Type); + } + + const char* spec = reinterpret_cast(method->spec()->body().begin()); + pushArguments(t, this_, spec, arguments); + + return local::invoke(t, method); + } + + virtual object invokeArray(vm::Thread* vmt, + GcMethod* method, + object this_, + const jvalue* arguments) + { + Thread* t = static_cast(vmt); + + assertT( + t, + t->state == Thread::ActiveState or t->state == Thread::ExclusiveState); + + assertT(t, ((method->flags() & ACC_STATIC) == 0) xor (this_ == 0)); + + if (UNLIKELY(t->sp + method->parameterFootprint() + 1 > stackSizeInWords(t) + / 2)) { + throwNew(t, GcStackOverflowError::Type); + } + + const char* spec = reinterpret_cast(method->spec()->body().begin()); + pushArguments(t, this_, spec, arguments); + + return local::invoke(t, method); + } + + virtual object invokeList(vm::Thread* vmt, + GcMethod* method, + object this_, + bool indirectObjects, + va_list arguments) + { + Thread* t = static_cast(vmt); + + assertT( + t, + t->state == Thread::ActiveState or t->state == Thread::ExclusiveState); + + assertT(t, ((method->flags() & ACC_STATIC) == 0) xor (this_ == 0)); + + if (UNLIKELY(t->sp + method->parameterFootprint() + 1 > stackSizeInWords(t) + / 2)) { + throwNew(t, GcStackOverflowError::Type); + } + + const char* spec = reinterpret_cast(method->spec()->body().begin()); + pushArguments(t, this_, spec, indirectObjects, arguments); + + return local::invoke(t, method); + } + + virtual object invokeList(vm::Thread* vmt, + GcClassLoader* loader, + const char* className, + const char* methodName, + const char* methodSpec, + object this_, + va_list arguments) + { + Thread* t = static_cast(vmt); + + assertT( + t, + t->state == Thread::ActiveState or t->state == Thread::ExclusiveState); + + if (UNLIKELY(t->sp + parameterFootprint(vmt, methodSpec, false) + > stackSizeInWords(t) / 2)) { + throwNew(t, GcStackOverflowError::Type); + } + + pushArguments(t, this_, methodSpec, false, arguments); + + GcMethod* method + = resolveMethod(t, loader, className, methodName, methodSpec); + + assertT(t, ((method->flags() & ACC_STATIC) == 0) xor (this_ == 0)); + + return local::invoke(t, method); + } + + virtual object getStackTrace(vm::Thread* t, vm::Thread*) + { + // not implemented + return makeObjectArray(t, 0); + } + + virtual void initialize(BootImage*, avian::util::Slice) + { + abort(s); + } + + virtual void addCompilationHandler(CompilationHandler*) + { + abort(s); + } + + virtual void compileMethod(vm::Thread*, + Zone*, + GcTriple**, + GcTriple**, + avian::codegen::DelayedPromise**, + GcMethod*, + OffsetResolver*, + JavaVM*) + { + abort(s); + } + + virtual void visitRoots(vm::Thread*, HeapWalker*) + { + abort(s); + } + + virtual void normalizeVirtualThunks(vm::Thread*) + { + abort(s); + } + + virtual unsigned* makeCallTable(vm::Thread*, HeapWalker*) + { + abort(s); + } + + virtual void boot(vm::Thread*, BootImage* image, uint8_t* code) + { + expect(s, image == 0 and code == 0); + } + + virtual void callWithCurrentContinuation(vm::Thread*, object) + { + abort(s); + } + + virtual void dynamicWind(vm::Thread*, object, object, object) + { + abort(s); + } + + virtual void feedResultToContinuation(vm::Thread*, GcContinuation*, object) + { + abort(s); + } + + virtual void feedExceptionToContinuation(vm::Thread*, + GcContinuation*, + GcThrowable*) + { + abort(s); + } + + virtual void walkContinuationBody(vm::Thread*, + Heap::Walker*, + object, + unsigned) + { + abort(s); + } + + virtual void dispose(vm::Thread* t) + { + t->m->heap->free(t, sizeof(Thread) + t->m->stackSizeInBytes); + } + + virtual void dispose() + { + signals.setCrashDumpDirectory(0); + this->~MyProcessor(); + allocator->free(this, sizeof(*this)); + } + + System* s; + Allocator* allocator; + SignalRegistrar signals; +}; + +} // namespace + +namespace vm { + +Processor* makeProcessor(System* system, + Allocator* allocator, + const char* crashDumpDirectory, + bool) +{ + return new (allocator->allocate(sizeof(local::MyProcessor))) + local::MyProcessor(system, allocator, crashDumpDirectory); +} + +} // namespace vm diff --git a/sgx-jvm/avian/src/jnienv.cpp b/sgx-jvm/avian/src/jnienv.cpp new file mode 100644 index 0000000000..57613ab2d2 --- /dev/null +++ b/sgx-jvm/avian/src/jnienv.cpp @@ -0,0 +1,3811 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#include "avian/jnienv.h" +#include "avian/machine.h" +#include "avian/util.h" +#include "avian/processor.h" +#include "avian/constants.h" + +#include + +using namespace vm; + +namespace { + +namespace local { + +jint JNICALL AttachCurrentThread(Machine* m, Thread** t, void*) +{ + *t = static_cast(m->localThread->get()); + if (*t == 0) { + *t = attachThread(m, false); + } + return 0; +} + +jint JNICALL AttachCurrentThreadAsDaemon(Machine* m, Thread** t, void*) +{ + *t = static_cast(m->localThread->get()); + if (*t == 0) { + *t = attachThread(m, true); + } + return 0; +} + +jint JNICALL DetachCurrentThread(Machine* m) +{ + Thread* t = static_cast(m->localThread->get()); + if (t) { + // todo: detaching the root thread seems to cause stability + // problems which I haven't yet had a chance to investigate + // thoroughly. Meanwhile, we just ignore requests to detach it, + // which leaks a bit of memory but should be harmless otherwise. + if (m->rootThread != t) { + m->localThread->set(0); + + ACQUIRE_RAW(t, t->m->stateLock); + + enter(t, Thread::ActiveState); + + t->javaThread->peer() = 0; + + enter(t, Thread::ZombieState); + + t->state = Thread::JoinedState; + } + + return 0; + } else { + return -1; + } +} + +uint64_t destroyJavaVM(Thread* t, uintptr_t*) +{ +#ifndef SGX + // wait for other non-daemon threads to exit + { + ACQUIRE(t, t->m->stateLock); + while (t->m->liveCount - t->m->daemonCount > 1) { + t->m->stateLock->wait(t->systemThread, 0); + } + } +#endif + { + ENTER(t, Thread::ActiveState); + + t->m->classpath->shutDown(t); + } +#ifndef SGX + // wait again in case the Classpath::shutDown process started new + // threads: + { + ACQUIRE(t, t->m->stateLock); + while (t->m->liveCount - t->m->daemonCount > 1) { + t->m->stateLock->wait(t->systemThread, 0); + } + + enter(t, Thread::ExclusiveState); + } +#endif + shutDown(t); + + return 1; +} + +jint JNICALL DestroyJavaVM(Machine* m) +{ + Thread* t; + AttachCurrentThread(m, &t, 0); + + if (runRaw(t, destroyJavaVM, 0)) { + t->exit(); + return 0; + } else { + return -1; + } +} + +jint JNICALL GetEnv(Machine* m, Thread** t, jint version) +{ + *t = static_cast(m->localThread->get()); + if (*t) { + if (version <= JNI_VERSION_1_6) { + return AVIAN_JNI_OK; + } else { + return AVIAN_JNI_EVERSION; + } + } else { + return AVIAN_JNI_EDETACHED; + } +} + +jint JNICALL GetVersion(Thread* t) +{ + ENTER(t, Thread::ActiveState); + + return JNI_VERSION_1_6; +} + +jsize JNICALL GetStringLength(Thread* t, jstring s) +{ + ENTER(t, Thread::ActiveState); + + return (*s)->length(t); +} + +const jchar* JNICALL GetStringChars(Thread* t, jstring s, jboolean* isCopy) +{ + ENTER(t, Thread::ActiveState); + + jchar* chars = static_cast( + t->m->heap->allocate(((*s)->length(t) + 1) * sizeof(jchar))); + stringChars(t, *s, chars); + + if (isCopy) + *isCopy = true; + return chars; +} + +void JNICALL ReleaseStringChars(Thread* t, jstring s, const jchar* chars) +{ + ENTER(t, Thread::ActiveState); + + t->m->heap->free(chars, ((*s)->length(t) + 1) * sizeof(jchar)); +} + +void JNICALL + GetStringRegion(Thread* t, jstring s, jsize start, jsize length, jchar* dst) +{ + ENTER(t, Thread::ActiveState); + + stringChars(t, *s, start, length, dst); +} + +const jchar* JNICALL GetStringCritical(Thread* t, jstring s, jboolean* isCopy) +{ + if (t->criticalLevel == 0) { + enter(t, Thread::ActiveState); + } + + ++t->criticalLevel; + + if (isCopy) { + *isCopy = true; + } + + object data = (*s)->data(); + if (objectClass(t, data) == type(t, GcByteArray::Type)) { + return GetStringChars(t, s, isCopy); + } else { + return &cast(t, data)->body()[(*s)->offset(t)]; + } +} + +void JNICALL ReleaseStringCritical(Thread* t, jstring s, const jchar* chars) +{ + if (objectClass(t, (*s)->data()) == type(t, GcByteArray::Type)) { + ReleaseStringChars(t, s, chars); + } + + if ((--t->criticalLevel) == 0) { + enter(t, Thread::IdleState); + } +} + +jsize JNICALL GetStringUTFLength(Thread* t, jstring s) +{ + ENTER(t, Thread::ActiveState); + + return stringUTFLength(t, *s); +} + +const char* JNICALL GetStringUTFChars(Thread* t, jstring s, jboolean* isCopy) +{ + ENTER(t, Thread::ActiveState); + + int length = stringUTFLength(t, *s); + char* chars = static_cast(t->m->heap->allocate(length + 1)); + stringUTFChars(t, *s, chars, length); + + if (isCopy) + *isCopy = true; + return chars; +} + +void JNICALL ReleaseStringUTFChars(Thread* t, jstring s, const char* chars) +{ + ENTER(t, Thread::ActiveState); + + t->m->heap->free(chars, stringUTFLength(t, *s) + 1); +} + +void JNICALL GetStringUTFRegion(Thread* t, + jstring s, + jsize start, + jsize length, + char* dst) +{ + ENTER(t, Thread::ActiveState); + + stringUTFChars( + t, *s, start, length, dst, stringUTFLength(t, *s, start, length)); +} + +jsize JNICALL GetArrayLength(Thread* t, jarray array) +{ + ENTER(t, Thread::ActiveState); + + return fieldAtOffset(*array, BytesPerWord); +} + +uint64_t newString(Thread* t, uintptr_t* arguments) +{ + const jchar* chars = reinterpret_cast(arguments[0]); + jsize size = arguments[1]; + + GcCharArray* a = makeCharArray(t, size); + if (size) { + memcpy(a->body().begin(), chars, size * sizeof(jchar)); + } + + return reinterpret_cast( + makeLocalReference(t, t->m->classpath->makeString(t, a, 0, size))); +} + +jstring JNICALL NewString(Thread* t, const jchar* chars, jsize size) +{ + if (chars == 0) + return 0; + + uintptr_t arguments[] + = {reinterpret_cast(chars), static_cast(size)}; + + return reinterpret_cast(run(t, newString, arguments)); +} + +uint64_t newStringUTF(Thread* t, uintptr_t* arguments) +{ + const char* chars = reinterpret_cast(arguments[0]); + + object array = parseUtf8(t, chars, strlen(chars)); + + return reinterpret_cast(makeLocalReference( + t, + t->m->classpath->makeString( + t, array, 0, fieldAtOffset(array, BytesPerWord) - 1))); +} + +jstring JNICALL NewStringUTF(Thread* t, const char* chars) +{ + if (chars == 0) + return 0; + + uintptr_t arguments[] = {reinterpret_cast(chars)}; + + return reinterpret_cast(run(t, newStringUTF, arguments)); +} + +void replace(int a, int b, const char* in, int8_t* out) +{ + while (*in) { + *out = (*in == a ? b : *in); + ++in; + ++out; + } + *out = 0; +} + +uint64_t defineClass(Thread* t, uintptr_t* arguments) +{ + jobject loader = reinterpret_cast(arguments[0]); + const uint8_t* buffer = reinterpret_cast(arguments[1]); + jsize length = arguments[2]; + + return reinterpret_cast(makeLocalReference( + t, + getJClass( + t, + cast(t, + defineClass(t, + loader ? cast(t, *loader) + : roots(t)->bootLoader(), + buffer, + length))))); +} + +jclass JNICALL DefineClass(Thread* t, + const char*, + jobject loader, + const jbyte* buffer, + jsize length) +{ + uintptr_t arguments[] = {reinterpret_cast(loader), + reinterpret_cast(buffer), + static_cast(length)}; + + return reinterpret_cast(run(t, defineClass, arguments)); +} + +uint64_t findClass(Thread* t, uintptr_t* arguments) +{ + const char* name = reinterpret_cast(arguments[0]); + + GcByteArray* n = makeByteArray(t, strlen(name) + 1); + replace('.', '/', name, n->body().begin()); + + GcMethod* caller = getCaller(t, 0); + + GcClass* c + = resolveClass(t, + caller ? t->m->classpath->libraryClassLoader(t, caller) + : roots(t)->appLoader(), + n); + + if (t->m->classpath->mayInitClasses()) { + PROTECT(t, c); + + initClass(t, c); + } + + return reinterpret_cast(makeLocalReference(t, getJClass(t, c))); +} + +jclass JNICALL FindClass(Thread* t, const char* name) +{ + uintptr_t arguments[] = {reinterpret_cast(name)}; + + return reinterpret_cast(run(t, findClass, arguments)); +} + +uint64_t throwNew(Thread* t, uintptr_t* arguments) +{ + jclass c = reinterpret_cast(arguments[0]); + const char* message = reinterpret_cast(arguments[1]); + + GcString* m = 0; + PROTECT(t, m); + + if (message) { + m = makeString(t, "%s", message); + } + + object trace = makeTrace(t); + PROTECT(t, trace); + + t->exception = cast(t, make(t, (*c)->vmClass())); + t->exception->setMessage(t, m); + t->exception->setTrace(t, trace); + + return 1; +} + +jint JNICALL ThrowNew(Thread* t, jclass c, const char* message) +{ + if (t->exception) { + return -1; + } + + uintptr_t arguments[] + = {reinterpret_cast(c), reinterpret_cast(message)}; + + return run(t, throwNew, arguments) ? 0 : -1; +} + +jint JNICALL Throw(Thread* t, jthrowable throwable) +{ + if (t->exception) { + return -1; + } + + ENTER(t, Thread::ActiveState); + + t->exception = *throwable; + + return 0; +} + +jobject JNICALL NewLocalRef(Thread* t, jobject o) +{ + ENTER(t, Thread::ActiveState); + + return makeLocalReference(t, *o); +} + +void JNICALL DeleteLocalRef(Thread* t, jobject r) +{ + ENTER(t, Thread::ActiveState); + + disposeLocalReference(t, r); +} + +jboolean JNICALL ExceptionCheck(Thread* t) +{ + return t->exception != 0; +} + +uint64_t getObjectClass(Thread* t, uintptr_t* arguments) +{ + jobject o = reinterpret_cast(arguments[0]); + + return reinterpret_cast( + makeLocalReference(t, getJClass(t, objectClass(t, *o)))); +} + +jclass JNICALL GetObjectClass(Thread* t, jobject o) +{ + uintptr_t arguments[] = {reinterpret_cast(o)}; + + return reinterpret_cast(run(t, getObjectClass, arguments)); +} + +uint64_t getSuperclass(Thread* t, uintptr_t* arguments) +{ + GcClass* class_ = (*reinterpret_cast(arguments[0]))->vmClass(); + if (class_->flags() & ACC_INTERFACE) { + return 0; + } else { + GcClass* super = class_->super(); + return super ? reinterpret_cast( + makeLocalReference(t, getJClass(t, super))) + : 0; + } +} + +jclass JNICALL GetSuperclass(Thread* t, jclass c) +{ + uintptr_t arguments[] = {reinterpret_cast(c)}; + + return reinterpret_cast(run(t, getSuperclass, arguments)); +} + +uint64_t isInstanceOf(Thread* t, uintptr_t* arguments) +{ + jobject o = reinterpret_cast(arguments[0]); + jclass c = reinterpret_cast(arguments[1]); + + return instanceOf(t, (*c)->vmClass(), *o); +} + +jboolean JNICALL IsInstanceOf(Thread* t, jobject o, jclass c) +{ + uintptr_t arguments[] + = {reinterpret_cast(o), reinterpret_cast(c)}; + + return run(t, isInstanceOf, arguments); +} + +uint64_t isAssignableFrom(Thread* t, uintptr_t* arguments) +{ + jclass b = reinterpret_cast(arguments[0]); + jclass a = reinterpret_cast(arguments[1]); + + return isAssignableFrom(t, (*a)->vmClass(), (*b)->vmClass()); +} + +jboolean JNICALL IsAssignableFrom(Thread* t, jclass b, jclass a) +{ + uintptr_t arguments[] + = {reinterpret_cast(b), reinterpret_cast(a)}; + + return run(t, isAssignableFrom, arguments); +} + +GcMethod* findMethod(Thread* t, jclass c, const char* name, const char* spec) +{ + GcByteArray* n = makeByteArray(t, "%s", name); + PROTECT(t, n); + + GcByteArray* s = makeByteArray(t, "%s", spec); + return vm::findMethod(t, (*c)->vmClass(), n, s); +} + +jint methodID(Thread* t, GcMethod* method) +{ + int id = method->nativeID(); + + loadMemoryBarrier(); + + if (id == 0) { + PROTECT(t, method); + + ACQUIRE(t, t->m->referenceLock); + + if (method->nativeID() == 0) { + GcVector* v = vectorAppend(t, roots(t)->jNIMethodTable(), method); + // sequence point, for gc (don't recombine statements) + roots(t)->setJNIMethodTable(t, v); + + storeStoreMemoryBarrier(); + + method->nativeID() = roots(t)->jNIMethodTable()->size(); + } + } + + return method->nativeID(); +} + +uint64_t getMethodID(Thread* t, uintptr_t* arguments) +{ + jclass c = reinterpret_cast(arguments[0]); + const char* name = reinterpret_cast(arguments[1]); + const char* spec = reinterpret_cast(arguments[2]); + + GcMethod* method = findMethod(t, c, name, spec); + + assertT(t, (method->flags() & ACC_STATIC) == 0); + + return methodID(t, method); +} + +jmethodID JNICALL + GetMethodID(Thread* t, jclass c, const char* name, const char* spec) +{ + uintptr_t arguments[] = {reinterpret_cast(c), + reinterpret_cast(name), + reinterpret_cast(spec)}; + + return run(t, getMethodID, arguments); +} + +uint64_t getStaticMethodID(Thread* t, uintptr_t* arguments) +{ + jclass c = reinterpret_cast(arguments[0]); + const char* name = reinterpret_cast(arguments[1]); + const char* spec = reinterpret_cast(arguments[2]); + + GcMethod* method = findMethod(t, c, name, spec); + + assertT(t, method->flags() & ACC_STATIC); + + return methodID(t, method); +} + +jmethodID JNICALL + GetStaticMethodID(Thread* t, jclass c, const char* name, const char* spec) +{ + uintptr_t arguments[] = {reinterpret_cast(c), + reinterpret_cast(name), + reinterpret_cast(spec)}; + + return run(t, getStaticMethodID, arguments); +} + +GcMethod* getMethod(Thread* t, jmethodID m) +{ + assertT(t, m); + + GcMethod* method + = cast(t, roots(t)->jNIMethodTable()->body()[m - 1]); + + assertT(t, (method->flags() & ACC_STATIC) == 0); + + return method; +} + +uint64_t newObjectV(Thread* t, uintptr_t* arguments) +{ + jclass c = reinterpret_cast(arguments[0]); + jmethodID m = arguments[1]; + va_list* a = reinterpret_cast(arguments[2]); + + object o = make(t, (*c)->vmClass()); + PROTECT(t, o); + + t->m->processor->invokeList(t, getMethod(t, m), o, true, *a); + + return reinterpret_cast(makeLocalReference(t, o)); +} + +jobject JNICALL NewObjectV(Thread* t, jclass c, jmethodID m, va_list a) +{ + uintptr_t arguments[] = {reinterpret_cast(c), + m, + reinterpret_cast(VA_LIST(a))}; + + return reinterpret_cast(run(t, newObjectV, arguments)); +} + +jobject JNICALL NewObject(Thread* t, jclass c, jmethodID m, ...) +{ + va_list a; + va_start(a, m); + + jobject r = NewObjectV(t, c, m, a); + + va_end(a); + + return r; +} + +uint64_t newObjectA(Thread* t, uintptr_t* arguments) +{ + jclass c = reinterpret_cast(arguments[0]); + jmethodID m = arguments[1]; + const jvalue* a = reinterpret_cast(arguments[2]); + + object o = make(t, (*c)->vmClass()); + PROTECT(t, o); + + t->m->processor->invokeArray(t, getMethod(t, m), o, a); + + return reinterpret_cast(makeLocalReference(t, o)); +} + +jobject JNICALL NewObjectA(Thread* t, jclass c, jmethodID m, const jvalue* a) +{ + uintptr_t arguments[] + = {reinterpret_cast(c), m, reinterpret_cast(a)}; + + return reinterpret_cast(run(t, newObjectA, arguments)); +} + +uint64_t callObjectMethodV(Thread* t, uintptr_t* arguments) +{ + jobject o = reinterpret_cast(arguments[0]); + jmethodID m = arguments[1]; + va_list* a = reinterpret_cast(arguments[2]); + + return reinterpret_cast(makeLocalReference( + t, t->m->processor->invokeList(t, getMethod(t, m), *o, true, *a))); +} + +jobject JNICALL CallObjectMethodV(Thread* t, jobject o, jmethodID m, va_list a) +{ + uintptr_t arguments[] = {reinterpret_cast(o), + m, + reinterpret_cast(VA_LIST(a))}; + + return reinterpret_cast(run(t, callObjectMethodV, arguments)); +} + +jobject JNICALL CallObjectMethod(Thread* t, jobject o, jmethodID m, ...) +{ + va_list a; + va_start(a, m); + + jobject r = CallObjectMethodV(t, o, m, a); + + va_end(a); + + return r; +} + +uint64_t callObjectMethodA(Thread* t, uintptr_t* arguments) +{ + jobject o = reinterpret_cast(arguments[0]); + jmethodID m = arguments[1]; + const jvalue* a = reinterpret_cast(arguments[2]); + + return reinterpret_cast(makeLocalReference( + t, t->m->processor->invokeArray(t, getMethod(t, m), *o, a))); +} + +jobject JNICALL + CallObjectMethodA(Thread* t, jobject o, jmethodID m, const jvalue* a) +{ + uintptr_t arguments[] + = {reinterpret_cast(o), m, reinterpret_cast(a)}; + + return reinterpret_cast(run(t, callObjectMethodA, arguments)); +} + +uint64_t callIntMethodV(Thread* t, uintptr_t* arguments) +{ + jobject o = reinterpret_cast(arguments[0]); + jmethodID m = arguments[1]; + va_list* a = reinterpret_cast(arguments[2]); + + return cast( + t, t->m->processor->invokeList(t, getMethod(t, m), *o, true, *a)) + ->value(); +} + +jboolean JNICALL + CallBooleanMethodV(Thread* t, jobject o, jmethodID m, va_list a) +{ + uintptr_t arguments[] = {reinterpret_cast(o), + m, + reinterpret_cast(VA_LIST(a))}; + + return run(t, callIntMethodV, arguments) != 0; +} + +jboolean JNICALL CallBooleanMethod(Thread* t, jobject o, jmethodID m, ...) +{ + va_list a; + va_start(a, m); + + jboolean r = CallBooleanMethodV(t, o, m, a); + + va_end(a); + + return r; +} + +uint64_t callIntMethodA(Thread* t, uintptr_t* arguments) +{ + jobject o = reinterpret_cast(arguments[0]); + jmethodID m = arguments[1]; + const jvalue* a = reinterpret_cast(arguments[2]); + + return cast(t, t->m->processor->invokeArray(t, getMethod(t, m), *o, a)) + ->value(); +} + +jboolean JNICALL + CallBooleanMethodA(Thread* t, jobject o, jmethodID m, const jvalue* a) +{ + uintptr_t arguments[] + = {reinterpret_cast(o), m, reinterpret_cast(a)}; + + return run(t, callIntMethodA, arguments) != 0; +} + +jbyte JNICALL CallByteMethodV(Thread* t, jobject o, jmethodID m, va_list a) +{ + uintptr_t arguments[] = {reinterpret_cast(o), + m, + reinterpret_cast(VA_LIST(a))}; + + return run(t, callIntMethodV, arguments); +} + +jbyte JNICALL CallByteMethod(Thread* t, jobject o, jmethodID m, ...) +{ + va_list a; + va_start(a, m); + + jbyte r = CallByteMethodV(t, o, m, a); + + va_end(a); + + return r; +} + +jbyte JNICALL + CallByteMethodA(Thread* t, jobject o, jmethodID m, const jvalue* a) +{ + uintptr_t arguments[] + = {reinterpret_cast(o), m, reinterpret_cast(a)}; + + return run(t, callIntMethodA, arguments); +} + +jchar JNICALL CallCharMethodV(Thread* t, jobject o, jmethodID m, va_list a) +{ + uintptr_t arguments[] = {reinterpret_cast(o), + m, + reinterpret_cast(VA_LIST(a))}; + + return run(t, callIntMethodV, arguments); +} + +jchar JNICALL CallCharMethod(Thread* t, jobject o, jmethodID m, ...) +{ + va_list a; + va_start(a, m); + + jchar r = CallCharMethodV(t, o, m, a); + + va_end(a); + + return r; +} + +jchar JNICALL + CallCharMethodA(Thread* t, jobject o, jmethodID m, const jvalue* a) +{ + uintptr_t arguments[] + = {reinterpret_cast(o), m, reinterpret_cast(a)}; + + return run(t, callIntMethodA, arguments); +} + +jshort JNICALL CallShortMethodV(Thread* t, jobject o, jmethodID m, va_list a) +{ + uintptr_t arguments[] = {reinterpret_cast(o), + m, + reinterpret_cast(VA_LIST(a))}; + + return run(t, callIntMethodV, arguments); +} + +jshort JNICALL CallShortMethod(Thread* t, jobject o, jmethodID m, ...) +{ + va_list a; + va_start(a, m); + + jshort r = CallShortMethodV(t, o, m, a); + + va_end(a); + + return r; +} + +jshort JNICALL + CallShortMethodA(Thread* t, jobject o, jmethodID m, const jvalue* a) +{ + uintptr_t arguments[] + = {reinterpret_cast(o), m, reinterpret_cast(a)}; + + return run(t, callIntMethodA, arguments); +} + +jint JNICALL CallIntMethodV(Thread* t, jobject o, jmethodID m, va_list a) +{ + uintptr_t arguments[] = {reinterpret_cast(o), + m, + reinterpret_cast(VA_LIST(a))}; + + return run(t, callIntMethodV, arguments); +} + +jint JNICALL CallIntMethod(Thread* t, jobject o, jmethodID m, ...) +{ + va_list a; + va_start(a, m); + + jint r = CallIntMethodV(t, o, m, a); + + va_end(a); + + return r; +} + +jint JNICALL CallIntMethodA(Thread* t, jobject o, jmethodID m, const jvalue* a) +{ + uintptr_t arguments[] + = {reinterpret_cast(o), m, reinterpret_cast(a)}; + + return run(t, callIntMethodA, arguments); +} + +uint64_t callLongMethodV(Thread* t, uintptr_t* arguments) +{ + jobject o = reinterpret_cast(arguments[0]); + jmethodID m = arguments[1]; + va_list* a = reinterpret_cast(arguments[2]); + + return cast( + t, t->m->processor->invokeList(t, getMethod(t, m), *o, true, *a)) + ->value(); +} + +jlong JNICALL CallLongMethodV(Thread* t, jobject o, jmethodID m, va_list a) +{ + uintptr_t arguments[] = {reinterpret_cast(o), + m, + reinterpret_cast(VA_LIST(a))}; + + return run(t, callLongMethodV, arguments); +} + +jlong JNICALL CallLongMethod(Thread* t, jobject o, jmethodID m, ...) +{ + va_list a; + va_start(a, m); + + jlong r = CallLongMethodV(t, o, m, a); + + va_end(a); + + return r; +} + +uint64_t callLongMethodA(Thread* t, uintptr_t* arguments) +{ + jobject o = reinterpret_cast(arguments[0]); + jmethodID m = arguments[1]; + const jvalue* a = reinterpret_cast(arguments[2]); + + return cast(t, + t->m->processor->invokeArray(t, getMethod(t, m), *o, a)) + ->value(); +} + +jlong JNICALL + CallLongMethodA(Thread* t, jobject o, jmethodID m, const jvalue* a) +{ + uintptr_t arguments[] + = {reinterpret_cast(o), m, reinterpret_cast(a)}; + + return run(t, callLongMethodA, arguments); +} + +jfloat JNICALL CallFloatMethodV(Thread* t, jobject o, jmethodID m, va_list a) +{ + uintptr_t arguments[] = {reinterpret_cast(o), + m, + reinterpret_cast(VA_LIST(a))}; + + return bitsToFloat(run(t, callIntMethodV, arguments)); +} + +jfloat JNICALL CallFloatMethod(Thread* t, jobject o, jmethodID m, ...) +{ + va_list a; + va_start(a, m); + + jfloat r = CallFloatMethodV(t, o, m, a); + + va_end(a); + + return r; +} + +jfloat JNICALL + CallFloatMethodA(Thread* t, jobject o, jmethodID m, const jvalue* a) +{ + uintptr_t arguments[] + = {reinterpret_cast(o), m, reinterpret_cast(a)}; + + return bitsToFloat(run(t, callIntMethodA, arguments)); +} + +jdouble JNICALL CallDoubleMethodV(Thread* t, jobject o, jmethodID m, va_list a) +{ + uintptr_t arguments[] = {reinterpret_cast(o), + m, + reinterpret_cast(VA_LIST(a))}; + + return bitsToDouble(run(t, callLongMethodV, arguments)); +} + +jdouble JNICALL CallDoubleMethod(Thread* t, jobject o, jmethodID m, ...) +{ + va_list a; + va_start(a, m); + + jdouble r = CallDoubleMethodV(t, o, m, a); + + va_end(a); + + return r; +} + +jdouble JNICALL + CallDoubleMethodA(Thread* t, jobject o, jmethodID m, const jvalue* a) +{ + uintptr_t arguments[] + = {reinterpret_cast(o), m, reinterpret_cast(a)}; + + return bitsToDouble(run(t, callLongMethodA, arguments)); +} + +uint64_t callVoidMethodV(Thread* t, uintptr_t* arguments) +{ + jobject o = reinterpret_cast(arguments[0]); + jmethodID m = arguments[1]; + va_list* a = reinterpret_cast(arguments[2]); + + t->m->processor->invokeList(t, getMethod(t, m), *o, true, *a); + + return 0; +} + +void JNICALL CallVoidMethodV(Thread* t, jobject o, jmethodID m, va_list a) +{ + uintptr_t arguments[] = {reinterpret_cast(o), + m, + reinterpret_cast(VA_LIST(a))}; + + run(t, callVoidMethodV, arguments); +} + +void JNICALL CallVoidMethod(Thread* t, jobject o, jmethodID m, ...) +{ + va_list a; + va_start(a, m); + + CallVoidMethodV(t, o, m, a); + + va_end(a); +} + +uint64_t callVoidMethodA(Thread* t, uintptr_t* arguments) +{ + jobject o = reinterpret_cast(arguments[0]); + jmethodID m = arguments[1]; + const jvalue* a = reinterpret_cast(arguments[2]); + + t->m->processor->invokeArray(t, getMethod(t, m), *o, a); + + return 0; +} + +void JNICALL CallVoidMethodA(Thread* t, jobject o, jmethodID m, const jvalue* a) +{ + uintptr_t arguments[] + = {reinterpret_cast(o), m, reinterpret_cast(a)}; + + run(t, callVoidMethodA, arguments); +} + +GcMethod* getStaticMethod(Thread* t, jmethodID m) +{ + assertT(t, m); + + GcMethod* method + = cast(t, roots(t)->jNIMethodTable()->body()[m - 1]); + + assertT(t, method->flags() & ACC_STATIC); + + return method; +} + +uint64_t callStaticObjectMethodV(Thread* t, uintptr_t* arguments) +{ + jmethodID m = arguments[0]; + va_list* a = reinterpret_cast(arguments[1]); + + return reinterpret_cast(makeLocalReference( + t, t->m->processor->invokeList(t, getStaticMethod(t, m), 0, true, *a))); +} + +jobject JNICALL + CallStaticObjectMethodV(Thread* t, jclass, jmethodID m, va_list a) +{ + uintptr_t arguments[] = {m, reinterpret_cast(VA_LIST(a))}; + + return reinterpret_cast(run(t, callStaticObjectMethodV, arguments)); +} + +jobject JNICALL CallStaticObjectMethod(Thread* t, jclass c, jmethodID m, ...) +{ + va_list a; + va_start(a, m); + + jobject r = CallStaticObjectMethodV(t, c, m, a); + + va_end(a); + + return r; +} + +uint64_t callStaticObjectMethodA(Thread* t, uintptr_t* arguments) +{ + jmethodID m = arguments[0]; + const jvalue* a = reinterpret_cast(arguments[1]); + + return reinterpret_cast(makeLocalReference( + t, t->m->processor->invokeArray(t, getStaticMethod(t, m), 0, a))); +} + +jobject JNICALL + CallStaticObjectMethodA(Thread* t, jclass, jmethodID m, const jvalue* a) +{ + uintptr_t arguments[] = {m, reinterpret_cast(a)}; + + return reinterpret_cast(run(t, callStaticObjectMethodA, arguments)); +} + +uint64_t callStaticIntMethodV(Thread* t, uintptr_t* arguments) +{ + jmethodID m = arguments[0]; + va_list* a = reinterpret_cast(arguments[1]); + + return cast(t, + t->m->processor->invokeList( + t, getStaticMethod(t, m), 0, true, *a))->value(); +} + +jboolean JNICALL + CallStaticBooleanMethodV(Thread* t, jclass, jmethodID m, va_list a) +{ + uintptr_t arguments[] = {m, reinterpret_cast(VA_LIST(a))}; + + return run(t, callStaticIntMethodV, arguments) != 0; +} + +jboolean JNICALL CallStaticBooleanMethod(Thread* t, jclass c, jmethodID m, ...) +{ + va_list a; + va_start(a, m); + + jboolean r = CallStaticBooleanMethodV(t, c, m, a); + + va_end(a); + + return r; +} + +uint64_t callStaticIntMethodA(Thread* t, uintptr_t* arguments) +{ + jmethodID m = arguments[0]; + const jvalue* a = reinterpret_cast(arguments[1]); + + return cast( + t, t->m->processor->invokeArray(t, getStaticMethod(t, m), 0, a)) + ->value(); +} + +jboolean JNICALL + CallStaticBooleanMethodA(Thread* t, jclass, jmethodID m, const jvalue* a) +{ + uintptr_t arguments[] = {m, reinterpret_cast(a)}; + + return run(t, callStaticIntMethodA, arguments) != 0; +} + +jbyte JNICALL CallStaticByteMethodV(Thread* t, jclass, jmethodID m, va_list a) +{ + uintptr_t arguments[] = {m, reinterpret_cast(VA_LIST(a))}; + + return run(t, callStaticIntMethodV, arguments); +} + +jbyte JNICALL CallStaticByteMethod(Thread* t, jclass c, jmethodID m, ...) +{ + va_list a; + va_start(a, m); + + jbyte r = CallStaticByteMethodV(t, c, m, a); + + va_end(a); + + return r; +} + +jbyte JNICALL + CallStaticByteMethodA(Thread* t, jclass, jmethodID m, const jvalue* a) +{ + uintptr_t arguments[] = {m, reinterpret_cast(a)}; + + return run(t, callStaticIntMethodA, arguments); +} + +jchar JNICALL CallStaticCharMethodV(Thread* t, jclass, jmethodID m, va_list a) +{ + uintptr_t arguments[] = {m, reinterpret_cast(VA_LIST(a))}; + + return run(t, callStaticIntMethodV, arguments); +} + +jchar JNICALL CallStaticCharMethod(Thread* t, jclass c, jmethodID m, ...) +{ + va_list a; + va_start(a, m); + + jchar r = CallStaticCharMethodV(t, c, m, a); + + va_end(a); + + return r; +} + +jchar JNICALL + CallStaticCharMethodA(Thread* t, jclass, jmethodID m, const jvalue* a) +{ + uintptr_t arguments[] = {m, reinterpret_cast(a)}; + + return run(t, callStaticIntMethodA, arguments); +} + +jshort JNICALL CallStaticShortMethodV(Thread* t, jclass, jmethodID m, va_list a) +{ + uintptr_t arguments[] = {m, reinterpret_cast(VA_LIST(a))}; + + return run(t, callStaticIntMethodV, arguments); +} + +jshort JNICALL CallStaticShortMethod(Thread* t, jclass c, jmethodID m, ...) +{ + va_list a; + va_start(a, m); + + jshort r = CallStaticShortMethodV(t, c, m, a); + + va_end(a); + + return r; +} + +jshort JNICALL + CallStaticShortMethodA(Thread* t, jclass, jmethodID m, const jvalue* a) +{ + uintptr_t arguments[] = {m, reinterpret_cast(a)}; + + return run(t, callStaticIntMethodA, arguments); +} + +jint JNICALL CallStaticIntMethodV(Thread* t, jclass, jmethodID m, va_list a) +{ + uintptr_t arguments[] = {m, reinterpret_cast(VA_LIST(a))}; + + return run(t, callStaticIntMethodV, arguments); +} + +jint JNICALL CallStaticIntMethod(Thread* t, jclass c, jmethodID m, ...) +{ + va_list a; + va_start(a, m); + + jint r = CallStaticIntMethodV(t, c, m, a); + + va_end(a); + + return r; +} + +jint JNICALL + CallStaticIntMethodA(Thread* t, jclass, jmethodID m, const jvalue* a) +{ + uintptr_t arguments[] = {m, reinterpret_cast(a)}; + + return run(t, callStaticIntMethodA, arguments); +} + +uint64_t callStaticLongMethodV(Thread* t, uintptr_t* arguments) +{ + jmethodID m = arguments[0]; + va_list* a = reinterpret_cast(arguments[1]); + + return cast(t, + t->m->processor->invokeList( + t, getStaticMethod(t, m), 0, true, *a))->value(); +} + +jlong JNICALL CallStaticLongMethodV(Thread* t, jclass, jmethodID m, va_list a) +{ + uintptr_t arguments[] = {m, reinterpret_cast(VA_LIST(a))}; + + return run(t, callStaticLongMethodV, arguments); +} + +jlong JNICALL CallStaticLongMethod(Thread* t, jclass c, jmethodID m, ...) +{ + va_list a; + va_start(a, m); + + jlong r = CallStaticLongMethodV(t, c, m, a); + + va_end(a); + + return r; +} + +uint64_t callStaticLongMethodA(Thread* t, uintptr_t* arguments) +{ + jmethodID m = arguments[0]; + const jvalue* a = reinterpret_cast(arguments[1]); + + return cast( + t, t->m->processor->invokeArray(t, getStaticMethod(t, m), 0, a)) + ->value(); +} + +jlong JNICALL + CallStaticLongMethodA(Thread* t, jclass, jmethodID m, const jvalue* a) +{ + uintptr_t arguments[] = {m, reinterpret_cast(a)}; + + return run(t, callStaticLongMethodA, arguments); +} + +jfloat JNICALL CallStaticFloatMethodV(Thread* t, jclass, jmethodID m, va_list a) +{ + uintptr_t arguments[] = {m, reinterpret_cast(VA_LIST(a))}; + + return bitsToFloat(run(t, callStaticIntMethodV, arguments)); +} + +jfloat JNICALL CallStaticFloatMethod(Thread* t, jclass c, jmethodID m, ...) +{ + va_list a; + va_start(a, m); + + jfloat r = CallStaticFloatMethodV(t, c, m, a); + + va_end(a); + + return r; +} + +jfloat JNICALL + CallStaticFloatMethodA(Thread* t, jclass, jmethodID m, const jvalue* a) +{ + uintptr_t arguments[] = {m, reinterpret_cast(a)}; + + return bitsToFloat(run(t, callStaticIntMethodA, arguments)); +} + +jdouble JNICALL + CallStaticDoubleMethodV(Thread* t, jclass, jmethodID m, va_list a) +{ + uintptr_t arguments[] = {m, reinterpret_cast(VA_LIST(a))}; + + return bitsToDouble(run(t, callStaticLongMethodV, arguments)); +} + +jdouble JNICALL CallStaticDoubleMethod(Thread* t, jclass c, jmethodID m, ...) +{ + va_list a; + va_start(a, m); + + jdouble r = CallStaticDoubleMethodV(t, c, m, a); + + va_end(a); + + return r; +} + +jdouble JNICALL + CallStaticDoubleMethodA(Thread* t, jclass, jmethodID m, const jvalue* a) +{ + uintptr_t arguments[] = {m, reinterpret_cast(a)}; + + return bitsToDouble(run(t, callStaticLongMethodA, arguments)); +} + +uint64_t callStaticVoidMethodV(Thread* t, uintptr_t* arguments) +{ + jmethodID m = arguments[0]; + va_list* a = reinterpret_cast(arguments[1]); + + t->m->processor->invokeList(t, getStaticMethod(t, m), 0, true, *a); + + return 0; +} + +void JNICALL CallStaticVoidMethodV(Thread* t, jclass, jmethodID m, va_list a) +{ + uintptr_t arguments[] = {m, reinterpret_cast(VA_LIST(a))}; + + run(t, callStaticVoidMethodV, arguments); +} + +void JNICALL CallStaticVoidMethod(Thread* t, jclass c, jmethodID m, ...) +{ + va_list a; + va_start(a, m); + + CallStaticVoidMethodV(t, c, m, a); + + va_end(a); +} + +uint64_t callStaticVoidMethodA(Thread* t, uintptr_t* arguments) +{ + jmethodID m = arguments[0]; + const jvalue* a = reinterpret_cast(arguments[1]); + + t->m->processor->invokeArray(t, getStaticMethod(t, m), 0, a); + + return 0; +} + +void JNICALL + CallStaticVoidMethodA(Thread* t, jclass, jmethodID m, const jvalue* a) +{ + uintptr_t arguments[] = {m, reinterpret_cast(a)}; + + run(t, callStaticVoidMethodA, arguments); +} + +jint fieldID(Thread* t, GcField* field) +{ + int id = field->nativeID(); + + loadMemoryBarrier(); + + if (id == 0) { + PROTECT(t, field); + + ACQUIRE(t, t->m->referenceLock); + + if (field->nativeID() == 0) { + GcVector* v = vectorAppend(t, roots(t)->jNIFieldTable(), field); + // sequence point, for gc (don't recombine statements) + roots(t)->setJNIFieldTable(t, v); + + storeStoreMemoryBarrier(); + + field->nativeID() = roots(t)->jNIFieldTable()->size(); + } + } + + return field->nativeID(); +} + +uint64_t getFieldID(Thread* t, uintptr_t* arguments) +{ + jclass c = reinterpret_cast(arguments[0]); + const char* name = reinterpret_cast(arguments[1]); + const char* spec = reinterpret_cast(arguments[2]); + + return fieldID(t, resolveField(t, (*c)->vmClass(), name, spec)); +} + +jfieldID JNICALL + GetFieldID(Thread* t, jclass c, const char* name, const char* spec) +{ + uintptr_t arguments[] = {reinterpret_cast(c), + reinterpret_cast(name), + reinterpret_cast(spec)}; + + return run(t, getFieldID, arguments); +} + +jfieldID JNICALL + GetStaticFieldID(Thread* t, jclass c, const char* name, const char* spec) +{ + uintptr_t arguments[] = {reinterpret_cast(c), + reinterpret_cast(name), + reinterpret_cast(spec)}; + + return run(t, getFieldID, arguments); +} + +GcField* getField(Thread* t, jfieldID f) +{ + assertT(t, f); + + GcField* field = cast(t, roots(t)->jNIFieldTable()->body()[f - 1]); + + assertT(t, (field->flags() & ACC_STATIC) == 0); + + return field; +} + +uint64_t getObjectField(Thread* t, uintptr_t* arguments) +{ + jobject o = reinterpret_cast(arguments[0]); + GcField* field = getField(t, arguments[1]); + + PROTECT(t, field); + ACQUIRE_FIELD_FOR_READ(t, field); + + return reinterpret_cast( + makeLocalReference(t, fieldAtOffset(*o, field->offset()))); +} + +jobject JNICALL GetObjectField(Thread* t, jobject o, jfieldID field) +{ + uintptr_t arguments[] = {reinterpret_cast(o), field}; + + return reinterpret_cast(run(t, getObjectField, arguments)); +} + +uint64_t getBooleanField(Thread* t, uintptr_t* arguments) +{ + jobject o = reinterpret_cast(arguments[0]); + GcField* field = getField(t, arguments[1]); + + PROTECT(t, field); + ACQUIRE_FIELD_FOR_READ(t, field); + + return fieldAtOffset(*o, field->offset()); +} + +jboolean JNICALL GetBooleanField(Thread* t, jobject o, jfieldID field) +{ + uintptr_t arguments[] = {reinterpret_cast(o), field}; + + return run(t, getBooleanField, arguments); +} + +uint64_t getByteField(Thread* t, uintptr_t* arguments) +{ + jobject o = reinterpret_cast(arguments[0]); + GcField* field = getField(t, arguments[1]); + + PROTECT(t, field); + ACQUIRE_FIELD_FOR_READ(t, field); + + return fieldAtOffset(*o, field->offset()); +} + +jbyte JNICALL GetByteField(Thread* t, jobject o, jfieldID field) +{ + uintptr_t arguments[] = {reinterpret_cast(o), field}; + + return run(t, getByteField, arguments); +} + +uint64_t getCharField(Thread* t, uintptr_t* arguments) +{ + jobject o = reinterpret_cast(arguments[0]); + GcField* field = getField(t, arguments[1]); + + PROTECT(t, field); + ACQUIRE_FIELD_FOR_READ(t, field); + + return fieldAtOffset(*o, field->offset()); +} + +jchar JNICALL GetCharField(Thread* t, jobject o, jfieldID field) +{ + uintptr_t arguments[] = {reinterpret_cast(o), field}; + + return run(t, getCharField, arguments); +} + +uint64_t getShortField(Thread* t, uintptr_t* arguments) +{ + jobject o = reinterpret_cast(arguments[0]); + GcField* field = getField(t, arguments[1]); + + PROTECT(t, field); + ACQUIRE_FIELD_FOR_READ(t, field); + + return fieldAtOffset(*o, field->offset()); +} + +jshort JNICALL GetShortField(Thread* t, jobject o, jfieldID field) +{ + uintptr_t arguments[] = {reinterpret_cast(o), field}; + + return run(t, getShortField, arguments); +} + +uint64_t getIntField(Thread* t, uintptr_t* arguments) +{ + jobject o = reinterpret_cast(arguments[0]); + GcField* field = getField(t, arguments[1]); + + PROTECT(t, field); + ACQUIRE_FIELD_FOR_READ(t, field); + + return fieldAtOffset(*o, field->offset()); +} + +jint JNICALL GetIntField(Thread* t, jobject o, jfieldID field) +{ + uintptr_t arguments[] = {reinterpret_cast(o), field}; + + return run(t, getIntField, arguments); +} + +uint64_t getLongField(Thread* t, uintptr_t* arguments) +{ + jobject o = reinterpret_cast(arguments[0]); + GcField* field = getField(t, arguments[1]); + + PROTECT(t, field); + ACQUIRE_FIELD_FOR_READ(t, field); + + return fieldAtOffset(*o, field->offset()); +} + +jlong JNICALL GetLongField(Thread* t, jobject o, jfieldID field) +{ + uintptr_t arguments[] = {reinterpret_cast(o), field}; + + return run(t, getLongField, arguments); +} + +uint64_t getFloatField(Thread* t, uintptr_t* arguments) +{ + jobject o = reinterpret_cast(arguments[0]); + GcField* field = getField(t, arguments[1]); + + PROTECT(t, field); + ACQUIRE_FIELD_FOR_READ(t, field); + + return floatToBits(fieldAtOffset(*o, field->offset())); +} + +jfloat JNICALL GetFloatField(Thread* t, jobject o, jfieldID field) +{ + uintptr_t arguments[] = {reinterpret_cast(o), field}; + + return bitsToFloat(run(t, getFloatField, arguments)); +} + +uint64_t getDoubleField(Thread* t, uintptr_t* arguments) +{ + jobject o = reinterpret_cast(arguments[0]); + GcField* field = getField(t, arguments[1]); + + PROTECT(t, field); + ACQUIRE_FIELD_FOR_READ(t, field); + + return doubleToBits(fieldAtOffset(*o, field->offset())); +} + +jdouble JNICALL GetDoubleField(Thread* t, jobject o, jfieldID field) +{ + uintptr_t arguments[] = {reinterpret_cast(o), field}; + + return bitsToDouble(run(t, getDoubleField, arguments)); +} + +uint64_t setObjectField(Thread* t, uintptr_t* arguments) +{ + jobject o = reinterpret_cast(arguments[0]); + GcField* field = getField(t, arguments[1]); + jobject v = reinterpret_cast(arguments[2]); + + PROTECT(t, field); + ACQUIRE_FIELD_FOR_WRITE(t, field); + + setField(t, *o, field->offset(), (v ? *v : 0)); + + return 1; +} + +void JNICALL SetObjectField(Thread* t, jobject o, jfieldID field, jobject v) +{ + uintptr_t arguments[] + = {reinterpret_cast(o), field, reinterpret_cast(v)}; + + run(t, setObjectField, arguments); +} + +uint64_t setBooleanField(Thread* t, uintptr_t* arguments) +{ + jobject o = reinterpret_cast(arguments[0]); + GcField* field = getField(t, arguments[1]); + jboolean v = arguments[2]; + + PROTECT(t, field); + ACQUIRE_FIELD_FOR_WRITE(t, field); + + fieldAtOffset(*o, field->offset()) = v; + + return 1; +} + +void JNICALL SetBooleanField(Thread* t, jobject o, jfieldID field, jboolean v) +{ + uintptr_t arguments[] = {reinterpret_cast(o), field, v}; + + run(t, setBooleanField, arguments); +} + +uint64_t setByteField(Thread* t, uintptr_t* arguments) +{ + jobject o = reinterpret_cast(arguments[0]); + GcField* field = getField(t, arguments[1]); + jbyte v = arguments[2]; + + PROTECT(t, field); + ACQUIRE_FIELD_FOR_WRITE(t, field); + + fieldAtOffset(*o, field->offset()) = v; + + return 1; +} + +void JNICALL SetByteField(Thread* t, jobject o, jfieldID field, jbyte v) +{ + uintptr_t arguments[] + = {reinterpret_cast(o), field, static_cast(v)}; + + run(t, setByteField, arguments); +} + +uint64_t setCharField(Thread* t, uintptr_t* arguments) +{ + jobject o = reinterpret_cast(arguments[0]); + GcField* field = getField(t, arguments[1]); + jchar v = arguments[2]; + + PROTECT(t, field); + ACQUIRE_FIELD_FOR_WRITE(t, field); + + fieldAtOffset(*o, field->offset()) = v; + + return 1; +} + +void JNICALL SetCharField(Thread* t, jobject o, jfieldID field, jchar v) +{ + uintptr_t arguments[] = {reinterpret_cast(o), field, v}; + + run(t, setCharField, arguments); +} + +uint64_t setShortField(Thread* t, uintptr_t* arguments) +{ + jobject o = reinterpret_cast(arguments[0]); + GcField* field = getField(t, arguments[1]); + jshort v = arguments[2]; + + PROTECT(t, field); + ACQUIRE_FIELD_FOR_WRITE(t, field); + + fieldAtOffset(*o, field->offset()) = v; + + return 1; +} + +void JNICALL SetShortField(Thread* t, jobject o, jfieldID field, jshort v) +{ + uintptr_t arguments[] + = {reinterpret_cast(o), field, static_cast(v)}; + + run(t, setShortField, arguments); +} + +uint64_t setIntField(Thread* t, uintptr_t* arguments) +{ + jobject o = reinterpret_cast(arguments[0]); + GcField* field = getField(t, arguments[1]); + jint v = arguments[2]; + + PROTECT(t, field); + ACQUIRE_FIELD_FOR_WRITE(t, field); + + fieldAtOffset(*o, field->offset()) = v; + + return 1; +} + +void JNICALL SetIntField(Thread* t, jobject o, jfieldID field, jint v) +{ + uintptr_t arguments[] + = {reinterpret_cast(o), field, static_cast(v)}; + + run(t, setIntField, arguments); +} + +uint64_t setLongField(Thread* t, uintptr_t* arguments) +{ + jobject o = reinterpret_cast(arguments[0]); + GcField* field = getField(t, arguments[1]); + jlong v; + memcpy(&v, arguments + 2, sizeof(jlong)); + + PROTECT(t, field); + ACQUIRE_FIELD_FOR_WRITE(t, field); + + fieldAtOffset(*o, field->offset()) = v; + + return 1; +} + +void JNICALL SetLongField(Thread* t, jobject o, jfieldID field, jlong v) +{ + uintptr_t arguments[2 + (sizeof(jlong) / BytesPerWord)]; + arguments[0] = reinterpret_cast(o); + arguments[1] = field; + memcpy(arguments + 2, &v, sizeof(jlong)); + + run(t, setLongField, arguments); +} + +uint64_t setFloatField(Thread* t, uintptr_t* arguments) +{ + jobject o = reinterpret_cast(arguments[0]); + GcField* field = getField(t, arguments[1]); + jfloat v = bitsToFloat(arguments[2]); + + PROTECT(t, field); + ACQUIRE_FIELD_FOR_WRITE(t, field); + + fieldAtOffset(*o, field->offset()) = v; + + return 1; +} + +void JNICALL SetFloatField(Thread* t, jobject o, jfieldID field, jfloat v) +{ + uintptr_t arguments[] + = {reinterpret_cast(o), field, floatToBits(v)}; + + run(t, setFloatField, arguments); +} + +uint64_t setDoubleField(Thread* t, uintptr_t* arguments) +{ + jobject o = reinterpret_cast(arguments[0]); + GcField* field = getField(t, arguments[1]); + jdouble v; + memcpy(&v, arguments + 2, sizeof(jdouble)); + + PROTECT(t, field); + ACQUIRE_FIELD_FOR_WRITE(t, field); + + fieldAtOffset(*o, field->offset()) = v; + + return 1; +} + +void JNICALL SetDoubleField(Thread* t, jobject o, jfieldID field, jdouble v) +{ + uintptr_t arguments[2 + (sizeof(jdouble) / BytesPerWord)]; + arguments[0] = reinterpret_cast(o); + arguments[1] = field; + memcpy(arguments + 2, &v, sizeof(jdouble)); + + run(t, setDoubleField, arguments); +} + +GcField* getStaticField(Thread* t, jfieldID f) +{ + assertT(t, f); + + GcField* field = cast(t, roots(t)->jNIFieldTable()->body()[f - 1]); + + assertT(t, field->flags() & ACC_STATIC); + + return field; +} + +uint64_t getStaticObjectField(Thread* t, uintptr_t* arguments) +{ + GcJclass* c = cast(t, *reinterpret_cast(arguments[0])); + + initClass(t, c->vmClass()); + + GcField* field = getStaticField(t, arguments[1]); + + PROTECT(t, field); + ACQUIRE_FIELD_FOR_READ(t, field); + + return reinterpret_cast(makeLocalReference( + t, fieldAtOffset(c->vmClass()->staticTable(), field->offset()))); +} + +jobject JNICALL GetStaticObjectField(Thread* t, jclass c, jfieldID field) +{ + uintptr_t arguments[] = {reinterpret_cast(c), field}; + + return reinterpret_cast(run(t, getStaticObjectField, arguments)); +} + +uint64_t getStaticBooleanField(Thread* t, uintptr_t* arguments) +{ + GcJclass* c = cast(t, *reinterpret_cast(arguments[0])); + + initClass(t, c->vmClass()); + + GcField* field = getStaticField(t, arguments[1]); + + PROTECT(t, field); + ACQUIRE_FIELD_FOR_READ(t, field); + + return fieldAtOffset(c->vmClass()->staticTable(), field->offset()); +} + +jboolean JNICALL GetStaticBooleanField(Thread* t, jclass c, jfieldID field) +{ + uintptr_t arguments[] = {reinterpret_cast(c), field}; + + return run(t, getStaticBooleanField, arguments); +} + +uint64_t getStaticByteField(Thread* t, uintptr_t* arguments) +{ + GcJclass* c = cast(t, *reinterpret_cast(arguments[0])); + + initClass(t, c->vmClass()); + + GcField* field = getStaticField(t, arguments[1]); + + PROTECT(t, field); + ACQUIRE_FIELD_FOR_READ(t, field); + + return fieldAtOffset(c->vmClass()->staticTable(), field->offset()); +} + +jbyte JNICALL GetStaticByteField(Thread* t, jclass c, jfieldID field) +{ + uintptr_t arguments[] = {reinterpret_cast(c), field}; + + return run(t, getStaticByteField, arguments); +} + +uint64_t getStaticCharField(Thread* t, uintptr_t* arguments) +{ + GcJclass* c = cast(t, *reinterpret_cast(arguments[0])); + + initClass(t, c->vmClass()); + + GcField* field = getStaticField(t, arguments[1]); + + PROTECT(t, field); + ACQUIRE_FIELD_FOR_READ(t, field); + + return fieldAtOffset(c->vmClass()->staticTable(), field->offset()); +} + +jchar JNICALL GetStaticCharField(Thread* t, jclass c, jfieldID field) +{ + uintptr_t arguments[] = {reinterpret_cast(c), field}; + + return run(t, getStaticCharField, arguments); +} + +uint64_t getStaticShortField(Thread* t, uintptr_t* arguments) +{ + GcJclass* c = cast(t, *reinterpret_cast(arguments[0])); + + initClass(t, c->vmClass()); + + GcField* field = getStaticField(t, arguments[1]); + + PROTECT(t, field); + ACQUIRE_FIELD_FOR_READ(t, field); + + return fieldAtOffset(c->vmClass()->staticTable(), field->offset()); +} + +jshort JNICALL GetStaticShortField(Thread* t, jclass c, jfieldID field) +{ + uintptr_t arguments[] = {reinterpret_cast(c), field}; + + return run(t, getStaticShortField, arguments); +} + +uint64_t getStaticIntField(Thread* t, uintptr_t* arguments) +{ + GcJclass* c = cast(t, *reinterpret_cast(arguments[0])); + + initClass(t, c->vmClass()); + + GcField* field = getStaticField(t, arguments[1]); + + PROTECT(t, field); + ACQUIRE_FIELD_FOR_READ(t, field); + + return fieldAtOffset(c->vmClass()->staticTable(), field->offset()); +} + +jint JNICALL GetStaticIntField(Thread* t, jclass c, jfieldID field) +{ + uintptr_t arguments[] = {reinterpret_cast(c), field}; + + return run(t, getStaticIntField, arguments); +} + +uint64_t getStaticLongField(Thread* t, uintptr_t* arguments) +{ + GcJclass* c = cast(t, *reinterpret_cast(arguments[0])); + + initClass(t, c->vmClass()); + + GcField* field = getStaticField(t, arguments[1]); + + PROTECT(t, field); + ACQUIRE_FIELD_FOR_READ(t, field); + + return fieldAtOffset(c->vmClass()->staticTable(), field->offset()); +} + +jlong JNICALL GetStaticLongField(Thread* t, jclass c, jfieldID field) +{ + uintptr_t arguments[] = {reinterpret_cast(c), field}; + + return run(t, getStaticLongField, arguments); +} + +uint64_t getStaticFloatField(Thread* t, uintptr_t* arguments) +{ + GcJclass* c = cast(t, *reinterpret_cast(arguments[0])); + + initClass(t, c->vmClass()); + + GcField* field = getStaticField(t, arguments[1]); + + PROTECT(t, field); + ACQUIRE_FIELD_FOR_READ(t, field); + + return floatToBits( + fieldAtOffset(c->vmClass()->staticTable(), field->offset())); +} + +jfloat JNICALL GetStaticFloatField(Thread* t, jclass c, jfieldID field) +{ + uintptr_t arguments[] = {reinterpret_cast(c), field}; + + return bitsToFloat(run(t, getStaticFloatField, arguments)); +} + +uint64_t getStaticDoubleField(Thread* t, uintptr_t* arguments) +{ + GcJclass* c = cast(t, *reinterpret_cast(arguments[0])); + + initClass(t, c->vmClass()); + + GcField* field = getStaticField(t, arguments[1]); + + PROTECT(t, field); + ACQUIRE_FIELD_FOR_READ(t, field); + + return doubleToBits( + fieldAtOffset(c->vmClass()->staticTable(), field->offset())); +} + +jdouble JNICALL GetStaticDoubleField(Thread* t, jclass c, jfieldID field) +{ + uintptr_t arguments[] = {reinterpret_cast(c), field}; + + return bitsToDouble(run(t, getStaticDoubleField, arguments)); +} + +uint64_t setStaticObjectField(Thread* t, uintptr_t* arguments) +{ + GcJclass* c = cast(t, *reinterpret_cast(arguments[0])); + + initClass(t, c->vmClass()); + + GcField* field = getStaticField(t, arguments[1]); + jobject v = reinterpret_cast(arguments[2]); + + PROTECT(t, field); + ACQUIRE_FIELD_FOR_WRITE(t, field); + + setField(t, c->vmClass()->staticTable(), field->offset(), (v ? *v : 0)); + + return 1; +} + +void JNICALL + SetStaticObjectField(Thread* t, jclass c, jfieldID field, jobject v) +{ + uintptr_t arguments[] + = {reinterpret_cast(c), field, reinterpret_cast(v)}; + + run(t, setStaticObjectField, arguments); +} + +uint64_t setStaticBooleanField(Thread* t, uintptr_t* arguments) +{ + GcJclass* c = cast(t, *reinterpret_cast(arguments[0])); + + initClass(t, c->vmClass()); + + GcField* field = getStaticField(t, arguments[1]); + jboolean v = arguments[2]; + + PROTECT(t, field); + ACQUIRE_FIELD_FOR_WRITE(t, field); + + fieldAtOffset(c->vmClass()->staticTable(), field->offset()) = v; + + return 1; +} + +void JNICALL + SetStaticBooleanField(Thread* t, jclass c, jfieldID field, jboolean v) +{ + uintptr_t arguments[] = {reinterpret_cast(c), field, v}; + + run(t, setStaticBooleanField, arguments); +} + +uint64_t setStaticByteField(Thread* t, uintptr_t* arguments) +{ + GcJclass* c = cast(t, *reinterpret_cast(arguments[0])); + + initClass(t, c->vmClass()); + + GcField* field = getStaticField(t, arguments[1]); + jbyte v = arguments[2]; + + PROTECT(t, field); + ACQUIRE_FIELD_FOR_WRITE(t, field); + + fieldAtOffset(c->vmClass()->staticTable(), field->offset()) = v; + + return 1; +} + +void JNICALL SetStaticByteField(Thread* t, jclass c, jfieldID field, jbyte v) +{ + uintptr_t arguments[] + = {reinterpret_cast(c), field, static_cast(v)}; + + run(t, setStaticByteField, arguments); +} + +uint64_t setStaticCharField(Thread* t, uintptr_t* arguments) +{ + GcJclass* c = cast(t, *reinterpret_cast(arguments[0])); + + initClass(t, c->vmClass()); + + GcField* field = getStaticField(t, arguments[1]); + jchar v = arguments[2]; + + PROTECT(t, field); + ACQUIRE_FIELD_FOR_WRITE(t, field); + + fieldAtOffset(c->vmClass()->staticTable(), field->offset()) = v; + + return 1; +} + +void JNICALL SetStaticCharField(Thread* t, jclass c, jfieldID field, jchar v) +{ + uintptr_t arguments[] = {reinterpret_cast(c), field, v}; + + run(t, setStaticCharField, arguments); +} + +uint64_t setStaticShortField(Thread* t, uintptr_t* arguments) +{ + GcJclass* c = cast(t, *reinterpret_cast(arguments[0])); + + initClass(t, c->vmClass()); + + GcField* field = getStaticField(t, arguments[1]); + jshort v = arguments[2]; + + PROTECT(t, field); + ACQUIRE_FIELD_FOR_WRITE(t, field); + + fieldAtOffset(c->vmClass()->staticTable(), field->offset()) = v; + + return 1; +} + +void JNICALL SetStaticShortField(Thread* t, jclass c, jfieldID field, jshort v) +{ + uintptr_t arguments[] + = {reinterpret_cast(c), field, static_cast(v)}; + + run(t, setStaticShortField, arguments); +} + +uint64_t setStaticIntField(Thread* t, uintptr_t* arguments) +{ + GcJclass* c = cast(t, *reinterpret_cast(arguments[0])); + + initClass(t, c->vmClass()); + + GcField* field = getStaticField(t, arguments[1]); + jint v = arguments[2]; + + PROTECT(t, field); + ACQUIRE_FIELD_FOR_WRITE(t, field); + + fieldAtOffset(c->vmClass()->staticTable(), field->offset()) = v; + + return 1; +} + +void JNICALL SetStaticIntField(Thread* t, jclass c, jfieldID field, jint v) +{ + uintptr_t arguments[] + = {reinterpret_cast(c), field, static_cast(v)}; + + run(t, setStaticIntField, arguments); +} + +uint64_t setStaticLongField(Thread* t, uintptr_t* arguments) +{ + GcJclass* c = cast(t, *reinterpret_cast(arguments[0])); + + initClass(t, c->vmClass()); + + GcField* field = getStaticField(t, arguments[1]); + jlong v; + memcpy(&v, arguments + 2, sizeof(jlong)); + + PROTECT(t, field); + ACQUIRE_FIELD_FOR_WRITE(t, field); + + fieldAtOffset(c->vmClass()->staticTable(), field->offset()) = v; + + return 1; +} + +void JNICALL SetStaticLongField(Thread* t, jclass c, jfieldID field, jlong v) +{ + uintptr_t arguments[2 + (sizeof(jlong) / BytesPerWord)]; + arguments[0] = reinterpret_cast(c); + arguments[1] = field; + memcpy(arguments + 2, &v, sizeof(jlong)); + + run(t, setStaticLongField, arguments); +} + +uint64_t setStaticFloatField(Thread* t, uintptr_t* arguments) +{ + GcJclass* c = cast(t, *reinterpret_cast(arguments[0])); + + initClass(t, c->vmClass()); + + GcField* field = getStaticField(t, arguments[1]); + jfloat v = bitsToFloat(arguments[2]); + + PROTECT(t, field); + ACQUIRE_FIELD_FOR_WRITE(t, field); + + fieldAtOffset(c->vmClass()->staticTable(), field->offset()) = v; + + return 1; +} + +void JNICALL SetStaticFloatField(Thread* t, jclass c, jfieldID field, jfloat v) +{ + uintptr_t arguments[] + = {reinterpret_cast(c), field, floatToBits(v)}; + + run(t, setStaticFloatField, arguments); +} + +uint64_t setStaticDoubleField(Thread* t, uintptr_t* arguments) +{ + GcJclass* c = cast(t, *reinterpret_cast(arguments[0])); + + initClass(t, c->vmClass()); + + GcField* field = getStaticField(t, arguments[1]); + jdouble v; + memcpy(&v, arguments + 2, sizeof(jdouble)); + + PROTECT(t, field); + ACQUIRE_FIELD_FOR_WRITE(t, field); + + fieldAtOffset(c->vmClass()->staticTable(), field->offset()) = v; + + return 1; +} + +void JNICALL + SetStaticDoubleField(Thread* t, jclass c, jfieldID field, jdouble v) +{ + uintptr_t arguments[2 + (sizeof(jdouble) / BytesPerWord)]; + arguments[0] = reinterpret_cast(c); + arguments[1] = field; + memcpy(arguments + 2, &v, sizeof(jdouble)); + + run(t, setStaticDoubleField, arguments); +} + +jobject JNICALL newGlobalRef(Thread* t, jobject o, bool weak) +{ + ENTER(t, Thread::ActiveState); + + ACQUIRE(t, t->m->referenceLock); + + if (o) { + for (Reference* r = t->m->jniReferences; r; r = r->next) { + if (r->target == *o and r->weak == weak) { + acquire(t, r); + + return &(r->target); + } + } + + Reference* r = new (t->m->heap->allocate(sizeof(Reference))) + Reference(*o, &(t->m->jniReferences), weak); + + acquire(t, r); + + return &(r->target); + } else { + return 0; + } +} + +jobject JNICALL NewGlobalRef(Thread* t, jobject o) +{ + return newGlobalRef(t, o, false); +} + +void JNICALL DeleteGlobalRef(Thread* t, jobject r) +{ + ENTER(t, Thread::ActiveState); + + ACQUIRE(t, t->m->referenceLock); + + if (r) { + release(t, reinterpret_cast(r)); + } +} + +jobject JNICALL NewWeakGlobalRef(Thread* t, jobject o) +{ + return newGlobalRef(t, o, true); +} + +void JNICALL DeleteWeakGlobalRef(Thread* t, jobject r) +{ + DeleteGlobalRef(t, r); +} + +jint JNICALL EnsureLocalCapacity(Thread*, jint) +{ + return 0; +} + +jthrowable JNICALL ExceptionOccurred(Thread* t) +{ + ENTER(t, Thread::ActiveState); + + return reinterpret_cast(makeLocalReference(t, t->exception)); +} + +void JNICALL ExceptionDescribe(Thread* t) +{ + ENTER(t, Thread::ActiveState); + + return printTrace(t, t->exception); +} + +void JNICALL ExceptionClear(Thread* t) +{ + ENTER(t, Thread::ActiveState); + + t->exception = 0; +} + +uint64_t newObjectArray(Thread* t, uintptr_t* arguments) +{ + jsize length = arguments[0]; + jclass class_ = reinterpret_cast(arguments[1]); + jobject init = reinterpret_cast(arguments[2]); + + object a = makeObjectArray(t, (*class_)->vmClass(), length); + object value = (init ? *init : 0); + for (jsize i = 0; i < length; ++i) { + reinterpret_cast(a)->setBodyElement(t, i, value); + } + return reinterpret_cast(makeLocalReference(t, a)); +} + +jobjectArray JNICALL + NewObjectArray(Thread* t, jsize length, jclass class_, jobject init) +{ + uintptr_t arguments[] = {static_cast(length), + reinterpret_cast(class_), + reinterpret_cast(init)}; + + return reinterpret_cast(run(t, newObjectArray, arguments)); +} + +jobject JNICALL + GetObjectArrayElement(Thread* t, jobjectArray array, jsize index) +{ + ENTER(t, Thread::ActiveState); + + return makeLocalReference( + t, objectArrayBody(t, reinterpret_cast(*array), index)); +} + +void JNICALL SetObjectArrayElement(Thread* t, + jobjectArray array, + jsize index, + jobject value) +{ + ENTER(t, Thread::ActiveState); + + setField(t, + reinterpret_cast(*array), + ArrayBody + (index * BytesPerWord), + (value ? *value : 0)); +} + +uint64_t newArray(Thread* t, uintptr_t* arguments) +{ + object (*constructor)(Thread*, unsigned) + = reinterpret_cast(arguments[0]); + + jsize length = arguments[1]; + + return reinterpret_cast( + makeLocalReference(t, constructor(t, length))); +} + +jbooleanArray JNICALL NewBooleanArray(Thread* t, jsize length) +{ + uintptr_t arguments[] + = {reinterpret_cast(voidPointer(makeBooleanArray)), + static_cast(length)}; + + return reinterpret_cast(run(t, newArray, arguments)); +} + +object makeByteArray0(Thread* t, unsigned length) +{ + return makeByteArray(t, length); +} + +jbyteArray JNICALL NewByteArray(Thread* t, jsize length) +{ + uintptr_t arguments[] + = {reinterpret_cast(voidPointer(makeByteArray0)), + static_cast(length)}; + + return reinterpret_cast(run(t, newArray, arguments)); +} + +jcharArray JNICALL NewCharArray(Thread* t, jsize length) +{ + uintptr_t arguments[] + = {reinterpret_cast(voidPointer(makeCharArray)), + static_cast(length)}; + + return reinterpret_cast(run(t, newArray, arguments)); +} + +jshortArray JNICALL NewShortArray(Thread* t, jsize length) +{ + uintptr_t arguments[] + = {reinterpret_cast(voidPointer(makeShortArray)), + static_cast(length)}; + + return reinterpret_cast(run(t, newArray, arguments)); +} + +jintArray JNICALL NewIntArray(Thread* t, jsize length) +{ + uintptr_t arguments[] + = {reinterpret_cast(voidPointer(makeIntArray)), + static_cast(length)}; + + return reinterpret_cast(run(t, newArray, arguments)); +} + +jlongArray JNICALL NewLongArray(Thread* t, jsize length) +{ + uintptr_t arguments[] + = {reinterpret_cast(voidPointer(makeLongArray)), + static_cast(length)}; + + return reinterpret_cast(run(t, newArray, arguments)); +} + +jfloatArray JNICALL NewFloatArray(Thread* t, jsize length) +{ + uintptr_t arguments[] + = {reinterpret_cast(voidPointer(makeFloatArray)), + static_cast(length)}; + + return reinterpret_cast(run(t, newArray, arguments)); +} + +jdoubleArray JNICALL NewDoubleArray(Thread* t, jsize length) +{ + uintptr_t arguments[] + = {reinterpret_cast(voidPointer(makeDoubleArray)), + static_cast(length)}; + + return reinterpret_cast(run(t, newArray, arguments)); +} + +jboolean* JNICALL + GetBooleanArrayElements(Thread* t, jbooleanArray array, jboolean* isCopy) +{ + ENTER(t, Thread::ActiveState); + + unsigned size = (*array)->length() * sizeof(jboolean); + jboolean* p = static_cast(t->m->heap->allocate(size)); + if (size) { + memcpy(p, (*array)->body().begin(), size); + } + + if (isCopy) { + *isCopy = true; + } + + return p; +} + +jbyte* JNICALL + GetByteArrayElements(Thread* t, jbyteArray array, jboolean* isCopy) +{ + ENTER(t, Thread::ActiveState); + + unsigned size = (*array)->length() * sizeof(jbyte); + jbyte* p = static_cast(t->m->heap->allocate(size)); + if (size) { + memcpy(p, (*array)->body().begin(), size); + } + + if (isCopy) { + *isCopy = true; + } + + return p; +} + +jchar* JNICALL + GetCharArrayElements(Thread* t, jcharArray array, jboolean* isCopy) +{ + ENTER(t, Thread::ActiveState); + + unsigned size = (*array)->length() * sizeof(jchar); + jchar* p = static_cast(t->m->heap->allocate(size)); + if (size) { + memcpy(p, (*array)->body().begin(), size); + } + + if (isCopy) { + *isCopy = true; + } + + return p; +} + +jshort* JNICALL + GetShortArrayElements(Thread* t, jshortArray array, jboolean* isCopy) +{ + ENTER(t, Thread::ActiveState); + + unsigned size = (*array)->length() * sizeof(jshort); + jshort* p = static_cast(t->m->heap->allocate(size)); + if (size) { + memcpy(p, (*array)->body().begin(), size); + } + + if (isCopy) { + *isCopy = true; + } + + return p; +} + +jint* JNICALL GetIntArrayElements(Thread* t, jintArray array, jboolean* isCopy) +{ + ENTER(t, Thread::ActiveState); + + unsigned size = (*array)->length() * sizeof(jint); + jint* p = static_cast(t->m->heap->allocate(size)); + if (size) { + memcpy(p, (*array)->body().begin(), size); + } + + if (isCopy) { + *isCopy = true; + } + + return p; +} + +jlong* JNICALL + GetLongArrayElements(Thread* t, jlongArray array, jboolean* isCopy) +{ + ENTER(t, Thread::ActiveState); + + unsigned size = (*array)->length() * sizeof(jlong); + jlong* p = static_cast(t->m->heap->allocate(size)); + if (size) { + memcpy(p, (*array)->body().begin(), size); + } + + if (isCopy) { + *isCopy = true; + } + + return p; +} + +jfloat* JNICALL + GetFloatArrayElements(Thread* t, jfloatArray array, jboolean* isCopy) +{ + ENTER(t, Thread::ActiveState); + + unsigned size = (*array)->length() * sizeof(jfloat); + jfloat* p = static_cast(t->m->heap->allocate(size)); + if (size) { + memcpy(p, (*array)->body().begin(), size); + } + + if (isCopy) { + *isCopy = true; + } + + return p; +} + +jdouble* JNICALL + GetDoubleArrayElements(Thread* t, jdoubleArray array, jboolean* isCopy) +{ + ENTER(t, Thread::ActiveState); + + unsigned size = (*array)->length() * sizeof(jdouble); + jdouble* p = static_cast(t->m->heap->allocate(size)); + if (size) { + memcpy(p, (*array)->body().begin(), size); + } + + if (isCopy) { + *isCopy = true; + } + + return p; +} + +void JNICALL ReleaseBooleanArrayElements(Thread* t, + jbooleanArray array, + jboolean* p, + jint mode) +{ + ENTER(t, Thread::ActiveState); + + unsigned size = (*array)->length() * sizeof(jboolean); + + if (mode == 0 or mode == AVIAN_JNI_COMMIT) { + if (size) { + memcpy((*array)->body().begin(), p, size); + } + } + + if (mode == 0 or mode == AVIAN_JNI_ABORT) { + t->m->heap->free(p, size); + } +} + +void JNICALL + ReleaseByteArrayElements(Thread* t, jbyteArray array, jbyte* p, jint mode) +{ + ENTER(t, Thread::ActiveState); + + unsigned size = (*array)->length() * sizeof(jbyte); + + if (mode == 0 or mode == AVIAN_JNI_COMMIT) { + if (size) { + memcpy((*array)->body().begin(), p, size); + } + } + + if (mode == 0 or mode == AVIAN_JNI_ABORT) { + t->m->heap->free(p, size); + } +} + +void JNICALL + ReleaseCharArrayElements(Thread* t, jcharArray array, jchar* p, jint mode) +{ + ENTER(t, Thread::ActiveState); + + unsigned size = (*array)->length() * sizeof(jchar); + + if (mode == 0 or mode == AVIAN_JNI_COMMIT) { + if (size) { + memcpy((*array)->body().begin(), p, size); + } + } + + if (mode == 0 or mode == AVIAN_JNI_ABORT) { + t->m->heap->free(p, size); + } +} + +void JNICALL ReleaseShortArrayElements(Thread* t, + jshortArray array, + jshort* p, + jint mode) +{ + ENTER(t, Thread::ActiveState); + + unsigned size = (*array)->length() * sizeof(jshort); + + if (mode == 0 or mode == AVIAN_JNI_COMMIT) { + if (size) { + memcpy((*array)->body().begin(), p, size); + } + } + + if (mode == 0 or mode == AVIAN_JNI_ABORT) { + t->m->heap->free(p, size); + } +} + +void JNICALL + ReleaseIntArrayElements(Thread* t, jintArray array, jint* p, jint mode) +{ + ENTER(t, Thread::ActiveState); + + unsigned size = (*array)->length() * sizeof(jint); + + if (mode == 0 or mode == AVIAN_JNI_COMMIT) { + if (size) { + memcpy((*array)->body().begin(), p, size); + } + } + + if (mode == 0 or mode == AVIAN_JNI_ABORT) { + t->m->heap->free(p, size); + } +} + +void JNICALL + ReleaseLongArrayElements(Thread* t, jlongArray array, jlong* p, jint mode) +{ + ENTER(t, Thread::ActiveState); + + unsigned size = (*array)->length() * sizeof(jlong); + + if (mode == 0 or mode == AVIAN_JNI_COMMIT) { + if (size) { + memcpy((*array)->body().begin(), p, size); + } + } + + if (mode == 0 or mode == AVIAN_JNI_ABORT) { + t->m->heap->free(p, size); + } +} + +void JNICALL ReleaseFloatArrayElements(Thread* t, + jfloatArray array, + jfloat* p, + jint mode) +{ + ENTER(t, Thread::ActiveState); + + unsigned size = (*array)->length() * sizeof(jfloat); + + if (mode == 0 or mode == AVIAN_JNI_COMMIT) { + if (size) { + memcpy((*array)->body().begin(), p, size); + } + } + + if (mode == 0 or mode == AVIAN_JNI_ABORT) { + t->m->heap->free(p, size); + } +} + +void JNICALL ReleaseDoubleArrayElements(Thread* t, + jdoubleArray array, + jdouble* p, + jint mode) +{ + ENTER(t, Thread::ActiveState); + + unsigned size = (*array)->length() * sizeof(jdouble); + + if (mode == 0 or mode == AVIAN_JNI_COMMIT) { + if (size) { + memcpy((*array)->body().begin(), p, size); + } + } + + if (mode == 0 or mode == AVIAN_JNI_ABORT) { + t->m->heap->free(p, size); + } +} + +void JNICALL GetBooleanArrayRegion(Thread* t, + jbooleanArray array, + jint offset, + jint length, + jboolean* dst) +{ + ENTER(t, Thread::ActiveState); + + if (length) { + memcpy(dst, &(*array)->body()[offset], length * sizeof(jboolean)); + } +} + +void JNICALL GetByteArrayRegion(Thread* t, + jbyteArray array, + jint offset, + jint length, + jbyte* dst) +{ + ENTER(t, Thread::ActiveState); + + if (length) { + memcpy(dst, &(*array)->body()[offset], length * sizeof(jbyte)); + } +} + +void JNICALL GetCharArrayRegion(Thread* t, + jcharArray array, + jint offset, + jint length, + jchar* dst) +{ + ENTER(t, Thread::ActiveState); + + if (length) { + memcpy(dst, &(*array)->body()[offset], length * sizeof(jchar)); + } +} + +void JNICALL GetShortArrayRegion(Thread* t, + jshortArray array, + jint offset, + jint length, + jshort* dst) +{ + ENTER(t, Thread::ActiveState); + + if (length) { + memcpy(dst, &(*array)->body()[offset], length * sizeof(jshort)); + } +} + +void JNICALL GetIntArrayRegion(Thread* t, + jintArray array, + jint offset, + jint length, + jint* dst) +{ + ENTER(t, Thread::ActiveState); + + if (length) { + memcpy(dst, &(*array)->body()[offset], length * sizeof(jint)); + } +} + +void JNICALL GetLongArrayRegion(Thread* t, + jlongArray array, + jint offset, + jint length, + jlong* dst) +{ + ENTER(t, Thread::ActiveState); + + if (length) { + memcpy(dst, &(*array)->body()[offset], length * sizeof(jlong)); + } +} + +void JNICALL GetFloatArrayRegion(Thread* t, + jfloatArray array, + jint offset, + jint length, + jfloat* dst) +{ + ENTER(t, Thread::ActiveState); + + if (length) { + memcpy(dst, &(*array)->body()[offset], length * sizeof(jfloat)); + } +} + +void JNICALL GetDoubleArrayRegion(Thread* t, + jdoubleArray array, + jint offset, + jint length, + jdouble* dst) +{ + ENTER(t, Thread::ActiveState); + + if (length) { + memcpy(dst, &(*array)->body()[offset], length * sizeof(jdouble)); + } +} + +void JNICALL SetBooleanArrayRegion(Thread* t, + jbooleanArray array, + jint offset, + jint length, + const jboolean* src) +{ + ENTER(t, Thread::ActiveState); + + if (length) { + memcpy(&(*array)->body()[offset], src, length * sizeof(jboolean)); + } +} + +void JNICALL SetByteArrayRegion(Thread* t, + jbyteArray array, + jint offset, + jint length, + const jbyte* src) +{ + ENTER(t, Thread::ActiveState); + + if (length) { + memcpy(&(*array)->body()[offset], src, length * sizeof(jbyte)); + } +} + +void JNICALL SetCharArrayRegion(Thread* t, + jcharArray array, + jint offset, + jint length, + const jchar* src) +{ + ENTER(t, Thread::ActiveState); + + if (length) { + memcpy(&(*array)->body()[offset], src, length * sizeof(jchar)); + } +} + +void JNICALL SetShortArrayRegion(Thread* t, + jshortArray array, + jint offset, + jint length, + const jshort* src) +{ + ENTER(t, Thread::ActiveState); + + if (length) { + memcpy(&(*array)->body()[offset], src, length * sizeof(jshort)); + } +} + +void JNICALL SetIntArrayRegion(Thread* t, + jintArray array, + jint offset, + jint length, + const jint* src) +{ + ENTER(t, Thread::ActiveState); + + if (length) { + memcpy(&(*array)->body()[offset], src, length * sizeof(jint)); + } +} + +void JNICALL SetLongArrayRegion(Thread* t, + jlongArray array, + jint offset, + jint length, + const jlong* src) +{ + ENTER(t, Thread::ActiveState); + + if (length) { + memcpy(&(*array)->body()[offset], src, length * sizeof(jlong)); + } +} + +void JNICALL SetFloatArrayRegion(Thread* t, + jfloatArray array, + jint offset, + jint length, + const jfloat* src) +{ + ENTER(t, Thread::ActiveState); + + if (length) { + memcpy(&(*array)->body()[offset], src, length * sizeof(jfloat)); + } +} + +void JNICALL SetDoubleArrayRegion(Thread* t, + jdoubleArray array, + jint offset, + jint length, + const jdouble* src) +{ + ENTER(t, Thread::ActiveState); + + if (length) { + memcpy(&(*array)->body()[offset], src, length * sizeof(jdouble)); + } +} + +void* JNICALL + GetPrimitiveArrayCritical(Thread* t, jarray array, jboolean* isCopy) +{ + if (t->criticalLevel == 0) { + enter(t, Thread::ActiveState); + } + + ++t->criticalLevel; + + if (isCopy) { + *isCopy = true; + } + + expect(t, *array); + + return reinterpret_cast(*array) + 2; +} + +void JNICALL ReleasePrimitiveArrayCritical(Thread* t, jarray, void*, jint) +{ + if ((--t->criticalLevel) == 0) { + enter(t, Thread::IdleState); + } +} + +uint64_t fromReflectedMethod(Thread* t, uintptr_t* arguments) +{ + jobject m = reinterpret_cast(arguments[0]); + + return methodID(t, t->m->classpath->getVMMethod(t, *m)); +} + +jmethodID JNICALL FromReflectedMethod(Thread* t, jobject method) +{ + uintptr_t arguments[] = {reinterpret_cast(method)}; + + return static_cast(run(t, fromReflectedMethod, arguments)); +} + +uint64_t toReflectedMethod(Thread* t, uintptr_t* arguments) +{ + jmethodID m = arguments[1]; + jboolean isStatic = arguments[2]; + + return reinterpret_cast(makeLocalReference( + t, + t->m->classpath->makeJMethod( + t, isStatic ? getStaticMethod(t, m) : getMethod(t, m)))); +} + +jobject JNICALL + ToReflectedMethod(Thread* t, jclass c, jmethodID method, jboolean isStatic) +{ + uintptr_t arguments[] = {reinterpret_cast(c), + static_cast(method), + static_cast(isStatic)}; + + return reinterpret_cast(run(t, toReflectedMethod, arguments)); +} + +uint64_t fromReflectedField(Thread* t, uintptr_t* arguments) +{ + jobject f = reinterpret_cast(arguments[0]); + + return fieldID(t, t->m->classpath->getVMField(t, cast(t, *f))); +} + +jfieldID JNICALL FromReflectedField(Thread* t, jobject field) +{ + uintptr_t arguments[] = {reinterpret_cast(field)}; + + return static_cast(run(t, fromReflectedField, arguments)); +} + +uint64_t toReflectedField(Thread* t, uintptr_t* arguments) +{ + jfieldID f = arguments[1]; + jboolean isStatic = arguments[2]; + + return reinterpret_cast(makeLocalReference( + t, + t->m->classpath->makeJField( + t, isStatic ? getStaticField(t, f) : getField(t, f)))); +} + +jobject JNICALL + ToReflectedField(Thread* t, jclass c, jfieldID field, jboolean isStatic) +{ + uintptr_t arguments[] = {reinterpret_cast(c), + static_cast(field), + static_cast(isStatic)}; + + return reinterpret_cast(run(t, toReflectedField, arguments)); +} + +uint64_t registerNatives(Thread* t, uintptr_t* arguments) +{ + jclass c = reinterpret_cast(arguments[0]); + const JNINativeMethod* methods + = reinterpret_cast(arguments[1]); + jint methodCount = arguments[2]; + + for (int i = 0; i < methodCount; ++i) { + if (methods[i].function) { + // Android's class library sometimes prepends a mysterious "!" + // to the method signature, which we happily ignore: + const char* sig = methods[i].signature; + if (*sig == '!') + ++sig; + + GcMethod* method + = findMethodOrNull(t, (*c)->vmClass(), methods[i].name, sig); + + if (method == 0 or (method->flags() & ACC_NATIVE) == 0) { + // The JNI spec says we must throw a NoSuchMethodError in this + // case, but that would prevent using a code shrinker like + // ProGuard effectively. Instead, we just ignore it. + + if (false) { + fprintf(stderr, + "not found: %s.%s%s\n", + (*c)->vmClass()->name()->body().begin(), + methods[i].name, + sig); + abort(t); + } + } else { + registerNative(t, method, methods[i].function); + } + } + } + + return 1; +} + +jint JNICALL RegisterNatives(Thread* t, + jclass c, + const JNINativeMethod* methods, + jint methodCount) +{ + uintptr_t arguments[] = {reinterpret_cast(c), + reinterpret_cast(methods), + static_cast(methodCount)}; + + return run(t, registerNatives, arguments) ? 0 : -1; +} + +jint JNICALL UnregisterNatives(Thread* t, jclass c) +{ + ENTER(t, Thread::ActiveState); + + unregisterNatives(t, (*c)->vmClass()); + + return 0; +} + +uint64_t monitorOp(Thread* t, uintptr_t* arguments) +{ + void (*op)(Thread*, object) + = reinterpret_cast(arguments[0]); + + jobject o = reinterpret_cast(arguments[1]); + + op(t, *o); + + return 1; +} + +void acquire0(Thread* t, object o) +{ + return acquire(t, o); +} + +jint JNICALL MonitorEnter(Thread* t, jobject o) +{ + uintptr_t arguments[] = {reinterpret_cast(voidPointer(acquire0)), + reinterpret_cast(o)}; + + return run(t, monitorOp, arguments) ? 0 : -1; +} + +void release0(Thread* t, object o) +{ + return release(t, o); +} + +jint JNICALL MonitorExit(Thread* t, jobject o) +{ + uintptr_t arguments[] = {reinterpret_cast(voidPointer(release0)), + reinterpret_cast(o)}; + + return run(t, monitorOp, arguments) ? 0 : -1; +} + +jint JNICALL GetJavaVM(Thread* t, Machine** m) +{ + *m = t->m; + return 0; +} + +jboolean JNICALL IsSameObject(Thread* t, jobject a, jobject b) +{ + if (a and b) { + ENTER(t, Thread::ActiveState); + + return *a == *b; + } else { + return a == b; + } +} + +uint64_t pushLocalFrame(Thread* t, uintptr_t* arguments) +{ + if (t->m->processor->pushLocalFrame(t, arguments[0])) { + return 1; + } else { + throw_(t, roots(t)->outOfMemoryError()); + } +} + +jint JNICALL PushLocalFrame(Thread* t, jint capacity) +{ + uintptr_t arguments[] = {static_cast(capacity)}; + + return run(t, pushLocalFrame, arguments) ? 0 : -1; +} + +uint64_t popLocalFrame(Thread* t, uintptr_t* arguments) +{ + uint64_t r; + jobject presult = reinterpret_cast(arguments[0]); + if (presult != NULL) { + object result = *presult; + PROTECT(t, result); + + t->m->processor->popLocalFrame(t); + + r = reinterpret_cast(makeLocalReference(t, result)); + } else { + t->m->processor->popLocalFrame(t); + r = 0; + } + + return r; +} + +jobject JNICALL PopLocalFrame(Thread* t, jobject result) +{ + uintptr_t arguments[] = {reinterpret_cast(result)}; + + return reinterpret_cast(run(t, popLocalFrame, arguments)); +} + +uint64_t newDirectByteBuffer(Thread* t, uintptr_t* arguments) +{ + jlong capacity; + memcpy(&capacity, arguments + 1, sizeof(jlong)); + + return reinterpret_cast(makeLocalReference( + t, + t->m->classpath->makeDirectByteBuffer( + t, reinterpret_cast(arguments[0]), capacity))); +} + +jobject JNICALL NewDirectByteBuffer(Thread* t, void* p, jlong capacity) +{ + uintptr_t arguments[1 + (sizeof(jlong) / BytesPerWord)]; + arguments[0] = reinterpret_cast(p); + memcpy(arguments + 1, &capacity, sizeof(jlong)); + + return reinterpret_cast(run(t, newDirectByteBuffer, arguments)); +} + +uint64_t getDirectBufferAddress(Thread* t, uintptr_t* arguments) +{ + return reinterpret_cast(t->m->classpath->getDirectBufferAddress( + t, *reinterpret_cast(arguments[0]))); +} + +void* JNICALL GetDirectBufferAddress(Thread* t, jobject b) +{ + uintptr_t arguments[] = {reinterpret_cast(b)}; + + return reinterpret_cast(run(t, getDirectBufferAddress, arguments)); +} + +uint64_t getDirectBufferCapacity(Thread* t, uintptr_t* arguments) +{ + return t->m->classpath->getDirectBufferCapacity( + t, *reinterpret_cast(arguments[0])); +} + +jlong JNICALL GetDirectBufferCapacity(Thread* t, jobject b) +{ + uintptr_t arguments[] = {reinterpret_cast(b)}; + + return run(t, getDirectBufferCapacity, arguments); +} + +struct JavaVMOption { + char* optionString; + void* extraInfo; +}; + +struct JavaVMInitArgs { + jint version; + + jint nOptions; + JavaVMOption* options; + jboolean ignoreUnrecognized; +}; + +int parseSize(const char* s) +{ + unsigned length = strlen(s); + RUNTIME_ARRAY(char, buffer, length + 1); + + if (length == 0) + return 0; + + char suffix = s[length - 1]; + if (suffix== 'k' or suffix == 'K') { + memcpy(RUNTIME_ARRAY_BODY(buffer), s, length - 1); + RUNTIME_ARRAY_BODY(buffer)[length - 1] = 0; + return atoi(RUNTIME_ARRAY_BODY(buffer)) * 1024; + } + + if (suffix == 'm' or suffix == 'M') { + memcpy(RUNTIME_ARRAY_BODY(buffer), s, length - 1); + RUNTIME_ARRAY_BODY(buffer)[length - 1] = 0; + return atoi(RUNTIME_ARRAY_BODY(buffer)) * 1024 * 1024; + } + + if (suffix == 'g' or suffix == 'G') { + memcpy(RUNTIME_ARRAY_BODY(buffer), s, length - 1); + RUNTIME_ARRAY_BODY(buffer)[length - 1] = 0; + return atoi(RUNTIME_ARRAY_BODY(buffer)) * 1024 * 1024 * 1024; + } + + return atoi(s); +} + +void append(char** p, const char* value, unsigned length, char tail) +{ + if (length) { + memcpy(*p, value, length); + *p += length; + *((*p)++) = tail; + } +} + +uint64_t boot(Thread* t, uintptr_t*) +{ + GcThrowable* throwable = makeThrowable(t, GcNullPointerException::Type); + // sequence point, for gc (don't recombine statements) + roots(t)->setNullPointerException(t, throwable); + + throwable = makeThrowable(t, GcArithmeticException::Type); + // sequence point, for gc (don't recombine statements) + roots(t)->setArithmeticException(t, throwable); + + throwable = makeThrowable(t, GcArrayIndexOutOfBoundsException::Type); + // sequence point, for gc (don't recombine statements) + roots(t)->setArrayIndexOutOfBoundsException(t, throwable); + + throwable = makeThrowable(t, GcOutOfMemoryError::Type); + // sequence point, for gc (don't recombine statements) + roots(t)->setOutOfMemoryError(t, throwable); + + throwable = makeThrowable(t, GcThrowable::Type); + // sequence point, for gc (don't recombine statements) + roots(t)->setShutdownInProgress(t, throwable); + + t->m->classpath->preBoot(t); + + t->javaThread = t->m->classpath->makeThread(t, 0); + + t->javaThread->peer() = reinterpret_cast(t); + +#ifndef SGX + GcThread* jthread = t->m->classpath->makeThread(t, t); + // sequence point, for gc (don't recombine statements) + roots(t)->setFinalizerThread(t, jthread); + roots(t)->finalizerThread()->daemon() = true; +#endif + + t->m->classpath->boot(t); + + const char* port = findProperty(t, "avian.trace.port"); + if (port) { + GcString* host = makeString(t, "0.0.0.0"); + PROTECT(t, host); + + GcMethod* method = resolveMethod(t, + roots(t)->bootLoader(), + "avian/Traces", + "startTraceListener", + "(Ljava/lang/String;I)V"); + + t->m->processor->invoke(t, method, 0, host, atoi(port)); + } + + enter(t, Thread::IdleState); + + return 1; +} + +} // namespace local + +} // namespace + +namespace vm { + +void populateJNITables(JavaVMVTable* vmTable, JNIEnvVTable* envTable) +{ + memset(vmTable, 0, sizeof(JavaVMVTable)); + + vmTable->DestroyJavaVM = local::DestroyJavaVM; + vmTable->AttachCurrentThread = local::AttachCurrentThread; + vmTable->AttachCurrentThreadAsDaemon = local::AttachCurrentThreadAsDaemon; + vmTable->DetachCurrentThread = local::DetachCurrentThread; + vmTable->GetEnv = local::GetEnv; + + memset(envTable, 0, sizeof(JNIEnvVTable)); + + envTable->GetVersion = local::GetVersion; + envTable->GetStringLength = local::GetStringLength; + envTable->GetStringChars = local::GetStringChars; + envTable->ReleaseStringChars = local::ReleaseStringChars; + envTable->GetStringRegion = local::GetStringRegion; + envTable->GetStringCritical = local::GetStringCritical; + envTable->ReleaseStringCritical = local::ReleaseStringCritical; + envTable->GetStringUTFLength = local::GetStringUTFLength; + envTable->GetStringUTFChars = local::GetStringUTFChars; + envTable->ReleaseStringUTFChars = local::ReleaseStringUTFChars; + envTable->GetStringUTFRegion = local::GetStringUTFRegion; + envTable->GetArrayLength = local::GetArrayLength; + envTable->NewString = local::NewString; + envTable->NewStringUTF = local::NewStringUTF; + envTable->DefineClass = local::DefineClass; + envTable->FindClass = local::FindClass; + envTable->ThrowNew = local::ThrowNew; + envTable->Throw = local::Throw; + envTable->ExceptionCheck = local::ExceptionCheck; + envTable->NewDirectByteBuffer = local::NewDirectByteBuffer; + envTable->GetDirectBufferAddress = local::GetDirectBufferAddress; + envTable->GetDirectBufferCapacity = local::GetDirectBufferCapacity; + envTable->NewLocalRef = local::NewLocalRef; + envTable->DeleteLocalRef = local::DeleteLocalRef; + envTable->GetObjectClass = local::GetObjectClass; + envTable->GetSuperclass = local::GetSuperclass; + envTable->IsInstanceOf = local::IsInstanceOf; + envTable->IsAssignableFrom = local::IsAssignableFrom; + envTable->GetFieldID = local::GetFieldID; + envTable->GetMethodID = local::GetMethodID; + envTable->GetStaticMethodID = local::GetStaticMethodID; + envTable->NewObjectV = local::NewObjectV; + envTable->NewObjectA = local::NewObjectA; + envTable->NewObject = local::NewObject; + envTable->CallObjectMethodV = local::CallObjectMethodV; + envTable->CallObjectMethodA = local::CallObjectMethodA; + envTable->CallObjectMethod = local::CallObjectMethod; + envTable->CallBooleanMethodV = local::CallBooleanMethodV; + envTable->CallBooleanMethodA = local::CallBooleanMethodA; + envTable->CallBooleanMethod = local::CallBooleanMethod; + envTable->CallByteMethodV = local::CallByteMethodV; + envTable->CallByteMethodA = local::CallByteMethodA; + envTable->CallByteMethod = local::CallByteMethod; + envTable->CallCharMethodV = local::CallCharMethodV; + envTable->CallCharMethodA = local::CallCharMethodA; + envTable->CallCharMethod = local::CallCharMethod; + envTable->CallShortMethodV = local::CallShortMethodV; + envTable->CallShortMethodA = local::CallShortMethodA; + envTable->CallShortMethod = local::CallShortMethod; + envTable->CallIntMethodV = local::CallIntMethodV; + envTable->CallIntMethodA = local::CallIntMethodA; + envTable->CallIntMethod = local::CallIntMethod; + envTable->CallLongMethodV = local::CallLongMethodV; + envTable->CallLongMethodA = local::CallLongMethodA; + envTable->CallLongMethod = local::CallLongMethod; + envTable->CallFloatMethodV = local::CallFloatMethodV; + envTable->CallFloatMethodA = local::CallFloatMethodA; + envTable->CallFloatMethod = local::CallFloatMethod; + envTable->CallDoubleMethodV = local::CallDoubleMethodV; + envTable->CallDoubleMethodA = local::CallDoubleMethodA; + envTable->CallDoubleMethod = local::CallDoubleMethod; + envTable->CallVoidMethodV = local::CallVoidMethodV; + envTable->CallVoidMethodA = local::CallVoidMethodA; + envTable->CallVoidMethod = local::CallVoidMethod; + envTable->CallStaticObjectMethodV = local::CallStaticObjectMethodV; + envTable->CallStaticObjectMethodA = local::CallStaticObjectMethodA; + envTable->CallStaticObjectMethod = local::CallStaticObjectMethod; + envTable->CallStaticBooleanMethodV = local::CallStaticBooleanMethodV; + envTable->CallStaticBooleanMethodA = local::CallStaticBooleanMethodA; + envTable->CallStaticBooleanMethod = local::CallStaticBooleanMethod; + envTable->CallStaticByteMethodV = local::CallStaticByteMethodV; + envTable->CallStaticByteMethodA = local::CallStaticByteMethodA; + envTable->CallStaticByteMethod = local::CallStaticByteMethod; + envTable->CallStaticCharMethodV = local::CallStaticCharMethodV; + envTable->CallStaticCharMethodA = local::CallStaticCharMethodA; + envTable->CallStaticCharMethod = local::CallStaticCharMethod; + envTable->CallStaticShortMethodV = local::CallStaticShortMethodV; + envTable->CallStaticShortMethodA = local::CallStaticShortMethodA; + envTable->CallStaticShortMethod = local::CallStaticShortMethod; + envTable->CallStaticIntMethodV = local::CallStaticIntMethodV; + envTable->CallStaticIntMethodA = local::CallStaticIntMethodA; + envTable->CallStaticIntMethod = local::CallStaticIntMethod; + envTable->CallStaticLongMethodV = local::CallStaticLongMethodV; + envTable->CallStaticLongMethodA = local::CallStaticLongMethodA; + envTable->CallStaticLongMethod = local::CallStaticLongMethod; + envTable->CallStaticFloatMethodV = local::CallStaticFloatMethodV; + envTable->CallStaticFloatMethodA = local::CallStaticFloatMethodA; + envTable->CallStaticFloatMethod = local::CallStaticFloatMethod; + envTable->CallStaticDoubleMethodV = local::CallStaticDoubleMethodV; + envTable->CallStaticDoubleMethodA = local::CallStaticDoubleMethodA; + envTable->CallStaticDoubleMethod = local::CallStaticDoubleMethod; + envTable->CallStaticVoidMethodV = local::CallStaticVoidMethodV; + envTable->CallStaticVoidMethodA = local::CallStaticVoidMethodA; + envTable->CallStaticVoidMethod = local::CallStaticVoidMethod; + envTable->GetStaticFieldID = local::GetStaticFieldID; + envTable->GetObjectField = local::GetObjectField; + envTable->GetBooleanField = local::GetBooleanField; + envTable->GetByteField = local::GetByteField; + envTable->GetCharField = local::GetCharField; + envTable->GetShortField = local::GetShortField; + envTable->GetIntField = local::GetIntField; + envTable->GetLongField = local::GetLongField; + envTable->GetFloatField = local::GetFloatField; + envTable->GetDoubleField = local::GetDoubleField; + envTable->SetObjectField = local::SetObjectField; + envTable->SetBooleanField = local::SetBooleanField; + envTable->SetByteField = local::SetByteField; + envTable->SetCharField = local::SetCharField; + envTable->SetShortField = local::SetShortField; + envTable->SetIntField = local::SetIntField; + envTable->SetLongField = local::SetLongField; + envTable->SetFloatField = local::SetFloatField; + envTable->SetDoubleField = local::SetDoubleField; + envTable->GetStaticObjectField = local::GetStaticObjectField; + envTable->GetStaticBooleanField = local::GetStaticBooleanField; + envTable->GetStaticByteField = local::GetStaticByteField; + envTable->GetStaticCharField = local::GetStaticCharField; + envTable->GetStaticShortField = local::GetStaticShortField; + envTable->GetStaticIntField = local::GetStaticIntField; + envTable->GetStaticLongField = local::GetStaticLongField; + envTable->GetStaticFloatField = local::GetStaticFloatField; + envTable->GetStaticDoubleField = local::GetStaticDoubleField; + envTable->SetStaticObjectField = local::SetStaticObjectField; + envTable->SetStaticBooleanField = local::SetStaticBooleanField; + envTable->SetStaticByteField = local::SetStaticByteField; + envTable->SetStaticCharField = local::SetStaticCharField; + envTable->SetStaticShortField = local::SetStaticShortField; + envTable->SetStaticIntField = local::SetStaticIntField; + envTable->SetStaticLongField = local::SetStaticLongField; + envTable->SetStaticFloatField = local::SetStaticFloatField; + envTable->SetStaticDoubleField = local::SetStaticDoubleField; + envTable->NewGlobalRef = local::NewGlobalRef; + envTable->NewWeakGlobalRef = local::NewWeakGlobalRef; + envTable->DeleteGlobalRef = local::DeleteGlobalRef; + envTable->DeleteWeakGlobalRef = local::DeleteWeakGlobalRef; + envTable->EnsureLocalCapacity = local::EnsureLocalCapacity; + envTable->ExceptionOccurred = local::ExceptionOccurred; + envTable->ExceptionDescribe = local::ExceptionDescribe; + envTable->ExceptionClear = local::ExceptionClear; + envTable->NewObjectArray = local::NewObjectArray; + envTable->GetObjectArrayElement = local::GetObjectArrayElement; + envTable->SetObjectArrayElement = local::SetObjectArrayElement; + envTable->NewBooleanArray = local::NewBooleanArray; + envTable->NewByteArray = local::NewByteArray; + envTable->NewCharArray = local::NewCharArray; + envTable->NewShortArray = local::NewShortArray; + envTable->NewIntArray = local::NewIntArray; + envTable->NewLongArray = local::NewLongArray; + envTable->NewFloatArray = local::NewFloatArray; + envTable->NewDoubleArray = local::NewDoubleArray; + envTable->GetBooleanArrayElements = local::GetBooleanArrayElements; + envTable->GetByteArrayElements = local::GetByteArrayElements; + envTable->GetCharArrayElements = local::GetCharArrayElements; + envTable->GetShortArrayElements = local::GetShortArrayElements; + envTable->GetIntArrayElements = local::GetIntArrayElements; + envTable->GetLongArrayElements = local::GetLongArrayElements; + envTable->GetFloatArrayElements = local::GetFloatArrayElements; + envTable->GetDoubleArrayElements = local::GetDoubleArrayElements; + envTable->ReleaseBooleanArrayElements = local::ReleaseBooleanArrayElements; + envTable->ReleaseByteArrayElements = local::ReleaseByteArrayElements; + envTable->ReleaseCharArrayElements = local::ReleaseCharArrayElements; + envTable->ReleaseShortArrayElements = local::ReleaseShortArrayElements; + envTable->ReleaseIntArrayElements = local::ReleaseIntArrayElements; + envTable->ReleaseLongArrayElements = local::ReleaseLongArrayElements; + envTable->ReleaseFloatArrayElements = local::ReleaseFloatArrayElements; + envTable->ReleaseDoubleArrayElements = local::ReleaseDoubleArrayElements; + envTable->GetBooleanArrayRegion = local::GetBooleanArrayRegion; + envTable->GetByteArrayRegion = local::GetByteArrayRegion; + envTable->GetCharArrayRegion = local::GetCharArrayRegion; + envTable->GetShortArrayRegion = local::GetShortArrayRegion; + envTable->GetIntArrayRegion = local::GetIntArrayRegion; + envTable->GetLongArrayRegion = local::GetLongArrayRegion; + envTable->GetFloatArrayRegion = local::GetFloatArrayRegion; + envTable->GetDoubleArrayRegion = local::GetDoubleArrayRegion; + envTable->SetBooleanArrayRegion = local::SetBooleanArrayRegion; + envTable->SetByteArrayRegion = local::SetByteArrayRegion; + envTable->SetCharArrayRegion = local::SetCharArrayRegion; + envTable->SetShortArrayRegion = local::SetShortArrayRegion; + envTable->SetIntArrayRegion = local::SetIntArrayRegion; + envTable->SetLongArrayRegion = local::SetLongArrayRegion; + envTable->SetFloatArrayRegion = local::SetFloatArrayRegion; + envTable->SetDoubleArrayRegion = local::SetDoubleArrayRegion; + envTable->GetPrimitiveArrayCritical = local::GetPrimitiveArrayCritical; + envTable->ReleasePrimitiveArrayCritical + = local::ReleasePrimitiveArrayCritical; + envTable->RegisterNatives = local::RegisterNatives; + envTable->UnregisterNatives = local::UnregisterNatives; + envTable->MonitorEnter = local::MonitorEnter; + envTable->MonitorExit = local::MonitorExit; + envTable->GetJavaVM = local::GetJavaVM; + envTable->IsSameObject = local::IsSameObject; + envTable->PushLocalFrame = local::PushLocalFrame; + envTable->PopLocalFrame = local::PopLocalFrame; + envTable->FromReflectedMethod = local::FromReflectedMethod; + envTable->ToReflectedMethod = local::ToReflectedMethod; + envTable->FromReflectedField = local::FromReflectedField; + envTable->ToReflectedField = local::ToReflectedField; +} + +} // namespace vm + +extern "C" AVIAN_EXPORT jint JNICALL JNI_GetDefaultJavaVMInitArgs(void*) +{ + return 0; +} + +extern "C" AVIAN_EXPORT jint JNICALL + JNI_GetCreatedJavaVMs(Machine**, jsize, jsize*) +{ + // todo + return -1; +} + +extern "C" AVIAN_EXPORT jint JNICALL + JNI_CreateJavaVM(Machine** m, Thread** t, void* args) +{ + local::JavaVMInitArgs* a = static_cast(args); + + unsigned heapLimit = 0; + unsigned stackLimit = 0; + const char* bootLibraries = 0; + const char* classpath = 0; + const char* javaHome = AVIAN_JAVA_HOME; + bool reentrant = false; + const char* embedPrefix = AVIAN_EMBED_PREFIX; + const char* bootClasspathPrepend = ""; + const char* bootClasspath = 0; + const char* bootClasspathAppend = ""; + const char* crashDumpDirectory = 0; + + unsigned propertyCount = 0; + + for (int i = 0; i < a->nOptions; ++i) { + if (strncmp(a->options[i].optionString, "-X", 2) == 0) { + const char* p = a->options[i].optionString + 2; + if (strncmp(p, "mx", 2) == 0) { + heapLimit = local::parseSize(p + 2); + } else if (strncmp(p, "ss", 2) == 0) { + stackLimit = local::parseSize(p + 2); + } else if (strncmp(p, + BOOTCLASSPATH_PREPEND_OPTION ":", + sizeof(BOOTCLASSPATH_PREPEND_OPTION)) == 0) { + bootClasspathPrepend = p + sizeof(BOOTCLASSPATH_PREPEND_OPTION); + } else if (strncmp( + p, BOOTCLASSPATH_OPTION ":", sizeof(BOOTCLASSPATH_OPTION)) + == 0) { + bootClasspath = p + sizeof(BOOTCLASSPATH_OPTION); + } else if (strncmp(p, + BOOTCLASSPATH_APPEND_OPTION ":", + sizeof(BOOTCLASSPATH_APPEND_OPTION)) == 0) { + bootClasspathAppend = p + sizeof(BOOTCLASSPATH_APPEND_OPTION); + } + } else if (strncmp(a->options[i].optionString, "-D", 2) == 0) { + const char* p = a->options[i].optionString + 2; + if (strncmp(p, BOOTSTRAP_PROPERTY "=", sizeof(BOOTSTRAP_PROPERTY)) == 0) { + bootLibraries = p + sizeof(BOOTSTRAP_PROPERTY); + } else if (strncmp(p, + JAVA_COMMAND_PROPERTY "=", + sizeof(JAVA_COMMAND_PROPERTY)) == 0 + or strncmp(p, + JAVA_LAUNCHER_PROPERTY "=", + sizeof(JAVA_LAUNCHER_PROPERTY)) == 0) { + // this means we're being invoked via the javac or java + // command, so the bootstrap library should be e.g. libjvm.so + bootLibraries = SO_PREFIX "jvm" SO_SUFFIX; + } else if (strncmp(p, CRASHDIR_PROPERTY "=", sizeof(CRASHDIR_PROPERTY)) + == 0) { + crashDumpDirectory = p + sizeof(CRASHDIR_PROPERTY); + } else if (strncmp(p, CLASSPATH_PROPERTY "=", sizeof(CLASSPATH_PROPERTY)) + == 0) { + classpath = p + sizeof(CLASSPATH_PROPERTY); + } else if (strncmp(p, JAVA_HOME_PROPERTY "=", sizeof(JAVA_HOME_PROPERTY)) + == 0) { + javaHome = p + sizeof(JAVA_HOME_PROPERTY); + } else if (strncmp(p, REENTRANT_PROPERTY "=", sizeof(REENTRANT_PROPERTY)) + == 0) { + reentrant = strcmp(p + sizeof(REENTRANT_PROPERTY), "true") == 0; + } else if (strncmp(p, + EMBED_PREFIX_PROPERTY "=", + sizeof(EMBED_PREFIX_PROPERTY)) == 0) { + embedPrefix = p + sizeof(EMBED_PREFIX_PROPERTY); + } + + ++propertyCount; + } + } + + if (heapLimit == 0) + heapLimit = 128 * 1024 * 1024; + + if (stackLimit == 0) + stackLimit = 128 * 1024; + + bool addClasspathProperty = classpath == 0; + if (addClasspathProperty) { + classpath = "."; + ++propertyCount; + } + + System* s = makeSystem(reentrant); + Heap* h = makeHeap(s, heapLimit); + Classpath* c = makeClasspath(s, h, javaHome, embedPrefix); + + if (bootClasspath == 0) { + bootClasspath = c->bootClasspath(); + } + + unsigned bcppl = strlen(bootClasspathPrepend); + unsigned bcpl = strlen(bootClasspath); + unsigned bcpal = strlen(bootClasspathAppend); + + unsigned bootClasspathBufferSize = bcppl + bcpl + bcpal + 3; + RUNTIME_ARRAY(char, bootClasspathBuffer, bootClasspathBufferSize); + char* bootClasspathPointer = RUNTIME_ARRAY_BODY(bootClasspathBuffer); + if (bootClasspathBufferSize > 3) { + local::append(&bootClasspathPointer, + bootClasspathPrepend, + bcppl, + bcpl + bcpal ? PATH_SEPARATOR : 0); + local::append( + &bootClasspathPointer, bootClasspath, bcpl, bcpal ? PATH_SEPARATOR : 0); + local::append(&bootClasspathPointer, bootClasspathAppend, bcpal, 0); + } else { + *RUNTIME_ARRAY_BODY(bootClasspathBuffer) = 0; + } + + char* bootLibrary = bootLibraries ? strdup(bootLibraries) : 0; + char* bootLibraryEnd = bootLibrary ? strchr(bootLibrary, PATH_SEPARATOR) : 0; + if (bootLibraryEnd) + *bootLibraryEnd = 0; + + Finder* bf + = makeFinder(s, h, RUNTIME_ARRAY_BODY(bootClasspathBuffer), bootLibrary); + Finder* af = makeFinder(s, h, classpath, bootLibrary); + if (bootLibrary) + free(bootLibrary); + Processor* p = makeProcessor(s, h, crashDumpDirectory, true); + + // reserve space for avian.version and file.encoding: + propertyCount += 2; + + const char** properties = static_cast( + h->allocate(sizeof(const char*) * propertyCount)); + + const char** propertyPointer = properties; + + const char** arguments = static_cast( + h->allocate(sizeof(const char*) * a->nOptions)); + + const char** argumentPointer = arguments; + + for (int i = 0; i < a->nOptions; ++i) { + if (strncmp(a->options[i].optionString, "-D", 2) == 0) { + *(propertyPointer++) = a->options[i].optionString + 2; + } + *(argumentPointer++) = a->options[i].optionString; + } + + unsigned cpl = strlen(classpath); + RUNTIME_ARRAY(char, classpathProperty, cpl + strlen(CLASSPATH_PROPERTY) + 2); + if (addClasspathProperty) { + char* p = RUNTIME_ARRAY_BODY(classpathProperty); + local::append(&p, CLASSPATH_PROPERTY, strlen(CLASSPATH_PROPERTY), '='); + local::append(&p, classpath, cpl, 0); + *(propertyPointer++) = RUNTIME_ARRAY_BODY(classpathProperty); + } + + *(propertyPointer++) = "avian.version=" AVIAN_VERSION; + + // todo: should this be derived from the OS locale? Should it be + // overrideable via JavaVMInitArgs? + *(propertyPointer++) = "file.encoding=UTF-8"; + + *m = new (h->allocate(sizeof(Machine))) Machine(s, + h, + bf, + af, + p, + c, + properties, + propertyCount, + arguments, + a->nOptions, + stackLimit); + + h->free(properties, sizeof(const char*) * propertyCount); + + *t = p->makeThread(*m, 0, 0); + + enter(*t, Thread::ActiveState); + enter(*t, Thread::IdleState); + + return run(*t, local::boot, 0) ? 0 : -1; +} + +extern "C" AVIAN_EXPORT jstring JNICALL JVM_GetTemporaryDirectory(JNIEnv* e UNUSED) +{ + // Unimplemented + // This is used in newer builds of openjdk8, as a place to store statistics or something... + abort(); +} + +extern "C" AVIAN_EXPORT jboolean JNICALL JVM_KnownToNotExist(JNIEnv* e UNUSED, jobject loader UNUSED, jstring classname UNUSED) +{ + // Unimplemented + abort(); +} + +extern "C" AVIAN_EXPORT jintArray JNICALL JVM_GetResourceLookupCache(JNIEnv* e UNUSED, jobject loader UNUSED, jstring resourcename UNUSED) +{ + // Unimplemented + abort(); +} diff --git a/sgx-jvm/avian/src/lzma-decode.cpp b/sgx-jvm/avian/src/lzma-decode.cpp new file mode 100644 index 0000000000..e94253e340 --- /dev/null +++ b/sgx-jvm/avian/src/lzma-decode.cpp @@ -0,0 +1,66 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#include "avian/lzma-util.h" +#include "C/LzmaDec.h" + +using namespace vm; + +namespace { + +int32_t read4(const uint8_t* in) +{ + return (static_cast(in[3]) << 24) + | (static_cast(in[2]) << 16) + | (static_cast(in[1]) << 8) | (static_cast(in[0])); +} + +} // namespace + +namespace vm { + +uint8_t* decodeLZMA(System* s, + avian::util::Alloc* a, + uint8_t* in, + size_t inSize, + size_t* outSize) +{ + const size_t PropHeaderSize = 5; + const size_t HeaderSize = 13; + + int32_t outSize32 = read4(in + PropHeaderSize); + expect(s, outSize32 >= 0); + SizeT outSizeT = outSize32; + + uint8_t* out = static_cast(a->allocate(outSize32)); + + SizeT inSizeT = inSize; + LzmaAllocator allocator(a); + + ELzmaStatus status; + int result = LzmaDecode(out, + &outSizeT, + in + HeaderSize, + &inSizeT, + in, + PropHeaderSize, + LZMA_FINISH_END, + &status, + &(allocator.allocator)); + + expect(s, result == SZ_OK); + expect(s, status == LZMA_STATUS_FINISHED_WITH_MARK); + + *outSize = outSize32; + + return out; +} + +} // namespace vm diff --git a/sgx-jvm/avian/src/lzma-encode.cpp b/sgx-jvm/avian/src/lzma-encode.cpp new file mode 100644 index 0000000000..b15ebe54eb --- /dev/null +++ b/sgx-jvm/avian/src/lzma-encode.cpp @@ -0,0 +1,79 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#include "avian/lzma-util.h" +#include "C/LzmaEnc.h" + +using namespace vm; + +namespace { + +SRes myProgress(void*, UInt64, UInt64) +{ + return SZ_OK; +} + +} // namespace + +namespace vm { + +uint8_t* encodeLZMA(System* s, + avian::util::Alloc* a, + uint8_t* in, + size_t inSize, + size_t* outSize) +{ + const unsigned PropHeaderSize = 5; + const unsigned HeaderSize = 13; + + unsigned bufferSize = inSize * 2; + + uint8_t* buffer = static_cast(a->allocate(bufferSize)); + + LzmaAllocator allocator(a); + + CLzmaEncProps props; + LzmaEncProps_Init(&props); + props.level = 9; + props.writeEndMark = 1; + + ICompressProgress progress = {myProgress}; + + SizeT propsSize = PropHeaderSize; + + int32_t inSize32 = inSize; + memcpy(buffer + PropHeaderSize, &inSize32, 4); + + SizeT outSizeT = bufferSize; + int result = LzmaEncode(buffer + HeaderSize, + &outSizeT, + in, + inSize, + &props, + buffer, + &propsSize, + 1, + &progress, + &(allocator.allocator), + &(allocator.allocator)); + + expect(s, result == SZ_OK); + + *outSize = outSizeT + HeaderSize; + + uint8_t* out = static_cast(a->allocate(*outSize)); + memcpy(out, buffer, *outSize); + + a->free(buffer, bufferSize); + + return out; +} + +} // namespace vm diff --git a/sgx-jvm/avian/src/lzma/load.cpp b/sgx-jvm/avian/src/lzma/load.cpp new file mode 100644 index 0000000000..3f177e6b39 --- /dev/null +++ b/sgx-jvm/avian/src/lzma/load.cpp @@ -0,0 +1,195 @@ +#include +#include +#include +#include +#include +#include +#include + +#include "C/LzmaDec.h" + +#if (defined __MINGW32__) || (defined _MSC_VER) +#define EXPORT __declspec(dllexport) +#include +#define open _open +#define write _write +#define close _close +#ifdef _MSC_VER +#define S_IRWXU (_S_IREAD | _S_IWRITE) +#define and && +#endif +#else +#define EXPORT __attribute__((visibility("default"))) +#include +#include +#include +#define O_BINARY 0 +#endif + +#if (!defined __x86_64__) && ((defined __MINGW32__) || (defined _MSC_VER)) +#define SYMBOL(x) binary_exe_##x +#else +#define SYMBOL(x) _binary_exe_##x +#endif + +extern "C" { +extern const uint8_t SYMBOL(start)[]; +extern const uint8_t SYMBOL(end)[]; + +} // extern "C" + +namespace { + +int32_t read4(const uint8_t* in) +{ + return (static_cast(in[3]) << 24) + | (static_cast(in[2]) << 16) + | (static_cast(in[1]) << 8) | (static_cast(in[0])); +} + +void* myAllocate(void*, size_t size) +{ + return malloc(size); +} + +void myFree(void*, void* address) +{ + free(address); +} + +#if (defined __MINGW32__) || (defined _MSC_VER) + +void* openLibrary(const char* name) +{ + return LoadLibrary(name); +} + +void* librarySymbol(void* library, const char* name) +{ + void* address; + FARPROC p = GetProcAddress(static_cast(library), name); + memcpy(&address, &p, sizeof(void*)); + return address; +} + +const char* libraryError(void*) +{ + return "unknown error"; +} + +const char* temporaryFileName(char* buffer, unsigned size) +{ + unsigned c = GetTempPathA(size, buffer); + if (c) { + if (GetTempFileNameA(buffer, "223", 0, buffer + c)) { + DeleteFileA(buffer + c); + return buffer + c; + } + } + return 0; +} + +#else + +void* openLibrary(const char* name) +{ + return dlopen(name, RTLD_LAZY | RTLD_LOCAL); +} + +void* librarySymbol(void* library, const char* name) +{ + return dlsym(library, name); +} + +const char* libraryError(void*) +{ + return dlerror(); +} + +const char* temporaryFileName(char* buffer, unsigned) +{ + return tmpnam(buffer); +} + +#endif + +} // namespace + +int main(int ac, const char** av) +{ + const unsigned PropHeaderSize = 5; + const unsigned HeaderSize = 13; + + SizeT inSize = SYMBOL(end) - SYMBOL(start); + + int32_t outSize32 = read4(SYMBOL(start) + PropHeaderSize); + SizeT outSize = outSize32; + + uint8_t* out = static_cast(malloc(outSize)); + if (out) { + ISzAlloc allocator = {myAllocate, myFree}; + ELzmaStatus status = LZMA_STATUS_NOT_SPECIFIED; + + if (SZ_OK == LzmaDecode(out, + &outSize, + SYMBOL(start) + HeaderSize, + &inSize, + SYMBOL(start), + PropHeaderSize, + LZMA_FINISH_END, + &status, + &allocator)) { + const unsigned BufferSize = 1024; + char buffer[BufferSize]; + const char* name = temporaryFileName(buffer, BufferSize); + if (name) { + int file = open(name, O_CREAT | O_EXCL | O_WRONLY | O_BINARY, S_IRWXU); + if (file != -1) { + SizeT result = write(file, out, outSize); + free(out); + + if (close(file) == 0 and outSize == result) { + void* library = openLibrary(name); + unlink(name); + + if (library) { + void* main = librarySymbol(library, "avianMain"); + if (main) { + int (*mainFunction)(const char*, int, const char**); + memcpy(&mainFunction, &main, sizeof(void*)); + return mainFunction(name, ac, av); + } else { + fprintf(stderr, "unable to find main in %s", name); + } + } else { + fprintf(stderr, + "unable to load %s: %s\n", + name, + libraryError(library)); + } + } else { + unlink(name); + + fprintf(stderr, + "close or write failed; tried %d, got %d; %s\n", + static_cast(outSize), + static_cast(result), + strerror(errno)); + } + } else { + fprintf(stderr, "unable to open %s\n", name); + } + } else { + fprintf(stderr, "unable to make temporary file name\n"); + } + } else { + fprintf(stderr, "unable to decode LZMA data\n"); + } + } else { + fprintf(stderr, + "unable to allocate buffer of size %d\n", + static_cast(outSize)); + } + + return -1; +} diff --git a/sgx-jvm/avian/src/lzma/main.cpp b/sgx-jvm/avian/src/lzma/main.cpp new file mode 100644 index 0000000000..5820e235cf --- /dev/null +++ b/sgx-jvm/avian/src/lzma/main.cpp @@ -0,0 +1,192 @@ +#include +#include +#include +#include +#include +#include +#ifdef _WIN32 +#include +#else +#include +#include +#endif +#include + +#include "LzmaEnc.h" +#include "LzmaDec.h" + +namespace { + +int32_t read4(const uint8_t* in) +{ + return (static_cast(in[3]) << 24) + | (static_cast(in[2]) << 16) + | (static_cast(in[1]) << 8) | (static_cast(in[0])); +} + +void* myAllocate(void*, size_t size) +{ + return malloc(size); +} + +void myFree(void*, void* address) +{ + free(address); +} + +SRes myProgress(void*, UInt64, UInt64) +{ + return SZ_OK; +} + +void usageAndExit(const char* program) +{ + fprintf(stderr, + "usage: %s {encode|decode} " + "[]", + program); + exit(-1); +} + +} // namespace + +int main(int argc, const char** argv) +{ + if (argc < 4 or argc > 5) { + usageAndExit(argv[0]); + } + + bool encode = strcmp(argv[1], "encode") == 0; + + uint8_t* data = 0; + unsigned size; + int fd = open(argv[2], O_RDONLY); + if (fd != -1) { + struct stat s; + int r = fstat(fd, &s); + if (r != -1) { +#ifdef _WIN32 + HANDLE fm; + HANDLE h = (HANDLE)_get_osfhandle(fd); + + fm = CreateFileMapping(h, NULL, PAGE_READONLY, 0, 0, NULL); + data = static_cast( + MapViewOfFile(fm, FILE_MAP_READ, 0, 0, s.st_size)); + + CloseHandle(fm); +#else + data = static_cast( + mmap(0, s.st_size, PROT_READ, MAP_PRIVATE, fd, 0)); +#endif + size = s.st_size; + } + close(fd); + } + + bool success = false; + + if (data) { + const unsigned PropHeaderSize = 5; + const unsigned HeaderSize = 13; + + SizeT outSize; + bool outSizeIsValid; + if (encode) { + outSize = size * 2; + outSizeIsValid = true; + } else { + int32_t outSize32 = read4(data + PropHeaderSize); + if (outSize32 < 0 and argc == 5) { + outSize32 = atoi(argv[4]); + } + + outSize = outSize32; + outSizeIsValid = outSize32 >= 0; + } + + if (outSizeIsValid) { + uint8_t* out = static_cast(malloc(outSize)); + if (out) { + SizeT inSize = size; + ISzAlloc allocator = {myAllocate, myFree}; + ELzmaStatus status = LZMA_STATUS_NOT_SPECIFIED; + int result; + if (encode) { + CLzmaEncProps props; + LzmaEncProps_Init(&props); + props.level = 9; + props.writeEndMark = 1; + + ICompressProgress progress = {myProgress}; + + SizeT propsSize = PropHeaderSize; + + int32_t inSize32 = inSize; + memcpy(out + PropHeaderSize, &inSize32, 4); + + result = LzmaEncode(out + HeaderSize, + &outSize, + data, + inSize, + &props, + out, + &propsSize, + 1, + &progress, + &allocator, + &allocator); + + outSize += HeaderSize; + } else { + result = LzmaDecode(out, + &outSize, + data + HeaderSize, + &inSize, + data, + PropHeaderSize, + LZMA_FINISH_END, + &status, + &allocator); + } + + if (result == SZ_OK) { + FILE* outFile = fopen(argv[3], "wb"); + + if (outFile) { + if (fwrite(out, outSize, 1, outFile) == 1) { + success = true; + } else { + fprintf(stderr, "unable to write to %s\n", argv[3]); + } + + fclose(outFile); + } else { + fprintf(stderr, "unable to open %s\n", argv[3]); + } + } else { + fprintf(stderr, + "unable to %s data: result %d status %d\n", + encode ? "encode" : "decode", + result, + status); + } + + free(out); + } else { + fprintf(stderr, "unable to allocate output buffer\n"); + } + } else { + fprintf(stderr, "unable to determine uncompressed size\n"); + } + +#ifdef _WIN32 + UnmapViewOfFile(data); +#else + munmap(data, size); +#endif + } else { + perror(argv[0]); + } + + return (success ? 0 : -1); +} diff --git a/sgx-jvm/avian/src/machine.cpp b/sgx-jvm/avian/src/machine.cpp new file mode 100644 index 0000000000..50768edc2e --- /dev/null +++ b/sgx-jvm/avian/src/machine.cpp @@ -0,0 +1,6366 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#include "avian/jnienv.h" +#include "avian/machine.h" +#include "avian/util.h" +#include +#include "avian/constants.h" +#include "avian/processor.h" +#include "avian/arch.h" +#include "avian/lzma.h" + +#include +#include + +#if defined(PLATFORM_WINDOWS) +#define WIN32_LEAN_AND_MEAN +#include +#endif + +using namespace vm; +using namespace avian::util; + +namespace { + +const bool DebugClassReader = false; + +const unsigned NoByte = 0xFFFF; + +#ifdef USE_ATOMIC_OPERATIONS +void atomicIncrement(uint32_t* p, int v) +{ + for (uint32_t old = *p; not atomicCompareAndSwap32(p, old, old + v); + old = *p) { + } +} +#endif + +void join(Thread* t, Thread* o) +{ + if (t != o) { + assertT(t, o->state != Thread::JoinedState); + assertT(t, (o->getFlags() & Thread::SystemFlag) == 0); + if (o->getFlags() & Thread::JoinFlag) { + o->systemThread->join(); + } + o->state = Thread::JoinedState; + } +} + +#ifndef NDEBUG + +bool find(Thread* t, Thread* o) +{ + return (t == o) or (t->peer and find(t->peer, o)) + or (t->child and find(t->child, o)); +} + +unsigned count(Thread* t, Thread* o) +{ + unsigned c = 0; + + if (t != o) + ++c; + if (t->peer) + c += count(t->peer, o); + if (t->child) + c += count(t->child, o); + + return c; +} + +Thread** fill(Thread* t, Thread* o, Thread** array) +{ + if (t != o) + *(array++) = t; + if (t->peer) + array = fill(t->peer, o, array); + if (t->child) + array = fill(t->child, o, array); + + return array; +} + +#endif // not NDEBUG + +void dispose(Thread* t, Thread* o, bool remove) +{ + if (remove) { +#ifndef NDEBUG + expect(t, find(t->m->rootThread, o)); + + unsigned c = count(t->m->rootThread, o); + THREAD_RUNTIME_ARRAY(t, Thread*, threads, c); + fill(t->m->rootThread, o, RUNTIME_ARRAY_BODY(threads)); +#endif + + if (o->parent) { + Thread* previous = 0; + for (Thread* p = o->parent->child; p;) { + if (p == o) { + if (p == o->parent->child) { + o->parent->child = p->peer; + } else { + previous->peer = p->peer; + } + break; + } else { + previous = p; + p = p->peer; + } + } + + for (Thread* p = o->child; p;) { + Thread* next = p->peer; + p->peer = o->parent->child; + o->parent->child = p; + p->parent = o->parent; + p = next; + } + } else if (o->child) { + t->m->rootThread = o->child; + + for (Thread* p = o->peer; p;) { + Thread* next = p->peer; + p->peer = t->m->rootThread; + t->m->rootThread = p; + p = next; + } + } else if (o->peer) { + t->m->rootThread = o->peer; + } else { + abort(t); + } + +#ifndef NDEBUG + expect(t, not find(t->m->rootThread, o)); + + for (unsigned i = 0; i < c; ++i) { + expect(t, find(t->m->rootThread, RUNTIME_ARRAY_BODY(threads)[i])); + } +#endif + } + + o->dispose(); +} + +void visitAll(Thread* m, Thread* o, void (*visit)(Thread*, Thread*)) +{ + for (Thread* p = o->child; p;) { + Thread* child = p; + p = p->peer; + visitAll(m, child, visit); + } + + visit(m, o); +} + +void disposeNoRemove(Thread* m, Thread* o) +{ + dispose(m, o, false); +} + +void interruptDaemon(Thread* m, Thread* o) +{ + if (o->getFlags() & Thread::DaemonFlag) { + interrupt(m, o); + } +} + +void turnOffTheLights(Thread* t) +{ + expect(t, t->m->liveCount == 1); + + visitAll(t, t->m->rootThread, join); + + enter(t, Thread::ExitState); + + { + GcFinalizer* p = 0; + PROTECT(t, p); + + for (p = t->m->finalizers; p;) { + GcFinalizer* f = p; + p = cast(t, p->next()); + + void (*function)(Thread*, object); + memcpy(&function, &f->finalize(), BytesPerWord); + if (function) { + function(t, f->target()); + } + } + + for (p = t->m->tenuredFinalizers; p;) { + GcFinalizer* f = p; + p = cast(t, p->next()); + + void (*function)(Thread*, object); + memcpy(&function, &f->finalize(), BytesPerWord); + if (function) { + function(t, f->target()); + } + } + } + + if (GcArray* files = roots(t)->virtualFiles()) { + PROTECT(t, files); + for (unsigned i = 0; i < files->length(); ++i) { + object region = files->body()[i]; + if (region) { + static_cast(cast(t, region)->region()) + ->dispose(); + } + } + } + + for (GcFinder* p = roots(t)->virtualFileFinders(); p; p = p->next()) { + static_cast(p->finder())->dispose(); + } + + Machine* m = t->m; + + visitAll(t, t->m->rootThread, disposeNoRemove); + + System* s = m->system; + + expect(s, m->threadCount == 0); + + Heap* h = m->heap; + Processor* p = m->processor; + Classpath* c = m->classpath; + Finder* bf = m->bootFinder; + Finder* af = m->appFinder; + + c->dispose(); + h->disposeFixies(); + m->dispose(); + p->dispose(); + bf->dispose(); + af->dispose(); + h->dispose(); + s->dispose(); +} + +void killZombies(Thread* t, Thread* o) +{ + for (Thread* p = o->child; p;) { + Thread* child = p; + p = p->peer; + killZombies(t, child); + } + + if ((o->getFlags() & Thread::SystemFlag) == 0) { + switch (o->state) { + case Thread::ZombieState: + join(t, o); + // fall through + + case Thread::JoinedState: + dispose(t, o, true); + + default: + break; + } + } +} + +unsigned footprint(Thread* t) +{ + expect(t, t->criticalLevel == 0); + + unsigned n = t->heapOffset + t->heapIndex + t->backupHeapIndex; + + for (Thread* c = t->child; c; c = c->peer) { + n += footprint(c); + } + + return n; +} + +void visitRoots(Thread* t, Heap::Visitor* v) +{ + if (t->state != Thread::ZombieState) { + v->visit(&(t->javaThread)); + v->visit(&(t->exception)); + + t->m->processor->visitObjects(t, v); + + for (Thread::Protector* p = t->protector; p; p = p->next) { + p->visit(v); + } + } + + for (Thread* c = t->child; c; c = c->peer) { + visitRoots(c, v); + } +} + +bool walk(Thread*, + Heap::Walker* w, + uint32_t* mask, + unsigned fixedSize, + unsigned arrayElementSize, + unsigned arrayLength, + unsigned start) +{ + unsigned fixedSizeInWords = ceilingDivide(fixedSize, BytesPerWord); + unsigned arrayElementSizeInWords + = ceilingDivide(arrayElementSize, BytesPerWord); + + for (unsigned i = start; i < fixedSizeInWords; ++i) { + if (mask[i / 32] & (static_cast(1) << (i % 32))) { + if (not w->visit(i)) { + return false; + } + } + } + + bool arrayObjectElements = false; + for (unsigned j = 0; j < arrayElementSizeInWords; ++j) { + unsigned k = fixedSizeInWords + j; + if (mask[k / 32] & (static_cast(1) << (k % 32))) { + arrayObjectElements = true; + break; + } + } + + if (arrayObjectElements) { + unsigned arrayStart; + unsigned elementStart; + if (start > fixedSizeInWords) { + unsigned s = start - fixedSizeInWords; + arrayStart = s / arrayElementSizeInWords; + elementStart = s % arrayElementSizeInWords; + } else { + arrayStart = 0; + elementStart = 0; + } + + for (unsigned i = arrayStart; i < arrayLength; ++i) { + for (unsigned j = elementStart; j < arrayElementSizeInWords; ++j) { + unsigned k = fixedSizeInWords + j; + if (mask[k / 32] & (static_cast(1) << (k % 32))) { + if (not w->visit(fixedSizeInWords + (i * arrayElementSizeInWords) + + j)) { + return false; + } + } + } + } + } + + return true; +} + +object findInInterfaces( + Thread* t, + GcClass* class_, + GcByteArray* name, + GcByteArray* spec, + object (*find)(Thread*, GcClass*, GcByteArray*, GcByteArray*)) +{ + object result = 0; + if (GcArray* itable = cast(t, class_->interfaceTable())) { + PROTECT(t, itable); + for (unsigned i = 0; i < itable->length() and result == 0; i += 2) { + result = find(t, cast(t, itable->body()[i]), name, spec); + } + } + return result; +} + +void finalizerTargetUnreachable(Thread* t, Heap::Visitor* v, GcFinalizer** p) +{ + v->visit(&(*p)->target()); + + GcFinalizer* finalizer = *p; + *p = cast(t, finalizer->next()); + + void (*function)(Thread*, object); + memcpy(&function, &finalizer->finalize(), BytesPerWord); + + if (function) { + // TODO: use set() here? + finalizer->next() = t->m->finalizeQueue; + t->m->finalizeQueue = finalizer; + } else { + finalizer->setQueueTarget(t, finalizer->target()); + finalizer->setQueueNext(t, roots(t)->objectsToFinalize()); + roots(t)->setObjectsToFinalize(t, finalizer); + } +} + +void referenceTargetUnreachable(Thread* t, Heap::Visitor* v, GcJreference** p) +{ + if (DebugReferences) { + fprintf( + stderr, "target %p unreachable for reference %p\n", (*p)->target(), *p); + } + + v->visit(p); + (*p)->target() = 0; + + if (objectClass(t, *p) == type(t, GcCleaner::Type)) { + // In openjdk, sun/misc/Cleaner extends PhantomReference + GcCleaner* cleaner = (*p)->as(t); + + *p = cast(t, (*p)->vmNext()); + + cleaner->setQueueNext(t, roots(t)->objectsToClean()); + roots(t)->setObjectsToClean(t, cleaner); + } else { + if ((*p)->queue() + and t->m->heap->status((*p)->queue()) != Heap::Unreachable) { + // queue is reachable - add the reference + + v->visit(&(*p)->queue()); + + GcReferenceQueue* q = (*p)->queue(); + + if (q->front()) { + (*p)->setJNext(t, q->front()); + } else { + (*p)->setJNext(t, *p); + } + q->setFront(t, *p); + + (*p)->queue() = 0; + } + + *p = cast(t, (*p)->vmNext()); + } +} + +void referenceUnreachable(Thread* t, Heap::Visitor* v, GcJreference** p) +{ + GcJreference* r = t->m->heap->follow(*p); + + if (DebugReferences) { + fprintf(stderr, "reference %p unreachable (target %p)\n", *p, r->target()); + } + + if (r->queue() and t->m->heap->status(r->queue()) != Heap::Unreachable) { + // queue is reachable - add the reference + referenceTargetUnreachable(t, v, p); + } else { + *p = cast(t, (*p)->vmNext()); + } +} + +void referenceTargetReachable(Thread* t, Heap::Visitor* v, GcJreference** p) +{ + if (DebugReferences) { + fprintf( + stderr, "target %p reachable for reference %p\n", (*p)->target(), *p); + } + + v->visit(p); + v->visit(&(*p)->target()); + + if (t->m->heap->status((*p)->queue()) == Heap::Unreachable) { + (*p)->queue() = 0; + } else { + v->visit(&(*p)->queue()); + } +} + +bool isFinalizable(Thread* t, object o) +{ + return t->m->heap->status(o) == Heap::Unreachable + and (t->m->heap->follow(objectClass(t, o))->vmFlags() + & HasFinalizerFlag); +} + +void clearTargetIfFinalizable(Thread* t, GcJreference* r) +{ + if (isFinalizable(t, t->m->heap->follow(r->target()))) { + r->target() = 0; + } +} + +void postVisit(Thread* t, Heap::Visitor* v) +{ + Machine* m = t->m; + bool major = m->heap->collectionType() == Heap::MajorCollection; + + assertT(t, m->finalizeQueue == 0); + + m->heap->postVisit(); + + for (GcJreference* p = m->weakReferences; p;) { + GcJreference* r = m->heap->follow(p); + p = cast(t, r->vmNext()); + clearTargetIfFinalizable(t, r); + } + + if (major) { + for (GcJreference* p = m->tenuredWeakReferences; p;) { + GcJreference* r = m->heap->follow(p); + p = cast(t, r->vmNext()); + clearTargetIfFinalizable(t, r); + } + } + + for (Reference* r = m->jniReferences; r; r = r->next) { + if (r->weak + and isFinalizable(t, + static_cast(t->m->heap->follow(r->target)))) { + r->target = 0; + } + } + + GcFinalizer* firstNewTenuredFinalizer = 0; + GcFinalizer* lastNewTenuredFinalizer = 0; + + { + object unreachable = 0; + for (GcFinalizer** p = &(m->finalizers); *p;) { + v->visit(p); + + if (m->heap->status((*p)->target()) == Heap::Unreachable) { + GcFinalizer* finalizer = *p; + *p = cast(t, finalizer->next()); + + finalizer->next() = unreachable; + unreachable = finalizer; + } else { + p = reinterpret_cast(&(*p)->next()); + } + } + + for (GcFinalizer** p = &(m->finalizers); *p;) { + // target is reachable + v->visit(&(*p)->target()); + + if (m->heap->status(*p) == Heap::Tenured) { + // the finalizer is tenured, so we remove it from + // m->finalizers and later add it to m->tenuredFinalizers + + if (lastNewTenuredFinalizer == 0) { + lastNewTenuredFinalizer = *p; + } + + GcFinalizer* finalizer = *p; + *p = cast(t, finalizer->next()); + finalizer->next() = firstNewTenuredFinalizer; + firstNewTenuredFinalizer = finalizer; + } else { + p = reinterpret_cast(&(*p)->next()); + } + } + + for (object* p = &unreachable; *p;) { + // target is unreachable - queue it up for finalization + finalizerTargetUnreachable(t, v, reinterpret_cast(p)); + } + } + + GcJreference* firstNewTenuredWeakReference = 0; + GcJreference* lastNewTenuredWeakReference = 0; + + for (GcJreference** p = &(m->weakReferences); *p;) { + if (m->heap->status(*p) == Heap::Unreachable) { + // reference is unreachable + referenceUnreachable(t, v, p); + } else if (m->heap->status(m->heap->follow(*p)->target()) + == Heap::Unreachable) { + // target is unreachable + referenceTargetUnreachable(t, v, p); + } else { + // both reference and target are reachable + referenceTargetReachable(t, v, p); + + if (m->heap->status(*p) == Heap::Tenured) { + // the reference is tenured, so we remove it from + // m->weakReferences and later add it to + // m->tenuredWeakReferences + + if (lastNewTenuredWeakReference == 0) { + lastNewTenuredWeakReference = *p; + } + + GcJreference* reference = (*p); + *p = cast(t, reference->vmNext()); + reference->vmNext() = firstNewTenuredWeakReference; + firstNewTenuredWeakReference = reference; + } else { + p = reinterpret_cast(&(*p)->vmNext()); + } + } + } + + if (major) { + { + object unreachable = 0; + for (GcFinalizer** p = &(m->tenuredFinalizers); *p;) { + v->visit(p); + + if (m->heap->status((*p)->target()) == Heap::Unreachable) { + GcFinalizer* finalizer = *p; + *p = cast(t, finalizer->next()); + + finalizer->next() = unreachable; + unreachable = finalizer; + } else { + p = reinterpret_cast(&(*p)->next()); + } + } + + for (GcFinalizer** p = &(m->tenuredFinalizers); *p;) { + // target is reachable + v->visit(&(*p)->target()); + p = reinterpret_cast(&(*p)->next()); + } + + for (object* p = &unreachable; *p;) { + // target is unreachable - queue it up for finalization + finalizerTargetUnreachable(t, v, reinterpret_cast(p)); + } + } + + for (GcJreference** p = &(m->tenuredWeakReferences); *p;) { + if (m->heap->status(*p) == Heap::Unreachable) { + // reference is unreachable + referenceUnreachable(t, v, reinterpret_cast(p)); + } else if (m->heap->status(m->heap->follow(*p)->target()) + == Heap::Unreachable) { + // target is unreachable + referenceTargetUnreachable(t, v, reinterpret_cast(p)); + } else { + // both reference and target are reachable + referenceTargetReachable(t, v, reinterpret_cast(p)); + p = reinterpret_cast(&(*p)->vmNext()); + } + } + } + + if (lastNewTenuredFinalizer) { + lastNewTenuredFinalizer->next() = m->tenuredFinalizers; + m->tenuredFinalizers = firstNewTenuredFinalizer; + } + + if (lastNewTenuredWeakReference) { + lastNewTenuredWeakReference->vmNext() = m->tenuredWeakReferences; + m->tenuredWeakReferences = firstNewTenuredWeakReference; + } + + for (Reference* r = m->jniReferences; r; r = r->next) { + if (r->weak) { + if (m->heap->status(r->target) == Heap::Unreachable) { + r->target = 0; + } else { + v->visit(&(r->target)); + } + } + } +} + +void postCollect(Thread* t) +{ +#ifdef VM_STRESS + t->m->heap->free(t->defaultHeap, ThreadHeapSizeInBytes); + t->defaultHeap + = static_cast(t->m->heap->allocate(ThreadHeapSizeInBytes)); + memset(t->defaultHeap, 0, ThreadHeapSizeInBytes); +#endif + + if (t->heap == t->defaultHeap) { + memset(t->defaultHeap, 0, t->heapIndex * BytesPerWord); + } else { + memset(t->defaultHeap, 0, ThreadHeapSizeInBytes); + t->heap = t->defaultHeap; + } + + t->heapOffset = 0; + + if (t->m->heap->limitExceeded()) { + // if we're out of memory, pretend the thread-local heap is + // already full so we don't make things worse: + t->heapIndex = ThreadHeapSizeInWords; + } else { + t->heapIndex = 0; + } + + if (t->getFlags() & Thread::UseBackupHeapFlag) { + memset(t->backupHeap, 0, ThreadBackupHeapSizeInBytes); + + t->clearFlag(Thread::UseBackupHeapFlag); + t->backupHeapIndex = 0; + } + + for (Thread* c = t->child; c; c = c->peer) { + postCollect(c); + } +} + +uint64_t invoke(Thread* t, uintptr_t* arguments) +{ + GcMethod* m = cast(t, *reinterpret_cast(arguments[0])); + object o = *reinterpret_cast(arguments[1]); + + t->m->processor->invoke(t, m, o); + + return 1; +} + +void finalizeObject(Thread* t, object o, const char* name) +{ + for (GcClass* c = objectClass(t, o); c; c = c->super()) { + GcArray* mtable = cast(t, c->methodTable()); + for (unsigned i = 0; i < mtable->length(); ++i) { + GcMethod* m = cast(t, mtable->body()[i]); + + if (vm::strcmp(reinterpret_cast(name), + m->name()->body().begin()) == 0 + and vm::strcmp(reinterpret_cast("()V"), + m->spec()->body().begin()) == 0) { + PROTECT(t, m); + PROTECT(t, o); + + uintptr_t arguments[] = {reinterpret_cast(&m), + reinterpret_cast(&o)}; + + run(t, invoke, arguments); + + t->exception = 0; + return; + } + } + } + abort(t); +} + +unsigned readByte(AbstractStream& s, unsigned* value) +{ + if (*value == NoByte) { + return s.read1(); + } else { + unsigned r = *value; + *value = NoByte; + return r; + } +} + +GcCharArray* parseUtf8NonAscii(Thread* t, + AbstractStream& s, + GcByteArray* bytesSoFar, + unsigned byteCount, + unsigned sourceIndex, + unsigned byteA, + unsigned byteB) +{ + PROTECT(t, bytesSoFar); + + unsigned length = bytesSoFar->length() - 1; + GcCharArray* value = makeCharArray(t, length + 1); + + unsigned vi = 0; + for (; vi < byteCount; ++vi) { + value->body()[vi] = bytesSoFar->body()[vi]; + } + + for (unsigned si = sourceIndex; si < length; ++si) { + unsigned a = readByte(s, &byteA); + if (a & 0x80) { + if (a & 0x20) { + // 3 bytes + si += 2; + assertT(t, si < length); + unsigned b = readByte(s, &byteB); + unsigned c = s.read1(); + value->body()[vi++] = ((a & 0xf) << 12) | ((b & 0x3f) << 6) + | (c & 0x3f); + } else { + // 2 bytes + ++si; + assertT(t, si < length); + unsigned b = readByte(s, &byteB); + + if (a == 0xC0 and b == 0x80) { + value->body()[vi++] = 0; + } else { + value->body()[vi++] = ((a & 0x1f) << 6) | (b & 0x3f); + } + } + } else { + value->body()[vi++] = a; + } + } + + if (vi < length) { + PROTECT(t, value); + + GcCharArray* v = makeCharArray(t, vi + 1); + memcpy(v->body().begin(), value->body().begin(), vi * 2); + value = v; + } + + return value; +} + +object parseUtf8(Thread* t, AbstractStream& s, unsigned length) +{ + GcByteArray* value = makeByteArray(t, length + 1); + unsigned vi = 0; + for (unsigned si = 0; si < length; ++si) { + unsigned a = s.read1(); + if (a & 0x80) { + if (a & 0x20) { + // 3 bytes + return parseUtf8NonAscii(t, s, value, vi, si, a, NoByte); + } else { + // 2 bytes + unsigned b = s.read1(); + + if (a == 0xC0 and b == 0x80) { + ++si; + assertT(t, si < length); + value->body()[vi++] = 0; + } else { + return parseUtf8NonAscii(t, s, value, vi, si, a, b); + } + } + } else { + value->body()[vi++] = a; + } + } + + if (vi < length) { + PROTECT(t, value); + + GcByteArray* v = makeByteArray(t, vi + 1); + memcpy(v->body().begin(), value->body().begin(), vi); + value = v; + } + + return value; +} + +GcByteArray* makeByteArray(Thread* t, Stream& s, unsigned length) +{ + GcByteArray* value = makeByteArray(t, length + 1); + s.read(reinterpret_cast(value->body().begin()), length); + return value; +} + +void removeByteArray(Thread* t, object o) +{ + hashMapRemove(t, roots(t)->byteArrayMap(), o, byteArrayHash, objectEqual); +} + +GcByteArray* internByteArray(Thread* t, GcByteArray* array) +{ + PROTECT(t, array); + + ACQUIRE(t, t->m->referenceLock); + + GcTriple* n = hashMapFindNode( + t, roots(t)->byteArrayMap(), array, byteArrayHash, byteArrayEqual); + if (n) { + return cast(t, cast(t, n->first())->target()); + } else { + hashMapInsert(t, roots(t)->byteArrayMap(), array, 0, byteArrayHash); + addFinalizer(t, array, removeByteArray); + return array; + } +} + +unsigned parsePoolEntry(Thread* t, + Stream& s, + uint32_t* index, + GcSingleton* pool, + unsigned i) +{ + PROTECT(t, pool); + + s.setPosition(index[i]); + + switch (s.read1()) { + case CONSTANT_Integer: + case CONSTANT_Float: { + uint32_t v = s.read4(); + singletonValue(t, pool, i) = v; + + if (DebugClassReader) { + fprintf(stderr, " consts[%d] = int/float 0x%x\n", i, v); + } + } + return 1; + + case CONSTANT_Long: + case CONSTANT_Double: { + uint64_t v = s.read8(); + memcpy(&singletonValue(t, pool, i), &v, 8); + + if (DebugClassReader) { + fprintf(stderr, " consts[%d] = long/double \n", i); + } + } + return 2; + + case CONSTANT_Utf8: { + if (singletonObject(t, pool, i) == 0) { + GcByteArray* value = internByteArray(t, makeByteArray(t, s, s.read2())); + pool->setBodyElement(t, i, reinterpret_cast(value)); + + if (DebugClassReader) { + fprintf(stderr, " consts[%d] = utf8 %s\n", i, value->body().begin()); + } + } + } + return 1; + + case CONSTANT_Class: { + if (singletonObject(t, pool, i) == 0) { + unsigned si = s.read2() - 1; + parsePoolEntry(t, s, index, pool, si); + + GcReference* value = makeReference( + t, 0, 0, cast(t, singletonObject(t, pool, si)), 0); + pool->setBodyElement(t, i, reinterpret_cast(value)); + + if (DebugClassReader) { + fprintf(stderr, " consts[%d] = class \n", i); + } + } + } + return 1; + + case CONSTANT_String: { + if (singletonObject(t, pool, i) == 0) { + unsigned si = s.read2() - 1; + parsePoolEntry(t, s, index, pool, si); + + object value + = parseUtf8(t, cast(t, singletonObject(t, pool, si))); + value = t->m->classpath->makeString( + t, value, 0, fieldAtOffset(value, BytesPerWord) - 1); + value = intern(t, value); + pool->setBodyElement(t, i, reinterpret_cast(value)); + + if (DebugClassReader) { + fprintf(stderr, " consts[%d] = string \n", i); + } + } + } + return 1; + + case CONSTANT_NameAndType: { + if (singletonObject(t, pool, i) == 0) { + unsigned ni = s.read2() - 1; + unsigned ti = s.read2() - 1; + + parsePoolEntry(t, s, index, pool, ni); + parsePoolEntry(t, s, index, pool, ti); + + GcByteArray* name = cast(t, singletonObject(t, pool, ni)); + GcByteArray* type = cast(t, singletonObject(t, pool, ti)); + GcPair* value = makePair(t, name, type); + pool->setBodyElement(t, i, reinterpret_cast(value)); + + if (DebugClassReader) { + fprintf(stderr, + " consts[%d] = nameAndType %s%s\n", + i, + name->body().begin(), + type->body().begin()); + } + } + } + return 1; + + case CONSTANT_Fieldref: + case CONSTANT_Methodref: + case CONSTANT_InterfaceMethodref: { + if (singletonObject(t, pool, i) == 0) { + unsigned ci = s.read2() - 1; + unsigned nti = s.read2() - 1; + + parsePoolEntry(t, s, index, pool, ci); + parsePoolEntry(t, s, index, pool, nti); + + GcByteArray* className + = cast(t, singletonObject(t, pool, ci))->name(); + GcPair* nameAndType = cast(t, singletonObject(t, pool, nti)); + + object value = makeReference(t, + 0, + className, + cast(t, nameAndType->first()), + cast(t, nameAndType->second())); + pool->setBodyElement(t, i, reinterpret_cast(value)); + + if (DebugClassReader) { + fprintf(stderr, + " consts[%d] = method %s.%s%s\n", + i, + className->body().begin(), + cast(t, nameAndType->first())->body().begin(), + cast(t, nameAndType->second())->body().begin()); + } + } + } + return 1; + + case CONSTANT_MethodHandle: + if (singletonObject(t, pool, i) == 0) { + unsigned kind = s.read1(); + unsigned ri = s.read2() - 1; + + parsePoolEntry(t, s, index, pool, ri); + + GcReference* value = cast(t, singletonObject(t, pool, ri)); + + if (DebugClassReader) { + fprintf(stderr, + " consts[%d] = method handle %d %s.%s%s\n", + i, + kind, + value->class_()->body().begin(), + value->name()->body().begin(), + value->spec()->body().begin()); + } + + value = makeReference( + t, kind, value->class_(), value->name(), value->spec()); + + pool->setBodyElement(t, i, reinterpret_cast(value)); + } + return 1; + + case CONSTANT_MethodType: + if (singletonObject(t, pool, i) == 0) { + unsigned ni = s.read2() - 1; + + parsePoolEntry(t, s, index, pool, ni); + + pool->setBodyElement( + t, i, reinterpret_cast(singletonObject(t, pool, ni))); + } + return 1; + + case CONSTANT_InvokeDynamic: + if (singletonObject(t, pool, i) == 0) { + unsigned bootstrap = s.read2(); + unsigned nti = s.read2() - 1; + + parsePoolEntry(t, s, index, pool, nti); + + GcPair* nameAndType = cast(t, singletonObject(t, pool, nti)); + + const char* specString = reinterpret_cast( + cast(t, nameAndType->second())->body().begin()); + + unsigned parameterCount; + unsigned parameterFootprint; + unsigned returnCode; + scanMethodSpec(t, + specString, + true, + ¶meterCount, + ¶meterFootprint, + &returnCode); + + GcMethod* template_ + = makeMethod(t, + 0, + returnCode, + parameterCount, + parameterFootprint, + ACC_STATIC, + 0, + 0, + 0, + cast(t, nameAndType->first()), + cast(t, nameAndType->second()), + 0, + 0, + 0); + + object value = reinterpret_cast( + makeInvocation(t, bootstrap, -1, 0, pool, template_, 0)); + + pool->setBodyElement(t, i, reinterpret_cast(value)); + } + return 1; + + default: + abort(t); + } +} + +GcSingleton* parsePool(Thread* t, Stream& s) +{ + unsigned count = s.read2() - 1; + GcSingleton* pool = makeSingletonOfSize(t, count + poolMaskSize(count)); + PROTECT(t, pool); + + if (DebugClassReader) { + fprintf(stderr, " const pool entries %d\n", count); + } + + if (count) { + uint32_t* index = static_cast(t->m->heap->allocate(count * 4)); + + THREAD_RESOURCE2(t, + uint32_t*, + index, + unsigned, + count, + t->m->heap->free(index, count * 4)); + + for (unsigned i = 0; i < count; ++i) { + index[i] = s.position(); + + switch (s.read1()) { + case CONSTANT_Class: + case CONSTANT_String: + singletonMarkObject(t, pool, i); + s.skip(2); + break; + + case CONSTANT_Integer: + s.skip(4); + break; + + case CONSTANT_Float: + singletonSetBit(t, pool, count, i); + s.skip(4); + break; + + case CONSTANT_NameAndType: + case CONSTANT_Fieldref: + case CONSTANT_Methodref: + case CONSTANT_InterfaceMethodref: + singletonMarkObject(t, pool, i); + s.skip(4); + break; + + case CONSTANT_Long: + s.skip(8); + ++i; + break; + + case CONSTANT_Double: + singletonSetBit(t, pool, count, i); + singletonSetBit(t, pool, count, i + 1); + s.skip(8); + ++i; + break; + + case CONSTANT_Utf8: + singletonMarkObject(t, pool, i); + s.skip(s.read2()); + break; + + case CONSTANT_MethodHandle: + singletonMarkObject(t, pool, i); + s.skip(3); + break; + + case CONSTANT_MethodType: + singletonMarkObject(t, pool, i); + s.skip(2); + break; + + case CONSTANT_InvokeDynamic: + singletonMarkObject(t, pool, i); + s.skip(4); + break; + + default: + abort(t); + } + } + + unsigned end = s.position(); + + for (unsigned i = 0; i < count;) { + i += parsePoolEntry(t, s, index, pool, i); + } + + s.setPosition(end); + } + + return pool; +} + +void addInterfaces(Thread* t, GcClass* class_, GcHashMap* map) +{ + GcArray* table = cast(t, class_->interfaceTable()); + if (table) { + unsigned increment = 2; + if (class_->flags() & ACC_INTERFACE) { + increment = 1; + } + + PROTECT(t, map); + PROTECT(t, table); + + for (unsigned i = 0; i < table->length(); i += increment) { + GcClass* interface = cast(t, table->body()[i]); + GcByteArray* name = interface->name(); + hashMapInsertMaybe( + t, map, name, interface, byteArrayHash, byteArrayEqual); + } + } +} + +GcClassAddendum* getClassAddendum(Thread* t, GcClass* class_, GcSingleton* pool) +{ + GcClassAddendum* addendum = class_->addendum(); + if (addendum == 0) { + PROTECT(t, class_); + + addendum = makeClassAddendum(t, pool, 0, 0, 0, 0, -1, 0, 0, 0, 0); + setField(t, class_, ClassAddendum, addendum); + } + return addendum; +} + +void parseInterfaceTable(Thread* t, + Stream& s, + GcClass* class_, + GcSingleton* pool, + Gc::Type throwType) +{ + PROTECT(t, class_); + PROTECT(t, pool); + + GcHashMap* map = makeHashMap(t, 0, 0); + PROTECT(t, map); + + if (class_->super()) { + addInterfaces(t, class_->super(), map); + } + + unsigned count = s.read2(); + GcArray* table = 0; + PROTECT(t, table); + + if (count) { + table = makeArray(t, count); + + GcClassAddendum* addendum = getClassAddendum(t, class_, pool); + addendum->setInterfaceTable(t, table); + } + + for (unsigned i = 0; i < count; ++i) { + GcByteArray* name + = cast(t, singletonObject(t, pool, s.read2() - 1))->name(); + PROTECT(t, name); + + GcClass* interface = resolveClass( + t, class_->loader(), name, true, throwType); + + PROTECT(t, interface); + + table->setBodyElement(t, i, interface); + + hashMapInsertMaybe(t, map, name, interface, byteArrayHash, byteArrayEqual); + + addInterfaces(t, interface, map); + } + + GcArray* interfaceTable = 0; + if (map->size()) { + unsigned length = map->size(); + if ((class_->flags() & ACC_INTERFACE) == 0) { + length *= 2; + } + interfaceTable = makeArray(t, length); + PROTECT(t, interfaceTable); + + unsigned i = 0; + for (HashMapIterator it(t, map); it.hasMore();) { + GcClass* interface = cast(t, it.next()->second()); + + interfaceTable->setBodyElement(t, i, interface); + ++i; + + if ((class_->flags() & ACC_INTERFACE) == 0) { + if (GcArray* vt = cast(t, interface->virtualTable())) { + PROTECT(t, vt); + // we'll fill in this table in parseMethodTable(): + GcArray* vtable = makeArray(t, vt->length()); + + interfaceTable->setBodyElement(t, i, vtable); + } + + ++i; + } + } + } + + class_->setInterfaceTable(t, interfaceTable); +} + +void parseFieldTable(Thread* t, Stream& s, GcClass* class_, GcSingleton* pool) +{ + PROTECT(t, class_); + PROTECT(t, pool); + + unsigned memberOffset = BytesPerWord; + if (class_->super()) { + memberOffset = class_->super()->fixedSize(); + } + + unsigned count = s.read2(); + if (count) { + unsigned staticOffset = BytesPerWord * 3; + unsigned staticCount = 0; + + GcArray* fieldTable = makeArray(t, count); + PROTECT(t, fieldTable); + + GcIntArray* staticValueTable = makeIntArray(t, count); + PROTECT(t, staticValueTable); + + GcFieldAddendum* addendum = 0; + PROTECT(t, addendum); + + THREAD_RUNTIME_ARRAY(t, uint8_t, staticTypes, count); + + for (unsigned i = 0; i < count; ++i) { + unsigned flags = s.read2(); + unsigned name = s.read2(); + unsigned spec = s.read2(); + + unsigned value = 0; + + addendum = 0; + + unsigned code = fieldCode( + t, + cast(t, singletonObject(t, pool, spec - 1))->body()[0]); + + unsigned attributeCount = s.read2(); + for (unsigned j = 0; j < attributeCount; ++j) { + GcByteArray* name + = cast(t, singletonObject(t, pool, s.read2() - 1)); + unsigned length = s.read4(); + + if (vm::strcmp(reinterpret_cast("ConstantValue"), + name->body().begin()) == 0) { + value = s.read2(); + } else if (vm::strcmp(reinterpret_cast("Signature"), + name->body().begin()) == 0) { + if (addendum == 0) { + addendum = makeFieldAddendum(t, pool, 0, 0); + } + + addendum->setSignature(t, singletonObject(t, pool, s.read2() - 1)); + } else if (vm::strcmp(reinterpret_cast( + "RuntimeVisibleAnnotations"), + name->body().begin()) == 0) { + if (addendum == 0) { + addendum = makeFieldAddendum(t, pool, 0, 0); + } + + GcByteArray* body = makeByteArray(t, length); + s.read(reinterpret_cast(body->body().begin()), length); + + addendum->setAnnotationTable(t, body); + } else { + s.skip(length); + } + } + + GcField* field + = makeField(t, + 0, // vm flags + code, + flags, + 0, // offset + 0, // native ID + cast(t, singletonObject(t, pool, name - 1)), + cast(t, singletonObject(t, pool, spec - 1)), + addendum, + class_); + + unsigned size = fieldSize(t, code); + if (flags & ACC_STATIC) { + staticOffset = pad(staticOffset, size); + + field->offset() = staticOffset; + + staticOffset += size; + + staticValueTable->body()[staticCount] = value; + + RUNTIME_ARRAY_BODY(staticTypes)[staticCount++] = code; + } else { + if (flags & ACC_FINAL) { + class_->vmFlags() |= HasFinalMemberFlag; + } + + memberOffset = pad(memberOffset, size); + + field->offset() = memberOffset; + + memberOffset += size; + } + + fieldTable->setBodyElement(t, i, field); + } + + class_->setFieldTable(t, fieldTable); + + if (staticCount) { + unsigned footprint + = ceilingDivide(staticOffset - (BytesPerWord * 2), BytesPerWord); + GcSingleton* staticTable = makeSingletonOfSize(t, footprint); + + uint8_t* body = reinterpret_cast(staticTable->body().begin()); + + memcpy(body, &class_, BytesPerWord); + singletonMarkObject(t, staticTable, 0); + + for (unsigned i = 0, offset = BytesPerWord; i < staticCount; ++i) { + unsigned size = fieldSize(t, RUNTIME_ARRAY_BODY(staticTypes)[i]); + offset = pad(offset, size); + + unsigned value = staticValueTable->body()[i]; + if (value) { + switch (RUNTIME_ARRAY_BODY(staticTypes)[i]) { + case ByteField: + case BooleanField: + body[offset] = singletonValue(t, pool, value - 1); + break; + + case CharField: + case ShortField: + *reinterpret_cast(body + offset) + = singletonValue(t, pool, value - 1); + break; + + case IntField: + case FloatField: + *reinterpret_cast(body + offset) + = singletonValue(t, pool, value - 1); + break; + + case LongField: + case DoubleField: + memcpy(body + offset, &singletonValue(t, pool, value - 1), 8); + break; + + case ObjectField: + memcpy(body + offset, + &singletonObject(t, pool, value - 1), + BytesPerWord); + break; + + default: + abort(t); + } + } + + if (RUNTIME_ARRAY_BODY(staticTypes)[i] == ObjectField) { + singletonMarkObject(t, staticTable, offset / BytesPerWord); + } + + offset += size; + } + + class_->setStaticTable(t, staticTable); + } + } + + class_->fixedSize() = memberOffset; + + if (class_->super() and memberOffset == class_->super()->fixedSize()) { + class_->setObjectMask(t, class_->super()->objectMask()); + } else { + GcIntArray* mask = makeIntArray( + t, ceilingDivide(class_->fixedSize(), 32 * BytesPerWord)); + mask->body()[0] = 1; + + GcIntArray* superMask = 0; + if (class_->super()) { + superMask = class_->super()->objectMask(); + if (superMask) { + memcpy( + mask->body().begin(), + superMask->body().begin(), + ceilingDivide(class_->super()->fixedSize(), 32 * BytesPerWord) * 4); + } + } + + bool sawReferenceField = false; + GcArray* fieldTable = cast(t, class_->fieldTable()); + if (fieldTable) { + for (int i = fieldTable->length() - 1; i >= 0; --i) { + GcField* field = cast(t, fieldTable->body()[i]); + if ((field->flags() & ACC_STATIC) == 0 + and field->code() == ObjectField) { + unsigned index = field->offset() / BytesPerWord; + mask->body()[index / 32] |= 1 << (index % 32); + sawReferenceField = true; + } + } + } + + if (superMask or sawReferenceField) { + class_->setObjectMask(t, mask); + } + } +} + +uint16_t read16(uint8_t* code, unsigned& ip) +{ + uint16_t a = code[ip++]; + uint16_t b = code[ip++]; + return (a << 8) | b; +} + +uint32_t read32(uint8_t* code, unsigned& ip) +{ + uint32_t b = code[ip++]; + uint32_t a = code[ip++]; + uint32_t c = code[ip++]; + uint32_t d = code[ip++]; + return (a << 24) | (b << 16) | (c << 8) | d; +} + +void disassembleCode(const char* prefix, uint8_t* code, unsigned length) +{ + unsigned ip = 0; + + while (ip < length) { + unsigned instr; + fprintf(stderr, "%s%x:\t", prefix, ip); + switch (instr = code[ip++]) { + case aaload: + fprintf(stderr, "aaload\n"); + break; + case aastore: + fprintf(stderr, "aastore\n"); + break; + + case aconst_null: + fprintf(stderr, "aconst_null\n"); + break; + + case aload: + fprintf(stderr, "aload %02x\n", code[ip++]); + break; + case aload_0: + fprintf(stderr, "aload_0\n"); + break; + case aload_1: + fprintf(stderr, "aload_1\n"); + break; + case aload_2: + fprintf(stderr, "aload_2\n"); + break; + case aload_3: + fprintf(stderr, "aload_3\n"); + break; + + case anewarray: + fprintf(stderr, "anewarray %04x\n", read16(code, ip)); + break; + case areturn: + fprintf(stderr, "areturn\n"); + break; + case arraylength: + fprintf(stderr, "arraylength\n"); + break; + + case astore: + fprintf(stderr, "astore %02x\n", code[ip++]); + break; + case astore_0: + fprintf(stderr, "astore_0\n"); + break; + case astore_1: + fprintf(stderr, "astore_1\n"); + break; + case astore_2: + fprintf(stderr, "astore_2\n"); + break; + case astore_3: + fprintf(stderr, "astore_3\n"); + break; + + case athrow: + fprintf(stderr, "athrow\n"); + break; + case baload: + fprintf(stderr, "baload\n"); + break; + case bastore: + fprintf(stderr, "bastore\n"); + break; + + case bipush: + fprintf(stderr, "bipush %02x\n", code[ip++]); + break; + case caload: + fprintf(stderr, "caload\n"); + break; + case castore: + fprintf(stderr, "castore\n"); + break; + case checkcast: + fprintf(stderr, "checkcast %04x\n", read16(code, ip)); + break; + case d2f: + fprintf(stderr, "d2f\n"); + break; + case d2i: + fprintf(stderr, "d2i\n"); + break; + case d2l: + fprintf(stderr, "d2l\n"); + break; + case dadd: + fprintf(stderr, "dadd\n"); + break; + case daload: + fprintf(stderr, "daload\n"); + break; + case dastore: + fprintf(stderr, "dastore\n"); + break; + case dcmpg: + fprintf(stderr, "dcmpg\n"); + break; + case dcmpl: + fprintf(stderr, "dcmpl\n"); + break; + case dconst_0: + fprintf(stderr, "dconst_0\n"); + break; + case dconst_1: + fprintf(stderr, "dconst_1\n"); + break; + case ddiv: + fprintf(stderr, "ddiv\n"); + break; + case dmul: + fprintf(stderr, "dmul\n"); + break; + case dneg: + fprintf(stderr, "dneg\n"); + break; + case vm::drem: + fprintf(stderr, "drem\n"); + break; + case dsub: + fprintf(stderr, "dsub\n"); + break; + case vm::dup: + fprintf(stderr, "dup\n"); + break; + case dup_x1: + fprintf(stderr, "dup_x1\n"); + break; + case dup_x2: + fprintf(stderr, "dup_x2\n"); + break; + case vm::dup2: + fprintf(stderr, "dup2\n"); + break; + case dup2_x1: + fprintf(stderr, "dup2_x1\n"); + break; + case dup2_x2: + fprintf(stderr, "dup2_x2\n"); + break; + case f2d: + fprintf(stderr, "f2d\n"); + break; + case f2i: + fprintf(stderr, "f2i\n"); + break; + case f2l: + fprintf(stderr, "f2l\n"); + break; + case fadd: + fprintf(stderr, "fadd\n"); + break; + case faload: + fprintf(stderr, "faload\n"); + break; + case fastore: + fprintf(stderr, "fastore\n"); + break; + case fcmpg: + fprintf(stderr, "fcmpg\n"); + break; + case fcmpl: + fprintf(stderr, "fcmpl\n"); + break; + case fconst_0: + fprintf(stderr, "fconst_0\n"); + break; + case fconst_1: + fprintf(stderr, "fconst_1\n"); + break; + case fconst_2: + fprintf(stderr, "fconst_2\n"); + break; + case fdiv: + fprintf(stderr, "fdiv\n"); + break; + case fmul: + fprintf(stderr, "fmul\n"); + break; + case fneg: + fprintf(stderr, "fneg\n"); + break; + case frem: + fprintf(stderr, "frem\n"); + break; + case fsub: + fprintf(stderr, "fsub\n"); + break; + + case getfield: + fprintf(stderr, "getfield %04x\n", read16(code, ip)); + break; + case getstatic: + fprintf(stderr, "getstatic %04x\n", read16(code, ip)); + break; + case goto_: { + int16_t offset = read16(code, ip); + fprintf(stderr, "goto %04x\n", offset + ip - 3); + } break; + case goto_w: { + int32_t offset = read32(code, ip); + fprintf(stderr, "goto_w %08x\n", offset + ip - 5); + } break; + + case i2b: + fprintf(stderr, "i2b\n"); + break; + case i2c: + fprintf(stderr, "i2c\n"); + break; + case i2d: + fprintf(stderr, "i2d\n"); + break; + case i2f: + fprintf(stderr, "i2f\n"); + break; + case i2l: + fprintf(stderr, "i2l\n"); + break; + case i2s: + fprintf(stderr, "i2s\n"); + break; + case iadd: + fprintf(stderr, "iadd\n"); + break; + case iaload: + fprintf(stderr, "iaload\n"); + break; + case iand: + fprintf(stderr, "iand\n"); + break; + case iastore: + fprintf(stderr, "iastore\n"); + break; + case iconst_m1: + fprintf(stderr, "iconst_m1\n"); + break; + case iconst_0: + fprintf(stderr, "iconst_0\n"); + break; + case iconst_1: + fprintf(stderr, "iconst_1\n"); + break; + case iconst_2: + fprintf(stderr, "iconst_2\n"); + break; + case iconst_3: + fprintf(stderr, "iconst_3\n"); + break; + case iconst_4: + fprintf(stderr, "iconst_4\n"); + break; + case iconst_5: + fprintf(stderr, "iconst_5\n"); + break; + case idiv: + fprintf(stderr, "idiv\n"); + break; + + case if_acmpeq: { + int16_t offset = read16(code, ip); + fprintf(stderr, "if_acmpeq %04x\n", offset + ip - 3); + } break; + case if_acmpne: { + int16_t offset = read16(code, ip); + fprintf(stderr, "if_acmpne %04x\n", offset + ip - 3); + } break; + case if_icmpeq: { + int16_t offset = read16(code, ip); + fprintf(stderr, "if_icmpeq %04x\n", offset + ip - 3); + } break; + case if_icmpne: { + int16_t offset = read16(code, ip); + fprintf(stderr, "if_icmpne %04x\n", offset + ip - 3); + } break; + + case if_icmpgt: { + int16_t offset = read16(code, ip); + fprintf(stderr, "if_icmpgt %04x\n", offset + ip - 3); + } break; + case if_icmpge: { + int16_t offset = read16(code, ip); + fprintf(stderr, "if_icmpge %04x\n", offset + ip - 3); + } break; + case if_icmplt: { + int16_t offset = read16(code, ip); + fprintf(stderr, "if_icmplt %04x\n", offset + ip - 3); + } break; + case if_icmple: { + int16_t offset = read16(code, ip); + fprintf(stderr, "if_icmple %04x\n", offset + ip - 3); + } break; + + case ifeq: { + int16_t offset = read16(code, ip); + fprintf(stderr, "ifeq %04x\n", offset + ip - 3); + } break; + case ifne: { + int16_t offset = read16(code, ip); + fprintf(stderr, "ifne %04x\n", offset + ip - 3); + } break; + case ifgt: { + int16_t offset = read16(code, ip); + fprintf(stderr, "ifgt %04x\n", offset + ip - 3); + } break; + case ifge: { + int16_t offset = read16(code, ip); + fprintf(stderr, "ifge %04x\n", offset + ip - 3); + } break; + case iflt: { + int16_t offset = read16(code, ip); + fprintf(stderr, "iflt %04x\n", offset + ip - 3); + } break; + case ifle: { + int16_t offset = read16(code, ip); + fprintf(stderr, "ifle %04x\n", offset + ip - 3); + } break; + + case ifnonnull: { + int16_t offset = read16(code, ip); + fprintf(stderr, "ifnonnull %04x\n", offset + ip - 3); + } break; + case ifnull: { + int16_t offset = read16(code, ip); + fprintf(stderr, "ifnull %04x\n", offset + ip - 3); + } break; + + case iinc: { + uint8_t a = code[ip++]; + uint8_t b = code[ip++]; + fprintf(stderr, "iinc %02x %02x\n", a, b); + } break; + + case iload: + fprintf(stderr, "iload %02x\n", code[ip++]); + break; + case fload: + fprintf(stderr, "fload %02x\n", code[ip++]); + break; + + case iload_0: + fprintf(stderr, "iload_0\n"); + break; + case fload_0: + fprintf(stderr, "fload_0\n"); + break; + case iload_1: + fprintf(stderr, "iload_1\n"); + break; + case fload_1: + fprintf(stderr, "fload_1\n"); + break; + + case iload_2: + fprintf(stderr, "iload_2\n"); + break; + case fload_2: + fprintf(stderr, "fload_2\n"); + break; + case iload_3: + fprintf(stderr, "iload_3\n"); + break; + case fload_3: + fprintf(stderr, "fload_3\n"); + break; + + case imul: + fprintf(stderr, "imul\n"); + break; + case ineg: + fprintf(stderr, "ineg\n"); + break; + + case instanceof: + fprintf(stderr, "instanceof %04x\n", read16(code, ip)); + break; + case invokeinterface: + fprintf(stderr, "invokeinterface %04x\n", read16(code, ip)); + break; + case invokespecial: + fprintf(stderr, "invokespecial %04x\n", read16(code, ip)); + break; + case invokestatic: + fprintf(stderr, "invokestatic %04x\n", read16(code, ip)); + break; + case invokevirtual: + fprintf(stderr, "invokevirtual %04x\n", read16(code, ip)); + break; + + case ior: + fprintf(stderr, "ior\n"); + break; + case irem: + fprintf(stderr, "irem\n"); + break; + case ireturn: + fprintf(stderr, "ireturn\n"); + break; + case freturn: + fprintf(stderr, "freturn\n"); + break; + case ishl: + fprintf(stderr, "ishl\n"); + break; + case ishr: + fprintf(stderr, "ishr\n"); + break; + + case istore: + fprintf(stderr, "istore %02x\n", code[ip++]); + break; + case fstore: + fprintf(stderr, "fstore %02x\n", code[ip++]); + break; + + case istore_0: + fprintf(stderr, "istore_0\n"); + break; + case fstore_0: + fprintf(stderr, "fstore_0\n"); + break; + case istore_1: + fprintf(stderr, "istore_1\n"); + break; + case fstore_1: + fprintf(stderr, "fstore_1\n"); + break; + case istore_2: + fprintf(stderr, "istore_2\n"); + break; + case fstore_2: + fprintf(stderr, "fstore_2\n"); + break; + case istore_3: + fprintf(stderr, "istore_3\n"); + break; + case fstore_3: + fprintf(stderr, "fstore_3\n"); + break; + + case isub: + fprintf(stderr, "isub\n"); + break; + case iushr: + fprintf(stderr, "iushr\n"); + break; + case ixor: + fprintf(stderr, "ixor\n"); + break; + + case jsr: + fprintf(stderr, "jsr %04x\n", read16(code, ip)); + break; + case jsr_w: + fprintf(stderr, "jsr_w %08x\n", read32(code, ip)); + break; + + case l2d: + fprintf(stderr, "l2d\n"); + break; + case l2f: + fprintf(stderr, "l2f\n"); + break; + case l2i: + fprintf(stderr, "l2i\n"); + break; + case ladd: + fprintf(stderr, "ladd\n"); + break; + case laload: + fprintf(stderr, "laload\n"); + break; + + case land: + fprintf(stderr, "land\n"); + break; + case lastore: + fprintf(stderr, "lastore\n"); + break; + + case lcmp: + fprintf(stderr, "lcmp\n"); + break; + case lconst_0: + fprintf(stderr, "lconst_0\n"); + break; + case lconst_1: + fprintf(stderr, "lconst_1\n"); + break; + + case ldc: + fprintf(stderr, "ldc %04x\n", read16(code, ip)); + break; + case ldc_w: + fprintf(stderr, "ldc_w %08x\n", read32(code, ip)); + break; + case ldc2_w: + fprintf(stderr, "ldc2_w %04x\n", read16(code, ip)); + break; + + case ldiv_: + fprintf(stderr, "ldiv_\n"); + break; + + case lload: + fprintf(stderr, "lload %02x\n", code[ip++]); + break; + case dload: + fprintf(stderr, "dload %02x\n", code[ip++]); + break; + + case lload_0: + fprintf(stderr, "lload_0\n"); + break; + case dload_0: + fprintf(stderr, "dload_0\n"); + break; + case lload_1: + fprintf(stderr, "lload_1\n"); + break; + case dload_1: + fprintf(stderr, "dload_1\n"); + break; + case lload_2: + fprintf(stderr, "lload_2\n"); + break; + case dload_2: + fprintf(stderr, "dload_2\n"); + break; + case lload_3: + fprintf(stderr, "lload_3\n"); + break; + case dload_3: + fprintf(stderr, "dload_3\n"); + break; + + case lmul: + fprintf(stderr, "lmul\n"); + break; + case lneg: + fprintf(stderr, "lneg\n"); + break; + + case lookupswitch: { + int32_t default_ = read32(code, ip); + int32_t pairCount = read32(code, ip); + fprintf(stderr, + "lookupswitch default: %d pairCount: %d\n", + default_, + pairCount); + + for (int i = 0; i < pairCount; i++) { + int32_t k = read32(code, ip); + int32_t d = read32(code, ip); + fprintf(stderr, "%s key: %02x dest: %2x\n", prefix, k, d); + } + } break; + + case lor: + fprintf(stderr, "lor\n"); + break; + case lrem: + fprintf(stderr, "lrem\n"); + break; + case lreturn: + fprintf(stderr, "lreturn\n"); + break; + case dreturn: + fprintf(stderr, "dreturn\n"); + break; + case lshl: + fprintf(stderr, "lshl\n"); + break; + case lshr: + fprintf(stderr, "lshr\n"); + break; + + case lstore: + fprintf(stderr, "lstore %02x\n", code[ip++]); + break; + case dstore: + fprintf(stderr, "dstore %02x\n", code[ip++]); + break; + + case lstore_0: + fprintf(stderr, "lstore_0\n"); + break; + case dstore_0: + fprintf(stderr, "dstore_0\n"); + break; + case lstore_1: + fprintf(stderr, "lstore_1\n"); + break; + case dstore_1: + fprintf(stderr, "dstore_1\n"); + break; + case lstore_2: + fprintf(stderr, "lstore_2\n"); + break; + case dstore_2: + fprintf(stderr, "dstore_2\n"); + break; + case lstore_3: + fprintf(stderr, "lstore_3\n"); + break; + case dstore_3: + fprintf(stderr, "dstore_3\n"); + break; + + case lsub: + fprintf(stderr, "lsub\n"); + break; + case lushr: + fprintf(stderr, "lushr\n"); + break; + case lxor: + fprintf(stderr, "lxor\n"); + break; + + case monitorenter: + fprintf(stderr, "monitorenter\n"); + break; + case monitorexit: + fprintf(stderr, "monitorexit\n"); + break; + + case multianewarray: { + unsigned type = read16(code, ip); + fprintf(stderr, "multianewarray %04x %02x\n", type, code[ip++]); + } break; + + case new_: + fprintf(stderr, "new %04x\n", read16(code, ip)); + break; + + case newarray: + fprintf(stderr, "newarray %02x\n", code[ip++]); + break; + + case nop: + fprintf(stderr, "nop\n"); + break; + case pop_: + fprintf(stderr, "pop\n"); + break; + case pop2: + fprintf(stderr, "pop2\n"); + break; + + case putfield: + fprintf(stderr, "putfield %04x\n", read16(code, ip)); + break; + case putstatic: + fprintf(stderr, "putstatic %04x\n", read16(code, ip)); + break; + + case ret: + fprintf(stderr, "ret %02x\n", code[ip++]); + break; + + case return_: + fprintf(stderr, "return_\n"); + break; + case saload: + fprintf(stderr, "saload\n"); + break; + case sastore: + fprintf(stderr, "sastore\n"); + break; + + case sipush: + fprintf(stderr, "sipush %04x\n", read16(code, ip)); + break; + + case swap: + fprintf(stderr, "swap\n"); + break; + + case tableswitch: { + int32_t default_ = read32(code, ip); + int32_t bottom = read32(code, ip); + int32_t top = read32(code, ip); + fprintf(stderr, + "tableswitch default: %d bottom: %d top: %d\n", + default_, + bottom, + top); + + for (int i = 0; i < top - bottom + 1; i++) { + int32_t d = read32(code, ip); + fprintf(stderr, "%s key: %d dest: %2x\n", prefix, i + bottom, d); + } + } break; + + case wide: { + switch (code[ip++]) { + case aload: + fprintf(stderr, "wide aload %04x\n", read16(code, ip)); + break; + + case astore: + fprintf(stderr, "wide astore %04x\n", read16(code, ip)); + break; + case iinc: + fprintf(stderr, + "wide iinc %04x %04x\n", + read16(code, ip), + read16(code, ip)); + break; + case iload: + fprintf(stderr, "wide iload %04x\n", read16(code, ip)); + break; + case istore: + fprintf(stderr, "wide istore %04x\n", read16(code, ip)); + break; + case lload: + fprintf(stderr, "wide lload %04x\n", read16(code, ip)); + break; + case lstore: + fprintf(stderr, "wide lstore %04x\n", read16(code, ip)); + break; + case ret: + fprintf(stderr, "wide ret %04x\n", read16(code, ip)); + break; + + default: { + fprintf(stderr, + "unknown wide instruction %02x %04x\n", + instr, + read16(code, ip)); + } + } + } break; + + default: { + fprintf(stderr, "unknown instruction %02x\n", instr); + } + } + } +} + +GcCode* parseCode(Thread* t, Stream& s, GcSingleton* pool) +{ + PROTECT(t, pool); + + unsigned maxStack = s.read2(); + unsigned maxLocals = s.read2(); + unsigned length = s.read4(); + + if (DebugClassReader) { + fprintf(stderr, + " code: maxStack %d maxLocals %d length %d\n", + maxStack, + maxLocals, + length); + } + + GcCode* code = makeCode(t, pool, 0, 0, 0, 0, 0, maxStack, maxLocals, length); + s.read(code->body().begin(), length); + PROTECT(t, code); + + if (DebugClassReader) { + disassembleCode(" ", code->body().begin(), length); + } + + unsigned ehtLength = s.read2(); + if (ehtLength) { + GcExceptionHandlerTable* eht = makeExceptionHandlerTable(t, ehtLength); + for (unsigned i = 0; i < ehtLength; ++i) { + unsigned start = s.read2(); + unsigned end = s.read2(); + unsigned ip = s.read2(); + unsigned catchType = s.read2(); + eht->body()[i] = exceptionHandler(start, end, ip, catchType); + } + + code->setExceptionHandlerTable(t, eht); + } + + unsigned attributeCount = s.read2(); + for (unsigned j = 0; j < attributeCount; ++j) { + GcByteArray* name + = cast(t, singletonObject(t, pool, s.read2() - 1)); + unsigned length = s.read4(); + + if (vm::strcmp(reinterpret_cast("LineNumberTable"), + name->body().begin()) == 0) { + unsigned lntLength = s.read2(); + GcLineNumberTable* lnt = makeLineNumberTable(t, lntLength); + for (unsigned i = 0; i < lntLength; ++i) { + unsigned ip = s.read2(); + unsigned line = s.read2(); + lnt->body()[i] = lineNumber(ip, line); + } + + code->setLineNumberTable(t, lnt); + } else { + s.skip(length); + } + } + + return code; +} + +GcList* addInterfaceMethods(Thread* t, + GcClass* class_, + GcHashMap* virtualMap, + unsigned* virtualCount, + bool makeList) +{ + GcArray* itable = cast(t, class_->interfaceTable()); + if (itable) { + PROTECT(t, class_); + PROTECT(t, virtualMap); + PROTECT(t, itable); + + GcList* list = 0; + PROTECT(t, list); + + GcMethod* method = 0; + PROTECT(t, method); + + GcArray* vtable = 0; + PROTECT(t, vtable); + + unsigned stride = (class_->flags() & ACC_INTERFACE) ? 1 : 2; + for (unsigned i = 0; i < itable->length(); i += stride) { + vtable = cast( + t, cast(t, itable->body()[i])->virtualTable()); + if (vtable) { + for (unsigned j = 0; j < vtable->length(); ++j) { + method = cast(t, vtable->body()[j]); + GcTriple* n + = hashMapFindNode(t, virtualMap, method, methodHash, methodEqual); + if (n == 0) { + method = makeMethod(t, + method->vmFlags(), + method->returnCode(), + method->parameterCount(), + method->parameterFootprint(), + method->flags(), + (*virtualCount)++, + 0, + 0, + method->name(), + method->spec(), + 0, + class_, + method->code()); + + hashMapInsert(t, virtualMap, method, method, methodHash); + + if (makeList) { + if (list == 0) { + list = vm::makeList(t, 0, 0, 0); + } + listAppend(t, list, method); + } + } + } + } + } + + return list; + } + + return 0; +} + +void parseMethodTable(Thread* t, Stream& s, GcClass* class_, GcSingleton* pool) +{ + PROTECT(t, class_); + PROTECT(t, pool); + + GcHashMap* virtualMap = makeHashMap(t, 0, 0); + PROTECT(t, virtualMap); + + unsigned virtualCount = 0; + unsigned declaredVirtualCount = 0; + + GcArray* superVirtualTable = 0; + PROTECT(t, superVirtualTable); + + if ((class_->flags() & ACC_INTERFACE) == 0) { + if (class_->super()) { + superVirtualTable = cast(t, class_->super()->virtualTable()); + } + + if (superVirtualTable) { + virtualCount = superVirtualTable->length(); + for (unsigned i = 0; i < virtualCount; ++i) { + object method = superVirtualTable->body()[i]; + hashMapInsert(t, virtualMap, method, method, methodHash); + } + } + } + + GcList* newVirtuals = makeList(t, 0, 0, 0); + PROTECT(t, newVirtuals); + + unsigned count = s.read2(); + + if (DebugClassReader) { + fprintf(stderr, " method count %d\n", count); + } + + if (count) { + GcArray* methodTable = makeArray(t, count); + PROTECT(t, methodTable); + + GcMethodAddendum* addendum = 0; + PROTECT(t, addendum); + + GcCode* code = 0; + PROTECT(t, code); + + for (unsigned i = 0; i < count; ++i) { + unsigned flags = s.read2(); + unsigned name = s.read2(); + unsigned spec = s.read2(); + + if (DebugClassReader) { + fprintf(stderr, + " method flags %d name %d spec %d '%s%s'\n", + flags, + name, + spec, + cast(t, singletonObject(t, pool, name - 1)) + ->body() + .begin(), + cast(t, singletonObject(t, pool, spec - 1)) + ->body() + .begin()); + } + + addendum = 0; + code = 0; + + unsigned attributeCount = s.read2(); + for (unsigned j = 0; j < attributeCount; ++j) { + GcByteArray* attributeName + = cast(t, singletonObject(t, pool, s.read2() - 1)); + unsigned length = s.read4(); + + if (vm::strcmp(reinterpret_cast("Code"), + attributeName->body().begin()) == 0) { + code = parseCode(t, s, pool); + } else if (vm::strcmp(reinterpret_cast("Exceptions"), + attributeName->body().begin()) == 0) { + if (addendum == 0) { + addendum = makeMethodAddendum(t, pool, 0, 0, 0, 0, 0); + } + unsigned exceptionCount = s.read2(); + GcShortArray* body = makeShortArray(t, exceptionCount); + for (unsigned i = 0; i < exceptionCount; ++i) { + body->body()[i] = s.read2(); + } + addendum->setExceptionTable(t, body); + } else if (vm::strcmp( + reinterpret_cast("AnnotationDefault"), + attributeName->body().begin()) == 0) { + if (addendum == 0) { + addendum = makeMethodAddendum(t, pool, 0, 0, 0, 0, 0); + } + + GcByteArray* body = makeByteArray(t, length); + s.read(reinterpret_cast(body->body().begin()), length); + + addendum->setAnnotationDefault(t, body); + } else if (vm::strcmp(reinterpret_cast("Signature"), + attributeName->body().begin()) == 0) { + if (addendum == 0) { + addendum = makeMethodAddendum(t, pool, 0, 0, 0, 0, 0); + } + + addendum->setSignature(t, singletonObject(t, pool, s.read2() - 1)); + } else if (vm::strcmp(reinterpret_cast( + "RuntimeVisibleAnnotations"), + attributeName->body().begin()) == 0) { + if (addendum == 0) { + addendum = makeMethodAddendum(t, pool, 0, 0, 0, 0, 0); + } + + GcByteArray* body = makeByteArray(t, length); + s.read(reinterpret_cast(body->body().begin()), length); + + addendum->setAnnotationTable(t, body); + } else if (vm::strcmp(reinterpret_cast( + "RuntimeVisibleParameterAnnotations"), + attributeName->body().begin()) == 0) { + if (addendum == 0) { + addendum = makeMethodAddendum(t, pool, 0, 0, 0, 0, 0); + } + + GcByteArray* body = makeByteArray(t, length); + s.read(reinterpret_cast(body->body().begin()), length); + + addendum->setParameterAnnotationTable(t, body); + } else { + s.skip(length); + } + } + + const char* specString = reinterpret_cast( + cast(t, singletonObject(t, pool, spec - 1)) + ->body() + .begin()); + + unsigned parameterCount; + unsigned parameterFootprint; + unsigned returnCode; + scanMethodSpec(t, + specString, + flags & ACC_STATIC, + ¶meterCount, + ¶meterFootprint, + &returnCode); + + GcMethod* method = t->m->processor->makeMethod( + t, + 0, // vm flags + returnCode, + parameterCount, + parameterFootprint, + flags, + 0, // offset + cast(t, singletonObject(t, pool, name - 1)), + cast(t, singletonObject(t, pool, spec - 1)), + addendum, + class_, + code); + + PROTECT(t, method); + + if (methodVirtual(t, method)) { + ++declaredVirtualCount; + + GcTriple* p + = hashMapFindNode(t, virtualMap, method, methodHash, methodEqual); + + if (p) { + method->offset() = cast(t, p->first())->offset(); + + p->setSecond(t, method); + } else { + method->offset() = virtualCount++; + + listAppend(t, newVirtuals, method); + + hashMapInsert(t, virtualMap, method, method, methodHash); + } + + if (UNLIKELY((class_->flags() & ACC_INTERFACE) == 0 + and vm::strcmp(reinterpret_cast("finalize"), + method->name()->body().begin()) == 0 + and vm::strcmp(reinterpret_cast("()V"), + method->spec()->body().begin()) == 0 + and (not emptyMethod(t, method)))) { + class_->vmFlags() |= HasFinalizerFlag; + } + } else { + method->offset() = i; + + if (vm::strcmp(reinterpret_cast(""), + method->name()->body().begin()) == 0) { + method->vmFlags() |= ClassInitFlag; + class_->vmFlags() |= NeedInitFlag; + } else if (vm::strcmp(reinterpret_cast(""), + method->name()->body().begin()) == 0) { + method->vmFlags() |= ConstructorFlag; + } + } + + methodTable->setBodyElement(t, i, method); + } + + class_->setMethodTable(t, methodTable); + } + + GcList* abstractVirtuals + = addInterfaceMethods(t, class_, virtualMap, &virtualCount, true); + + PROTECT(t, abstractVirtuals); + + bool populateInterfaceVtables = false; + + if (declaredVirtualCount == 0 and abstractVirtuals == 0 + and (class_->flags() & ACC_INTERFACE) == 0) { + if (class_->super()) { + // inherit virtual table from superclass + class_->setVirtualTable(t, superVirtualTable); + + if (class_->super()->interfaceTable() + and cast(t, class_->interfaceTable())->length() + == cast(t, class_->super()->interfaceTable()) + ->length()) { + // inherit interface table from superclass + class_->setInterfaceTable(t, class_->super()->interfaceTable()); + } else { + populateInterfaceVtables = true; + } + } else { + // apparently, Object does not have any virtual methods. We + // give it a vtable anyway so code doesn't break elsewhere. + GcArray* vtable = makeArray(t, 0); + class_->setVirtualTable(t, vtable); + } + } else if (virtualCount) { + // generate class vtable + + GcArray* vtable = makeArray(t, virtualCount); + + unsigned i = 0; + if (class_->flags() & ACC_INTERFACE) { + PROTECT(t, vtable); + + for (HashMapIterator it(t, virtualMap); it.hasMore();) { + GcMethod* method = cast(t, it.next()->first()); + assertT(t, vtable->body()[method->offset()] == 0); + vtable->setBodyElement(t, method->offset(), method); + ++i; + } + } else { + populateInterfaceVtables = true; + + if (superVirtualTable) { + for (; i < superVirtualTable->length(); ++i) { + object method = superVirtualTable->body()[i]; + method = hashMapFind(t, virtualMap, method, methodHash, methodEqual); + + vtable->setBodyElement(t, i, method); + } + } + + for (GcPair* p = cast(t, newVirtuals->front()); p; + p = cast(t, p->second())) { + vtable->setBodyElement(t, i, p->first()); + ++i; + } + } + + if (abstractVirtuals) { + PROTECT(t, vtable); + + object originalMethodTable = class_->methodTable(); + PROTECT(t, originalMethodTable); + + unsigned oldLength + = class_->methodTable() + ? cast(t, class_->methodTable())->length() + : 0; + + GcClassAddendum* addendum = getClassAddendum(t, class_, pool); + addendum->declaredMethodCount() = oldLength; + + GcArray* newMethodTable + = makeArray(t, oldLength + abstractVirtuals->size()); + + if (oldLength) { + GcArray* mtable = cast(t, class_->methodTable()); + for (size_t i = 0; i < oldLength; i++) { + newMethodTable->setBodyElement(t, i, mtable->body()[i]); + } + } + + mark(t, newMethodTable, ArrayBody, oldLength); + + unsigned mti = oldLength; + for (GcPair* p = cast(t, abstractVirtuals->front()); p; + p = cast(t, p->second())) { + newMethodTable->setBodyElement(t, mti++, p->first()); + + if ((class_->flags() & ACC_INTERFACE) == 0) { + vtable->setBodyElement(t, i++, p->first()); + } + } + + assertT(t, newMethodTable->length() == mti); + + class_->setMethodTable(t, newMethodTable); + } + + assertT(t, vtable->length() == i); + + class_->setVirtualTable(t, vtable); + } + + if (populateInterfaceVtables) { + // generate interface vtables + GcArray* itable = cast(t, class_->interfaceTable()); + if (itable) { + PROTECT(t, itable); + + for (unsigned i = 0; i < itable->length(); i += 2) { + GcArray* ivtable = cast( + t, cast(t, itable->body()[i])->virtualTable()); + if (ivtable) { + GcArray* vtable = cast(t, itable->body()[i + 1]); + + for (unsigned j = 0; j < ivtable->length(); ++j) { + object method = ivtable->body()[j]; + method + = hashMapFind(t, virtualMap, method, methodHash, methodEqual); + assertT(t, method); + + vtable->setBodyElement(t, j, method); + } + } + } + } + } +} + +void parseAttributeTable(Thread* t, + Stream& s, + GcClass* class_, + GcSingleton* pool) +{ + PROTECT(t, class_); + PROTECT(t, pool); + + unsigned attributeCount = s.read2(); + for (unsigned j = 0; j < attributeCount; ++j) { + GcByteArray* name + = cast(t, singletonObject(t, pool, s.read2() - 1)); + unsigned length = s.read4(); + + if (vm::strcmp(reinterpret_cast("SourceFile"), + name->body().begin()) == 0) { + class_->setSourceFile( + t, cast(t, singletonObject(t, pool, s.read2() - 1))); + } else if (vm::strcmp(reinterpret_cast("Signature"), + name->body().begin()) == 0) { + GcClassAddendum* addendum = getClassAddendum(t, class_, pool); + addendum->setSignature(t, singletonObject(t, pool, s.read2() - 1)); + } else if (vm::strcmp(reinterpret_cast("InnerClasses"), + name->body().begin()) == 0) { + unsigned innerClassCount = s.read2(); + GcArray* table = makeArray(t, innerClassCount); + PROTECT(t, table); + + for (unsigned i = 0; i < innerClassCount; ++i) { + int16_t inner = s.read2(); + int16_t outer = s.read2(); + int16_t name = s.read2(); + int16_t flags = s.read2(); + + GcInnerClassReference* reference = makeInnerClassReference( + t, + inner + ? cast(t, singletonObject(t, pool, inner - 1)) + ->name() + : 0, + outer + ? cast(t, singletonObject(t, pool, outer - 1)) + ->name() + : 0, + name ? cast(t, singletonObject(t, pool, name - 1)) : 0, + flags); + + table->setBodyElement(t, i, reference); + } + + GcClassAddendum* addendum = getClassAddendum(t, class_, pool); + addendum->setInnerClassTable(t, table); + } else if (vm::strcmp( + reinterpret_cast("RuntimeVisibleAnnotations"), + name->body().begin()) == 0) { + GcByteArray* body = makeByteArray(t, length); + PROTECT(t, body); + s.read(reinterpret_cast(body->body().begin()), length); + + GcClassAddendum* addendum = getClassAddendum(t, class_, pool); + addendum->setAnnotationTable(t, body); + } else if (vm::strcmp(reinterpret_cast("BootstrapMethods"), + name->body().begin()) == 0) { + unsigned count = s.read2(); + GcArray* array = makeArray(t, count); + PROTECT(t, array); + + for (unsigned i = 0; i < count; ++i) { + unsigned reference = s.read2() - 1; + unsigned argumentCount = s.read2(); + GcCharArray* element = makeCharArray(t, 1 + argumentCount); + element->body()[0] = reference; + for (unsigned ai = 0; ai < argumentCount; ++ai) { + element->body()[1 + ai] = s.read2() - 1; + } + array->setBodyElement(t, i, element); + } + + GcClassAddendum* addendum = getClassAddendum(t, class_, pool); + addendum->setBootstrapMethodTable(t, array); + } else if (vm::strcmp(reinterpret_cast("EnclosingMethod"), + name->body().begin()) == 0) { + int16_t enclosingClass = s.read2(); + int16_t enclosingMethod = s.read2(); + + GcClassAddendum* addendum = getClassAddendum(t, class_, pool); + + addendum->setEnclosingClass( + t, + cast(t, singletonObject(t, pool, enclosingClass - 1)) + ->name()); + + addendum->setEnclosingMethod( + t, + enclosingMethod + ? cast(t, singletonObject(t, pool, enclosingMethod - 1)) + : 0); + } else { + s.skip(length); + } + } +} + +void updateClassTables(Thread* t, GcClass* newClass, GcClass* oldClass) +{ + GcArray* fieldTable = cast(t, newClass->fieldTable()); + if (fieldTable) { + for (unsigned i = 0; i < fieldTable->length(); ++i) { + cast(t, fieldTable->body()[i])->setClass(t, newClass); + } + } + + GcSingleton* staticTable = newClass->staticTable(); + if (staticTable) { + staticTable->setBodyElement(t, 0, reinterpret_cast(newClass)); + } + + if (newClass->flags() & ACC_INTERFACE) { + GcArray* virtualTable = cast(t, newClass->virtualTable()); + if (virtualTable) { + for (unsigned i = 0; i < virtualTable->length(); ++i) { + GcMethod* m = cast(t, virtualTable->body()[i]); + if (m->class_() == oldClass) { + m->setClass(t, newClass); + } + } + } + } + + GcArray* methodTable = cast(t, newClass->methodTable()); + if (methodTable) { + for (unsigned i = 0; i < methodTable->length(); ++i) { + cast(t, methodTable->body()[i])->setClass(t, newClass); + } + } +} + +void updateBootstrapClass(Thread* t, GcClass* bootstrapClass, GcClass* class_) +{ + expect(t, bootstrapClass != class_); + + // verify that the classes have the same layout + expect(t, bootstrapClass->super() == class_->super()); + + expect(t, bootstrapClass->fixedSize() >= class_->fixedSize()); + + expect(t, (class_->vmFlags() & HasFinalizerFlag) == 0); + + PROTECT(t, bootstrapClass); + PROTECT(t, class_); + + ENTER(t, Thread::ExclusiveState); + + bootstrapClass->vmFlags() &= ~BootstrapFlag; + bootstrapClass->vmFlags() |= class_->vmFlags(); + bootstrapClass->flags() |= class_->flags(); + + bootstrapClass->setArrayElementClass(t, class_->arrayElementClass()); + bootstrapClass->setSuper(t, class_->super()); + bootstrapClass->setInterfaceTable(t, class_->interfaceTable()); + bootstrapClass->setVirtualTable(t, class_->virtualTable()); + bootstrapClass->setFieldTable(t, class_->fieldTable()); + bootstrapClass->setMethodTable(t, class_->methodTable()); + bootstrapClass->setStaticTable(t, class_->staticTable()); + bootstrapClass->setAddendum(t, class_->addendum()); + + updateClassTables(t, bootstrapClass, class_); +} + +GcClass* makeArrayClass(Thread* t, + GcClassLoader* loader, + unsigned dimensions, + GcByteArray* spec, + GcClass* elementClass) +{ + if (type(t, GcJobject::Type)->vmFlags() & BootstrapFlag) { + PROTECT(t, loader); + PROTECT(t, spec); + PROTECT(t, elementClass); + + // Load java.lang.Object if present so we can use its vtable, but + // don't throw an exception if we can't find it. This way, we + // avoid infinite recursion due to trying to create an array to + // make a stack trace for a ClassNotFoundException. + resolveSystemClass( + t, roots(t)->bootLoader(), type(t, GcJobject::Type)->name(), false); + } + + GcArray* vtable = cast(t, type(t, GcJobject::Type)->virtualTable()); + + // From JDK docs: for array classes the public, private, protected modifiers are the same as + // the underlying type, and the final modifier is always set. Testing on OpenJDK shows that + // ACC_ABSTRACT is also set on array classes. + int flags = elementClass->flags() & (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED); + flags |= ACC_FINAL; + flags |= ACC_ABSTRACT; + + GcClass* c = t->m->processor->makeClass(t, + flags, + 0, + 2 * BytesPerWord, + BytesPerWord, + dimensions, + elementClass, + type(t, GcArray::Type)->objectMask(), + spec, + 0, + type(t, GcJobject::Type), + roots(t)->arrayInterfaceTable(), + vtable, + 0, + 0, + 0, + 0, + loader, + vtable->length()); + + PROTECT(t, c); + + t->m->processor->initVtable(t, c); + + return c; +} + +void saveLoadedClass(Thread* t, GcClassLoader* loader, GcClass* c) +{ + PROTECT(t, loader); + PROTECT(t, c); + + ACQUIRE(t, t->m->classLock); + + if (loader->map() == 0) { + GcHashMap* map = makeHashMap(t, 0, 0); + loader->setMap(t, map); + } + + hashMapInsert( + t, cast(t, loader->map()), c->name(), c, byteArrayHash); +} + +GcClass* makeArrayClass(Thread* t, + GcClassLoader* loader, + GcByteArray* spec, + bool throw_, + Gc::Type throwType) +{ + PROTECT(t, loader); + PROTECT(t, spec); + + const char* s = reinterpret_cast(spec->body().begin()); + const char* start = s; + unsigned dimensions = 0; + for (; *s == '['; ++s) + ++dimensions; + + GcByteArray* elementSpec; + switch (*s) { + case 'L': { + ++s; + const char* elementSpecStart = s; + while (*s and *s != ';') + ++s; + if (dimensions > 1) { + elementSpecStart -= dimensions; + ++s; + } + + elementSpec = makeByteArray(t, s - elementSpecStart + 1); + memcpy(elementSpec->body().begin(), + &spec->body()[elementSpecStart - start], + s - elementSpecStart); + elementSpec->body()[s - elementSpecStart] = 0; + } break; + + default: + if (dimensions > 1) { + char c = *s; + elementSpec = makeByteArray(t, dimensions + 1); + unsigned i; + for (i = 0; i < dimensions - 1; ++i) { + elementSpec->body()[i] = '['; + } + elementSpec->body()[i++] = c; + elementSpec->body()[i] = 0; + --dimensions; + } else { + abort(t); + } + } + + GcClass* elementClass + = cast(t, + hashMapFind(t, + roots(t)->bootstrapClassMap(), + elementSpec, + byteArrayHash, + byteArrayEqual)); + + if (elementClass == 0) { + elementClass = resolveClass(t, loader, elementSpec, throw_, throwType); + if (elementClass == 0) + return 0; + } + + PROTECT(t, elementClass); + + ACQUIRE(t, t->m->classLock); + + GcClass* class_ = findLoadedClass(t, elementClass->loader(), spec); + if (class_) { + return class_; + } + + class_ = makeArrayClass( + t, elementClass->loader(), dimensions, spec, elementClass); + + PROTECT(t, class_); + + saveLoadedClass(t, elementClass->loader(), class_); + + return class_; +} + +GcClass* resolveArrayClass(Thread* t, + GcClassLoader* loader, + GcByteArray* spec, + bool throw_, + Gc::Type throwType) +{ + GcClass* c = cast(t, + hashMapFind(t, + roots(t)->bootstrapClassMap(), + spec, + byteArrayHash, + byteArrayEqual)); + + if (c) { + c->setVirtualTable(t, type(t, GcJobject::Type)->virtualTable()); + + return c; + } else { + PROTECT(t, loader); + PROTECT(t, spec); + + c = findLoadedClass(t, roots(t)->bootLoader(), spec); + + if (c) { + return c; + } else { + return makeArrayClass(t, loader, spec, throw_, throwType); + } + } +} + +void removeMonitor(Thread* t, object o) +{ + unsigned hash; + if (DebugMonitors) { + hash = objectHash(t, o); + } + + object m + = hashMapRemove(t, roots(t)->monitorMap(), o, objectHash, objectEqual); + + if (DebugMonitors) { + fprintf(stderr, "dispose monitor %p for object %x\n", m, hash); + } +} + +void removeString(Thread* t, object o) +{ + hashMapRemove(t, roots(t)->stringMap(), o, stringHash, objectEqual); +} + +void bootClass(Thread* t, + Gc::Type type, + int superType, + uint32_t* objectMask, + unsigned fixedSize, + unsigned arrayElementSize, + unsigned vtableLength) +{ + GcClass* super + = (superType >= 0 ? vm::type(t, static_cast(superType)) : 0); + + unsigned maskSize + = ceilingDivide(fixedSize + arrayElementSize, 32 * BytesPerWord); + + GcIntArray* mask; + if (objectMask) { + if (super and super->objectMask() + and super->objectMask()->length() == maskSize + and memcmp(super->objectMask()->body().begin(), + objectMask, + sizeof(uint32_t) * maskSize) == 0) { + mask = vm::type(t, static_cast(superType))->objectMask(); + } else { + mask = makeIntArray(t, maskSize); + memcpy(mask->body().begin(), objectMask, sizeof(uint32_t) * maskSize); + } + } else { + mask = 0; + } + + int flags = 0; + switch(type) { + case Gc::JbyteType: + case Gc::JintType: + case Gc::JshortType: + case Gc::JlongType: + case Gc::JbooleanType: + case Gc::JcharType: + case Gc::JfloatType: + case Gc::JdoubleType: + + case Gc::ByteArrayType: + case Gc::IntArrayType: + case Gc::ShortArrayType: + case Gc::LongArrayType: + case Gc::BooleanArrayType: + case Gc::CharArrayType: + case Gc::FloatArrayType: + case Gc::DoubleArrayType: + // Primitive and array types are final, abstract and public. + flags = ACC_FINAL | ACC_ABSTRACT | ACC_PUBLIC; + default: + break; + } + + super = (superType >= 0 ? vm::type(t, static_cast(superType)) : 0); + + GcClass* class_ = t->m->processor->makeClass(t, + flags, + BootstrapFlag, + fixedSize, + arrayElementSize, + arrayElementSize ? 1 : 0, + 0, + mask, + 0, + 0, + super, + 0, + 0, + 0, + 0, + 0, + 0, + roots(t)->bootLoader(), + vtableLength); + + setType(t, type, class_); +} + +void bootJavaClass(Thread* t, + Gc::Type type, + int superType, + const char* name, + int vtableLength, + object bootMethod) +{ + PROTECT(t, bootMethod); + + GcByteArray* n = makeByteArray(t, name); + PROTECT(t, n); + + GcClass* class_ = vm::type(t, type); + PROTECT(t, class_); + + class_->setName(t, n); + + GcArray* vtable; + if (vtableLength >= 0) { + vtable = makeArray(t, vtableLength); + for (int i = 0; i < vtableLength; ++i) { + vtable->setBodyElement(t, i, bootMethod); + } + } else { + vtable = cast( + t, vm::type(t, static_cast(superType))->virtualTable()); + } + + class_->setVirtualTable(t, vtable); + + t->m->processor->initVtable(t, class_); + + hashMapInsert(t, roots(t)->bootstrapClassMap(), n, class_, byteArrayHash); +} + +void nameClass(Thread* t, Gc::Type type, const char* name) +{ + GcByteArray* n = makeByteArray(t, name); + cast(t, t->m->types->body()[type])->setName(t, n); +} + +void makeArrayInterfaceTable(Thread* t) +{ + GcArray* interfaceTable = makeArray(t, 4); + + interfaceTable->setBodyElement(t, 0, type(t, GcSerializable::Type)); + + interfaceTable->setBodyElement(t, 2, type(t, GcCloneable::Type)); + + roots(t)->setArrayInterfaceTable(t, interfaceTable); +} + +void boot(Thread* t) +{ + Machine* m = t->m; + + m->unsafe = true; + + m->roots = reinterpret_cast(allocate(t, GcRoots::FixedSize, true)); + + object classLoader = allocate(t, GcSystemClassLoader::FixedSize, true); + // sequence point, for gc (don't recombine statements) + roots(t)->setBootLoader(t, reinterpret_cast(classLoader)); + + classLoader = allocate(t, GcSystemClassLoader::FixedSize, true); + // sequence point, for gc (don't recombine statements) + roots(t)->setAppLoader(t, reinterpret_cast(classLoader)); + + m->types = reinterpret_cast( + allocate(t, pad((TypeCount + 2) * BytesPerWord), true)); + m->types->length() = TypeCount; + +#include "type-initializations.cpp" + + GcClass* arrayClass = type(t, GcArray::Type); + setField(t, m->types, 0, arrayClass); + + GcClass* rootsClass = type(t, GcRoots::Type); + setField(t, m->roots, 0, rootsClass); + + GcClass* loaderClass = type(t, GcSystemClassLoader::Type); + setField(t, roots(t)->bootLoader(), 0, loaderClass); + setField(t, roots(t)->appLoader(), 0, loaderClass); + + GcClass* objectClass = type(t, GcJobject::Type); + + GcClass* classClass = type(t, GcClass::Type); + setField(t, classClass, 0, classClass); + classClass->setSuper(t, objectClass); + + GcClass* intArrayClass = type(t, GcIntArray::Type); + setField(t, intArrayClass, 0, classClass); + intArrayClass->setSuper(t, objectClass); + + m->unsafe = false; + + type(t, GcSingleton::Type)->vmFlags() |= SingletonFlag; + + type(t, GcContinuation::Type)->vmFlags() |= ContinuationFlag; + + type(t, GcJreference::Type)->vmFlags() |= ReferenceFlag; + type(t, GcWeakReference::Type)->vmFlags() |= ReferenceFlag + | WeakReferenceFlag; + type(t, GcSoftReference::Type)->vmFlags() |= ReferenceFlag + | WeakReferenceFlag; + type(t, GcPhantomReference::Type)->vmFlags() |= ReferenceFlag + | WeakReferenceFlag; + + type(t, GcJboolean::Type)->vmFlags() |= PrimitiveFlag; + type(t, GcJbyte::Type)->vmFlags() |= PrimitiveFlag; + type(t, GcJchar::Type)->vmFlags() |= PrimitiveFlag; + type(t, GcJshort::Type)->vmFlags() |= PrimitiveFlag; + type(t, GcJint::Type)->vmFlags() |= PrimitiveFlag; + type(t, GcJlong::Type)->vmFlags() |= PrimitiveFlag; + type(t, GcJfloat::Type)->vmFlags() |= PrimitiveFlag; + type(t, GcJdouble::Type)->vmFlags() |= PrimitiveFlag; + type(t, GcJvoid::Type)->vmFlags() |= PrimitiveFlag; + + type(t, GcBooleanArray::Type) + ->setArrayElementClass(t, type(t, GcJboolean::Type)); + type(t, GcByteArray::Type)->setArrayElementClass(t, type(t, GcJbyte::Type)); + type(t, GcCharArray::Type)->setArrayElementClass(t, type(t, GcJchar::Type)); + type(t, GcShortArray::Type)->setArrayElementClass(t, type(t, GcJshort::Type)); + type(t, GcIntArray::Type)->setArrayElementClass(t, type(t, GcJint::Type)); + type(t, GcLongArray::Type)->setArrayElementClass(t, type(t, GcJlong::Type)); + type(t, GcFloatArray::Type)->setArrayElementClass(t, type(t, GcJfloat::Type)); + type(t, GcDoubleArray::Type) + ->setArrayElementClass(t, type(t, GcJdouble::Type)); + + { + GcHashMap* map = makeHashMap(t, 0, 0); + roots(t)->bootLoader()->setMap(t, map); + } + + roots(t)->bootLoader()->as(t)->finder() = m->bootFinder; + + { + GcHashMap* map = makeHashMap(t, 0, 0); + roots(t)->appLoader()->setMap(t, map); + } + + roots(t)->appLoader()->as(t)->finder() = m->appFinder; + + roots(t)->appLoader()->setParent(t, roots(t)->bootLoader()); + + { + GcHashMap* map = makeHashMap(t, 0, 0); + // sequence point, for gc (don't recombine statements) + roots(t)->setBootstrapClassMap(t, map); + } + + { + GcWeakHashMap* map = makeWeakHashMap(t, 0, 0); + // sequence point, for gc (don't recombine statements) + roots(t)->setStringMap(t, map->as(t)); + } + + makeArrayInterfaceTable(t); + + type(t, GcBooleanArray::Type) + ->setInterfaceTable(t, roots(t)->arrayInterfaceTable()); + type(t, GcByteArray::Type) + ->setInterfaceTable(t, roots(t)->arrayInterfaceTable()); + type(t, GcCharArray::Type) + ->setInterfaceTable(t, roots(t)->arrayInterfaceTable()); + type(t, GcShortArray::Type) + ->setInterfaceTable(t, roots(t)->arrayInterfaceTable()); + type(t, GcIntArray::Type) + ->setInterfaceTable(t, roots(t)->arrayInterfaceTable()); + type(t, GcLongArray::Type) + ->setInterfaceTable(t, roots(t)->arrayInterfaceTable()); + type(t, GcFloatArray::Type) + ->setInterfaceTable(t, roots(t)->arrayInterfaceTable()); + type(t, GcDoubleArray::Type) + ->setInterfaceTable(t, roots(t)->arrayInterfaceTable()); + + m->processor->boot(t, 0, 0); + + { + GcCode* bootCode = makeCode(t, 0, 0, 0, 0, 0, 0, 0, 0, 1); + bootCode->body()[0] = impdep1; + object bootMethod + = makeMethod(t, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, bootCode); + PROTECT(t, bootMethod); + +# include "type-java-initializations.cpp" +# include "type-name-initializations.cpp" + + } + +} + +class HeapClient : public Heap::Client { + public: + HeapClient(Machine* m) : m(m) + { + } + + virtual void visitRoots(Heap::Visitor* v) + { + ::visitRoots(m, v); + + postVisit(m->rootThread, v); + } + + virtual void collect(void* context, Heap::CollectionType type) + { + collect(static_cast(context), type); + } + + virtual bool isFixed(void* p) + { + return objectFixed(m->rootThread, static_cast(p)); + } + + virtual unsigned sizeInWords(void* p) + { + Thread* t = m->rootThread; + + object o = static_cast(m->heap->follow(maskAlignedPointer(p))); + + unsigned n = baseSize(t, o, m->heap->follow(objectClass(t, o))); + + if (objectExtended(t, o)) { + ++n; + } + + return n; + } + + virtual unsigned copiedSizeInWords(void* p) + { + Thread* t = m->rootThread; + + object o = static_cast(m->heap->follow(maskAlignedPointer(p))); + assertT(t, not objectFixed(t, o)); + + unsigned n = baseSize(t, o, m->heap->follow(objectClass(t, o))); + + if (objectExtended(t, o) or hashTaken(t, o)) { + ++n; + } + + return n; + } + + virtual void copy(void* srcp, void* dstp) + { + Thread* t = m->rootThread; + + object src = static_cast(m->heap->follow(maskAlignedPointer(srcp))); + assertT(t, not objectFixed(t, src)); + + GcClass* class_ = m->heap->follow(objectClass(t, src)); + + unsigned base = baseSize(t, src, class_); + unsigned n = extendedSize(t, src, base); + + object dst = static_cast(dstp); + + memcpy(dst, src, n * BytesPerWord); + + if (hashTaken(t, src)) { + alias(dst, 0) &= PointerMask; + alias(dst, 0) |= ExtendedMark; + extendedWord(t, dst, base) = takeHash(t, src); + } + } + + virtual void walk(void* p, Heap::Walker* w) + { + object o = static_cast(m->heap->follow(maskAlignedPointer(p))); + ::walk(m->rootThread, w, o, 0); + } + + void dispose() + { + m->heap->free(this, sizeof(*this)); + } + + private: + Machine* m; +}; + +void doCollect(Thread* t, Heap::CollectionType type, int pendingAllocation) +{ + expect(t, not t->m->collecting); + + t->m->collecting = true; + THREAD_RESOURCE0(t, t->m->collecting = false); + +#ifdef VM_STRESS + bool stress = (t->getFlags() & Thread::StressFlag) != 0; + if (not stress) + t->setFlag(Thread::StressFlag); +#endif + + Machine* m = t->m; + + m->unsafe = true; + m->heap->collect( + type, + footprint(m->rootThread), + pendingAllocation - (t->m->heapPoolIndex * ThreadHeapSizeInWords)); + m->unsafe = false; + + postCollect(m->rootThread); + + killZombies(t, m->rootThread); + + for (unsigned i = 0; i < m->heapPoolIndex; ++i) { + m->heap->free(m->heapPool[i], ThreadHeapSizeInBytes); + } + m->heapPoolIndex = 0; + + if (m->heap->limitExceeded()) { + // if we're out of memory, disallow further allocations of fixed + // objects: + m->fixedFootprint = FixedFootprintThresholdInBytes; + } else { + m->fixedFootprint = 0; + } + +#ifdef VM_STRESS + if (not stress) + t->clearFlag(Thread::StressFlag); +#endif + + GcFinalizer* finalizeQueue = t->m->finalizeQueue; + t->m->finalizeQueue = 0; + for (; finalizeQueue; + finalizeQueue = cast(t, finalizeQueue->next())) { + void (*function)(Thread*, object); + memcpy(&function, &finalizeQueue->finalize(), BytesPerWord); + function(t, finalizeQueue->target()); + } + +#ifndef SGX + if ((roots(t)->objectsToFinalize() or roots(t)->objectsToClean()) + and m->finalizeThread == 0 and t->state != Thread::ExitState) { + m->finalizeThread = m->processor->makeThread( + m, roots(t)->finalizerThread(), m->rootThread); + + addThread(t, m->finalizeThread); + + if (not startThread(t, m->finalizeThread)) { + removeThread(t, m->finalizeThread); + m->finalizeThread = 0; + } + } +#endif +} + +uint64_t invokeLoadClass(Thread* t, uintptr_t* arguments) +{ + GcMethod* method = cast(t, reinterpret_cast(arguments[0])); + object loader = reinterpret_cast(arguments[1]); + object specString = reinterpret_cast(arguments[2]); + + return reinterpret_cast( + t->m->processor->invoke(t, method, loader, specString)); +} + +bool isInitializing(Thread* t, GcClass* c) +{ + for (Thread::ClassInitStack* s = t->classInitStack; s; s = s->next) { + if (s->class_ == c) { + return true; + } + } + return false; +} + +object findInTable(Thread* t, + GcArray* table, + GcByteArray* name, + GcByteArray* spec, + GcByteArray* (*getName)(Thread*, object), + GcByteArray* (*getSpec)(Thread*, object)) +{ + if (table) { + for (unsigned i = 0; i < table->length(); ++i) { + object o = table->body()[i]; + if (vm::strcmp(getName(t, o)->body().begin(), name->body().begin()) == 0 + and vm::strcmp(getSpec(t, o)->body().begin(), spec->body().begin()) + == 0) { + return o; + } + } + + if (false) { + fprintf( + stderr, "%s %s not in\n", name->body().begin(), spec->body().begin()); + + for (unsigned i = 0; i < table->length(); ++i) { + object o = table->body()[i]; + fprintf(stderr, + "\t%s %s\n", + getName(t, o)->body().begin(), + getSpec(t, o)->body().begin()); + } + } + } + + return 0; +} + +void updatePackageMap(Thread* t, GcClass* class_) +{ + PROTECT(t, class_); + + if (roots(t)->packageMap() == 0) { + GcHashMap* map = makeHashMap(t, 0, 0); + // sequence point, for gc (don't recombine statements) + roots(t)->setPackageMap(t, map); + } + + GcByteArray* className = class_->name(); + if ('[' != className->body()[0]) { + THREAD_RUNTIME_ARRAY(t, char, packageName, className->length()); + + char* s = reinterpret_cast(className->body().begin()); + char* p = strrchr(s, '/'); + + if (p) { + int length = (p - s) + 1; + memcpy( + RUNTIME_ARRAY_BODY(packageName), className->body().begin(), length); + RUNTIME_ARRAY_BODY(packageName)[length] = 0; + + GcByteArray* key + = vm::makeByteArray(t, "%s", RUNTIME_ARRAY_BODY(packageName)); + PROTECT(t, key); + + hashMapRemove( + t, roots(t)->packageMap(), key, byteArrayHash, byteArrayEqual); + + GcByteArray* source = class_->source(); + if (source) { + // note that we strip the "file:" prefix, since OpenJDK's + // Package.defineSystemPackage expects an unadorned filename: + const unsigned PrefixLength = 5; + unsigned sourceNameLength = source->length() - PrefixLength; + THREAD_RUNTIME_ARRAY(t, char, sourceName, sourceNameLength); + memcpy(RUNTIME_ARRAY_BODY(sourceName), + &source->body()[PrefixLength], + sourceNameLength); + + source = vm::makeByteArray(t, "%s", RUNTIME_ARRAY_BODY(sourceName)); + } else { + source = vm::makeByteArray(t, "avian-dummy-package-source"); + } + + hashMapInsert(t, roots(t)->packageMap(), key, source, byteArrayHash); + } + } +} + +} // namespace + +namespace vm { + +Machine::Machine(System* system, + Heap* heap, + Finder* bootFinder, + Finder* appFinder, + Processor* processor, + Classpath* classpath, + const char** properties, + unsigned propertyCount, + const char** arguments, + unsigned argumentCount, + unsigned stackSizeInBytes) + : vtable(&javaVMVTable), + system(system), + heapClient(new (heap->allocate(sizeof(HeapClient))) HeapClient(this)), + heap(heap), + bootFinder(bootFinder), + appFinder(appFinder), + processor(processor), + classpath(classpath), + rootThread(0), + exclusive(0), + finalizeThread(0), + jniReferences(0), + propertyCount(propertyCount), + arguments(arguments), + argumentCount(argumentCount), + threadCount(0), + activeCount(0), + liveCount(0), + daemonCount(0), + fixedFootprint(0), + stackSizeInBytes(stackSizeInBytes), + localThread(0), + stateLock(0), + heapLock(0), + classLock(0), + referenceLock(0), + shutdownLock(0), + libraries(0), + errorLog(0), + bootimage(0), + types(0), + roots(0), + finalizers(0), + tenuredFinalizers(0), + finalizeQueue(0), + weakReferences(0), + tenuredWeakReferences(0), + unsafe(false), + collecting(false), + triedBuiltinOnLoad(false), + dumpedHeapOnOOM(false), + alive(true), + heapPoolIndex(0) +{ + heap->setClient(heapClient); + + populateJNITables(&javaVMVTable, &jniEnvVTable); + + // Copying the properties memory (to avoid memory crashes) + this->properties = (char**)heap->allocate(sizeof(char*) * propertyCount); + for (unsigned int i = 0; i < propertyCount; i++) { + size_t length = strlen(properties[i]) + 1; // +1 for null-terminating char + this->properties[i] = (char*)heap->allocate(sizeof(char) * length); + memcpy(this->properties[i], properties[i], length); + } + + const char* bootstrapProperty = findProperty(this, BOOTSTRAP_PROPERTY); + const char* bootstrapPropertyDup + = bootstrapProperty ? strdup(bootstrapProperty) : 0; + const char* bootstrapPropertyEnd + = bootstrapPropertyDup + + (bootstrapPropertyDup ? strlen(bootstrapPropertyDup) : 0); + char* codeLibraryName = (char*)bootstrapPropertyDup; + char* codeLibraryNameEnd = 0; + if (codeLibraryName && (codeLibraryNameEnd + = strchr(codeLibraryName, system->pathSeparator()))) + *codeLibraryNameEnd = 0; + + if (not system->success(system->make(&localThread)) + or not system->success(system->make(&stateLock)) + or not system->success(system->make(&heapLock)) + or not system->success(system->make(&classLock)) + or not system->success(system->make(&referenceLock)) + or not system->success(system->make(&shutdownLock)) + or not system->success(system->load(&libraries, bootstrapPropertyDup))) { + system->abort(); + } + + System::Library* additionalLibrary = 0; + while (codeLibraryNameEnd && codeLibraryNameEnd + 1 < bootstrapPropertyEnd) { + codeLibraryName = codeLibraryNameEnd + 1; + codeLibraryNameEnd = strchr(codeLibraryName, system->pathSeparator()); + if (codeLibraryNameEnd) + *codeLibraryNameEnd = 0; + + if (!system->success(system->load(&additionalLibrary, codeLibraryName))) + system->abort(); + libraries->setNext(additionalLibrary); + } + + if (bootstrapPropertyDup) + free((void*)bootstrapPropertyDup); +} + +void Machine::dispose() +{ + localThread->dispose(); + stateLock->dispose(); + heapLock->dispose(); + classLock->dispose(); + referenceLock->dispose(); + shutdownLock->dispose(); + + if (libraries) { + libraries->disposeAll(); + } + + for (Reference* r = jniReferences; r;) { + Reference* tmp = r; + r = r->next; + heap->free(tmp, sizeof(*tmp)); + } + + for (unsigned i = 0; i < heapPoolIndex; ++i) { + heap->free(heapPool[i], ThreadHeapSizeInBytes); + } + + if (bootimage) { + heap->free(bootimage, bootimageSize); + } + + heap->free(arguments, sizeof(const char*) * argumentCount); + + for (unsigned int i = 0; i < propertyCount; i++) { + heap->free(properties[i], sizeof(char) * (strlen(properties[i]) + 1)); + } + heap->free(properties, sizeof(const char*) * propertyCount); + + static_cast(heapClient)->dispose(); + + heap->free(this, sizeof(*this)); +} + +Thread::Thread(Machine* m, GcThread* javaThread, Thread* parent) + : vtable(&(m->jniEnvVTable)), + m(m), + parent(parent), + peer(0), + child(0), + waitNext(0), + state(NoState), + criticalLevel(0), + systemThread(0), + lock(0), + javaThread(javaThread), + exception(0), + heapIndex(0), + heapOffset(0), + protector(0), + classInitStack(0), + libraryLoadStack(0), + runnable(this), + defaultHeap( + static_cast(m->heap->allocate(ThreadHeapSizeInBytes))), + heap(defaultHeap), + backupHeapIndex(0), + flags(ActiveFlag) +{ +} + +void Thread::init() +{ + memset(defaultHeap, 0, ThreadHeapSizeInBytes); + memset(backupHeap, 0, ThreadBackupHeapSizeInBytes); + + if (parent == 0) { + assertT(this, m->rootThread == 0); + assertT(this, javaThread == 0); + + m->rootThread = this; + m->unsafe = true; + + if (not m->system->success(m->system->attach(&runnable))) { + abort(this); + } + + BootImage* image = 0; + uint8_t* code = 0; + const char* imageFunctionName = findProperty(m, "avian.bootimage"); + if (imageFunctionName) { + bool lzma = strncmp("lzma:", imageFunctionName, 5) == 0; + const char* symbolName = lzma ? imageFunctionName + 5 : imageFunctionName; + + void* imagep = m->libraries->resolve(symbolName); + if (imagep) { + uint8_t* (*imageFunction)(size_t*); + memcpy(&imageFunction, &imagep, BytesPerWord); + + size_t size = 0; + uint8_t* imageBytes = imageFunction(&size); + if (lzma) { +#ifdef AVIAN_USE_LZMA + m->bootimage = image = reinterpret_cast(decodeLZMA( + m->system, m->heap, imageBytes, size, &(m->bootimageSize))); +#else + abort(this); +#endif + } else { + image = reinterpret_cast(imageBytes); + } + + const char* codeFunctionName = findProperty(m, "avian.codeimage"); + if (codeFunctionName) { + void* codep = m->libraries->resolve(codeFunctionName); + if (codep) { + uint8_t* (*codeFunction)(size_t*); + memcpy(&codeFunction, &codep, BytesPerWord); + + code = codeFunction(&size); + } + } + } + } + + m->unsafe = false; + + enter(this, ActiveState); + + if (image and code) { + m->processor->boot(this, image, code); + makeArrayInterfaceTable(this); + } else { + boot(this); + } + + GcWeakHashMap* map = makeWeakHashMap(this, 0, 0); + // sequence point, for gc (don't recombine statements) + roots(this)->setByteArrayMap(this, map->as(this)); + + map = makeWeakHashMap(this, 0, 0); + // sequence point, for gc (don't recombine statements) + roots(this)->setMonitorMap(this, map->as(this)); + + GcVector* v = makeVector(this, 0, 0); + // sequence point, for gc (don't recombine statements) + roots(this)->setClassRuntimeDataTable(this, v); + + v = makeVector(this, 0, 0); + // sequence point, for gc (don't recombine statements) + roots(this)->setMethodRuntimeDataTable(this, v); + + v = makeVector(this, 0, 0); + // sequence point, for gc (don't recombine statements) + roots(this)->setJNIMethodTable(this, v); + + v = makeVector(this, 0, 0); + // sequence point, for gc (don't recombine statements) + roots(this)->setJNIFieldTable(this, v); + + m->localThread->set(this); + } + + expect(this, m->system->success(m->system->make(&lock))); +} + +void Thread::exit() +{ + if (state != Thread::ExitState and state != Thread::ZombieState) { + enter(this, Thread::ExclusiveState); + + if (m->liveCount == 1) { + turnOffTheLights(this); + } else { + javaThread->peer() = 0; + + enter(this, Thread::ZombieState); + } + } +} + +void Thread::dispose() +{ + if (lock) { + lock->dispose(); + } + + if (systemThread) { + systemThread->dispose(); + } + + --m->threadCount; + + m->heap->free(defaultHeap, ThreadHeapSizeInBytes); + + m->processor->dispose(this); +} + +void shutDown(Thread* t) +{ + ACQUIRE(t, t->m->shutdownLock); + + GcPair* hooks = roots(t)->shutdownHooks(); + PROTECT(t, hooks); + + roots(t)->setShutdownHooks(t, 0); + + GcPair* h = hooks; + PROTECT(t, h); + for (; h; h = cast(t, h->second())) { + startThread(t, cast(t, h->first())); + } + + // wait for hooks to exit + h = hooks; + for (; h; h = cast(t, h->second())) { + while (true) { + Thread* ht + = reinterpret_cast(cast(t, h->first())->peer()); + + { + ACQUIRE(t, t->m->stateLock); + + if (ht == 0 or ht->state == Thread::ZombieState + or ht->state == Thread::JoinedState) { + break; + } else { + ENTER(t, Thread::IdleState); + t->m->stateLock->wait(t->systemThread, 0); + } + } + } + } + + // tell finalize thread to exit and wait for it to do so + { + ACQUIRE(t, t->m->stateLock); + Thread* finalizeThread = t->m->finalizeThread; + if (finalizeThread) { + t->m->finalizeThread = 0; + t->m->stateLock->notifyAll(t->systemThread); + + while (finalizeThread->state != Thread::ZombieState + and finalizeThread->state != Thread::JoinedState) { + ENTER(t, Thread::IdleState); + t->m->stateLock->wait(t->systemThread, 0); + } + } + } + + // interrupt daemon threads and tell them to die + + // todo: be more aggressive about killing daemon threads, e.g. at + // any GC point, not just at waits/sleeps + { + ACQUIRE(t, t->m->stateLock); + + t->m->alive = false; + + visitAll(t, t->m->rootThread, interruptDaemon); + } +} + +void enter(Thread* t, Thread::State s) +{ + stress(t); + + if (s == t->state) + return; + + if (t->state == Thread::ExitState) { + // once in exit state, we stay that way + return; + } + +#ifdef USE_ATOMIC_OPERATIONS +#define INCREMENT atomicIncrement +#define ACQUIRE_LOCK ACQUIRE_RAW(t, t->m->stateLock) +#define STORE_LOAD_MEMORY_BARRIER storeLoadMemoryBarrier() +#else +#define INCREMENT(pointer, value) *(pointer) += value; +#define ACQUIRE_LOCK +#define STORE_LOAD_MEMORY_BARRIER + + ACQUIRE_RAW(t, t->m->stateLock); +#endif // not USE_ATOMIC_OPERATIONS + + switch (s) { + case Thread::ExclusiveState: { + ACQUIRE_LOCK; + + while (t->m->exclusive) { + // another thread got here first. + ENTER(t, Thread::IdleState); + t->m->stateLock->wait(t->systemThread, 0); + } + + switch (t->state) { + case Thread::ActiveState: + break; + + case Thread::IdleState: { + INCREMENT(&(t->m->activeCount), 1); + } break; + + default: + abort(t); + } + + t->state = Thread::ExclusiveState; + t->m->exclusive = t; + + STORE_LOAD_MEMORY_BARRIER; + + while (t->m->activeCount > 1) { + t->m->stateLock->wait(t->systemThread, 0); + } + } break; + + case Thread::IdleState: + if (LIKELY(t->state == Thread::ActiveState)) { + // fast path + assertT(t, t->m->activeCount > 0); + INCREMENT(&(t->m->activeCount), -1); + + t->state = s; + + STORE_LOAD_MEMORY_BARRIER; + + if (t->m->exclusive) { + ACQUIRE_LOCK; + + t->m->stateLock->notifyAll(t->systemThread); + } + + break; + } else { + // fall through to slow path + } + + case Thread::ZombieState: { + ACQUIRE_LOCK; + + switch (t->state) { + case Thread::ExclusiveState: { + assertT(t, t->m->exclusive == t); + t->m->exclusive = 0; + } break; + + case Thread::ActiveState: + break; + + default: + abort(t); + } + + assertT(t, t->m->activeCount > 0); + INCREMENT(&(t->m->activeCount), -1); + + if (s == Thread::ZombieState) { + assertT(t, t->m->liveCount > 0); + --t->m->liveCount; + + if (t->getFlags() & Thread::DaemonFlag) { + --t->m->daemonCount; + } + } + + t->state = s; + + t->m->stateLock->notifyAll(t->systemThread); + } break; + + case Thread::ActiveState: + if (LIKELY(t->state == Thread::IdleState and t->m->exclusive == 0)) { + // fast path + INCREMENT(&(t->m->activeCount), 1); + + t->state = s; + + STORE_LOAD_MEMORY_BARRIER; + + if (t->m->exclusive) { + // another thread has entered the exclusive state, so we + // return to idle and use the slow path to become active + enter(t, Thread::IdleState); + } else { + break; + } + } + + { + ACQUIRE_LOCK; + + switch (t->state) { + case Thread::ExclusiveState: { + assertT(t, t->m->exclusive == t); + + t->state = s; + t->m->exclusive = 0; + + t->m->stateLock->notifyAll(t->systemThread); + } break; + + case Thread::NoState: + case Thread::IdleState: { + while (t->m->exclusive) { + t->m->stateLock->wait(t->systemThread, 0); + } + + INCREMENT(&(t->m->activeCount), 1); + if (t->state == Thread::NoState) { + ++t->m->liveCount; + ++t->m->threadCount; + } + t->state = s; + } break; + + default: + abort(t); + } + } + break; + + case Thread::ExitState: { + ACQUIRE_LOCK; + + switch (t->state) { + case Thread::ExclusiveState: { + assertT(t, t->m->exclusive == t); + // exit state should also be exclusive, so don't set exclusive = 0 + + t->m->stateLock->notifyAll(t->systemThread); + } break; + + case Thread::ActiveState: + break; + + default: + abort(t); + } + + assertT(t, t->m->activeCount > 0); + INCREMENT(&(t->m->activeCount), -1); + + t->state = s; + + while (t->m->liveCount - t->m->daemonCount > 1) { + t->m->stateLock->wait(t->systemThread, 0); + } + } break; + + default: + abort(t); + } +} + +object allocate2(Thread* t, unsigned sizeInBytes, bool objectMask) +{ + return allocate3( + t, + t->m->heap, + ceilingDivide(sizeInBytes, BytesPerWord) > ThreadHeapSizeInWords + ? Machine::FixedAllocation + : Machine::MovableAllocation, + sizeInBytes, + objectMask); +} + +object allocate3(Thread* t, + Alloc* allocator, + Machine::AllocationType type, + unsigned sizeInBytes, + bool objectMask) +{ + expect(t, t->criticalLevel == 0); + + if (UNLIKELY(t->getFlags() & Thread::UseBackupHeapFlag)) { + expect(t, + t->backupHeapIndex + ceilingDivide(sizeInBytes, BytesPerWord) + <= ThreadBackupHeapSizeInWords); + + object o = reinterpret_cast(t->backupHeap + t->backupHeapIndex); + t->backupHeapIndex += ceilingDivide(sizeInBytes, BytesPerWord); + fieldAtOffset(o, 0) = 0; + return o; + } else if (UNLIKELY(t->getFlags() & Thread::TracingFlag)) { + expect(t, + t->heapIndex + ceilingDivide(sizeInBytes, BytesPerWord) + <= ThreadHeapSizeInWords); + return allocateSmall(t, sizeInBytes); + } + + ACQUIRE_RAW(t, t->m->stateLock); + + while (t->m->exclusive and t->m->exclusive != t) { + // another thread wants to enter the exclusive state, either for a + // collection or some other reason. We give it a chance here. + ENTER(t, Thread::IdleState); + + while (t->m->exclusive) { + t->m->stateLock->wait(t->systemThread, 0); + } + } + + do { + switch (type) { + case Machine::MovableAllocation: + if (t->heapIndex + ceilingDivide(sizeInBytes, BytesPerWord) + > ThreadHeapSizeInWords) { + t->heap = 0; + if ((not t->m->heap->limitExceeded()) + and t->m->heapPoolIndex < ThreadHeapPoolSize) { + t->heap = static_cast( + t->m->heap->tryAllocate(ThreadHeapSizeInBytes)); + + if (t->heap) { + memset(t->heap, 0, ThreadHeapSizeInBytes); + + t->m->heapPool[t->m->heapPoolIndex++] = t->heap; + t->heapOffset += t->heapIndex; + t->heapIndex = 0; + } + } + } + break; + + case Machine::FixedAllocation: + if (t->m->fixedFootprint + sizeInBytes > FixedFootprintThresholdInBytes) { + t->heap = 0; + } + break; + + case Machine::ImmortalAllocation: + break; + } + + int pendingAllocation = t->m->heap->fixedFootprint( + ceilingDivide(sizeInBytes, BytesPerWord), objectMask); + + if (t->heap == 0 or t->m->heap->limitExceeded(pendingAllocation)) { + // fprintf(stderr, "gc"); + // vmPrintTrace(t); + collect(t, Heap::MinorCollection, pendingAllocation); + } + + if (t->m->heap->limitExceeded(pendingAllocation)) { + throw_(t, roots(t)->outOfMemoryError()); + } + } while (type == Machine::MovableAllocation + and t->heapIndex + ceilingDivide(sizeInBytes, BytesPerWord) + > ThreadHeapSizeInWords); + + switch (type) { + case Machine::MovableAllocation: { + return allocateSmall(t, sizeInBytes); + } + + case Machine::FixedAllocation: { + object o = static_cast(t->m->heap->allocateFixed( + allocator, ceilingDivide(sizeInBytes, BytesPerWord), objectMask)); + + memset(o, 0, sizeInBytes); + + alias(o, 0) = FixedMark; + + t->m->fixedFootprint += t->m->heap->fixedFootprint( + ceilingDivide(sizeInBytes, BytesPerWord), objectMask); + + return o; + } + + case Machine::ImmortalAllocation: { + object o = static_cast(t->m->heap->allocateImmortalFixed( + allocator, ceilingDivide(sizeInBytes, BytesPerWord), objectMask)); + + memset(o, 0, sizeInBytes); + + alias(o, 0) = FixedMark; + + return o; + } + + default: + abort(t); + } +} + +void collect(Thread* t, Heap::CollectionType type, int pendingAllocation) +{ + ENTER(t, Thread::ExclusiveState); + + unsigned pending = pendingAllocation + - (t->m->heapPoolIndex * ThreadHeapSizeInWords); + + if (t->m->heap->limitExceeded(pending)) { + type = Heap::MajorCollection; + } + + doCollect(t, type, pendingAllocation); + + if (t->m->heap->limitExceeded(pending)) { + // try once more, giving the heap a chance to squeeze everything + // into the smallest possible space: + doCollect(t, Heap::MajorCollection, pendingAllocation); + } +} + +object makeNewGeneral(Thread* t, GcClass* class_) +{ + assertT(t, t->state == Thread::ActiveState); + + PROTECT(t, class_); + + object instance = makeNew(t, class_); + PROTECT(t, instance); + + if (class_->vmFlags() & WeakReferenceFlag) { + ACQUIRE(t, t->m->referenceLock); + + cast(t, instance)->vmNext() = t->m->weakReferences; + t->m->weakReferences = cast(t, instance); + } + + if (class_->vmFlags() & HasFinalizerFlag) { + addFinalizer(t, instance, 0); + } + + return instance; +} + +void popResources(Thread* t) +{ + while (t->resource != t->checkpoint->resource) { + Thread::Resource* r = t->resource; + t->resource = r->next; + r->release(); + } + + t->protector = t->checkpoint->protector; +} + +GcByteArray* makeByteArrayV(Thread* t, const char* format, va_list a, int size) +{ + THREAD_RUNTIME_ARRAY(t, char, buffer, size); + + int r = vm::vsnprintf(RUNTIME_ARRAY_BODY(buffer), size - 1, format, a); + if (r >= 0 and r < size - 1) { + GcByteArray* s = makeByteArray(t, strlen(RUNTIME_ARRAY_BODY(buffer)) + 1); + memcpy(s->body().begin(), RUNTIME_ARRAY_BODY(buffer), s->length()); + return s; + } else { + return 0; + } +} + +GcByteArray* makeByteArray(Thread* t, const char* format, ...) +{ + int size = 256; + while (true) { + va_list a; + va_start(a, format); + GcByteArray* s = makeByteArrayV(t, format, a, size); + va_end(a); + + if (s) { + return s; + } else { + size *= 2; + } + } +} + +GcString* makeString(Thread* t, const char* format, ...) +{ + int size = 256; + while (true) { + va_list a; + va_start(a, format); + GcByteArray* s = makeByteArrayV(t, format, a, size); + va_end(a); + + if (s) { + return t->m->classpath->makeString(t, s, 0, s->length() - 1); + } else { + size *= 2; + } + } +} + +int stringUTFLength(Thread* t, + GcString* string, + unsigned start, + unsigned length) +{ + unsigned result = 0; + + if (length) { + object data = string->data(); + if (objectClass(t, data) == type(t, GcByteArray::Type)) { + result = length; + } else { + GcCharArray* a = cast(t, data); + for (unsigned i = 0; i < length; ++i) { + uint16_t c = a->body()[string->offset(t) + start + i]; + if (c == 0) + result += 1; // null char (was 2 bytes in Java) + else if (c < 0x80) + result += 1; // ASCII char + else if (c < 0x800) + result += 2; // two-byte char + else + result += 3; // three-byte char + } + } + } + + return result; +} + +void stringChars(Thread* t, + GcString* string, + unsigned start, + unsigned length, + char* chars) +{ + if (length) { + object data = string->data(); + if (objectClass(t, data) == type(t, GcByteArray::Type)) { + GcByteArray* b = cast(t, data); + memcpy(chars, &b->body()[string->offset(t) + start], length); + } else { + GcCharArray* c = cast(t, data); + for (unsigned i = 0; i < length; ++i) { + chars[i] = c->body()[string->offset(t) + start + i]; + } + } + } + chars[length] = 0; +} + +void stringChars(Thread* t, + GcString* string, + unsigned start, + unsigned length, + uint16_t* chars) +{ + if (length) { + object data = string->data(); + if (objectClass(t, data) == type(t, GcByteArray::Type)) { + GcByteArray* b = cast(t, data); + for (unsigned i = 0; i < length; ++i) { + chars[i] = b->body()[string->offset(t) + start + i]; + } + } else { + GcCharArray* c = cast(t, data); + memcpy(chars, + &c->body()[string->offset(t) + start], + length * sizeof(uint16_t)); + } + } + chars[length] = 0; +} + +void stringUTFChars(Thread* t, + GcString* string, + unsigned start, + unsigned length, + char* chars, + unsigned charsLength UNUSED) +{ + assertT(t, + static_cast(stringUTFLength(t, string, start, length)) + == charsLength); + + object data = string->data(); + if (objectClass(t, data) == type(t, GcByteArray::Type)) { + GcByteArray* b = cast(t, data); + memcpy(chars, &b->body()[string->offset(t) + start], length); + chars[length] = 0; + } else { + GcCharArray* cs = cast(t, data); + int j = 0; + for (unsigned i = 0; i < length; ++i) { + uint16_t c = cs->body()[string->offset(t) + start + i]; + if (!c) { // null char + chars[j++] = 0; + } else if (c < 0x80) { // ASCII char + chars[j++] = static_cast(c); + } else if (c < 0x800) { // two-byte char + chars[j++] = static_cast(0x0c0 | (c >> 6)); + chars[j++] = static_cast(0x080 | (c & 0x03f)); + } else { // three-byte char + chars[j++] = static_cast(0x0e0 | ((c >> 12) & 0x0f)); + chars[j++] = static_cast(0x080 | ((c >> 6) & 0x03f)); + chars[j++] = static_cast(0x080 | (c & 0x03f)); + } + } + chars[j] = 0; + } +} + +uint64_t resolveBootstrap(Thread* t, uintptr_t* arguments) +{ + GcByteArray* name + = cast(t, reinterpret_cast(arguments[0])); + + resolveSystemClass(t, roots(t)->bootLoader(), name); + + return 1; +} + +bool isAssignableFrom(Thread* t, GcClass* a, GcClass* b) +{ + assertT(t, a); + assertT(t, b); + + if (a == b) + return true; + + if (a->flags() & ACC_INTERFACE) { + if (b->vmFlags() & BootstrapFlag) { + uintptr_t arguments[] = {reinterpret_cast(b->name())}; + + if (run(t, resolveBootstrap, arguments) == 0) { + t->exception = 0; + return false; + } + } + + GcArray* itable = cast(t, b->interfaceTable()); + if (itable) { + unsigned stride = (b->flags() & ACC_INTERFACE) ? 1 : 2; + for (unsigned i = 0; i < itable->length(); i += stride) { + if (itable->body()[i] == a) { + return true; + } + } + } + } else if (a->arrayDimensions()) { + if (b->arrayDimensions()) { + return isAssignableFrom( + t, a->arrayElementClass(), b->arrayElementClass()); + } + } else if ((a->vmFlags() & PrimitiveFlag) == (b->vmFlags() & PrimitiveFlag)) { + for (; b; b = b->super()) { + if (b == a) { + return true; + } + } + } + + return false; +} + +bool instanceOf(Thread* t, GcClass* class_, object o) +{ + if (o == 0) { + return false; + } else { + return isAssignableFrom(t, class_, objectClass(t, o)); + } +} + +GcMethod* classInitializer(Thread* t, GcClass* class_) +{ + if (GcArray* mtable = cast(t, class_->methodTable())) { + PROTECT(t, mtable); + for (unsigned i = 0; i < mtable->length(); ++i) { + GcMethod* o = cast(t, mtable->body()[i]); + + if (o->vmFlags() & ClassInitFlag) { + return o; + } + } + } + return 0; +} + +unsigned fieldCode(Thread* t, unsigned javaCode) +{ + switch (javaCode) { + case 'B': + return ByteField; + case 'C': + return CharField; + case 'D': + return DoubleField; + case 'F': + return FloatField; + case 'I': + return IntField; + case 'J': + return LongField; + case 'S': + return ShortField; + case 'V': + return VoidField; + case 'Z': + return BooleanField; + case 'L': + case '[': + return ObjectField; + + default: + abort(t); + } +} + +unsigned fieldType(Thread* t, unsigned code) +{ + switch (code) { + case VoidField: + return VOID_TYPE; + case ByteField: + case BooleanField: + return INT8_TYPE; + case CharField: + case ShortField: + return INT16_TYPE; + case DoubleField: + return DOUBLE_TYPE; + case FloatField: + return FLOAT_TYPE; + case IntField: + return INT32_TYPE; + case LongField: + return INT64_TYPE; + case ObjectField: + return POINTER_TYPE; + + default: + abort(t); + } +} + +unsigned primitiveSize(Thread* t, unsigned code) +{ + switch (code) { + case VoidField: + return 0; + case ByteField: + case BooleanField: + return 1; + case CharField: + case ShortField: + return 2; + case FloatField: + case IntField: + return 4; + case DoubleField: + case LongField: + return 8; + + default: + abort(t); + } +} + +GcClass* parseClass(Thread* t, + GcClassLoader* loader, + const uint8_t* data, + unsigned size, + Gc::Type throwType) +{ + PROTECT(t, loader); + + class Client : public Stream::Client { + public: + Client(Thread* t) : t(t) + { + } + + virtual void NO_RETURN handleError() + { + abort(t); + } + + private: + Thread* t; + } client(t); + + Stream s(&client, data, size); + + uint32_t magic = s.read4(); + expect(t, magic == 0xCAFEBABE); + unsigned minorVer = s.read2(); // minor version + unsigned majorVer = s.read2(); // major version + if (DebugClassReader) { + fprintf(stderr, "read class (minor %d major %d)\n", minorVer, majorVer); + } + + GcSingleton* pool = parsePool(t, s); + PROTECT(t, pool); + + unsigned flags = s.read2(); + unsigned name = s.read2(); + + GcClass* class_ = (GcClass*)makeClass( + t, + flags, + 0, // VM flags + 0, // fixed size + 0, // array size + 0, // array dimensions + 0, // array element class + 0, // runtime data index + 0, // object mask + cast(t, singletonObject(t, pool, name - 1))->name(), + 0, // source file + 0, // super + 0, // interfaces + 0, // vtable + 0, // fields + 0, // methods + 0, // addendum + 0, // static table + loader, + 0, // source + 0); // vtable length + PROTECT(t, class_); + + unsigned super = s.read2(); + if (super) { + GcClass* sc = resolveClass( + t, + loader, + cast(t, singletonObject(t, pool, super - 1))->name(), + true, + throwType); + + class_->setSuper(t, sc); + + class_->vmFlags() |= (sc->vmFlags() & (ReferenceFlag | WeakReferenceFlag + | HasFinalizerFlag | NeedInitFlag)); + } + + if (DebugClassReader) { + fprintf(stderr, " flags %d name %d super %d\n", flags, name, super); + } + + parseInterfaceTable(t, s, class_, pool, throwType); + + parseFieldTable(t, s, class_, pool); + + parseMethodTable(t, s, class_, pool); + + parseAttributeTable(t, s, class_, pool); + + GcArray* vtable = cast(t, class_->virtualTable()); + unsigned vtableLength = (vtable ? vtable->length() : 0); + + GcClass* real = t->m->processor->makeClass(t, + class_->flags(), + class_->vmFlags(), + class_->fixedSize(), + class_->arrayElementSize(), + class_->arrayDimensions(), + class_->arrayElementClass(), + class_->objectMask(), + class_->name(), + class_->sourceFile(), + class_->super(), + class_->interfaceTable(), + class_->virtualTable(), + class_->fieldTable(), + class_->methodTable(), + class_->addendum(), + class_->staticTable(), + class_->loader(), + vtableLength); + + PROTECT(t, real); + + t->m->processor->initVtable(t, real); + + updateClassTables(t, real, class_); + + if (roots(t)->poolMap()) { + object bootstrapClass = hashMapFind(t, + roots(t)->bootstrapClassMap(), + class_->name(), + byteArrayHash, + byteArrayEqual); + + hashMapInsert(t, + roots(t)->poolMap(), + bootstrapClass ? bootstrapClass : real, + pool, + objectHash); + } + + return real; +} + +uint64_t runParseClass(Thread* t, uintptr_t* arguments) +{ + GcClassLoader* loader + = cast(t, reinterpret_cast(arguments[0])); + System::Region* region = reinterpret_cast(arguments[1]); + Gc::Type throwType = static_cast(arguments[2]); + + return reinterpret_cast( + parseClass(t, loader, region->start(), region->length(), throwType)); +} + +GcClass* resolveSystemClass(Thread* t, + GcClassLoader* loader, + GcByteArray* spec, + bool throw_, + Gc::Type throwType) +{ + PROTECT(t, loader); + PROTECT(t, spec); + + ACQUIRE(t, t->m->classLock); + + GcClass* class_ = cast(t, + hashMapFind(t, + cast(t, loader->map()), + spec, + byteArrayHash, + byteArrayEqual)); + + if (class_ == 0) { + PROTECT(t, class_); + + if (loader->parent()) { + class_ = resolveSystemClass(t, loader->parent(), spec, false); + if (class_) { + return class_; + } + } + + if (spec->body()[0] == '[') { + class_ = resolveArrayClass(t, loader, spec, throw_, throwType); + } else { + GcSystemClassLoader* sysLoader = loader->as(t); + PROTECT(t, sysLoader); + + THREAD_RUNTIME_ARRAY(t, char, file, spec->length() + 6); + memcpy( + RUNTIME_ARRAY_BODY(file), spec->body().begin(), spec->length() - 1); + memcpy(RUNTIME_ARRAY_BODY(file) + spec->length() - 1, ".class", 7); + + System::Region* region = static_cast(sysLoader->finder()) + ->find(RUNTIME_ARRAY_BODY(file)); + + if (region) { + if (Verbose) { + fprintf(stderr, "parsing %s\n", spec->body().begin()); + } + + { + THREAD_RESOURCE(t, System::Region*, region, region->dispose()); + + uintptr_t arguments[] = {reinterpret_cast(loader), + reinterpret_cast(region), + static_cast(throwType)}; + + // parse class file + class_ = cast( + t, reinterpret_cast(runRaw(t, runParseClass, arguments))); + + if (UNLIKELY(t->exception)) { + if (throw_) { + GcThrowable* e = t->exception; + t->exception = 0; + vm::throw_(t, e); + } else { + t->exception = 0; + return 0; + } + } + } + + if (Verbose) { + fprintf( + stderr, "done parsing %s: %p\n", spec->body().begin(), class_); + } + + { + const char* source = static_cast(sysLoader->finder()) + ->sourceUrl(RUNTIME_ARRAY_BODY(file)); + + if (source) { + unsigned length = strlen(source); + GcByteArray* array = makeByteArray(t, length + 1); + memcpy(array->body().begin(), source, length); + array = internByteArray(t, array); + + class_->setSource(t, array); + } + } + + GcClass* bootstrapClass + = cast(t, + hashMapFind(t, + roots(t)->bootstrapClassMap(), + spec, + byteArrayHash, + byteArrayEqual)); + + if (bootstrapClass) { + PROTECT(t, bootstrapClass); + + updateBootstrapClass(t, bootstrapClass, class_); + class_ = bootstrapClass; + } + } + } + + if (class_) { + hashMapInsert( + t, cast(t, loader->map()), spec, class_, byteArrayHash); + + updatePackageMap(t, class_); + } else if (throw_) { + throwNew(t, throwType, "%s", spec->body().begin()); + } + } + + return class_; +} + +GcClass* findLoadedClass(Thread* t, GcClassLoader* loader, GcByteArray* spec) +{ + PROTECT(t, loader); + PROTECT(t, spec); + + ACQUIRE(t, t->m->classLock); + + return loader->map() + ? cast(t, + hashMapFind(t, + cast(t, loader->map()), + spec, + byteArrayHash, + byteArrayEqual)) + : 0; +} + +GcClass* resolveClass(Thread* t, + GcClassLoader* loader, + GcByteArray* spec, + bool throw_, + Gc::Type throwType) +{ + if (objectClass(t, loader) == type(t, GcSystemClassLoader::Type)) { + return resolveSystemClass(t, loader, spec, throw_, throwType); + } else { + PROTECT(t, loader); + PROTECT(t, spec); + + GcClass* c = findLoadedClass(t, loader, spec); + if (c) { + return c; + } + + if (spec->body()[0] == '[') { + c = resolveArrayClass(t, loader, spec, throw_, throwType); + } else { + if (roots(t)->loadClassMethod() == 0) { + GcMethod* m = resolveMethod(t, + roots(t)->bootLoader(), + "java/lang/ClassLoader", + "loadClass", + "(Ljava/lang/String;)Ljava/lang/Class;"); + + if (m) { + roots(t)->setLoadClassMethod(t, m); + + GcClass* classLoaderClass = type(t, GcClassLoader::Type); + + if (classLoaderClass->vmFlags() & BootstrapFlag) { + resolveSystemClass( + t, roots(t)->bootLoader(), classLoaderClass->name()); + } + } + } + + GcMethod* method = findVirtualMethod( + t, roots(t)->loadClassMethod(), objectClass(t, loader)); + + PROTECT(t, method); + + THREAD_RUNTIME_ARRAY(t, char, s, spec->length()); + replace('/', + '.', + RUNTIME_ARRAY_BODY(s), + reinterpret_cast(spec->body().begin())); + + GcString* specString = makeString(t, "%s", RUNTIME_ARRAY_BODY(s)); + PROTECT(t, specString); + + uintptr_t arguments[] = {reinterpret_cast(method), + reinterpret_cast(loader), + reinterpret_cast(specString)}; + + GcJclass* jc = cast( + t, reinterpret_cast(runRaw(t, invokeLoadClass, arguments))); + + if (LIKELY(jc)) { + c = jc->vmClass(); + } else if (t->exception) { + if (throw_) { + GcThrowable* e + = type(t, throwType) == objectClass(t, t->exception) + ? t->exception + : makeThrowable(t, throwType, specString, 0, t->exception); + t->exception = 0; + vm::throw_(t, e); + } else { + t->exception = 0; + } + } + } + + if (LIKELY(c)) { + PROTECT(t, c); + + saveLoadedClass(t, loader, c); + } else if (throw_) { + throwNew(t, throwType, "%s", spec->body().begin()); + } + + return c; + } +} + +GcMethod* resolveMethod(Thread* t, + GcClass* class_, + const char* methodName, + const char* methodSpec) +{ + PROTECT(t, class_); + + GcByteArray* name = makeByteArray(t, methodName); + PROTECT(t, name); + + GcByteArray* spec = makeByteArray(t, methodSpec); + + GcMethod* method + = cast(t, findMethodInClass(t, class_, name, spec)); + + if (method == 0) { + throwNew(t, + GcNoSuchMethodError::Type, + "%s %s not found in %s", + methodName, + methodSpec, + class_->name()->body().begin()); + } else { + return method; + } +} + +GcField* resolveField(Thread* t, + GcClass* class_, + const char* fieldName, + const char* fieldSpec) +{ + PROTECT(t, class_); + + GcByteArray* name = makeByteArray(t, fieldName); + PROTECT(t, name); + + GcByteArray* spec = makeByteArray(t, fieldSpec); + PROTECT(t, spec); + + GcField* field = cast( + t, findInInterfaces(t, class_, name, spec, findFieldInClass)); + + GcClass* c = class_; + PROTECT(t, c); + + for (; c != 0 and field == 0; c = c->super()) { + field = cast(t, findFieldInClass(t, c, name, spec)); + } + + if (field == 0) { + throwNew(t, + GcNoSuchFieldError::Type, + "%s %s not found in %s", + fieldName, + fieldSpec, + class_->name()->body().begin()); + } else { + return field; + } +} + +bool classNeedsInit(Thread* t, GcClass* c) +{ + if (c->vmFlags() & NeedInitFlag) { + if (c->vmFlags() & InitFlag) { + // the class is currently being initialized. If this the thread + // which is initializing it, we should not try to initialize it + // recursively. Otherwise, we must wait for the responsible + // thread to finish. + for (Thread::ClassInitStack* s = t->classInitStack; s; s = s->next) { + if (s->class_ == c) { + return false; + } + } + } + return true; + } else { + return false; + } +} + +bool preInitClass(Thread* t, GcClass* c) +{ + int flags = c->vmFlags(); + + loadMemoryBarrier(); + + if (flags & NeedInitFlag) { + PROTECT(t, c); + ACQUIRE(t, t->m->classLock); + + if (c->vmFlags() & NeedInitFlag) { + if (c->vmFlags() & InitFlag) { + // If the class is currently being initialized and this the thread + // which is initializing it, we should not try to initialize it + // recursively. + if (isInitializing(t, c)) { + return false; + } + + // some other thread is on the job - wait for it to finish. + while (c->vmFlags() & InitFlag) { + ENTER(t, Thread::IdleState); + t->m->classLock->wait(t->systemThread, 0); + } + } else if (c->vmFlags() & InitErrorFlag) { + throwNew( + t, GcNoClassDefFoundError::Type, "%s", c->name()->body().begin()); + } else { + c->vmFlags() |= InitFlag; + return true; + } + } + } + return false; +} + +void postInitClass(Thread* t, GcClass* c) +{ + PROTECT(t, c); + ACQUIRE(t, t->m->classLock); + + if (t->exception + and instanceOf(t, type(t, GcException::Type), t->exception)) { + c->vmFlags() |= NeedInitFlag | InitErrorFlag; + c->vmFlags() &= ~InitFlag; + + GcThrowable* exception = t->exception; + t->exception = 0; + + GcExceptionInInitializerError* initExecption + = makeThrowable(t, GcExceptionInInitializerError::Type, 0, 0, exception) + ->as(t); + + initExecption->setException(t, exception->cause()); + + throw_(t, initExecption->as(t)); + } else { + c->vmFlags() &= ~(NeedInitFlag | InitFlag); + } + t->m->classLock->notifyAll(t->systemThread); +} + +void initClass(Thread* t, GcClass* c) +{ + PROTECT(t, c); + + GcClass* super = c->super(); + if (super) { + initClass(t, super); + } + + if (preInitClass(t, c)) { + OBJECT_RESOURCE(t, c, postInitClass(t, cast(t, c))); + + GcMethod* initializer = classInitializer(t, c); + + if (initializer) { + Thread::ClassInitStack stack(t, c); + + t->m->processor->invoke(t, initializer, 0); + } + } +} + +GcClass* resolveObjectArrayClass(Thread* t, + GcClassLoader* loader, + GcClass* elementClass) +{ + PROTECT(t, loader); + PROTECT(t, elementClass); + + { + GcClass* arrayClass + = cast(t, getClassRuntimeData(t, elementClass)->arrayClass()); + if (arrayClass) { + return arrayClass; + } + } + + GcByteArray* elementSpec = elementClass->name(); + PROTECT(t, elementSpec); + + GcByteArray* spec; + if (elementSpec->body()[0] == '[') { + spec = makeByteArray(t, elementSpec->length() + 1); + spec->body()[0] = '['; + memcpy( + &spec->body()[1], elementSpec->body().begin(), elementSpec->length()); + } else { + spec = makeByteArray(t, elementSpec->length() + 3); + spec->body()[0] = '['; + spec->body()[1] = 'L'; + memcpy(&spec->body()[2], + elementSpec->body().begin(), + elementSpec->length() - 1); + spec->body()[elementSpec->length() + 1] = ';'; + spec->body()[elementSpec->length() + 2] = 0; + } + + GcClass* arrayClass = resolveClass(t, loader, spec); + + getClassRuntimeData(t, elementClass)->setArrayClass(t, arrayClass); + + return arrayClass; +} + +object makeObjectArray(Thread* t, GcClass* elementClass, unsigned count) +{ + GcClass* arrayClass + = resolveObjectArrayClass(t, elementClass->loader(), elementClass); + + PROTECT(t, arrayClass); + + object array = makeArray(t, count); + setObjectClass(t, array, arrayClass); + + return array; +} + +static GcByteArray* getFieldName(Thread* t, object obj) +{ + return reinterpret_cast(cast(t, obj)->name()); +} + +static GcByteArray* getFieldSpec(Thread* t, object obj) +{ + return reinterpret_cast(cast(t, obj)->spec()); +} + +static GcByteArray* getMethodName(Thread* t, object obj) +{ + return reinterpret_cast(cast(t, obj)->name()); +} + +static GcByteArray* getMethodSpec(Thread* t, object obj) +{ + return reinterpret_cast(cast(t, obj)->spec()); +} + +object findFieldInClass(Thread* t, + GcClass* class_, + GcByteArray* name, + GcByteArray* spec) +{ + return findInTable(t, + cast(t, class_->fieldTable()), + name, + spec, + getFieldName, + getFieldSpec); +} + +object findMethodInClass(Thread* t, + GcClass* class_, + GcByteArray* name, + GcByteArray* spec) +{ + return findInTable(t, + cast(t, class_->methodTable()), + name, + spec, + getMethodName, + getMethodSpec); +} + +object findInHierarchyOrNull( + Thread* t, + GcClass* class_, + GcByteArray* name, + GcByteArray* spec, + object (*find)(Thread*, GcClass*, GcByteArray*, GcByteArray*)) +{ + GcClass* originalClass = class_; + + object o = 0; + if ((class_->flags() & ACC_INTERFACE) and class_->virtualTable()) { + o = findInTable(t, + cast(t, class_->virtualTable()), + name, + spec, + getMethodName, + getMethodSpec); + } + + if (o == 0) { + for (; o == 0 and class_; class_ = class_->super()) { + o = find(t, class_, name, spec); + } + + if (o == 0 and find == findFieldInClass) { + o = findInInterfaces(t, originalClass, name, spec, find); + } + } + + return o; +} + +unsigned parameterFootprint(Thread* t, const char* s, bool static_) +{ + unsigned footprint = 0; + for (MethodSpecIterator it(t, s); it.hasNext();) { + switch (*it.next()) { + case 'J': + case 'D': + footprint += 2; + break; + + default: + ++footprint; + break; + } + } + + if (not static_) { + ++footprint; + } + return footprint; +} + +void addFinalizer(Thread* t, object target, void (*finalize)(Thread*, object)) +{ + PROTECT(t, target); + + ACQUIRE(t, t->m->referenceLock); + + void* function; + memcpy(&function, &finalize, BytesPerWord); + + GcFinalizer* f = makeFinalizer(t, 0, function, 0, 0, 0); + f->target() = target; + f->next() = t->m->finalizers; + t->m->finalizers = f; +} + +GcMonitor* objectMonitor(Thread* t, object o, bool createNew) +{ + assertT(t, t->state == Thread::ActiveState); + + object m = hashMapFind(t, roots(t)->monitorMap(), o, objectHash, objectEqual); + + if (m) { + if (DebugMonitors) { + fprintf(stderr, "found monitor %p for object %x\n", m, objectHash(t, o)); + } + + return cast(t, m); + } else if (createNew) { + PROTECT(t, o); + PROTECT(t, m); + + { + ENTER(t, Thread::ExclusiveState); + + m = hashMapFind(t, roots(t)->monitorMap(), o, objectHash, objectEqual); + + if (m) { + if (DebugMonitors) { + fprintf( + stderr, "found monitor %p for object %x\n", m, objectHash(t, o)); + } + + return cast(t, m); + } + + object head = makeMonitorNode(t, 0, 0); + m = makeMonitor(t, 0, 0, 0, head, head, 0); + + if (DebugMonitors) { + fprintf(stderr, "made monitor %p for object %x\n", m, objectHash(t, o)); + } + + hashMapInsert(t, roots(t)->monitorMap(), o, m, objectHash); + + addFinalizer(t, o, removeMonitor); + } + + return cast(t, m); + } else { + return 0; + } +} + +object intern(Thread* t, object s) +{ + PROTECT(t, s); + + ACQUIRE(t, t->m->referenceLock); + + GcTriple* n + = hashMapFindNode(t, roots(t)->stringMap(), s, stringHash, stringEqual); + + if (n) { + return cast(t, n->first())->target(); + } else { + hashMapInsert(t, roots(t)->stringMap(), s, 0, stringHash); + addFinalizer(t, s, removeString); + return s; + } +} + +object clone(Thread* t, object o) +{ + PROTECT(t, o); + + GcClass* class_ = objectClass(t, o); + unsigned size = baseSize(t, o, class_) * BytesPerWord; + object clone; + + if (class_->arrayElementSize()) { + clone = static_cast(allocate(t, size, class_->objectMask())); + memcpy(clone, o, size); + // clear any object header flags: + setObjectClass(t, o, objectClass(t, o)); + } else if (instanceOf(t, type(t, GcCloneable::Type), o)) { + clone = make(t, class_); + memcpy(reinterpret_cast(clone) + 1, + reinterpret_cast(o) + 1, + size - BytesPerWord); + } else { + GcByteArray* classNameSlash = objectClass(t, o)->name(); + THREAD_RUNTIME_ARRAY(t, char, classNameDot, classNameSlash->length()); + replace('/', + '.', + RUNTIME_ARRAY_BODY(classNameDot), + reinterpret_cast(classNameSlash->body().begin())); + throwNew(t, + GcCloneNotSupportedException::Type, + "%s", + RUNTIME_ARRAY_BODY(classNameDot)); + } + + return clone; +} + +void walk(Thread* t, Heap::Walker* w, object o, unsigned start) +{ + GcClass* class_ = t->m->heap->follow(objectClass(t, o)); + GcIntArray* objectMask = t->m->heap->follow(class_->objectMask()); + + bool more = true; + + if (objectMask) { + unsigned fixedSize = class_->fixedSize(); + unsigned arrayElementSize = class_->arrayElementSize(); + unsigned arrayLength = (arrayElementSize ? fieldAtOffset( + o, fixedSize - BytesPerWord) + : 0); + + THREAD_RUNTIME_ARRAY(t, uint32_t, mask, objectMask->length()); + memcpy(RUNTIME_ARRAY_BODY(mask), + objectMask->body().begin(), + objectMask->length() * 4); + + more = ::walk(t, + w, + RUNTIME_ARRAY_BODY(mask), + fixedSize, + arrayElementSize, + arrayLength, + start); + } else if (class_->vmFlags() & SingletonFlag) { + GcSingleton* s = cast(t, o); + unsigned length = s->length(); + if (length) { + more = ::walk(t, + w, + singletonMask(t, s), + (singletonCount(t, s) + 2) * BytesPerWord, + 0, + 0, + start); + } else if (start == 0) { + more = w->visit(0); + } + } else if (start == 0) { + more = w->visit(0); + } + + if (more and class_->vmFlags() & ContinuationFlag) { + t->m->processor->walkContinuationBody(t, w, o, start); + } +} + +int walkNext(Thread* t, object o, int previous) +{ + class Walker : public Heap::Walker { + public: + Walker() : value(-1) + { + } + + bool visit(unsigned offset) + { + value = offset; + return false; + } + + int value; + } walker; + + walk(t, &walker, o, previous + 1); + return walker.value; +} + +void visitRoots(Machine* m, Heap::Visitor* v) +{ + v->visit(&(m->types)); + v->visit(&(m->roots)); + + for (Thread* t = m->rootThread; t; t = t->peer) { + ::visitRoots(t, v); + } + + for (Reference* r = m->jniReferences; r; r = r->next) { + if (not r->weak) { + v->visit(&(r->target)); + } + } +} + +void logTrace(FILE* f, const char* fmt, ...) +{ + va_list a; + va_start(a, fmt); +#ifdef PLATFORM_WINDOWS + const unsigned length = _vscprintf(fmt, a); +#else + const unsigned length = vsnprintf(0, 0, fmt, a); +#endif + va_end(a); + + RUNTIME_ARRAY(char, buffer, length + 1); + va_start(a, fmt); + vsnprintf(RUNTIME_ARRAY_BODY(buffer), length + 1, fmt, a); + va_end(a); + RUNTIME_ARRAY_BODY(buffer)[length] = 0; + + ::fprintf(f, "%s", RUNTIME_ARRAY_BODY(buffer)); +#ifdef PLATFORM_WINDOWS + ::OutputDebugStringA(RUNTIME_ARRAY_BODY(buffer)); +#endif +} + +void printTrace(Thread* t, GcThrowable* exception) +{ + if (exception == 0) { + exception = makeThrowable(t, GcNullPointerException::Type); + } + + for (GcThrowable* e = exception; e; e = e->cause()) { + if (e != exception) { + logTrace(errorLog(t), "caused by: "); + } + + logTrace(errorLog(t), "%s", objectClass(t, e)->name()->body().begin()); + + if (e->message()) { + GcString* m = e->message(); + THREAD_RUNTIME_ARRAY(t, char, message, m->length(t) + 1); + stringChars(t, m, RUNTIME_ARRAY_BODY(message)); + logTrace(errorLog(t), ": %s\n", RUNTIME_ARRAY_BODY(message)); + } else { + logTrace(errorLog(t), "\n"); + } + + object trace = e->trace(); + if (trace) { + for (unsigned i = 0; i < objectArrayLength(t, trace); ++i) { + GcTraceElement* e + = cast(t, objectArrayBody(t, trace, i)); + GcMethod* m = cast(t, e->method()); + const int8_t* class_ = m->class_()->name()->body().begin(); + const int8_t* method = m->name()->body().begin(); + int line = t->m->processor->lineNumber(t, m, e->ip()); + + logTrace(errorLog(t), " at %s.%s ", class_, method); + + switch (line) { + case NativeLine: + logTrace(errorLog(t), "(native)\n"); + break; + case UnknownLine: + logTrace(errorLog(t), "(unknown line)\n"); + break; + default: + logTrace(errorLog(t), "(line %d)\n", line); + } + } + } + + if (e == e->cause()) { + break; + } + } + + ::fflush(errorLog(t)); +} + +object makeTrace(Thread* t, Processor::StackWalker* walker) +{ + class Visitor : public Processor::StackVisitor { + public: + Visitor(Thread* t) : t(t), trace(0), index(0), protector(t, &trace) + { + } + + virtual bool visit(Processor::StackWalker* walker) + { + if (trace == 0) { + trace = makeObjectArray(t, walker->count()); + assertT(t, trace); + } + + GcTraceElement* e = makeTraceElement(t, walker->method(), walker->ip()); + assertT(t, index < objectArrayLength(t, trace)); + reinterpret_cast(trace)->setBodyElement(t, index, e); + ++index; + return true; + } + + Thread* t; + object trace; + unsigned index; + Thread::SingleProtector protector; + } v(t); + + walker->walk(&v); + + return v.trace ? v.trace : makeObjectArray(t, 0); +} + +object makeTrace(Thread* t, Thread* target) +{ + class Visitor : public Processor::StackVisitor { + public: + Visitor(Thread* t) : t(t), trace(0) + { + } + + virtual bool visit(Processor::StackWalker* walker) + { + trace = vm::makeTrace(t, walker); + return false; + } + + Thread* t; + object trace; + } v(t); + + t->m->processor->walkStack(target, &v); + + return v.trace ? v.trace : makeObjectArray(t, 0); +} + +void runFinalizeThread(Thread* t) +{ + GcFinalizer* finalizeList = 0; + PROTECT(t, finalizeList); + + GcCleaner* cleanList = 0; + PROTECT(t, cleanList); + + while (true) { + { + ACQUIRE(t, t->m->stateLock); + + while (t->m->finalizeThread and roots(t)->objectsToFinalize() == 0 + and roots(t)->objectsToClean() == 0) { + ENTER(t, Thread::IdleState); + t->m->stateLock->wait(t->systemThread, 0); + } + + if (t->m->finalizeThread == 0) { + return; + } else { + finalizeList = roots(t)->objectsToFinalize(); + roots(t)->setObjectsToFinalize(t, 0); + + cleanList = roots(t)->objectsToClean(); + roots(t)->setObjectsToClean(t, 0); + } + } + + for (; finalizeList; finalizeList = finalizeList->queueNext()) { + finalizeObject(t, finalizeList->queueTarget(), "finalize"); + } + + for (; cleanList; cleanList = cleanList->queueNext()) { + finalizeObject(t, cleanList, "clean"); + } + } +} + +object parseUtf8(Thread* t, const char* data, unsigned length) +{ + class Client : public Stream::Client { + public: + Client(Thread* t) : t(t) + { + } + + virtual void handleError() + { + if (false) + abort(t); + } + + private: + Thread* t; + } client(t); + + Stream s(&client, reinterpret_cast(data), length); + + return ::parseUtf8(t, s, length); +} + +object parseUtf8(Thread* t, GcByteArray* array) +{ + for (unsigned i = 0; i < array->length() - 1; ++i) { + if (array->body()[i] & 0x80) { + goto slow_path; + } + } + + return array; + +slow_path: + class Client : public Stream::Client { + public: + Client(Thread* t) : t(t) + { + } + + virtual void handleError() + { + if (false) + abort(t); + } + + private: + Thread* t; + } client(t); + + class MyStream : public AbstractStream { + public: + class MyProtector : public Thread::Protector { + public: + MyProtector(Thread* t, MyStream* s) : Protector(t), s(s) + { + } + + virtual void visit(Heap::Visitor* v) + { + v->visit(&(s->array)); + } + + MyStream* s; + }; + + MyStream(Thread* t, Client* client, GcByteArray* array) + : AbstractStream(client, array->length() - 1), + array(array), + protector(t, this) + { + } + + virtual void copy(uint8_t* dst, unsigned offset, unsigned size) + { + memcpy(dst, &array->body()[offset], size); + } + + GcByteArray* array; + MyProtector protector; + } s(t, &client, array); + + return ::parseUtf8(t, s, array->length() - 1); +} + +GcMethod* getCaller(Thread* t, unsigned target, bool skipMethodInvoke) +{ + if (static_cast(target) == -1) { + target = 2; + } + + class Visitor : public Processor::StackVisitor { + public: + Visitor(Thread* t, unsigned target, bool skipMethodInvoke) + : t(t), + method(0), + count(0), + target(target), + skipMethodInvoke(skipMethodInvoke) + { + } + + virtual bool visit(Processor::StackWalker* walker) + { + if (skipMethodInvoke + and walker->method()->class_() == type(t, GcJmethod::Type) + and strcmp(walker->method()->name()->body().begin(), + reinterpret_cast("invoke")) == 0) { + return true; + } + + if (count == target) { + method = walker->method(); + return false; + } else { + ++count; + return true; + } + } + + Thread* t; + GcMethod* method; + unsigned count; + unsigned target; + bool skipMethodInvoke; + } v(t, target, skipMethodInvoke); + + t->m->processor->walkStack(t, &v); + + return v.method; +} + +GcClass* defineClass(Thread* t, + GcClassLoader* loader, + const uint8_t* buffer, + unsigned length) +{ + PROTECT(t, loader); + + GcClass* c = parseClass(t, loader, buffer, length); + + // char name[byteArrayLength(t, className(t, c))]; + // memcpy(name, &byteArrayBody(t, className(t, c), 0), + // byteArrayLength(t, className(t, c))); + // replace('/', '-', name); + + // const unsigned BufferSize = 1024; + // char path[BufferSize]; + // snprintf(path, BufferSize, "/tmp/avian-define-class/%s.class", name); + + // FILE* file = fopen(path, "wb"); + // if (file) { + // fwrite(buffer, length, 1, file); + // fclose(file); + // } + + PROTECT(t, c); + + saveLoadedClass(t, loader, c); + + return c; +} + +void populateMultiArray(Thread* t, + object array, + int32_t* counts, + unsigned index, + unsigned dimensions) +{ + if (index + 1 == dimensions or counts[index] == 0) { + return; + } + + PROTECT(t, array); + + GcByteArray* spec = objectClass(t, array)->name(); + PROTECT(t, spec); + + GcByteArray* elementSpec = makeByteArray(t, spec->length() - 1); + memcpy(elementSpec->body().begin(), &spec->body()[1], spec->length() - 1); + + GcClass* class_ + = resolveClass(t, objectClass(t, array)->loader(), elementSpec); + PROTECT(t, class_); + + for (int32_t i = 0; i < counts[index]; ++i) { + GcArray* a = makeArray( + t, + ceilingDivide(counts[index + 1] * class_->arrayElementSize(), + BytesPerWord)); + a->length() = counts[index + 1]; + setObjectClass(t, a, class_); + setField(t, array, ArrayBody + (i * BytesPerWord), a); + + populateMultiArray(t, a, counts, index + 1, dimensions); + } +} + +object interruptLock(Thread* t, GcThread* thread) +{ + object lock = thread->interruptLock(); + + loadMemoryBarrier(); + + if (lock == 0) { + PROTECT(t, thread); + ACQUIRE(t, t->m->referenceLock); + + if (thread->interruptLock() == 0) { + object head = makeMonitorNode(t, 0, 0); + GcMonitor* lock = makeMonitor(t, 0, 0, 0, head, head, 0); + + storeStoreMemoryBarrier(); + + thread->setInterruptLock(t, lock); + } + } + + return thread->interruptLock(); +} + +void clearInterrupted(Thread* t) +{ + monitorAcquire(t, cast(t, interruptLock(t, t->javaThread))); + t->javaThread->interrupted() = false; + monitorRelease(t, cast(t, interruptLock(t, t->javaThread))); +} + +void threadInterrupt(Thread* t, GcThread* thread) +{ + PROTECT(t, thread); + + monitorAcquire(t, cast(t, interruptLock(t, thread))); + Thread* p = reinterpret_cast(thread->peer()); + if (p) { + interrupt(t, p); + } + thread->interrupted() = true; + monitorRelease(t, cast(t, interruptLock(t, thread))); +} + +bool threadIsInterrupted(Thread* t, GcThread* thread, bool clear) +{ + PROTECT(t, thread); + + monitorAcquire(t, cast(t, interruptLock(t, thread))); + bool v = thread->interrupted(); + if (clear) { + thread->interrupted() = false; + } + monitorRelease(t, cast(t, interruptLock(t, thread))); + return v; +} + +GcJclass* getDeclaringClass(Thread* t, GcClass* c) +{ + GcClassAddendum* addendum = c->addendum(); + if (addendum) { + GcArray* table = cast(t, addendum->innerClassTable()); + if (table) { + for (unsigned i = 0; i < table->length(); ++i) { + GcInnerClassReference* reference + = cast(t, table->body()[i]); + if (reference->outer() + and strcmp(reference->inner()->body().begin(), + c->name()->body().begin()) == 0) { + return getJClass(t, resolveClass(t, c->loader(), reference->outer())); + } + } + } + } + + return 0; +} + +// Called when interpreting invokedynamic. `invocation` points to +// static data in the bootstrap method table, which in turn points to +// a bootstrap method and stores additional data to be passed to +// it. `resolveDynamic` will then call this bootstrap method after +// resolving the arguments as required. The called method is assumed +// to be a lambda `metafactory` or `altMetafactory`. +// +// Note that capture/bridging etc happens within the bootstrap method, +// this is just the code that dispatches to it. +// +// Returns the CallSite returned by the bootstrap method. +GcCallSite* resolveDynamic(Thread* t, GcInvocation* invocation) +{ + PROTECT(t, invocation); + + // Use the invocation's Class to get the bootstrap method table and get a classloader. + GcClass* c = invocation->class_(); + PROTECT(t, c); + + // First element points to the bootstrap method. The rest are static data passed to the BSM. + GcCharArray* bootstrapArray = cast( + t, + cast(t, c->addendum()->bootstrapMethodTable()) + ->body()[invocation->bootstrap()]); + + PROTECT(t, bootstrapArray); + + // Resolve the bootstrap method itself. + GcMethod* bootstrap = cast(t, + resolve(t, + c->loader(), + invocation->pool(), + bootstrapArray->body()[0], + findMethodInClass, + GcNoSuchMethodError::Type)); + PROTECT(t, bootstrap); + + // Caller context info to be passed to the bootstrap method. + GcLookup* lookup + = makeLookup(t, c, ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED | ACC_STATIC); + PROTECT(t, lookup); + + // The name of the linked-to method. + GcByteArray* nameBytes = invocation->template_()->name(); + GcString* name + = t->m->classpath->makeString(t, nameBytes, 0, nameBytes->length() - 1); + PROTECT(t, name); + + // This is the type of the linked-to method (e.g. lambda). + GcMethodType* type = makeMethodType( + t, c->loader(), invocation->template_()->spec(), 0, 0, 0); + PROTECT(t, type); + + // `array` stores either + // 1. All the arguments to be passed to the bootstrap method in the case of `metafactory` + // 2. The vararg object array to be passed to `altMetafactory` + GcArray* array = makeArray(t, bootstrap->parameterCount()); + PROTECT(t, array); + + // These are common arguments to metafactory and altMetafactory + unsigned argument = 0; + array->setBodyElement(t, argument++, lookup); + array->setBodyElement(t, argument++, name); + array->setBodyElement(t, argument++, type); + + THREAD_RUNTIME_ARRAY(t, char, specBuffer, bootstrap->spec()->length()); + + const char* spec; + // `argArray` stores the final arguments to be passed to the bootstrap method. + // Later in this function we iterate through the method signature + + // bootstrap array and resolve the arguments as required into `array`. + // + // In the case of a `metafactory` call: + // `argArray = [caller, invokedName, invokedType, methodType, methodImplementation, instantiatedType]` + // `array = argArray` + // + // In the case of an `altMetafactory` call: + // `argArray = [caller, invokedName, invokedType, array]` + // `array = [methodType, methodImplementation, instantiatedType, flags, ...]` + GcArray* argArray = array; + PROTECT(t, argArray); + + // Check if the bootstrap method's signature matches that of an altMetafactory + if (::strcmp(reinterpret_cast(bootstrap->spec()->body().begin()), + "(Ljava/lang/invoke/MethodHandles$Lookup;" + "Ljava/lang/String;" + "Ljava/lang/invoke/MethodType;" + "[Ljava/lang/Object;)" + "Ljava/lang/invoke/CallSite;") == 0) { + // If so, create a new array to store the varargs in, and hardcode the BSM signature. + array = makeArray(t, bootstrapArray->length() - 1); + spec = "(Ljava/lang/invoke/MethodHandles$Lookup;" + "Ljava/lang/String;" + "Ljava/lang/invoke/MethodType;" + "Ljava/lang/invoke/MethodType;" + "Ljava/lang/invoke/MethodHandle;" + "Ljava/lang/invoke/MethodType;" + "I" + "I" + "[Ljava/lang/Class;" + "I" + "[Ljava/lang/invoke/MethodType;" + ")Ljava/lang/invoke/CallSite;"; + } else if (bootstrap->parameterCount() == 2 + bootstrapArray->length()) { + // We're calling the simpler `metafactory`. 2 + bootstrapArray->length() is the + // arguments to the bootstrap method (bootstrapArray->length() - 1), plus the 3 static + // arguments (lookup, name, type). + memcpy(RUNTIME_ARRAY_BODY(specBuffer), + bootstrap->spec()->body().begin(), + bootstrap->spec()->length()); + spec = RUNTIME_ARRAY_BODY(specBuffer); + } else { + abort(t); + } + + MethodSpecIterator it(t, spec); + + // Skip over the already handled 3 arguments. + for (unsigned i = 0; i < argument; ++i) + it.next(); + + // If we're calling altMetafactory then we reset the argument + // offset, because we are filling the vararg array instead of the + // final argument array. + if (argArray != array) { + argument = 0; + } + + // `i` iterates through the bootstrap arguments (the +1 is because we skip + // the boostrap method's name), `it` iterates through the corresponding types + // in the method signature + unsigned i = 0; + while (i + 1 < bootstrapArray->length() && it.hasNext()) { + const char* p = it.next(); + + switch (*p) { + case 'L': { + const char* const methodType = "Ljava/lang/invoke/MethodType;"; + const char* const methodHandle = "Ljava/lang/invoke/MethodHandle;"; + if (strncmp(p, methodType, strlen(methodType)) == 0) { + GcMethodType* type = makeMethodType( + t, + c->loader(), + cast( + t, + singletonObject( + t, invocation->pool(), bootstrapArray->body()[i + 1])), + 0, + 0, + 0); + + array->setBodyElement(t, i + argument, type); + } else if (strncmp(p, methodHandle, strlen(methodHandle)) == 0) { + GcReference* reference = cast( + t, + singletonObject( + t, invocation->pool(), bootstrapArray->body()[i + 1])); + int kind = reference->kind(); + + GcMethod* method = cast(t, + resolve(t, + c->loader(), + invocation->pool(), + bootstrapArray->body()[i + 1], + findMethodInClass, + GcNoSuchMethodError::Type)); + + GcMethodHandle* handle + = makeMethodHandle(t, kind, c->loader(), method, 0); + + array->setBodyElement(t, i + argument, handle); + } else { + abort(t); + } + } break; + + case 'I': + case 'F': { + GcInt* box = makeInt( + t, + singletonValue(t, invocation->pool(), bootstrapArray->body()[i + 1])); + + array->setBodyElement(t, i + argument, box); + } break; + + case 'J': + case 'D': { + uint64_t v; + memcpy( + &v, + &singletonValue(t, invocation->pool(), bootstrapArray->body()[i + 1]), + 8); + + GcLong* box = makeLong(t, v); + + array->setBodyElement(t, i + argument, box); + } break; + + default: + abort(t); + } + + ++i; + } + + GcMethodHandle* handle + = (bootstrap->flags() & ACC_STATIC) + ? 0 + : makeMethodHandle(t, REF_invokeSpecial, c->loader(), bootstrap, 0); + + // If we're calling altMetafactory we set the fourth argument to the vararg array. + if (argArray != array) { + argArray->setBodyElement(t, 3, array); + } + + // Finally we make the bootstrap call. + return cast( + t, t->m->processor->invokeArray(t, bootstrap, handle, argArray)); +} + +void noop() +{ +} + +#include "type-constructors.cpp" + +} // namespace vm + +// for debugging +AVIAN_EXPORT void vmfPrintTrace(Thread* t, FILE* out) +{ + class Visitor : public Processor::StackVisitor { + public: + Visitor(Thread* t, FILE* out) : t(t), out(out) + { + } + + virtual bool visit(Processor::StackWalker* walker) + { + const int8_t* class_ = walker->method()->class_()->name()->body().begin(); + const int8_t* method = walker->method()->name()->body().begin(); + int line = t->m->processor->lineNumber(t, walker->method(), walker->ip()); + + fprintf(out, " at %s.%s ", class_, method); + + switch (line) { + case NativeLine: + fprintf(out, "(native)\n"); + break; + case UnknownLine: + fprintf(out, "(unknown line)\n"); + break; + default: + fprintf(out, "(line %d)\n", line); + } + + return true; + } + + Thread* t; + FILE* out; + } v(t, out); + + fprintf(out, "debug trace for thread %p\n", t); + + t->m->processor->walkStack(t, &v); + + fflush(out); +} + +AVIAN_EXPORT void vmPrintTrace(Thread* t) +{ + vmfPrintTrace(t, stderr); +} + +// also for debugging +AVIAN_EXPORT void* vmAddressFromLine(GcMethod* m, unsigned line) +{ + GcCode* code = m->code(); + printf("code: %p\n", code); + GcLineNumberTable* lnt = code->lineNumberTable(); + printf("lnt: %p\n", lnt); + + if (lnt) { + unsigned last = 0; + unsigned bottom = 0; + unsigned top = lnt->length(); + for (unsigned i = bottom; i < top; i++) { + uint64_t ln = lnt->body()[i]; + if (lineNumberLine(ln) == line) + return reinterpret_cast(lineNumberIp(ln)); + else if (lineNumberLine(ln) > line) + return reinterpret_cast(last); + last = lineNumberIp(ln); + } + } + return 0; +} diff --git a/sgx-jvm/avian/src/main.cpp b/sgx-jvm/avian/src/main.cpp new file mode 100644 index 0000000000..dd6b616666 --- /dev/null +++ b/sgx-jvm/avian/src/main.cpp @@ -0,0 +1,295 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#include "stdlib.h" +#include "stdio.h" +#include "string.h" +#include "jni.h" + +#include +#include "avian/finder.h" + +#include + +#if (defined __MINGW32__) || (defined _MSC_VER) +#define PATH_SEPARATOR ';' +#else +#define PATH_SEPARATOR ':' +#endif + +#ifdef _MSC_VER + +#define not! +#define or || +#define and && +#define xor ^ + +#endif // not _MSC_VER + +#ifdef BOOT_LIBRARY + +// since we aren't linking against libstdc++, we must implement this +// ourselves: +extern "C" void __cxa_pure_virtual(void) +{ + abort(); +} + +// we link against a System implmentation, which requires this at link +// time, but it should not be used at runtime: +extern "C" uint64_t vmNativeCall(void*, void*, unsigned, unsigned) +{ + abort(); + // abort is not declared __declspec(noreturn) on MSVC, so we have to + // pretend it might return to make the compiler happy: + return 0; +} + +#endif // BOOT_LIBRARY + +namespace { + +const char* mainClass(const char* jar) +{ + using namespace vm; + + System* system = makeSystem(); + + class MyAllocator : public avian::util::Alloc { + public: + MyAllocator(System* s) : s(s) + { + } + + virtual void* allocate(size_t size) + { + void* p = s->tryAllocate(size); + if (p == 0) { + abort(s); + } + return p; + } + + virtual void free(const void* p, size_t) + { + s->free(p); + } + + System* s; + } allocator(system); + + Finder* finder = makeFinder(system, &allocator, jar, 0); + + char* result = 0; + + System::Region* region = finder->find("META-INF/MANIFEST.MF"); + if (region) { + size_t start = 0; + size_t length; + while (readLine(region->start(), region->length(), &start, &length)) { + const unsigned PrefixLength = 12; + if (strncasecmp("Main-Class: ", + reinterpret_cast(region->start() + start), + PrefixLength) == 0) { + result = static_cast(malloc(length + 1 - PrefixLength)); + memcpy(result, + region->start() + start + PrefixLength, + length - PrefixLength); + result[length - PrefixLength] = 0; + break; + } + start += length; + } + + region->dispose(); + } + + finder->dispose(); + + system->dispose(); + + return result; +} + +void usageAndExit(const char* name) +{ + fprintf( + stderr, + "usage: %s\n" + "\t[{-cp|-classpath} ]\n" + "\t[-Xmx]\n" + "\t[-Xss]\n" + "\t[-Xbootclasspath/p:]\n" + "\t[-Xbootclasspath:]\n" + "\t[-Xbootclasspath/a:]\n" + "\t[-D= ...]\n" + "\t{|-jar } [ ...]\n", + name); + exit(-1); +} + +} // namespace + +int main(int ac, const char** av) +{ + JavaVMInitArgs vmArgs; + vmArgs.version = JNI_VERSION_1_2; + vmArgs.nOptions = 1; + vmArgs.ignoreUnrecognized = JNI_TRUE; + + const char* class_ = 0; + const char* jar = 0; + int argc = 0; + const char** argv = 0; + const char* classpath = "."; + + for (int i = 1; i < ac; ++i) { + if (strcmp(av[i], "-cp") == 0 or strcmp(av[i], "-classpath") == 0) { + if (i + 1 == ac) + usageAndExit(av[0]); + classpath = av[++i]; + } else if (strcmp(av[i], "-jar") == 0) { + if (i + 1 == ac) + usageAndExit(av[0]); + jar = av[++i]; + } else if (strncmp(av[i], "-X", 2) == 0 or strncmp(av[i], "-D", 2) == 0) { + ++vmArgs.nOptions; + } else if (strcmp(av[i], "-client") == 0 or strcmp(av[i], "-server") == 0) { + // ignore + } else if (strcmp(av[i], "-version") == 0) { + fprintf(stderr, "Avian " AVIAN_VERSION "\n"); + exit(0); + } else { + if (jar == 0) { + class_ = av[i++]; + } + if (i < ac) { + argc = ac - i; + argv = av + i; + i = ac; + } + } + } + + if (jar) { + classpath = jar; + + class_ = mainClass(jar); + + if (class_ == 0) { + fprintf(stderr, "Main-Class manifest header not found in %s\n", jar); + exit(-1); + } + } + +#ifdef BOOT_LIBRARY + ++vmArgs.nOptions; +#endif + +#ifdef BOOT_IMAGE + vmArgs.nOptions += 2; +#endif + +#ifdef BOOT_BUILTINS + ++vmArgs.nOptions; +#endif + + RUNTIME_ARRAY(JavaVMOption, options, vmArgs.nOptions); + vmArgs.options = RUNTIME_ARRAY_BODY(options); + + unsigned optionIndex = 0; + +#ifdef BOOT_IMAGE + vmArgs.options[optionIndex++].optionString + = const_cast("-Davian.bootimage=bootimageBin"); + + vmArgs.options[optionIndex++].optionString + = const_cast("-Davian.codeimage=codeimageBin"); +#endif + +#ifdef BOOT_LIBRARY + vmArgs.options[optionIndex++].optionString + = const_cast("-Davian.bootstrap=" BOOT_LIBRARY); +#endif + +#ifdef BOOT_BUILTINS + vmArgs.options[optionIndex++].optionString + = const_cast("-Davian.builtins=" BOOT_BUILTINS); +#endif + +#define CLASSPATH_PROPERTY "-Djava.class.path=" + + size_t classpathSize = strlen(classpath); + size_t classpathPropertyBufferSize = sizeof(CLASSPATH_PROPERTY) + + classpathSize; + + RUNTIME_ARRAY(char, classpathPropertyBuffer, classpathPropertyBufferSize); + memcpy(RUNTIME_ARRAY_BODY(classpathPropertyBuffer), + CLASSPATH_PROPERTY, + sizeof(CLASSPATH_PROPERTY) - 1); + memcpy(RUNTIME_ARRAY_BODY(classpathPropertyBuffer) + + sizeof(CLASSPATH_PROPERTY) - 1, + classpath, + classpathSize + 1); + + vmArgs.options[optionIndex++].optionString + = RUNTIME_ARRAY_BODY(classpathPropertyBuffer); + + for (int i = 1; i < ac; ++i) { + if (strncmp(av[i], "-X", 2) == 0 or strncmp(av[i], "-D", 2) == 0) { + vmArgs.options[optionIndex++].optionString = const_cast(av[i]); + } + } + + if (class_ == 0) { + usageAndExit(av[0]); + } + + JavaVM* vm; + void* env; + JNI_CreateJavaVM(&vm, &env, &vmArgs); + JNIEnv* e = static_cast(env); + + jclass c = 0; + if (not e->ExceptionCheck()) { + c = e->FindClass(class_); + } + + if (jar) { + free(const_cast(class_)); + } + + if (not e->ExceptionCheck()) { + jmethodID m = e->GetStaticMethodID(c, "main", "([Ljava/lang/String;)V"); + if (not e->ExceptionCheck()) { + jclass stringClass = e->FindClass("java/lang/String"); + if (not e->ExceptionCheck()) { + jobjectArray a = e->NewObjectArray(argc, stringClass, 0); + if (not e->ExceptionCheck()) { + for (int i = 0; i < argc; ++i) { + e->SetObjectArrayElement(a, i, e->NewStringUTF(argv[i])); + } + + e->CallStaticVoidMethod(c, m, a); + } + } + } + } + + int exitCode = 0; + if (e->ExceptionCheck()) { + exitCode = -1; + e->ExceptionDescribe(); + } + + vm->DestroyJavaVM(); + + return exitCode; +} diff --git a/sgx-jvm/avian/src/openjdk/caseSensitive/WS2tcpip.h b/sgx-jvm/avian/src/openjdk/caseSensitive/WS2tcpip.h new file mode 100644 index 0000000000..5caab3e7f6 --- /dev/null +++ b/sgx-jvm/avian/src/openjdk/caseSensitive/WS2tcpip.h @@ -0,0 +1 @@ +#include "ws2tcpip.h" diff --git a/sgx-jvm/avian/src/openjdk/caseSensitive/Wincon.h b/sgx-jvm/avian/src/openjdk/caseSensitive/Wincon.h new file mode 100644 index 0000000000..40d2ad2a68 --- /dev/null +++ b/sgx-jvm/avian/src/openjdk/caseSensitive/Wincon.h @@ -0,0 +1,3 @@ +// Console_md.c #includes "Wincon.h", which only matches "wincon.h" on +// a case insensive filesystem, so we redirect here. +#include "wincon.h" diff --git a/sgx-jvm/avian/src/openjdk/jni_md.h b/sgx-jvm/avian/src/openjdk/jni_md.h new file mode 100644 index 0000000000..555c772249 --- /dev/null +++ b/sgx-jvm/avian/src/openjdk/jni_md.h @@ -0,0 +1,30 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#ifndef JNI_MD_H +#define JNI_MD_H + +#include "stdint.h" + +#if (defined __MINGW32__) || (defined _MSC_VER) +#define JNIEXPORT __declspec(dllexport) +#define JNICALL __stdcall +#else // not (defined __MINGW32__) || (defined _MSC_VER) +#define JNIEXPORT __attribute__((visibility("default"))) __attribute__((used)) +#define JNICALL +#endif // not (defined __MINGW32__) || (defined _MSC_VER) + +#define JNIIMPORT + +typedef int32_t jint; +typedef int64_t jlong; +typedef int8_t jbyte; + +#endif // JNI_MD_H diff --git a/sgx-jvm/avian/src/openjdk/my_java_props_macosx.c b/sgx-jvm/avian/src/openjdk/my_java_props_macosx.c new file mode 100644 index 0000000000..f6833283f6 --- /dev/null +++ b/sgx-jvm/avian/src/openjdk/my_java_props_macosx.c @@ -0,0 +1,34 @@ +#include "java_props_macosx.h" + +PreferredToolkit +getPreferredToolkit() +{ + return XToolkit; +} + +void +setOSNameAndVersion(java_props_t* props) +{ + props->os_name = strdup("iOS"); + props->os_version = strdup("Unknown"); +} + +void +setProxyProperties(java_props_t* props) +{ + // ignore +} + +void +setUserHome(java_props_t* props) +{ + // ignore +} + +char* +setupMacOSXLocale(int cat) +{ + return 0; +} + +char* environ[0]; diff --git a/sgx-jvm/avian/src/openjdk/my_management.c b/sgx-jvm/avian/src/openjdk/my_management.c new file mode 100644 index 0000000000..7f117bf58b --- /dev/null +++ b/sgx-jvm/avian/src/openjdk/my_management.c @@ -0,0 +1,2 @@ +#define JNI_OnLoad management_JNI_OnLoad +#include "management.c" diff --git a/sgx-jvm/avian/src/openjdk/my_net_util.c b/sgx-jvm/avian/src/openjdk/my_net_util.c new file mode 100644 index 0000000000..11728df231 --- /dev/null +++ b/sgx-jvm/avian/src/openjdk/my_net_util.c @@ -0,0 +1,20 @@ +#define JNI_OnLoad net_JNI_OnLoad +#include "net_util.c" + +#ifdef _WIN32 + +#undef IN6_SET_ADDR_UNSPECIFIED +#define IN6_SET_ADDR_UNSPECIFIED(a) \ + memset((a)->s6_bytes,0,sizeof(struct in6_addr)) + +void +IN6ADDR_SETANY(struct sockaddr_in6 *a) +{ + a->sin6_family = AF_INET6; + a->sin6_port = 0; + a->sin6_flowinfo = 0; + IN6_SET_ADDR_UNSPECIFIED(&a->sin6_addr); + a->sin6_scope_id = 0; +} + +#endif diff --git a/sgx-jvm/avian/src/openjdk/stubs.cpp b/sgx-jvm/avian/src/openjdk/stubs.cpp new file mode 100644 index 0000000000..c2175fdd34 --- /dev/null +++ b/sgx-jvm/avian/src/openjdk/stubs.cpp @@ -0,0 +1,18 @@ +#include "avian/machine.h" + +using namespace vm; + +extern "C" AVIAN_EXPORT jint JNICALL net_JNI_OnLoad(JavaVM*, void*) +{ + return 0; +} + +extern "C" AVIAN_EXPORT jint JNICALL management_JNI_OnLoad(JavaVM*, void*) +{ + return 0; +} + +extern "C" char* findJavaTZ_md(const char*, const char*) +{ + return 0; +} diff --git a/sgx-jvm/avian/src/powerpc-regs.S b/sgx-jvm/avian/src/powerpc-regs.S new file mode 100644 index 0000000000..da5940f403 --- /dev/null +++ b/sgx-jvm/avian/src/powerpc-regs.S @@ -0,0 +1,64 @@ +#define r0 0 +#define r1 1 +#define r2 2 +#define r3 3 +#define r4 4 +#define r5 5 +#define r6 6 +#define r7 7 +#define r8 8 +#define r9 9 +#define r10 10 +#define r11 11 +#define r12 12 +#define r13 13 +#define r14 14 +#define r15 15 +#define r16 16 +#define r17 17 +#define r18 18 +#define r19 19 +#define r20 20 +#define r21 21 +#define r22 22 +#define r23 23 +#define r24 24 +#define r25 25 +#define r26 26 +#define r27 27 +#define r28 28 +#define r29 29 +#define r30 30 +#define r31 31 +#define f0 0 +#define f1 1 +#define f2 2 +#define f3 3 +#define f4 4 +#define f5 5 +#define f6 6 +#define f7 7 +#define f8 8 +#define f9 9 +#define f10 10 +#define f11 11 +#define f12 12 +#define f13 13 +#define f14 14 +#define f15 15 +#define f16 16 +#define f17 17 +#define f18 18 +#define f19 19 +#define f20 20 +#define f21 21 +#define f22 22 +#define f23 23 +#define f24 24 +#define f25 25 +#define f26 26 +#define f27 27 +#define f28 28 +#define f29 29 +#define f30 30 +#define f31 31 diff --git a/sgx-jvm/avian/src/process.cpp b/sgx-jvm/avian/src/process.cpp new file mode 100644 index 0000000000..ba6cfd5809 --- /dev/null +++ b/sgx-jvm/avian/src/process.cpp @@ -0,0 +1,310 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#include "avian/process.h" + +#include + +using namespace vm; + +namespace { + +unsigned mangledSize(int8_t c) +{ + switch (c) { + case '_': + case ';': + case '[': + return 2; + + case '$': + return 6; + + default: + return 1; + } +} + +unsigned mangle(int8_t c, char* dst) +{ + switch (c) { + case '/': + dst[0] = '_'; + return 1; + + case '_': + dst[0] = '_'; + dst[1] = '1'; + return 2; + + case ';': + dst[0] = '_'; + dst[1] = '2'; + return 2; + + case '[': + dst[0] = '_'; + dst[1] = '3'; + return 2; + + case '$': + memcpy(dst, "_00024", 6); + return 6; + + default: + dst[0] = c; + return 1; + } +} + +unsigned jniNameLength(Thread* t UNUSED, GcMethod* method, bool decorate) +{ + unsigned size = 0; + + GcByteArray* className = method->class_()->name(); + for (unsigned i = 0; i < className->length() - 1; ++i) { + size += mangledSize(className->body()[i]); + } + + ++size; + + GcByteArray* methodName = method->name(); + for (unsigned i = 0; i < methodName->length() - 1; ++i) { + size += mangledSize(methodName->body()[i]); + } + + if (decorate) { + size += 2; + + GcByteArray* methodSpec = method->spec(); + for (unsigned i = 1; + i < methodSpec->length() - 1 and methodSpec->body()[i] != ')'; + ++i) { + size += mangledSize(methodSpec->body()[i]); + } + } + + return size; +} + +void makeJNIName(Thread* t UNUSED, + const char* prefix, + unsigned prefixLength, + char* name, + GcMethod* method, + bool decorate) +{ + memcpy(name, prefix, prefixLength); + name += prefixLength; + + GcByteArray* className = method->class_()->name(); + for (unsigned i = 0; i < className->length() - 1; ++i) { + name += mangle(className->body()[i], name); + } + + *(name++) = '_'; + + GcByteArray* methodName = method->name(); + for (unsigned i = 0; i < methodName->length() - 1; ++i) { + name += mangle(methodName->body()[i], name); + } + + if (decorate) { + *(name++) = '_'; + *(name++) = '_'; + + GcByteArray* methodSpec = method->spec(); + for (unsigned i = 1; + i < methodSpec->length() - 1 and methodSpec->body()[i] != ')'; + ++i) { + name += mangle(methodSpec->body()[i], name); + } + } + + *(name++) = 0; +} + +void* resolveNativeMethod(Thread* t, + const char* undecorated, + const char* decorated) +{ + for (System::Library* lib = t->m->libraries; lib; lib = lib->next()) { + void* p = lib->resolve(undecorated); + if (p) { + return p; + } else { + p = lib->resolve(decorated); + if (p) { + return p; + } + } + } + + return 0; +} + +void* resolveNativeMethod(Thread* t, + GcMethod* method, + const char* prefix, + unsigned prefixLength, + int footprint UNUSED) +{ + unsigned undecoratedSize = prefixLength + jniNameLength(t, method, false); + // extra 6 is for code below: + THREAD_RUNTIME_ARRAY(t, char, undecorated, undecoratedSize + 1 + 6); + makeJNIName(t, + prefix, + prefixLength, + RUNTIME_ARRAY_BODY(undecorated) + 1, + method, + false); + + unsigned decoratedSize = prefixLength + jniNameLength(t, method, true); + // extra 6 is for code below: + THREAD_RUNTIME_ARRAY(t, char, decorated, decoratedSize + 1 + 6); + makeJNIName( + t, prefix, prefixLength, RUNTIME_ARRAY_BODY(decorated) + 1, method, true); + + void* p = resolveNativeMethod(t, + RUNTIME_ARRAY_BODY(undecorated) + 1, + RUNTIME_ARRAY_BODY(decorated) + 1); + if (p) { + return p; + } + +#ifdef PLATFORM_WINDOWS + // on windows, we also try the _%s@%d and %s@%d variants + if (footprint == -1) { + footprint = method->parameterFootprint() + 1; + if (method->flags() & ACC_STATIC) { + ++footprint; + } + } + + *RUNTIME_ARRAY_BODY(undecorated) = '_'; + vm::snprintf(RUNTIME_ARRAY_BODY(undecorated) + undecoratedSize + 1, + 5, + "@%d", + footprint * BytesPerWord); + + *RUNTIME_ARRAY_BODY(decorated) = '_'; + vm::snprintf(RUNTIME_ARRAY_BODY(decorated) + decoratedSize + 1, + 5, + "@%d", + footprint * BytesPerWord); + + p = resolveNativeMethod( + t, RUNTIME_ARRAY_BODY(undecorated), RUNTIME_ARRAY_BODY(decorated)); + if (p) { + return p; + } + + // one more try without the leading underscore + p = resolveNativeMethod(t, + RUNTIME_ARRAY_BODY(undecorated) + 1, + RUNTIME_ARRAY_BODY(decorated) + 1); + if (p) { + return p; + } +#endif + + return 0; +} + +GcNative* resolveNativeMethod(Thread* t, GcMethod* method) +{ + void* p = resolveNativeMethod(t, method, "Avian_", 6, 3); + if (p) { + return makeNative(t, p, true); + } + + p = resolveNativeMethod(t, method, "Java_", 5, -1); + if (p) { + return makeNative(t, p, false); + } + + return 0; +} + +} // namespace + +namespace vm { + +void resolveNative(Thread* t, GcMethod* method) +{ + PROTECT(t, method); + + assertT(t, method->flags() & ACC_NATIVE); + + initClass(t, method->class_()); + + if (getMethodRuntimeData(t, method)->native() == 0) { + GcNative* native = resolveNativeMethod(t, method); + if (UNLIKELY(native == 0)) { + throwNew(t, + GcUnsatisfiedLinkError::Type, + "%s.%s%s", + method->class_()->name()->body().begin(), + method->name()->body().begin(), + method->spec()->body().begin()); + } + + PROTECT(t, native); + + GcMethodRuntimeData* runtimeData = getMethodRuntimeData(t, method); + + // ensure other threads only see the methodRuntimeDataNative field + // populated once the object it points to has been populated: + storeStoreMemoryBarrier(); + + runtimeData->setNative(t, native); + } +} + +int findLineNumber(Thread* t UNUSED, GcMethod* method, unsigned ip) +{ + if (method->flags() & ACC_NATIVE) { + return NativeLine; + } + + // our parameter indicates the instruction following the one we care + // about, so we back up first: + --ip; + + GcLineNumberTable* lnt = method->code()->lineNumberTable(); + if (lnt) { + unsigned bottom = 0; + unsigned top = lnt->length(); + for (unsigned span = top - bottom; span; span = top - bottom) { + unsigned middle = bottom + (span / 2); + uint64_t ln = lnt->body()[middle]; + + if (ip >= lineNumberIp(ln) + and (middle + 1 == lnt->length() + or ip < lineNumberIp(lnt->body()[middle + 1]))) { + return lineNumberLine(ln); + } else if (ip < lineNumberIp(ln)) { + top = middle; + } else if (ip > lineNumberIp(ln)) { + bottom = middle + 1; + } + } + + if (top < lnt->length()) { + return lineNumberLine(lnt->body()[top]); + } else { + return UnknownLine; + } + } else { + return UnknownLine; + } +} + +} // namespace vm diff --git a/sgx-jvm/avian/src/system/CMakeLists.txt b/sgx-jvm/avian/src/system/CMakeLists.txt new file mode 100644 index 0000000000..5c6f2a58fa --- /dev/null +++ b/sgx-jvm/avian/src/system/CMakeLists.txt @@ -0,0 +1,7 @@ + +if (MSVC) + #todo: support mingw compiler + add_library(avian_system windows.cpp windows/crash.cpp) +else() + add_library(avian_system posix.cpp posix/crash.cpp) +endif() diff --git a/sgx-jvm/avian/src/system/posix.cpp b/sgx-jvm/avian/src/system/posix.cpp new file mode 100644 index 0000000000..64a667887c --- /dev/null +++ b/sgx-jvm/avian/src/system/posix.cpp @@ -0,0 +1,1002 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#ifndef __STDC_CONSTANT_MACROS +#define __STDC_CONSTANT_MACROS +#endif + +#include "sys/types.h" +#ifdef __APPLE__ +#include "CoreFoundation/CoreFoundation.h" +#include "sys/ucontext.h" +#undef assert +#elif defined(__ANDROID__) +#include /* for sigcontext */ +#include /* for stack_t */ +typedef struct ucontext { + unsigned long uc_flags; + struct ucontext* uc_link; + stack_t uc_stack; + struct sigcontext uc_mcontext; + unsigned long uc_sigmask; +} ucontext_t; +#else +#if defined __FreeBSD__ +#include "limits.h" +#endif +#include "ucontext.h" +#endif + +#include "sys/mman.h" + +#include "sys/stat.h" +#include "sys/time.h" +#include "time.h" +#include "fcntl.h" +#include "dlfcn.h" +#include "errno.h" +#include "unistd.h" +#include "pthread.h" +#include "signal.h" +#include "stdint.h" +#include "dirent.h" +#include "sched.h" + +#include +#include + +#include +#include +#include +#include + +#define ACQUIRE(x) MutexResource MAKE_NAME(mutexResource_)(x) + +using namespace vm; +using namespace avian::util; + +namespace { + +class MutexResource { + public: + MutexResource(pthread_mutex_t& m) : m(&m) + { + pthread_mutex_lock(&m); + } + + ~MutexResource() + { + pthread_mutex_unlock(m); + } + + private: + pthread_mutex_t* m; +}; + +const int VisitSignal = SIGUSR1; +const unsigned VisitSignalIndex = 0; +const int InterruptSignal = SIGUSR2; +const unsigned InterruptSignalIndex = 1; +const int PipeSignal = SIGPIPE; +const unsigned PipeSignalIndex = 2; + +const int signals[] = {VisitSignal, InterruptSignal, PipeSignal}; + +const unsigned SignalCount = 3; + +class MySystem; +MySystem* globalSystem; + +void handleSignal(int signal, siginfo_t* info, void* context); + +void* run(void* r) +{ + static_cast(r)->run(); + return 0; +} + +void pathOfExecutable(System* s, const char** retBuf, unsigned* size) +{ +#ifdef __APPLE__ + CFBundleRef bundle = CFBundleGetMainBundle(); + CFURLRef url = CFBundleCopyExecutableURL(bundle); + CFStringRef path = CFURLCopyPath(url); + path = CFURLCreateStringByReplacingPercentEscapes( + kCFAllocatorDefault, path, CFSTR("")); + CFIndex pathSize = CFStringGetMaximumSizeOfFileSystemRepresentation(path); + char* buffer = reinterpret_cast(allocate(s, pathSize)); + if (CFStringGetFileSystemRepresentation(path, buffer, pathSize)) { + *size = pathSize; + *retBuf = buffer; + } else { + abort(); + } +#else + if (s) + *size = 0; + *retBuf = NULL; +#endif +} + +const bool Verbose = false; + +const unsigned Notified = 1 << 0; + +class MySystem : public System { + public: + class Thread : public System::Thread { + public: + Thread(System* s, System::Runnable* r) : s(s), r(r), next(0), flags(0) + { + pthread_mutex_init(&mutex, 0); + pthread_cond_init(&condition, 0); + } + + virtual void interrupt() + { + ACQUIRE(mutex); + + r->setInterrupted(true); + + pthread_kill(thread, InterruptSignal); + + // pthread_kill won't necessarily wake a thread blocked in + // pthread_cond_{timed}wait (it does on Linux but not Mac OS), + // so we signal the condition as well: + int rv UNUSED = pthread_cond_signal(&condition); + expect(s, rv == 0); + } + + virtual bool getAndClearInterrupted() + { + ACQUIRE(mutex); + + bool interrupted = r->interrupted(); + + r->setInterrupted(false); + + return interrupted; + } + + virtual void join() + { + int rv UNUSED = pthread_join(thread, 0); + expect(s, rv == 0); + } + + virtual void dispose() + { + pthread_mutex_destroy(&mutex); + pthread_cond_destroy(&condition); + ::free(this); + } + + pthread_t thread; + pthread_mutex_t mutex; + pthread_cond_t condition; + System* s; + System::Runnable* r; + Thread* next; + unsigned flags; + }; + + class Mutex : public System::Mutex { + public: + Mutex(System* s) : s(s) + { + pthread_mutex_init(&mutex, 0); + } + + virtual void acquire() + { + pthread_mutex_lock(&mutex); + } + + virtual void release() + { + pthread_mutex_unlock(&mutex); + } + + virtual void dispose() + { + pthread_mutex_destroy(&mutex); + ::free(this); + } + + System* s; + pthread_mutex_t mutex; + }; + + class Monitor : public System::Monitor { + public: + Monitor(System* s) : s(s), owner_(0), first(0), last(0), depth(0) + { + pthread_mutex_init(&mutex, 0); + } + + virtual bool tryAcquire(System::Thread* context) + { + Thread* t = static_cast(context); + + if (owner_ == t) { + ++depth; + return true; + } else { + switch (pthread_mutex_trylock(&mutex)) { + case EBUSY: + return false; + + case 0: + owner_ = t; + ++depth; + return true; + + default: + sysAbort(s); + } + } + } + + virtual void acquire(System::Thread* context) + { + Thread* t = static_cast(context); + + if (owner_ != t) { + pthread_mutex_lock(&mutex); + owner_ = t; + } + ++depth; + } + + virtual void release(System::Thread* context) + { + Thread* t = static_cast(context); + + if (owner_ == t) { + if (--depth == 0) { + owner_ = 0; + pthread_mutex_unlock(&mutex); + } + } else { + sysAbort(s); + } + } + + void append(Thread* t) + { +#ifndef NDEBUG + for (Thread* x = first; x; x = x->next) { + expect(s, t != x); + } +#endif + + if (last) { + expect(s, t != last); + last->next = t; + last = t; + } else { + first = last = t; + } + } + + void remove(Thread* t) + { + Thread* previous = 0; + for (Thread* current = first; current;) { + if (t == current) { + if (current == first) { + first = t->next; + } else { + expect(s, previous != t->next); + previous->next = t->next; + } + + if (current == last) { + last = previous; + } + + t->next = 0; + + break; + } else { + previous = current; + current = current->next; + } + } + +#ifndef NDEBUG + for (Thread* x = first; x; x = x->next) { + expect(s, t != x); + } +#endif + } + + virtual void wait(System::Thread* context, int64_t time) + { + wait(context, time, false); + } + + virtual bool waitAndClearInterrupted(System::Thread* context, int64_t time) + { + return wait(context, time, true); + } + + bool wait(System::Thread* context, int64_t time, bool clearInterrupted) + { + Thread* t = static_cast(context); + + if (owner_ == t) { + // Initialized here to make gcc 4.2 a happy compiler + bool interrupted = false; + bool notified = false; + unsigned depth = 0; + + { + ACQUIRE(t->mutex); + + expect(s, (t->flags & Notified) == 0); + + interrupted = t->r->interrupted(); + if (interrupted and clearInterrupted) { + t->r->setInterrupted(false); + } + + append(t); + + depth = this->depth; + this->depth = 0; + owner_ = 0; + pthread_mutex_unlock(&mutex); + + if (not interrupted) { + // pretend anything greater than one million years (in + // milliseconds) is infinity so as to avoid overflow: + if (time and time < INT64_C(31536000000000000)) { + int64_t then = s->now() + time; + timespec ts = {static_cast(then / 1000), + static_cast((then % 1000) * 1000 * 1000)}; + int rv UNUSED + = pthread_cond_timedwait(&(t->condition), &(t->mutex), &ts); + expect(s, rv == 0 or rv == ETIMEDOUT or rv == EINTR); + } else { + int rv UNUSED = pthread_cond_wait(&(t->condition), &(t->mutex)); + expect(s, rv == 0 or rv == EINTR); + } + + interrupted = t->r->interrupted(); + if (interrupted and clearInterrupted) { + t->r->setInterrupted(false); + } + } + + notified = ((t->flags & Notified) != 0); + } + + pthread_mutex_lock(&mutex); + + { + ACQUIRE(t->mutex); + t->flags = 0; + } + + if (not notified) { + remove(t); + } else { +#ifndef NDEBUG + for (Thread* x = first; x; x = x->next) { + expect(s, t != x); + } +#endif + } + + t->next = 0; + + owner_ = t; + this->depth = depth; + + return interrupted; + } else { + sysAbort(s); + } + } + + void doNotify(Thread* t) + { + ACQUIRE(t->mutex); + + t->flags |= Notified; + int rv UNUSED = pthread_cond_signal(&(t->condition)); + expect(s, rv == 0); + } + + virtual void notify(System::Thread* context) + { + Thread* t = static_cast(context); + + if (owner_ == t) { + if (first) { + Thread* t = first; + first = first->next; + if (t == last) { + expect(s, first == 0); + last = 0; + } + + doNotify(t); + } + } else { + sysAbort(s); + } + } + + virtual void notifyAll(System::Thread* context) + { + Thread* t = static_cast(context); + + if (owner_ == t) { + for (Thread* t = first; t; t = t->next) { + doNotify(t); + } + first = last = 0; + } else { + sysAbort(s); + } + } + + virtual System::Thread* owner() + { + return owner_; + } + + virtual void dispose() + { + expect(s, owner_ == 0); + pthread_mutex_destroy(&mutex); + ::free(this); + } + + System* s; + pthread_mutex_t mutex; + Thread* owner_; + Thread* first; + Thread* last; + unsigned depth; + }; + + class Local : public System::Local { + public: + Local(System* s) : s(s) + { + int r UNUSED = pthread_key_create(&key, 0); + expect(s, r == 0); + } + + virtual void* get() + { + return pthread_getspecific(key); + } + + virtual void set(void* p) + { + int r UNUSED = pthread_setspecific(key, p); + expect(s, r == 0); + } + + virtual void dispose() + { + int r UNUSED = pthread_key_delete(key); + expect(s, r == 0); + + ::free(this); + } + + System* s; + pthread_key_t key; + }; + + class Region : public System::Region { + public: + Region(System* s, uint8_t* start, size_t length) + : s(s), start_(start), length_(length) + { + } + + virtual const uint8_t* start() + { + return start_; + } + + virtual size_t length() + { + return length_; + } + + virtual void dispose() + { + if (start_) { + munmap(start_, length_); + } + ::free(this); + } + + System* s; + uint8_t* start_; + size_t length_; + }; + + class Directory : public System::Directory { + public: + Directory(System* s, DIR* directory) : s(s), directory(directory) + { + } + + virtual const char* next() + { + if (directory) { + dirent* e = readdir(directory); + if (e) { + return e->d_name; + } + } + return 0; + } + + virtual void dispose() + { + if (directory) { + closedir(directory); + } + ::free(this); + } + + System* s; + DIR* directory; + }; + + class Library : public System::Library { + public: + Library(System* s, + void* p, + const char* name, + unsigned nameLength, + bool isMain) + : s(s), + p(p), + mainExecutable(isMain), + name_(name), + nameLength(nameLength), + next_(0) + { + } + + virtual void* resolve(const char* function) + { + return dlsym(p, function); + } + + virtual const char* name() + { + return name_; + } + + virtual System::Library* next() + { + return next_; + } + + virtual void setNext(System::Library* lib) + { + next_ = lib; + } + + virtual void disposeAll() + { + if (Verbose) { + fprintf(stderr, "close %p\n", p); + } + + if (not mainExecutable) + dlclose(p); + + if (next_) { + next_->disposeAll(); + } + + if (name_) { + ::free(const_cast(name_)); + } + + ::free(this); + } + + System* s; + void* p; + bool mainExecutable; + const char* name_; + unsigned nameLength; + System::Library* next_; + }; + + MySystem(bool reentrant) : reentrant(reentrant), threadVisitor(0), visitTarget(0) + { + if (not reentrant) { + expect(this, globalSystem == 0); + globalSystem = this; + + expect(this, registerHandler(InterruptSignalIndex)); + expect(this, registerHandler(VisitSignalIndex)); + expect(this, registerHandler(PipeSignalIndex)); + + expect(this, make(&visitLock) == 0); + } + } + + // Returns true on success, false on failure + bool unregisterHandler(int index) + { + return sigaction(signals[index], oldHandlers + index, 0) == 0; + } + + // Returns true on success, false on failure + bool registerHandler(int index) + { + struct sigaction sa; + memset(&sa, 0, sizeof(struct sigaction)); + sigemptyset(&(sa.sa_mask)); + sa.sa_flags = SA_SIGINFO; + sa.sa_sigaction = handleSignal; + + return sigaction(signals[index], &sa, oldHandlers + index) == 0; + } + + virtual void* tryAllocate(size_t sizeInBytes) + { + return malloc(sizeInBytes); + } + + virtual void free(const void* p) + { + if (p) + ::free(const_cast(p)); + } + + virtual bool success(Status s) { + return s == 0; + } + + virtual Status attach(Runnable* r) + { + Thread* t = new (allocate(this, sizeof(Thread))) Thread(this, r); + t->thread = pthread_self(); + r->attach(t); + return 0; + } + + virtual Status start(Runnable* r) + { + Thread* t = new (allocate(this, sizeof(Thread))) Thread(this, r); + r->attach(t); + int rv UNUSED = pthread_create(&(t->thread), 0, run, r); + expect(this, rv == 0); + return 0; + } + + virtual Status make(System::Mutex** m) + { + *m = new (allocate(this, sizeof(Mutex))) Mutex(this); + return 0; + } + + virtual Status make(System::Monitor** m) + { + *m = new (allocate(this, sizeof(Monitor))) Monitor(this); + return 0; + } + + virtual Status make(System::Local** l) + { + *l = new (allocate(this, sizeof(Local))) Local(this); + return 0; + } + + virtual Status visit(System::Thread* st UNUSED, + System::Thread* sTarget, + ThreadVisitor* visitor) + { + expect(this, not reentrant); + + assertT(this, st != sTarget); + + Thread* target = static_cast(sTarget); + +#ifdef __APPLE__ + // On Mac OS, signals sent using pthread_kill are never delivered + // if the target thread is blocked (e.g. acquiring a lock or + // waiting on a condition), so we can't rely on it and must use + // the Mach-specific thread execution API instead. + + mach_port_t port = pthread_mach_thread_np(target->thread); + + if (thread_suspend(port)) + return -1; + + THREAD_STATE_TYPE state; + mach_msg_type_number_t stateCount = THREAD_STATE_COUNT; + kern_return_t rv + = thread_get_state(port, + THREAD_STATE, + reinterpret_cast(&state), + &stateCount); + + if (rv == 0) { + visitor->visit(reinterpret_cast(THREAD_STATE_IP(state)), + reinterpret_cast(THREAD_STATE_STACK(state)), + reinterpret_cast(THREAD_STATE_LINK(state))); + } + + thread_resume(port); + + return rv ? -1 : 0; +#else // not __APPLE__ + Thread* t = static_cast(st); + + ACQUIRE_MONITOR(t, visitLock); + + while (threadVisitor) + visitLock->wait(t, 0); + + threadVisitor = visitor; + visitTarget = target; + + int rv = pthread_kill(target->thread, VisitSignal); + + int result; + if (rv == 0) { + while (visitTarget) + visitLock->wait(t, 0); + + result = 0; + } else { + visitTarget = 0; + + result = -1; + } + + threadVisitor = 0; + + globalSystem->visitLock->notifyAll(t); + + return result; +#endif // not __APPLE__ + } + + virtual Status map(System::Region** region, const char* name) + { + Status status = 1; + + int fd = ::open(name, O_RDONLY); + if (fd != -1) { + struct stat s; + int r = fstat(fd, &s); + if (r != -1) { + void* data = mmap(0, s.st_size, PROT_READ, MAP_PRIVATE, fd, 0); + if (data) { + *region = new (allocate(this, sizeof(Region))) + Region(this, static_cast(data), s.st_size); + status = 0; + } + } + close(fd); + } + + return status; + } + + virtual Status open(System::Directory** directory, const char* name) + { + Status status = 1; + + DIR* d = opendir(name); + if (d) { + *directory = new (allocate(this, sizeof(Directory))) Directory(this, d); + status = 0; + } + + return status; + } + + virtual FileType stat(const char* name, size_t* length) + { +#ifdef __FreeBSD__ + // Now the hack below causes the error "Dereferencing type-punned + // pointer will break strict aliasing rules", so another workaround + // is needed... + struct stat ss; + struct stat* s = &ss; +#else + // Ugly Hack Alert: It seems that the Apple iOS Simulator's stat + // implementation writes beyond the end of the struct stat we pass + // it, which can clobber unrelated parts of the stack. Perhaps + // this is due to some kind of header/library mismatch, but I've + // been unable to track it down so far. The workaround is to give + // it 8 words more than it should need, where 8 is a number I just + // made up and seems to work. + void* array[ceilingDivide(sizeof(struct stat), sizeof(void*)) + 8]; + struct stat* s = reinterpret_cast(array); +#endif + + int r = ::stat(name, s); + if (r == 0) { + if (S_ISREG(s->st_mode)) { + *length = s->st_size; + return TypeFile; + } else if (S_ISDIR(s->st_mode)) { + *length = 0; + return TypeDirectory; + } else { + *length = 0; + return TypeUnknown; + } + } else { + *length = 0; + return TypeDoesNotExist; + } + } + + virtual const char* libraryPrefix() + { + return SO_PREFIX; + } + + virtual const char* librarySuffix() + { + return SO_SUFFIX; + } + + virtual const char* toAbsolutePath(AllocOnly* allocator, const char* name) + { + if (name[0] == '/') { + return copy(allocator, name); + } else { + char buffer[PATH_MAX]; + return append(allocator, getcwd(buffer, PATH_MAX), "/", name); + } + } + + virtual Status load(System::Library** lib, const char* name) + { + unsigned nameLength = (name ? strlen(name) : 0); + bool isMain = name == 0; + if (isMain) { + pathOfExecutable(this, &name, &nameLength); + } + void* p = dlopen(name, RTLD_LAZY | RTLD_LOCAL); + + if (p) { + if (Verbose) { + fprintf(stderr, "open %s as %p\n", name, p); + } + + char* n; + if (name) { + n = static_cast(allocate(this, nameLength + 1)); + memcpy(n, name, nameLength + 1); + if (isMain) { + free(name); + } + } else { + n = 0; + } + + *lib = new (allocate(this, sizeof(Library))) + Library(this, p, n, nameLength, isMain); + + return 0; + } else { + if (Verbose) { + fprintf(stderr, "dlerror opening %s: %s\n", name, dlerror()); + } + return 1; + } + } + + virtual char pathSeparator() + { + return ':'; + } + + virtual char fileSeparator() + { + return '/'; + } + + virtual int64_t now() + { + timeval tv = {0, 0}; + gettimeofday(&tv, 0); + return (static_cast(tv.tv_sec) * 1000) + + (static_cast(tv.tv_usec) / 1000); + } + + virtual void yield() + { + sched_yield(); + } + + virtual void exit(int code) + { + ::exit(code); + } + + virtual void abort() + { + avian::system::crash(); + } + + virtual void dispose() + { + if (not reentrant) { + visitLock->dispose(); + + expect(this, unregisterHandler(InterruptSignalIndex)); + expect(this, unregisterHandler(VisitSignalIndex)); + expect(this, unregisterHandler(PipeSignalIndex)); + globalSystem = 0; + } + + ::free(this); + } + + struct sigaction oldHandlers[SignalCount]; + + bool reentrant; + ThreadVisitor* threadVisitor; + Thread* visitTarget; + System::Monitor* visitLock; +}; + +void handleSignal(int signal, siginfo_t*, void* context) +{ + ucontext_t* c = static_cast(context); + + void* ip = reinterpret_cast(IP_REGISTER(c)); + void* stack = reinterpret_cast(STACK_REGISTER(c)); + void* link = reinterpret_cast(LINK_REGISTER(c)); + + switch (signal) { + case VisitSignal: { + globalSystem->threadVisitor->visit(ip, stack, link); + + System::Thread* t = globalSystem->visitTarget; + globalSystem->visitTarget = 0; + + ACQUIRE_MONITOR(t, globalSystem->visitLock); + globalSystem->visitLock->notifyAll(t); + } break; + + case InterruptSignal: + case PipeSignal: + break; + + default: + abort(); + } +} + +} // namespace + +namespace vm { + +AVIAN_EXPORT System* makeSystem(bool reentrant) +{ + return new (malloc(sizeof(MySystem))) MySystem(reentrant); +} + +} // namespace vm diff --git a/sgx-jvm/avian/src/system/posix/crash.cpp b/sgx-jvm/avian/src/system/posix/crash.cpp new file mode 100644 index 0000000000..c275e6fb29 --- /dev/null +++ b/sgx-jvm/avian/src/system/posix/crash.cpp @@ -0,0 +1,22 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#include + +namespace avian { +namespace system { + +NO_RETURN void crash() +{ + abort(); +} + +} // namespace system +} // namespace avian diff --git a/sgx-jvm/avian/src/system/posix/memory.cpp b/sgx-jvm/avian/src/system/posix/memory.cpp new file mode 100644 index 0000000000..4b00666bed --- /dev/null +++ b/sgx-jvm/avian/src/system/posix/memory.cpp @@ -0,0 +1,63 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#include + +#include + +#include "sys/mman.h" + +namespace avian { +namespace system { + +const size_t Memory::PageSize = 1 << 12; + +util::Slice Memory::allocate(size_t sizeInBytes, + Permissions perms) +{ + unsigned prot = 0; + if(perms & Read) { + prot |= PROT_READ; + } + if(perms & Write) { + prot |= PROT_WRITE; + } + if(perms & Execute) { + prot |= PROT_EXEC; + } +#ifdef MAP_32BIT + // map to the lower 32 bits of memory when possible so as to avoid + // expensive relative jumps + const unsigned Extra = MAP_32BIT; +#else + const unsigned Extra = 0; +#endif + + void* p = mmap(0, + sizeInBytes, + prot, + MAP_PRIVATE | MAP_ANON | Extra, + -1, + 0); + + if (p == MAP_FAILED) { + return util::Slice(0, 0); + } else { + return util::Slice(static_cast(p), sizeInBytes); + } +} + +void Memory::free(util::Slice pages) +{ + munmap(const_cast(pages.begin()), pages.count); +} + +} // namespace system +} // namespace avian diff --git a/sgx-jvm/avian/src/system/posix/signal.cpp b/sgx-jvm/avian/src/system/posix/signal.cpp new file mode 100644 index 0000000000..9d8b7c7463 --- /dev/null +++ b/sgx-jvm/avian/src/system/posix/signal.cpp @@ -0,0 +1,227 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#include "signal.h" +#include "sys/types.h" +#ifdef __APPLE__ +#include "CoreFoundation/CoreFoundation.h" +#include "sys/ucontext.h" +#undef assert +#elif defined(__ANDROID__) +#include /* for sigcontext */ +#include /* for stack_t */ +typedef struct ucontext { + unsigned long uc_flags; + struct ucontext* uc_link; + stack_t uc_stack; + struct sigcontext uc_mcontext; + unsigned long uc_sigmask; +} ucontext_t; +#else +#if defined __FreeBSD__ +#include "limits.h" +#endif +#include "ucontext.h" +#endif + +#include "avian/arch.h" +#include +#include + +namespace avian { +namespace system { + +namespace posix { + +const int InvalidSignal = -1; +const int SegFaultSignal = SIGSEGV; +const unsigned SegFaultSignalIndex = 0; +#ifdef __APPLE__ +const int AltSegFaultSignal = SIGBUS; +#else +const int AltSegFaultSignal = InvalidSignal; +#endif +const unsigned AltSegFaultSignalIndex = 1; +const int DivideByZeroSignal = SIGFPE; +const unsigned DivideByZeroSignalIndex = 2; + +const int signals[] = {SegFaultSignal, AltSegFaultSignal, DivideByZeroSignal}; + +const unsigned SignalCount = 3; +} + +struct SignalRegistrar::Data { + Handler* handlers[posix::SignalCount]; + struct sigaction oldHandlers[posix::SignalCount]; + + bool registerHandler(Handler* handler, int index); + + Data() + { + if (instance) { + crash(); + } + + instance = this; + } + + ~Data() + { + instance = 0; + } + + static SignalRegistrar::Data* instance; +}; + +SignalRegistrar::Data* SignalRegistrar::Data::instance = 0; + +namespace posix { + +using namespace vm; + +void handleSignal(int signal, siginfo_t*, void* context) +{ + ucontext_t* c = static_cast(context); + + void* ip = reinterpret_cast(IP_REGISTER(c)); + void* stack = reinterpret_cast(STACK_REGISTER(c)); + void* thread = reinterpret_cast(THREAD_REGISTER(c)); +#ifdef FRAME_REGISTER + void* frame = reinterpret_cast(FRAME_REGISTER(c)); +#else + void* frame = 0; +#endif + + unsigned index; + + switch (signal) { + case SegFaultSignal: + case AltSegFaultSignal: + case DivideByZeroSignal: { + switch (signal) { + case SegFaultSignal: + index = SegFaultSignalIndex; + break; + + case AltSegFaultSignal: + index = AltSegFaultSignalIndex; + break; + + case DivideByZeroSignal: + index = DivideByZeroSignalIndex; + break; + + default: + crash(); + } + + bool jump = SignalRegistrar::Data::instance->handlers[index]->handleSignal( + &ip, &frame, &stack, &thread); + + if (jump) { + // I'd like to use setcontext here (and get rid of the + // sigprocmask call), but it doesn't work on my Linux x86_64 + // system, and I can't tell from the documentation if it's even + // supposed to work. + + sigset_t set; + sigemptyset(&set); + sigaddset(&set, signal); + pthread_sigmask(SIG_UNBLOCK, &set, 0); + + vmJump(ip, frame, stack, thread, 0, 0); + } else { + crash(); + } + } break; + + default: + crash(); + } +} + +} // namespace posix + +SignalRegistrar::SignalRegistrar() +{ + data = new (malloc(sizeof(Data))) Data(); +} + +SignalRegistrar::~SignalRegistrar() +{ + data->~Data(); + free(data); +} + +bool SignalRegistrar::Data::registerHandler(Handler* handler, int index) +{ + if (handler) { + handlers[index] = handler; + + struct sigaction sa; + memset(&sa, 0, sizeof(struct sigaction)); + sigemptyset(&(sa.sa_mask)); + sa.sa_flags = SA_SIGINFO; + sa.sa_sigaction = posix::handleSignal; + + return sigaction(posix::signals[index], &sa, oldHandlers + index) == 0; + } else if (handlers[index]) { + handlers[index] = 0; + return sigaction(posix::signals[index], oldHandlers + index, 0) == 0; + } else { + return false; + } +} + +bool SignalRegistrar::registerHandler(Signal signal, Handler* handler) +{ + switch (signal) { + case SegFault: + if (!data->registerHandler(handler, posix::SegFaultSignalIndex)) { + return false; + } + if (posix::AltSegFaultSignal != posix::InvalidSignal) { + return data->registerHandler(handler, posix::AltSegFaultSignalIndex); + } else { + return true; + } + case DivideByZero: + return data->registerHandler(handler, posix::DivideByZeroSignalIndex); + default: + crash(); + } +} + +bool SignalRegistrar::unregisterHandler(Signal signal) +{ + switch (signal) { + case SegFault: + if (!data->registerHandler(0, posix::SegFaultSignalIndex)) { + return false; + } + if (posix::AltSegFaultSignal != posix::InvalidSignal) { + return data->registerHandler(0, posix::AltSegFaultSignalIndex); + } else { + return true; + } + case DivideByZero: + return data->registerHandler(0, posix::DivideByZeroSignalIndex); + default: + crash(); + } +} + +void SignalRegistrar::setCrashDumpDirectory(const char*) +{ + // Do nothing, not currently supported on posix +} + +} // namespace system +} // namespace avian diff --git a/sgx-jvm/avian/src/system/sgx.cpp b/sgx-jvm/avian/src/system/sgx.cpp new file mode 100644 index 0000000000..62a1547856 --- /dev/null +++ b/sgx-jvm/avian/src/system/sgx.cpp @@ -0,0 +1,519 @@ +// (C) 2016 R3 CEV Ltd +// +// Platform implementation for an Intel SGX enclave, which is similar to having no platform at all. + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#define PATH_MAX 256 + +using namespace vm; +using namespace avian::util; + +// Weak link against the JAR functions that the Avian embedder must provide. +// This lets us look it up at runtime without having it be present in libavian.a +extern "C" __attribute__((weak)) const uint8_t* embedded_file_boot_jar(size_t* size); +extern "C" __attribute__((weak)) const uint8_t* embedded_file_app_jar(size_t* size); + +extern "C" const uint8_t* javahomeJar(size_t* size); + +namespace { + void abort_with(const char *msg) { + printf("%s\n", msg); + while(true); + } + + class MySystem; + MySystem* globalSystem; + const bool Verbose = false; + + class MySystem : public System { + public: + class Thread : public System::Thread { + public: + Thread* next; + + Thread(System* s UNUSED, System::Runnable* r UNUSED) : next(0) + { + } + + virtual void interrupt() + { + printf("Thread::Interrupt()\n"); + } + + virtual bool getAndClearInterrupted() + { + printf("Thread::getAndClearInterrupted()\n"); + return false; + } + + virtual void join() + { + printf("Thread::Join()\n"); + } + + virtual void dispose() + { + } + }; + + class Mutex : public System::Mutex { + public: + Mutex(System* s) : s(s) + { + + } + + virtual void acquire() + { + + } + + virtual void release() + { + + } + + virtual void dispose() + { + + } + + System* s; + }; + + class Monitor : public System::Monitor { + public: + Monitor(System* s) : s(s), owner_(0), first(0), last(0), depth(0) + { + + } + + virtual bool tryAcquire(System::Thread* context UNUSED) + { + return true; + } + + virtual void acquire(System::Thread* context UNUSED) + { + } + + virtual void release(System::Thread* context UNUSED) + { + } + + void append(Thread* t) + { + for (Thread* x = first; x; x = x->next) { + expect(s, t != x); + } + + if (last) { + expect(s, t != last); + last->next = t; + last = t; + } else { + first = last = t; + } + } + + void remove(Thread* t) + { + Thread* previous = 0; + for (Thread* current = first; current;) { + if (t == current) { + if (current == first) { + first = t->next; + } else { + expect(s, previous != t->next); + previous->next = t->next; + } + + if (current == last) { + last = previous; + } + + t->next = 0; + + break; + } else { + previous = current; + current = current->next; + } + } + + for (Thread* x = first; x; x = x->next) { + expect(s, t != x); + } + } + + virtual void wait(System::Thread* context UNUSED, int64_t time UNUSED) + { + wait(context, time, false); + } + + virtual bool waitAndClearInterrupted(System::Thread* context UNUSED, int64_t time UNUSED) + { + return wait(context, time, true); + } + + bool wait(System::Thread* context UNUSED, int64_t time UNUSED, bool clearInterrupted UNUSED) + { + abort_with("STUB: Thread::Wait()"); + return true; + } + + void doNotify(Thread* t UNUSED) + { + printf("STUB: Thread::Notify()\n"); + } + + virtual void notify(System::Thread* context UNUSED) + { + } + + virtual void notifyAll(System::Thread* context UNUSED) + { + } + + virtual System::Thread* owner() + { + return owner_; + } + + virtual void dispose() + { + expect(s, owner_ == 0); + ::free(this); + } + + System* s; + Thread* owner_; + Thread* first; + Thread* last; + unsigned depth; + }; + + class Local : public System::Local { + public: + void *value; + + Local(System* s) : s(s) + { + } + + virtual void* get() + { + return value; + } + + virtual void set(void* p) + { + value = p; + } + + virtual void dispose() + { + ::free(this); + } + + System* s; + }; + + class Region : public System::Region { + public: + Region(System* s, uint8_t* start, size_t length) + : s(s), start_(start), length_(length) + { + } + + virtual const uint8_t* start() + { + return start_; + } + + virtual size_t length() + { + return length_; + } + + virtual void dispose() + { + if (start_) { + printf("STUB: munmap\n"); + //munmap(start_, length_); + } + ::free(this); + } + + System* s; + uint8_t* start_; + size_t length_; + }; + + class Directory : public System::Directory { + public: + Directory(System* s, void* directory UNUSED) : s(s) + { + } + + virtual const char* next() + { + return 0; + } + + virtual void dispose() + { + ::free(this); + } + + System* s; + }; + + class Library : public System::Library { + public: + Library(System* s UNUSED) : next_(0) {} + + virtual void* resolve(const char* function) + { + const void *ptr = NULL; + if (!strcmp(function, "embedded_file_boot_jar")) { + return (void *) &embedded_file_boot_jar; + } if (!strcmp(function, "embedded_file_app_jar")) { + return (void *) &embedded_file_app_jar; + } if (!strcmp(function, "javahomeJar")) { + return (void *) &javahomeJar; + } else if ((ptr = dlsym(NULL, function))) { + return (void *) ptr; + } else { + // If you seem to be hitting a JNI call you're sure should exist, try uncommenting this. + // It is expected that some resolutions won't work as multiple names are tried for each + // native call, which is why we don't spam them all to the logs here. + // + // printf("Could not resolve file/function %s, check dispatch tables\n", function); + return NULL; + } + } + + virtual const char* name() + { + return "main"; + } + + virtual System::Library* next() + { + return next_; + } + + virtual void setNext(System::Library* lib) + { + next_ = lib; + } + + virtual void disposeAll() + { + if (next_) { + next_->disposeAll(); + } + + ::free(this); + } + + System* s; + System::Library* next_; + }; + + MySystem(bool reentrant) : reentrant(reentrant), threadVisitor(0), visitTarget(0) + { + if (not reentrant) { + expect(this, globalSystem == 0); + globalSystem = this; + expect(this, make(&visitLock) == 0); + } + } + + bool unregisterHandler(int index UNUSED) + { + return true; + } + + // Returns true on success, false on failure + bool registerHandler(int index UNUSED) + { + printf("System::registerHandler(%d)\n", index); + return true; + } + + virtual void* tryAllocate(size_t sizeInBytes) + { + return malloc(sizeInBytes); + } + + virtual void free(const void* p) + { + if (p) + ::free(const_cast(p)); + } + + virtual bool success(Status s) { + return s == 0; + } + + virtual Status attach(Runnable* r) + { + Thread* t = new (allocate(this, sizeof(Thread))) Thread(this, r); + r->attach(t); + return 0; + } + + virtual Status start(Runnable* r) + { + Thread* t = new (allocate(this, sizeof(Thread))) Thread(this, r); + r->attach(t); + printf("System::start (thread!!)\n"); + // We implement threads as blocking calls! This is of course totally wrong, but with extra threads + // patched out in a few places, it's hopefully sufficient. + r->run(); + return 0; + } + + virtual Status make(System::Mutex** m) + { + *m = new (allocate(this, sizeof(Mutex))) Mutex(this); + return 0; + } + + virtual Status make(System::Monitor** m) + { + *m = new (allocate(this, sizeof(Monitor))) Monitor(this); + return 0; + } + + virtual Status make(System::Local** l) + { + *l = new (allocate(this, sizeof(Local))) Local(this); + return 0; + } + + virtual Status visit(System::Thread* st UNUSED, + System::Thread* sTarget UNUSED, + ThreadVisitor* visitor UNUSED) + { + printf("System::visit (threads)\n"); + return 0; + } + + virtual Status map(System::Region** region UNUSED, const char* name) + { + printf("System::map(%s)\n", name); + return 0; + } + + virtual Status open(System::Directory** directory UNUSED, const char* name) + { + printf("System::open(%s)\n", name); + return 1; + } + + virtual FileType stat(const char* name, size_t* length) + { + // Avian does a stat on the current directory during startup but doesn't seem to care about the result, + // so suppress stub logging of stat(".") + if (strcmp(name, ".")) + printf("System::stat(%s)\n", name); + *length = 0; + return TypeDoesNotExist; + } + + virtual const char* libraryPrefix() + { + return SO_PREFIX; + } + + virtual const char* librarySuffix() + { + return SO_SUFFIX; + } + + virtual const char* toAbsolutePath(AllocOnly* allocator, const char* name) + { + return copy(allocator, name); + } + + virtual Status load(System::Library** lib, const char* name) + { + if (name != NULL) { + printf("System::load(%s)", name); + while(1); + } + + // Request to get a System::Library for the main process. + *lib = new (allocate(this, sizeof(Library))) Library(this); + return 0; + } + + virtual char pathSeparator() + { + return ':'; + } + + virtual char fileSeparator() + { + return '/'; + } + + virtual int64_t now() + { + timeval tv = {0, 0}; + gettimeofday(&tv, 0); + return (static_cast(tv.tv_sec) * 1000) + (static_cast(tv.tv_usec) / 1000); + } + + virtual void yield() + { + + } + + virtual void exit(int code UNUSED) + { + abort_with("exit()"); + } + + virtual void abort() + { + abort_with("abort!"); + } + + virtual void dispose() + { + if (not reentrant) { + visitLock->dispose(); + globalSystem = 0; + } + + ::free(this); + } + + bool reentrant; + ThreadVisitor* threadVisitor; + Thread* visitTarget; + System::Monitor* visitLock; + }; +} // namespace + +namespace vm { + AVIAN_EXPORT System* makeSystem(bool reentrant) + { + return new (malloc(sizeof(MySystem))) MySystem(reentrant); + } +} // namespace vm diff --git a/sgx-jvm/avian/src/system/sgx/memory.cpp b/sgx-jvm/avian/src/system/sgx/memory.cpp new file mode 100644 index 0000000000..b91f84da50 --- /dev/null +++ b/sgx-jvm/avian/src/system/sgx/memory.cpp @@ -0,0 +1,23 @@ +#include +#include + +namespace avian { + namespace system { + util::Slice Memory::allocate(size_t sizeInBytes, Permissions) + { + void* p = malloc(sizeInBytes); + + if (p == NULL) { + return util::Slice(0, 0); + } else { + return util::Slice(static_cast(p), sizeInBytes); + } + } + + void Memory::free(util::Slice slice) + { + ::free(slice.begin()); + } + + } // namespace system +} // namespace avian diff --git a/sgx-jvm/avian/src/system/sgx/signal.cpp b/sgx-jvm/avian/src/system/sgx/signal.cpp new file mode 100644 index 0000000000..dcb02686e1 --- /dev/null +++ b/sgx-jvm/avian/src/system/sgx/signal.cpp @@ -0,0 +1,34 @@ +#include "avian/arch.h" +#include +#include + +extern "C" { + void debug_print(const char *msg); +} + +namespace avian { + namespace system { + SignalRegistrar::SignalRegistrar() + { + } + + SignalRegistrar::~SignalRegistrar() + { + } + + bool SignalRegistrar::registerHandler(Signal signal UNUSED, Handler* handler UNUSED) + { + return true; + } + + bool SignalRegistrar::unregisterHandler(Signal signal UNUSED) + { + return true; + } + + void SignalRegistrar::setCrashDumpDirectory(const char*) + { + } + } // namespace system +} // namespace avian + diff --git a/sgx-jvm/avian/src/system/windows.cpp b/sgx-jvm/avian/src/system/windows.cpp new file mode 100644 index 0000000000..5833c28274 --- /dev/null +++ b/sgx-jvm/avian/src/system/windows.cpp @@ -0,0 +1,1033 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#include "sys/stat.h" +#include "windows.h" + +#ifdef _MSC_VER +#define S_ISREG(x) ((x)&_S_IFREG) +#define S_ISDIR(x) ((x)&_S_IFDIR) +#define FTIME _ftime_s +#else +#define FTIME _ftime +#endif + +#undef max +#undef min + +#include "avian/arch.h" +#include +#include +#include +#include + +#if defined(WINAPI_FAMILY) + +#if !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) + +#define WaitForSingleObject(hHandle, dwMilliseconds) \ + WaitForSingleObjectEx((hHandle), (dwMilliseconds), FALSE) + +#define CreateEvent(lpEventAttributes, bManualReset, bInitialState, lpName) \ + CreateEventEx((lpEventAttributes), \ + (lpName), \ + ((bManualReset) ? CREATE_EVENT_MANUAL_RESET : 0) \ + | ((bInitialState) ? CREATE_EVENT_INITIAL_SET : 0), \ + EVENT_ALL_ACCESS) + +#define CreateMutex(lpEventAttributes, bInitialOwner, lpName) \ + CreateMutexEx((lpEventAttributes), \ + (lpName), \ + (bInitialOwner) ? CREATE_MUTEX_INITIAL_OWNER : 0, \ + MUTEX_ALL_ACCESS) + +#include "thread-emulation.h" + +#endif + +#if defined(WINAPI_PARTITION_PHONE) \ + && WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_PHONE) +// Headers in Windows Phone 8 DevKit contain severe error, so let's define +// needed functions on our own +extern "C" { +WINBASEAPI +_Ret_maybenull_ HANDLE WINAPI + CreateFileMappingFromApp(_In_ HANDLE hFile, + _In_opt_ PSECURITY_ATTRIBUTES SecurityAttributes, + _In_ ULONG PageProtection, + _In_ ULONG64 MaximumSize, + _In_opt_ PCWSTR Name); + +WINBASEAPI +_Ret_maybenull_ __out_data_source(FILE) PVOID WINAPI + MapViewOfFileFromApp(_In_ HANDLE hFileMappingObject, + _In_ ULONG DesiredAccess, + _In_ ULONG64 FileOffset, + _In_ SIZE_T NumberOfBytesToMap); + +WINBASEAPI +BOOL WINAPI UnmapViewOfFile(_In_ LPCVOID lpBaseAddress); +} +#endif // WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_PHONE) + +#else + +#ifndef WINAPI_PARTITION_DESKTOP +#define WINAPI_PARTITION_DESKTOP 1 +#endif + +#ifndef WINAPI_FAMILY_PARTITION +#define WINAPI_FAMILY_PARTITION(x) (x) +#endif + +#endif + +#define ACQUIRE(s, x) MutexResource MAKE_NAME(mutexResource_)(s, x) + +using namespace vm; + +namespace { + +class MutexResource { + public: + MutexResource(System* s, HANDLE m) : s(s), m(m) + { + int r UNUSED = WaitForSingleObject(m, INFINITE); + assertT(s, r == WAIT_OBJECT_0); + } + + ~MutexResource() + { + bool success UNUSED = ReleaseMutex(m); + assertT(s, success); + } + + private: + System* s; + HANDLE m; +}; + +class MySystem; +MySystem* globalSystem; + +DWORD WINAPI run(void* r) +{ + static_cast(r)->run(); + return 0; +} + +const bool Verbose = false; + +const unsigned Waiting = 1 << 0; +const unsigned Notified = 1 << 1; + +class MySystem : public System { + public: + class Thread : public System::Thread { + public: + Thread(System* s, System::Runnable* r) : s(s), r(r), next(0), flags(0) + { + mutex = CreateMutex(0, false, 0); + assertT(s, mutex); + + event = CreateEvent(0, true, false, 0); + assertT(s, event); + } + + virtual void interrupt() + { + ACQUIRE(s, mutex); + + r->setInterrupted(true); + + if (flags & Waiting) { + int r UNUSED = SetEvent(event); + assertT(s, r != 0); + } + } + + virtual bool getAndClearInterrupted() + { + ACQUIRE(s, mutex); + + bool interrupted = r->interrupted(); + + r->setInterrupted(false); + + return interrupted; + } + + virtual void join() + { + int r UNUSED = WaitForSingleObject(thread, INFINITE); + assertT(s, r == WAIT_OBJECT_0); + } + + virtual void dispose() + { + CloseHandle(event); + CloseHandle(mutex); + CloseHandle(thread); + ::free(this); + } + + HANDLE thread; + HANDLE mutex; + HANDLE event; + System* s; + System::Runnable* r; + Thread* next; + unsigned flags; + }; + + class Mutex : public System::Mutex { + public: + Mutex(System* s) : s(s) + { + mutex = CreateMutex(0, false, 0); + assertT(s, mutex); + } + + virtual void acquire() + { + int r UNUSED = WaitForSingleObject(mutex, INFINITE); + assertT(s, r == WAIT_OBJECT_0); + } + + virtual void release() + { + bool success UNUSED = ReleaseMutex(mutex); + assertT(s, success); + } + + virtual void dispose() + { + CloseHandle(mutex); + ::free(this); + } + + System* s; + HANDLE mutex; + }; + + class Monitor : public System::Monitor { + public: + Monitor(System* s) : s(s), owner_(0), first(0), last(0), depth(0) + { + mutex = CreateMutex(0, false, 0); + assertT(s, mutex); + } + + virtual bool tryAcquire(System::Thread* context) + { + Thread* t = static_cast(context); + assertT(s, t); + + if (owner_ == t) { + ++depth; + return true; + } else { + switch (WaitForSingleObject(mutex, 0)) { + case WAIT_TIMEOUT: + return false; + + case WAIT_OBJECT_0: + owner_ = t; + ++depth; + return true; + + default: + sysAbort(s); + } + } + } + + virtual void acquire(System::Thread* context) + { + Thread* t = static_cast(context); + assertT(s, t); + + if (owner_ != t) { + int r UNUSED = WaitForSingleObject(mutex, INFINITE); + assertT(s, r == WAIT_OBJECT_0); + owner_ = t; + } + ++depth; + } + + virtual void release(System::Thread* context) + { + Thread* t = static_cast(context); + assertT(s, t); + + if (owner_ == t) { + if (--depth == 0) { + owner_ = 0; + bool success UNUSED = ReleaseMutex(mutex); + assertT(s, success); + } + } else { + sysAbort(s); + } + } + + void append(Thread* t) + { +#ifndef NDEBUG + for (Thread* x = first; x; x = x->next) { + expect(s, t != x); + } +#endif + + if (last) { + last->next = t; + last = t; + } else { + first = last = t; + } + } + + void remove(Thread* t) + { + Thread* previous = 0; + for (Thread* current = first; current;) { + if (t == current) { + if (current == first) { + first = t->next; + } else { + previous->next = t->next; + } + + if (current == last) { + last = previous; + } + + t->next = 0; + + break; + } else { + previous = current; + current = current->next; + } + } + +#ifndef NDEBUG + for (Thread* x = first; x; x = x->next) { + expect(s, t != x); + } +#endif + } + + virtual void wait(System::Thread* context, int64_t time) + { + wait(context, time, false); + } + + virtual bool waitAndClearInterrupted(System::Thread* context, int64_t time) + { + return wait(context, time, true); + } + + bool wait(System::Thread* context, int64_t time, bool clearInterrupted) + { + Thread* t = static_cast(context); + assertT(s, t); + + if (owner_ == t) { + // Initialized here to make gcc 4.2 a happy compiler + bool interrupted = false; + bool notified = false; + unsigned depth = 0; + + int r UNUSED; + + { + ACQUIRE(s, t->mutex); + + expect(s, (t->flags & Notified) == 0); + + interrupted = t->r->interrupted(); + if (interrupted and clearInterrupted) { + t->r->setInterrupted(false); + } + + t->flags |= Waiting; + + append(t); + + depth = this->depth; + this->depth = 0; + owner_ = 0; + + bool success UNUSED = ReleaseMutex(mutex); + assertT(s, success); + + if (not interrupted) { + success = ResetEvent(t->event); + assertT(s, success); + + success = ReleaseMutex(t->mutex); + assertT(s, success); + + r = WaitForSingleObject(t->event, (time ? time : INFINITE)); + assertT(s, r == WAIT_OBJECT_0 or r == WAIT_TIMEOUT); + + r = WaitForSingleObject(t->mutex, INFINITE); + assertT(s, r == WAIT_OBJECT_0); + + interrupted = t->r->interrupted(); + if (interrupted and clearInterrupted) { + t->r->setInterrupted(false); + } + } + + notified = ((t->flags & Notified) != 0); + } + + r = WaitForSingleObject(mutex, INFINITE); + assertT(s, r == WAIT_OBJECT_0); + + { + ACQUIRE(s, t->mutex); + t->flags = 0; + } + + if (not notified) { + remove(t); + } else { +#ifndef NDEBUG + for (Thread* x = first; x; x = x->next) { + expect(s, t != x); + } +#endif + } + + t->next = 0; + + owner_ = t; + this->depth = depth; + + return interrupted; + } else { + sysAbort(s); + } + } + + void doNotify(Thread* t) + { + ACQUIRE(s, t->mutex); + + t->flags |= Notified; + + bool success UNUSED = SetEvent(t->event); + assertT(s, success); + } + + virtual void notify(System::Thread* context) + { + Thread* t = static_cast(context); + assertT(s, t); + + if (owner_ == t) { + if (first) { + Thread* t = first; + first = first->next; + if (t == last) { + expect(s, first == 0); + last = 0; + } + + doNotify(t); + } + } else { + sysAbort(s); + } + } + + virtual void notifyAll(System::Thread* context) + { + Thread* t = static_cast(context); + assertT(s, t); + + if (owner_ == t) { + for (Thread* t = first; t; t = t->next) { + doNotify(t); + } + first = last = 0; + } else { + sysAbort(s); + } + } + + virtual System::Thread* owner() + { + return owner_; + } + + virtual void dispose() + { + assertT(s, owner_ == 0); + CloseHandle(mutex); + ::free(this); + } + + System* s; + HANDLE mutex; + Thread* owner_; + Thread* first; + Thread* last; + unsigned depth; + }; + + class Local : public System::Local { + public: + Local(System* s) : s(s) + { + key = TlsAlloc(); + assertT(s, key != TLS_OUT_OF_INDEXES); + } + + virtual void* get() + { + return TlsGetValue(key); + } + + virtual void set(void* p) + { + bool r UNUSED = TlsSetValue(key, p); + assertT(s, r); + } + + virtual void dispose() + { + bool r UNUSED = TlsFree(key); + assertT(s, r); + + ::free(this); + } + + System* s; + unsigned key; + }; + + class Region : public System::Region { + public: + Region(System* system, + uint8_t* start, + size_t length, + HANDLE mapping, + HANDLE file) + : system(system), + start_(start), + length_(length), + mapping(mapping), + file(file) + { + } + + virtual const uint8_t* start() + { + return start_; + } + + virtual size_t length() + { + return length_; + } + + virtual void dispose() + { + if (start_) { + if (start_) + UnmapViewOfFile(start_); + if (mapping) + CloseHandle(mapping); + if (file) + CloseHandle(file); + } + system->free(this); + } + + System* system; + uint8_t* start_; + size_t length_; + HANDLE mapping; + HANDLE file; + }; + + class Directory : public System::Directory { + public: + Directory(System* s) : s(s), handle(0), findNext(false) + { + } + + virtual const char* next() + { + if (handle and handle != INVALID_HANDLE_VALUE) { + if (findNext) { + if (FindNextFile(handle, &data)) { + return data.cFileName; + } + } else { + findNext = true; + return data.cFileName; + } + } + return 0; + } + + virtual void dispose() + { + if (handle and handle != INVALID_HANDLE_VALUE) { + FindClose(handle); + } + ::free(this); + } + + System* s; + HANDLE handle; + WIN32_FIND_DATA data; + bool findNext; + }; + + class Library : public System::Library { + public: + Library(System* s, HMODULE handle, const char* name) + : s(s), handle(handle), name_(name), next_(0) + { + } + + virtual void* resolve(const char* function) + { + void* address; + FARPROC p = GetProcAddress(handle, function); + memcpy(&address, &p, BytesPerWord); + return address; + } + + virtual const char* name() + { + return name_; + } + + virtual System::Library* next() + { + return next_; + } + + virtual void setNext(System::Library* lib) + { + next_ = lib; + } + + virtual void disposeAll() + { + if (Verbose) { + fprintf(stderr, "close %p\n", handle); + fflush(stderr); + } + + if (name_) { + FreeLibrary(handle); + } + + if (next_) { + next_->disposeAll(); + } + + if (name_) { + ::free(const_cast(name_)); + } + + ::free(this); + } + + System* s; + HMODULE handle; + const char* name_; + System::Library* next_; + }; + + MySystem(bool reentrant): reentrant(reentrant) + { + if (not reentrant) { + expect(this, globalSystem == 0); + globalSystem = this; + } + + mutex = CreateMutex(0, false, 0); + assertT(this, mutex); + } + + virtual void* tryAllocate(size_t sizeInBytes) + { + return malloc(sizeInBytes); + } + + virtual void free(const void* p) + { + if (p) + ::free(const_cast(p)); + } + + virtual bool success(Status s) { + return s == 0; + } + + virtual Status attach(Runnable* r) + { + Thread* t = new (allocate(this, sizeof(Thread))) Thread(this, r); + bool success UNUSED = DuplicateHandle(GetCurrentProcess(), + GetCurrentThread(), + GetCurrentProcess(), + &(t->thread), + 0, + false, + DUPLICATE_SAME_ACCESS); + assertT(this, success); + r->attach(t); + return 0; + } + + virtual Status start(Runnable* r) + { + Thread* t = new (allocate(this, sizeof(Thread))) Thread(this, r); + r->attach(t); + DWORD id; + t->thread = CreateThread(0, 0, run, r, 0, &id); + assertT(this, t->thread); + return 0; + } + + virtual Status make(System::Mutex** m) + { + *m = new (allocate(this, sizeof(Mutex))) Mutex(this); + return 0; + } + + virtual Status make(System::Monitor** m) + { + *m = new (allocate(this, sizeof(Monitor))) Monitor(this); + return 0; + } + + virtual Status make(System::Local** l) + { + *l = new (allocate(this, sizeof(Local))) Local(this); + return 0; + } + + virtual Status visit(System::Thread* st UNUSED, + System::Thread* sTarget, + ThreadVisitor* visitor) + { +#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) + assertT(this, st != sTarget); + + Thread* target = static_cast(sTarget); + + ACQUIRE(this, mutex); + + bool success = false; + int rv = SuspendThread(target->thread); + if (rv != -1) { + CONTEXT context; + memset(&context, 0, sizeof(CONTEXT)); + context.ContextFlags = CONTEXT_CONTROL; + rv = GetThreadContext(target->thread, &context); + + if (rv) { +#ifdef ARCH_x86_32 + visitor->visit(reinterpret_cast(context.Eip), + reinterpret_cast(context.Esp), + reinterpret_cast(context.Ebp)); +#elif defined ARCH_x86_64 + visitor->visit(reinterpret_cast(context.Rip), + reinterpret_cast(context.Rsp), + reinterpret_cast(context.Rbp)); +#endif + success = true; + } + + rv = ResumeThread(target->thread); + expect(this, rv != -1); + } + + return (success ? 0 : 1); +#else +#pragma message( \ + "TODO: http://msdn.microsoft.com/en-us/library/windowsphone/develop/system.windows.application.unhandledexception(v=vs.105).aspx") + return false; +#endif + } + + virtual Status map(System::Region** region, const char* name) + { + Status status = 1; + size_t nameLen = strlen(name) * 2; + RUNTIME_ARRAY(wchar_t, wideName, nameLen + 1); + MultiByteToWideChar( + CP_UTF8, 0, name, -1, RUNTIME_ARRAY_BODY(wideName), nameLen + 1); +#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) + HANDLE file = CreateFileW(RUNTIME_ARRAY_BODY(wideName), + FILE_READ_DATA, + FILE_SHARE_READ, + 0, + OPEN_EXISTING, + 0, + 0); +#else + HANDLE file = CreateFile2(RUNTIME_ARRAY_BODY(wideName), + GENERIC_READ, + FILE_SHARE_READ, + OPEN_EXISTING, + 0); +#endif + if (file != INVALID_HANDLE_VALUE) { +#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) + unsigned size = GetFileSize(file, 0); +#else + FILE_STANDARD_INFO info; + unsigned size = INVALID_FILE_SIZE; + if (GetFileInformationByHandleEx( + file, FileStandardInfo, &info, sizeof(info))) + size = info.EndOfFile.QuadPart; +#endif + if (size != INVALID_FILE_SIZE) { +#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) + HANDLE mapping = CreateFileMapping(file, 0, PAGE_READONLY, 0, size, 0); +#else + HANDLE mapping + = CreateFileMappingFromApp(file, 0, PAGE_READONLY, size, 0); +#endif + if (mapping) { +#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) + void* data = MapViewOfFile(mapping, FILE_MAP_READ, 0, 0, 0); +#else + void* data = MapViewOfFileFromApp(mapping, FILE_MAP_READ, 0, 0); +#endif + if (data) { + *region = new (allocate(this, sizeof(Region))) + Region(this, static_cast(data), size, file, mapping); + status = 0; + } + + if (status) { + CloseHandle(mapping); + } + } + } + + if (status) { + CloseHandle(file); + } + } + + return status; + } + + virtual Status open(System::Directory** directory, const char* name) + { + Status status = 1; + + unsigned length = strlen(name); + RUNTIME_ARRAY(char, buffer, length + 3); + memcpy(RUNTIME_ARRAY_BODY(buffer), name, length); + memcpy(RUNTIME_ARRAY_BODY(buffer) + length, "\\*", 3); + + Directory* d = new (allocate(this, sizeof(Directory))) Directory(this); + +#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) + d->handle = FindFirstFile(RUNTIME_ARRAY_BODY(buffer), &(d->data)); +#else + d->handle = FindFirstFileEx(RUNTIME_ARRAY_BODY(buffer), + FindExInfoStandard, + &(d->data), + FindExSearchNameMatch, + 0, + 0); +#endif + if (d->handle == INVALID_HANDLE_VALUE) { + d->dispose(); + } else { + *directory = d; + status = 0; + } + + return status; + } + + virtual FileType stat(const char* name, size_t* length) + { + size_t nameLen = strlen(name) * 2; + RUNTIME_ARRAY(wchar_t, wideName, nameLen + 1); + MultiByteToWideChar( + CP_UTF8, 0, name, -1, RUNTIME_ARRAY_BODY(wideName), nameLen + 1); + WIN32_FILE_ATTRIBUTE_DATA data; + if (GetFileAttributesExW( + RUNTIME_ARRAY_BODY(wideName), GetFileExInfoStandard, &data)) { + if (data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { + return TypeDirectory; + } else { + *length = (data.nFileSizeHigh * static_cast(MAXDWORD + 1)) + + data.nFileSizeLow; + return TypeFile; + } + } else { + return TypeDoesNotExist; + } + } + + virtual const char* libraryPrefix() + { + return SO_PREFIX; + } + + virtual const char* librarySuffix() + { + return SO_SUFFIX; + } + + virtual const char* toAbsolutePath(avian::util::AllocOnly* allocator, + const char* name) + { +#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) + if (strncmp(name, "//", 2) == 0 or strncmp(name, "\\\\", 2) == 0 + or strncmp(name + 1, ":/", 2) == 0 + or strncmp(name + 1, ":\\", 2) == 0) { + return copy(allocator, name); + } else { + TCHAR buffer[MAX_PATH]; + GetCurrentDirectory(MAX_PATH, buffer); + return append(allocator, buffer, "\\", name); + } +#else +#pragma message( \ + "TODO:http://lunarfrog.com/blog/2012/05/21/winrt-folders-access/ Windows.ApplicationModel.Package.Current.InstalledLocation") + return copy(allocator, name); +#endif + } + + virtual Status load(System::Library** lib, const char* name) + { + HMODULE handle; + unsigned nameLength = (name ? strlen(name) : 0); + if (name) { + size_t nameLen = nameLength * 2; + RUNTIME_ARRAY(wchar_t, wideName, nameLen + 1); + MultiByteToWideChar( + CP_UTF8, 0, name, -1, RUNTIME_ARRAY_BODY(wideName), nameLen + 1); + +#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) + handle = LoadLibraryW(RUNTIME_ARRAY_BODY(wideName)); +#else + handle = LoadPackagedLibrary(RUNTIME_ARRAY_BODY(wideName), 0); +#endif + } else { +#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) + handle = GetModuleHandle(0); +#else + // Most of WinRT/WP8 applications can not host native object files inside + // main executable + assertT(this, false); +#endif + } + + if (handle) { + if (Verbose) { + fprintf(stderr, "open %s as %p\n", name, handle); + fflush(stderr); + } + + char* n; + if (name) { + n = static_cast(allocate(this, nameLength + 1)); + memcpy(n, name, nameLength + 1); + } else { + n = 0; + } + + *lib = new (allocate(this, sizeof(Library))) Library(this, handle, n); + + return 0; + } else { + if (Verbose) { + fprintf(stderr, "unable to open %s: %ld\n", name, GetLastError()); + fflush(stderr); + } + + return 1; + } + } + + virtual char pathSeparator() + { + return ';'; + } + + virtual char fileSeparator() + { + return '\\'; + } + + virtual int64_t now() + { + // We used to use _ftime here, but that only gives us 1-second + // resolution on Windows 7. _ftime_s might work better, but MinGW + // doesn't have it as of this writing. So we use this mess instead: + FILETIME time; + GetSystemTimeAsFileTime(&time); + return (((static_cast(time.dwHighDateTime) << 32) + | time.dwLowDateTime) / 10000) - 11644473600000LL; + } + + virtual void yield() + { +#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) + SwitchToThread(); +#else + YieldProcessor(); +#endif + } + + virtual void exit(int code) + { + ::exit(code); + } + + virtual void abort() + { + avian::system::crash(); + } + + virtual void dispose() + { + if (not reentrant) { + globalSystem = 0; + } + + CloseHandle(mutex); + ::free(this); + } + + HANDLE mutex; + bool reentrant; +}; + +} // namespace + +namespace vm { + +AVIAN_EXPORT System* makeSystem(bool reentrant) +{ + return new (malloc(sizeof(MySystem))) MySystem(reentrant); +} + +} // namespace vm diff --git a/sgx-jvm/avian/src/system/windows/crash.cpp b/sgx-jvm/avian/src/system/windows/crash.cpp new file mode 100644 index 0000000000..16ea717b72 --- /dev/null +++ b/sgx-jvm/avian/src/system/windows/crash.cpp @@ -0,0 +1,28 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#include + +namespace avian { +namespace system { + +NO_RETURN void crash() +{ + // trigger an EXCEPTION_ACCESS_VIOLATION, which we will catch and + // generate a debug dump for + *static_cast(0) = 0; + + // Some (all?) compilers don't realize that we can't possibly continue past + // the above statement. + abort(); +} + +} // namespace system +} // namespace avian diff --git a/sgx-jvm/avian/src/system/windows/memory.cpp b/sgx-jvm/avian/src/system/windows/memory.cpp new file mode 100644 index 0000000000..c6d33053ca --- /dev/null +++ b/sgx-jvm/avian/src/system/windows/memory.cpp @@ -0,0 +1,55 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#include + +#include + +#include + +namespace avian { +namespace system { + +const size_t Memory::PageSize = 1 << 12; + +util::Slice Memory::allocate(size_t sizeInBytes, + Permissions perms) +{ + unsigned prot; + switch(perms) { + case Read: + prot = PAGE_READONLY; + break; + case ReadWrite: + prot = PAGE_READWRITE; + break; + case ReadExecute: + prot = PAGE_EXECUTE_READ; + break; + case ReadWriteExecute: + prot = PAGE_EXECUTE_READWRITE; + break; + default: + UNREACHABLE_; + } + void* ret = VirtualAlloc( + 0, sizeInBytes, MEM_COMMIT | MEM_RESERVE, prot); + return util::Slice((uint8_t*)ret, sizeInBytes); +} + +void Memory::free(util::Slice pages) +{ + int r = VirtualFree(pages.begin(), 0, MEM_RELEASE); + (void) r; + ASSERT(r); +} + +} // namespace system +} // namespace avian diff --git a/sgx-jvm/avian/src/system/windows/signal.cpp b/sgx-jvm/avian/src/system/windows/signal.cpp new file mode 100644 index 0000000000..66e1cd1f8d --- /dev/null +++ b/sgx-jvm/avian/src/system/windows/signal.cpp @@ -0,0 +1,343 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#include "windows.h" +#include "sys/timeb.h" + +#ifdef _MSC_VER +#define FTIME _ftime_s +#else +#define FTIME _ftime +#endif + +#ifndef WINAPI_FAMILY + +#ifndef WINAPI_PARTITION_DESKTOP +#define WINAPI_PARTITION_DESKTOP 1 +#endif + +#ifndef WINAPI_FAMILY_PARTITION +#define WINAPI_FAMILY_PARTITION(x) (x) +#endif + +#endif + +#include +#include + +namespace avian { +namespace system { + +namespace windows { + +const unsigned HandlerCount = 2; + +} // namespace windows + +struct SignalRegistrar::Data { + Handler* handlers[windows::HandlerCount]; + const char* crashDumpDirectory; + +#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) + LPTOP_LEVEL_EXCEPTION_FILTER oldHandler; +#endif + + Data() + : crashDumpDirectory(0), +#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) + oldHandler(0) +#endif + { + if (instance) { + crash(); + } + instance = this; + memset(handlers, 0, sizeof(handlers)); + } + + ~Data() + { + instance = 0; + } + + bool registerHandler(Handler* handler, int index); + + bool findHandler() + { + for (unsigned i = 0; i < windows::HandlerCount; ++i) { + if (handlers[i]) + return true; + } + return false; + } + + static SignalRegistrar::Data* instance; +}; + +SignalRegistrar::Data* SignalRegistrar::Data::instance = 0; + +namespace windows { + +#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) + +#pragma pack(push, 4) +struct MINIDUMP_EXCEPTION_INFORMATION { + DWORD thread; + LPEXCEPTION_POINTERS exception; + BOOL exceptionInCurrentAddressSpace; +}; +#pragma pack(pop) + +struct MINIDUMP_USER_STREAM_INFORMATION; +struct MINIDUMP_CALLBACK_INFORMATION; + +enum MINIDUMP_TYPE { MiniDumpNormal = 0, MiniDumpWithFullMemory = 2 }; + +typedef BOOL (*MiniDumpWriteDumpType)( + HANDLE processHandle, + DWORD processId, + HANDLE file, + MINIDUMP_TYPE type, + const MINIDUMP_EXCEPTION_INFORMATION* exception, + const MINIDUMP_USER_STREAM_INFORMATION* userStream, + const MINIDUMP_CALLBACK_INFORMATION* callback); + +#endif + +void dump(LPEXCEPTION_POINTERS e, const char* directory) +{ + HINSTANCE dbghelp = LoadLibrary("dbghelp.dll"); + + if (dbghelp) { + MiniDumpWriteDumpType MiniDumpWriteDump + = reinterpret_cast( + GetProcAddress(dbghelp, "MiniDumpWriteDump")); + + if (MiniDumpWriteDump) { + char name[MAX_PATH]; + _timeb tb; + FTIME(&tb); + vm::snprintf(name, + MAX_PATH, + "%s\\crash-%" LLD ".mdmp", + directory, + (static_cast(tb.time) * 1000) + + static_cast(tb.millitm)); + + HANDLE file + = CreateFile(name, FILE_WRITE_DATA, 0, 0, CREATE_ALWAYS, 0, 0); + + if (file != INVALID_HANDLE_VALUE) { + MINIDUMP_EXCEPTION_INFORMATION exception + = {GetCurrentThreadId(), e, true}; + + MiniDumpWriteDump(GetCurrentProcess(), + GetCurrentProcessId(), + file, + MiniDumpWithFullMemory, + &exception, + 0, + 0); + + CloseHandle(file); + } + } + + FreeLibrary(dbghelp); + } +} + +void logException(LPEXCEPTION_POINTERS e, const char* directory) +{ + char name[MAX_PATH]; + _timeb tb; + FTIME(&tb); + vm::snprintf(name, MAX_PATH, "%s\\exceptions.txt", directory); + + FILE* log = vm::fopen(name, "ab"); + if (log) { +#ifdef ARCH_x86_32 + void* ip = reinterpret_cast(e->ContextRecord->Eip); + void* base = reinterpret_cast(e->ContextRecord->Ebp); + void* stack = reinterpret_cast(e->ContextRecord->Esp); + void* thread = reinterpret_cast(e->ContextRecord->Ebx); +#elif defined ARCH_x86_64 + void* ip = reinterpret_cast(e->ContextRecord->Rip); + void* base = reinterpret_cast(e->ContextRecord->Rbp); + void* stack = reinterpret_cast(e->ContextRecord->Rsp); + void* thread = reinterpret_cast(e->ContextRecord->Rbx); +#endif + + HMODULE module; + if (GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, + static_cast(ip), + &module)) { + GetModuleFileName(module, name, MAX_PATH); + } else { + module = 0; + } + + fprintf(log, + "timestamp %" LLD + " code %ld ip %p base %p stack %p thread %p module %s\n", + (static_cast(tb.time) * 1000) + + static_cast(tb.millitm), + e->ExceptionRecord->ExceptionCode, + ip, + base, + stack, + thread, + module ? name : "(unknown)"); + + fflush(log); + fclose(log); + } +} + +LONG CALLBACK handleException(LPEXCEPTION_POINTERS e) +{ + SignalRegistrar::Handler* handler = 0; + if (e->ExceptionRecord->ExceptionCode == EXCEPTION_ACCESS_VIOLATION) { + handler + = SignalRegistrar::Data::instance->handlers[SignalRegistrar::SegFault]; + } else if (e->ExceptionRecord->ExceptionCode + == EXCEPTION_INT_DIVIDE_BY_ZERO) { + handler = SignalRegistrar::Data::instance + ->handlers[SignalRegistrar::DivideByZero]; + } + + if (handler) { +#ifdef ARCH_x86_32 + void* ip = reinterpret_cast(e->ContextRecord->Eip); + void* base = reinterpret_cast(e->ContextRecord->Ebp); + void* stack = reinterpret_cast(e->ContextRecord->Esp); + void* thread = reinterpret_cast(e->ContextRecord->Ebx); +#elif defined ARCH_x86_64 + void* ip = reinterpret_cast(e->ContextRecord->Rip); + void* base = reinterpret_cast(e->ContextRecord->Rbp); + void* stack = reinterpret_cast(e->ContextRecord->Rsp); + void* thread = reinterpret_cast(e->ContextRecord->Rbx); +#endif + + bool jump = handler->handleSignal(&ip, &base, &stack, &thread); + + if (jump) { +#ifdef ARCH_x86_32 + e->ContextRecord->Eip = reinterpret_cast(ip); + e->ContextRecord->Ebp = reinterpret_cast(base); + e->ContextRecord->Esp = reinterpret_cast(stack); + e->ContextRecord->Ebx = reinterpret_cast(thread); +#elif defined ARCH_x86_64 + e->ContextRecord->Rip = reinterpret_cast(ip); + e->ContextRecord->Rbp = reinterpret_cast(base); + e->ContextRecord->Rsp = reinterpret_cast(stack); + e->ContextRecord->Rbx = reinterpret_cast(thread); +#endif + + return EXCEPTION_CONTINUE_EXECUTION; + } else if (SignalRegistrar::Data::instance->crashDumpDirectory) { + // We only generate a crash dump if exception occurred in code + // belonging to the current executable. If the exception + // occurred in a library, there may be a handler available to + // handle it, in which case it is premature to assume we're + // going to crash. Generating a full memory dump on each such + // event is time consuming and eats up disk space, so we'd + // prefer to avoid it unless we're really crashing. + HMODULE module; + if (GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, + static_cast(ip), + &module) and module == GetModuleHandle(0)) { + dump(e, SignalRegistrar::Data::instance->crashDumpDirectory); + } else { + logException(e, SignalRegistrar::Data::instance->crashDumpDirectory); + } + } + } + + return EXCEPTION_CONTINUE_SEARCH; +} + +} // namespace windows + +SignalRegistrar::SignalRegistrar() +{ + data = new (malloc(sizeof(Data))) Data(); +} + +SignalRegistrar::~SignalRegistrar() +{ + data->~Data(); + free(data); +} + +bool SignalRegistrar::Data::registerHandler(Handler* handler, int index) +{ + if (index != SegFault && index != DivideByZero) { + crash(); + } + + if (handler) { + handlers[index] = handler; + +#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) + if (oldHandler == 0) { +#ifdef ARCH_x86_32 + oldHandler = SetUnhandledExceptionFilter(windows::handleException); +#elif defined ARCH_x86_64 + AddVectoredExceptionHandler(1, windows::handleException); + oldHandler = reinterpret_cast(1); +#endif + } +#else +#pragma message( \ + "TODO: http://msdn.microsoft.com/en-us/library/windowsphone/develop/system.windows.application.unhandledexception(v=vs.105).aspx") +#endif + + return true; + } else if (handlers[index]) { + handlers[index] = 0; + + if (not findHandler()) { +#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) +#ifdef ARCH_x86_32 + SetUnhandledExceptionFilter(oldHandler); + oldHandler = 0; +#elif defined ARCH_x86_64 +// do nothing, handlers are never "unregistered" anyway +#endif +#else +#pragma message( \ + "TODO: http://msdn.microsoft.com/en-us/library/windowsphone/develop/system.windows.application.unhandledexception(v=vs.105).aspx") +#endif + } + + return true; + } else { + return false; + } +} + +bool SignalRegistrar::registerHandler(Signal signal, Handler* handler) +{ + return data->registerHandler(handler, signal); +} + +bool SignalRegistrar::unregisterHandler(Signal signal) +{ + return data->registerHandler(0, signal); +} + +void SignalRegistrar::setCrashDumpDirectory(const char* crashDumpDirectory) +{ + data->crashDumpDirectory = crashDumpDirectory; +} + +} // namespace system +} // namespace avian diff --git a/sgx-jvm/avian/src/thunks.cpp b/sgx-jvm/avian/src/thunks.cpp new file mode 100644 index 0000000000..43a2a0c45d --- /dev/null +++ b/sgx-jvm/avian/src/thunks.cpp @@ -0,0 +1,75 @@ +THUNK(tryInitClass) +THUNK(findInterfaceMethodFromInstance) +THUNK(findInterfaceMethodFromInstanceAndReference) +THUNK(findSpecialMethodFromReference) +THUNK(findStaticMethodFromReference) +THUNK(findVirtualMethodFromReference) +THUNK(getMethodAddress) +THUNK(compareDoublesG) +THUNK(compareDoublesL) +THUNK(compareFloatsG) +THUNK(compareFloatsL) +THUNK(compareLongs) +THUNK(addDouble) +THUNK(subtractDouble) +THUNK(multiplyDouble) +THUNK(divideDouble) +THUNK(moduloDouble) +THUNK(negateDouble) +THUNK(squareRootDouble) +THUNK(doubleToFloat) +THUNK(doubleToInt) +THUNK(doubleToLong) +THUNK(addFloat) +THUNK(subtractFloat) +THUNK(multiplyFloat) +THUNK(divideFloat) +THUNK(moduloFloat) +THUNK(negateFloat) +THUNK(absoluteFloat) +THUNK(absoluteLong) +THUNK(absoluteInt) +THUNK(divideLong) +THUNK(divideInt) +THUNK(moduloLong) +THUNK(moduloInt) +THUNK(floatToDouble) +THUNK(floatToInt) +THUNK(floatToLong) +THUNK(intToDouble) +THUNK(intToFloat) +THUNK(longToDouble) +THUNK(longToFloat) +THUNK(makeBlankObjectArray) +THUNK(makeBlankObjectArrayFromReference) +THUNK(makeBlankArray) +THUNK(lookUpAddress) +THUNK(setMaybeNull) +THUNK(acquireMonitorForObject) +THUNK(acquireMonitorForObjectOnEntrance) +THUNK(releaseMonitorForObject) +THUNK(acquireMonitorForClassOnEntrance) +THUNK(releaseMonitorForClass) +THUNK(makeMultidimensionalArray) +THUNK(makeMultidimensionalArrayFromReference) +THUNK(throw_) +THUNK(checkCast) +THUNK(checkCastFromReference) +THUNK(getStaticFieldValueFromReference) +THUNK(getFieldValueFromReference) +THUNK(setStaticFieldValueFromReference) +THUNK(setFieldValueFromReference) +THUNK(setStaticLongFieldValueFromReference) +THUNK(setLongFieldValueFromReference) +THUNK(setStaticObjectFieldValueFromReference) +THUNK(setObjectFieldValueFromReference) +THUNK(instanceOf64) +THUNK(instanceOfFromReference) +THUNK(makeNewGeneral64) +THUNK(makeNew64) +THUNK(makeNewFromReference) +THUNK(setObject) +THUNK(getJClass64) +THUNK(getJClassFromReference) +THUNK(gcIfNecessary) +THUNK(idleIfNecessary) diff --git a/sgx-jvm/avian/src/tools/CMakeLists.txt b/sgx-jvm/avian/src/tools/CMakeLists.txt new file mode 100644 index 0000000000..9825129a2c --- /dev/null +++ b/sgx-jvm/avian/src/tools/CMakeLists.txt @@ -0,0 +1,3 @@ +add_subdirectory(binary-to-object) +add_subdirectory(object-writer) +add_subdirectory(type-generator) diff --git a/sgx-jvm/avian/src/tools/binary-to-object/CMakeLists.txt b/sgx-jvm/avian/src/tools/binary-to-object/CMakeLists.txt new file mode 100644 index 0000000000..1de4e5f9e4 --- /dev/null +++ b/sgx-jvm/avian/src/tools/binary-to-object/CMakeLists.txt @@ -0,0 +1,3 @@ +add_executable(binary_to_object main.cpp) + +target_link_libraries(binary_to_object object_writer) diff --git a/sgx-jvm/avian/src/tools/binary-to-object/main.cpp b/sgx-jvm/avian/src/tools/binary-to-object/main.cpp new file mode 100644 index 0000000000..a6b25ae137 --- /dev/null +++ b/sgx-jvm/avian/src/tools/binary-to-object/main.cpp @@ -0,0 +1,173 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#include +#include +#include +#include + +#include +#ifdef _WIN32 +#include +#include +#else +#include +#include +#endif +#include + +#include + +extern "C" void __cxa_pure_virtual() +{ + abort(); +} + +void* operator new(size_t size) +{ + return malloc(size); +} + +void operator delete(void*) throw() +{ + abort(); +} + +namespace { + +using namespace avian::tools; +using namespace avian::util; + +bool writeObject(uint8_t* data, + size_t size, + OutputStream* out, + const char* startName, + const char* endName, + Platform* platform, + unsigned alignment, + bool writable, + bool executable) +{ + + SymbolInfo symbols[] = {SymbolInfo(0, startName), SymbolInfo(size, endName)}; + + unsigned accessFlags = (writable ? Platform::Writable : 0) + | (executable ? Platform::Executable : 0); + + return platform->writeObject(out, + Slice(symbols, 2), + Slice(data, size), + accessFlags, + alignment); +} + +void usageAndExit(const char* name) +{ + fprintf(stderr, + "usage: %s " + " " + "[ [{writable|executable}...]]\n", + name); + exit(-1); +} + +} // namespace + +int main(int argc, const char** argv) +{ + if (argc < 7 || argc > 10) { + usageAndExit(argv[0]); + } + + unsigned alignment = 1; + if (argc > 7) { + alignment = atoi(argv[7]); + } + + bool writable = false; + bool executable = false; + + for (int i = 8; i < argc; ++i) { + if (strcmp("writable", argv[i]) == 0) { + writable = true; + } else if (strcmp("executable", argv[i]) == 0) { + executable = true; + } else { + usageAndExit(argv[0]); + } + } + + const char* format = argv[5]; + const char* architecture = argv[6]; + + Platform* platform = Platform::getPlatform( + PlatformInfo(PlatformInfo::formatFromString(format), + PlatformInfo::archFromString(architecture))); + + if (!platform) { + fprintf(stderr, "unsupported platform: %s/%s\n", format, architecture); + return 1; + } + + + uint8_t* data = 0; + unsigned size; + int fd = open(argv[1], O_RDONLY); + if (fd != -1) { + struct stat s; + int r = fstat(fd, &s); + if (r != -1) { +#ifdef _WIN32 + HANDLE fm; + HANDLE h = (HANDLE)_get_osfhandle(fd); + + fm = CreateFileMapping(h, NULL, PAGE_READONLY, 0, 0, NULL); + data = static_cast( + MapViewOfFile(fm, FILE_MAP_READ, 0, 0, s.st_size)); + + CloseHandle(fm); +#else + data = static_cast( + mmap(0, s.st_size, PROT_READ, MAP_PRIVATE, fd, 0)); +#endif + size = s.st_size; + } + close(fd); + } + + bool success = false; + + if (data) { + FileOutputStream out(argv[2]); + if (out.isValid()) { + success = writeObject(data, + size, + &out, + argv[3], + argv[4], + platform, + alignment, + writable, + executable); + } else { + fprintf(stderr, "unable to open %s\n", argv[2]); + } + +#ifdef _WIN32 + UnmapViewOfFile(data); +#else + munmap(data, size); +#endif + } else { + perror(argv[0]); + } + + return (success ? 0 : -1); +} diff --git a/sgx-jvm/avian/src/tools/bootimage-generator/main.cpp b/sgx-jvm/avian/src/tools/bootimage-generator/main.cpp new file mode 100644 index 0000000000..1b271a22dd --- /dev/null +++ b/sgx-jvm/avian/src/tools/bootimage-generator/main.cpp @@ -0,0 +1,2324 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#include +#include "avian/heapwalk.h" +#include "avian/common.h" +#include "avian/machine.h" +#include "avian/util.h" +#include +#include +#include +#include "avian/target.h" +#include +#include +#include "avian/lzma.h" + +#include +#include + +// since we aren't linking against libstdc++, we must implement this +// ourselves: +extern "C" void __cxa_pure_virtual(void) +{ + abort(); +} + +using namespace vm; +using namespace avian::tools; +using namespace avian::util; +using namespace avian::codegen; + +namespace { + +const unsigned HeapCapacity = 512 * 1024 * 1024; + +const unsigned TargetFixieSizeInBytes = 8 + (TargetBytesPerWord * 2); +const unsigned TargetFixieSizeInWords + = ceilingDivide(TargetFixieSizeInBytes, TargetBytesPerWord); +const unsigned TargetFixieAge = 0; +const unsigned TargetFixieFlags = 2; +const unsigned TargetFixieSize = 4; + +const bool DebugNativeTarget = false; + +enum Type { + Type_none, + Type_object, + Type_object_nogc, + Type_int8_t, + Type_uint8_t, + Type_int16_t, + Type_uint16_t, + Type_int32_t, + Type_uint32_t, + Type_intptr_t, + Type_uintptr_t, + Type_int64_t, + Type_int64_t_pad, + Type_uint64_t, + Type_float, + Type_double, + Type_double_pad, + Type_word, + Type_array +}; + +class Field { + public: + Type type; + unsigned buildOffset; + unsigned buildSize; + unsigned targetOffset; + unsigned targetSize; +}; + +void init(Field* f, + Type type, + unsigned buildOffset, + unsigned buildSize, + unsigned targetOffset, + unsigned targetSize) +{ + f->type = type; + f->buildOffset = buildOffset; + f->buildSize = buildSize; + f->targetOffset = targetOffset; + f->targetSize = targetSize; +} + +class TypeMap { + public: + enum Kind { NormalKind, SingletonKind, PoolKind }; + + TypeMap(unsigned buildFixedSizeInWords, + unsigned targetFixedSizeInWords, + unsigned fixedFieldCount, + Kind kind = NormalKind, + unsigned buildArrayElementSizeInBytes = 0, + unsigned targetArrayElementSizeInBytes = 0, + Type arrayElementType = Type_none) + : buildFixedSizeInWords(buildFixedSizeInWords), + targetFixedSizeInWords(targetFixedSizeInWords), + fixedFieldCount(fixedFieldCount), + buildArrayElementSizeInBytes(buildArrayElementSizeInBytes), + targetArrayElementSizeInBytes(targetArrayElementSizeInBytes), + arrayElementType(arrayElementType), + kind(kind) + { + } + + uintptr_t* targetFixedOffsets() + { + return reinterpret_cast(this + 1); + } + + Field* fixedFields() + { + return reinterpret_cast(targetFixedOffsets() + + (buildFixedSizeInWords * BytesPerWord)); + } + + static unsigned sizeInBytes(unsigned buildFixedSizeInWords, + unsigned fixedFieldCount) + { + return sizeof(TypeMap) + + (buildFixedSizeInWords * BytesPerWord * BytesPerWord) + + (sizeof(Field) * fixedFieldCount); + } + + unsigned buildFixedSizeInWords; + unsigned targetFixedSizeInWords; + unsigned fixedFieldCount; + unsigned buildArrayElementSizeInBytes; + unsigned targetArrayElementSizeInBytes; + Type arrayElementType; + Kind kind; +}; + +// Notes on immutable references in the heap image: +// +// One of the advantages of a bootimage-based build is that reduces +// the overhead of major GCs at runtime since we can avoid scanning +// the pre-built heap image entirely. However, this only works if we +// can ensure that no part of the heap image (with exceptions noted +// below) ever points to runtime-allocated objects. Therefore (most) +// references in the heap image are considered immutable, and any +// attempt to update them at runtime will cause the process to abort. +// +// However, some references in the heap image really must be updated +// at runtime: e.g. the static field table for each class. Therefore, +// we allocate these as "fixed" objects, subject to mark-and-sweep +// collection, instead of as "copyable" objects subject to copying +// collection. This strategy avoids the necessity of maintaining +// "dirty reference" bitsets at runtime for the entire heap image; +// each fixed object has its own bitset specific to that object. +// +// In addition to the "fixed" object solution, there are other +// strategies available to avoid attempts to update immutable +// references at runtime: +// +// * Table-based: use a lazily-updated array or vector to associate +// runtime data with heap image objects (see +// e.g. getClassRuntimeData in machine.cpp). +// +// * Update references at build time: for example, we set the names +// of primitive classes before generating the heap image so that we +// need not populate them lazily at runtime. + +bool endsWith(const char* suffix, const char* s, unsigned length) +{ + unsigned suffixLength = strlen(suffix); + return length >= suffixLength + and memcmp(suffix, s + (length - suffixLength), suffixLength) == 0; +} + +GcVector* getNonStaticFields(Thread* t, + GcHashMap* typeMaps, + GcClass* c, + GcVector* fields, + unsigned* count, + GcByteArray** array) +{ + PROTECT(t, typeMaps); + PROTECT(t, c); + PROTECT(t, fields); + + *array = cast( + t, + hashMapFind( + t, typeMaps, reinterpret_cast(c), objectHash, objectEqual)); + + if (*array) { + *count += reinterpret_cast((*array)->body().begin()) + ->fixedFieldCount; + } else { + if (c->super()) { + fields + = getNonStaticFields(t, typeMaps, c->super(), fields, count, array); + } + + if (GcArray* ftable = cast(t, c->fieldTable())) { + PROTECT(t, ftable); + for (unsigned i = 0; i < ftable->length(); ++i) { + GcField* field = cast(t, ftable->body()[i]); + + if ((field->flags() & ACC_STATIC) == 0) { + ++(*count); + fields = vectorAppend(t, fields, reinterpret_cast(field)); + } + } + } + } + + return vectorAppend(t, fields, 0); +} + +GcVector* allFields(Thread* t, + GcHashMap* typeMaps, + GcClass* c, + unsigned* count, + GcByteArray** array) +{ + PROTECT(t, typeMaps); + PROTECT(t, c); + + GcVector* fields = makeVector(t, 0, 0); + PROTECT(t, fields); + + *array = cast( + t, + hashMapFind( + t, typeMaps, reinterpret_cast(c), objectHash, objectEqual)); + + bool includeMembers; + if (*array) { + includeMembers = false; + *count += reinterpret_cast((*array)->body().begin()) + ->fixedFieldCount; + } else { + includeMembers = true; + if (c->super()) { + fields + = getNonStaticFields(t, typeMaps, c->super(), fields, count, array); + } + } + + if (GcArray* ftable = cast(t, c->fieldTable())) { + PROTECT(t, ftable); + for (unsigned i = 0; i < ftable->length(); ++i) { + GcField* field = cast(t, ftable->body()[i]); + + if (includeMembers or (field->flags() & ACC_STATIC)) { + ++(*count); + fields = vectorAppend(t, fields, reinterpret_cast(field)); + } + } + } + + return fields; +} + +TypeMap* classTypeMap(Thread* t, GcHashMap* typeMaps, object p) +{ + return reinterpret_cast( + cast(t, hashMapFind(t, typeMaps, p, objectHash, objectEqual)) + ->body() + .begin()); +} + +TypeMap* typeMap(Thread* t, GcHashMap* typeMaps, object p) +{ + return reinterpret_cast( + cast( + t, + objectClass(t, p) == type(t, GcSingleton::Type) + ? hashMapFind(t, typeMaps, p, objectHash, objectEqual) + : hashMapFind(t, + typeMaps, + reinterpret_cast(objectClass(t, p)), + objectHash, + objectEqual)) + ->body() + .begin()); +} + +unsigned targetFieldOffset(Thread* t, GcHashMap* typeMaps, GcField* field) +{ + unsigned offset + = ((field->flags() & ACC_STATIC) + ? typeMap(t, + typeMaps, + reinterpret_cast(field->class_()->staticTable())) + : classTypeMap( + t, typeMaps, reinterpret_cast(field->class_()))) + ->targetFixedOffsets()[field->offset()]; + + assertT(t, not((field->offset() == 0) xor (offset == 0))); + + return offset; +} + +void addClass(Thread* t, + GcClass* c, + const uint8_t* start, + size_t length, + GcHashMap* typeMaps) +{ + PROTECT(t, c); + PROTECT(t, typeMaps); + + { + class Client : public Stream::Client { + public: + Client(Thread* t) : t(t) + { + } + + virtual void NO_RETURN handleError() + { + abort(t); + } + + private: + Thread* t; + } client(t); + + Stream s(&client, start, length); + + uint32_t magic = s.read4(); + expect(t, magic == 0xCAFEBABE); + s.read2(); // minor version + s.read2(); // major version + + unsigned count = s.read2() - 1; + if (count) { + THREAD_RUNTIME_ARRAY(t, Type, types, count + 2); + RUNTIME_ARRAY_BODY(types)[0] = Type_object; + RUNTIME_ARRAY_BODY(types)[1] = Type_intptr_t; + + for (unsigned i = 2; i < count + 2; ++i) { + unsigned constType = s.read1(); + switch (constType) { + case CONSTANT_Class: + case CONSTANT_String: + RUNTIME_ARRAY_BODY(types)[i] = Type_object; + s.skip(2); + break; + + case CONSTANT_Integer: + case CONSTANT_Float: + RUNTIME_ARRAY_BODY(types)[i] = Type_int32_t; + s.skip(4); + break; + + case CONSTANT_NameAndType: + case CONSTANT_Fieldref: + case CONSTANT_Methodref: + case CONSTANT_InterfaceMethodref: + RUNTIME_ARRAY_BODY(types)[i] = Type_object; + s.skip(4); + break; + + case CONSTANT_Long: + RUNTIME_ARRAY_BODY(types)[i++] = Type_int64_t; + RUNTIME_ARRAY_BODY(types)[i] = Type_int64_t_pad; + s.skip(8); + break; + + case CONSTANT_Double: + RUNTIME_ARRAY_BODY(types)[i++] = Type_double; + RUNTIME_ARRAY_BODY(types)[i] = Type_double_pad; + s.skip(8); + break; + + case CONSTANT_Utf8: + RUNTIME_ARRAY_BODY(types)[i] = Type_object; + s.skip(s.read2()); + break; + + case CONSTANT_MethodHandle: + RUNTIME_ARRAY_BODY(types)[i] = Type_object; + s.skip(3); + break; + + case CONSTANT_MethodType: + RUNTIME_ARRAY_BODY(types)[i] = Type_object; + s.skip(2); + break; + + case CONSTANT_InvokeDynamic: + RUNTIME_ARRAY_BODY(types)[i] = Type_object; + s.skip(4); + break; + + default: + fprintf(stderr, "unknown class constant: %d\n", constType); + abort(t); + } + } + + GcByteArray* array + = makeByteArray(t, TypeMap::sizeInBytes(count + 2, count + 2)); + + TypeMap* map = new (array->body().begin()) + TypeMap(count + 2, count + 2, count + 2, TypeMap::PoolKind); + + for (unsigned i = 0; i < count + 2; ++i) { + expect(t, i < map->buildFixedSizeInWords); + + map->targetFixedOffsets()[i * BytesPerWord] = i * TargetBytesPerWord; + + init(new (map->fixedFields() + i) Field, + RUNTIME_ARRAY_BODY(types)[i], + i* BytesPerWord, + BytesPerWord, + i* TargetBytesPerWord, + TargetBytesPerWord); + } + + hashMapInsert( + t, + typeMaps, + reinterpret_cast(hashMapFind(t, + roots(t)->poolMap(), + reinterpret_cast(c), + objectHash, + objectEqual)), + reinterpret_cast(array), + objectHash); + } + } + + { + GcByteArray* array = 0; + PROTECT(t, array); + + unsigned count = 0; + GcVector* fields = allFields(t, typeMaps, c, &count, &array); + PROTECT(t, fields); + + THREAD_RUNTIME_ARRAY(t, Field, memberFields, count + 1); + + unsigned memberIndex; + unsigned buildMemberOffset; + unsigned targetMemberOffset; + + if (array) { + memberIndex = 0; + buildMemberOffset = 0; + targetMemberOffset = 0; + + TypeMap* map = reinterpret_cast(array->body().begin()); + + for (unsigned j = 0; j < map->fixedFieldCount; ++j) { + Field* f = map->fixedFields() + j; + + RUNTIME_ARRAY_BODY(memberFields)[memberIndex] = *f; + + targetMemberOffset = f->targetOffset + f->targetSize; + + ++memberIndex; + } + } else { + init(new (RUNTIME_ARRAY_BODY(memberFields)) Field, + Type_object, + 0, + BytesPerWord, + 0, + TargetBytesPerWord); + + memberIndex = 1; + buildMemberOffset = BytesPerWord; + targetMemberOffset = TargetBytesPerWord; + } + + const unsigned StaticHeader = 3; + + THREAD_RUNTIME_ARRAY(t, Field, staticFields, count + StaticHeader); + + init(new (RUNTIME_ARRAY_BODY(staticFields)) Field, + Type_object, + 0, + BytesPerWord, + 0, + TargetBytesPerWord); + + init(new (RUNTIME_ARRAY_BODY(staticFields) + 1) Field, + Type_intptr_t, + BytesPerWord, + BytesPerWord, + TargetBytesPerWord, + TargetBytesPerWord); + + init(new (RUNTIME_ARRAY_BODY(staticFields) + 2) Field, + Type_object, + BytesPerWord * 2, + BytesPerWord, + TargetBytesPerWord * 2, + TargetBytesPerWord); + + unsigned staticIndex = StaticHeader; + unsigned buildStaticOffset = BytesPerWord * StaticHeader; + unsigned targetStaticOffset = TargetBytesPerWord * StaticHeader; + + for (unsigned i = 0; i < fields->size(); ++i) { + GcField* field = cast(t, fields->body()[i]); + if (field) { + unsigned buildSize = fieldSize(t, field->code()); + unsigned targetSize = buildSize; + + Type type; + switch (field->code()) { + case ObjectField: + type = Type_object; + targetSize = TargetBytesPerWord; + break; + + case ByteField: + case BooleanField: + type = Type_int8_t; + break; + + case CharField: + case ShortField: + type = Type_int8_t; + break; + + case FloatField: + case IntField: + type = Type_int32_t; + break; + + case LongField: + case DoubleField: + type = Type_int64_t; + break; + + default: + abort(t); + } + + if (field->flags() & ACC_STATIC) { + targetStaticOffset = pad(targetStaticOffset, targetSize); + + buildStaticOffset = field->offset(); + + init(new (RUNTIME_ARRAY_BODY(staticFields) + staticIndex) Field, + type, + buildStaticOffset, + buildSize, + targetStaticOffset, + targetSize); + + targetStaticOffset += targetSize; + + ++staticIndex; + } else { + targetMemberOffset = pad(targetMemberOffset, targetSize); + + buildMemberOffset = field->offset(); + + init(new (RUNTIME_ARRAY_BODY(memberFields) + memberIndex) Field, + type, + buildMemberOffset, + buildSize, + targetMemberOffset, + targetSize); + + targetMemberOffset += targetSize; + + ++memberIndex; + } + } else { + targetMemberOffset = pad(targetMemberOffset, TargetBytesPerWord); + } + } + + if (hashMapFind( + t, typeMaps, reinterpret_cast(c), objectHash, objectEqual) + == 0) { + GcByteArray* array = makeByteArray( + t, + TypeMap::sizeInBytes(ceilingDivide(c->fixedSize(), BytesPerWord), + memberIndex)); + + TypeMap* map = new (array->body().begin()) + TypeMap(ceilingDivide(c->fixedSize(), BytesPerWord), + ceilingDivide(targetMemberOffset, TargetBytesPerWord), + memberIndex); + + for (unsigned i = 0; i < memberIndex; ++i) { + Field* f = RUNTIME_ARRAY_BODY(memberFields) + i; + + expect(t, f->buildOffset < map->buildFixedSizeInWords * BytesPerWord); + + map->targetFixedOffsets()[f->buildOffset] = f->targetOffset; + + map->fixedFields()[i] = *f; + } + + hashMapInsert(t, + typeMaps, + reinterpret_cast(c), + reinterpret_cast(array), + objectHash); + } + + if (c->staticTable()) { + GcByteArray* array = makeByteArray( + t, + TypeMap::sizeInBytes(singletonCount(t, c->staticTable()) + 2, + staticIndex)); + + TypeMap* map = new (array->body().begin()) + TypeMap(singletonCount(t, c->staticTable()) + 2, + ceilingDivide(targetStaticOffset, TargetBytesPerWord), + staticIndex, + TypeMap::SingletonKind); + + for (unsigned i = 0; i < staticIndex; ++i) { + Field* f = RUNTIME_ARRAY_BODY(staticFields) + i; + + expect(t, f->buildOffset < map->buildFixedSizeInWords * BytesPerWord); + + map->targetFixedOffsets()[f->buildOffset] = f->targetOffset; + + map->fixedFields()[i] = *f; + } + + hashMapInsert(t, + typeMaps, + reinterpret_cast(c->staticTable()), + reinterpret_cast(array), + objectHash); + } + } +} + +void compileMethods(Thread* t, + GcClass* c, + Zone* zone, + GcTriple** constants, + GcTriple** calls, + GcPair** methods, + DelayedPromise** addresses, + OffsetResolver* resolver, + JavaVM* hostVM, + const char* methodName, + const char* methodSpec) +{ + PROTECT(t, c); + + if (GcArray* mtable = cast(t, c->methodTable())) { + PROTECT(t, mtable); + for (unsigned i = 0; i < mtable->length(); ++i) { + GcMethod* method = cast(t, mtable->body()[i]); + if (((methodName == 0 + or ::strcmp(reinterpret_cast(method->name()->body().begin()), + methodName) == 0) + and (methodSpec == 0 + or ::strcmp( + reinterpret_cast(method->spec()->body().begin()), + methodSpec) == 0))) { + if (method->code() or (method->flags() & ACC_NATIVE)) { + PROTECT(t, method); + + t->m->processor->compileMethod( + t, zone, constants, calls, addresses, method, resolver, hostVM); + + if (method->code()) { + *methods = makePair(t, + reinterpret_cast(method), + reinterpret_cast(*methods)); + } + } + + GcMethodAddendum* addendum = method->addendum(); + if (addendum and addendum->exceptionTable()) { + PROTECT(t, addendum); + GcShortArray* exceptionTable + = cast(t, addendum->exceptionTable()); + PROTECT(t, exceptionTable); + + // resolve exception types now to avoid trying to update + // immutable references at runtime + for (unsigned i = 0; i < exceptionTable->length(); ++i) { + uint16_t index = exceptionTable->body()[i] - 1; + + object o = singletonObject(t, addendum->pool(), index); + + if (objectClass(t, o) == type(t, GcReference::Type)) { + o = reinterpret_cast(resolveClass( + t, roots(t)->bootLoader(), cast(t, o)->name())); + + addendum->pool()->setBodyElement( + t, index, reinterpret_cast(o)); + } + } + } + } + } + } +} + +GcTriple* makeCodeImage(Thread* t, + Zone* zone, + BootImage* image, + uint8_t* code, + JavaVM* hostVM, + const char* className, + const char* methodName, + const char* methodSpec, + GcHashMap* typeMaps) +{ + PROTECT(t, typeMaps); + + t->m->classpath->interceptMethods(t); + + GcPair* classes = 0; + PROTECT(t, classes); + + class MyOffsetResolver : public OffsetResolver { + public: + MyOffsetResolver(GcHashMap** typeMaps, GcPair** classes) + : typeMaps(typeMaps), classes(classes) + { + } + + virtual unsigned fieldOffset(Thread* t, GcField* field) + { + return targetFieldOffset(t, *typeMaps, field); + } + + virtual void addClass(Thread* t, + GcClass* c, + const uint8_t* start, + size_t length) + { + PROTECT(t, c); + + *classes = makePair( + t, reinterpret_cast(c), reinterpret_cast(*classes)); + + return ::addClass(t, c, start, length, *typeMaps); + } + + GcHashMap** typeMaps; + GcPair** classes; + } resolver(&typeMaps, &classes); + + Finder* finder = static_cast( + roots(t)->bootLoader()->as(t)->finder()); + + for (Finder::Iterator it(finder); it.hasMore();) { + size_t nameSize = 0; + const char* name = it.next(&nameSize); + + if (endsWith(".class", name, nameSize) + and (className == 0 or strncmp(name, className, nameSize - 6) == 0)) { + if (false) { + fprintf(stderr, "pass 1 %.*s\n", (int)nameSize - 6, name); + } + + GcClass* c + = resolveSystemClass(t, + roots(t)->bootLoader(), + makeByteArray(t, "%.*s", nameSize - 6, name), + true); + + System::Region* region = finder->find(name); + + THREAD_RESOURCE(t, System::Region*, region, region->dispose()); + + addClass(t, c, region->start(), region->length(), typeMaps); + } + } + + GcTriple* constants = 0; + PROTECT(t, constants); + + GcTriple* calls = 0; + PROTECT(t, calls); + + GcPair* methods = 0; + PROTECT(t, methods); + + DelayedPromise* addresses = 0; + + for (Finder::Iterator it(finder); it.hasMore();) { + size_t nameSize = 0; + const char* name = it.next(&nameSize); + + if (endsWith(".class", name, nameSize) + and (className == 0 or strncmp(name, className, nameSize - 6) == 0)) { + if (false) { + fprintf(stderr, "pass 2 %.*s\n", (int)nameSize - 6, name); + } + + GcClass* c + = resolveSystemClass(t, + roots(t)->bootLoader(), + makeByteArray(t, "%.*s", nameSize - 6, name), + true); + + classes = makePair( + t, reinterpret_cast(c), reinterpret_cast(classes)); + } + } + + // Each method compilation may result in the creation of new, + // synthetic classes (e.g. for lambda expressions), so we must + // iterate until we've visited them all: + while (classes) { + GcPair* myClasses = classes; + PROTECT(t, myClasses); + + classes = 0; + + for (; myClasses; myClasses = cast(t, myClasses->second())) { + compileMethods(t, + cast(t, myClasses->first()), + zone, + &constants, + &calls, + &methods, + &addresses, + &resolver, + hostVM, + methodName, + methodSpec); + } + } + + for (; calls; calls = cast(t, calls->third())) { + GcMethod* method = cast(t, calls->first()); + uintptr_t address; + if (method->flags() & ACC_NATIVE) { + address = reinterpret_cast(code + image->thunks.native.start); + } else { + address = method->code()->compiled(); + } + + static_cast(cast(t, calls->second())->value()) + ->listener->resolve(address, 0); + } + + for (; addresses; addresses = addresses->next) { + uint8_t* value = reinterpret_cast(addresses->basis->value()); + expect(t, value >= code); + + addresses->listener->resolve(static_cast(value - code), 0); + } + + for (; methods; methods = cast(t, methods->second())) { + cast(t, methods->first())->code()->compiled() + -= reinterpret_cast(code); + } + + t->m->processor->normalizeVirtualThunks(t); + + return constants; +} + +void visitRoots(Thread* t, BootImage* image, HeapWalker* w, GcTriple* constants) +{ + Machine* m = t->m; + + for (HashMapIterator it(t, cast(t, roots(t)->bootLoader()->map())); + it.hasMore();) { + w->visitRoot(it.next()->second()); + } + + image->bootLoader + = w->visitRoot(reinterpret_cast(roots(t)->bootLoader())); + image->appLoader + = w->visitRoot(reinterpret_cast(roots(t)->appLoader())); + image->types = w->visitRoot(reinterpret_cast(m->types)); + + m->processor->visitRoots(t, w); + + for (; constants; constants = cast(t, constants->third())) { + w->visitRoot(constants->first()); + } +} + +unsigned targetOffset(Thread* t, GcHashMap* typeMaps, object p, unsigned offset) +{ + TypeMap* map = typeMap(t, typeMaps, p); + + if (map->targetArrayElementSizeInBytes + and offset >= map->buildFixedSizeInWords * BytesPerWord) { + return (map->targetFixedSizeInWords * TargetBytesPerWord) + + (((offset - (map->buildFixedSizeInWords * BytesPerWord)) + / map->buildArrayElementSizeInBytes) + * map->targetArrayElementSizeInBytes); + } else { + return map->targetFixedOffsets()[offset]; + } +} + +unsigned targetSize(Thread* t, GcHashMap* typeMaps, object p) +{ + TypeMap* map = typeMap(t, typeMaps, p); + + if (map->targetArrayElementSizeInBytes) { + return map->targetFixedSizeInWords + + ceilingDivide( + map->targetArrayElementSizeInBytes + * fieldAtOffset( + p, (map->buildFixedSizeInWords - 1) * BytesPerWord), + TargetBytesPerWord); + } else { + switch (map->kind) { + case TypeMap::NormalKind: + return map->targetFixedSizeInWords; + + case TypeMap::SingletonKind: + return map->targetFixedSizeInWords + + singletonMaskSize(map->targetFixedSizeInWords - 2, + TargetBitsPerWord); + + case TypeMap::PoolKind: { + unsigned maskSize + = poolMaskSize(map->targetFixedSizeInWords - 2, TargetBitsPerWord); + + return map->targetFixedSizeInWords + maskSize + + singletonMaskSize(map->targetFixedSizeInWords - 2 + maskSize, + TargetBitsPerWord); + } + + default: + abort(t); + } + } +} + +unsigned objectMaskCount(TypeMap* map) +{ + unsigned count = map->targetFixedSizeInWords; + + if (map->targetArrayElementSizeInBytes) { + ++count; + } + + return count; +} + +unsigned targetSize(Thread* t, + GcHashMap* typeMaps, + object referer, + unsigned refererOffset, + object p) +{ + if (referer and objectClass(t, referer) == type(t, GcClass::Type) + and (refererOffset * BytesPerWord) == ClassObjectMask) { + return (TargetBytesPerWord * 2) + + pad(ceilingDivide( + objectMaskCount(classTypeMap(t, typeMaps, referer)), 32) + * 4, + TargetBytesPerWord); + } else { + return targetSize(t, typeMaps, p); + } +} + +void copy(Thread* t, uint8_t* src, uint8_t* dst, Type type) +{ + switch (type) { + case Type_int8_t: + memcpy(dst, src, 1); + break; + + case Type_int16_t: { + int16_t s; + memcpy(&s, src, 2); + int16_t d = targetV2(s); + memcpy(dst, &d, 2); + } break; + + case Type_int32_t: + case Type_float: { + int32_t s; + memcpy(&s, src, 4); + int32_t d = targetV4(s); + memcpy(dst, &d, 4); + } break; + + case Type_int64_t: + case Type_double: { + int64_t s; + memcpy(&s, src, 8); + int64_t d = targetV8(s); + memcpy(dst, &d, 8); + } break; + + case Type_int64_t_pad: + case Type_double_pad: + break; + + case Type_intptr_t: { + intptr_t s; + memcpy(&s, src, BytesPerWord); + target_intptr_t d = targetVW(s); + memcpy(dst, &d, TargetBytesPerWord); + } break; + + case Type_object: { + memset(dst, 0, TargetBytesPerWord); + } break; + + default: + abort(t); + } +} + +bool nonObjectsEqual(uint8_t* src, uint8_t* dst, Type type) +{ + switch (type) { + case Type_int8_t: + return memcmp(dst, src, 1) == 0; + + case Type_int16_t: + return memcmp(dst, src, 2) == 0; + + case Type_int32_t: + case Type_float: + return memcmp(dst, src, 4) == 0; + + case Type_int64_t: + case Type_double: + return memcmp(dst, src, 8) == 0; + + case Type_int64_t_pad: + case Type_double_pad: + return true; + + case Type_intptr_t: + return memcmp(dst, src, BytesPerWord) == 0; + + case Type_object: + case Type_object_nogc: + return true; + + default: + abort(); + } +} + +bool nonObjectsEqual(TypeMap* map, uint8_t* src, uint8_t* dst) +{ + for (unsigned i = 0; i < map->fixedFieldCount; ++i) { + Field* field = map->fixedFields() + i; + if (not nonObjectsEqual( + src + field->buildOffset, dst + field->targetOffset, field->type)) { + return false; + } + } + + if (map->targetArrayElementSizeInBytes) { + unsigned fixedSize = map->buildFixedSizeInWords * BytesPerWord; + unsigned count = fieldAtOffset(src, fixedSize - BytesPerWord); + + for (unsigned i = 0; i < count; ++i) { + if (not nonObjectsEqual( + src + fixedSize + (i * map->buildArrayElementSizeInBytes), + dst + (map->targetFixedSizeInWords * TargetBytesPerWord) + + (i * map->targetArrayElementSizeInBytes), + map->arrayElementType)) { + return false; + } + } + } + + return true; +} + +void copy(Thread* t, GcHashMap* typeMaps, object p, uint8_t* dst) +{ + TypeMap* map = typeMap(t, typeMaps, p); + + uint8_t* src = reinterpret_cast(p); + + for (unsigned i = 0; i < map->fixedFieldCount; ++i) { + Field* field = map->fixedFields() + i; + if (field->type > Type_array) + abort(t); + copy(t, src + field->buildOffset, dst + field->targetOffset, field->type); + } + + if (map->targetArrayElementSizeInBytes) { + unsigned fixedSize = map->buildFixedSizeInWords * BytesPerWord; + unsigned count = fieldAtOffset(p, fixedSize - BytesPerWord); + + for (unsigned i = 0; i < count; ++i) { + copy(t, + src + fixedSize + (i * map->buildArrayElementSizeInBytes), + dst + (map->targetFixedSizeInWords * TargetBytesPerWord) + + (i * map->targetArrayElementSizeInBytes), + map->arrayElementType); + } + + if (objectClass(t, p) == type(t, GcClass::Type)) { + uint16_t fixedSize; + uint8_t arrayElementSize; + GcByteArray* array = cast( + t, hashMapFind(t, typeMaps, p, objectHash, objectEqual)); + PROTECT(t, array); + + GcClass* c = cast(t, p); + PROTECT(t, c); + + if (array) { + TypeMap* classMap = reinterpret_cast(array->body().begin()); + + fixedSize + = targetV2(classMap->targetFixedSizeInWords * TargetBytesPerWord); + + arrayElementSize = classMap->targetArrayElementSizeInBytes; + } else if (c->fixedSize() == BytesPerWord * 2 + and c->arrayElementSize() == BytesPerWord) { + fixedSize = targetV2(TargetBytesPerWord * 2); + + arrayElementSize = TargetBytesPerWord; + } else { + fixedSize = 0; + arrayElementSize = 0; + } + + if (fixedSize) { + memcpy(dst + TargetClassFixedSize, &fixedSize, 2); + + memcpy(dst + TargetClassArrayElementSize, &arrayElementSize, 1); + } + + // if (strcmp("vm::lineNumberTable", + // reinterpret_cast(&byteArrayBody(t, className(t, + // p), 0))) == 0) trap(); + } + } else { + switch (map->kind) { + case TypeMap::NormalKind: + if (objectClass(t, p) == type(t, GcField::Type)) { + uint16_t offset + = targetV2(targetFieldOffset(t, typeMaps, cast(t, p))); + memcpy(dst + TargetFieldOffset, &offset, 2); + } + break; + + case TypeMap::SingletonKind: { + unsigned maskSize = singletonMaskSize(map->targetFixedSizeInWords - 2, + TargetBitsPerWord); + + target_uintptr_t targetLength + = targetVW(map->targetFixedSizeInWords - 2 + maskSize); + memcpy(dst + TargetBytesPerWord, &targetLength, TargetBytesPerWord); + + uint8_t* mask = dst + (map->targetFixedSizeInWords * TargetBytesPerWord); + memset(mask, 0, maskSize * TargetBytesPerWord); + + for (unsigned i = 0; i < map->fixedFieldCount; ++i) { + Field* field = map->fixedFields() + i; + if (field->type == Type_object) { + unsigned offset = field->targetOffset / TargetBytesPerWord; + reinterpret_cast(mask)[offset / 32] + |= targetV4(static_cast(1) << (offset % 32)); + } + } + + if (DebugNativeTarget) { + expect(t, + memcmp(src + (map->targetFixedSizeInWords * TargetBytesPerWord), + mask, + singletonMaskSize(map->targetFixedSizeInWords - 2, + TargetBitsPerWord) * TargetBytesPerWord) + == 0); + } + } break; + + case TypeMap::PoolKind: { + unsigned poolMaskSize = vm::poolMaskSize(map->targetFixedSizeInWords - 2, + TargetBitsPerWord); + + unsigned objectMaskSize = singletonMaskSize( + map->targetFixedSizeInWords - 2 + poolMaskSize, TargetBitsPerWord); + + target_uintptr_t targetLength = targetVW(map->targetFixedSizeInWords - 2 + + poolMaskSize + objectMaskSize); + memcpy(dst + TargetBytesPerWord, &targetLength, TargetBytesPerWord); + + uint8_t* poolMask = dst + + (map->targetFixedSizeInWords * TargetBytesPerWord); + + memset(poolMask, 0, poolMaskSize * TargetBytesPerWord); + + uint8_t* objectMask = dst + ((map->targetFixedSizeInWords + poolMaskSize) + * TargetBytesPerWord); + + memset(objectMask, 0, objectMaskSize * TargetBytesPerWord); + + for (unsigned i = 0; i < map->fixedFieldCount; ++i) { + Field* field = map->fixedFields() + i; + switch (field->type) { + case Type_object: + reinterpret_cast(objectMask)[i / 32] + |= targetV4(static_cast(1) << (i % 32)); + break; + + case Type_float: + case Type_double: + reinterpret_cast(poolMask)[i / TargetBitsPerWord] + |= targetVW(static_cast(1) + << (i % TargetBitsPerWord)); + break; + + default: + break; + } + } + + if (DebugNativeTarget) { + expect(t, + memcmp(src + (map->targetFixedSizeInWords * TargetBytesPerWord), + poolMask, + (poolMaskSize + + singletonMaskSize( + map->targetFixedSizeInWords - 2 + poolMaskSize, + TargetBitsPerWord)) * TargetBytesPerWord) == 0); + } + } break; + + default: + abort(t); + } + } +} + +void copy(Thread* t, + GcHashMap* typeMaps, + object referer, + unsigned refererOffset, + object p, + uint8_t* dst) +{ + if (referer and objectClass(t, referer) == type(t, GcClass::Type) + and (refererOffset * BytesPerWord) == ClassObjectMask) { + TypeMap* map = classTypeMap(t, typeMaps, referer); + + memset(dst, 0, TargetBytesPerWord); + + unsigned length = ceilingDivide(objectMaskCount(map), 32); + + target_uintptr_t targetLength = targetVW(length); + + memcpy(dst + TargetBytesPerWord, &targetLength, TargetBytesPerWord); + + memset(dst + (TargetBytesPerWord * 2), 0, length * 4); + + for (unsigned i = 0; i < map->fixedFieldCount; ++i) { + Field* field = map->fixedFields() + i; + if (field->type == Type_object) { + unsigned offset = field->targetOffset / TargetBytesPerWord; + reinterpret_cast(dst + (TargetBytesPerWord * 2))[offset / 32] + |= targetV4(static_cast(1) << (offset % 32)); + } + } + + if (map->targetArrayElementSizeInBytes + and map->arrayElementType == Type_object) { + unsigned offset = map->targetFixedSizeInWords; + reinterpret_cast(dst + (TargetBytesPerWord * 2))[offset / 32] + |= targetV4(static_cast(1) << (offset % 32)); + } + } else { + copy(t, typeMaps, p, dst); + } + + if (DebugNativeTarget) { + expect(t, targetSize(t, typeMaps, p) == baseSize(t, p, objectClass(t, p))); + expect(t, + nonObjectsEqual( + typeMap(t, typeMaps, p), reinterpret_cast(p), dst)); + } +} + +HeapWalker* makeHeapImage(Thread* t, + BootImage* image, + target_uintptr_t* heap, + target_uintptr_t* map, + unsigned capacity, + GcTriple* constants, + GcHashMap* typeMaps) +{ + class Visitor : public HeapVisitor { + public: + Visitor(Thread* t, + GcHashMap* typeMaps, + target_uintptr_t* heap, + target_uintptr_t* map, + unsigned capacity) + : t(t), + typeMaps(typeMaps), + currentObject(0), + currentNumber(0), + currentOffset(0), + heap(heap), + map(map), + position(0), + capacity(capacity) + { + } + + void visit(unsigned number) + { + if (currentObject) { + if (DebugNativeTarget) { + expect(t, + targetOffset( + t, typeMaps, currentObject, currentOffset * BytesPerWord) + == currentOffset * BytesPerWord); + } + + unsigned offset + = currentNumber - 1 + + (targetOffset( + t, typeMaps, currentObject, currentOffset * BytesPerWord) + / TargetBytesPerWord); + + unsigned mark = heap[offset] & (~TargetPointerMask); + unsigned value = number | (mark << TargetBootShift); + + if (value) + targetMarkBit(map, offset); + + heap[offset] = targetVW(value); + } + } + + virtual void root() + { + currentObject = 0; + } + + virtual unsigned visitNew(object p) + { + if (p) { + unsigned size + = targetSize(t, typeMaps, currentObject, currentOffset, p); + + unsigned number; + if ((currentObject + and objectClass(t, currentObject) == type(t, GcClass::Type) + and (currentOffset * BytesPerWord) == ClassStaticTable) + or instanceOf(t, type(t, GcSystemClassLoader::Type), p) + or instanceOf(t, type(t, GcAddendum::Type), p)) { + // Static tables, system classloaders, and addendums must be + // allocated as fixed objects in the heap image so that they + // can be marked as dirty and visited during GC. Otherwise, + // attempts to update references in these objects to point + // to runtime-allocated memory would fail because we don't + // scan non-fixed objects in the heap image during GC. + + target_uintptr_t* dst = heap + position + TargetFixieSizeInWords; + + unsigned maskSize = ceilingDivide(size, TargetBitsPerWord); + + unsigned total = TargetFixieSizeInWords + size + maskSize; + + expect(t, position + total < capacity); + + memset(heap + position, 0, TargetFixieSizeInBytes); + + uint16_t age = targetV2(FixieTenureThreshold + 1); + memcpy(reinterpret_cast(heap + position) + TargetFixieAge, + &age, + 2); + + uint16_t flags = targetV2(1); + memcpy(reinterpret_cast(heap + position) + TargetFixieFlags, + &flags, + 2); + + uint32_t targetSize = targetV4(size); + memcpy(reinterpret_cast(heap + position) + TargetFixieSize, + &targetSize, + 4); + + copy(t, + typeMaps, + currentObject, + currentOffset, + p, + reinterpret_cast(dst)); + + dst[0] |= FixedMark; + + memset(heap + position + TargetFixieSizeInWords + size, + 0, + maskSize * TargetBytesPerWord); + + number = (dst - heap) + 1; + position += total; + } else { + expect(t, position + size < capacity); + + copy(t, + typeMaps, + currentObject, + currentOffset, + p, + reinterpret_cast(heap + position)); + + number = position + 1; + position += size; + } + + visit(number); + + return number; + } else { + return 0; + } + } + + virtual void visitOld(object, unsigned number) + { + visit(number); + } + + virtual void push(object object, unsigned number, unsigned offset) + { + currentObject = object; + currentNumber = number; + currentOffset = offset; + } + + virtual void pop() + { + currentObject = 0; + } + + Thread* t; + GcHashMap* typeMaps; + object currentObject; + unsigned currentNumber; + unsigned currentOffset; + target_uintptr_t* heap; + target_uintptr_t* map; + unsigned position; + unsigned capacity; + } visitor(t, typeMaps, heap, map, capacity / TargetBytesPerWord); + + HeapWalker* w = makeHeapWalker(t, &visitor); + visitRoots(t, image, w, constants); + + image->heapSize = visitor.position * TargetBytesPerWord; + + return w; +} + +void updateConstants(Thread* t, GcTriple* constants, HeapMap* heapTable) +{ + for (; constants; constants = cast(t, constants->third())) { + unsigned target = heapTable->find(constants->first()); + expect(t, target > 0); + + for (Promise::Listener* pl + = static_cast( + cast(t, constants->second())->value())->listener; + pl; + pl = pl->next) { + pl->resolve((target - 1) * TargetBytesPerWord, 0); + } + } +} + +BootImage::Thunk targetThunk(BootImage::Thunk t) +{ + return BootImage::Thunk( + targetV4(t.start), targetV4(t.frameSavedOffset), targetV4(t.length)); +} + +void writeBootImage2(Thread* t, + OutputStream* bootimageOutput, + OutputStream* codeOutput, + BootImage* image, + uint8_t* code, + JavaVM* hostVM, + const char* className, + const char* methodName, + const char* methodSpec, + const char* bootimageStart, + const char* bootimageEnd, + const char* codeimageStart, + const char* codeimageEnd, + bool useLZMA) +{ + GcThrowable* throwable + = cast(t, make(t, type(t, GcOutOfMemoryError::Type))); + // sequence point, for gc (don't recombine statements) + roots(t)->setOutOfMemoryError(t, throwable); + + Zone zone(t->m->heap, 64 * 1024); + + class MyCompilationHandler : public Processor::CompilationHandler { + public: + String heapDup(const char* name) + { + String ret(name); + char* n = (char*)heap->allocate(ret.length + 1); + memcpy(n, ret.text, ret.length + 1); + ret.text = n; + return ret; + } + + virtual void compiled(const void* code, + unsigned size UNUSED, + unsigned frameSize UNUSED, + const char* name) + { + uint64_t offset = reinterpret_cast(code) - codeOffset; + symbols.add(SymbolInfo(offset, heapDup(name))); + // printf("%ld %ld %s.%s%s\n", offset, offset + size, class_, name, spec); + } + + virtual void dispose() + { + } + + DynamicArray symbols; + uint64_t codeOffset; + Heap* heap; + + MyCompilationHandler(uint64_t codeOffset, Heap* heap) + : codeOffset(codeOffset), heap(heap) + { + } + + } compilationHandler(reinterpret_cast(code), t->m->heap); + + t->m->processor->addCompilationHandler(&compilationHandler); + + GcHashMap* classPoolMap; + GcHashMap* typeMaps; + GcTriple* constants; + + { + classPoolMap = makeHashMap(t, 0, 0); + PROTECT(t, classPoolMap); + + roots(t)->setPoolMap(t, classPoolMap); + + typeMaps = makeHashMap(t, 0, 0); + PROTECT(t, typeMaps); + +#include "type-maps.cpp" + + for (unsigned i = 0; i < t->m->types->length(); ++i) { + Type* source = types[i]; + unsigned typeCount = 0; + unsigned fieldCount = 1; + while (source[typeCount] != Type_none) { + ++typeCount; + ++fieldCount; + } + + THREAD_RUNTIME_ARRAY(t, Field, fields, fieldCount); + + init(new (RUNTIME_ARRAY_BODY(fields)) Field, + Type_object, + 0, + BytesPerWord, + 0, + TargetBytesPerWord); + + unsigned buildOffset = BytesPerWord; + unsigned targetOffset = TargetBytesPerWord; + bool sawArray = false; + Type type = Type_none; + unsigned buildSize = 0; + unsigned targetSize = 0; + unsigned fieldOffset = 1; + for (unsigned j = 0; j < typeCount; ++j) { + switch (source[j]) { + case Type_object: + type = Type_object; + buildSize = BytesPerWord; + targetSize = TargetBytesPerWord; + break; + + case Type_object_nogc: + type = Type_object_nogc; + buildSize = BytesPerWord; + targetSize = TargetBytesPerWord; + break; + + case Type_word: + case Type_intptr_t: + case Type_uintptr_t: + type = Type_intptr_t; + buildSize = BytesPerWord; + targetSize = TargetBytesPerWord; + break; + + case Type_int8_t: + case Type_uint8_t: + type = Type_int8_t; + buildSize = targetSize = 1; + break; + + case Type_int16_t: + case Type_uint16_t: + type = Type_int16_t; + buildSize = targetSize = 2; + break; + + case Type_int32_t: + case Type_uint32_t: + case Type_float: + type = Type_int32_t; + buildSize = targetSize = 4; + break; + + case Type_int64_t: + case Type_uint64_t: + case Type_double: + type = Type_int64_t; + buildSize = targetSize = 8; + break; + + case Type_array: + type = Type_none; + buildSize = targetSize = 0; + break; + + default: + abort(t); + } + + if (source[j] == Type_array) { + sawArray = true; + } + + if (not sawArray) { + buildOffset = pad(buildOffset, buildSize); + + targetOffset = pad(targetOffset, targetSize); + + init(new (RUNTIME_ARRAY_BODY(fields) + (fieldOffset++)) Field, + type, + buildOffset, + buildSize, + targetOffset, + targetSize); + + buildOffset += buildSize; + targetOffset += targetSize; + } + } + + unsigned fixedFieldCount; + Type arrayElementType; + unsigned buildArrayElementSize; + unsigned targetArrayElementSize; + if (sawArray) { + fixedFieldCount = fieldCount - 2; + arrayElementType = type; + buildArrayElementSize = buildSize; + targetArrayElementSize = targetSize; + } else { + fixedFieldCount = fieldCount; + arrayElementType = Type_none; + buildArrayElementSize = 0; + targetArrayElementSize = 0; + } + + GcByteArray* array = makeByteArray( + t, + TypeMap::sizeInBytes(ceilingDivide(buildOffset, BytesPerWord), + fixedFieldCount)); + + TypeMap* map = new (array->body().begin()) + TypeMap(ceilingDivide(buildOffset, BytesPerWord), + ceilingDivide(targetOffset, TargetBytesPerWord), + fixedFieldCount, + TypeMap::NormalKind, + buildArrayElementSize, + targetArrayElementSize, + arrayElementType); + + for (unsigned j = 0; j < fixedFieldCount; ++j) { + Field* f = RUNTIME_ARRAY_BODY(fields) + j; + + expect(t, f->buildOffset < map->buildFixedSizeInWords * BytesPerWord); + + map->targetFixedOffsets()[f->buildOffset] = f->targetOffset; + + map->fixedFields()[j] = *f; + } + + hashMapInsert( + t, + typeMaps, + reinterpret_cast(vm::type(t, static_cast(i))), + reinterpret_cast(array), + objectHash); + } + + constants = makeCodeImage(t, + &zone, + image, + code, + hostVM, + className, + methodName, + methodSpec, + typeMaps); + + PROTECT(t, constants); + + // these roots will not be used when the bootimage is loaded, so + // there's no need to preserve them: + roots(t)->setPoolMap(t, 0); + + GcWeakHashMap* map = makeWeakHashMap(t, 0, 0); + // sequence point, for gc (don't recombine statements) + roots(t)->setByteArrayMap(t, map->as(t)); + + // name all primitive classes so we don't try to update immutable + // references at runtime: + { + GcByteArray* name = makeByteArray(t, "void"); + // sequence point, for gc (don't recombine statements) + type(t, GcJvoid::Type)->setName(t, name); + + name = makeByteArray(t, "boolean"); + // sequence point, for gc (don't recombine statements) + type(t, GcJboolean::Type)->setName(t, name); + + name = makeByteArray(t, "byte"); + // sequence point, for gc (don't recombine statements) + type(t, GcJbyte::Type)->setName(t, name); + + name = makeByteArray(t, "short"); + // sequence point, for gc (don't recombine statements) + type(t, GcJshort::Type)->setName(t, name); + + name = makeByteArray(t, "char"); + // sequence point, for gc (don't recombine statements) + type(t, GcJchar::Type)->setName(t, name); + + name = makeByteArray(t, "int"); + // sequence point, for gc (don't recombine statements) + type(t, GcJint::Type)->setName(t, name); + + name = makeByteArray(t, "float"); + // sequence point, for gc (don't recombine statements) + type(t, GcJfloat::Type)->setName(t, name); + + name = makeByteArray(t, "long"); + // sequence point, for gc (don't recombine statements) + type(t, GcJlong::Type)->setName(t, name); + + name = makeByteArray(t, "double"); + // sequence point, for gc (don't recombine statements) + type(t, GcJdouble::Type)->setName(t, name); + } + + // resolve primitive array classes in case they are needed at + // runtime: + { + GcByteArray* name = makeByteArray(t, "[B"); + resolveSystemClass(t, roots(t)->bootLoader(), name, true); + + name = makeByteArray(t, "[Z"); + resolveSystemClass(t, roots(t)->bootLoader(), name, true); + + name = makeByteArray(t, "[S"); + resolveSystemClass(t, roots(t)->bootLoader(), name, true); + + name = makeByteArray(t, "[C"); + resolveSystemClass(t, roots(t)->bootLoader(), name, true); + + name = makeByteArray(t, "[I"); + resolveSystemClass(t, roots(t)->bootLoader(), name, true); + + name = makeByteArray(t, "[J"); + resolveSystemClass(t, roots(t)->bootLoader(), name, true); + + name = makeByteArray(t, "[F"); + resolveSystemClass(t, roots(t)->bootLoader(), name, true); + + name = makeByteArray(t, "[D"); + resolveSystemClass(t, roots(t)->bootLoader(), name, true); + } + } + + target_uintptr_t* heap + = static_cast(t->m->heap->allocate(HeapCapacity)); + + target_uintptr_t* heapMap = static_cast( + t->m->heap->allocate(heapMapSize(HeapCapacity))); + memset(heapMap, 0, heapMapSize(HeapCapacity)); + + HeapWalker* heapWalker = makeHeapImage( + t, image, heap, heapMap, HeapCapacity, constants, typeMaps); + + updateConstants(t, constants, heapWalker->map()); + + image->bootClassCount + = cast(t, roots(t)->bootLoader()->map())->size(); + + unsigned* bootClassTable = static_cast( + t->m->heap->allocate(image->bootClassCount * sizeof(unsigned))); + + { + unsigned i = 0; + for (HashMapIterator it(t, + cast(t, roots(t)->bootLoader()->map())); + it.hasMore();) { + bootClassTable[i++] + = targetVW(heapWalker->map()->find(it.next()->second())); + } + } + + image->appClassCount + = cast(t, roots(t)->appLoader()->map())->size(); + + unsigned* appClassTable = static_cast( + t->m->heap->allocate(image->appClassCount * sizeof(unsigned))); + + { + unsigned i = 0; + for ( + HashMapIterator it(t, cast(t, roots(t)->appLoader()->map())); + it.hasMore();) { + appClassTable[i++] + = targetVW(heapWalker->map()->find(it.next()->second())); + } + } + + image->stringCount = roots(t)->stringMap()->size(); + unsigned* stringTable = static_cast( + t->m->heap->allocate(image->stringCount * sizeof(unsigned))); + + { + unsigned i = 0; + for (HashMapIterator it(t, roots(t)->stringMap()); it.hasMore();) { + stringTable[i++] + = targetVW(heapWalker->map()->find(reinterpret_cast( + cast(t, it.next()->first())->target()))); + } + } + + unsigned* callTable = t->m->processor->makeCallTable(t, heapWalker); + + heapWalker->dispose(); + + image->magic = BootImage::Magic; + image->initialized = 0; + + fprintf(stderr, + "class count %d string count %d call count %d\n" + "heap size %d code size %d\n", + image->bootClassCount, + image->stringCount, + image->callCount, + image->heapSize, + image->codeSize); + + Buffer bootimageData; + + if (true) { + { + BootImage targetImage; + +#ifdef FIELD +#undef FIELD +#endif + +#define FIELD(name) targetImage.name = targetV4(image->name); +#include "bootimage-fields.cpp" +#undef FIELD + +#define THUNK_FIELD(name) \ + targetImage.thunks.name = targetThunk(image->thunks.name); +#include "bootimage-fields.cpp" +#undef THUNK_FIELD + + bootimageData.write(&targetImage, sizeof(BootImage)); + } + + bootimageData.write(bootClassTable, + image->bootClassCount * sizeof(unsigned)); + bootimageData.write(appClassTable, image->appClassCount * sizeof(unsigned)); + bootimageData.write(stringTable, image->stringCount * sizeof(unsigned)); + bootimageData.write(callTable, image->callCount * sizeof(unsigned) * 2); + + unsigned offset = sizeof(BootImage) + + (image->bootClassCount * sizeof(unsigned)) + + (image->appClassCount * sizeof(unsigned)) + + (image->stringCount * sizeof(unsigned)) + + (image->callCount * sizeof(unsigned) * 2); + + while (offset % TargetBytesPerWord) { + uint8_t c = 0; + bootimageData.write(&c, 1); + ++offset; + } + + bootimageData.write(heapMap, + pad(heapMapSize(image->heapSize), TargetBytesPerWord)); + + bootimageData.write(heap, pad(image->heapSize, TargetBytesPerWord)); + + // fwrite(code, pad(image->codeSize, TargetBytesPerWord), 1, codeOutput); + + Platform* platform = Platform::getPlatform( + PlatformInfo((PlatformInfo::Format)AVIAN_TARGET_FORMAT, + (PlatformInfo::Architecture)AVIAN_TARGET_ARCH)); + + if (!platform) { + fprintf(stderr, + "unsupported platform: target-format = %d / target-arch = %d\n", + AVIAN_TARGET_FORMAT, + AVIAN_TARGET_ARCH); + abort(); + } + + uint8_t* bootimage; + size_t bootimageLength; + if (useLZMA) { +#ifdef AVIAN_USE_LZMA + bootimage = encodeLZMA(t->m->system, + t->m->heap, + bootimageData.data, + bootimageData.length, + &bootimageLength); + + fprintf(stderr, "compressed heap size %zu\n", bootimageLength); +#else + abort(t); +#endif + } else { + bootimage = bootimageData.data; + bootimageLength = bootimageData.length; + } + + SymbolInfo bootimageSymbols[] + = {SymbolInfo(0, bootimageStart), + SymbolInfo(bootimageLength, bootimageEnd)}; + + platform->writeObject(bootimageOutput, + Slice(bootimageSymbols, 2), + Slice(bootimage, bootimageLength), + Platform::Writable, + TargetBytesPerWord); + + if (useLZMA) { + t->m->heap->free(bootimage, bootimageLength); + } + + compilationHandler.symbols.add(SymbolInfo(0, codeimageStart)); + compilationHandler.symbols.add(SymbolInfo(image->codeSize, codeimageEnd)); + + platform->writeObject(codeOutput, + Slice(compilationHandler.symbols), + Slice(code, image->codeSize), + Platform::Executable, + TargetBytesPerWord); + + for (SymbolInfo* sym = compilationHandler.symbols.begin(); + sym != compilationHandler.symbols.end() - 2; + sym++) { + t->m->heap->free(const_cast((const void*)sym->name.text), + sym->name.length + 1); + } + } +} + +uint64_t writeBootImage(Thread* t, uintptr_t* arguments) +{ + OutputStream* bootimageOutput = reinterpret_cast(arguments[0]); + OutputStream* codeOutput = reinterpret_cast(arguments[1]); + BootImage* image = reinterpret_cast(arguments[2]); + uint8_t* code = reinterpret_cast(arguments[3]); + JavaVM* hostVM = reinterpret_cast(arguments[4]); + const char* className = reinterpret_cast(arguments[5]); + const char* methodName = reinterpret_cast(arguments[6]); + const char* methodSpec = reinterpret_cast(arguments[7]); + + const char* bootimageStart = reinterpret_cast(arguments[8]); + const char* bootimageEnd = reinterpret_cast(arguments[9]); + const char* codeimageStart = reinterpret_cast(arguments[10]); + const char* codeimageEnd = reinterpret_cast(arguments[11]); + bool useLZMA = arguments[12]; + + writeBootImage2(t, + bootimageOutput, + codeOutput, + image, + code, + hostVM, + className, + methodName, + methodSpec, + bootimageStart, + bootimageEnd, + codeimageStart, + codeimageEnd, + useLZMA); + + return 1; +} + +char* myStrndup(const char* src, unsigned length) +{ + char* s = static_cast(malloc(length + 1)); + memcpy(s, src, length); + s[length] = 0; + return s; +} + +class Arguments { + public: + const char* classpath; + + const char* bootimage; + const char* codeimage; + + const char* hostvm; + + char* entryClass; + char* entryMethod; + char* entrySpec; + + char* bootimageStart; + char* bootimageEnd; + + char* codeimageStart; + char* codeimageEnd; + + bool useLZMA; + + bool maybeSplit(const char* src, char*& destA, char*& destB) + { + if (src) { + const char* split = strchr(src, ':'); + if (!split) { + return false; + } + + destA = myStrndup(src, split - src); + destB = strdup(split + 1); + } + return true; + } + + Arguments(int ac, const char** av) + : entryClass(0), + entryMethod(0), + entrySpec(0), + bootimageStart(0), + bootimageEnd(0), + codeimageStart(0), + codeimageEnd(0) + { + ArgParser parser; + Arg classpath(parser, true, "cp", ""); + Arg bootimage(parser, true, "bootimage", ""); + Arg codeimage(parser, true, "codeimage", ""); + Arg hostvm(parser, false, "hostvm", ""); + Arg entry( + parser, false, "entry", "[.[]]"); + Arg bootimageSymbols(parser, + false, + "bootimage-symbols", + ":"); + Arg codeimageSymbols(parser, + false, + "codeimage-symbols", + ":"); + Arg useLZMA(parser, false, "use-lzma", 0); + + if (!parser.parse(ac, av)) { + parser.printUsage(av[0]); + exit(1); + } + + this->classpath = classpath.value; + this->bootimage = bootimage.value; + this->codeimage = codeimage.value; + this->hostvm = hostvm.value; + this->useLZMA = useLZMA.value != 0; + + if (entry.value) { + if (const char* entryClassEnd = strchr(entry.value, '.')) { + entryClass = myStrndup(entry.value, entryClassEnd - entry.value); + if (const char* entryMethodEnd = strchr(entryClassEnd, '(')) { + entryMethod = myStrndup(entryClassEnd + 1, + entryMethodEnd - entryClassEnd - 1); + entrySpec = strdup(entryMethodEnd); + } else { + entryMethod = strdup(entryClassEnd + 1); + } + } else { + entryClass = strdup(entry.value); + } + } + + if (!maybeSplit(bootimageSymbols.value, bootimageStart, bootimageEnd) + || !maybeSplit(codeimageSymbols.value, codeimageStart, codeimageEnd)) { + fprintf(stderr, "wrong format for symbols\n"); + parser.printUsage(av[0]); + exit(1); + } + + if (!bootimageStart) { + bootimageStart = strdup("_binary_bootimage_bin_start"); + } + + if (!bootimageEnd) { + bootimageEnd = strdup("_binary_bootimage_bin_end"); + } + + if (!codeimageStart) { + codeimageStart = strdup("_binary_codeimage_bin_start"); + } + + if (!codeimageEnd) { + codeimageEnd = strdup("_binary_codeimage_bin_end"); + } + } + + ~Arguments() + { + if (entryClass) { + free(entryClass); + } + if (entryMethod) { + free(entryMethod); + } + if (entrySpec) { + free(entrySpec); + } + if (bootimageStart) { + free(bootimageStart); + } + if (bootimageEnd) { + free(bootimageEnd); + } + if (codeimageStart) { + free(codeimageStart); + } + if (codeimageEnd) { + free(codeimageEnd); + } + } + + void dump() + { + printf( + "classpath = %s\n" + "bootimage = %s\n" + "codeimage = %s\n" + "hostvm = %s\n" + "entryClass = %s\n" + "entryMethod = %s\n" + "entrySpec = %s\n" + "bootimageStart = %s\n" + "bootimageEnd = %s\n" + "codeimageStart = %s\n" + "codeimageEnd = %s\n", + classpath, + bootimage, + codeimage, + hostvm, + entryClass, + entryMethod, + entrySpec, + bootimageStart, + bootimageEnd, + codeimageStart, + codeimageEnd); + } +}; + +} // namespace + +int main(int ac, const char** av) +{ + Arguments args(ac, av); + // args.dump(); + + System* s = makeSystem(); + Heap* h = makeHeap(s, HeapCapacity * 2); + Classpath* c = makeClasspath(s, h, AVIAN_JAVA_HOME, AVIAN_EMBED_PREFIX); + Finder* f = makeFinder(s, h, args.classpath, 0); + Processor* p = makeProcessor(s, h, 0, false); + +// todo: currently, the compiler cannot compile code with jumps or +// calls spanning more than the maximum size of an immediate value +// in a branch instruction for the target architecture (~32MB on ARM). +// When that limitation is removed, we'll be able to specify a +// capacity as large as we like here: +#if (AVIAN_TARGET_ARCH == AVIAN_ARCH_X86_64) \ + || (AVIAN_TARGET_ARCH == AVIAN_ARCH_X86) + const unsigned CodeCapacity = 128 * 1024 * 1024; +#else + const unsigned CodeCapacity = 30 * 1024 * 1024; +#endif + + Slice code = Slice::alloc(h, CodeCapacity); + BootImage image; + p->initialize(&image, code); + + Machine* m = new (h->allocate(sizeof(Machine))) + Machine(s, h, f, 0, p, c, 0, 0, 0, 0, 128 * 1024); + Thread* t = p->makeThread(m, 0, 0); + + enter(t, Thread::ActiveState); + enter(t, Thread::IdleState); + + FileOutputStream bootimageOutput(args.bootimage); + if (!bootimageOutput.isValid()) { + fprintf(stderr, "unable to open %s\n", args.bootimage); + return -1; + } + + FileOutputStream codeOutput(args.codeimage); + if (!codeOutput.isValid()) { + fprintf(stderr, "unable to open %s\n", args.codeimage); + return -1; + } + + JavaVM* hostVM = 0; + System::Library* hostVMLibrary = 0; + if (args.hostvm) { + if (s->success(s->load(&hostVMLibrary, args.hostvm))) { + typedef jint(JNICALL * CreateVM)(Machine**, Thread**, void*); + const char* name = "JNI_CreateJavaVM"; + CreateVM createVM + = reinterpret_cast(hostVMLibrary->resolve(name)); + + if (createVM) { + JavaVMInitArgs vmArgs; + vmArgs.version = JNI_VERSION_1_6; + vmArgs.nOptions = 2; + vmArgs.ignoreUnrecognized = JNI_TRUE; + +#define CLASSPATH_PROPERTY "-Xbootclasspath:" + + const char* classpath = args.classpath; + size_t classpathSize = strlen(classpath); + size_t classpathPropertyBufferSize = sizeof(CLASSPATH_PROPERTY) + + classpathSize; + + RUNTIME_ARRAY( + char, classpathPropertyBuffer, classpathPropertyBufferSize); + memcpy(RUNTIME_ARRAY_BODY(classpathPropertyBuffer), + CLASSPATH_PROPERTY, + sizeof(CLASSPATH_PROPERTY) - 1); + memcpy(RUNTIME_ARRAY_BODY(classpathPropertyBuffer) + + sizeof(CLASSPATH_PROPERTY) - 1, + classpath, + classpathSize + 1); + + JavaVMOption options[2]; + options[0].optionString = RUNTIME_ARRAY_BODY(classpathPropertyBuffer); + options[1].optionString = const_cast("-Davian.reentrant=true"); + + vmArgs.options = options; + + Thread* dummy; + if (JNI_OK != createVM(&hostVM, &dummy, &vmArgs)) { + fprintf(stderr, "unable to initialize host VM\n"); + hostVMLibrary->disposeAll(); + return -1; + } + } else { + fprintf(stderr, "unable to find %s in %s\n", name, args.hostvm); + hostVMLibrary->disposeAll(); + return -1; + } + } else { + fprintf(stderr, "unable to open %s\n", args.hostvm); + return -1; + } + } + + uintptr_t arguments[] = {reinterpret_cast(&bootimageOutput), + reinterpret_cast(&codeOutput), + reinterpret_cast(&image), + reinterpret_cast(code.begin()), + reinterpret_cast(hostVM), + reinterpret_cast(args.entryClass), + reinterpret_cast(args.entryMethod), + reinterpret_cast(args.entrySpec), + reinterpret_cast(args.bootimageStart), + reinterpret_cast(args.bootimageEnd), + reinterpret_cast(args.codeimageStart), + reinterpret_cast(args.codeimageEnd), + static_cast(args.useLZMA)}; + + run(t, writeBootImage, arguments); + + if (hostVM) { + hostVM->vtable->DestroyJavaVM(hostVM); + hostVMLibrary->disposeAll(); + } + + if (t->exception) { + printTrace(t, t->exception); + return -1; + } else { + return 0; + } +} diff --git a/sgx-jvm/avian/src/tools/object-writer/CMakeLists.txt b/sgx-jvm/avian/src/tools/object-writer/CMakeLists.txt new file mode 100644 index 0000000000..1437bf1d67 --- /dev/null +++ b/sgx-jvm/avian/src/tools/object-writer/CMakeLists.txt @@ -0,0 +1,6 @@ +add_library(object_writer + elf.cpp + mach-o.cpp + pe.cpp + tools.cpp +) \ No newline at end of file diff --git a/sgx-jvm/avian/src/tools/object-writer/elf.cpp b/sgx-jvm/avian/src/tools/object-writer/elf.cpp new file mode 100644 index 0000000000..a54690d10c --- /dev/null +++ b/sgx-jvm/avian/src/tools/object-writer/elf.cpp @@ -0,0 +1,407 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#include +#include +#include +#include + +#include "endianness.h" + +#include + +#define EI_NIDENT 16 + +#define EI_MAG0 0 +#define EI_MAG1 1 +#define EI_MAG2 2 +#define EI_MAG3 3 +#define EI_CLASS 4 +#define EI_DATA 5 +#define EI_VERSION 6 +#define EI_OSABI 7 +#define EI_ABIVERSION 8 + +#define ELFMAG0 0x7f +#define ELFMAG1 'E' +#define ELFMAG2 'L' +#define ELFMAG3 'F' + +#define ELFCLASS64 2 +#define ELFCLASS32 1 + +#define EV_CURRENT 1 + +#define ELFDATA2LSB 1 +#define ELFDATA2MSB 2 + +#define ELFOSABI_SYSV 0 + +#define ET_REL 1 + +#define EM_386 3 +#define EM_X86_64 62 +#define EM_ARM 40 +#define EM_AARCH64 183 + +#define SHT_PROGBITS 1 +#define SHT_SYMTAB 2 +#define SHT_STRTAB 3 + +#define SHF_WRITE (1 << 0) +#define SHF_ALLOC (1 << 1) +#define SHF_EXECINSTR (1 << 2) + +#define STB_GLOBAL 1 + +#define STT_NOTYPE 0 + +#define STV_DEFAULT 0 + +#define SYMBOL_INFO(bind, type) (((bind) << 4) + ((type)&0xf)) + +#define OSABI ELFOSABI_SYSV + +namespace { + +using namespace avian::tools; +using namespace avian::util; + +template +struct ElfTypes { + typedef uint16_t Half; + typedef uint32_t Word; + typedef AddrTy Addr; + typedef uint64_t Xword; + typedef uint16_t Section; + typedef AddrTy Off; + typedef AddrTy XFlags; + static const unsigned BytesPerWord = sizeof(AddrTy); +}; + +template +struct Symbol_Ty; + +template <> +struct Symbol_Ty { + typedef ElfTypes Elf; + + Elf::Word st_name; + unsigned char st_info; + unsigned char st_other; + Elf::Section st_shndx; + Elf::Addr st_value; + Elf::Xword st_size; +}; + +template <> +struct Symbol_Ty { + typedef ElfTypes Elf; + + Elf::Word st_name; + Elf::Addr st_value; + Elf::Word st_size; + unsigned char st_info; + unsigned char st_other; + Elf::Section st_shndx; +}; + +using avian::endian::Endianness; + +#define V1 Endianness::v1 +#define V2 Endianness::v2 +#define V3 Endianness::v3 +#define V4 Endianness::v4 +#define VANY Endianness::vAny + +unsigned getElfPlatform(PlatformInfo::Architecture arch) +{ + switch (arch) { + case PlatformInfo::x86_64: + return EM_X86_64; + case PlatformInfo::x86: + return EM_386; + case PlatformInfo::Arm: + return EM_ARM; + case PlatformInfo::Arm64: + return EM_AARCH64; + default: + return ~0; + } +} + +const char* getSectionName(unsigned accessFlags, unsigned& sectionFlags) +{ + sectionFlags = SHF_ALLOC; + if (accessFlags & Platform::Writable) { + if (accessFlags & Platform::Executable) { + sectionFlags |= SHF_WRITE | SHF_EXECINSTR; + return ".rwx"; + } else { + sectionFlags |= SHF_WRITE; + return ".data"; + } + } else if (accessFlags & Platform::Executable) { + sectionFlags |= SHF_EXECINSTR; + return ".text"; + } else { + return ".rodata"; + } +} + +template +class ElfPlatform : public Platform { + public: + typedef ElfTypes Elf; + static const unsigned Class = Elf::BytesPerWord / 4; + + struct FileHeader { + unsigned char e_ident[EI_NIDENT]; + typename Elf::Half e_type; + typename Elf::Half e_machine; + typename Elf::Word e_version; + typename Elf::Addr e_entry; + typename Elf::Off e_phoff; + typename Elf::Off e_shoff; + typename Elf::Word e_flags; + typename Elf::Half e_ehsize; + typename Elf::Half e_phentsize; + typename Elf::Half e_phnum; + typename Elf::Half e_shentsize; + typename Elf::Half e_shnum; + typename Elf::Half e_shstrndx; + }; + + struct SectionHeader { + typename Elf::Word sh_name; + typename Elf::Word sh_type; + typename Elf::XFlags sh_flags; + typename Elf::Addr sh_addr; + typename Elf::Off sh_offset; + typename Elf::Off sh_size; + typename Elf::Word sh_link; + typename Elf::Word sh_info; + typename Elf::Addr sh_addralign; + typename Elf::Off sh_entsize; + }; + + typedef Symbol_Ty Symbol; + + static const unsigned Encoding = TargetLittleEndian ? ELFDATA2LSB + : ELFDATA2MSB; + + const unsigned machine; + + ElfPlatform(PlatformInfo::Architecture arch) + : Platform(PlatformInfo(PlatformInfo::Elf, arch)), + machine(getElfPlatform(arch)) + { + } + + class FileWriter { + public: + unsigned sectionCount; + unsigned sectionStringTableSectionNumber; + + AddrTy dataOffset; + + FileHeader header; + StringTable strings; + + FileWriter(unsigned machine) + : sectionCount(0), dataOffset(sizeof(FileHeader)) + { + memset(&header, 0, sizeof(FileHeader)); + header.e_ident[EI_MAG0] = V1(ELFMAG0); + header.e_ident[EI_MAG1] = V1(ELFMAG1); + header.e_ident[EI_MAG2] = V1(ELFMAG2); + header.e_ident[EI_MAG3] = V1(ELFMAG3); + header.e_ident[EI_CLASS] = V1(Class); + header.e_ident[EI_DATA] = V1(Encoding); + header.e_ident[EI_VERSION] = V1(EV_CURRENT); + header.e_ident[EI_OSABI] = V1(OSABI); + header.e_ident[EI_ABIVERSION] = V1(0); + header.e_type = V2(ET_REL); + header.e_machine = V2(machine); + header.e_version = V4(EV_CURRENT); + header.e_entry = VANY(static_cast(0)); + header.e_phoff = VANY(static_cast(0)); + header.e_shoff = VANY(static_cast(sizeof(FileHeader))); + header.e_flags = V4(machine == EM_ARM ? 0x04000000 : 0); + header.e_ehsize = V2(sizeof(FileHeader)); + header.e_phentsize = V2(0); + header.e_phnum = V2(0); + header.e_shentsize = V2(sizeof(SectionHeader)); + } + + void writeHeader(OutputStream* out) + { + header.e_shnum = V2(sectionCount); + header.e_shstrndx = V2(sectionStringTableSectionNumber); + out->writeChunk(&header, sizeof(FileHeader)); + } + }; + + class SectionWriter { + public: + FileWriter& file; + String name; + SectionHeader header; + const size_t* dataSize; + const uint8_t* const* data; + + SectionWriter(FileWriter& file) : file(file), name(""), dataSize(0), data(0) + { + memset(&header, 0, sizeof(SectionHeader)); + file.sectionCount++; + file.dataOffset += sizeof(SectionHeader); + size_t nameOffset = file.strings.add(name); + header.sh_name = V4(nameOffset); + } + + SectionWriter(FileWriter& file, + const char* chname, + unsigned type, + AddrTy flags, + unsigned alignment, + AddrTy addr, + const uint8_t* const* data, + size_t* dataSize, + size_t entsize = 0, + unsigned link = 0) + : file(file), name(chname), dataSize(dataSize), data(data) + { + if (strcmp(chname, ".shstrtab") == 0) { + file.sectionStringTableSectionNumber = file.sectionCount; + } + file.sectionCount++; + file.dataOffset += sizeof(SectionHeader); + size_t nameOffset = file.strings.add(name); + + header.sh_name = V4(nameOffset); + header.sh_type = V4(type); + header.sh_flags = VANY(flags); + header.sh_addr = VANY(addr); + // header.sh_offset = VANY(static_cast(bodySectionOffset)); + // header.sh_size = VANY(static_cast(*dataSize)); + header.sh_link = V4(link); + header.sh_info = V4(0); + header.sh_addralign = VANY(static_cast(alignment)); + header.sh_entsize = VANY(static_cast(entsize)); + } + + void writeHeader(OutputStream* out) + { + if (dataSize) { + header.sh_offset = VANY(file.dataOffset); + header.sh_size = VANY(static_cast(*dataSize)); + file.dataOffset += *dataSize; + } + + out->writeChunk(&header, sizeof(SectionHeader)); + } + + void writeData(OutputStream* out) + { + if (data) { + out->writeChunk(*data, *dataSize); + } + } + }; + + virtual bool writeObject(OutputStream* out, + Slice symbols, + Slice data, + unsigned accessFlags, + unsigned alignment) + { + unsigned sectionFlags; + const char* sectionName = getSectionName(accessFlags, sectionFlags); + + StringTable symbolStringTable; + Buffer symbolTable; + + FileWriter file(machine); + + const int bodySectionNumber = 1; + const int stringTableSectionNumber = 3; + + SectionWriter sections[] = {SectionWriter(file), // null section + SectionWriter(file, + sectionName, + SHT_PROGBITS, + sectionFlags, + alignment, + 0, + &data.items, + &data.count), // body section + SectionWriter(file, + ".shstrtab", + SHT_STRTAB, + 0, + 1, + 0, + &file.strings.data, + &file.strings.length), + SectionWriter(file, + ".strtab", + SHT_STRTAB, + 0, + 1, + 0, + &symbolStringTable.data, + &symbolStringTable.length), + SectionWriter(file, + ".symtab", + SHT_SYMTAB, + 0, + 8, + 0, + &symbolTable.data, + &symbolTable.length, + sizeof(Symbol), + stringTableSectionNumber)}; + + // for some reason, string tables require a null first element... + symbolStringTable.add(""); + + for (SymbolInfo* sym = symbols.begin(); sym != symbols.end(); sym++) { + size_t nameOffset = symbolStringTable.add(sym->name); + + Symbol symbolStruct; + symbolStruct.st_name = V4(nameOffset); + symbolStruct.st_value = VANY(static_cast(sym->addr)); + symbolStruct.st_size = VANY(static_cast(0)); + symbolStruct.st_info = V1(SYMBOL_INFO(STB_GLOBAL, STT_NOTYPE)); + symbolStruct.st_other = V1(STV_DEFAULT); + symbolStruct.st_shndx = V2(bodySectionNumber); + symbolTable.write(&symbolStruct, sizeof(Symbol)); + } + + file.writeHeader(out); + + for (unsigned i = 0; i < file.sectionCount; i++) { + sections[i].writeHeader(out); + } + + for (unsigned i = 0; i < file.sectionCount; i++) { + sections[i].writeData(out); + } + + return true; + } +}; + +ElfPlatform elfX86Platform(PlatformInfo::x86); +ElfPlatform elfArmPlatform(PlatformInfo::Arm); +ElfPlatform elfArm64Platform(PlatformInfo::Arm64); +ElfPlatform elfX86_64Platform(PlatformInfo::x86_64); + +} // namespace diff --git a/sgx-jvm/avian/src/tools/object-writer/endianness.h b/sgx-jvm/avian/src/tools/object-writer/endianness.h new file mode 100644 index 0000000000..f29c90bf24 --- /dev/null +++ b/sgx-jvm/avian/src/tools/object-writer/endianness.h @@ -0,0 +1,90 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#ifndef AVIAN_ENDIANNESS_H +#define AVIAN_ENDIANNESS_H + +namespace avian { + +namespace endian { + +static union { + uint32_t i; + char c[4]; +} _DetectEndianness = {1}; + +const bool LittleEndian = _DetectEndianness.c[0] == 1; + +template +class Endianness { + public: + static inline uint8_t v1(uint8_t v) + { + return v; + } + + static inline uint16_t v2(uint16_t v) + { + if (LittleEndian == TargetLittleEndian) { + return v; + } else { + return ((v >> 8) & 0xFF) | (v << 8); + } + } + + static inline uint32_t v4(uint32_t v) + { + if (LittleEndian == TargetLittleEndian) { + return v; + } else { + return ((v >> 24) & 0x000000FF) | ((v >> 8) & 0x0000FF00) + | ((v << 8) & 0x00FF0000) | ((v << 24)); + } + } + + static inline uint32_t vAny(uint32_t v) + { + return v4(v); + } + + static inline uint64_t v8(uint64_t v) + { + if (LittleEndian == TargetLittleEndian) { + return v; + } else { + return ((static_cast(v) >> 56) + & (static_cast(0xff) << 0)) + | ((static_cast(v) >> 40) + & (static_cast(0xff) << 8)) + | ((static_cast(v) >> 24) + & (static_cast(0xff) << 16)) + | ((static_cast(v) >> 8) + & (static_cast(0xff) << 24)) + | ((static_cast(v) << 8) + & (static_cast(0xff) << 32)) + | ((static_cast(v) << 24) + & (static_cast(0xff) << 40)) + | ((static_cast(v) << 40) + & (static_cast(0xff) << 48)) + | ((static_cast(v) << 56)); + } + } + + static inline uint64_t vAny(uint64_t v) + { + return v8(v); + } +}; + +} // namespace endian + +} // namespace avian + +#endif // AVIAN_ENDIANNESS_H diff --git a/sgx-jvm/avian/src/tools/object-writer/mach-o.cpp b/sgx-jvm/avian/src/tools/object-writer/mach-o.cpp new file mode 100644 index 0000000000..85f713ba23 --- /dev/null +++ b/sgx-jvm/avian/src/tools/object-writer/mach-o.cpp @@ -0,0 +1,292 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#include +#include +#include + +#include "endianness.h" + +#include + +#define MH_MAGIC_64 0xfeedfacf +#define MH_MAGIC 0xfeedface + +#define MH_OBJECT 1 + +#define LC_SYMTAB 2 + +#define S_REGULAR 0 + +#define N_SECT 0xe +#define N_EXT 0x1 + +#define CPU_ARCH_ABI64 0x01000000 + +#define CPU_TYPE_I386 7 +#define CPU_TYPE_X86_64 (CPU_TYPE_I386 | CPU_ARCH_ABI64) +#define CPU_TYPE_ARM 12 +#define CPU_TYPE_ARM64 (CPU_TYPE_ARM | CPU_ARCH_ABI64) + +#define CPU_SUBTYPE_I386_ALL 3 +#define CPU_SUBTYPE_X86_64_ALL CPU_SUBTYPE_I386_ALL +#define CPU_SUBTYPE_ARM_V7 9 +#define CPU_SUBTYPE_ARM_V8 13 + +namespace { + +using namespace avian::tools; +using namespace avian::util; + +typedef int cpu_type_t; +typedef int cpu_subtype_t; +typedef int vm_prot_t; + +using avian::endian::Endianness; + +#define V1 Endianness::v1 +#define V2 Endianness::v2 +#define V3 Endianness::v3 +#define V4 Endianness::v4 +#define VANY Endianness::vAny + +inline unsigned log(unsigned n) +{ + unsigned r = 0; + for (unsigned i = 1; i < n; ++r) + i <<= 1; + return r; +} + +template +class MachOPlatform : public Platform { + public: + struct FileHeader { + uint32_t magic; + cpu_type_t cputype; + cpu_subtype_t cpusubtype; + uint32_t filetype; + uint32_t ncmds; + uint32_t sizeofcmds; + + union { + uint32_t flags; + AddrTy flagsAndMaybeReserved; + }; + }; + + struct SegmentCommand { + uint32_t cmd; + uint32_t cmdsize; + char segname[16]; + AddrTy vmaddr; + AddrTy vmsize; + AddrTy fileoff; + AddrTy filesize; + vm_prot_t maxprot; + vm_prot_t initprot; + uint32_t nsects; + uint32_t flags; + }; + + struct Section { + char sectname[16]; + char segname[16]; + AddrTy addr; + AddrTy size; + uint32_t offset; + uint32_t align; + uint32_t reloff; + uint32_t nreloc; + uint32_t flags; + uint32_t reserved1; + AddrTy reserved2AndMaybe3; + }; + + struct NList { + union { + uint32_t n_strx; + } n_un; + uint8_t n_type; + uint8_t n_sect; + uint16_t n_desc; + AddrTy n_value; + }; + + struct SymtabCommand { + uint32_t cmd; + uint32_t cmdsize; + uint32_t symoff; + uint32_t nsyms; + uint32_t stroff; + uint32_t strsize; + }; + + static const unsigned BytesPerWord = sizeof(AddrTy); + static const unsigned Segment = BytesPerWord == 8 ? 0x19 : 1; + static const unsigned Magic = BytesPerWord == 8 ? 0xfeedfacf : 0xfeedface; + + static inline unsigned pad(unsigned n) + { + return (n + (BytesPerWord - 1)) & ~(BytesPerWord - 1); + } + + virtual bool writeObject(OutputStream* out, + Slice symbols, + Slice data, + unsigned accessFlags, + unsigned alignment) + { + cpu_type_t cpuType; + cpu_subtype_t cpuSubType; + switch (info.arch) { + case PlatformInfo::x86_64: + cpuType = CPU_TYPE_X86_64; + cpuSubType = CPU_SUBTYPE_X86_64_ALL; + break; + case PlatformInfo::x86: + cpuType = CPU_TYPE_I386; + cpuSubType = CPU_SUBTYPE_I386_ALL; + break; + case PlatformInfo::Arm: + cpuType = CPU_TYPE_ARM; + cpuSubType = CPU_SUBTYPE_ARM_V7; + break; + case PlatformInfo::Arm64: + cpuType = CPU_TYPE_ARM64; + cpuSubType = CPU_SUBTYPE_ARM_V8; + break; + default: + // should never happen (see MachOPlatform declarations at bottom) + fprintf(stderr, "unsupported architecture: %d\n", info.arch); + return false; + } + + const char* segmentName; + const char* sectionName; + if (accessFlags & Writable) { + if (accessFlags & Executable) { + segmentName = "__RWX"; + sectionName = "__rwx"; + } else { + segmentName = "__DATA"; + sectionName = "__data"; + } + } else { + segmentName = "__TEXT"; + sectionName = "__text"; + } + + FileHeader header = { + V4(Magic), // magic + static_cast(V4(cpuType)), + static_cast(V4(cpuSubType)), + V4(MH_OBJECT), // filetype, + V4(2), // ncmds + V4(sizeof(SegmentCommand) + sizeof(Section) + + sizeof(SymtabCommand)), // sizeofcmds + {V4(0)} // flags + }; + + AddrTy finalSize = pad(data.count); + + SegmentCommand segment = { + V4(Segment), // cmd + V4(sizeof(SegmentCommand) + sizeof(Section)), // cmdsize + "", // segname + VANY(static_cast(0)), // vmaddr + VANY(static_cast(finalSize)), // vmsize + VANY(static_cast(sizeof(FileHeader) + sizeof(SegmentCommand) + + sizeof(Section) + + sizeof(SymtabCommand))), // fileoff + VANY(static_cast(finalSize)), // filesize + static_cast(V4(7)), // maxprot + static_cast(V4(7)), // initprot + V4(1), // nsects + V4(0) // flags + }; + + strncpy(segment.segname, segmentName, sizeof(segment.segname)); + + Section sect = { + "", // sectname + "", // segname + VANY(static_cast(0)), // addr + VANY(static_cast(finalSize)), // size + V4(sizeof(FileHeader) + sizeof(SegmentCommand) + sizeof(Section) + + sizeof(SymtabCommand)), // offset + V4(log(alignment)), // align + V4(0), // reloff + V4(0), // nreloc + V4(S_REGULAR), // flags + V4(0), // reserved1 + V4(0), // reserved2 + }; + + strncpy(sect.segname, segmentName, sizeof(sect.segname)); + strncpy(sect.sectname, sectionName, sizeof(sect.sectname)); + + StringTable strings; + strings.add(""); + Buffer symbolList; + + for (SymbolInfo* sym = symbols.begin(); sym != symbols.end(); sym++) { + unsigned offset = strings.length; + strings.write("_", 1); + strings.add(sym->name); + NList symbol = { + {V4(offset)}, // n_un + V1(N_SECT | N_EXT), // n_type + V1(1), // n_sect + V2(0), // n_desc + VANY(static_cast(sym->addr)) // n_value + }; + symbolList.write(&symbol, sizeof(NList)); + } + + SymtabCommand symbolTable = { + V4(LC_SYMTAB), // cmd + V4(sizeof(SymtabCommand)), // cmdsize + V4(sizeof(FileHeader) + sizeof(SegmentCommand) + sizeof(Section) + + sizeof(SymtabCommand) + finalSize), // symoff + V4(symbols.count), // nsyms + V4(sizeof(FileHeader) + sizeof(SegmentCommand) + sizeof(Section) + + sizeof(SymtabCommand) + finalSize + + (sizeof(NList) * symbols.count)), // stroff + V4(strings.length), // strsize + }; + + out->writeChunk(&header, sizeof(header)); + out->writeChunk(&segment, sizeof(segment)); + out->writeChunk(§, sizeof(sect)); + out->writeChunk(&symbolTable, sizeof(symbolTable)); + + out->writeChunk(data.items, data.count); + out->writeRepeat(0, finalSize - data.count); + + out->writeChunk(symbolList.data, symbolList.length); + + out->writeChunk(strings.data, strings.length); + + return true; + } + + MachOPlatform(PlatformInfo::Architecture arch) + : Platform(PlatformInfo(PlatformInfo::MachO, arch)) + { + } +}; + +MachOPlatform darwinx86Platform(PlatformInfo::x86); +MachOPlatform darwinArmPlatform(PlatformInfo::Arm); +MachOPlatform darwinArm64Platform(PlatformInfo::Arm64); +MachOPlatform darwinx86_64Platform(PlatformInfo::x86_64); + +} // namespace diff --git a/sgx-jvm/avian/src/tools/object-writer/pe.cpp b/sgx-jvm/avian/src/tools/object-writer/pe.cpp new file mode 100644 index 0000000000..22888f1ecb --- /dev/null +++ b/sgx-jvm/avian/src/tools/object-writer/pe.cpp @@ -0,0 +1,299 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#include +#include +#include +#include + +#include + +namespace { + +// --- winnt.h ---- +#define IMAGE_SIZEOF_SHORT_NAME 8 + +#define IMAGE_FILE_RELOCS_STRIPPED \ + 0x0001 // Relocation info stripped from file. +#define IMAGE_FILE_LINE_NUMS_STRIPPED \ + 0x0004 // Line nunbers stripped from file. +#define IMAGE_FILE_MACHINE_AMD64 0x8664 // AMD64 (K8) +#define IMAGE_FILE_MACHINE_I386 0x014c // Intel 386. +#define IMAGE_FILE_MACHINE_ARM 0x01c0 // ARM Little-Endian +#define IMAGE_FILE_MACHINE_THUMB 0x01c2 // ARM Thumb/Thumb-2 Little-Endian +#define IMAGE_FILE_MACHINE_ARMNT 0x01c4 // ARM Thumb-2 Little-Endian +#define IMAGE_FILE_32BIT_MACHINE 0x0100 // 32 bit word machine. + +#define IMAGE_SCN_ALIGN_1BYTES 0x100000 +#define IMAGE_SCN_ALIGN_2BYTES 0x200000 +#define IMAGE_SCN_ALIGN_4BYTES 0x300000 +#define IMAGE_SCN_ALIGN_8BYTES 0x400000 +#define IMAGE_SCN_MEM_EXECUTE 0x20000000 +#define IMAGE_SCN_MEM_READ 0x40000000 +#define IMAGE_SCN_MEM_WRITE 0x80000000 +#define IMAGE_SCN_CNT_CODE 32 + +#ifdef _MSC_VER +#define PACKED_STRUCT _declspec(align(1)) +#else +#define PACKED_STRUCT __attribute__((packed)) +#endif + +struct IMAGE_FILE_HEADER { + uint16_t Machine; + uint16_t NumberOfSections; + uint32_t TimeDateStamp; + uint32_t PointerToSymbolTable; + uint32_t NumberOfSymbols; + uint16_t SizeOfOptionalHeader; + uint16_t Characteristics; +} PACKED_STRUCT; + +struct IMAGE_SECTION_HEADER { + uint8_t Name[IMAGE_SIZEOF_SHORT_NAME]; + union { + uint32_t PhysicalAddress; + uint32_t VirtualSize; + } Misc; + uint32_t VirtualAddress; + uint32_t SizeOfRawData; + uint32_t PointerToRawData; + uint32_t PointerToRelocations; + uint32_t PointerToLinenumbers; + uint16_t NumberOfRelocations; + uint16_t NumberOfLinenumbers; + uint32_t Characteristics; +} PACKED_STRUCT; + +struct IMAGE_SYMBOL { + union { + struct { + uint32_t Short; + uint32_t Long; + } Name; + } N; + uint32_t Value; + int16_t SectionNumber; + uint16_t Type; + uint8_t StorageClass; + uint8_t NumberOfAuxSymbols; +} PACKED_STRUCT; +// --- winnt.h ---- + +inline unsigned pad(unsigned n) +{ + return (n + (4 - 1)) & ~(4 - 1); +} + +using namespace avian::tools; +using namespace avian::util; + +template +class WindowsPlatform : public Platform { + public: + class FileWriter { + public: + unsigned sectionCount; + unsigned symbolCount; + unsigned dataStart; + unsigned dataOffset; + + IMAGE_FILE_HEADER header; + + StringTable strings; + Buffer symbols; + + FileWriter(unsigned machine, unsigned machineMask, unsigned symbolCount) + : sectionCount(0), + symbolCount(symbolCount), + dataStart(sizeof(IMAGE_FILE_HEADER)), + dataOffset(0) + { + header.Machine = machine; + // header.NumberOfSections = sectionCount; + header.TimeDateStamp = 0; + // header.PointerToSymbolTable = sizeof(IMAGE_FILE_HEADER) + // + sizeof(IMAGE_SECTION_HEADER) + // + pad(size); + // header.NumberOfSymbols = symbolCount; + header.SizeOfOptionalHeader = 0; + header.Characteristics = IMAGE_FILE_RELOCS_STRIPPED + | IMAGE_FILE_LINE_NUMS_STRIPPED | machineMask; + } + + void writeHeader(OutputStream* out) + { + header.NumberOfSections = sectionCount; + header.PointerToSymbolTable = dataStart + dataOffset; + dataOffset = pad(dataOffset + symbolCount * sizeof(IMAGE_SYMBOL)); + header.NumberOfSymbols = symbolCount; + out->writeChunk(&header, sizeof(IMAGE_FILE_HEADER)); + } + + void addSymbol(String name, + unsigned addr, + unsigned sectionNumber, + unsigned type, + unsigned storageClass) + { + unsigned nameOffset = strings.add(name); + IMAGE_SYMBOL symbol = { + {{0, 0}}, // Name + addr, // Value + static_cast(sectionNumber), // SectionNumber + static_cast(type), // Type + static_cast(storageClass), // StorageClass + 0, // NumberOfAuxSymbols + }; + symbol.N.Name.Long = nameOffset + 4; + symbols.write(&symbol, sizeof(IMAGE_SYMBOL)); + } + + void writeData(OutputStream* out) + { + out->writeChunk(symbols.data, symbols.length); + uint32_t size = strings.length + 4; + out->writeChunk(&size, 4); + out->writeChunk(strings.data, strings.length); + } + }; + + class SectionWriter { + public: + FileWriter& file; + IMAGE_SECTION_HEADER header; + size_t dataSize; + size_t finalSize; + const uint8_t* data; + unsigned dataOffset; + + SectionWriter(FileWriter& file, + const char* name, + unsigned sectionMask, + const uint8_t* data, + size_t dataSize) + : file(file), dataSize(dataSize), finalSize(pad(dataSize)), data(data) + { + file.sectionCount++; + file.dataStart += sizeof(IMAGE_SECTION_HEADER); + strcpy(reinterpret_cast(header.Name), name); + header.Misc.VirtualSize = 0; + header.SizeOfRawData = finalSize; + // header.PointerToRawData = file.dataOffset; + dataOffset = file.dataOffset; + file.dataOffset += finalSize; + header.PointerToRelocations = 0; + header.PointerToLinenumbers = 0; + header.NumberOfRelocations = 0; + header.NumberOfLinenumbers = 0; + header.Characteristics = sectionMask; + } + + void writeHeader(OutputStream* out) + { + header.PointerToRawData = dataOffset + file.dataStart; + out->writeChunk(&header, sizeof(IMAGE_SECTION_HEADER)); + } + + void writeData(OutputStream* out) + { + out->writeChunk(data, dataSize); + out->writeRepeat(0, finalSize - dataSize); + } + }; + + virtual bool writeObject(OutputStream* out, + Slice symbols, + Slice data, + unsigned accessFlags, + unsigned alignment) + { + int machine; + int machineMask; + + if (Architecture == PlatformInfo::x86_64) { + machine = IMAGE_FILE_MACHINE_AMD64; + machineMask = 0; + } else if (Architecture == PlatformInfo::x86) { + machine = IMAGE_FILE_MACHINE_I386; + machineMask = IMAGE_FILE_32BIT_MACHINE; + } else if (Architecture == PlatformInfo::Arm) { + machine = IMAGE_FILE_MACHINE_ARMNT; + machineMask = IMAGE_FILE_32BIT_MACHINE; + } + + int sectionMask; + switch (alignment) { + case 0: + case 1: + sectionMask = IMAGE_SCN_ALIGN_1BYTES; + break; + case 2: + sectionMask = IMAGE_SCN_ALIGN_2BYTES; + break; + case 4: + sectionMask = IMAGE_SCN_ALIGN_4BYTES; + break; + case 8: + sectionMask = IMAGE_SCN_ALIGN_8BYTES; + break; + default: + fprintf(stderr, "unsupported alignment: %d\n", alignment); + return false; + } + + sectionMask |= IMAGE_SCN_MEM_READ; + + const char* sectionName; + if (accessFlags & Platform::Writable) { + if (accessFlags & Platform::Executable) { + sectionName = ".rwx"; + sectionMask |= IMAGE_SCN_MEM_WRITE | IMAGE_SCN_MEM_EXECUTE + | IMAGE_SCN_CNT_CODE; + } else { + sectionName = ".data"; + sectionMask |= IMAGE_SCN_MEM_WRITE; + } + } else { + sectionName = ".text"; + sectionMask |= IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_CNT_CODE; + } + + FileWriter file(machine, machineMask, symbols.count); + + SectionWriter section( + file, sectionName, sectionMask, data.items, data.count); + + file.writeHeader(out); + + for (SymbolInfo* sym = symbols.begin(); sym != symbols.end(); sym++) { + file.addSymbol(sym->name, sym->addr, 1, 0, 2); + } + + section.writeHeader(out); + + section.writeData(out); + + file.writeData(out); + + return true; + } + + WindowsPlatform() : Platform(PlatformInfo(PlatformInfo::Pe, Architecture)) + { + } +}; + +WindowsPlatform<4, PlatformInfo::x86> windows32Platform; +WindowsPlatform<8, PlatformInfo::x86_64> windows64Platform; +WindowsPlatform<4, PlatformInfo::Arm> + windowsRtPlatform; // Windows Phone 8 and Windows RT + +} // namespace diff --git a/sgx-jvm/avian/src/tools/object-writer/tools.cpp b/sgx-jvm/avian/src/tools/object-writer/tools.cpp new file mode 100644 index 0000000000..138cc5e122 --- /dev/null +++ b/sgx-jvm/avian/src/tools/object-writer/tools.cpp @@ -0,0 +1,137 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#include +#include +#include +#include + +#include + +using namespace avian::util; + +namespace avian { + +namespace tools { + +Buffer::Buffer() : capacity(100), length(0), data((uint8_t*)malloc(capacity)) +{ +} + +Buffer::~Buffer() +{ + free(data); +} + +void Buffer::ensure(size_t more) +{ + if (length + more > capacity) { + capacity = capacity * 2 + more; + data = (uint8_t*)realloc(data, capacity); + } +} + +void Buffer::write(const void* d, size_t size) +{ + ensure(size); + memcpy(data + length, d, size); + length += size; +} + +unsigned StringTable::add(String str) +{ + unsigned offset = Buffer::length; + Buffer::write(str.text, str.length + 1); + return offset; +} + +void OutputStream::write(uint8_t byte) +{ + writeChunk(&byte, 1); +} + +void OutputStream::writeRepeat(uint8_t byte, size_t size) +{ + for (size_t i = 0; i < size; i++) { + write(byte); + } +} + +FileOutputStream::FileOutputStream(const char* name) : file(fopen(name, "wb")) +{ +} + +FileOutputStream::~FileOutputStream() +{ + if (file) { + fclose(file); + } +} + +bool FileOutputStream::isValid() +{ + return file; +} + +void FileOutputStream::writeChunk(const void* data, size_t size) +{ + fwrite(data, size, 1, file); +} + +void FileOutputStream::write(uint8_t byte) +{ + fputc(byte, file); +} + +Platform* Platform::first = 0; + +PlatformInfo::Format PlatformInfo::formatFromString(const char* format) +{ + if (strcmp(format, "elf") == 0 || strcmp(format, "linux") == 0 + || strcmp(format, "freebsd") == 0 || strcmp(format, "qnx") == 0) { + return Elf; + } else if (strcmp(format, "pe") == 0 || strcmp(format, "windows") == 0) { + return Pe; + } else if (strcmp(format, "macho") == 0 || strcmp(format, "darwin") == 0 + || strcmp(format, "ios") == 0 || strcmp(format, "macosx") == 0) { + return MachO; + } else { + return UnknownFormat; + } +} + +PlatformInfo::Architecture PlatformInfo::archFromString(const char* arch) +{ + if (strcmp(arch, "i386") == 0) { + return Architecture::x86; + } else if (strcmp(arch, "x86_64") == 0) { + return Architecture::x86_64; + } else if (strcmp(arch, "arm") == 0) { + return Architecture::Arm; + } else if (strcmp(arch, "arm64") == 0) { + return Architecture::Arm64; + } else { + return Architecture::UnknownArch; + } +} + +Platform* Platform::getPlatform(PlatformInfo info) +{ + for (Platform* p = first; p; p = p->next) { + if (p->info == info) { + return p; + } + } + return 0; +} + +} // namespace tools + +} // namespace avian diff --git a/sgx-jvm/avian/src/tools/type-generator/CMakeLists.txt b/sgx-jvm/avian/src/tools/type-generator/CMakeLists.txt new file mode 100644 index 0000000000..53bb7cabb1 --- /dev/null +++ b/sgx-jvm/avian/src/tools/type-generator/CMakeLists.txt @@ -0,0 +1,9 @@ +add_executable(type_generator main.cpp) + +target_link_libraries(type_generator + avian_jvm_finder + avian_system + avian_util + ${ZLIB_LIBRARIES} + ${PLATFORM_LIBS} +) diff --git a/sgx-jvm/avian/src/tools/type-generator/io.h b/sgx-jvm/avian/src/tools/type-generator/io.h new file mode 100644 index 0000000000..2dcbaac4c1 --- /dev/null +++ b/sgx-jvm/avian/src/tools/type-generator/io.h @@ -0,0 +1,181 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#include + +#include "assert.h" + +#ifndef AVIAN_TOOLS_TYPE_GENERATOR_IO_H +#define AVIAN_TOOLS_TYPE_GENERATOR_IO_H + +namespace avian { +namespace tools { +namespace typegenerator { + +class Input { + public: + virtual ~Input() + { + } + + virtual void dispose() = 0; + + virtual int peek() = 0; + + virtual int read() = 0; + + virtual unsigned line() = 0; + + virtual unsigned column() = 0; + + void skipSpace() + { + bool quit = false; + while (not quit) { + int c = peek(); + switch (c) { + case ' ': + case '\t': + case '\n': + read(); + break; + + default: + quit = true; + } + } + } +}; + +class FileInput : public Input { + public: + const char* file; + FILE* stream; + unsigned line_; + unsigned column_; + bool close; + + FileInput(const char* file, FILE* stream = 0, bool close = true) + : file(file), stream(stream), line_(1), column_(1), close(close) + { + } + + virtual ~FileInput() + { + dispose(); + } + + virtual void dispose() + { + if (stream and close) { + fclose(stream); + stream = 0; + } + } + + virtual int peek() + { + int c = getc(stream); + ungetc(c, stream); + return c; + } + + virtual int read() + { + int c = getc(stream); + if (c == '\n') { + ++line_; + column_ = 1; + } else { + ++column_; + } + return c; + } + + virtual unsigned line() + { + return line_; + } + + virtual unsigned column() + { + return column_; + } +}; + +class Output { + public: + virtual ~Output() + { + } + + virtual void dispose() = 0; + + virtual void write(const std::string& s) = 0; + + void write(int32_t i) + { + static const int Size = 32; + char s[Size]; + int c UNUSED = vm::snprintf(s, Size, "%d", i); + assert(c > 0 and c < Size); + write(s); + } + + void writeUnsigned(uint32_t i) + { + static const int Size = 32; + char s[Size]; + int c UNUSED = vm::snprintf(s, Size, "%u", i); + assert(c > 0 and c < Size); + write(s); + } +}; + +class FileOutput : public Output { + public: + const char* file; + FILE* stream; + bool close; + + FileOutput(const char* file, FILE* stream = 0, bool close = true) + : file(file), stream(stream), close(close) + { + } + + virtual ~FileOutput() + { + dispose(); + } + + virtual void dispose() + { + if (stream and close) { + fclose(stream); + stream = 0; + } + } + + virtual void write(const std::string& s) + { + fputs(s.c_str(), stream); + } + + const char* filename() + { + return file; + } +}; + +} // namespace typegenerator +} // namespace tools +} // namespace avian + +#endif // AVIAN_TOOLS_TYPE_GENERATOR_IO_H diff --git a/sgx-jvm/avian/src/tools/type-generator/main.cpp b/sgx-jvm/avian/src/tools/type-generator/main.cpp new file mode 100644 index 0000000000..40735927b2 --- /dev/null +++ b/sgx-jvm/avian/src/tools/type-generator/main.cpp @@ -0,0 +1,1707 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#include "stdlib.h" +#include "stdio.h" +#include "stdint.h" +#include "string.h" +#include "errno.h" + +#include +#include +#include +#include +#include +#include + +#include "avian/constants.h" +#include "avian/finder.h" + +#include +#include +#include + +#include "io.h" +#include "sexpr.h" + +#include "assert.h" + +using namespace avian::util; + +#define UNREACHABLE abort() + +#define UNUSED __attribute__((unused)) + +using namespace vm; +using namespace avian::tools::typegenerator; + +namespace avian { +namespace tools { +namespace typegenerator { + +class Class; + +class Field { + public: + std::string name; + size_t elementSize; + size_t offset; + uintptr_t ownerId; + bool noassert; + bool nogc; + bool polyfill; + bool threadParam; + + std::string javaSpec; + std::string typeName; + + Field(Class* ownerId, + const std::string& typeName, + const std::string& javaSpec, + const std::string& name) + : name(name), + elementSize(-1), + offset(0), + ownerId(reinterpret_cast(ownerId)), + noassert(false), + nogc(false), + polyfill(false), + threadParam(false), + javaSpec(javaSpec), + typeName(typeName) + { + } + + std::string dump() const + { + std::ostringstream ss; + ss << "field " << name << ":" << typeName << ":" << javaSpec + << ", size=" << elementSize << ", offset=" << offset; + if (noassert) { + ss << " noassert"; + } + if (nogc) { + ss << " nogc"; + } + if (polyfill) { + ss << " polyfill"; + } + return ss.str(); + } +}; + +class Method { + public: + std::string javaName; + std::string javaSpec; + + Method(const std::string& javaName, const std::string& javaSpec) + : javaName(javaName), javaSpec(javaSpec) + { + } + + bool operator==(const Method& o) const + { + return javaName == o.javaName && javaSpec == o.javaSpec; + } + + bool operator<(const Method& o) const + { + return javaName < o.javaName + || (javaName == o.javaName && javaSpec < o.javaSpec); + } + std::string dump() const + { + return "method " + javaName + javaSpec; + } +}; + +class Class { + public: + // "simple" name, used for generated code, defined in types.def + std::string name; + + // Name of the backing Java class, empty if there isn't one + std::string javaName; + + Class* super; + + std::vector fields; + std::set methods; + + Field* arrayField; + + bool overridesMethods; + + int fixedSize; + + Class(const std::string& name) + : name(name), + super(0), + arrayField(0), + overridesMethods(false), + fixedSize(-1) + { + } + + std::string dump() const + { + std::ostringstream ss; + ss << "class " << name; + if (javaName.size() > 0) { + ss << "(" << javaName << ")"; + } + if (super) { + ss << " : " << super->name << "(" << super->javaName << ")"; + } + ss << " {\n"; + + for (const auto f : fields) { + ss << " " << f->dump() << "\n"; + } + + for (const auto m : methods) { + ss << " " << m.dump() << "\n"; + } + ss << "}"; + return ss.str(); + } + + void dumpToStdout() const + { + printf("%s\n", dump().c_str()); + } +}; + +class Module { + public: + // Map from java-level name to Class + std::map javaClasses; + + std::map classes; + + void add(Class* cl) + { + assert(classes.find(cl->name) == classes.end()); + classes[cl->name] = cl; + if (cl->javaName != "") { + assert(javaClasses.find(cl->javaName) == javaClasses.end()); + javaClasses[cl->javaName] = cl; + } + } +}; +} +} +} + +namespace { + +namespace local { + +#ifndef POINTER_SIZE +#define POINTER_SIZE sizeof(void*) +#endif + +const unsigned BytesPerWord = POINTER_SIZE; + +inline bool equal(const char* a, const char* b) +{ + return strcmp(a, b) == 0; +} + +inline bool endsWith(const std::string& b, const std::string& a) +{ + if (b.size() > a.size()) { + return false; + } + return std::equal(a.begin() + a.size() - b.size(), a.end(), b.begin()); +} + +std::string enumName(Module& module, Field* f) +{ + std::string& type = f->typeName; + if (type == "void*") { + return "word"; + } else if (type == "maybe_object") { + return "uintptr_t"; + } else if (f->javaSpec.size() != 0 + && (f->javaSpec[0] == 'L' || f->javaSpec[0] == '[')) { + return "object"; + } + const auto it = module.classes.find(f->typeName); + assert(f->typeName.size() > 0); + if (it != module.classes.end()) { + return "object"; + } else { + return f->typeName; + } +} + +class Character : public Object { + public: + char value; + + static Character* make(char value) + { + Character* o = allocate(); + o->type = Object::Character; + o->value = value; + return o; + } +}; + +char character(Object* o) +{ + assert(o->type == Object::Character); + return static_cast(o)->value; +} + +class String : public Object { + public: + const char* value; + + static String* make(Object* s) + { + assert(s); + + String* o = allocate(); + o->type = Object::String; + + unsigned length = 0; + for (Object* p = s; p; p = cdr(p)) + ++length; + + char* value = static_cast(malloc(length + 1)); + assert(value); + unsigned i = 0; + for (Object* p = s; p; p = cdr(p)) + value[i++] = character(car(p)); + value[i] = 0; + + o->value = value; + return o; + } +}; + +const char* string(Object* o) +{ + assert(o->type == Object::String); + return static_cast(o)->value; +} + +class Singleton : public Object { + public: + static Singleton* make(Object::ObjectType type) + { + Singleton* o = allocate(); + o->type = type; + return o; + } +}; + +std::string capitalize(const std::string& s) +{ + if (s[0] >= 'a' && s[0] <= 'z') { + return (char)(s[0] + 'A' - 'a') + s.substr(1, s.size() - 1); + } + return s; +} + +Object* read(Input* in, Object* eos, int level) +{ + List s; + + int c; + while ((c = in->peek()) >= 0) { + switch (c) { + case '(': { + if (s.first) { + return String::make(s.first); + } else { + List list; + Object* o; + in->read(); + while ((o = read(in, eos, level + 1)) != eos) { + list.append(o); + } + return list.first; + } + } break; + + case ')': { + if (s.first) { + return String::make(s.first); + } else { + if (level == 0) { + fprintf(stderr, "unexpected ')'\n"); + abort(); + } + in->read(); + return eos; + } + } break; + + case ' ': + case '\t': + case '\n': + case '\r': { + if (s.first) { + return String::make(s.first); + } + } break; + + default: { + s.append(Character::make(c)); + } break; + } + + in->read(); + } + + if (level == 0) { + if (s.first) { + return String::make(s.first); + } else { + return eos; + } + } else { + fprintf(stderr, "unexpected end of stream\n"); + abort(); + } +} + +bool namesPointer(const std::string& s) +{ + return s == "Collector" or s == "Disposer" or endsWith("*", s); +} + +unsigned sizeOf(Module& module, const std::string& type) +{ + if (type == "object" or type == "intptr_t" or type == "uintptr_t" + or type == "maybe_object") { + return BytesPerWord; + } else if (type == "unsigned" or type == "int") { + return sizeof(int); + } else if (type == "bool") { + return sizeof(bool); + } else if (type == "int8_t" or type == "uint8_t") { + return sizeof(uint8_t); + } else if (type == "int16_t" or type == "uint16_t") { + return sizeof(uint16_t); + } else if (type == "int32_t" or type == "uint32_t") { + return sizeof(uint32_t); + } else if (type == "int64_t" or type == "uint64_t") { + return sizeof(uint64_t); + } else if (type == "char") { + return sizeof(char); + } else if (endsWith("[0]", type)) { + return 0; + } else if (namesPointer(type)) { + return BytesPerWord; + } else { + const auto it = module.classes.find(type); + if (it != module.classes.end()) { + return BytesPerWord; + } else { + fprintf(stderr, "unexpected type: %s\n", type.c_str()); + abort(); + } + } +} + +struct FieldSpec { + bool isArray; + std::string aliasName; + bool require; + Field* field; + + FieldSpec() + { + } + + FieldSpec(bool isArray, Field* field) + : isArray(isArray), require(false), field(field) + { + } +}; + +class ClassParser { + public: + Class* cl; + std::map fields; + + ClassParser(Class* cl) : cl(cl) + { + } + + void add(FieldSpec f) + { + if (f.field->polyfill) { + if (fields.find(f.field->name) == fields.end()) { + fields[f.field->name] = f.field; + cl->fields.push_back(f.field); + } else { + fields[f.field->name]->threadParam = true; + } + return; + } + if (f.aliasName.size() > 0) { + if (fields.find(f.aliasName) == fields.end()) { + if (fields.find(f.field->name) != fields.end()) { + // printf("alias %s.%s -> %s.%s\n", cl->name.c_str(), + // f.field->name.c_str(), cl->name.c_str(), f.aliasName.c_str()); + const auto it = fields.find(f.field->name); + assert(it != fields.end()); + Field* renamed = it->second; + fields.erase(it); + fields[f.aliasName] = renamed; + + renamed->name = f.aliasName; + + // TODO: this currently works around how avian uses an object (either + // a char[] or byte[]) for String.data + renamed->typeName = f.field->typeName; + renamed->javaSpec = f.field->javaSpec; + } else { + // printf("ignoring absent alias %s.%s -> %s.%s\n", cl->name.c_str(), + // f.field->name.c_str(), cl->name.c_str(), f-> aliasName.c_str()); + } + } else { + // printf("ignoring already defined alias %s.%s -> %s.%s\n", + // cl->name.c_str(), f.field->name.c_str(), cl->name.c_str(), f-> + // aliasName.c_str()); + } + } else { + if (fields.find(f.field->name) == fields.end()) { + // printf("add %s.%s\n", cl->name.c_str(), f.field->name.c_str()); + fields[f.field->name] = f.field; + if (f.isArray) { + add(FieldSpec(false, new Field(cl, "uintptr_t", "", "length"))); + assert(!cl->arrayField); + cl->arrayField = f.field; + } else { + cl->fields.push_back(f.field); + } + } else { + // printf("required check %s.%s\n", cl->name.c_str(), + // f.field->name.c_str()); + assert(f.aliasName.size() > 0 || f.require); + fields[f.field->name]->nogc |= f.field->nogc; + fields[f.field->name]->noassert |= f.field->noassert; + } + } + } + + void setSuper(Class* super) + { + assert(!cl->super); + cl->super = super; + assert(!super->arrayField); + assert(fields.size() == 0); + for (const auto f : super->fields) { + add(FieldSpec(false, f)); + } + } +}; + +FieldSpec parseArray(Module&, ClassParser& clparser, Object* p) +{ + const char* typeName = string(car(p)); + + p = cdr(p); + const char* name = string(car(p)); + + assert(!clparser.cl->arrayField); + return FieldSpec(true, new Field(clparser.cl, typeName, "", name)); +} + +FieldSpec parseVerbatimField(Module&, ClassParser& clparser, Object* p) +{ + const char* spec = string(car(p)); + const char* name = string(car(cdr(p))); + return FieldSpec(false, new Field(clparser.cl, spec, "", name)); +} + +FieldSpec parseField(Module& module, ClassParser& clparser, Object* p) +{ + FieldSpec f; + const char* spec = string(car(p)); + if (equal(spec, "field")) { + return parseVerbatimField(module, clparser, cdr(p)); + } else if (equal(spec, "array")) { + return parseArray(module, clparser, cdr(p)); + } else if (equal(spec, "noassert")) { + f = parseField(module, clparser, cdr(p)); + f.field->noassert = true; + f.require = true; + } else if (equal(spec, "nogc")) { + f = parseField(module, clparser, cdr(p)); + f.field->nogc = true; + f.require = true; + } else if (equal(spec, "require")) { + f = parseField(module, clparser, cdr(p)); + f.require = true; + } else if (equal(spec, "alias")) { + const char* name = string(car(cdr(p))); + f = parseField(module, clparser, cdr(cdr(p))); + f.aliasName = name; + } else if (equal(spec, "polyfill")) { + f = parseField(module, clparser, cdr(p)); + f.field->polyfill = true; + } else { + return parseVerbatimField(module, clparser, p); + } + return f; +} + +void parseSubdeclaration(Module& module, ClassParser& clparser, Object* p) +{ + const char* front = string(car(p)); + if (equal(front, "extends")) { + Class* super = module.classes[string(car(cdr(p)))]; + clparser.setSuper(super); + } else { + clparser.add(parseField(module, clparser, p)); + } +} + +const char* append(const char* a, const char* b, const char* c, const char* d) +{ + unsigned al = strlen(a); + unsigned bl = strlen(b); + unsigned cl = strlen(c); + unsigned dl = strlen(d); + char* p = static_cast(malloc(al + bl + cl + dl + 1)); + memcpy(p, a, al); + memcpy(p + al, b, bl); + memcpy(p + al + bl, c, cl); + memcpy(p + al + bl + cl, d, dl + 1); + return p; +} + +const char* append(const char* a, const char* b) +{ + return append(a, b, "", ""); +} + +const char* fieldType(const char* spec) +{ + switch (*spec) { + case 'B': + case 'Z': + return "uint8_t"; + case 'C': + case 'S': + return "uint16_t"; + case 'D': + case 'J': + return "uint64_t"; + case 'F': + case 'I': + return "uint32_t"; + case 'L': + case '[': + return "object"; + + default: + abort(); + } +} + +void parseJavaClass(Module& module, ClassParser& clparser, Stream* s) +{ + uint32_t magic = s->read4(); + assert(magic == 0xCAFEBABE); + (void)magic; + s->read2(); // minor version + s->read2(); // major version + + unsigned poolCount = s->read2() - 1; + std::vector pool(poolCount, -1); + for (unsigned i = 0; i < poolCount; ++i) { + unsigned c = s->read1(); + + switch (c) { + case CONSTANT_Integer: + case CONSTANT_Float: + pool[i] = s->read4(); + break; + + case CONSTANT_Long: + case CONSTANT_Double: + pool[i++] = s->read4(); + pool[i] = s->read4(); + break; + + case CONSTANT_Utf8: { + unsigned length = s->read2(); + uint8_t* p = static_cast(malloc(length + 1)); + s->read(p, length); + p[length] = 0; + pool[i] = reinterpret_cast(p); + } break; + + case CONSTANT_Class: + case CONSTANT_String: + pool[i] = s->read2(); + break; + + case CONSTANT_NameAndType: + pool[i] = s->read4(); + break; + + case CONSTANT_Fieldref: + case CONSTANT_Methodref: + case CONSTANT_InterfaceMethodref: + pool[i] = s->read4(); + break; + + default: + abort(); + } + } + + s->read2(); // flags + s->read2(); // name + + unsigned superIndex = s->read2(); + if (superIndex) { + const char* name + = reinterpret_cast(pool[pool[superIndex - 1] - 1]); + Class* super = module.javaClasses[name]; + clparser.setSuper(super); + } + + unsigned interfaceCount = s->read2(); + s->skip(interfaceCount * 2); + // for (unsigned i = 0; i < interfaceCount; ++i) { + // const char* name = reinterpret_cast + // (pool[pool[s->read2() - 1] - 1]); + // } + + unsigned fieldCount = s->read2(); + for (unsigned i = 0; i < fieldCount; ++i) { + unsigned flags = s->read2(); + unsigned nameIndex = s->read2(); + unsigned specIndex = s->read2(); + + unsigned attributeCount = s->read2(); + for (unsigned j = 0; j < attributeCount; ++j) { + s->read2(); + s->skip(s->read4()); + } + + if ((flags & ACC_STATIC) == 0) { + char* name = reinterpret_cast(pool[nameIndex - 1]); + unsigned nameLength = strlen(name); + if (nameLength > 0 and name[nameLength - 1] == '_') { + name[nameLength - 1] = 0; + } + + const char* spec = reinterpret_cast(pool[specIndex - 1]); + const char* memberType = fieldType(spec); + + clparser.add( + FieldSpec(false, new Field(clparser.cl, memberType, spec, name))); + } + } + + if (clparser.cl->super) { + clparser.cl->methods.insert(clparser.cl->super->methods.begin(), + clparser.cl->super->methods.end()); + } + + unsigned methodCount = s->read2(); + for (unsigned i = 0; i < methodCount; ++i) { + unsigned flags = s->read2(); + unsigned nameIndex = s->read2(); + unsigned specIndex = s->read2(); + + unsigned attributeCount = s->read2(); + for (unsigned j = 0; j < attributeCount; ++j) { + s->read2(); + s->skip(s->read4()); + } + + const char* name = reinterpret_cast(pool[nameIndex - 1]); + const char* spec = reinterpret_cast(pool[specIndex - 1]); + + if ((flags & (ACC_STATIC | ACC_PRIVATE)) == 0 and *name != '<') { + clparser.cl->methods.insert(Method(name, spec)); + clparser.cl->overridesMethods = true; + } + } +} + +void parseType(Finder* finder, Module& module, Object* p) +{ + const char* name = string(car(p)); + + Class* cl = new Class(name); + + ClassParser clparser(cl); + + const char* javaName = 0; + if (cdr(p) and car(cdr(p))->type == Object::String) { + p = cdr(p); + javaName = string(car(p)); + cl->javaName = javaName; + } + + bool isJavaType = javaName and *javaName != '['; + + if (isJavaType) { + class Client : public Stream::Client { + public: + virtual void NO_RETURN handleError() + { + abort(); + } + } client; + System::Region* region = finder->find(append(javaName, ".class")); + if (region == 0) { + return; + } + Stream s(&client, region->start(), region->length()); + parseJavaClass(module, clparser, &s); + region->dispose(); + } + + module.add(cl); + + for (p = cdr(p); p; p = cdr(p)) { + parseSubdeclaration(module, clparser, car(p)); + } + + if (not isJavaType) { + if (cl->super) { + cl->methods.insert(cl->super->methods.begin(), cl->super->methods.end()); + } + } +} + +void parseDeclaration(Finder* finder, Module& module, Object* p) +{ + const char* spec = string(car(p)); + if (equal(spec, "type")) { + parseType(finder, module, cdr(p)); + } else { + fprintf(stderr, "unexpected declaration spec: %s\n", spec); + abort(); + } +} + +void parse(Finder* finder, Input* in, Module& module) +{ + Object* eos = Singleton::make(Object::Eos); + List declarations; + + Object* o; + while ((o = read(in, eos, 0)) != eos) { + parseDeclaration(finder, module, o); + } +} + +void layoutClass(Module& module, Class* cl) +{ + if (cl->fixedSize >= 0) { + return; + } + + unsigned offset = BytesPerWord; + + unsigned size = 0; + unsigned alignment = BytesPerWord; + + alignment = BytesPerWord; + + for (const auto f : cl->fields) { + f->elementSize = sizeOf(module, f->typeName); + + if (!f->polyfill) { // polyfills contribute no size + alignment = f->elementSize; + offset = (offset + alignment - 1) & ~(alignment - 1); + f->offset = offset; + + size = f->elementSize; + + offset += size; + } + } + if (cl->arrayField) { + Field* f = cl->arrayField; + + f->elementSize = sizeOf(module, f->typeName); + + alignment = f->elementSize; + offset = (offset + alignment - 1) & ~(alignment - 1); + f->offset = offset; + } + // offset = (offset + BytesPerWord - 1) & ~(BytesPerWord - 1); + cl->fixedSize = offset; +} + +void layoutClasses(Module& module) +{ + for (const auto p : module.classes) { + Class* cl = p.second; + layoutClass(module, cl); + } +} + +void writeOffset(Output* out, size_t offset) +{ + out->write(offset); +} + +void writeOffset(Output* out, Class* cl) +{ + out->write(cl->fixedSize); + if (cl->arrayField) { + out->write(" + pad(length * "); + out->write(cl->arrayField->elementSize); + out->write(")"); + } +} + +std::string cppClassName(Class* cl) +{ + if (cl->name == "jobject") { + return "object"; + } else { + return "Gc" + capitalize(cl->name) + "*"; + } +} + +std::string cppFieldType(Module& module, Field* f) +{ + if (f->javaSpec.size() != 0) { + if (f->javaSpec[0] == 'L') { + std::string className = f->javaSpec.substr(1, f->javaSpec.size() - 2); + const auto it = module.javaClasses.find(className); + if (it != module.javaClasses.end()) { + return cppClassName(it->second); + } + } else if (f->javaSpec[0] == '[') { + const auto it = module.javaClasses.find(f->javaSpec); + if (it != module.javaClasses.end()) { + return cppClassName(it->second); + } + } + } + const auto it = module.classes.find(f->typeName); + assert(f->typeName.size() > 0); + if (it != module.classes.end()) { + return cppClassName(it->second); + } else if (f->typeName == "maybe_object") { + return "uintptr_t"; + } else { + return f->typeName; + } +} + +void writeAccessor(Output* out, Class* cl, Field* f) +{ + out->write("const unsigned "); + out->write(capitalize(cl->name)); + out->write(capitalize(f->name)); + out->write(" = "); + writeOffset(out, f->offset); + out->write(";\n\n"); + + out->write("#define HAVE_"); + out->write(capitalize(cl->name)); + out->write(capitalize(f->name)); + out->write(" 1\n"); + + if (! f->javaSpec.empty()) { + std::string s = f->javaSpec; + std::replace(s.begin(), s.end(), '/', '_'); + std::replace(s.begin(), s.end(), '$', '_'); + std::replace(s.begin(), s.end(), ';', '_'); + std::replace(s.begin(), s.end(), '[', '_'); + + out->write("#define HAVE_"); + out->write(capitalize(cl->name)); + out->write(capitalize(f->name)); + out->write("_"); + out->write(s); + out->write(" 1\n\n"); + } +} + +void writeAccessors(Output* out, Module& module) +{ + for (const auto p : module.classes) { + Class* cl = p.second; + for (const auto f : cl->fields) { + if (!f->polyfill) { + writeAccessor(out, cl, f); + } + } + if (cl->arrayField) { + writeAccessor(out, cl, cl->arrayField); + } + } +} + +void writeSizes(Output* out, Module& module) +{ + for (const auto p : module.classes) { + Class* cl = p.second; + + out->write("const unsigned FixedSizeOf"); + out->write(capitalize(cl->name)); + out->write(" = "); + out->write(cl->fixedSize); + out->write(";\n\n"); + + if (cl->arrayField) { + out->write("const unsigned ArrayElementSizeOf"); + out->write(capitalize(cl->name)); + out->write(" = "); + out->write(cl->arrayField->elementSize); + out->write(";\n\n"); + } + } +} + +std::string obfuscate(const std::string& s) +{ + if (s == "default" || s == "template" || s == "class" || s == "register" + || s == "this") { + return s + "_"; + } else { + return s; + } +} + +void writeConstructorParameters(Output* out, Module& module, Class* cl) +{ + for (const auto f : cl->fields) { + if (!f->polyfill) { + out->write(", "); + out->write(cppFieldType(module, f)); + out->write(" "); + out->write(obfuscate(f->name)); + } + } +} + +void writeConstructorArguments(Output* out, Class* cl) +{ + for (const auto f : cl->fields) { + if (!f->polyfill) { + out->write(", "); + out->write(obfuscate(f->name)); + } + } +} + +void writeConstructorInitializations(Output* out, Class* cl) +{ + for (const auto f : cl->fields) { + if (!f->polyfill) { + out->write(" o->set"); + out->write(capitalize(f->name)); + out->write("(t, "); + out->write(obfuscate(f->name)); + out->write(");\n"); + } + } +} + +void writeClassDeclarations(Output* out, Module& module) +{ + for (const auto p : module.classes) { + Class* cl = p.second; + + out->write("class Gc"); + out->write(capitalize(cl->name)); + out->write(";\n"); + } + out->write("\n"); +} + +bool isFieldGcVisible(Module& module, Field* f) +{ + return enumName(module, f) == "object" && !f->nogc; +} + +bool isFieldGcMarkable(Module& module, Field* f) +{ + return (f->typeName == "maybe_object" || enumName(module, f) == "object") + && !f->nogc; +} + +void writeClassAccessors(Output* out, Module& module, Class* cl) +{ + for (const auto f : cl->fields) { + if (!f->polyfill) { + out->write(" void set"); + out->write(capitalize(f->name)); + out->write("(Thread* t UNUSED, "); + out->write(cppFieldType(module, f)); + out->write(" value) { "); + if (isFieldGcMarkable(module, f)) { + out->write("setField(t, this , "); + out->write(capitalize(cl->name)); + out->write(capitalize(f->name)); + out->write(", reinterpret_cast(value));"); + } else { + out->write("field_at<"); + out->write(cppFieldType(module, f)); + out->write(">("); + out->write(capitalize(cl->name)); + out->write(capitalize(f->name)); + out->write(") = value;"); + } + out->write(" }\n"); + + out->write(" "); + out->write(cppFieldType(module, f)); + out->write("* "); + out->write(obfuscate(f->name)); + out->write("Ptr() { return &field_at<"); + out->write(cppFieldType(module, f)); + out->write(">("); + out->write(capitalize(cl->name)); + out->write(capitalize(f->name)); + out->write("); }\n"); + } + + out->write(" "); + out->write(cppFieldType(module, f)); + if (!f->polyfill && !isFieldGcMarkable(module, f)) { + out->write("&"); + } + out->write(" "); + out->write(obfuscate(f->name)); + if (f->threadParam || f->polyfill) { + out->write("(Thread*"); + } else { + out->write("("); + } + if (f->polyfill) { + out->write("); // polyfill, assumed to be implemented elsewhere\n"); + } else { + out->write(") { return field_at<"); + out->write(cppFieldType(module, f)); + out->write(">("); + out->write(capitalize(cl->name)); + out->write(capitalize(f->name)); + out->write("); }\n"); + } + } + if (cl->arrayField) { + Field* f = cl->arrayField; + out->write(" avian::util::Slice<"); + if (isFieldGcVisible(module, f)) { + out->write("const "); + } + out->write(cppFieldType(module, f)); + out->write("> "); + out->write(obfuscate(f->name)); + out->write("() { return avian::util::Slice<"); + if (isFieldGcVisible(module, f)) { + out->write("const "); + } + out->write(cppFieldType(module, f)); + out->write("> (&field_at<"); + if (isFieldGcVisible(module, f)) { + out->write("const "); + } + out->write(cppFieldType(module, f)); + out->write(">("); + out->write(capitalize(cl->name)); + out->write(capitalize(f->name)); + out->write("), field_at("); + out->write(capitalize(cl->name)); + out->write("Length)); }\n"); + + out->write(" void set"); + out->write(capitalize(f->name)); + out->write("Element(Thread* t UNUSED, size_t index, "); + out->write(cppFieldType(module, f)); + out->write(" value) { "); + if (isFieldGcMarkable(module, f)) { + out->write("setField(t, this , "); + out->write(capitalize(cl->name)); + out->write(capitalize(f->name)); + out->write(" + index * ("); + out->write(sizeOf(module, f->typeName)); + out->write("), reinterpret_cast(value));"); + } else { + out->write("field_at<"); + out->write(cppFieldType(module, f)); + out->write(">("); + out->write(capitalize(cl->name)); + out->write(capitalize(f->name)); + out->write(" + index * ("); + out->write(sizeOf(module, f->typeName)); + out->write(")) = value;"); + } + out->write(" }\n"); + } +} + +void writeClasses(Output* out, Module& module) +{ + for (const auto p : module.classes) { + Class* cl = p.second; + + out->write("class Gc"); + out->write(capitalize(cl->name)); + out->write(": public GcObject {\n"); + out->write(" public:\n"); + out->write(" static const Gc::Type Type = Gc::"); + out->write(capitalize(cl->name)); + out->write("Type;\n"); + out->write(" static const size_t FixedSize = FixedSizeOf"); + out->write(capitalize(cl->name)); + out->write(";\n\n"); + + out->write(" static Gc" + capitalize(cl->name) + "* makeZeroed(Thread* t"); + if (cl->arrayField) { + out->write(", uintptr_t length"); + } + out->write(");\n"); + + writeClassAccessors(out, module, cl); + + out->write("};\n\n"); + } +} + +void writeInitializerDeclarations(Output* out, Module& module) +{ + for (const auto p : module.classes) { + Class* cl = p.second; + out->write("void init"); + out->write(capitalize(cl->name)); + out->write("(Thread* t, Gc"); + out->write(capitalize(cl->name)); + out->write("* o"); + + writeConstructorParameters(out, module, cl); + + out->write(");\n\n"); + } +} + +void writeConstructorDeclarations(Output* out, Module& module) +{ + for (const auto p : module.classes) { + Class* cl = p.second; + out->write("Gc"); + out->write(capitalize(cl->name)); + out->write("* make"); + out->write(capitalize(cl->name)); + out->write("(Thread* t"); + + writeConstructorParameters(out, module, cl); + + out->write(");\n\n"); + } +} + +void writeInitializers(Output* out, Module& module) +{ + for (const auto p : module.classes) { + Class* cl = p.second; + out->write("void init"); + out->write(capitalize(cl->name)); + out->write("(Thread* t, Gc"); + out->write(capitalize(cl->name)); + out->write("* o"); + + writeConstructorParameters(out, module, cl); + + out->write(")\n{\n"); + + out->write(" setObjectClass(t, reinterpret_cast(o), "); + out->write( + "reinterpret_cast(reinterpret_cast(t->m->types)->" + "body()[Gc::"); + out->write(capitalize(cl->name)); + out->write("Type]));\n"); + + writeConstructorInitializations(out, cl); + + out->write("}\n\n"); + } +} + +void writeConstructors(Output* out, Module& module) +{ + for (const auto p : module.classes) { + Class* cl = p.second; + + bool hasObjectMask = cl->name == "singleton"; + + std::string name = "Gc" + capitalize(cl->name); + + out->write(name + "* " + name + "::makeZeroed(Thread* t"); + if (cl->arrayField) { + out->write(", uintptr_t length"); + } + out->write(")\n{\n"); + out->write(" " + name + "* o = reinterpret_cast<" + name + + "*>(allocate(t, "); + writeOffset(out, cl); + if (hasObjectMask) { + out->write(", true"); + } else { + out->write(", false"); + } + out->write("));\n"); + out->write(" setObjectClass(t, reinterpret_cast(o), "); + out->write( + "reinterpret_cast(reinterpret_cast(t->m->types)->" + "body()[Gc::"); + out->write(capitalize(cl->name)); + out->write("Type]));\n"); + out->write(" return o;\n"); + out->write("}\n\n"); + + out->write(name + "* make" + capitalize(cl->name)); + out->write("(Thread* t"); + + writeConstructorParameters(out, module, cl); + + out->write(")\n{\n"); + for (const auto f : cl->fields) { + if (enumName(module, f) == "object" and not f->nogc) { + out->write(" PROTECT(t, "); + out->write(obfuscate(f->name)); + out->write(");\n"); + + hasObjectMask = true; + } + } + if (cl->arrayField) { + Field* f = cl->arrayField; + if (f->typeName == "object" and not f->nogc) { + hasObjectMask = true; + } + } + + out->write(" " + name + "* o = reinterpret_cast<" + name + + "*>(allocate(t, "); + writeOffset(out, cl); + if (hasObjectMask) { + out->write(", true"); + } else { + out->write(", false"); + } + out->write("));\n"); + + out->write(" init"); + out->write(capitalize(cl->name)); + out->write("(t, o"); + writeConstructorArguments(out, cl); + out->write(");\n"); + + out->write(" return o;\n}\n\n"); + } +} + +void writeEnums(Output* out, Module& module) +{ + bool wrote = false; + for (const auto p : module.classes) { + Class* cl = p.second; + if (wrote) { + out->write(",\n"); + } else { + wrote = true; + } + out->write(capitalize(cl->name)); + out->write("Type"); + } + + if (wrote) { + out->write("\n"); + } +} + +void set(uint32_t* mask, unsigned index) +{ + if (index < 32) { + *mask |= 1 << index; + } else { + UNREACHABLE; + } +} + +void set(std::vector& mask, unsigned index) +{ + set(&(mask[index / 32]), index % 32); +} + +std::vector typeObjectMask(Module& module, Class* cl) +{ + std::vector mask(ceilingDivide( + cl->fixedSize + (cl->arrayField ? cl->arrayField->elementSize : 0), + 32 * BytesPerWord)); + + set(mask, 0); + + for (const auto f : cl->fields) { + unsigned offset = f->offset / BytesPerWord; + if (isFieldGcVisible(module, f)) { + set(mask, offset); + } + } + + if (cl->arrayField) { + Field* f = cl->arrayField; + unsigned offset = f->offset / BytesPerWord; + if (isFieldGcVisible(module, f)) { + set(mask, offset); + } + } + + return mask; +} + +bool trivialMask(const std::vector& mask) +{ + if (mask[0] != 1) { + return false; + } + + for (size_t i = 1; i < mask.size(); ++i) { + if (mask[i]) { + return false; + } + } + + return true; +} + +void writeInitialization(Output* out, + Module& module, + std::set& alreadyInited, + Class* cl) +{ + if (alreadyInited.find(cl) != alreadyInited.end()) { + return; + } + alreadyInited.insert(cl); + if (cl->super && cl->name != "intArray" && cl->name != "class") { + writeInitialization(out, module, alreadyInited, cl->super); + } + + std::vector mask = typeObjectMask(module, cl); + bool trivialMask = local::trivialMask(mask); + if (trivialMask) { + out->write("{ "); + } else { + out->write("{ uint32_t mask["); + out->write(mask.size()); + out->write("] = { "); + for (size_t i = 0; i < mask.size(); ++i) { + out->writeUnsigned(mask[i]); + if (i < mask.size() - 1) { + out->write(", "); + } + } + out->write(" };\n"); + } + + out->write("bootClass(t, Gc::"); + out->write(capitalize(cl->name)); + out->write("Type, "); + + if (cl->super) { + out->write("Gc::"); + out->write(capitalize(cl->super->name)); + out->write("Type"); + } else { + out->write("-1"); + } + out->write(", "); + + if (trivialMask) { + out->write("0"); + } else { + out->write("mask"); + } + out->write(", "); + + out->write(cl->fixedSize); + out->write(", "); + + out->write(cl->arrayField ? cl->arrayField->elementSize : 0); + out->write(", "); + + out->write(cl->methods.size()); + out->write("); }\n"); +} + +void writeInitializations(Output* out, Module& module) +{ + std::set alreadyInited; + + writeInitialization(out, module, alreadyInited, module.classes["intArray"]); + writeInitialization(out, module, alreadyInited, module.classes["class"]); + + for (const auto p : module.classes) { + Class* cl = p.second; + if (cl->name != "intArray" && cl->name != "class") { + writeInitialization(out, module, alreadyInited, cl); + } + } +} + +void writeJavaInitialization(Output* out, + Class* cl, + std::set& alreadyInited) +{ + if (alreadyInited.find(cl) != alreadyInited.end()) { + return; + } + + alreadyInited.insert(cl); + + if (cl->super) { + writeJavaInitialization(out, cl->super, alreadyInited); + } + + out->write("bootJavaClass(t, Gc::"); + out->write(capitalize(cl->name)); + out->write("Type, "); + + if (cl->super) { + out->write("Gc::"); + out->write(capitalize(cl->super->name)); + out->write("Type"); + } else { + out->write("-1"); + } + out->write(", \""); + + out->write(cl->javaName); + out->write("\", "); + + if (cl->overridesMethods) { + out->write(cl->methods.size()); + } else { + out->write("-1"); + } + out->write(", bootMethod);\n"); +} + +void writeJavaInitializations(Output* out, Module& module) +{ + std::set alreadyInited; + for (const auto p : module.classes) { + Class* cl = p.second; + if (cl->javaName.size()) { + writeJavaInitialization(out, cl, alreadyInited); + } + } +} + +void writeNameInitialization(Output* out, Class* cl) +{ + out->write("nameClass(t, Gc::"); + out->write(capitalize(cl->name)); + out->write("Type, \""); + if (cl->name == "jbyte" or cl->name == "jboolean" or cl->name == "jshort" + or cl->name == "jchar" or cl->name == "jint" or cl->name == "jlong" + or cl->name == "jfloat" or cl->name == "jdouble" or cl->name == "jvoid") { + out->write(cl->name.substr(1, cl->name.size() - 1)); + } else { + out->write("vm::"); + out->write(cl->name); + } + out->write("\");\n"); +} + +void writeNameInitializations(Output* out, Module& module) +{ + for (const auto p : module.classes) { + Class* cl = p.second; + if (!cl->javaName.size()) { + writeNameInitialization(out, cl); + } + } +} + +void writeMap(Output* out, Module& module, Class* cl) +{ + std::ostringstream ss; + for (const auto f : cl->fields) { + ss << "Type_"; + ss << enumName(module, f); + if (f->nogc) { + ss << "_nogc"; + } + + ss << ", "; + } + + if (cl->arrayField) { + Field* f = cl->arrayField; + ss << "Type_array, "; + ss << "Type_"; + ss << enumName(module, f); + ss << ", "; + } + + ss << "Type_none"; + + out->write(ss.str()); +} + +void writeMaps(Output* out, Module& module) +{ + out->write("Type types[]["); + out->write(module.classes.size()); + out->write("] = {\n"); + bool wrote = false; + for (const auto p : module.classes) { + Class* cl = p.second; + if (wrote) { + out->write(",\n"); + } else { + wrote = true; + } + + out->write("// "); + out->write(cl->name); + out->write("\n{ "); + writeMap(out, module, cl); + out->write(" }"); + } + out->write("\n};"); +} + +} // namespace local + +} // namespace + +extern "C" uint64_t vmNativeCall(void*, void*, unsigned, unsigned) +{ + abort(); +} + +extern "C" void vmJump(void*, void*, void*, void*, uintptr_t, uintptr_t) +{ + abort(); +} + +int main(int ac, char** av) +{ + ArgParser parser; + Arg classpath(parser, true, "cp", ""); + Arg input(parser, true, "i", ""); + Arg output(parser, true, "o", ""); + Arg outputType(parser, + true, + "t", + ""); + + if (!parser.parse(ac, av)) { + parser.printUsage(av[0]); + exit(1); + } + + if (!(local::equal(outputType.value, "enums") + || local::equal(outputType.value, "declarations") + || local::equal(outputType.value, "constructors") + || local::equal(outputType.value, "initializations") + || local::equal(outputType.value, "java-initializations") + || local::equal(outputType.value, "name-initializations") + || local::equal(outputType.value, "maps"))) { + parser.printUsage(av[0]); + exit(1); + } + + System* system = makeSystem(); + + class MyAllocator : public avian::util::Alloc { + public: + MyAllocator(System* s) : s(s) + { + } + + virtual void* allocate(size_t size) + { + void* p = s->tryAllocate(size); + if (p == 0) { + abort(s); + } + return p; + } + + virtual void free(const void* p, size_t) + { + s->free(p); + } + + System* s; + } allocator(system); + + Finder* finder = makeFinder(system, &allocator, classpath.value, 0); + + FILE* inStream = ::fopen(input.value, "rb"); + if (inStream == 0) { + fprintf(stderr, "unable to open %s: %s\n", input.value, strerror(errno)); + exit(1); + } + + FileInput in(0, inStream, false); + + Module module; + local::parse(finder, &in, module); + local::layoutClasses(module); + + finder->dispose(); + system->dispose(); + + FILE* outStream = ::fopen(output.value, "wb"); + if (outStream == 0) { + fprintf(stderr, "unable to open %s: %s\n", output.value, strerror(errno)); + exit(1); + } + FileOutput out(0, outStream, false); + + if (local::equal(outputType.value, "enums")) { + local::writeEnums(&out, module); + } else if (local::equal(outputType.value, "declarations")) { + out.write("const unsigned TypeCount = "); + out.Output::write(module.classes.size()); + out.write(";\n\n"); + + local::writeClassDeclarations(&out, module); + local::writeAccessors(&out, module); + local::writeSizes(&out, module); + local::writeClasses(&out, module); + local::writeInitializerDeclarations(&out, module); + local::writeConstructorDeclarations(&out, module); + } else if (local::equal(outputType.value, "constructors")) { + local::writeInitializers(&out, module); + local::writeConstructors(&out, module); + } else if (local::equal(outputType.value, "initializations")) { + local::writeInitializations(&out, module); + } else if (local::equal(outputType.value, "java-initializations")) { + local::writeJavaInitializations(&out, module); + } else if (local::equal(outputType.value, "name-initializations")) { + local::writeNameInitializations(&out, module); + } else if (local::equal(outputType.value, "maps")) { + local::writeMaps(&out, module); + } + + out.write("\n"); +} diff --git a/sgx-jvm/avian/src/tools/type-generator/sexpr.h b/sgx-jvm/avian/src/tools/type-generator/sexpr.h new file mode 100644 index 0000000000..07059d74ec --- /dev/null +++ b/sgx-jvm/avian/src/tools/type-generator/sexpr.h @@ -0,0 +1,111 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#ifndef AVIAN_TOOLS_TYPE_GENERATOR_SEXPR_H +#define AVIAN_TOOLS_TYPE_GENERATOR_SEXPR_H + +namespace avian { +namespace tools { +namespace typegenerator { + +template +inline T* allocate() +{ + T* t = static_cast(malloc(sizeof(T))); + assert(t); + return t; +} + +class Object { + public: + typedef enum { + Scalar, + Array, + Method, + Type, + Pair, + Character, + String, + Eos + } ObjectType; + + ObjectType type; +}; + +class Pair : public Object { + public: + Object* car; + Object* cdr; + + static Pair* make(Object* car, Object* cdr) + { + Pair* o = allocate(); + o->type = Object::Pair; + o->car = car; + o->cdr = cdr; + return o; + } +}; + +inline Object* cons(Object* car, Object* cdr) +{ + return Pair::make(car, cdr); +} + +inline Object*& car(Object* o) +{ + assert(o->type == Object::Pair); + return static_cast(o)->car; +} + +inline void setCar(Object* o, Object* v) +{ + assert(o->type == Object::Pair); + static_cast(o)->car = v; +} + +inline Object*& cdr(Object* o) +{ + assert(o->type == Object::Pair); + return static_cast(o)->cdr; +} + +inline void setCdr(Object* o, Object* v) +{ + assert(o->type == Object::Pair); + static_cast(o)->cdr = v; +} + +class List { + public: + Object* first; + Object* last; + + List() : first(0), last(0) + { + } + + void append(Object* o) + { + Object* p = cons(o, 0); + if (last) { + setCdr(last, p); + last = p; + } else { + first = last = p; + } + } +}; + +} // namespace typegenerator +} // namespace tools +} // namespace avian + +#endif // AVIAN_TOOLS_TYPE_GENERATOR_SEXPR_H diff --git a/sgx-jvm/avian/src/types.def b/sgx-jvm/avian/src/types.def new file mode 100644 index 0000000000..da247c9d26 --- /dev/null +++ b/sgx-jvm/avian/src/types.def @@ -0,0 +1,432 @@ +(type jobject java/lang/Object) + +(type class avian/VMClass + (array void* vtable)) + +(type jclass java/lang/Class + (require class vmClass)) + +(type jaccessibleObject java/lang/reflect/AccessibleObject) + +(type jexecutable java/lang/reflect/Executable) + +(type jfield java/lang/reflect/Field) + +(type jmethod java/lang/reflect/Method) + +(type jconstructor java/lang/reflect/Constructor) + +(type constantPool sun/reflect/ConstantPool) + +(type serializable java/io/Serializable) + +(type cloneable java/lang/Cloneable) + +(type callSite java/lang/invoke/CallSite + (require invocation invocation)) + +(type methodHandle java/lang/invoke/MethodHandle + (alias method method vmtarget)) + +(type methodType java/lang/invoke/MethodType) + +(type lookup java/lang/invoke/MethodHandles$Lookup) + +(type singleton avian/Singleton + (array maybe_object body)) + +(type classLoader java/lang/ClassLoader + (object map)) + +(type systemClassLoader avian/SystemClassLoader + (void* finder)) + +(type field avian/VMField) + +(type method avian/VMMethod) + +(type addendum avian/Addendum) + +(type classAddendum avian/ClassAddendum) + +(type methodAddendum avian/MethodAddendum) + +(type fieldAddendum avian/FieldAddendum) + +(type classRuntimeData + (object arrayClass) + (object jclass) + (object pool) + (object signers)) + +(type native + (void* function) + (uint8_t fast)) + +(type methodRuntimeData + (native native)) + +(type pointer + (void* value)) + +(type nativeIntercept + (extends native) + (object original)) + +(type region + (void* region) + (uint32_t position)) + +(type exceptionHandlerTable + (array uint64_t body)) + +(type lineNumberTable + (array uint64_t body)) + +(type invocation + (uint16_t bootstrap) + (int32_t index) + (class class) + (singleton pool) + (method template) + (callSite site)) + +(type triple + (object first) + (object second) + (object third)) + +(type finalizer + (nogc object target) + (void* finalize) + (nogc object next) + (object queueTarget) + (finalizer queueNext)) + +(type list + (uint32_t size) + (object front) + (object rear)) + +(type vector + (uint32_t size) + (array object body)) + +(type traceElement + (object method) + (int32_t ip)) + +(type treeNode + (object value) + (treeNode left) + (treeNode right)) + +(type callNode + (intptr_t address) + (method target) + (uintptr_t flags) + (callNode next)) + +(type wordArray + (array uintptr_t body)) + +(type array + (noassert array object body)) + +(type hashMap + (uint32_t size) + (field array array)) + +(type weakHashMap + (extends hashMap)) + +(type pair avian/Pair + (object first) + (object second)) + +(type monitor + (void* owner) + (void* waitHead) + (void* waitTail) + (object acquireHead) + (object acquireTail) + (uint32_t depth)) + +(type monitorNode + (void* value) + (object next)) + +(type innerClassReference avian/InnerClassReference) + +(type continuationContext + (continuationContext next) + (object before) + (object after) + (object continuation) + (method method)) + +(type continuation avian/Continuations$Continuation + (continuation next) + (continuationContext context) + (method method) + (void* address) + (uintptr_t returnAddressOffset) + (uintptr_t framePointerOffset) + (array uintptr_t body)) + +(type unwindResult avian/Continuations$UnwindResult) + +(type string java/lang/String + (alias data object value) + (alias length uint32_t count) + (alias hashCode uint32_t hash) + (polyfill uint32_t offset) + (polyfill uint32_t length)) + +(type thread java/lang/Thread + (require object sleepLock) + (require object interruptLock) + (require uint8_t interrupted) + (require uint8_t unparked) + (alias peer uint64_t eetop) + (alias peer uint64_t nativePeer) + (require uint64_t peer)) + +(type threadGroup java/lang/ThreadGroup) + +(type stackTraceElement java/lang/StackTraceElement) + +(type throwable java/lang/Throwable + (alias message string detailMessage) + (alias trace object backtrace) + (alias trace object stackState)) + +(type exception java/lang/Exception) + +(type runtimeException java/lang/RuntimeException) + +(type nullPointerException java/lang/NullPointerException) + +(type arithmeticException java/lang/ArithmeticException) + +(type illegalStateException java/lang/IllegalStateException) + +(type illegalArgumentException java/lang/IllegalArgumentException) + +(type illegalMonitorStateException java/lang/IllegalMonitorStateException) + +(type indexOutOfBoundsException java/lang/IndexOutOfBoundsException) + +(type arrayIndexOutOfBoundsException java/lang/ArrayIndexOutOfBoundsException) + +(type arrayStoreException java/lang/ArrayStoreException) + +(type negativeArraySizeException java/lang/NegativeArraySizeException) + +(type cloneNotSupportedException java/lang/CloneNotSupportedException) + +(type reflectiveOperationException java/lang/ReflectiveOperationException) + +(type classCastException java/lang/ClassCastException) + +(type classNotFoundException java/lang/ClassNotFoundException) + +(type invocationTargetException java/lang/reflect/InvocationTargetException) + +(type interruptedException java/lang/InterruptedException) + +(type error java/lang/Error) + +(type virtualMachineError java/lang/VirtualMachineError) + +(type outOfMemoryError java/lang/OutOfMemoryError) + +(type stackOverflowError java/lang/StackOverflowError) + +(type linkageError java/lang/LinkageError) + +(type incompatibleClassChangeError java/lang/IncompatibleClassChangeError) + +(type abstractMethodError java/lang/AbstractMethodError) + +(type noSuchFieldError java/lang/NoSuchFieldError) + +(type noSuchMethodError java/lang/NoSuchMethodError) + +(type noClassDefFoundError java/lang/NoClassDefFoundError) + +(type unsatisfiedLinkError java/lang/UnsatisfiedLinkError) + +(type exceptionInInitializerError java/lang/ExceptionInInitializerError) + +(type ioException java/io/IOException) + +(type fileNotFoundException java/io/FileNotFoundException) + +(type incompatibleContinuationException + avian/IncompatibleContinuationException) + +(type number java/lang/Number) + +(type byte java/lang/Byte) + +(type boolean java/lang/Boolean) + +(type short java/lang/Short) + +(type char java/lang/Character) + +(type int java/lang/Integer) + +(type long java/lang/Long) + +(type float java/lang/Float) + +(type double java/lang/Double) + +(type referenceQueue java/lang/ref/ReferenceQueue + (alias front jreference head) + (require object jnext)) + +(type jreference java/lang/ref/Reference + (alias target object referent) + (alias queue referenceQueue queue) + (alias jNext jreference next) + (alias jNext jreference queueNext) + (alias vmNext object discovered) + (alias vmNext object pendingNext) + (nogc object target) + (nogc object queue) + (nogc object vmNext)) + +(type weakReference java/lang/ref/WeakReference) + +(type softReference java/lang/ref/SoftReference) + +(type phantomReference java/lang/ref/PhantomReference) + +(type cleaner sun/misc/Cleaner + (cleaner queueNext)) + +(type byteArray [B + (extends jobject) + (array int8_t body)) + +(type reference + (uint8_t kind) + (byteArray class) + (byteArray name) + (byteArray spec)) + +(type finder + (void* finder) + (byteArray name) + (finder next)) + +(type booleanArray [Z + (extends jobject) + (array uint8_t body)) + +(type shortArray [S + (extends jobject) + (array int16_t body)) + +(type charArray [C + (extends jobject) + (array uint16_t body)) + +(type intArray [I + (extends jobject) + (array int32_t body)) + +(type code avian/Code + (singleton pool) + (intArray stackMap) + (object exceptionHandlerTable) + (lineNumberTable lineNumberTable) + (intptr_t compiled) + (uint32_t compiledSize) + (uint16_t maxStack) + (uint16_t maxLocals) + (array uint8_t body)) + +(type longArray [J + (extends jobject) + (array int64_t body)) + +(type floatArray [F + (extends jobject) + (array uint32_t body)) + +(type doubleArray [D + (extends jobject) + (array uint64_t body)) + +(type jbyte + (extends jobject)) + +(type jboolean + (extends jobject)) + +(type jshort + (extends jobject)) + +(type jchar + (extends jobject)) + +(type jint + (extends jobject)) + +(type jlong + (extends jobject)) + +(type jfloat + (extends jobject)) + +(type jdouble + (extends jobject)) + +(type jvoid + (extends jobject)) + +(type roots + (classLoader bootLoader) + (classLoader appLoader) + (hashMap bootstrapClassMap) + (hashMap packageMap) + (method findLoadedClassMethod) + (method loadClassMethod) + (hashMap monitorMap) + (hashMap stringMap) + (hashMap byteArrayMap) + (hashMap poolMap) + (vector classRuntimeDataTable) + (vector methodRuntimeDataTable) + (vector jNIMethodTable) + (vector jNIFieldTable) + (pair shutdownHooks) + (thread finalizerThread) + (finalizer objectsToFinalize) + (cleaner objectsToClean) + (throwable nullPointerException) + (throwable arithmeticException) + (throwable arrayIndexOutOfBoundsException) + (throwable outOfMemoryError) + (throwable shutdownInProgress) + (finder virtualFileFinders) + (field array virtualFiles) + (field array arrayInterfaceTable) + (object threadTerminated) + (field array invocations)) + +(type compileRoots + (field array callTable) + (treeNode methodTree) + (treeNode methodTreeSentinal) + (object objectPools) + (object staticTableArray) + (wordArray virtualThunks) + (wordArray dynamicThunks) + (method receiveMethod) + (method windMethod) + (method rewindMethod)) diff --git a/sgx-jvm/avian/src/util.cpp b/sgx-jvm/avian/src/util.cpp new file mode 100644 index 0000000000..9b2e31d3ff --- /dev/null +++ b/sgx-jvm/avian/src/util.cpp @@ -0,0 +1,604 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#include "avian/util.h" +#include + +using namespace vm; + +namespace { + +class TreeContext { + public: + class MyProtector : public Thread::Protector { + public: + MyProtector(Thread* thread, TreeContext* context) + : Protector(thread), context(context) + { + } + + virtual void visit(Heap::Visitor* v) + { + v->visit(&(context->root)); + v->visit(&(context->node)); + + for (List* p = context->ancestors; p; p = p->next) { + v->visit(&(p->item)); + } + } + + TreeContext* context; + }; + + TreeContext(Thread* thread, Zone* zone) + : zone(zone), + root(0), + node(0), + ancestors(0), + protector(thread, this), + fresh(false) + { + } + + Zone* zone; + GcTreeNode* root; + GcTreeNode* node; + List* ancestors; + MyProtector protector; + bool fresh; +}; + +List* path(TreeContext* c, + GcTreeNode* node, + List* next) +{ + return new (c->zone) List(node, next); +} + +inline object getTreeNodeValue(Thread*, GcTreeNode* n) +{ + return reinterpret_cast(alias(n, TreeNodeValue) & PointerMask); +} + +inline void setTreeNodeValue(Thread* t, GcTreeNode* n, object value) +{ + intptr_t red = alias(n, TreeNodeValue) & (~PointerMask); + + n->setValue(t, value); + + alias(n, TreeNodeValue) |= red; +} + +inline bool treeNodeRed(Thread*, GcTreeNode* n) +{ + return (alias(n, TreeNodeValue) & (~PointerMask)) == 1; +} + +inline void setTreeNodeRed(Thread*, GcTreeNode* n, bool red) +{ + if (red) { + alias(n, TreeNodeValue) |= 1; + } else { + alias(n, TreeNodeValue) &= PointerMask; + } +} + +inline GcTreeNode* cloneTreeNode(Thread* t, GcTreeNode* n) +{ + PROTECT(t, n); + + GcTreeNode* newNode + = makeTreeNode(t, getTreeNodeValue(t, n), n->left(), n->right()); + setTreeNodeRed(t, newNode, treeNodeRed(t, n)); + return newNode; +} + +GcTreeNode* treeFind(Thread* t, + GcTreeNode* tree, + intptr_t key, + GcTreeNode* sentinal, + intptr_t (*compare)(Thread* t, intptr_t key, object b)) +{ + GcTreeNode* node = tree; + while (node != sentinal) { + intptr_t difference = compare(t, key, getTreeNodeValue(t, node)); + if (difference < 0) { + node = node->left(); + } else if (difference > 0) { + node = node->right(); + } else { + return node; + } + } + + return 0; +} + +void treeFind(Thread* t, + TreeContext* c, + GcTreeNode* old, + intptr_t key, + GcTreeNode* node, + GcTreeNode* sentinal, + intptr_t (*compare)(Thread* t, intptr_t key, object b)) +{ + PROTECT(t, old); + PROTECT(t, node); + PROTECT(t, sentinal); + + GcTreeNode* newRoot = cloneTreeNode(t, old); + PROTECT(t, newRoot); + + GcTreeNode* new_ = newRoot; + PROTECT(t, new_); + + int count = 0; + while (old != sentinal) { + c->ancestors = path(c, new_, c->ancestors); + + intptr_t difference = compare(t, key, getTreeNodeValue(t, old)); + + if (difference < 0) { + old = old->left(); + GcTreeNode* n = cloneTreeNode(t, old); + new_->setLeft(t, n); + new_ = n; + } else if (difference > 0) { + old = old->right(); + GcTreeNode* n = cloneTreeNode(t, old); + new_->setRight(t, n); + new_ = n; + } else { + c->fresh = false; + c->root = newRoot; + c->node = new_; + c->ancestors = c->ancestors->next; + return; + } + + if (++count > 100) { + // if we've gone this deep, we probably have an unbalanced tree, + // which should only happen if there's a serious bug somewhere + // in our insertion process + abort(t); + } + } + + setTreeNodeValue(t, new_, getTreeNodeValue(t, node)); + + c->fresh = true; + c->root = newRoot; + c->node = new_; + c->ancestors = c->ancestors; +} + +GcTreeNode* leftRotate(Thread* t, GcTreeNode* n) +{ + PROTECT(t, n); + + GcTreeNode* child = cloneTreeNode(t, n->right()); + n->setRight(t, child->left()); + child->setLeft(t, n); + return child; +} + +GcTreeNode* rightRotate(Thread* t, GcTreeNode* n) +{ + PROTECT(t, n); + + GcTreeNode* child = cloneTreeNode(t, n->left()); + n->setLeft(t, child->right()); + child->setRight(t, n); + return child; +} + +GcTreeNode* treeAdd(Thread* t, TreeContext* c) +{ + GcTreeNode* new_ = c->node; + PROTECT(t, new_); + + GcTreeNode* newRoot = c->root; + PROTECT(t, newRoot); + + // rebalance + setTreeNodeRed(t, new_, true); + while (c->ancestors != 0 and treeNodeRed(t, c->ancestors->item)) { + if (c->ancestors->item == c->ancestors->next->item->left()) { + if (treeNodeRed(t, c->ancestors->next->item->right())) { + setTreeNodeRed(t, c->ancestors->item, false); + + GcTreeNode* n = cloneTreeNode(t, c->ancestors->next->item->right()); + + c->ancestors->next->item->setRight(t, n); + + setTreeNodeRed(t, c->ancestors->next->item->right(), false); + + setTreeNodeRed(t, c->ancestors->next->item, true); + + new_ = c->ancestors->next->item; + c->ancestors = c->ancestors->next->next; + } else { + if (new_ == c->ancestors->item->right()) { + new_ = c->ancestors->item; + c->ancestors = c->ancestors->next; + + GcTreeNode* n = leftRotate(t, new_); + + if (new_ == c->ancestors->item->right()) { + c->ancestors->item->setRight(t, n); + } else { + c->ancestors->item->setLeft(t, n); + } + c->ancestors = path(c, n, c->ancestors); + } + setTreeNodeRed(t, c->ancestors->item, false); + setTreeNodeRed(t, c->ancestors->next->item, true); + + GcTreeNode* n = rightRotate(t, c->ancestors->next->item); + if (c->ancestors->next->next == 0) { + newRoot = n; + } else if (c->ancestors->next->next->item->right() + == c->ancestors->next->item) { + c->ancestors->next->next->item->setRight(t, n); + } else { + c->ancestors->next->next->item->setLeft(t, n); + } + // done + } + } else { // this is just the reverse of the code above (right and + // left swapped): + if (treeNodeRed(t, c->ancestors->next->item->left())) { + setTreeNodeRed(t, c->ancestors->item, false); + + GcTreeNode* n = cloneTreeNode(t, c->ancestors->next->item->left()); + + c->ancestors->next->item->setLeft(t, n); + + setTreeNodeRed(t, c->ancestors->next->item->left(), false); + + setTreeNodeRed(t, c->ancestors->next->item, true); + + new_ = c->ancestors->next->item; + c->ancestors = c->ancestors->next->next; + } else { + if (new_ == c->ancestors->item->left()) { + new_ = c->ancestors->item; + c->ancestors = c->ancestors->next; + + GcTreeNode* n = rightRotate(t, new_); + + if (new_ == c->ancestors->item->left()) { + c->ancestors->item->setLeft(t, n); + } else { + c->ancestors->item->setRight(t, n); + } + c->ancestors = path(c, n, c->ancestors); + } + setTreeNodeRed(t, c->ancestors->item, false); + setTreeNodeRed(t, c->ancestors->next->item, true); + + GcTreeNode* n = leftRotate(t, c->ancestors->next->item); + if (c->ancestors->next->next == 0) { + newRoot = n; + } else if (c->ancestors->next->next->item->left() + == c->ancestors->next->item) { + c->ancestors->next->next->item->setLeft(t, n); + } else { + c->ancestors->next->next->item->setRight(t, n); + } + // done + } + } + } + + setTreeNodeRed(t, newRoot, false); + + return newRoot; +} + +} // namespace + +namespace vm { + +GcTriple* hashMapFindNode(Thread* t, + GcHashMap* map, + object key, + uint32_t (*hash)(Thread*, object), + bool (*equal)(Thread*, object, object)) +{ + bool weak = objectClass(t, map) == type(t, GcWeakHashMap::Type); + + GcArray* array = map->array(); + if (array) { + unsigned index = hash(t, key) & (array->length() - 1); + for (GcTriple* n = cast(t, array->body()[index]); n; + n = cast(t, n->third())) { + object k = n->first(); + if (weak) { + k = cast(t, k)->target(); + if (k == 0) { + continue; + } + } + + if (equal(t, key, k)) { + return n; + } + } + } + return 0; +} + +void hashMapResize(Thread* t, + GcHashMap* map, + uint32_t (*hash)(Thread*, object), + unsigned size) +{ + PROTECT(t, map); + + GcArray* newArray = 0; + + if (size) { + GcArray* oldArray = map->array(); + PROTECT(t, oldArray); + + unsigned newLength = nextPowerOfTwo(size); + if (oldArray and oldArray->length() == newLength) { + return; + } + + newArray = makeArray(t, newLength); + + if (oldArray != map->array()) { + // a resize was performed during a GC via the makeArray call + // above; nothing left to do + return; + } + + if (oldArray) { + bool weak = objectClass(t, map) == type(t, GcWeakHashMap::Type); + for (unsigned i = 0; i < oldArray->length(); ++i) { + GcTriple* next; + for (GcTriple* p = cast(t, oldArray->body()[i]); p; + p = next) { + next = cast(t, p->third()); + + object k = p->first(); + if (weak) { + k = cast(t, k)->target(); + if (k == 0) { + continue; + } + } + + unsigned index = hash(t, k) & (newLength - 1); + + p->setThird(t, newArray->body()[index]); + newArray->setBodyElement(t, index, p); + } + } + } + } + + map->setArray(t, newArray); +} + +void hashMapInsert(Thread* t, + GcHashMap* map, + object key, + object value, + uint32_t (*hash)(Thread*, object)) +{ + // note that we reinitialize the array variable whenever an + // allocation (and thus possibly a collection) occurs, in case the + // array changes due to a table resize. + + PROTECT(t, map); + + uint32_t h = hash(t, key); + + bool weak = objectClass(t, map) == type(t, GcWeakHashMap::Type); + + GcArray* array = map->array(); + + ++map->size(); + + if (array == 0 or map->size() >= array->length() * 2) { + PROTECT(t, key); + PROTECT(t, value); + + hashMapResize(t, map, hash, array ? array->length() * 2 : 16); + + array = map->array(); + } + + object k = key; + + if (weak) { + PROTECT(t, key); + PROTECT(t, value); + + GcWeakReference* r = makeWeakReference(t, 0, 0, 0, 0); + + r->setTarget(t, key); + r->setVmNext(t, t->m->weakReferences); + t->m->weakReferences = r->as(t); + k = r; + + array = map->array(); + } + + GcTriple* n = makeTriple(t, k, value, 0); + + array = map->array(); + + unsigned index = h & (array->length() - 1); + + n->setThird(t, array->body()[index]); + array->setBodyElement(t, index, n); + + if (map->size() <= array->length() / 3) { + // this might happen if nodes were removed during GC in which case + // we weren't able to resize at the time + hashMapResize(t, map, hash, array->length() / 2); + } +} + +GcTriple* hashMapRemoveNode(Thread* t, + GcHashMap* map, + unsigned index, + GcTriple* p, + GcTriple* n) +{ + if (p) { + p->setThird(t, n->third()); + } else { + map->array()->setBodyElement(t, index, n->third()); + } + --map->size(); + return n; +} + +object hashMapRemove(Thread* t, + GcHashMap* map, + object key, + uint32_t (*hash)(Thread*, object), + bool (*equal)(Thread*, object, object)) +{ + bool weak = objectClass(t, map) == type(t, GcWeakHashMap::Type); + + GcArray* array = map->array(); + object o = 0; + if (array) { + unsigned index = hash(t, key) & (array->length() - 1); + GcTriple* p = 0; + for (GcTriple* n = cast(t, array->body()[index]); n;) { + object k = n->first(); + if (weak) { + k = cast(t, k)->target(); + if (k == 0) { + n = cast(t, + hashMapRemoveNode(t, map, index, p, n)->third()); + continue; + } + } + + if (equal(t, key, k)) { + o = hashMapRemoveNode(t, map, index, p, n)->second(); + break; + } else { + p = n; + n = cast(t, n->third()); + } + } + + if ((not t->m->collecting) and map->size() <= array->length() / 3) { + PROTECT(t, o); + hashMapResize(t, map, hash, array->length() / 2); + } + } + + return o; +} + +void listAppend(Thread* t, GcList* list, object value) +{ + PROTECT(t, list); + + ++list->size(); + + object p = makePair(t, value, 0); + if (list->front()) { + cast(t, list->rear())->setSecond(t, p); + } else { + list->setFront(t, p); + } + list->setRear(t, p); +} + +GcVector* vectorAppend(Thread* t, GcVector* vector, object value) +{ + if (vector->length() == vector->size()) { + PROTECT(t, vector); + PROTECT(t, value); + + GcVector* newVector + = makeVector(t, vector->size(), max(16, vector->size() * 2)); + + if (vector->size()) { + for (size_t i = 0; i < vector->size(); i++) { + newVector->setBodyElement(t, i, vector->body()[i]); + } + } + + vector = newVector; + } + + vector->setBodyElement(t, vector->size(), value); + ++vector->size(); + return vector; +} + +GcArray* growArray(Thread* t, GcArray* array) +{ + PROTECT(t, array); + + GcArray* newArray = makeArray(t, array == 0 ? 16 : (array->length() * 2)); + + if (array) { + for (size_t i = 0; i < array->length(); i++) { + newArray->setBodyElement(t, i, array->body()[i]); + } + } + + return newArray; +} + +object treeQuery(Thread* t, + GcTreeNode* tree, + intptr_t key, + GcTreeNode* sentinal, + intptr_t (*compare)(Thread* t, intptr_t key, object b)) +{ + GcTreeNode* node = treeFind(t, tree, key, sentinal, compare); + return (node ? getTreeNodeValue(t, node) : 0); +} + +GcTreeNode* treeInsert(Thread* t, + Zone* zone, + GcTreeNode* tree, + intptr_t key, + object value, + GcTreeNode* sentinal, + intptr_t (*compare)(Thread* t, intptr_t key, object b)) +{ + PROTECT(t, tree); + PROTECT(t, sentinal); + + GcTreeNode* node = makeTreeNode(t, value, sentinal, sentinal); + + TreeContext c(t, zone); + treeFind(t, &c, tree, key, node, sentinal, compare); + expect(t, c.fresh); + + return treeAdd(t, &c); +} + +void treeUpdate(Thread* t, + GcTreeNode* tree, + intptr_t key, + object value, + GcTreeNode* sentinal, + intptr_t (*compare)(Thread* t, intptr_t key, object b)) +{ + setTreeNodeValue(t, treeFind(t, tree, key, sentinal, compare), value); +} + +} // namespace vm diff --git a/sgx-jvm/avian/src/util/CMakeLists.txt b/sgx-jvm/avian/src/util/CMakeLists.txt new file mode 100644 index 0000000000..d4311a7b7f --- /dev/null +++ b/sgx-jvm/avian/src/util/CMakeLists.txt @@ -0,0 +1 @@ +add_library(avian_util arg-parser.cpp fixed-allocator.cpp) \ No newline at end of file diff --git a/sgx-jvm/avian/src/util/arg-parser.cpp b/sgx-jvm/avian/src/util/arg-parser.cpp new file mode 100644 index 0000000000..50493d44fb --- /dev/null +++ b/sgx-jvm/avian/src/util/arg-parser.cpp @@ -0,0 +1,101 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#include +#include + +#include +#include + +namespace avian { +namespace util { + +Arg::Arg(ArgParser& parser, bool required, const char* name, const char* desc) + : next(0), required(required), name(name), desc(desc), value(0) +{ + *parser.last = this; + parser.last = &next; +} + +ArgParser::ArgParser() : first(0), last(&first) +{ +} + +bool ArgParser::parse(int ac, const char* const* av) +{ + Arg* state = 0; + + for (int i = 1; i < ac; i++) { + if (state) { + if (state->value) { + fprintf(stderr, + "duplicate parameter %s: '%s' and '%s'\n", + state->name, + state->value, + av[i]); + return false; + } + state->value = av[i]; + state = 0; + } else { + if (av[i][0] != '-') { + fprintf(stderr, "expected -parameter\n"); + return false; + } + bool found = false; + for (Arg* arg = first; arg; arg = arg->next) { + if (strcmp(arg->name, &av[i][1]) == 0) { + found = true; + if (arg->desc == 0) { + arg->value = "true"; + } else { + state = arg; + } + } + } + if (not found) { + fprintf(stderr, "unrecognized parameter %s\n", av[i]); + return false; + } + } + } + + if (state) { + fprintf(stderr, "expected argument after -%s\n", state->name); + return false; + } + + for (Arg* arg = first; arg; arg = arg->next) { + if (arg->required && !arg->value) { + fprintf(stderr, "expected value for %s\n", arg->name); + return false; + } + } + + return true; +} + +void ArgParser::printUsage(const char* exe) +{ + fprintf(stderr, "usage:\n%s \\\n", exe); + for (Arg* arg = first; arg; arg = arg->next) { + const char* lineEnd = arg->next ? " \\" : ""; + if (arg->required) { + fprintf(stderr, " -%s\t%s%s\n", arg->name, arg->desc, lineEnd); + } else if (arg->desc) { + fprintf(stderr, " [-%s\t%s]%s\n", arg->name, arg->desc, lineEnd); + } else { + fprintf(stderr, " [-%s]%s\n", arg->name, lineEnd); + } + } +} + +} // namespace util +} // namespace avian diff --git a/sgx-jvm/avian/src/util/fixed-allocator.cpp b/sgx-jvm/avian/src/util/fixed-allocator.cpp new file mode 100644 index 0000000000..bc87e6d1c0 --- /dev/null +++ b/sgx-jvm/avian/src/util/fixed-allocator.cpp @@ -0,0 +1,54 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#include + +#include + +namespace avian { +namespace util { + +FixedAllocator::FixedAllocator(Aborter* a, Slice memory) + : a(a), memory(memory), offset(0) +{ +} + +void* FixedAllocator::tryAllocate(size_t size) +{ + return allocate(size); +} + +void* FixedAllocator::allocate(size_t size, unsigned padAlignment) +{ + size_t paddedSize = vm::pad(size, padAlignment); + expect(a, offset + paddedSize < memory.count); + + void* p = memory.begin() + offset; + offset += paddedSize; + return p; +} + +void* FixedAllocator::allocate(size_t size) +{ + return allocate(size, vm::BytesPerWord); +} + +void FixedAllocator::free(const void* p, size_t size) +{ + if (p >= memory.begin() + and static_cast(p) + size == memory.begin() + offset) { + offset -= size; + } else { + abort(a); + } +} + +} // namespace util +} // namespace avian diff --git a/sgx-jvm/avian/src/x86_64.S b/sgx-jvm/avian/src/x86_64.S new file mode 100644 index 0000000000..501b8982f1 --- /dev/null +++ b/sgx-jvm/avian/src/x86_64.S @@ -0,0 +1,340 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#include "avian/types.h" + +#define LOCAL(x) .L##x + +#if defined __APPLE__ \ + || ((defined __MINGW32__ || defined __CYGWIN32__) && ! defined __x86_64__) +# define GLOBAL(x) _##x +#else +# define GLOBAL(x) x +#endif + +.text + +#define CHECKPOINT_THREAD 8 +#define CHECKPOINT_STACK 48 + +#ifdef __MINGW32__ + +.globl GLOBAL(vmNativeCall) +GLOBAL(vmNativeCall): + pushq %rbp + //save nonvolatile registers + pushq %r12 + pushq %r13 + pushq %r14 + pushq %r15 + movq %rsp, %rbp + + + // %rcx: function + // %rdx: arguments + // %r8: arguments count + // %r9: return type + + movq %rcx, %r10 + movq %rdx, %r11 + movq %r8, %r12 + movq %r9, %r13 + + // %r10: function + // %r11: arguments + // %r12: arguments count + // %r13: return type + + //allocate initial stack space + subq $32, %rsp + + //first arg + cmp $0, %r12 + je LOCAL(call) + movq 0(%r11),%rcx + movq 0(%r11),%xmm0 + subq $1, %r12 + + //second arg + cmp $0, %r12 + je LOCAL(call) + movq 8(%r11),%rdx + movq 8(%r11),%xmm1 + subq $1, %r12 + + //third arg + cmp $0, %r12 + je LOCAL(call) + movq 16(%r11),%r8 + movq 16(%r11),%xmm2 + subq $1, %r12 + + //fourth arg + cmp $0, %r12 + je LOCAL(call) + movq 24(%r11),%r9 + movq 24(%r11),%xmm3 + subq $1, %r12 + + + //calculate stack space for arguments, aligned + movq $8, %r15 + leaq (%r15, %r12, 8), %r15 + andq $0xFFFFFFFFFFFFFFF0, %r15 + + //reserve stack space for arguments + subq %r15, %rsp + + //reset the counter + addq $3, %r12 + jmp LOCAL(loopend) + +LOCAL(loop): + movq (%r11, %r12, 8), %r14 + movq %r14, (%rsp, %r12, 8); + subq $1, %r12 + +LOCAL(loopend): + //we don't need to move arg 3 and lower + cmpq $3, %r12 + jne LOCAL(loop) + +LOCAL(call): + call *%r10 + +LOCAL(void): + cmpq $VOID_TYPE,%r13 + jne LOCAL(float) + jmp LOCAL(exit) + +LOCAL(float): + cmpq $FLOAT_TYPE,%r13 + je LOCAL(copy) + cmpq $DOUBLE_TYPE,%r13 + jne LOCAL(exit) + +LOCAL(copy): + movq %xmm0,%rax + +LOCAL(exit): + + movq %rbp, %rsp + //return nonvolatile registers to their former state + popq %r15 + popq %r14 + popq %r13 + popq %r12 + + popq %rbp + ret + +.globl GLOBAL(vmJump) +GLOBAL(vmJump): + movq %rdx,%rbp + movq 40(%rsp),%rax + movq 48(%rsp),%rdx + movq %r8,%rsp + movq %r9,%rbx + jmp *%rcx + +#define VMRUN_FRAME_SIZE 80 + +.globl GLOBAL(vmRun) +GLOBAL(vmRun): + // %rcx: function + // %rdx: arguments + // %r8 : checkpoint + pushq %rbp + movq %rsp,%rbp + subq $VMRUN_FRAME_SIZE,%rsp + + movq %rbx,16(%rsp) + movq %r12,24(%rsp) + movq %r13,32(%rsp) + movq %r14,40(%rsp) + movq %r15,48(%rsp) + movq %rsi,56(%rsp) + movq %rdi,64(%rsp) + + movq %rsp,CHECKPOINT_STACK(%r8) + + movq %rcx,%r11 + movq CHECKPOINT_THREAD(%r8),%rcx + + call *%r11 + +.globl GLOBAL(vmRun_returnAddress) +GLOBAL(vmRun_returnAddress): + + movq 16(%rsp),%rbx + movq 24(%rsp),%r12 + movq 32(%rsp),%r13 + movq 40(%rsp),%r14 + movq 48(%rsp),%r15 + movq 56(%rsp),%rsi + movq 64(%rsp),%rdi + + addq $VMRUN_FRAME_SIZE,%rsp + popq %rbp + ret + +#else // not __MINGW32__ + +.globl GLOBAL(vmNativeCall) +GLOBAL(vmNativeCall): + pushq %rbp + movq %rsp,%rbp + + // %rdi aka -48(%rbp): function + // %rsi aka -40(%rbp): stack + // %rdx aka -32(%rbp): stackSize + // %rcx aka -24(%rbp): gprTable + // %r8 aka -16(%rbp): sseTable + // %r9 aka -8(%rbp): returnType + + // save our argument registers so we can clobber them + pushq %r9 + pushq %r8 + pushq %rcx + pushq %rdx + pushq %rsi + pushq %rdi + + // reserve space for arguments passed via memory + subq %rdx,%rsp + + // align to a 16 byte boundary + andq $0xFFFFFFFFFFFFFFF0,%rsp + + // copy memory arguments into place + movq $0,%rcx + jmp LOCAL(test) + +LOCAL(loop): + movq %rcx,%rax + movq %rcx,%rdx + addq %rsp,%rdx + addq -40(%rbp),%rax + movq (%rax),%rax + movq %rax,(%rdx) + addq $8,%rcx + +LOCAL(test): + cmpq -32(%rbp),%rcx + jb LOCAL(loop) + + // do we need to load the general-purpose registers? + cmpq $0,-24(%rbp) + je LOCAL(sse) + + // yes, we do + movq -24(%rbp),%rax + movq 0(%rax),%rdi + movq 8(%rax),%rsi + movq 16(%rax),%rdx + movq 24(%rax),%rcx + movq 32(%rax),%r8 + movq 40(%rax),%r9 + +LOCAL(sse): + // do we need to load the SSE registers? + cmpq $0,-16(%rbp) + je LOCAL(call) + + // yes, we do + movq -16(%rbp),%rax + movq 0(%rax),%xmm0 + movq 8(%rax),%xmm1 + movq 16(%rax),%xmm2 + movq 24(%rax),%xmm3 + movq 32(%rax),%xmm4 + movq 40(%rax),%xmm5 + movq 48(%rax),%xmm6 + movq 56(%rax),%xmm7 + +LOCAL(call): + call *-48(%rbp) + + // handle return value based on expected type + movq -8(%rbp),%rcx + +LOCAL(void): + cmpq $VOID_TYPE,%rcx + jne LOCAL(float) + jmp LOCAL(exit) + +LOCAL(float): + cmpq $FLOAT_TYPE,%rcx + je LOCAL(copy) + cmpq $DOUBLE_TYPE,%rcx + jne LOCAL(exit) + +LOCAL(copy): +#ifdef __APPLE__ + // as of OS X 10.6, Apple is still using an assembler that doesn't + // understand movq SSE,GPR, but movd does the same thing, despite + // the name + movd %xmm0,%rax +#else + movq %xmm0,%rax +#endif + +LOCAL(exit): + movq %rbp,%rsp + popq %rbp + ret + +.globl GLOBAL(vmJump) +GLOBAL(vmJump): + movq %rsi,%rbp + movq %rdx,%rsp + movq %rcx,%rbx + movq %r8,%rax + movq %r9,%rdx + jmp *%rdi + +#define VMRUN_FRAME_SIZE 64 + +.globl GLOBAL(vmRun) +GLOBAL(vmRun): + // %rdi: function + // %rsi: arguments + // %rdx: checkpoint + pushq %rbp + movq %rsp,%rbp + subq $VMRUN_FRAME_SIZE,%rsp + + movq %rbx,16(%rsp) + movq %r12,24(%rsp) + movq %r13,32(%rsp) + movq %r14,40(%rsp) + movq %r15,48(%rsp) + + movq %rsp,CHECKPOINT_STACK(%rdx) + + movq %rdi,%r11 + movq CHECKPOINT_THREAD(%rdx),%rdi + + call *%r11 + +.globl GLOBAL(vmRun_returnAddress) +GLOBAL(vmRun_returnAddress): + + movq 16(%rsp),%rbx + movq 24(%rsp),%r12 + movq 32(%rsp),%r13 + movq 40(%rsp),%r14 + movq 48(%rsp),%r15 + + addq $VMRUN_FRAME_SIZE,%rsp + popq %rbp + ret + +#endif // not __MINGW32__ diff --git a/sgx-jvm/avian/test/AllFloats.java b/sgx-jvm/avian/test/AllFloats.java new file mode 100644 index 0000000000..0bba388b9b --- /dev/null +++ b/sgx-jvm/avian/test/AllFloats.java @@ -0,0 +1,86 @@ +public class AllFloats { + private static float multiplyByFive(float a) {return 5f * a;} + private static double multiplyByFive(double a) {return 5d * a;} + private static float multiply(float a, float b) {return a * b;} + private static double multiply(double a, double b) {return a * b;} + private static double multiply(float a, double b) {return a * b;} + private static float divide(float a, float b) {return a / b;} + private static double divide(double a, double b) {return a / b;} + private static double divide(float a, double b) {return a / b;} + private static float remainder(float a, float b) {return a % b;} + private static double remainder(double a, double b) {return a % b;} + private static double remainder(float a, double b) {return a % b;} + private static float add(float a, float b) {return a + b;} + private static double add(double a, double b) {return a + b;} + private static double add(float a, double b) {return a + b;} + private static float subtract(float a, float b) {return a - b;} + private static double subtract(double a, double b) {return a - b;} + private static double subtract(float a, double b) {return a - b;} + private static float complex(float a, float b) {return (a - b) / (a * b) + (float)Math.sqrt(a);} + private static double complex(double a, double b) {return (a - b) / (a * b) + Math.sqrt(a);} + private static double complex(float a, double b) {return (a - b) / (a * b) + Math.sqrt(a);} + private static double sqrt(double a) {return Math.sqrt(a);} + private static float complexNoIntrinsic(float a, float b) {return (a - b) / (a * b) + (float)sqrt(a);} + private static int f2i(float a) {return (int)a;} + private static long f2l(float a) {return (long)a;} + private static float i2f(int a) {return (float)a;} + private static double i2d(int a) {return (double)a;} + private static int d2i(double a) {return (int)a;} + private static long d2l(double a) {return (long)a;} + private static float l2f(long a) {return (float)a;} + private static double l2d(long a) {return (double)a;} + private static float negate(float a) {return -a;} + private static double negate(double a) {return -a;} + private static int abs(int a) {return Math.abs(a);} + private static float abs(float a) {return Math.abs(a);} + + private static void expect(boolean v) { + if(!v)throw new RuntimeException(); + } + + private static int last(){return 0;} + + public static void main(String[] args) { + expect(multiplyByFive(36f) == 5f * 36f); + expect(multiplyByFive(36d) == 5d * 36d); + expect(multiply(5f, 4f) == 5f*4f); + expect(multiply(5d, 4d) == 5d*4d); + expect(multiply(5f, 4d) == 5f*4d); + expect(divide(5f, 2f) == 5f/2f); + expect(divide(5d, 2d) == 5d/2d); + expect(divide(5f, 2d) == 5f/2d); + expect(remainder(5f, 2f) == 5f%2f); + expect(remainder(5d, 2d) == 5d%2d); + expect(remainder(5f, 2d) == 5f%2d); + expect(add(5f, 4f) == 5f+4f); + expect(add(5d, 4d) == 5f+4d); + expect(add(5f, 4d) == 5f+4d); + expect(subtract(5f, 4f) == 5f-4f); + expect(subtract(5d, 4d) == 5f-4d); + expect(subtract(5f, 4d) == 5f-4d); + expect(complex(4f, 3f) == (4f-3f)/(4f*3f) + 2f); + expect(complex(4d, 3d) == (4d-3d)/(4d*3d) + 2d); + expect(complex(4f, 3d) == (4f-3d)/(4f*3d) + 2f); + expect(complexNoIntrinsic(4f, 3f) == (4f-3f)/(4f*3f) + 2f); + + expect(f2i(4f) == 4); + expect(f2l(4f) == 4); + expect(i2f(4) == 4f); + expect(i2d(4) == 4d); + + expect(d2i(4d) == 4); + expect(d2l(4d) == 4); + expect(l2f(4) == 4f); + expect(l2d(4) == 4d); + + expect(negate(4f) == -4f); + expect(negate(4d) == -4d); + + expect(abs(-4) == 4); + expect(abs(12) == 12); + expect(abs(-4f) == 4f); + expect(abs(12f) == 12f); + + int unused = last(); + } +} diff --git a/sgx-jvm/avian/test/Annotations.java b/sgx-jvm/avian/test/Annotations.java new file mode 100644 index 0000000000..f09b0251eb --- /dev/null +++ b/sgx-jvm/avian/test/Annotations.java @@ -0,0 +1,89 @@ +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; + +import avian.testing.annotations.Color; +import avian.testing.annotations.Test; +import avian.testing.annotations.TestComplex; +import avian.testing.annotations.TestEnum; +import avian.testing.annotations.TestInteger; + +public class Annotations { + private static void expect(boolean v) { + if (! v) throw new RuntimeException(); + } + + public static void main(String[] args) throws Exception { + Method m = Annotations.class.getMethod("foo"); + + expect(m.isAnnotationPresent(Test.class)); + + expect(((Test) m.getAnnotation(Test.class)).value().equals("couscous")); + + expect(((TestEnum) m.getAnnotation(TestEnum.class)).value() + .equals(Color.Red)); + + expect(((TestInteger) m.getAnnotation(TestInteger.class)).value() == 42); + + expect(m.getAnnotations().length == 3); + + Method noAnno = Annotations.class.getMethod("noAnnotation"); + expect(noAnno.getAnnotation(Test.class) == null); + expect(noAnno.getAnnotations().length == 0); + testProxyDefaultValue(); + testComplexAnnotation(); + } + + @Test("couscous") + @TestEnum(Color.Red) + @TestInteger(42) + public static void foo() { + + } + + public static void noAnnotation() { + + } + + private static void testProxyDefaultValue() { + ClassLoader loader = Annotations.class.getClassLoader(); + InvocationHandler handler = new InvocationHandler() { + public Object invoke(Object proxy, Method method, Object... args) { + return method.getDefaultValue(); + } + }; + Test test = (Test) + Proxy.newProxyInstance(loader, new Class[] { Test.class }, handler); + expect("Hello, world!".equals(test.value())); + } + + private interface World { + @TestComplex(arrayValue = { @Test, @Test(value = "7/9") }, + stringValue = "adjunct element", charValue = '7', doubleValue = 0.7778, + classValue = TestInteger.class) + int hello(); + } + + private static void testComplexAnnotation(TestComplex annotation) + throws Exception + { + expect(2 == annotation.arrayValue().length); + expect("Hello, world!".equals(annotation.arrayValue()[0].value())); + expect("7/9".equals(annotation.arrayValue()[1].value())); + expect("adjunct element".equals(annotation.stringValue())); + expect('7' == annotation.charValue()); + expect(0.7778 == annotation.doubleValue()); + expect(TestInteger.class == annotation.classValue()); + } + + public static void testComplexAnnotation() throws Exception { + ClassLoader loader = Annotations.class.getClassLoader(); + TestComplex annotation = (TestComplex) + World.class.getMethod("hello").getAnnotation(TestComplex.class); + testComplexAnnotation(annotation); + Class clazz = Proxy.getProxyClass(loader, new Class[] { World.class }); + annotation = (TestComplex) + clazz.getMethod("hello").getAnnotation(TestComplex.class); + expect(annotation == null); + } +} diff --git a/sgx-jvm/avian/test/ArrayDequeTest.java b/sgx-jvm/avian/test/ArrayDequeTest.java new file mode 100644 index 0000000000..103cda4fa3 --- /dev/null +++ b/sgx-jvm/avian/test/ArrayDequeTest.java @@ -0,0 +1,161 @@ +import java.util.ArrayDeque; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.NoSuchElementException; + +public class ArrayDequeTest { + private static void verify(boolean val) { + if (! val) { + throw new RuntimeException(); + } + } + + public static void main(String[] args) throws InterruptedException { + QueueHelper.sizeTest(new ArrayDeque()); + QueueHelper.isEmptyTest(new ArrayDeque()); + QueueHelper.addTest(new ArrayDeque()); + QueueHelper.addAllTest(new ArrayDeque()); + QueueHelper.elementTest(new ArrayDeque()); + QueueHelper.elementFail(new ArrayDeque()); + QueueHelper.removeEmptyFail(new ArrayDeque()); + QueueHelper.removeTest(new ArrayDeque()); + QueueHelper.containsTest(new ArrayDeque()); + QueueHelper.containsAllTest(new ArrayDeque()); + QueueHelper.removeObjectTest(new ArrayDeque()); + QueueHelper.removeAllTest(new ArrayDeque()); + QueueHelper.clearTest(new ArrayDeque()); + QueueHelper.toArrayTest(new ArrayDeque()); + + DequeHelper.addFirstTest(new ArrayDeque()); + DequeHelper.addLastTest(new ArrayDeque()); + DequeHelper.removeFirstTest(new ArrayDeque()); + DequeHelper.removeLastTest(new ArrayDeque()); + + iterateTest(false); + iterateTest(true); + iteratorRemoveTest(false); + iteratorRemoveTest(true); + iteratorNoElementFail(false); + iteratorNoElementFail(true); + } + + private static void iterateTest(boolean desc) { + int testQty = 10; + LinkedList compareList = new LinkedList(); + ArrayDeque ad = new ArrayDeque(); + + for (int i = 0; i < testQty; i++) { + Object o = new Object(); + compareList.add(o); + ad.add(o); + } + + Iterator compIt; + Iterator testIt; + if (desc) { + compIt = compareList.descendingIterator(); + testIt = ad.descendingIterator(); + } else { + compIt = compareList.iterator(); + testIt = ad.iterator(); + } + while (testIt.hasNext()) { + verify(testIt.next() == compIt.next()); + } + + // remove from the front + compareList.removeFirst(); + ad.removeFirst(); + + if (desc) { + compIt = compareList.descendingIterator(); + testIt = ad.descendingIterator(); + } else { + compIt = compareList.iterator(); + testIt = ad.iterator(); + } + while (testIt.hasNext()) { + verify(testIt.next() == compIt.next()); + } + + // remove from the end + compareList.removeLast(); + ad.removeLast(); + + if (desc) { + compIt = compareList.descendingIterator(); + testIt = ad.descendingIterator(); + } else { + compIt = compareList.iterator(); + testIt = ad.iterator(); + } + while (testIt.hasNext()) { + verify(testIt.next() == compIt.next()); + } + } + + private static void iteratorRemoveTest(boolean desc) { + int testQty = 20; + LinkedList compareList = new LinkedList(); + ArrayDeque ad = new ArrayDeque(); + + for (int i = 0; i < testQty; i++) { + Object o = new Object(); + compareList.add(o); + ad.add(o); + } + + Iterator compIt; + Iterator testIt; + if (desc) { + compIt = compareList.descendingIterator(); + testIt = ad.descendingIterator(); + } else { + compIt = compareList.iterator(); + testIt = ad.iterator(); + } + boolean flip = true; // start with true to ensure first is removed + while (testIt.hasNext()) { + // advance iterators + testIt.next(); + compIt.next(); + + if (flip || ! testIt.hasNext()) { + compIt.remove(); + testIt.remove(); + flip = false; + } else { + flip = true; + } + } + + if (desc) { + compIt = compareList.descendingIterator(); + testIt = ad.descendingIterator(); + } else { + compIt = compareList.iterator(); + testIt = ad.iterator(); + } + while (testIt.hasNext()) { + verify(testIt.next() == compIt.next()); + } + } + + private static void iteratorNoElementFail(boolean desc) { + ArrayDeque ad = new ArrayDeque(); + + Iterator testIt; + if (desc) { + testIt = ad.descendingIterator(); + } else { + testIt = ad.iterator(); + } + + try { + testIt.next(); + throw new RuntimeException("Exception should have thrown"); + } catch (NoSuchElementException e) { + // expected + } + } +} diff --git a/sgx-jvm/avian/test/ArraysTest.java b/sgx-jvm/avian/test/ArraysTest.java new file mode 100644 index 0000000000..cd008065b6 --- /dev/null +++ b/sgx-jvm/avian/test/ArraysTest.java @@ -0,0 +1,174 @@ +import java.util.Arrays; + +public class ArraysTest { + private static void expect(boolean v) { + if (! v) throw new RuntimeException(); + } + + private static > void expectSorted(T[] array) { + for (int i = 1; i < array.length; ++i) { + expect(array[i - 1].compareTo(array[i]) <= 0); + } + } + + private static int pseudoRandom(int seed) { + return 3170425 * seed + 132102; + } + + private static > int shuffle(T[] array, int seed) { + for (int i = array.length; i > 1; --i) { + int i2 = (seed < 0 ? -seed : seed) % i; + T value = array[i - 1]; + array[i - 1] = array[i2]; + array[i2] = value; + seed = pseudoRandom(seed); + } + return seed; + } + + public static void testSort() { + Integer[] array = new Integer[64]; + for (int i = 0; i < array.length; ++i) { + array[i] = Integer.valueOf(i + 1); + } + ; + int random = 12345; + for (int i = 0; i < 32; ++i) { + random = shuffle(array, random); + Arrays.sort(array); + expectSorted(array); + } + } + + public static void main(String[] args) { + { int[] array = new int[0]; + Exception exception = null; + try { + int x = array[0]; + } catch (ArrayIndexOutOfBoundsException e) { + exception = e; + } + + expect(exception != null); + } + + { int[] array = new int[0]; + Exception exception = null; + try { + int x = array[-1]; + } catch (ArrayIndexOutOfBoundsException e) { + exception = e; + } + + expect(exception != null); + } + + { int[] array = new int[3]; + int i = 0; + array[i++] = 1; + array[i++] = 2; + array[i++] = 3; + + expect(array[--i] == 3); + expect(array[--i] == 2); + expect(array[--i] == 1); + } + + { Object[][] array = new Object[1][1]; + expect(array.length == 1); + expect(array[0].length == 1); + } + + { Object[][] array = new Object[2][3]; + expect(array.length == 2); + expect(array[0].length == 3); + } + + { int j = 0; + byte[] decodeTable = new byte[256]; + for (int i = 'A'; i <= 'Z'; ++i) decodeTable[i] = (byte) j++; + for (int i = 'a'; i <= 'z'; ++i) decodeTable[i] = (byte) j++; + for (int i = '0'; i <= '9'; ++i) decodeTable[i] = (byte) j++; + decodeTable['+'] = (byte) j++; + decodeTable['/'] = (byte) j++; + decodeTable['='] = 0; + + expect(decodeTable['a'] != 0); + } + + { boolean p = true; + int[] array = new int[] { 1, 2 }; + expect(array[0] == array[p ? 0 : 1]); + p = false; + expect(array[1] == array[p ? 0 : 1]); + } + + { int[] array = new int[1024]; + array[1023] = -1; + expect(array[1023] == -1); + expect(array[1022] == 0); + } + + { Integer[] array = (Integer[]) + java.lang.reflect.Array.newInstance(Integer.class, 1); + array[0] = Integer.valueOf(42); + expect(array[0].intValue() == 42); + } + + { Object[] a = new Object[3]; + Object[] b = new Object[3]; + + expect(Arrays.equals(a, b)); + a[0] = new Object(); + expect(! Arrays.equals(a, b)); + expect(! Arrays.equals(b, new Object[4])); + expect(! Arrays.equals(a, null)); + expect(! Arrays.equals(null, b)); + expect(Arrays.equals((Object[])null, (Object[])null)); + b[0] = a[0]; + expect(Arrays.equals(a, b)); + + Arrays.hashCode(a); + Arrays.hashCode((Object[])null); + } + + { String[] list = new String[] { "Hello", "World", "!" }; + Object[] result = Arrays.copyOf(list, 2, Object[].class); + expect(list[1] == result[1]); + expect(result.length == 2); + expect(result.getClass().getComponentType() == Object.class); + } + + { Object[] a = new Object[3]; + Object[] b = new Object[3]; + + expect(Arrays.deepEquals(a, b)); + + a[0] = new Object(); + expect(! Arrays.deepEquals(a, b)); + expect(! Arrays.deepEquals(b, new Object[4])); + expect(! Arrays.deepEquals(a, null)); + expect(! Arrays.deepEquals(null, b)); + expect(Arrays.deepEquals((Object[])null, (Object[])null)); + + b[0] = a[0]; + expect(Arrays.deepEquals(a, b)); + + a[0] = new Object[] {1}; + expect(! Arrays.deepEquals(a, b)); + b[0] = new Object[] {1}; + expect(Arrays.deepEquals(a, b)); + ((Object[])a[0])[0] = (Long)1L; + expect(! Arrays.deepEquals(a, b)); + a[0] = new Integer[] {1}; + expect(Arrays.deepEquals(a, b)); + + a[0] = new int[] {1}; + expect(! Arrays.deepEquals(a, b)); + b[0] = new int[] {1}; + expect(Arrays.deepEquals(a, b)); + } + + testSort(); + } +} diff --git a/sgx-jvm/avian/test/AtomicTests.java b/sgx-jvm/avian/test/AtomicTests.java new file mode 100644 index 0000000000..9dab42703e --- /dev/null +++ b/sgx-jvm/avian/test/AtomicTests.java @@ -0,0 +1,231 @@ +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicLong; +import java.util.concurrent.atomic.AtomicReference; + + +public class AtomicTests { + private static final int threadCount = 10; + private static final int iterationsPerThread = 100; + + public static void main(String[] args) { + runAtomicIntegerTest(true); + runAtomicIntegerTest(false); + + runAtomicLongTest(true); + runAtomicLongTest(false); + + runAtomicReferenceTest(); + } + + private static void blockTillThreadsDone(AtomicInteger threadDoneCount) throws InterruptedException { + synchronized (threadDoneCount) { + while (threadDoneCount.get() < threadCount) { + threadDoneCount.wait(); + } + } + } + + private static void runAtomicIntegerTest(final boolean increment) { + final AtomicInteger result = new AtomicInteger(); + final AtomicInteger threadDoneCount = new AtomicInteger(); + // only using an AtomicBoolean here so I don't need two variables to do the synchronize/wait/notify + final AtomicBoolean threadsStart = new AtomicBoolean(false); + + Runnable operationRunnable = new Runnable() { + @Override + public void run() { + boolean flip = true; + for (int i = 0; i < iterationsPerThread; i++) { + if (flip) { + if (increment) { + result.incrementAndGet(); + } else { + result.decrementAndGet(); + } + flip = false; + } else { + if (increment) { + result.getAndIncrement(); + } else { + result.getAndDecrement(); + } + flip = true; + } + } + } + }; + + for (int i = 0; i < threadCount; i++) { + new Thread(new DelayedRunnable(threadsStart, + operationRunnable, + threadDoneCount)).start(); + } + + synchronized (threadsStart) { + threadsStart.set(true); + + threadsStart.notifyAll(); + } + + try { + blockTillThreadsDone(threadDoneCount); + } catch (InterruptedException e) { + // let thread exit + return; + } + + int expectedResult = threadCount * iterationsPerThread; + if (! increment) { + expectedResult *= -1; + } + int resultValue = result.get(); + if (resultValue != expectedResult) { + throw new IllegalStateException(resultValue + " != " + expectedResult); + } + } + + private static void runAtomicLongTest(final boolean increment) { + final AtomicLong result = new AtomicLong(); + final AtomicInteger threadDoneCount = new AtomicInteger(); + // only using an AtomicBoolean here so I don't need two variables to do the synchronize/wait/notify + final AtomicBoolean threadsStart = new AtomicBoolean(false); + + Runnable operationRunnable = new Runnable() { + @Override + public void run() { + boolean flip = true; + for (int i = 0; i < iterationsPerThread; i++) { + if (flip) { + if (increment) { + result.incrementAndGet(); + } else { + result.decrementAndGet(); + } + flip = false; + } else { + if (increment) { + result.getAndIncrement(); + } else { + result.getAndDecrement(); + } + flip = true; + } + } + } + }; + + for (int i = 0; i < threadCount; i++) { + new Thread(new DelayedRunnable(threadsStart, + operationRunnable, + threadDoneCount)).start(); + } + + synchronized (threadsStart) { + threadsStart.set(true); + + threadsStart.notifyAll(); + } + + try { + blockTillThreadsDone(threadDoneCount); + } catch (InterruptedException e) { + // let thread exit + return; + } + + long expectedResult = threadCount * iterationsPerThread; + if (! increment) { + expectedResult *= -1; + } + long resultValue = result.get(); + if (resultValue != expectedResult) { + throw new IllegalStateException(resultValue + " != " + expectedResult); + } + } + + private static void runAtomicReferenceTest() { + final AtomicReference result = new AtomicReference(0); + final AtomicInteger threadDoneCount = new AtomicInteger(0); + // only using an AtomicBoolean here so I don't need two variables to do the synchronize/wait/notify + final AtomicBoolean threadsStart = new AtomicBoolean(false); + + Runnable operationRunnable = new Runnable() { + @Override + public void run() { + for (int i = 0; i < iterationsPerThread; i++) { + Integer current = result.get(); + while (! result.compareAndSet(current, current + 1)) { + current = result.get(); + } + } + } + }; + + for (int i = 0; i < threadCount; i++) { + new Thread(new DelayedRunnable(threadsStart, + operationRunnable, + threadDoneCount)).start(); + } + + synchronized (threadsStart) { + threadsStart.set(true); + + threadsStart.notifyAll(); + } + + try { + blockTillThreadsDone(threadDoneCount); + } catch (InterruptedException e) { + // let thread exit + return; + } + + long expectedResult = threadCount * iterationsPerThread; + Integer resultValue = result.get(); + if (resultValue != expectedResult) { + throw new IllegalStateException(resultValue + " != " + expectedResult); + } + } + + private static class DelayedRunnable implements Runnable { + private final AtomicBoolean threadsStart; + private final Runnable operationRunnable; + private final AtomicInteger threadDoneCount; + + private DelayedRunnable(AtomicBoolean threadsStart, + Runnable operationRunnable, + AtomicInteger threadDoneCount) { + this.threadsStart = threadsStart; + this.operationRunnable = operationRunnable; + this.threadDoneCount = threadDoneCount; + } + + @Override + public void run() { + try { + try { + waitTillReady(); + } catch (InterruptedException e) { + // let thread exit + return; + } + operationRunnable.run(); + } finally { + synchronized (threadDoneCount) { + threadDoneCount.incrementAndGet(); + + threadDoneCount.notifyAll(); + } + } + } + + private void waitTillReady() throws InterruptedException { + synchronized (threadsStart) { + while (! threadsStart.get()) { + threadsStart.wait(); + } + } + } + } +} diff --git a/sgx-jvm/avian/test/BitsetTest.java b/sgx-jvm/avian/test/BitsetTest.java new file mode 100644 index 0000000000..6609eb60dd --- /dev/null +++ b/sgx-jvm/avian/test/BitsetTest.java @@ -0,0 +1,128 @@ +import java.util.BitSet; + +public class BitsetTest { + + public static void main(String[] args) { + BitSet bits = new BitSet(16); + bits.set(5); + bits.set(1); + + BitSet other = new BitSet(16); + other.set(5); + + assertTrue("bit 1 is set", bits.get(1)); + assertTrue("bit 5 is set", bits.get(5)); + assertTrue("bit 0 is not set", !bits.get(0)); + assertTrue("bit 16 is not set", !bits.get(16)); + assertCardinality(bits, 2); + + bits.and(other); + + assertTrue("bit 5 is set", bits.get(5)); + assertTrue("bit 1 is not set", !bits.get(1)); + assertCardinality(bits, 1); + + bits.set(100); + + assertTrue("bit 100 is set", bits.get(100)); + assertTrue("bit 101 is not set", !bits.get(101)); + assertCardinality(bits, 2); + + other.set(101); + + bits.or(other); + + assertTrue("bit 101 is set", bits.get(101)); + + assertEquals("first bit is 5", 5, bits.nextSetBit(0)); + assertEquals("first bit is 5 from 3", 5, bits.nextSetBit(4)); + assertEquals("first bit is 5 from 5", 5, bits.nextSetBit(5)); + assertEquals("second bit is 100", 100, bits.nextSetBit(6)); + assertEquals("second bit is 100 from 100", 100, bits.nextSetBit(100)); + assertEquals("third bit is 101", 101, bits.nextSetBit(101)); + assertEquals("there is no 4th bit", -1, bits.nextSetBit(102)); + assertCardinality(bits, 3); + + assertEquals("first empty bit is 0", 0, bits.nextClearBit(0)); + assertEquals("after 5, 6 is empty", 6, bits.nextClearBit(5)); + assertEquals("after 100, 102 is empty", 102, bits.nextClearBit(100)); + + testFlip(); + testClear(); + + BitSet expandingSet = new BitSet(); + //should force us to have 3 partitions. + expandingSet.set(128); + } + + private static void testFlip() { + /* simple case */ + BitSet bitset = new BitSet(); + bitset.set(0); + bitset.flip(0, 0); + assertTrue("Should not be flipped with 0 length range", bitset.get(0)); + bitset.flip(0, 1); + assertTrue("Should be false with range of one", !bitset.get(0)); + bitset.flip(0); + assertTrue("Should be true again", bitset.get(0)); + + /* need to grow */ + bitset.flip(1000); + assertTrue("1000 should be true", bitset.get(1000)); + assertTrue("1001 should be false", !bitset.get(1001)); + assertTrue("999 should be false", !bitset.get(999)); + + /* Range over 2 segments */ + bitset.flip(60, 70); + assertTrue("59 should be false", !bitset.get(59)); + for (int i=60; i < 70; ++i) { + assertTrue(i + " should be true", bitset.get(i)); + } + assertTrue("70 should be false", !bitset.get(70)); + } + + private static void testClear() { + BitSet bitset = new BitSet(); + bitset.set(0, 20); + assertCardinality(bitset, 20); + + bitset.clear(1); + assertTrue("bit 1 should be 0", !bitset.get(1)); + assertCardinality(bitset, 19); + + bitset.clear(0, 3); + assertTrue("bit 0 should be 0", !bitset.get(0)); + assertTrue("bit 1 should be 0", !bitset.get(1)); + assertTrue("bit 2 should be 0", !bitset.get(2)); + assertTrue("bit 3 should be 1", bitset.get(3)); + assertCardinality(bitset, 17); + + bitset = new BitSet(70); + bitset.flip(0, 65); + for (int i=0; i < 65; ++i) { + assertTrue("bit " + i + " should be set", bitset.get(i)); + } + assertTrue("bit 65 should not be set", !bitset.get(65)); + } + + static void assertTrue(String msg, boolean flag) { + if (flag) { + System.out.println(msg + " : OK."); + } else { + throw new RuntimeException("Error:"+msg); + } + } + + static void assertEquals(String msg, int expected, int actual) { + if (expected==actual) { + System.out.println(msg + " : OK. ["+actual+']'); + } else { + throw new RuntimeException("Error:"+msg+" expected:"+expected+", actual:"+actual); + } + } + + static void assertCardinality(BitSet set, int expectedCardinality) { + assertEquals("Checking cardinality", expectedCardinality, set.cardinality()); + } + +} diff --git a/sgx-jvm/avian/test/BufferedInputStreamTest.java b/sgx-jvm/avian/test/BufferedInputStreamTest.java new file mode 100644 index 0000000000..ba978cd5ef --- /dev/null +++ b/sgx-jvm/avian/test/BufferedInputStreamTest.java @@ -0,0 +1,80 @@ + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.BufferedInputStream; + +/** + * Checks that BufferedInputStream does not block if data is available in it's internal buffer. + */ +public class BufferedInputStreamTest +{ + public static void main(String[] args) throws IOException + { + MyByteArrayStream in = new MyByteArrayStream(new byte[100]); + + BufferedInputStream bin = new BufferedInputStream(in); + //read a single byte to fill the buffer + int b = bin.read(); + byte[] buf = new byte[10]; + //now try to read 10 bytes. this should a least return the content of the buffer. On OpenJDK this are + //4 bytes (the rest of the buffer returned by MyByteArrayStream in the first call). + //It should definately NOT block. + int count = bin.read(buf); + System.out.println("Read bytes: " + count); + } + + /** + * Internal Stream used to show the BufferedInputStream behaviour. + */ + static class MyByteArrayStream extends ByteArrayInputStream + { + boolean stopReading = false; + + /** + * @param buf + */ + public MyByteArrayStream(byte[] buf) + { + super(buf); + } + + /* (non-Javadoc) + * @see java.io.ByteArrayInputStream#read(byte[], int, int) + */ + @Override + public synchronized int read(byte[] b, int off, int len) + { + if(stopReading == false) + { //On the first call 5 bytes are returned. + stopReading = true; + return super.read(b, off, 5); + } + //on all following calls block. The spec says, that a least one byte is returned, if the + //stream is not at EOF. + while(available() == 0) + { + try + { + Thread.sleep(100); + } + catch (InterruptedException e) + { + } + } + return 0; + } + + /* (non-Javadoc) + * @see java.io.ByteArrayInputStream#available() + */ + @Override + public synchronized int available() + { + if(stopReading) + { + return 0; + } + return super.available(); + } + } +} diff --git a/sgx-jvm/avian/test/Buffers.java b/sgx-jvm/avian/test/Buffers.java new file mode 100644 index 0000000000..63a24ec928 --- /dev/null +++ b/sgx-jvm/avian/test/Buffers.java @@ -0,0 +1,195 @@ +import java.nio.ByteBuffer; +import java.nio.BufferUnderflowException; +import java.nio.BufferOverflowException; +import static avian.testing.Asserts.*; + +public class Buffers { + static { + System.loadLibrary("test"); + } + + private static void testArrays(Factory factory1, Factory factory2) { + final int size = 64; + ByteBuffer b1 = factory1.allocate(size); + ByteBuffer b2 = factory2.allocate(size); + + String s = "1234567890abcdefghijklmnopqrstuvwxyz"; + b1.put(s.getBytes()); + b1.flip(); + byte[] ba = new byte[s.length()]; + b1.get(ba); + assertEquals(s, new String(ba)); + b1.position(0); + b2.put(b1); + b2.flip(); + b2.get(ba); + assertEquals(s, new String(ba)); + b1.position(0); + b2.position(0); + b1.limit(b1.capacity()); + b2.limit(b2.capacity()); + b1.put(s.getBytes(), 4, 5); + b1.flip(); + ba = new byte[5]; + b1.get(ba); + assertEquals(s.substring(4, 9), new String(ba)); + } + + private static void testPrimativeGetAndSet(Factory factory1, Factory factory2) { + { final int size = 64; + ByteBuffer b1 = factory1.allocate(size); + try { + + for (int i = 0; i < size; ++i) + b1.put(i, (byte) 42); + + for (int i = 0; i < size; ++i) + assertEquals(b1.get(i), 42); + + for (int i = 0; i < size/4; i++) + b1.putFloat(i*4, (float) 19.12); + + for (int i = 0; i < size/4; i++) + assertEquals(b1.getFloat(i*4), (float) 19.12); + + ByteBuffer b3 = b1.duplicate(); + for (int i = 0; i < size/4; i++) + assertEquals(b3.getFloat(), (float) 19.12); + assertEquals(64, b3.position()); + + for (int i = 0; i < size/8; i++) + b1.putDouble(i*8, (double) 19.12); + + for (int i = 0; i < size/8; i++) + assertEquals(b1.getDouble(i*8), (double) 19.12); + + b3.position(0); + + for (int i = 0; i < size/8; i++) + assertEquals(b3.getDouble(i*8), (double) 19.12); + + for (int i = 0; i < size / 2; ++i) + b1.putShort(i * 2, (short) -12345); + + for (int i = 0; i < size / 2; ++i) + assertEquals(b1.getShort(i * 2), -12345); + + for (int i = 0; i < size / 4; ++i) + b1.putInt(i * 4, 0x12345678); + + for (int i = 0; i < size / 4; ++i) + assertEquals(b1.getInt(i * 4), 0x12345678); + + for (int i = 0; i < size / 8; ++i) + b1.putLong(i * 8, 0x1234567890ABCDEFL); + + for (int i = 0; i < size / 8; ++i) + assertEquals(b1.getLong(i * 8), 0x1234567890ABCDEFL); + + ByteBuffer b2 = factory2.allocate(size); + try { + b2.put(b1); + + for (int i = 0; i < size / 8; ++i) + assertTrue(b2.getLong(i * 8) == 0x1234567890ABCDEFL); + + } finally { + factory2.dispose(b2); + } + } finally { + factory1.dispose(b1); + } + } + } + + private static native ByteBuffer allocateNative(int capacity); + + private static native void freeNative(ByteBuffer b); + + public static void main(String[] args) throws Exception { + Factory array = new Factory() { + public ByteBuffer allocate(int capacity) { + return ByteBuffer.allocate(capacity); + } + + public void dispose(ByteBuffer b) { + // ignore + } + }; + + Factory direct = new Factory() { + public ByteBuffer allocate(int capacity) { + return ByteBuffer.allocateDirect(capacity); + } + + public void dispose(ByteBuffer b) { + // ignore + } + }; + + Factory native_ = new Factory() { + public ByteBuffer allocate(int capacity) { + return allocateNative(capacity); + } + + public void dispose(ByteBuffer b) { + freeNative(b); + } + }; + + testPrimativeGetAndSet(array, array); + testArrays(array, array); + testPrimativeGetAndSet(array, direct); + testArrays(array, direct); + testPrimativeGetAndSet(array, native_); + testArrays(array, native_); + + testPrimativeGetAndSet(direct, array); + testArrays(direct, array); + testPrimativeGetAndSet(direct, direct); + testArrays(direct, direct); + testPrimativeGetAndSet(direct, native_); + testArrays(direct, native_); + + testPrimativeGetAndSet(native_, array); + testArrays(native_, array); + testPrimativeGetAndSet(native_, direct); + testArrays(native_, direct); + testPrimativeGetAndSet(native_, native_); + testArrays(native_, native_); + + try { + ByteBuffer.allocate(1).getInt(); + assertTrue(false); + } catch (BufferUnderflowException e) { + // cool + } + + try { + ByteBuffer.allocate(1).getInt(0); + assertTrue(false); + } catch (IndexOutOfBoundsException e) { + // cool + } + + try { + ByteBuffer.allocate(1).putInt(1); + assertTrue(false); + } catch (BufferOverflowException e) { + // cool + } + + try { + ByteBuffer.allocate(1).putInt(0, 1); + assertTrue(false); + } catch (IndexOutOfBoundsException e) { + // cool + } + } + + private interface Factory { + public ByteBuffer allocate(int capacity); + + public void dispose(ByteBuffer b); + } +} diff --git a/sgx-jvm/avian/test/Busy.java b/sgx-jvm/avian/test/Busy.java new file mode 100644 index 0000000000..e301896416 --- /dev/null +++ b/sgx-jvm/avian/test/Busy.java @@ -0,0 +1,25 @@ +public class Busy { + private static volatile int foo = 0; + private static volatile boolean go; + + public static void main(String[] args) { + final Object lock = new Object(); + + synchronized (lock) { + new Thread() { + public void run() { + while (foo < 100) { + go = true; + } + } + }.start(); + + while (foo < 100) { + while (! go) { } + go = false; + byte[] array = new byte[256 * 1024]; + ++ foo; + } + } + } +} \ No newline at end of file diff --git a/sgx-jvm/avian/test/Collections.java b/sgx-jvm/avian/test/Collections.java new file mode 100644 index 0000000000..d778267dde --- /dev/null +++ b/sgx-jvm/avian/test/Collections.java @@ -0,0 +1,68 @@ +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Map; + +public class Collections { + public static void main(String[] args) { + testValues(); + testSort(); + } + + @SuppressWarnings("rawtypes") + private static void testValues() { + Map testMap = java.util.Collections.unmodifiableMap(java.util.Collections.emptyMap()); + Collection values = testMap.values(); + + if (values == null) { + throw new NullPointerException(); + } + + try { + values.clear(); + + throw new IllegalStateException("Object should be immutable, exception should have thrown"); + } catch (Exception e) { + // expected + } + } + + private static void expect(boolean v) { + if (! v) throw new RuntimeException(); + } + + private static > void expectSorted(List list) { + for (int i = 1; i < list.size(); ++i) { + expect(list.get(i - 1).compareTo(list.get(i)) <= 0); + } + } + + private static int pseudoRandom(int seed) { + return 3170425 * seed + 132102; + } + + private static > int shuffle(List list, int seed) { + for (int i = list.size(); i > 1; --i) { + int i2 = (seed < 0 ? -seed : seed) % i; + T value = list.get(i - 1); + list.set(i - 1, list.get(i2)); + list.set(i2, value); + seed = pseudoRandom(seed); + } + return seed; + } + + public static void testSort() { + List list = new ArrayList(); + for (int i = 0; i < 64; ++i) { + list.add(Integer.valueOf(i + 1)); + } + ; + int random = 12345; + for (int i = 0; i < 32; ++i) { + random = shuffle(list, random); + java.util.Collections.sort(list); + expectSorted(list); + } + } +} diff --git a/sgx-jvm/avian/test/CompletionServiceTest.java b/sgx-jvm/avian/test/CompletionServiceTest.java new file mode 100644 index 0000000000..975f632855 --- /dev/null +++ b/sgx-jvm/avian/test/CompletionServiceTest.java @@ -0,0 +1,54 @@ +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Executor; +import java.util.concurrent.ExecutorCompletionService; +import java.util.concurrent.TimeUnit; + +public class CompletionServiceTest { + public static void main(String args[]) throws InterruptedException, ExecutionException { + Executor dumbExecutor = new Executor() { + @Override + public void execute(Runnable task) { + new Thread(task).start(); + } + }; + + pollNoResultTest(dumbExecutor); + pollTimeoutNoResultTest(dumbExecutor); + takeTest(dumbExecutor); + } + + private static void verify(boolean val) { + if (! val) { + throw new RuntimeException(); + } + } + + private static void pollNoResultTest(Executor executor) { + ExecutorCompletionService ecs = new ExecutorCompletionService(executor); + + verify(ecs.poll() == null); + } + + private static void pollTimeoutNoResultTest(Executor executor) throws InterruptedException { + long delayTime = 0; + ExecutorCompletionService ecs = new ExecutorCompletionService(executor); + + long startTime = System.currentTimeMillis(); + verify(ecs.poll(delayTime, TimeUnit.MILLISECONDS) == null); + verify(System.currentTimeMillis() - startTime >= delayTime); + } + + private static void takeTest(Executor executor) throws InterruptedException, ExecutionException { + ExecutorCompletionService ecs = new ExecutorCompletionService(executor); + final Object result = new Object(); + ecs.submit(new Callable() { + @Override + public Object call() throws Exception { + return result; + } + }); + + verify(ecs.take().get() == result); + } +} diff --git a/sgx-jvm/avian/test/ConcurrentHashMapTest.java b/sgx-jvm/avian/test/ConcurrentHashMapTest.java new file mode 100644 index 0000000000..f0d271f412 --- /dev/null +++ b/sgx-jvm/avian/test/ConcurrentHashMapTest.java @@ -0,0 +1,166 @@ +import java.util.Iterator; +import java.util.Map; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.ConcurrentHashMap; + +public class ConcurrentHashMapTest { + private static final int ThreadCount = 4; + private static final int IterationCount = 100; + private static final int Range = 10; + private static final int CommonBase = -Range; + + private static void expect(boolean v) { + if (! v) throw new RuntimeException(); + } + + public static void main(String[] args) throws Throwable { + final ConcurrentMap map = new ConcurrentHashMap(); + final int[] counter = new int[1]; + final int[] step = new int[1]; + final Throwable[] exception = new Throwable[1]; + + synchronized (map) { + for (int i = 0; i < ThreadCount; ++i) { + final int index = i; + new Thread() { + public void run() { + try { + synchronized (map) { + ++ counter[0]; + map.notifyAll(); + while (exception[0] == null && step[0] == 0) { + map.wait(); + } + } + + for (int i = 0; i < IterationCount; ++i) { + populateCommon(map); + populate(map, index * Range); + } + + synchronized (map) { + -- counter[0]; + map.notifyAll(); + while (exception[0] == null && step[0] == 1) { + map.wait(); + } + } + + for (int i = 0; i < IterationCount; ++i) { + populate(map, index * Range); + depopulate(map, index * Range); + } + + synchronized (map) { + ++ counter[0]; + map.notifyAll(); + } + } catch (Throwable e) { + synchronized (map) { + exception[0] = e; + map.notifyAll(); + } + e.printStackTrace(); + } + } + }.start(); + } + + try { + while (exception[0] == null && counter[0] < ThreadCount) { + map.wait(); + } + + step[0] = 1; + map.notifyAll(); + + while (exception[0] == null && counter[0] > 0) { + map.wait(); + } + + if (map.size() != ThreadCount * Range) { + System.err.println + ("expected " + (ThreadCount * Range) + " got " + map.size()); + } + expect(map.size() == ThreadCount * Range); + for (int i = CommonBase, j = CommonBase + Range; i < j; ++i) { + expect(! map.containsKey(i)); + } + + step[0] = 2; + map.notifyAll(); + + while (exception[0] == null && counter[0] < ThreadCount) { + map.wait(); + } + + expect(map.isEmpty()); + expect(exception[0] == null); + } catch (Throwable e) { + exception[0] = e; + throw e; + } finally { + map.notifyAll(); + } + } + } + + private static void populateCommon(ConcurrentMap map) { + Object value = new Object(); + for (int i = CommonBase, j = CommonBase + Range; i < j; ++i) { + map.remove(i); + map.put(i, value); + map.remove(i); + } + } + + private static void populate(ConcurrentMap map, int base) { + for (int i = base, j = base + Range; i < j; ++i) { + map.remove(i); + Object value = new Object(); + expect(map.put(i, value) == null); + expect(map.containsKey(i)); + expect(map.get(i).equals(value)); + expect(map.putIfAbsent(i, new Object()) == value); + expect(map.get(i).equals(value)); + expect(! map.remove(i, new Object())); + expect(map.remove(i, value)); + expect(map.replace(i, value) == null); + expect(! map.containsKey(i)); + expect(map.get(i) == null); + expect(map.putIfAbsent(i, value) == null); + expect(map.containsKey(i)); + expect(map.get(i) == value); + Object newValue = new Object(); + expect(map.replace(i, newValue) == value); + expect(map.get(i) == newValue); + + boolean found = false; + for (Iterator> it = map.entrySet().iterator(); + it.hasNext();) + { + Map.Entry e = it.next(); + if (e.getKey() == i) { + expect(! found); + expect(e.getValue() == newValue); + found = true; + it.remove(); + } + } + + expect(found); + expect(! map.containsKey(i)); + expect(map.putIfAbsent(i, value) == null); + expect(map.containsKey(i)); + expect(map.get(i) == value); + } + } + + private static void depopulate(ConcurrentMap map, int base) + { + for (int i = base, j = base + Range; i < j; ++i) { + expect(map.containsKey(i)); + expect(map.remove(i) != null); + } + } +} diff --git a/sgx-jvm/avian/test/Datagrams.java b/sgx-jvm/avian/test/Datagrams.java new file mode 100644 index 0000000000..d5dcd88d07 --- /dev/null +++ b/sgx-jvm/avian/test/Datagrams.java @@ -0,0 +1,100 @@ +import java.net.SocketAddress; +import java.net.InetSocketAddress; +import java.net.ProtocolFamily; +import java.net.StandardProtocolFamily; +import java.nio.ByteBuffer; +import java.nio.channels.DatagramChannel; +import java.nio.channels.Selector; +import java.nio.channels.SelectionKey; + +public class Datagrams { + private static void expect(boolean v) { + if (! v) throw new RuntimeException(); + } + + private static boolean equal(byte[] a, int aOffset, byte[] b, int bOffset, + int length) + { + for (int i = 0; i < length; ++i) { + if (a[aOffset + i] != b[bOffset + i]) return false; + } + return true; + } + + public static void main(String[] args) throws Exception { + test(true); + test(false); + } + + private static void test(boolean send) throws Exception { + final String Hostname = "localhost"; + final int InPort = 22043; + final int OutPort = 22044; + final SocketAddress InAddress = new InetSocketAddress(Hostname, InPort); + final SocketAddress OutAddress = new InetSocketAddress(Hostname, OutPort); + final byte[] Message = "hello, world!".getBytes(); + + DatagramChannel out = DatagramChannel.open(); + try { + out.configureBlocking(false); + out.socket().bind(OutAddress); + if (! send) out.connect(InAddress); + + DatagramChannel in = DatagramChannel.open(); + try { + in.configureBlocking(false); + in.socket().bind(InAddress); + + Selector selector = Selector.open(); + try { + SelectionKey outKey = out.register + (selector, SelectionKey.OP_WRITE, null); + + SelectionKey inKey = in.register + (selector, SelectionKey.OP_READ, null); + + int state = 0; + ByteBuffer inBuffer = ByteBuffer.allocate(Message.length); + loop: while (true) { + selector.select(); + + switch (state) { + case 0: { + if (outKey.isWritable()) { + if (send) { + out.send(ByteBuffer.wrap(Message), InAddress); + } else { + out.write(ByteBuffer.wrap(Message)); + } + state = 1; + } + } break; + + case 1: { + if (inKey.isReadable()) { + expect(in.receive(inBuffer).equals(OutAddress)); + if (! inBuffer.hasRemaining()) { + expect(equal(inBuffer.array(), + inBuffer.arrayOffset(), + Message, + 0, + Message.length)); + break loop; + } + } + } break; + + default: throw new RuntimeException(); + } + } + } finally { + selector.close(); + } + } finally { + in.close(); + } + } finally { + out.close(); + } + } +} diff --git a/sgx-jvm/avian/test/Dates.java b/sgx-jvm/avian/test/Dates.java new file mode 100644 index 0000000000..dfd6d72273 --- /dev/null +++ b/sgx-jvm/avian/test/Dates.java @@ -0,0 +1,27 @@ +import java.text.FieldPosition; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.TimeZone; + +public class Dates { + private final static long EPOCH = 1234567890; + private final static String TEXT = "2009-02-13T23:31:30"; + + private static void expect(boolean v) { + if (! v) throw new RuntimeException(); + } + + public static void main(String[] args) throws Exception { + SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss"); + format.setTimeZone(TimeZone.getTimeZone("GMT")); + Date date = format.parse("1970-01-01T00:00:00"); + expect(0 == date.getTime()); + + date = new Date(EPOCH * 1000l); + String actual = format.format(date, new StringBuffer(), new FieldPosition(0)).toString(); + expect(TEXT.equals(actual)); + + date = format.parse(TEXT); + expect(EPOCH == date.getTime() / 1000l); + } +} diff --git a/sgx-jvm/avian/test/DefineClass.java b/sgx-jvm/avian/test/DefineClass.java new file mode 100644 index 0000000000..4cff3ecfde --- /dev/null +++ b/sgx-jvm/avian/test/DefineClass.java @@ -0,0 +1,86 @@ +import java.io.IOException; +import java.io.File; +import java.io.FileInputStream; + +public class DefineClass { + private static File findClass(String name, File directory) { + for (File file: directory.listFiles()) { + if (file.isFile()) { + if (file.getName().equals(name + ".class")) { + return file; + } + } else if (file.isDirectory()) { + File result = findClass(name, file); + if (result != null) { + return result; + } + } + } + return null; + } + + private static byte[] read(File file) throws IOException { + byte[] bytes = new byte[(int) file.length()]; + FileInputStream in = new FileInputStream(file); + try { + if (in.read(bytes) != (int) file.length()) { + throw new RuntimeException(); + } + return bytes; + } finally { + in.close(); + } + } + + private static Class loadClass(String name) throws Exception { + return new MyClassLoader(DefineClass.class.getClassLoader()).defineClass + (name, read(findClass(name, new File(System.getProperty("user.dir"))))); + } + + private static void testStatic() throws Exception { + loadClass("DefineClass$Hello") + .getMethod("main", String[].class).invoke(null, (Object) new String[0]); + } + + private static void testDerived() throws Exception { + System.out.println + (String.valueOf + (((Base) loadClass("DefineClass$Derived").newInstance()).zip())); + } + + public static void main(String[] args) throws Exception { + testStatic(); + testDerived(); + } + + private static class MyClassLoader extends ClassLoader { + public MyClassLoader(ClassLoader parent) { + super(parent); + } + + public Class defineClass(String name, byte[] bytes) { + return defineClass(name, bytes, 0, bytes.length); + } + } + + public static class Hello { + public static void main(String[] args) { + System.out.println("hello, world!"); + } + } + + public abstract static class Base { + public int foo; + public int[] array; + + public void bar() { } + + public abstract int zip(); + } + + public static class Derived extends Base { + public int zip() { + return 42; + } + } +} diff --git a/sgx-jvm/avian/test/DequeHelper.java b/sgx-jvm/avian/test/DequeHelper.java new file mode 100644 index 0000000000..4d19041a6b --- /dev/null +++ b/sgx-jvm/avian/test/DequeHelper.java @@ -0,0 +1,55 @@ +import java.util.Deque; + +public class DequeHelper { + private static void verify(boolean val) { + if (! val) { + throw new RuntimeException(); + } + } + + public static void main(String args[]) { + // prevents unit test failure + } + + public static void addFirstTest(Deque q) { + Object firstObject = new Object(); + Object lastObject = new Object(); + q.addFirst(lastObject); + q.addFirst(firstObject); + + verify(q.size() == 2); + verify(q.peekFirst() == firstObject); + verify(q.peekLast() == lastObject); + } + + public static void addLastTest(Deque q) { + Object firstObject = new Object(); + Object lastObject = new Object(); + q.addLast(firstObject); + q.addLast(lastObject); + + verify(q.size() == 2); + verify(q.peekFirst() == firstObject); + verify(q.peekLast() == lastObject); + } + + public static void removeFirstTest(Deque q) { + Object firstObject = new Object(); + Object lastObject = new Object(); + q.addLast(firstObject); + q.addLast(lastObject); + + verify(q.removeFirst() == firstObject); + verify(q.removeFirst() == lastObject); + } + + public static void removeLastTest(Deque q) { + Object firstObject = new Object(); + Object lastObject = new Object(); + q.addLast(firstObject); + q.addLast(lastObject); + + verify(q.removeLast() == lastObject); + verify(q.removeLast() == firstObject); + } +} diff --git a/sgx-jvm/avian/test/DivideByZero.java b/sgx-jvm/avian/test/DivideByZero.java new file mode 100644 index 0000000000..80f308adcb --- /dev/null +++ b/sgx-jvm/avian/test/DivideByZero.java @@ -0,0 +1,135 @@ +public class DivideByZero { + private static int divide(int n, int d) { + return n / d; + } + + private static int modulo(int n, int d) { + return n % d; + } + + private static long divide(long n, long d) { + return n / d; + } + + private static long modulo(long n, long d) { + return n % d; + } + + private static float divide(float n, float d) { + return n / d; + } + + private static float modulo(float n, float d) { + return n % d; + } + + private static double divide(double n, double d) { + return n / d; + } + + private static double modulo(double n, double d) { + return n % d; + } + + public static void main(String[] args) { + try { + int x = 1 / 0; + throw new RuntimeException(); + } catch (ArithmeticException e) { + e.printStackTrace(); + } + + try { + int x = 1 % 0; + throw new RuntimeException(); + } catch (ArithmeticException e) { + e.printStackTrace(); + } + + try { + int y = 2; + int x = y / 0; + throw new RuntimeException(); + } catch (ArithmeticException e) { + e.printStackTrace(); + } + + try { + int y = 2; + int x = y % 0; + throw new RuntimeException(); + } catch (ArithmeticException e) { + e.printStackTrace(); + } + + try { + int z = 0; + int y = 2; + int x = y / z; + throw new RuntimeException(); + } catch (ArithmeticException e) { + e.printStackTrace(); + } + + try { + int z = 0; + int y = 2; + int x = y % z; + throw new RuntimeException(); + } catch (ArithmeticException e) { + e.printStackTrace(); + } + + try { + long z = 0; + long y = 2; + long x = y / z; + throw new RuntimeException(); + } catch (ArithmeticException e) { + e.printStackTrace(); + } + + try { + long z = 0; + long y = 2; + long x = y % z; + throw new RuntimeException(); + } catch (ArithmeticException e) { + e.printStackTrace(); + } + + try { + divide(5, 0); + throw new RuntimeException(); + } catch (ArithmeticException e) { + e.printStackTrace(); + } + + try { + modulo(6, 0); + throw new RuntimeException(); + } catch (ArithmeticException e) { + e.printStackTrace(); + } + + try { + divide(5L, 0L); + throw new RuntimeException(); + } catch (ArithmeticException e) { + e.printStackTrace(); + } + + try { + modulo(6L, 0L); + throw new RuntimeException(); + } catch (ArithmeticException e) { + e.printStackTrace(); + } + + divide(5F, 0F); + modulo(6F, 0F); + + divide(5D, 0D); + modulo(6D, 0D); + } +} diff --git a/sgx-jvm/avian/test/EnumSetTest.java b/sgx-jvm/avian/test/EnumSetTest.java new file mode 100644 index 0000000000..3b1317b7ec --- /dev/null +++ b/sgx-jvm/avian/test/EnumSetTest.java @@ -0,0 +1,107 @@ +import java.util.EnumSet; +import java.util.Iterator; +import java.util.NoSuchElementException; + +public class EnumSetTest { + private enum SmallEnum { + ONE, + TWO, + THREE + } + + private enum LargerEnum { + LARGEONE, + LARGETWO, + LARGETHREE, + LARGEFOUR, + LARGEFIVE, + LARGESIX + } + + public static void main(String[] args) { + testAllOf(); + testNoneOf(); + testIterators(); + testOf(); + testCopyOf(); + testComplimentOf(); + } + + private static void testComplimentOf() { + EnumSet one = EnumSet.of(SmallEnum.ONE, SmallEnum.THREE); + EnumSet two = EnumSet.complementOf(one); + assertElementInSet(SmallEnum.TWO, two); + assertSize(1, two); + } + + private static void testCopyOf() { + EnumSet one = EnumSet.of(SmallEnum.ONE, SmallEnum.THREE); + EnumSet two = EnumSet.copyOf(one); + assertElementInSet(SmallEnum.ONE, two); + assertElementInSet(SmallEnum.THREE, two); + assertSize(2, two); + } + + private static void testOf() { + EnumSet set = EnumSet.of(LargerEnum.LARGEONE, LargerEnum.LARGEFIVE, LargerEnum.LARGETWO); + assertElementInSet(LargerEnum.LARGEONE, set); + assertElementInSet(LargerEnum.LARGEFIVE, set); + assertElementInSet(LargerEnum.LARGETWO, set); + assertSize(3, set); + } + + private static void testAllOf() { + EnumSet set = EnumSet.allOf(SmallEnum.class); + for (SmallEnum current : SmallEnum.values()) { + assertElementInSet(current, set); + } + assertSize(3, set); + } + + private static void testNoneOf() { + EnumSet set = EnumSet.noneOf(SmallEnum.class); + assertSize(0, set); + } + + private static void testIterators() { + EnumSet set = EnumSet.allOf(SmallEnum.class); + Iterator iterator = set.iterator(); + boolean exceptionCaught = false; + try { + iterator.remove(); + } catch (IllegalStateException e) { + exceptionCaught = true; + } + if (!exceptionCaught) { + throw new RuntimeException("Calling remove() before next() should throw IllegalStateException"); + } + + while (iterator.hasNext()) { + iterator.next(); + iterator.remove(); + } + assertSize(0, set); + + exceptionCaught = false; + try { + iterator.next(); + } catch (NoSuchElementException e) { + exceptionCaught = true; + } + if (!exceptionCaught) { + throw new RuntimeException("Calling next() when hasNext() == false should throw NoSuchElementException"); + } + } + + private static void assertElementInSet(Enum element, EnumSet set) { + if (!set.contains(element)) { + throw new RuntimeException("expected " + element + " in the set!"); + } + } + + private static void assertSize(int expectedSize, EnumSet set) { + if (set.size() != expectedSize) { + throw new RuntimeException("expected the set to be size=" + expectedSize + ", actual=" + set.size()); + } + } +} diff --git a/sgx-jvm/avian/test/Enums.java b/sgx-jvm/avian/test/Enums.java new file mode 100644 index 0000000000..9cb397fbc3 --- /dev/null +++ b/sgx-jvm/avian/test/Enums.java @@ -0,0 +1,39 @@ +public class Enums { + private enum Suit { CLUBS, HEARTS, SPADES, DIAMONDS }; + private enum Rank { ACE, TWO, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT, + NINE, TEN, JACK, QUEEN, KING }; + private enum Person { Joe(4), Mike(5) ; + private final int age; + private Person(int age) { + this.age = age; + } + public int getAge() { + return age; + } + }; + + private static void expect(boolean v) { + if (! v) throw new RuntimeException(); + } + + private static boolean checkFaceCard(Rank r) { + switch (r) { + case ACE: + case JACK: + case QUEEN: + case KING: + return true; + } + return false; + } + + public static void main(String[] args) { + expect(Suit.CLUBS.ordinal() == 0); + expect(Suit.valueOf("DIAMONDS") == Suit.DIAMONDS); + System.out.println(Suit.SPADES); + expect(Suit.values()[1] == Suit.HEARTS); + expect(!checkFaceCard(Rank.FIVE)); + expect(checkFaceCard(Rank.KING)); + expect(Person.Mike.getAge() == 5); + } +} diff --git a/sgx-jvm/avian/test/Exceptions.java b/sgx-jvm/avian/test/Exceptions.java new file mode 100644 index 0000000000..15f1c99c1d --- /dev/null +++ b/sgx-jvm/avian/test/Exceptions.java @@ -0,0 +1,63 @@ +public class Exceptions { + static class ThrowError { + static { + if (true) throw new AssertionError(); + } + + static void foo() { } + } + + static class ThrowException { + static { + if (true) throw new RuntimeException(); + } + + static void foo() { } + } + + private static void evenMoreDangerous() { + throw new RuntimeException("chaos! panic! overwhelming anxiety!"); + } + + private static void moreDangerous() { + evenMoreDangerous(); + } + + private static void dangerous() { + moreDangerous(); + } + + private static void expect(boolean v) { + if (! v) throw new RuntimeException(); + } + + public static void main(String[] args) { + boolean threw = false; + try { + dangerous(); + } catch (Exception e) { + e.printStackTrace(); + threw = true; + } + expect(threw); + threw = false; + + try { + ThrowError.foo(); + } catch (AssertionError e) { + e.printStackTrace(); + threw = true; + } + expect(threw); + threw = false; + + try { + ThrowException.foo(); + } catch (ExceptionInInitializerError e) { + e.printStackTrace(); + threw = true; + } + expect(threw); + } + +} diff --git a/sgx-jvm/avian/test/FileOutput.java b/sgx-jvm/avian/test/FileOutput.java new file mode 100644 index 0000000000..539b73fc59 --- /dev/null +++ b/sgx-jvm/avian/test/FileOutput.java @@ -0,0 +1,47 @@ +import java.io.FileOutputStream; +import java.io.FileInputStream; +import java.io.File; +import java.io.IOException; + +public class FileOutput { + private static void expect(boolean v) { + if (! v) throw new RuntimeException(); + } + + private static void test(boolean appendFirst) throws IOException { + try { + FileOutputStream f = new FileOutputStream("test.txt", appendFirst); + f.write("Hello world!\n".getBytes()); + f.close(); + + FileOutputStream f2 = new FileOutputStream("test.txt", true); + f2.write("Hello world again!".getBytes()); + f2.close(); + + FileInputStream in = new FileInputStream("test.txt"); + byte[] buffer = new byte[256]; + int c; + int offset = 0; + while ((c = in.read(buffer, offset, buffer.length - offset)) != -1) { + offset += c; + } + in.close(); + + if (! "Hello world!\nHello world again!".equals + (new String(buffer, 0, offset))) + { + throw new RuntimeException(); + } + } finally { + expect(new File("test.txt").delete()); + } + } + + public static void main(String[] args) throws IOException { + expect(new File("nonexistent-file").length() == 0); + + test(false); + test(true); + } + +} diff --git a/sgx-jvm/avian/test/Files.java b/sgx-jvm/avian/test/Files.java new file mode 100644 index 0000000000..21bd5cf07c --- /dev/null +++ b/sgx-jvm/avian/test/Files.java @@ -0,0 +1,100 @@ +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; + +public class Files { + private static final boolean IsWindows + = System.getProperty("os.name").equals("Windows"); + + private static void expect(boolean v) { + if (! v) throw new RuntimeException(); + } + + private static void isAbsoluteTest(boolean absolutePath) { + File file = new File("test.txt"); + if (absolutePath) { + file = file.getAbsoluteFile(); + } + + boolean isAbsolute = file.isAbsolute(); + + if (absolutePath) { + expect(isAbsolute); + } else { + expect(!isAbsolute); + } + + } + + private static void setExecutableTestWithPermissions(boolean executable) + throws Exception + { + File file = File.createTempFile("avian.", null); + try { + file.setExecutable(executable); + if (executable) { + expect(file.canExecute()); + } else { + // Commented out because this will fail on Windows - both on Avian and on OpenJDK + // The implementation for Windows considers canExecute() to be the same as canRead() + // expect(!file.canExecute()); + } + } finally { + expect(file.delete()); + } + } + + public static void main(String[] args) throws Exception { + isAbsoluteTest(true); + isAbsoluteTest(false); + setExecutableTestWithPermissions(true); + setExecutableTestWithPermissions(false); + + { File f = new File("test.txt"); + f.createNewFile(); + expect(! f.createNewFile()); + f.delete(); + } + + { File f = new File("test.txt"); + FileOutputStream out = new FileOutputStream(f); + try { + byte[] message = "hello, world!\n".getBytes(); + out.write(message); + out.close(); + + expect(f.lastModified() > 0); + + FileInputStream in = new FileInputStream(f); + try { + expect(in.available() == message.length); + + for (int i = 0; i < message.length; ++i) { + in.read(); + expect(in.available() == message.length - i - 1); + } + + expect(in.read() == -1); + expect(in.available() == 0); + } finally { + in.close(); + } + } finally { + f.delete(); + } + } + + if(IsWindows) { + expect(new File("/c:\\test").getPath().equals("c:\\test")); + } else { + expect(new File("/c:\\test").getPath().equals("/c:\\test")); + } + + expect(new File("foo/bar").getParent().equals("foo")); + expect(new File("foo/bar/").getParent().equals("foo")); + expect(new File("foo/bar//").getParent().equals("foo")); + + expect(new File("foo/nonexistent-directory").listFiles() == null); + } + +} diff --git a/sgx-jvm/avian/test/Finalizers.java b/sgx-jvm/avian/test/Finalizers.java new file mode 100644 index 0000000000..220a32ba4c --- /dev/null +++ b/sgx-jvm/avian/test/Finalizers.java @@ -0,0 +1,44 @@ +public class Finalizers { + private static final Object lock = new Object(); + private static boolean finalized = false; + + private static void expect(boolean v) { + if (! v) throw new RuntimeException(); + } + + protected void finalize() { + synchronized (lock) { + finalized = true; + lock.notifyAll(); + } + } + + public static void main(String[] args) throws Exception { + new Finalizers(); + + expect(! finalized); + + synchronized (lock) { + System.gc(); + lock.wait(5000); + } + + expect(finalized); + + new Finalizers2(); + + finalized = false; + + expect(! finalized); + + synchronized (lock) { + System.gc(); + lock.wait(5000); + } + + expect(finalized); + } + + private static class Finalizers2 extends Finalizers { } + +} diff --git a/sgx-jvm/avian/test/Floats.java b/sgx-jvm/avian/test/Floats.java new file mode 100644 index 0000000000..eca59b1bc9 --- /dev/null +++ b/sgx-jvm/avian/test/Floats.java @@ -0,0 +1,351 @@ +public class Floats { + private static void expect(boolean v) { + if (! v) throw new RuntimeException(); + } + + private static double multiply(double a, double b) { + return a * b; + } + + private static float multiply(float a, float b) { + return a * b; + } + + private static double divide(double a, double b) { + return a / b; + } + + private static double subtract(double a, double b) { + return a - b; + } + + private double field = 100d; + + private static int doubleToInt(Floats f) { + return (int) f.field; + } + + private static void multiplyAndStore(double a, double b, Floats f) { + f.field = a * b; + } + + private static double loadAndMultiply(double a, Floats f) { + return f.field * a; + } + + private static void subdivide(double src[], int srcoff, + double left[], int leftoff, + double right[], int rightoff) + { + double x1 = src[srcoff + 0]; + double y1 = src[srcoff + 1]; + double ctrlx1 = src[srcoff + 2]; + double ctrly1 = src[srcoff + 3]; + double ctrlx2 = src[srcoff + 4]; + double ctrly2 = src[srcoff + 5]; + double x2 = src[srcoff + 6]; + double y2 = src[srcoff + 7]; + if (left != null) { + left[leftoff + 0] = x1; + left[leftoff + 1] = y1; + } + if (right != null) { + right[rightoff + 6] = x2; + right[rightoff + 7] = y2; + } + x1 = (x1 + ctrlx1) / 2.0; + y1 = (y1 + ctrly1) / 2.0; + x2 = (x2 + ctrlx2) / 2.0; + y2 = (y2 + ctrly2) / 2.0; + double centerx = (ctrlx1 + ctrlx2) / 2.0; + double centery = (ctrly1 + ctrly2) / 2.0; + ctrlx1 = (x1 + centerx) / 2.0; + ctrly1 = (y1 + centery) / 2.0; + ctrlx2 = (x2 + centerx) / 2.0; + ctrly2 = (y2 + centery) / 2.0; + centerx = (ctrlx1 + ctrlx2) / 2.0; + centery = (ctrly1 + ctrly2) / 2.0; + if (left != null) { + left[leftoff + 2] = x1; + left[leftoff + 3] = y1; + left[leftoff + 4] = ctrlx1; + left[leftoff + 5] = ctrly1; + left[leftoff + 6] = centerx; + left[leftoff + 7] = centery; + } + if (right != null) { + right[rightoff + 0] = centerx; + right[rightoff + 1] = centery; + right[rightoff + 2] = ctrlx2; + right[rightoff + 3] = ctrly2; + right[rightoff + 4] = x2; + right[rightoff + 5] = y2; + } + } + + public static class Rectangle { + public double x; + public double y; + public double width; + public double height; + + public void setX(double x) { + this.x = x; + } + } + + public static void main(String[] args) throws Exception { + expect(new Double(42.0) == 42.0); + + { Rectangle r = new Rectangle(); + Rectangle.class.getMethod("setX", double.class).invoke(r, 42.0); + expect(r.x == 42.0); + } + + { double input[] = new double[8]; + double left[] = new double[8]; + double right[] = new double[8]; + + input[0] = 732.0; + input[1] = 952.0; + input[2] = 761.0; + input[3] = 942.0; + input[4] = 786.0; + input[5] = 944.0; + input[6] = 813.0; + input[7] = 939.0; + + subdivide(input, 0, left, 0, right, 0); + + expect(left[0] == 732.0); + expect(left[1] == 952.0); + expect(left[2] == 746.5); + expect(left[3] == 947.0); + expect(left[4] == 760.0); + expect(left[5] == 945.0); + expect(left[6] == 773.25); + expect(left[7] == 943.625); + + expect(right[0] == 773.25); + expect(right[1] == 943.625); + expect(right[2] == 786.5); + expect(right[3] == 942.25); + expect(right[4] == 799.5); + expect(right[5] == 941.5); + expect(right[6] == 813.0); + expect(right[7] == 939.0); + } + + expect(multiply(0.5d, 0.5d) == 0.25d); + expect(multiply(0.5f, 0.5f) == 0.25f); + + expect(multiply(0.5d, 0.1d) == 0.05d); + expect(multiply(0.5f, 0.1f) == 0.05f); + + expect(multiply(0.5d, 0.5d) < 0.5d); + expect(multiply(0.5f, 0.5f) < 0.5f); + + expect(multiply(0.5d, 0.1d) < 0.5d); + expect(multiply(0.5f, 0.1f) < 0.5f); + + expect(multiply(0.5d, 0.5d) > 0.1d); + expect(multiply(0.5f, 0.5f) > 0.1f); + + expect(multiply(0.5d, 0.1d) > 0.01d); + expect(multiply(0.5f, 0.1f) > 0.01f); + + expect(divide(0.5d, 0.5d) == 1.0d); + + expect(divide(0.5d, 0.1d) == 5.0d); + + expect(subtract(0.5d, 0.5d) == 0.0d); + + expect(subtract(0.5d, 0.1d) == 0.4d); + + { double d = 1d; + expect(((int) d) == 1); + } + + { double d = 12345d; + expect(((int) d) == 12345); + } + + expect(doubleToInt(new Floats()) == 100); + + { Floats f = new Floats(); + f.field = 32.0d; + expect(loadAndMultiply(2.0d, f) == 64.0d); + } + + { Floats f = new Floats(); + f.field = 32.0d; + expect(multiply(2.0d, f.field) == 64.0d); + } + + { Floats f = new Floats(); + multiplyAndStore(32.0d, 0.5d, f); + expect(f.field == 16.0d); + } + + { float f = 1f; + expect(((int) f) == 1); + } + + { float f = 1f; + expect(((long) f) == 1); + } + + expect(Math.round(0.4f) == 0); + expect(Math.round(0.5f) == 1); + expect(Math.round(1.0f) == 1); + expect(Math.round(1.9f) == 2); + + expect(Math.round(0.4d) == 0); + expect(Math.round(0.5d) == 1); + expect(Math.round(1.0d) == 1); + expect(Math.round(1.9d) == 2); + + { float b = 1.0f; + int blue = (int)(b * 255 + 0.5); + expect(blue == 255); + } + + { long z = 6553311036568663L; + double d = (double) z; + expect(d == 6553311036568663.0); + } + + { long z = 12345L; + float f = (float) z; + expect(f == 12345.0); + } + + { int z = 12345; + float f = (float) z; + expect(f == 12345.0); + } + + { int z = 12345; + double d = (double) z; + expect(d == 12345.0); + } + + // Test floatToIntBits + { + int orig = 0x7f800001; + float NaN = Float.intBitsToFloat(orig); + int result = Float.floatToIntBits(NaN); + int expected = 0x7fc00000; + expect(result == expected); + } + + { + int orig = 0x7f801001; + float NaN = Float.intBitsToFloat(orig); + int result = Float.floatToIntBits(NaN); + int expected = 0x7fc00000; + expect(result == expected); + } + + { + int orig = 0x00800001; + float number = Float.intBitsToFloat(orig); + int result = Float.floatToIntBits(number); + expect(result == orig); + } + + { + int orig = 0x80800003; + float number = Float.intBitsToFloat(orig); + int result = Float.floatToIntBits(number); + expect(result == orig); + } + + for (int x = 0; x < 1000; ++x) { + int m = 100; + int n = 200; + double array[][] = new double[m][n]; + + for (int i = 0; i < m; ++i) { + for (int j = 0; j < n; ++j) { + array[i][j] = 1234567890.0; + } + } + } + + { double v = Double.NaN; + expect(0 == (int) v); } + + { double v = Double.NEGATIVE_INFINITY; + expect(Integer.MIN_VALUE == (int) v); } + + { double v = Long.MIN_VALUE; + expect(Integer.MIN_VALUE == (int) v); } + + { double v = Double.POSITIVE_INFINITY; + expect(Integer.MAX_VALUE == (int) v); } + + { double v = Long.MAX_VALUE; + expect(Integer.MAX_VALUE == (int) v); } + + { float v = Float.NaN; + expect(0 == (int) v); } + + { float v = Float.NEGATIVE_INFINITY; + expect(Integer.MIN_VALUE == (int) v); } + + { float v = Integer.MIN_VALUE; + expect(Integer.MIN_VALUE == (int) v); } + + { float v = Float.POSITIVE_INFINITY; + expect(Integer.MAX_VALUE == (int) v); } + + { float v = Integer.MAX_VALUE; + expect(Integer.MAX_VALUE == (int) v); } + + { double v = Double.NaN; + expect(0 == (long) v); } + + { double v = Double.NEGATIVE_INFINITY; + expect(Long.MIN_VALUE == (long) v); } + + { double v = Long.MIN_VALUE; + expect(Long.MIN_VALUE == (long) v); } + + { double v = Double.POSITIVE_INFINITY; + expect(Long.MAX_VALUE == (long) v); } + + { double v = Long.MAX_VALUE; + expect(Long.MAX_VALUE == (long) v); } + + { float v = Float.NaN; + expect(0 == (long) v); } + + { float v = Float.NEGATIVE_INFINITY; + expect(Long.MIN_VALUE == (long) v); } + + { float v = Integer.MIN_VALUE; + expect(Integer.MIN_VALUE == (long) v); } + + { float v = Float.POSITIVE_INFINITY; + expect(Long.MAX_VALUE == (long) v); } + + expect(Double.NaN != Double.NaN); + expect(! (Double.NaN == Double.NaN)); + + { double d = Double.NaN; + expect(Double.NaN != d); + expect(! (Double.NaN == d)); + expect(d != d); + expect(! (d == d)); } + + expect(Float.NaN != Float.NaN); + expect(! (Float.NaN == Float.NaN)); + + { float d = Float.NaN; + expect(Float.NaN != d); + expect(! (Float.NaN == d)); + expect(d != d); + expect(! (d == d)); } + } +} diff --git a/sgx-jvm/avian/test/FormatStrings.java b/sgx-jvm/avian/test/FormatStrings.java new file mode 100644 index 0000000000..32e8305012 --- /dev/null +++ b/sgx-jvm/avian/test/FormatStrings.java @@ -0,0 +1,296 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +/* + * @author bcg + */ +public class FormatStrings { + + public static void main(String... args) throws Exception { + FormatStrings test = new FormatStrings(); + test.testLiteral(); + test.testString(); + test.testNewline(); + test.testPercent(); + test.testBoolean(); + test.testCharacter(); + test.testHashCode(); + test.testIntegers(); + test.testWidths(); + test.testPrecisions(); + } + + private void _testFormat(String expected, String format, Object... args) { + String actual = String.format(format, args); + ensureEquals(expected, actual); + System.err.println("Expected: " + expected + ", Actual: " + actual); + } + + private static void ensureEquals(String expected, String actual) { + if (expected != actual) { + if ((expected == null || actual == null) || !(expected.equals(actual))) { + throw new IllegalArgumentException( + "Expected `" + expected + "` but was actually `" + actual + "`."); + } + } + } + + public void testLiteral() { + _testFormat("test Literal 1", "test Literal 1"); + _testFormat("test Literal 2", "test Literal 2", (Object[]) null); + _testFormat("test Literal 3", "test Literal 3", new Object[0]); + } + + public void testString() { + _testFormat("test String 1", "test %s", "String 1"); + _testFormat("test String null", "test String %s", new Object[]{null} ); + _testFormat("test String 2", "test %2$s", "String 1", "String 2"); + _testFormat("String `string`", "String `%s`", new String("string")); + _testFormat("String `STRING`", "String `%S`", new String("string")); + _testFormat("String `another string`", "String `%s`", new String("another string")); + _testFormat("String `ANOTHER STRING`", "String `%S`", new String("another string")); + _testFormat("String `null`", "String `%s`", (String)null); + _testFormat("String `NULL`", "String `%S`", (String)null); + _testFormat("String `true`", "String `%s`", new Boolean("true")); + _testFormat("String `TRUE`", "String `%S`", new Boolean("true")); + _testFormat("String `false`", "String `%s`", new Boolean("false")); + _testFormat("String `FALSE`", "String `%S`", new Boolean("false")); + } + + public void testNewline() { + final String newline = System.getProperty("line.separator"); + _testFormat( + "<<<" + newline + " test newlines" + newline + ">>>", + "<<<%n test newlines%n>>>" + ); + } + + public void testBoolean() { + _testFormat("test boolean true", "test boolean %b", true); + _testFormat("test Boolean true", "test Boolean %b", Boolean.TRUE); + _testFormat("test boolean false", "test boolean %b", false); + _testFormat("test Boolean false", "test Boolean %b", Boolean.FALSE); + _testFormat("test null Boolean (false)", "test null Boolean (%b)", new Object[]{(Boolean)null}); + _testFormat("test non-null Boolean (true)", "test non-null Boolean (%b)", new Object()); + _testFormat("test boolean string (true)", "test boolean string (%b)", "false"); + _testFormat("Boolean `true`", "Boolean `%b`", new Boolean("true")); + _testFormat("Boolean `TRUE`", "Boolean `%B`", new Boolean("true")); + _testFormat("Boolean `false`", "Boolean `%b`", new Boolean("false")); + _testFormat("Boolean `FALSE`", "Boolean `%B`", new Boolean("false")); + _testFormat("Boolean `false`", "Boolean `%b`", (String)null); + _testFormat("Boolean `FALSE`", "Boolean `%B`", (String)null); + _testFormat("Boolean `true`", "Boolean `%b`", new String("")); + _testFormat("Boolean `TRUE`", "Boolean `%B`", new String("")); + _testFormat("Boolean `true`", "Boolean `%b`", new String("true")); + _testFormat("Boolean `TRUE`", "Boolean `%B`", new String("true")); + _testFormat("Boolean `true`", "Boolean `%b`", new String("false")); + _testFormat("Boolean `TRUE`", "Boolean `%B`", new String("false")); + } + + public void testPercent() { + _testFormat("Percents work 100%", "Percents work 100%%"); + } + + public void testCharacter() { + _testFormat("test character such as a", "test character such as %c", 'a'); + _testFormat("test character such as b", "test character such as %c", (int) 98); + _testFormat("test character such as c", "test character such as %c", (byte) 99); + _testFormat("test character such as d", "test character such as %c", (short) 100); + } + + public void testHashCode() { + final Object obj1 = new Object(); + final Object obj2 = new Object(); + final String hc1 = Integer.toHexString(obj1.hashCode()); + final String hc2 = Integer.toHexString(obj2.hashCode()); + _testFormat("test hashcode 1 (" + hc1 + ")" , "test hashcode 1 (%h)", obj1, obj2); + _testFormat("test hashcode 2 (" + hc2 + ")" , "test hashcode 2 (%2$h)", obj1, obj2); + _testFormat("test hashcode null", "test hashcode %h", (String) null); + } + + public void testIntegers() { + + _testFormat("Long 1", "Long %d", new Long(1)); + _testFormat("Long 2", "Long %2$d", new Long(1), new Long(2)); + _testFormat("Integer 1", "Integer %d", new Integer(1)); + _testFormat("Integer 2", "Integer %2$d", new Integer(1), new Integer(2)); + _testFormat("Short 1", "Short %d", new Short((short)1)); + _testFormat("Short 2", "Short %2$d", new Short((short)1), new Short((short)2)); + _testFormat("Byte 1", "Byte %d", new Byte((byte)1)); + _testFormat("Byte 2", "Byte %2$d", new Byte((byte)1), new Byte((byte)2)); + + _testFormat("Long 144", "Long %o", new Long(100)); + _testFormat("Long 310", "Long %2$o", new Long(100), new Long(200)); + _testFormat("Integer 144", "Integer %o", new Integer(100)); + _testFormat("Integer 310", "Integer %2$o", new Integer(100), new Integer(200)); + _testFormat("Short 144", "Short %o", new Short((short)100)); + _testFormat("Short 310", "Short %2$o", new Short((short)100), new Short((short)200)); + _testFormat("Byte 144", "Byte %o", new Byte((byte)100)); + _testFormat("Byte 310", "Byte %2$o", new Byte((byte)100), new Byte((byte)200)); + + _testFormat("Long 64", "Long %x", new Long(100)); + _testFormat("Long c8", "Long %2$x", new Long(100), new Long(200)); + _testFormat("Long C8", "Long %2$X", new Long(100), new Long(200)); + _testFormat("Integer 64", "Integer %x", new Integer(100)); + _testFormat("Integer c8", "Integer %2$x", new Integer(100), new Integer(200)); + _testFormat("Short 64", "Short %x", new Short((short)100)); + _testFormat("Short C8", "Short %2$X", new Short((short)100), new Short((short)200)); + _testFormat("Byte 64", "Byte %x", new Byte((byte)100)); + _testFormat("Byte c8", "Byte %2$x", new Byte((byte)100), new Byte((byte)200)); + + _testFormat("Decimal `1`", "Decimal `%d`", new Integer((int)1)); + _testFormat("Decimal `0`", "Decimal `%d`", new Integer((int)0)); + _testFormat("Decimal `100`", "Decimal `%d`", new Integer((int)100)); + _testFormat("Decimal `100000`", "Decimal `%d`", new Integer((int)100000)); + _testFormat("Decimal `63`", "Decimal `%d`", new Integer((int)63)); + _testFormat("Decimal `64`", "Decimal `%d`", new Integer((int)64)); + _testFormat("Decimal `-1`", "Decimal `%d`", new Integer((int)-1)); + _testFormat("Decimal `-100`", "Decimal `%d`", new Integer((int)-100)); + _testFormat("Decimal `-100000`", "Decimal `%d`", new Integer((int)-100000)); + _testFormat("Decimal `1`", "Decimal `%d`", new Byte((byte)1)); + _testFormat("Decimal `0`", "Decimal `%d`", new Byte((byte)0)); + _testFormat("Decimal `100`", "Decimal `%d`", new Byte((byte)100)); + _testFormat("Decimal `63`", "Decimal `%d`", new Byte((byte)63)); + _testFormat("Decimal `64`", "Decimal `%d`", new Byte((byte)64)); + _testFormat("Decimal `-1`", "Decimal `%d`", new Byte((byte)-1)); + _testFormat("Decimal `-100`", "Decimal `%d`", new Byte((byte)-100)); + _testFormat("Decimal `1`", "Decimal `%d`", new Long((long)1)); + _testFormat("Decimal `0`", "Decimal `%d`", new Long((long)0)); + _testFormat("Decimal `100`", "Decimal `%d`", new Long((long)100)); + _testFormat("Decimal `100000`", "Decimal `%d`", new Long((long)100000)); + _testFormat("Decimal `63`", "Decimal `%d`", new Long((long)63)); + _testFormat("Decimal `64`", "Decimal `%d`", new Long((long)64)); + _testFormat("Decimal `-1`", "Decimal `%d`", new Long((long)-1)); + _testFormat("Decimal `-100`", "Decimal `%d`", new Long((long)-100)); + _testFormat("Decimal `-100000`", "Decimal `%d`", new Long((long)-100000)); + _testFormat("Decimal `1`", "Decimal `%d`", new Short((short)1)); + _testFormat("Decimal `0`", "Decimal `%d`", new Short((short)0)); + _testFormat("Decimal `100`", "Decimal `%d`", new Short((short)100)); + _testFormat("Decimal `63`", "Decimal `%d`", new Short((short)63)); + _testFormat("Decimal `64`", "Decimal `%d`", new Short((short)64)); + _testFormat("Decimal `-1`", "Decimal `%d`", new Short((short)-1)); + _testFormat("Decimal `-100`", "Decimal `%d`", new Short((short)-100)); + + _testFormat("Octal `1`", "Octal `%o`", new Integer((int)1)); + _testFormat("Octal `0`", "Octal `%o`", new Integer((int)0)); + _testFormat("Octal `144`", "Octal `%o`", new Integer((int)100)); + _testFormat("Octal `303240`", "Octal `%o`", new Integer((int)100000)); + _testFormat("Octal `77`", "Octal `%o`", new Integer((int)63)); + _testFormat("Octal `100`", "Octal `%o`", new Integer((int)64)); + _testFormat("Octal `37777777777`", "Octal `%o`", new Integer((int)-1)); + _testFormat("Octal `37777777634`", "Octal `%o`", new Integer((int)-100)); + _testFormat("Octal `37777474540`", "Octal `%o`", new Integer((int)-100000)); + _testFormat("Octal `1`", "Octal `%o`", new Byte((byte)1)); + _testFormat("Octal `0`", "Octal `%o`", new Byte((byte)0)); + _testFormat("Octal `144`", "Octal `%o`", new Byte((byte)100)); + _testFormat("Octal `77`", "Octal `%o`", new Byte((byte)63)); + _testFormat("Octal `100`", "Octal `%o`", new Byte((byte)64)); + _testFormat("Octal `377`", "Octal `%o`", new Byte((byte)-1)); + _testFormat("Octal `234`", "Octal `%o`", new Byte((byte)-100)); + _testFormat("Octal `1`", "Octal `%o`", new Long((long)1)); + _testFormat("Octal `0`", "Octal `%o`", new Long((long)0)); + _testFormat("Octal `144`", "Octal `%o`", new Long((long)100)); + _testFormat("Octal `303240`", "Octal `%o`", new Long((long)100000)); + _testFormat("Octal `77`", "Octal `%o`", new Long((long)63)); + _testFormat("Octal `100`", "Octal `%o`", new Long((long)64)); + _testFormat("Octal `1`", "Octal `%o`", new Short((short)1)); + _testFormat("Octal `0`", "Octal `%o`", new Short((short)0)); + _testFormat("Octal `144`", "Octal `%o`", new Short((short)100)); + _testFormat("Octal `77`", "Octal `%o`", new Short((short)63)); + _testFormat("Octal `100`", "Octal `%o`", new Short((short)64)); + _testFormat("Octal `177777`", "Octal `%o`", new Short((short)-1)); + _testFormat("Octal `177634`", "Octal `%o`", new Short((short)-100)); + + _testFormat("HexDec `1`", "HexDec `%x`", new Integer((int)1)); + _testFormat("HexDec `1`", "HexDec `%X`", new Integer((int)1)); + _testFormat("HexDec `0`", "HexDec `%x`", new Integer((int)0)); + _testFormat("HexDec `0`", "HexDec `%X`", new Integer((int)0)); + _testFormat("HexDec `64`", "HexDec `%x`", new Integer((int)100)); + _testFormat("HexDec `64`", "HexDec `%X`", new Integer((int)100)); + _testFormat("HexDec `186a0`", "HexDec `%x`", new Integer((int)100000)); + _testFormat("HexDec `186A0`", "HexDec `%X`", new Integer((int)100000)); + _testFormat("HexDec `3f`", "HexDec `%x`", new Integer((int)63)); + _testFormat("HexDec `3F`", "HexDec `%X`", new Integer((int)63)); + _testFormat("HexDec `40`", "HexDec `%x`", new Integer((int)64)); + _testFormat("HexDec `40`", "HexDec `%X`", new Integer((int)64)); + _testFormat("HexDec `ffffffff`", "HexDec `%x`", new Integer((int)-1)); + _testFormat("HexDec `FFFFFFFF`", "HexDec `%X`", new Integer((int)-1)); + _testFormat("HexDec `ffffff9c`", "HexDec `%x`", new Integer((int)-100)); + _testFormat("HexDec `FFFFFF9C`", "HexDec `%X`", new Integer((int)-100)); + _testFormat("HexDec `fffe7960`", "HexDec `%x`", new Integer((int)-100000)); + _testFormat("HexDec `FFFE7960`", "HexDec `%X`", new Integer((int)-100000)); + _testFormat("HexDec `1`", "HexDec `%x`", new Byte((byte)1)); + _testFormat("HexDec `1`", "HexDec `%X`", new Byte((byte)1)); + _testFormat("HexDec `0`", "HexDec `%x`", new Byte((byte)0)); + _testFormat("HexDec `0`", "HexDec `%X`", new Byte((byte)0)); + _testFormat("HexDec `64`", "HexDec `%x`", new Byte((byte)100)); + _testFormat("HexDec `64`", "HexDec `%X`", new Byte((byte)100)); + _testFormat("HexDec `3f`", "HexDec `%x`", new Byte((byte)63)); + _testFormat("HexDec `3F`", "HexDec `%X`", new Byte((byte)63)); + _testFormat("HexDec `40`", "HexDec `%x`", new Byte((byte)64)); + _testFormat("HexDec `40`", "HexDec `%X`", new Byte((byte)64)); + _testFormat("HexDec `ff`", "HexDec `%x`", new Byte((byte)-1)); + _testFormat("HexDec `FF`", "HexDec `%X`", new Byte((byte)-1)); + _testFormat("HexDec `9c`", "HexDec `%x`", new Byte((byte)-100)); + _testFormat("HexDec `9C`", "HexDec `%X`", new Byte((byte)-100)); + _testFormat("HexDec `1`", "HexDec `%x`", new Long((long)1)); + _testFormat("HexDec `1`", "HexDec `%X`", new Long((long)1)); + _testFormat("HexDec `0`", "HexDec `%x`", new Long((long)0)); + _testFormat("HexDec `0`", "HexDec `%X`", new Long((long)0)); + _testFormat("HexDec `64`", "HexDec `%x`", new Long((long)100)); + _testFormat("HexDec `64`", "HexDec `%X`", new Long((long)100)); + _testFormat("HexDec `186a0`", "HexDec `%x`", new Long((long)100000)); + _testFormat("HexDec `186A0`", "HexDec `%X`", new Long((long)100000)); + _testFormat("HexDec `3f`", "HexDec `%x`", new Long((long)63)); + _testFormat("HexDec `3F`", "HexDec `%X`", new Long((long)63)); + _testFormat("HexDec `40`", "HexDec `%x`", new Long((long)64)); + _testFormat("HexDec `40`", "HexDec `%X`", new Long((long)64)); + _testFormat("HexDec `ffffffffffffffff`", "HexDec `%x`", new Long((long)-1)); + _testFormat("HexDec `FFFFFFFFFFFFFFFF`", "HexDec `%X`", new Long((long)-1)); + _testFormat("HexDec `ffffffffffffff9c`", "HexDec `%x`", new Long((long)-100)); + _testFormat("HexDec `FFFFFFFFFFFFFF9C`", "HexDec `%X`", new Long((long)-100)); + _testFormat("HexDec `fffffffffffe7960`", "HexDec `%x`", new Long((long)-100000)); + _testFormat("HexDec `FFFFFFFFFFFE7960`", "HexDec `%X`", new Long((long)-100000)); + _testFormat("HexDec `1`", "HexDec `%x`", new Short((short)1)); + _testFormat("HexDec `1`", "HexDec `%X`", new Short((short)1)); + _testFormat("HexDec `0`", "HexDec `%x`", new Short((short)0)); + _testFormat("HexDec `0`", "HexDec `%X`", new Short((short)0)); + _testFormat("HexDec `64`", "HexDec `%x`", new Short((short)100)); + _testFormat("HexDec `64`", "HexDec `%X`", new Short((short)100)); + _testFormat("HexDec `3f`", "HexDec `%x`", new Short((short)63)); + _testFormat("HexDec `3F`", "HexDec `%X`", new Short((short)63)); + _testFormat("HexDec `40`", "HexDec `%x`", new Short((short)64)); + _testFormat("HexDec `40`", "HexDec `%X`", new Short((short)64)); + _testFormat("HexDec `ffff`", "HexDec `%x`", new Short((short)-1)); + _testFormat("HexDec `FFFF`", "HexDec `%X`", new Short((short)-1)); + _testFormat("HexDec `ff9c`", "HexDec `%x`", new Short((short)-100)); + _testFormat("HexDec `FF9C`", "HexDec `%X`", new Short((short)-100)); + } + + public void testWidths() { + _testFormat("0001", "%04d", 1); + _testFormat(" 1", "%4d", 1); + _testFormat(" 11", "%4x", 17); + _testFormat("0011", "%04x", 17); + _testFormat(" a", "%2x", 10); + _testFormat(" A", "%2X", 10); + _testFormat("a ", "%-2x", 10); + _testFormat("A ", "%-2X", 10); + _testFormat("10000", "%4d", 10000); + _testFormat("Hello World ", "%-15s", "Hello World"); + _testFormat(" Hello World", "%15s", "Hello World"); + } + + public void testPrecisions() { + _testFormat("Hello", "%-1.5s", "Hello World"); + _testFormat("Hello", "%1.5s", "Hello World"); + } + +} diff --git a/sgx-jvm/avian/test/FutureTaskTest.java b/sgx-jvm/avian/test/FutureTaskTest.java new file mode 100644 index 0000000000..7a8ea9d9a7 --- /dev/null +++ b/sgx-jvm/avian/test/FutureTaskTest.java @@ -0,0 +1,105 @@ +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.FutureTask; +import java.util.concurrent.RunnableFuture; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + +public class FutureTaskTest { + private static final int DELAY_TIME = 10; + + public static void main(String[] args) throws InterruptedException, ExecutionException { + isDoneTest(false); + isDoneTest(true); + getCallableResultTest(); + getRunnableResultTest(); + getTimeoutFail(); + getExecutionExceptionTest(); + } + + private static void isDoneTest(final boolean throwException) { + RunnableFuture future = new FutureTask(new Runnable() { + @Override + public void run() { + if (throwException) { + throw new RuntimeException(); + } + } + }, null); + + // should finish the future + future.run(); + + if (! future.isDone()) { + throw new RuntimeException("Future should be done"); + } + } + + private static void getCallableResultTest() throws InterruptedException, ExecutionException { + final Object result = new Object(); + FutureTask future = new FutureTask(new Callable() { + @Override + public Object call() throws Exception { + return result; + } + }); + + future.run(); + if (future.get() != result) { + throw new RuntimeException("Bad result returned: " + future.get()); + } + } + + private static void getRunnableResultTest() throws InterruptedException, ExecutionException { + final Object result = new Object(); + FutureTask future = new FutureTask(new Runnable() { + @Override + public void run() { + // nothing here + } + }, result); + + future.run(); + if (future.get() != result) { + throw new RuntimeException("Bad result returned: " + future.get()); + } + } + + private static void getTimeoutFail() throws InterruptedException, + ExecutionException { + RunnableFuture future = new FutureTask(new Runnable() { + @Override + public void run() { + // wont run + } + }, null); + + long startTime = System.currentTimeMillis(); + try { + future.get(DELAY_TIME, TimeUnit.MILLISECONDS); + throw new RuntimeException("Exception should have been thrown"); + } catch (TimeoutException e) { + long catchTime = System.currentTimeMillis(); + if (catchTime - startTime < DELAY_TIME) { + throw new RuntimeException("get with timeout did not block long enough"); + } + } + } + + private static void getExecutionExceptionTest() throws InterruptedException, ExecutionException { + FutureTask future = new FutureTask(new Runnable() { + @Override + public void run() { + throw new RuntimeException(); + } + }, null); + + future.run(); + try { + future.get(); + throw new RuntimeException("Exception should have thrown"); + } catch (ExecutionException e) { + // expected + } + } +} diff --git a/sgx-jvm/avian/test/GC.java b/sgx-jvm/avian/test/GC.java new file mode 100644 index 0000000000..9fabee0cc9 --- /dev/null +++ b/sgx-jvm/avian/test/GC.java @@ -0,0 +1,203 @@ +public class GC { + private static final Integer cache[] = new Integer[100]; + private static final Integer MAX_INT_OBJ = new Integer(Integer.MAX_VALUE); + + private static Integer valueOf(int i) { + try { + return cache[i]; + } catch (ArrayIndexOutOfBoundsException e) { + return (i == Integer.MAX_VALUE) ? MAX_INT_OBJ : new Integer(i); + } + } + + private static void small() { + for (int i = 0; i < 1024; ++i) { + byte[] a = new byte[4 * 1024]; + } + } + + private static void medium() { + for (int i = 0; i < 8; ++i) { + Object[] array = new Object[32]; + for (int j = 0; j < 32; ++j) { + array[j] = new byte[32 * 1024]; + } + } + } + + private static void large() { + for (int i = 0; i < 8; ++i) { + byte[] a = new byte[16 * 1024 * 1024]; + } + + for (int i = 0; i < 8; ++i) { + byte[] a = new byte[16 * 1024 * 1024]; + for (int j = 0; j < 32; ++j) { + byte[] b = new byte[32 * 1024]; + } + } + } + + private static void stackMap1(boolean predicate) { + if (predicate) { + Object a = null; + } + + System.gc(); + } + + private static void stackMap2(boolean predicate) { + if (predicate) { + int a = 42; + } else { + Object a = null; + } + + System.gc(); + } + + private static void stackMap3(boolean predicate) { + if (predicate) { + Object a = null; + } else { + int a = 42; + } + + System.gc(); + } + + private static void stackMap4(boolean predicate) { + int i = 2; + if (predicate) { + Object a = null; + } else { + Object a = null; + } + + do { + System.gc(); + int a = 42; + -- i; + } while (i >= 0); + } + + private static void noop() { } + + private static void stackMap5(boolean predicate) { + if (predicate) { + noop(); + } + + if (predicate) { + noop(); + } else { + Object a = null; + } + + System.gc(); + } + + private static void stackMap6(boolean predicate) { + if (predicate) { + int a = 42; + } else { + Object a = null; + } + + if (predicate) { + noop(); + } else { + Object a = null; + } + + noop(); + System.gc(); + } + + private static void stackMap7(boolean predicate) { + try { + if (predicate) { + Object a = null; + } else { + Object a = null; + } + + try { + int a = 42; + throw new DummyException(); + } finally { + System.gc(); + } + } catch (DummyException e) { + e.toString(); + } + } + + private static void stackMap8(boolean predicate) { + try { + Object x = new Object(); + if (predicate) { + Object a = null; + } else { + Object a = null; + } + + try { + int a = 42; + throw new DummyException(); + } finally { + System.gc(); + x.toString(); + } + } catch (DummyException e) { + e.toString(); + } + } + + public static void main(String[] args) { + valueOf(1000); + + Object[] array = new Object[1024 * 1024]; + array[0] = new Object(); + + small(); + + array[1] = new Object(); + + medium(); + + array[2] = new Object(); + + large(); + + array[0].toString(); + array[1].toString(); + array[2].toString(); + + stackMap1(true); + stackMap1(false); + + stackMap2(true); + stackMap2(false); + + stackMap3(true); + stackMap3(false); + + stackMap4(true); + stackMap4(false); + + stackMap5(true); + stackMap5(false); + + stackMap6(true); + stackMap6(false); + + stackMap7(true); + stackMap7(false); + + stackMap8(true); + stackMap8(false); + } + + private static class DummyException extends RuntimeException { } +} diff --git a/sgx-jvm/avian/test/Hello.java b/sgx-jvm/avian/test/Hello.java new file mode 100644 index 0000000000..d7d4f91935 --- /dev/null +++ b/sgx-jvm/avian/test/Hello.java @@ -0,0 +1,5 @@ +public class Hello { + public static void main(String[] args) { + System.out.println("hello, world!"); + } +} diff --git a/sgx-jvm/avian/test/Initializers.java b/sgx-jvm/avian/test/Initializers.java new file mode 100644 index 0000000000..5b6fe2c2cb --- /dev/null +++ b/sgx-jvm/avian/test/Initializers.java @@ -0,0 +1,24 @@ +public class Initializers { + private static class Static2 { + public static String foo = "Static2.foo"; + + static { + System.gc(); + new Exception().printStackTrace(); + } + } + + private static class Static1 { + public static String foo = "Static1.foo"; + + static { + System.out.println(Static2.foo); + } + } + + public static void main(String[] args) { + Object x = new Object(); + System.out.println(Static1.foo); + x.toString(); + } +} diff --git a/sgx-jvm/avian/test/Integers.java b/sgx-jvm/avian/test/Integers.java new file mode 100644 index 0000000000..7c977d6136 --- /dev/null +++ b/sgx-jvm/avian/test/Integers.java @@ -0,0 +1,324 @@ +public class Integers { + private static void expect(boolean v) { + if (! v) throw new RuntimeException(); + } + + private static int gcd(int m, int n) { + int temp; + m = Math.abs(m); + n = Math.abs(n); + if (m < n) { + temp = m; + m = n; + n = temp; + } + while (n != 0) { + temp = m; + m = n; + n = temp % n; + } + return m; + } + + public static void main(String[] args) throws Exception { + { int foo = 1028; + foo -= 1023; + expect(foo == 5); + } + + expect(gcd(12, 4) == 4); + + { int a = 2; + int b = 2; + int c = a + b; + } + + { int a = 2; + int c = a + a; + } + + { int a = -5; + int b = 2; + expect(a >> b == -5 >> 2); + expect(a >>> b == -5 >>> 2); + expect(a << b == -5 << 2); + expect(a + b == -5 + 2); + expect(a - b == -5 - 2); + expect(a * b == -5 * 2); + expect(a / b == -5 / 2); + expect(a % b == -5 % 2); + expect((a & b) == (-5 & 2)); + expect((a | b) == (-5 | 2)); + expect((a ^ b) == (-5 ^ 2)); + expect(-a == 5); + expect(~a == ~-5); + + a = 5; + b = 2; + expect(a >> b == 5 >> 2); + expect(a >>> b == 5 >>> 2); + expect(a << b == 5 << 2); + expect(a + b == 5 + 2); + expect(a - b == 5 - 2); + expect(a * b == 5 * 2); + expect(a / b == 5 / 2); + expect(a % b == 5 % 2); + expect((a & b) == (5 & 2)); + expect((a | b) == (5 | 2)); + expect((a ^ b) == (5 ^ 2)); + expect(-a == -5); + expect(~a == ~5); + } + + { int a = -5; + expect(a >> 2 == -5 >> 2); + expect(a >>> 2 == -5 >>> 2); + expect(a << 2 == -5 << 2); + expect(a + 2 == -5 + 2); + expect(a - 2 == -5 - 2); + expect(a * 2 == -5 * 2); + expect(a / 2 == -5 / 2); + expect(a % 2 == -5 % 2); + expect((a & 2) == (-5 & 2)); + expect((a | 2) == (-5 | 2)); + expect((a ^ 2) == (-5 ^ 2)); + + a = 5; + expect(a >> 2 == 5 >> 2); + expect(a >>> 2 == 5 >>> 2); + expect(a << 2 == 5 << 2); + expect(a + 2 == 5 + 2); + expect(a - 2 == 5 - 2); + expect(a * 2 == 5 * 2); + expect(a / 2 == 5 / 2); + expect(a % 2 == 5 % 2); + expect((a & 2) == (5 & 2)); + expect((a | 2) == (5 | 2)); + expect((a ^ 2) == (5 ^ 2)); + } + + { int a = -5; + int b = 1234567; + expect(a + b == -5 + 1234567); + expect(a - b == -5 - 1234567); + expect(a * b == -5 * 1234567); + expect(a / b == -5 / 1234567); + expect(a % b == -5 % 1234567); + expect((a & b) == (-5 & 1234567)); + expect((a | b) == (-5 | 1234567)); + expect((a ^ b) == (-5 ^ 1234567)); + + a = 5; + b = 1234567; + expect(a + b == 5 + 1234567); + expect(a - b == 5 - 1234567); + expect(a * b == 5 * 1234567); + expect(a / b == 5 / 1234567); + expect(a % b == 5 % 1234567); + expect((a & b) == (5 & 1234567)); + expect((a | b) == (5 | 1234567)); + expect((a ^ b) == (5 ^ 1234567)); + } + + { int a = -5; + expect(a + 1234567 == -5 + 1234567); + expect(a - 1234567 == -5 - 1234567); + expect(a * 1234567 == -5 * 1234567); + expect(a / 1234567 == -5 / 1234567); + expect(a % 1234567 == -5 % 1234567); + expect((a & 1234567) == (-5 & 1234567)); + expect((a | 1234567) == (-5 | 1234567)); + expect((a ^ 1234567) == (-5 ^ 1234567)); + + a = 5; + expect(a + 1234567 == 5 + 1234567); + expect(a - 1234567 == 5 - 1234567); + expect(a * 1234567 == 5 * 1234567); + expect(a / 1234567 == 5 / 1234567); + expect(a % 1234567 == 5 % 1234567); + expect((a & 1234567) == (5 & 1234567)); + expect((a | 1234567) == (5 | 1234567)); + expect((a ^ 1234567) == (5 ^ 1234567)); + } + + { int a = -1234567; + int b = 2; + expect(a >> b == -1234567 >> 2); + expect(a >>> b == -1234567 >>> 2); + expect(a << b == -1234567 << 2); + expect(a + b == -1234567 + 2); + expect(a - b == -1234567 - 2); + expect(a * b == -1234567 * 2); + expect(a / b == -1234567 / 2); + expect(a % b == -1234567 % 2); + expect((a & b) == (-1234567 & 2)); + expect((a | b) == (-1234567 | 2)); + expect((a ^ b) == (-1234567 ^ 2)); + expect(-a == 1234567); + expect(~a == ~-1234567); + + a = 1234567; + b = 2; + expect(a >> b == 1234567 >> 2); + expect(a >>> b == 1234567 >>> 2); + expect(a << b == 1234567 << 2); + expect(a + b == 1234567 + 2); + expect(a - b == 1234567 - 2); + expect(a * b == 1234567 * 2); + expect(a / b == 1234567 / 2); + expect(a % b == 1234567 % 2); + expect((a & b) == (1234567 & 2)); + expect((a | b) == (1234567 | 2)); + expect((a ^ b) == (1234567 ^ 2)); + expect(-a == -1234567); + expect(~a == ~1234567); + } + + { int a = -1234567; + expect(a >> 2 == -1234567 >> 2); + expect(a >>> 2 == -1234567 >>> 2); + expect(a << 2 == -1234567 << 2); + expect(a + 2 == -1234567 + 2); + expect(a - 2 == -1234567 - 2); + expect(a * 2 == -1234567 * 2); + expect(a / 2 == -1234567 / 2); + expect(a % 2 == -1234567 % 2); + expect((a & 2) == (-1234567 & 2)); + expect((a | 2) == (-1234567 | 2)); + expect((a ^ 2) == (-1234567 ^ 2)); + + a = 1234567; + expect(a >> 2 == 1234567 >> 2); + expect(a >>> 2 == 1234567 >>> 2); + expect(a << 2 == 1234567 << 2); + expect(a + 2 == 1234567 + 2); + expect(a - 2 == 1234567 - 2); + expect(a * 2 == 1234567 * 2); + expect(a / 2 == 1234567 / 2); + expect(a % 2 == 1234567 % 2); + expect((a & 2) == (1234567 & 2)); + expect((a | 2) == (1234567 | 2)); + expect((a ^ 2) == (1234567 ^ 2)); + } + + { int a = -1234567; + int b = 1234567; + expect(a + b == -1234567 + 1234567); + expect(a - b == -1234567 - 1234567); + expect(a * b == -1234567 * 1234567); + expect(a / b == -1234567 / 1234567); + expect(a % b == -1234567 % 1234567); + expect((a & b) == (-1234567 & 1234567)); + expect((a | b) == (-1234567 | 1234567)); + expect((a ^ b) == (-1234567 ^ 1234567)); + + a = 1234567; + b = 1234567; + expect(a + b == 1234567 + 1234567); + expect(a - b == 1234567 - 1234567); + expect(a * b == 1234567 * 1234567); + expect(a / b == 1234567 / 1234567); + expect(a % b == 1234567 % 1234567); + expect((a & b) == (1234567 & 1234567)); + expect((a | b) == (1234567 | 1234567)); + expect((a ^ b) == (1234567 ^ 1234567)); + } + + { int a = -1234567; + expect(a + 1234567 == -1234567 + 1234567); + expect(a - 1234567 == -1234567 - 1234567); + expect(a * 1234567 == -1234567 * 1234567); + expect(a / 1234567 == -1234567 / 1234567); + expect(a % 1234567 == -1234567 % 1234567); + expect((a & 1234567) == (-1234567 & 1234567)); + expect((a | 1234567) == (-1234567 | 1234567)); + expect((a ^ 1234567) == (-1234567 ^ 1234567)); + + a = 1234567; + expect(a + 1234567 == 1234567 + 1234567); + expect(a - 1234567 == 1234567 - 1234567); + expect(a * 1234567 == 1234567 * 1234567); + expect(a / 1234567 == 1234567 / 1234567); + expect(a % 1234567 == 1234567 % 1234567); + expect((a & 1234567) == (1234567 & 1234567)); + expect((a | 1234567) == (1234567 | 1234567)); + expect((a ^ 1234567) == (1234567 ^ 1234567)); + } + + { int get_buffer = 2144642881; + int bits_left = 30; + int l = 9; + int code = (((get_buffer >> (bits_left -= (l)))) & ((1<<(l))-1)); + expect(code == 510); + } + + { int width = 8; + int height = 8; + int depth = 24; + int scanlinePad = 4; + + int bytesPerLine = (((width * depth + 7) / 8) + (scanlinePad - 1)) + / scanlinePad * scanlinePad; + expect(bytesPerLine == 24); + } + + { int y = -11760768; + expect((y + 0x8000) == (-11760768 + 0x8000)); } + + expect(Math.min(796, 1069) == 796); + + { int b = 1; + expect((b << 32) == 1); } + + { int b = 0xFFFFFFFF; + expect((b >>> -1) == 1); } + + { int b = 0x10000000; + expect((b >> -31) == 0x8000000); } + + { int b = 1; int s = 32; + expect((b << s) == 1); } + + { int b = 0xFFFFFFFF; int s = -1; + expect((b >>> s) == 1); } + + { int b = 0x10000000; int s = -31; + expect((b >> s) == 0x8000000); } + + { int b = 0xBE; + expect((b & 0xFF) == 0xBE); } + + { int b = 0xBE; + expect((b >>> 0) == 0xBE); } + + { int b = 0xBE; + expect((b >> 0) == 0xBE); } + + { int b = 0xBE; + expect((b << 0) == 0xBE); } + + { int b = 0xBE; + expect(((b >>> 0) & 0xFF) == 0xBE); } + + { int b = 0xBE; int x = 0xFF; + expect((b & x) == 0xBE); } + + { int b = 0xBE; int x = 0; + expect((b >>> x) == 0xBE); } + + { int b = 0xBE; int x = 0; + expect((b >> x) == 0xBE); } + + { int b = 0xBE; int x = 0; + expect((b << x) == 0xBE); } + + { int b = 0xBE; int x = 0; int y = 0xFF; + expect(((b >>> x) & y) == 0xBE); } + + expect(123 == Integer.decode("123").intValue()); + expect(-123 == Integer.decode("-123").intValue()); + expect(-83 == Integer.decode("-0123").intValue()); + expect(-291 == Integer.decode("-0x123").intValue()); + expect(291 == Integer.decode("#123").intValue()); + } +} diff --git a/sgx-jvm/avian/test/InvokeDynamic.java b/sgx-jvm/avian/test/InvokeDynamic.java new file mode 100644 index 0000000000..6d6e2842aa --- /dev/null +++ b/sgx-jvm/avian/test/InvokeDynamic.java @@ -0,0 +1,111 @@ +public class InvokeDynamic { + private final int foo; + + private InvokeDynamic(int foo) { + this.foo = foo; + } + + private interface Operation { + int operate(int a, int b); + } + + private interface Operation2 { + long operate(long a, int b); + } + + private static class Pair { + public final A first; + public final B second; + + public Pair(A first, B second) { + this.first = first; + this.second = second; + } + } + + private interface Supplier extends java.io.Serializable { + T get(); + } + + private static void expect(boolean v) { + if (! v) throw new RuntimeException(); + } + + public static void main(String[] args) { + int c = 4; + Operation op = (a, b) -> a + b - c; + expect(op.operate(2, 3) == (2 + 3) - 4); + + for (int i = 0; i < 4; ++i) { + new InvokeDynamic(i).test(); + } + } + + private interface Foo extends java.io.Serializable { + void someFunction(Integer a, Integer b, String s); + } + + private interface UnboxedSerializable extends java.io.Serializable { + int add(int a, int b); + } + + private interface Unboxed { + int add(int a, int b); + } + + private void requiresBridge(Number a, Object... rest) { + String s = "" + a; + for (Object r : rest) { + s += r; + } + } + + private static Integer addBoxed(Integer a, Integer b) { + return a + b; + } + + private interface Marker { + } + + private void test() { + { int c = 2; + Operation op = (a, b) -> ((a + b) * c) - foo; + expect(op.operate(2, 3) == ((2 + 3) * 2) - foo); + } + + { int c = 2; + Operation2 op = (a, b) -> ((a + b) * c) - foo; + expect(op.operate(2, 3) == ((2 + 3) * 2) - foo); + } + + { Supplier> s = () -> new Pair(42L, 77.1D); + expect(s.get().first == 42L); + expect(s.get().second == 77.1D); + } + + { double[] a = new double[] { 3.14D }; + Supplier> s = () -> new Pair(42L, a[0]); + expect(s.get().first == 42L); + expect(s.get().second == 3.14D); + } + + { Foo s = this::requiresBridge; + s.someFunction(1, 2, ""); + } + + // This abort()s in machine.cpp + // { Foo s = (Foo & Marker) this::requiresBridge; + // s.someFunction(1, 2, ""); + // } + + // NPE + // { UnboxedSerializable s = InvokeDynamic::addBoxed; + // expect(s.add(1, 2) == 3); + // } + + // NPE + // { Unboxed s = InvokeDynamic::addBoxed; + // expect(s.add(1, 2) == 3); + // } + } +} diff --git a/sgx-jvm/avian/test/JNI.java b/sgx-jvm/avian/test/JNI.java new file mode 100644 index 0000000000..b0583b6606 --- /dev/null +++ b/sgx-jvm/avian/test/JNI.java @@ -0,0 +1,141 @@ +import java.lang.reflect.Method; +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; + +public class JNI { + private static boolean onLoadCalled; + + static { + System.loadLibrary("test"); + } + + private static void expect(boolean v) { + if (! v) throw new RuntimeException(); + } + + private static float echo(float f) { + return f; + } + + private static native float doEcho(float f); + + private static double echo(double f) { + return f; + } + + private static native double doEcho(double f); + + private static native double addDoubles + (double a1, double a2, double a3, double a4, double a5, double a6, + double a7, double a8, double a9, double a10, double a11, double a12, + double a13, double a14, double a15, double a16, double a17, double a18, + double a19, double a20); + + private static native float addFloats + (float a1, float a2, float a3, float a4, float a5, float a6, + float a7, float a8, float a9, float a10, float a11, float a12, + float a13, float a14, float a15, float a16, float a17, float a18, + float a19, float a20); + + private static native double addMix + (float a1, double a2, float a3, double a4, float a5, float a6, + float a7, float a8, float a9, float a10, float a11, float a12, + float a13, float a14, float a15, double a16, float a17, float a18, + float a19, float a20); + + private static native int addStackBoundary2 + (Object o1, Object o2, Object o3, int i1, int i2); + + private static native int addStackBoundary3 + (Object o1, Object o2, Object o3, int i1, int i2, int i3); + + private static native int addStackBoundary4 + (Object o1, Object o2, Object o3, int i1, int i2, int i3, int i4); + + private static native int addStackBoundary5 + (Object o1, Object o2, Object o3, int i1, int i2, int i3, int i4, int i5); + + private static native int addStackBoundary6 + (Object o1, Object o2, Object o3, int i1, int i2, int i3, int i4, int i5, int i6); + + private static native long fromReflectedMethod(Object m); + + private static native Object toReflectedMethod(Class c, long id, + boolean isStatic); + + private static native int callStaticIntMethod(Class c, long id); + + private static native Object newObject(Class c, long id); + + private static native long fromReflectedField(Field f); + + private static native Field toReflectedField(Class c, long id, + boolean isStatic); + + private static native int getStaticIntField(Class c, long id); + + private static native Object testLocalRef(Object o); + + public static int method242() { return 242; } + + public static final int field950 = 950; + + public static void main(String[] args) throws Exception { + expect(onLoadCalled); + + expect(addDoubles + (1.0d, 2.0d, 3.0d, 4.0d, 5.0d, 6.0d, 7.0d, 8.0d, 9.0d, 10.0d, 11.0d, + 12.0d, 13.0d, 14.0d, 15.0d, 16.0d, 17.0d, 18.0d, 19.0d, 20.0d) + == 210.0d); + + expect(addFloats + (1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 10.0f, 11.0f, + 12.0f, 13.0f, 14.0f, 15.0f, 16.0f, 17.0f, 18.0f, 19.0f, 20.0f) + == 210.0f); + + expect(addMix + (1.0f, 2.0d, 3.0f, 4.0d, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 10.0f, 11.0f, + 12.0f, 13.0f, 14.0f, 15.0f, 16.0d, 17.0f, 18.0f, 19.0f, 20.0f) + == 210.0d); + + expect(addStackBoundary2(null, null, null, 1, 10) == 11); + expect(addStackBoundary3(null, null, null, 1, 10, 100) == 111); + expect(addStackBoundary4(null, null, null, 1, 10, 100, 1000) == 1111); + expect(addStackBoundary5(null, null, null, 1, 10, 100, 1000, 10000) == 11111); + expect(addStackBoundary6(null, null, null, 1, 10, 100, 1000, 10000, 100000) == 111111); + + expect(doEcho(42.0f) == 42.0f); + expect(doEcho(42.0d) == 42.0d); + + expect(callStaticIntMethod + (JNI.class, fromReflectedMethod + (JNI.class.getMethod("method242"))) == 242); + + expect(((Method) toReflectedMethod + (JNI.class, fromReflectedMethod + (JNI.class.getMethod("method242")), true)) + .getName().equals("method242")); + + expect(newObject + (JNI.class, fromReflectedMethod + (JNI.class.getConstructor())) instanceof JNI); + + expect(((Constructor) toReflectedMethod + (JNI.class, fromReflectedMethod + (JNI.class.getConstructor()), false)) + .getDeclaringClass().equals(JNI.class)); + + expect(getStaticIntField + (JNI.class, fromReflectedField + (JNI.class.getField("field950"))) == 950); + + expect(toReflectedField + (JNI.class, fromReflectedField + (JNI.class.getField("field950")), true) + .getName().equals("field950")); + + { Object o = new Object(); + expect(testLocalRef(o) == o); + } + } +} diff --git a/sgx-jvm/avian/test/LazyLoading.java b/sgx-jvm/avian/test/LazyLoading.java new file mode 100644 index 0000000000..80d279e3f3 --- /dev/null +++ b/sgx-jvm/avian/test/LazyLoading.java @@ -0,0 +1,183 @@ +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; + +public class LazyLoading { + public static boolean loadLazy; + + public static void expect(boolean v) { + if (! v) throw new RuntimeException(); + } + + private static File findClass(String name, File directory) { + for (File file: directory.listFiles()) { + if (file.isFile()) { + if (file.getName().equals(name + ".class")) { + return file; + } + } else if (file.isDirectory()) { + File result = findClass(name, file); + if (result != null) { + return result; + } + } + } + return null; + } + + private static byte[] read(File file) throws IOException { + byte[] bytes = new byte[(int) file.length()]; + FileInputStream in = new FileInputStream(file); + try { + if (in.read(bytes) != (int) file.length()) { + throw new RuntimeException(); + } + return bytes; + } finally { + in.close(); + } + } + + public static void main(String[] args) throws Exception { + Class c = new MyClassLoader(LazyLoading.class.getClassLoader()).loadClass + ("LazyLoading$Test"); + + c.getMethod("test").invoke(null); + } + + private static class MyClassLoader extends ClassLoader { + public MyClassLoader(ClassLoader parent) { + super(parent); + } + + protected Class findClass(String name) throws ClassNotFoundException { + try { + return defineClass + (name, read + (LazyLoading.findClass + (name, new File(System.getProperty("user.dir"))))); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + public Class loadClass(String name) throws ClassNotFoundException { + if ("LazyLoading$Test".equals(name)) { + return findClass(name); + } else if ("LazyLoading$Lazy".equals(name) + || "LazyLoading$Interface".equals(name)) + { + if (loadLazy) { + return findClass(name); + } else { + throw new ClassNotFoundException(name); + } + } else { + return super.loadClass(name); + } + } + + private Class defineClass(String name, byte[] bytes) { + return defineClass(name, bytes, 0, bytes.length); + } + } + + public static class Test { + public static void test() { + doTest(); + loadLazy = true; + doTest(); + } + + private static void doTest() { + if (loadLazy) { + // anewarray + Lazy[] array = new Lazy[1]; + + // new and invokespecial + Object lazy = new Lazy(); + + // checkcast + array[0] = (Lazy) lazy; + + // instanceof + expect(lazy instanceof Lazy); + + // invokeinterface + expect(array[0].interfaceMethod() == 42); + + // invokestatic + expect(Lazy.staticMethod() == 43); + + // invokevirtual + expect(array[0].virtualMethod() == 44); + + // ldc + expect(Lazy.class == lazy.getClass()); + + // multianewarray + Lazy[][] multiarray = new Lazy[5][6]; + multiarray[2][3] = array[0]; + expect(multiarray[2][3] == array[0]); + + // getfield + expect(array[0].intField == 45); + + // getstatic + expect(Lazy.intStaticField == 46); + + // putfield int + array[0].intField = 47; + expect(array[0].intField == 47); + + // putfield long + array[0].longField = 48; + expect(array[0].longField == 48); + + // putfield object + Object x = new Object(); + array[0].objectField = x; + expect(array[0].objectField == x); + + // putstatic int + array[0].intStaticField = 49; + expect(array[0].intStaticField == 49); + + // putstatic long + array[0].longStaticField = 50; + expect(array[0].longStaticField == 50); + + // putstatic object + Object y = new Object(); + array[0].objectStaticField = y; + expect(array[0].objectStaticField == y); + } + } + } + + private interface Interface { + public int interfaceMethod(); + } + + private static class Lazy implements Interface { + public static int intStaticField = 46; + public static long longStaticField; + public static Object objectStaticField; + + public int intField = 45; + public long longField; + public Object objectField; + + public int interfaceMethod() { + return 42; + } + + public static int staticMethod() { + return 43; + } + + public int virtualMethod() { + return 44; + } + } +} diff --git a/sgx-jvm/avian/test/LinkedBlockingQueueTest.java b/sgx-jvm/avian/test/LinkedBlockingQueueTest.java new file mode 100644 index 0000000000..f0eed44994 --- /dev/null +++ b/sgx-jvm/avian/test/LinkedBlockingQueueTest.java @@ -0,0 +1,208 @@ +import java.util.LinkedList; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.TimeUnit; + +public class LinkedBlockingQueueTest { + private static final int DELAY_TILL_ACTION = 10; + + public static void main(String[] args) throws InterruptedException { + remainingCapacityTest(); + QueueHelper.sizeTest(new LinkedBlockingQueue()); + QueueHelper.isEmptyTest(new LinkedBlockingQueue()); + QueueHelper.addTest(new LinkedBlockingQueue()); + addCapacityFail(); + offerTest(); + offerWithTimeoutTest(); + offerTimeoutTest(); + putTest(); + QueueHelper.addAllTest(new LinkedBlockingQueue()); + addAllFail(); + QueueHelper.elementTest(new LinkedBlockingQueue()); + QueueHelper.elementFail(new LinkedBlockingQueue()); + pollEmptyTest(); + pollTest(); + pollTimeoutTest(); + takeTest(); + QueueHelper.removeEmptyFail(new LinkedBlockingQueue()); + QueueHelper.removeTest(new LinkedBlockingQueue()); + drainToTest(); + drainToLimitTest(); + QueueHelper.containsTest(new LinkedBlockingQueue()); + QueueHelper.containsAllTest(new LinkedBlockingQueue()); + QueueHelper.removeObjectTest(new LinkedBlockingQueue()); + QueueHelper.removeAllTest(new LinkedBlockingQueue()); + QueueHelper.clearTest(new LinkedBlockingQueue()); + QueueHelper.toArrayTest(new LinkedBlockingQueue()); + } + + private static void verify(boolean val) { + if (! val) { + throw new RuntimeException(); + } + } + + private static void remainingCapacityTest() { + LinkedBlockingQueue lbq = new LinkedBlockingQueue(2); + verify(lbq.remainingCapacity() == 2); + + lbq.add(new Object()); + verify(lbq.remainingCapacity() == 1); + } + + private static void addCapacityFail() { + LinkedBlockingQueue lbq = new LinkedBlockingQueue(1); + Object testObject = new Object(); + lbq.add(testObject); + + try { + lbq.add(new Object()); + throw new RuntimeException("Exception should have thrown"); + } catch (IllegalStateException e) { + // expected + } + + verify(lbq.size() == 1); + verify(lbq.peek() == testObject); + } + + private static void offerTest() { + LinkedBlockingQueue lbq = new LinkedBlockingQueue(1); + Object testObject = new Object(); + verify(lbq.offer(testObject)); + verify(! lbq.offer(new Object())); + + verify(lbq.size() == 1); + verify(lbq.peek() == testObject); + } + + private static void offerWithTimeoutTest() throws InterruptedException { + final LinkedBlockingQueue lbq = new LinkedBlockingQueue(1); + lbq.add(new Object()); + + new Thread(new Runnable() { + @Override + public void run() { + try { + // sleep to make sure offer call starts first + Thread.sleep(DELAY_TILL_ACTION); + lbq.take(); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + } + }).start(); + + // should accept once thread starts + verify(lbq.offer(new Object(), 10, TimeUnit.SECONDS)); + } + + private static void offerTimeoutTest() throws InterruptedException { + LinkedBlockingQueue lbq = new LinkedBlockingQueue(1); + lbq.add(new Object()); + + verify(! lbq.offer(new Object(), 10, TimeUnit.MILLISECONDS)); + } + + private static void putTest() throws InterruptedException { + LinkedBlockingQueue lbq = new LinkedBlockingQueue(); + Object testObject = new Object(); + lbq.put(testObject); + + verify(lbq.size() == 1); + verify(lbq.peek() == testObject); + } + + private static void addAllFail() { + LinkedBlockingQueue lbq = new LinkedBlockingQueue(1); + LinkedList toAdd = new LinkedList(); + toAdd.add(new Object()); + toAdd.add(new Object()); + + try { + lbq.addAll(toAdd); + throw new RuntimeException("Exception should have thrown"); + } catch (IllegalStateException e) { + // expected + } + } + + private static void pollEmptyTest() { + LinkedBlockingQueue lbq = new LinkedBlockingQueue(); + + verify(lbq.poll() == null); + } + + private static void pollTest() { + LinkedBlockingQueue lbq = new LinkedBlockingQueue(); + Object testObject = new Object(); + lbq.add(testObject); + + verify(lbq.poll() == testObject); + } + + private static void pollTimeoutTest() throws InterruptedException { + final LinkedBlockingQueue lbq = new LinkedBlockingQueue(); + final Object testObject = new Object(); + new Thread(new Runnable() { + @Override + public void run() { + try { + Thread.sleep(DELAY_TILL_ACTION); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + + lbq.add(testObject); + } + }).start(); + + + verify(lbq.poll(DELAY_TILL_ACTION * 10, TimeUnit.MILLISECONDS) == testObject); + } + + private static void takeTest() throws InterruptedException { + final LinkedBlockingQueue lbq = new LinkedBlockingQueue(); + final Object testObject = new Object(); + new Thread(new Runnable() { + @Override + public void run() { + try { + Thread.sleep(DELAY_TILL_ACTION); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + + lbq.add(testObject); + } + }).start(); + + + verify(lbq.take() == testObject); + } + + private static void drainToTest() { + int objQty = 2; + LinkedBlockingQueue lbq = new LinkedBlockingQueue(); + for (int i = 0; i < objQty; i++) { + lbq.add(new Object()); + } + + LinkedList drainToResult = new LinkedList(); + verify(lbq.drainTo(drainToResult) == objQty); + verify(drainToResult.size() == objQty); + } + + private static void drainToLimitTest() { + int objQty = 4; + int limit = 2; + LinkedBlockingQueue lbq = new LinkedBlockingQueue(); + for (int i = 0; i < objQty; i++) { + lbq.add(new Object()); + } + + LinkedList drainToResult = new LinkedList(); + verify(lbq.drainTo(drainToResult, limit) == limit); + verify(drainToResult.size() == limit); + verify(lbq.size() == objQty - limit); + } +} diff --git a/sgx-jvm/avian/test/List.java b/sgx-jvm/avian/test/List.java new file mode 100644 index 0000000000..c25950c525 --- /dev/null +++ b/sgx-jvm/avian/test/List.java @@ -0,0 +1,193 @@ +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.ListIterator; + +public class List { + private static void expect(boolean v) { + if (! v) throw new RuntimeException(); + } + + private static String printList(ArrayList list) { + StringBuilder sb = new StringBuilder(); + + for (Integer i : list) { + sb.append(i); + sb.append(", "); + } + sb.setLength(sb.length()-2); + return sb.toString(); + } + + private static void isEqual(String s1, String s2) { + System.out.println(s1); + expect(s1.equals(s2)); + } + + private static void testIterators(java.util.List l) { + l.add(1); + l.add(2); + l.add(3); + + ListIterator it = l.listIterator(); + expect(it.next().equals(Integer.valueOf(1))); + expect(it.next().equals(Integer.valueOf(2))); + expect(it.next().equals(Integer.valueOf(3))); + expect(! it.hasNext()); + + it = l.listIterator(1); + expect(it.next().equals(Integer.valueOf(2))); + expect(it.next().equals(Integer.valueOf(3))); + expect(! it.hasNext()); + + it = l.listIterator(2); + expect(it.next().equals(Integer.valueOf(3))); + expect(! it.hasNext()); + + it = l.listIterator(3); + expect(it.previous().equals(Integer.valueOf(3))); + expect(it.previous().equals(Integer.valueOf(2))); + expect(it.previous().equals(Integer.valueOf(1))); + expect(! it.hasPrevious()); + + it = l.listIterator(2); + expect(it.previous().equals(Integer.valueOf(2))); + expect(it.previous().equals(Integer.valueOf(1))); + expect(! it.hasPrevious()); + + it = l.listIterator(1); + expect(it.previous().equals(Integer.valueOf(1))); + expect(! it.hasPrevious()); + } + + private static void testIterators2(java.util.List l) { + l.add(1); + l.add(2); + l.add(3); + + ListIterator it = l.listIterator(); + expect(it.next().equals(Integer.valueOf(1))); + it.remove(); + expect(it.next().equals(Integer.valueOf(2))); + it.remove(); + expect(it.next().equals(Integer.valueOf(3))); + it.remove(); + expect(! it.hasNext()); + expect(l.isEmpty()); + + l.add(1); + l.add(2); + l.add(3); + + it = l.listIterator(1); + expect(it.next().equals(Integer.valueOf(2))); + it.remove(); + expect(it.next().equals(Integer.valueOf(3))); + it.remove(); + expect(! it.hasNext()); + expect(l.size() == 1); + + l.add(2); + l.add(3); + + it = l.listIterator(2); + expect(it.next().equals(Integer.valueOf(3))); + it.remove(); + expect(! it.hasNext()); + expect(l.size() == 2); + + l.add(3); + + it = l.listIterator(3); + expect(it.previous().equals(Integer.valueOf(3))); + it.remove(); + expect(it.previous().equals(Integer.valueOf(2))); + it.remove(); + expect(it.previous().equals(Integer.valueOf(1))); + it.remove(); + expect(! it.hasPrevious()); + expect(l.isEmpty()); + + l.add(1); + l.add(2); + l.add(3); + + it = l.listIterator(2); + expect(it.previous().equals(Integer.valueOf(2))); + it.remove(); + expect(it.previous().equals(Integer.valueOf(1))); + it.remove(); + expect(! it.hasPrevious()); + expect(l.size() == 1); + + l.clear(); + l.add(1); + l.add(2); + l.add(3); + + it = l.listIterator(1); + expect(it.previous().equals(Integer.valueOf(1))); + it.remove(); + expect(! it.hasPrevious()); + expect(l.size() == 2); + } + + private static void testGrow() { + ArrayList foo = new ArrayList(2); + foo.add(0); + foo.add(1); + foo.add(2); // first grow + foo.add(3); + foo.add(4); // second grow + foo.add(5); + + for (int i = 0; i < foo.size(); i++) { + expect(i == foo.get(i)); + } + } + + private static void testRemove() { + ArrayList foo = new ArrayList(2); + foo.add("Uno"); + foo.add("Dos"); + foo.add("Tres"); + foo.add("Cuatro"); + + ArrayList fooToRemove = new ArrayList(2); + fooToRemove.add(foo.get(0)); + fooToRemove.add(foo.get(1)); + + for (String s : fooToRemove) { + foo.remove(s); + } + + expect(foo.size() == 2); + } + + public static void main(String args[]) { + ArrayList l = new ArrayList(); + l.add(1); l.add(2); l.add(3); l.add(4); l.add(5); + isEqual(printList(l), "1, 2, 3, 4, 5"); + l.add(0, 6); + isEqual(printList(l), "6, 1, 2, 3, 4, 5"); + l.add(2, 7); + isEqual(printList(l), "6, 1, 7, 2, 3, 4, 5"); + l.remove(1); + isEqual(printList(l), "6, 7, 2, 3, 4, 5"); + l.add(6, 8); + isEqual(printList(l), "6, 7, 2, 3, 4, 5, 8"); + Integer[] ints = new Integer[15]; + Integer[] z = l.toArray(ints); + expect(z == ints); + for (int i=0; i < z.length; i++) { + System.out.println(z[i]); + } + + testIterators(new ArrayList()); + testIterators(new LinkedList()); + + testIterators2(new ArrayList()); + testIterators2(new LinkedList()); + testGrow(); + testRemove(); + } +} diff --git a/sgx-jvm/avian/test/Logging.java b/sgx-jvm/avian/test/Logging.java new file mode 100644 index 0000000000..cbfc663d25 --- /dev/null +++ b/sgx-jvm/avian/test/Logging.java @@ -0,0 +1,150 @@ +import java.util.logging.Handler; +import java.util.logging.Level; +import java.util.logging.LogRecord; +import java.util.logging.Logger; + +public class Logging { + private static final Logger log = Logger.getLogger("Logging"); + + private static class MyHandler extends Handler { + private static final int NAME_WIDTH = 18; + private static final int METHOD_WIDTH = 20; + private static final int LEVEL_WIDTH = 8; + + public Object clone() { return this; } + public void close() { } + public void flush() { } + + private void maybeLogThrown(StringBuilder sb, Throwable t) { + if (t != null) { + sb.append("\nCaused by: "); + sb.append(t.getClass().getName()); + sb.append(": "); + sb.append(t.getMessage()); + sb.append('\n'); + + for (StackTraceElement elt : t.getStackTrace()) { + sb.append('\t'); + sb.append(elt.getClassName()); + sb.append('.'); + sb.append(elt.getMethodName()); + sb.append('('); + sb.append(elt.getFileName()); + sb.append(':'); + sb.append(elt.getLineNumber()); + sb.append(')'); + sb.append('\n'); + } + maybeLogThrown(sb, t.getCause()); + } + } + + private void indent(StringBuilder sb, int amount) { + do { + sb.append(' '); + } while (--amount > 0); + } + + public void publish(LogRecord r) { + StringBuilder sb = new StringBuilder(); + sb.append(r.getLoggerName()); + indent(sb, NAME_WIDTH - r.getLoggerName().length()); + String methodName = r.getSourceMethodName(); + if (methodName == null) { + methodName = ""; + } + sb.append(methodName); + indent(sb, METHOD_WIDTH - methodName.length()); + sb.append(r.getLevel().getName()); + indent(sb, LEVEL_WIDTH - r.getLevel().getName().length()); + sb.append(r.getMessage()); + maybeLogThrown(sb, r.getThrown()); + System.out.println(sb.toString()); + } + } + + public void run() { + log.info("Started run"); + a(); + log.log(Level.INFO, "Ended {}!", "run"); + } + + private void a() { + log.fine("Started a()"); + b(); + } + + private void b() { + log.info("Started b()"); + c(); + } + + private void c() { + log.warning("Started c()"); + try { + d(); + } catch (Exception ex) { + log.log(Level.SEVERE, "Exception caught in c", ex); + } + } + + private void d() throws Exception { + e(); + } + + private void e() throws Exception { + throw new Exception("Started here"); + } + + private static void expect(boolean v) { + if (! v) throw new RuntimeException(); + } + + private static final boolean useCustomHandler = true; + public static void main(String args[]) { + if (useCustomHandler) { + Logger root = Logger.getLogger(""); + root.addHandler(new MyHandler()); + for (Handler h : root.getHandlers()) root.removeHandler(h); + root.addHandler(new MyHandler()); + } + + Logging me = new Logging(); + me.run(); + + { final boolean[] logged = new boolean[1]; + Logger root = Logger.getLogger(""); + for (Handler h : root.getHandlers()) root.removeHandler(h); + root.setLevel(Level.FINER); + root.addHandler(new Handler() { + public void publish(LogRecord r) { + logged[0] = true; + } + + public void close() { } + public void flush() { } + }); + + Logger foo = Logger.getLogger("foo"); + expect(foo.getLevel() == null); + expect(foo.getParent() == root); + + foo.info("hi"); + expect(logged[0]); + + logged[0] = false; + foo.fine("hi"); + expect(logged[0]); + + logged[0] = false; + foo.finest("hi"); + expect(! logged[0]); + + root.setLevel(Level.FINEST); + + logged[0] = false; + foo.finest("hi"); + expect(logged[0]); + } + } +} diff --git a/sgx-jvm/avian/test/Longs.java b/sgx-jvm/avian/test/Longs.java new file mode 100644 index 0000000000..4d9395f7b0 --- /dev/null +++ b/sgx-jvm/avian/test/Longs.java @@ -0,0 +1,394 @@ +public class Longs { + private static volatile long volatileLong = getConstant(); + + private static long getConstant() { + return 0x123456789ABCDEFL; + } + + private static void expect(boolean v) { + if (! v) throw new RuntimeException(); + } + + public static long readLongFrom(java.io.InputStream in) + throws java.io.IOException + { + long b1 = in.read(); + long b2 = in.read(); + long b3 = in.read(); + long b4 = in.read(); + long b5 = in.read(); + long b6 = in.read(); + long b7 = in.read(); + long b8 = in.read(); + if (b8 == -1) throw new java.io.EOFException(); + return (long) ((b1 << 56) | (b2 << 48) | (b3 << 40) | (b4 << 32) | + (b5 << 24) | (b6 << 16) | (b7 << 8) | (b8)); + } + + public static void putInt(int val, byte[] dst, int offset) { + System.out.println("put " + val); + dst[offset] = (byte)((val >> 24) & 0xff); + dst[offset+1] = (byte)((val >> 16) & 0xff); + dst[offset+2] = (byte)((val >> 8) & 0xff); + dst[offset+3] = (byte)((val ) & 0xff); + } + + public static void putLong(long val, byte[] dst, int offset) { + putInt((int)(val >> 32), dst, offset); + putInt((int)val, dst, offset + 4); + } + + public static int getInt(byte[] src, int offset) { + int r = ((src[offset] & 0xFF) << 24) + | ((src[offset + 1] & 0xFF) << 16) + | ((src[offset + 2] & 0xFF) << 8) + | ((src[offset + 3] & 0xFF)); + System.out.println("get " + r); + return r; + } + + public static long getLong(byte[] src, int offset) { + return ((long) getInt(src, offset) << 32) + | ((long) getInt(src, offset + 4) & 0xffffffffL); + } + + private static long roundUp(long a, long b) { + a += b - 1L; + return a - (a % b); + } + + private static int negativeOne() { + return -1; + } + + private static long unsignedShiftRight32(long x) { + return x >>> 32; + } + + public static class Rectangle { + public long x; + public long y; + public long width; + public long height; + + public void setX(long x) { + this.x = x; + } + } + + public static void main(String[] args) throws Exception { + expect(volatileLong == getConstant()); + + { Rectangle r = new Rectangle(); + Rectangle.class.getMethod("setX", long.class).invoke(r, 42L); + expect(r.x == 42L); + } + + { long a = 0x1FFFFFFFFL; + long b = -1; + expect(a != b); + } + + expect(Math.abs(-123L) == 123L); + + expect(readLongFrom(new java.io.InputStream() { + int step; + + public int read() { + return ++step; + } + }) == 0x0102030405060708L); + + expect(((long) negativeOne()) == -1); + + { long foo = 25214903884L; + int radix = 10; + expect(foo > 0); + foo /= radix; + expect(foo > 0); + } + + expect(roundUp(156, 2) == 156); + expect(((int) roundUp(156, 2)) == 156); + + expect(Long.parseLong("25214903884") == 25214903884L); + + expect(Long.parseLong("-9223372036854775808") == -9223372036854775808L); + + expect(String.valueOf(25214903884L).equals("25214903884")); + + expect(String.valueOf(-9223372036854775808L).equals + ("-9223372036854775808")); + + { long a = -5; + long b = 2; + expect(a >> b == -5L >> 2); + expect(a >>> b == -5L >>> 2); + expect(a << b == -5L << 2); + expect(a + b == -5L + 2L); + expect(a - b == -5L - 2L); + expect(a * b == -5L * 2L); + expect(a / b == -5L / 2L); + expect(a % b == -5L % 2L); + expect((a & b) == (-5L & 2L)); + expect((a | b) == (-5L | 2L)); + expect((a ^ b) == (-5L ^ 2L)); + expect(-a == 5L); + expect(~a == ~-5L); + + a = 5; + b = 2; + expect(a >> b == 5L >> 2); + expect(a >>> b == 5L >>> 2); + expect(a << b == 5L << 2); + expect(a + b == 5L + 2L); + expect(a - b == 5L - 2L); + expect(a * b == 5L * 2L); + expect(a / b == 5L / 2L); + expect(a % b == 5L % 2L); + expect((a & b) == (5L & 2L)); + expect((a | b) == (5L | 2L)); + expect((a ^ b) == (5L ^ 2L)); + expect(-a == -5L); + expect(~a == ~5L); + } + + { long a = -25214903884L; + long b = 2; + expect(a >> b == -25214903884L >> 2); + expect(a >>> b == -25214903884L >>> 2); + expect(a << b == -25214903884L << 2); + expect(a + b == -25214903884L + 2L); + expect(a - b == -25214903884L - 2L); + expect(a * b == -25214903884L * 2L); + expect(a / b == -25214903884L / 2L); + expect(a % b == -25214903884L % 2L); + expect((a & b) == (-25214903884L & 2L)); + expect((a | b) == (-25214903884L | 2L)); + expect((a ^ b) == (-25214903884L ^ 2L)); + expect(-a == 25214903884L); + expect(~a == ~-25214903884L); + + a = 25214903884L; + b = 2; + expect(a >> b == 25214903884L >> 2); + expect(a >>> b == 25214903884L >>> 2); + expect(a << b == 25214903884L << 2); + expect(a + b == 25214903884L + 2L); + expect(a - b == 25214903884L - 2L); + expect(a * b == 25214903884L * 2L); + expect(a / b == 25214903884L / 2L); + expect(a % b == 25214903884L % 2L); + expect((a & b) == (25214903884L & 2L)); + expect((a | b) == (25214903884L | 2L)); + expect((a ^ b) == (25214903884L ^ 2L)); + expect(-a == -25214903884L); + expect(~a == ~25214903884L); + } + + { long b = 2; + expect((-25214903884L) >> b == -25214903884L >> 2); + expect((-25214903884L) >>> b == -25214903884L >>> 2); + expect((-25214903884L) << b == -25214903884L << 2); + expect((-25214903884L) + b == -25214903884L + 2L); + expect((-25214903884L) - b == -25214903884L - 2L); + expect((-25214903884L) * b == -25214903884L * 2L); + expect((-25214903884L) / b == -25214903884L / 2L); + expect((-25214903884L) % b == -25214903884L % 2L); + expect(((-25214903884L) & b) == (-25214903884L & 2L)); + expect(((-25214903884L) | b) == (-25214903884L | 2L)); + expect(((-25214903884L) ^ b) == (-25214903884L ^ 2L)); + + b = 2; + expect(25214903884L >> b == 25214903884L >> 2); + expect(25214903884L >>> b == 25214903884L >>> 2); + expect(25214903884L << b == 25214903884L << 2); + expect(25214903884L + b == 25214903884L + 2L); + expect(25214903884L - b == 25214903884L - 2L); + expect(25214903884L * b == 25214903884L * 2L); + expect(25214903884L / b == 25214903884L / 2L); + expect(25214903884L % b == 25214903884L % 2L); + expect((25214903884L & b) == (25214903884L & 2L)); + expect((25214903884L | b) == (25214903884L | 2L)); + expect((25214903884L ^ b) == (25214903884L ^ 2L)); + } + + { long a = 2L; + expect(a + (-25214903884L) == 2L + (-25214903884L)); + expect(a - (-25214903884L) == 2L - (-25214903884L)); + expect(a * (-25214903884L) == 2L * (-25214903884L)); + expect(a / (-25214903884L) == 2L / (-25214903884L)); + expect(a % (-25214903884L) == 2L % (-25214903884L)); + expect((a & (-25214903884L)) == (2L & (-25214903884L))); + expect((a | (-25214903884L)) == (2L | (-25214903884L))); + expect((a ^ (-25214903884L)) == (2L ^ (-25214903884L))); + + a = 2L; + expect(a + 25214903884L == 2L + 25214903884L); + expect(a - 25214903884L == 2L - 25214903884L); + expect(a * 25214903884L == 2L * 25214903884L); + expect(a / 25214903884L == 2L / 25214903884L); + expect(a % 25214903884L == 2L % 25214903884L); + expect((a & 25214903884L) == (2L & 25214903884L)); + expect((a | 25214903884L) == (2L | 25214903884L)); + expect((a ^ 25214903884L) == (2L ^ 25214903884L)); + } + + { long b = 2; + expect((-281474976710656L) >> b == -281474976710656L >> 2); + expect((-281474976710656L) >>> b == -281474976710656L >>> 2); + expect((-281474976710656L) << b == -281474976710656L << 2); + expect((-281474976710656L) + b == -281474976710656L + 2L); + expect((-281474976710656L) - b == -281474976710656L - 2L); + expect((-281474976710656L) * b == -281474976710656L * 2L); + expect((-281474976710656L) / b == -281474976710656L / 2L); + expect((-281474976710656L) % b == -281474976710656L % 2L); + expect(((-281474976710656L) & b) == (-281474976710656L & 2L)); + expect(((-281474976710656L) | b) == (-281474976710656L | 2L)); + expect(((-281474976710656L) ^ b) == (-281474976710656L ^ 2L)); + + b = 2; + expect(281474976710656L >> b == 281474976710656L >> 2); + expect(281474976710656L >>> b == 281474976710656L >>> 2); + expect(281474976710656L << b == 281474976710656L << 2); + expect(281474976710656L + b == 281474976710656L + 2L); + expect(281474976710656L - b == 281474976710656L - 2L); + expect(281474976710656L * b == 281474976710656L * 2L); + expect(281474976710656L / b == 281474976710656L / 2L); + expect(281474976710656L % b == 281474976710656L % 2L); + expect((281474976710656L & b) == (281474976710656L & 2L)); + expect((281474976710656L | b) == (281474976710656L | 2L)); + expect((281474976710656L ^ b) == (281474976710656L ^ 2L)); + } + + { long a = 2L; + expect(a + (-281474976710656L) == 2L + (-281474976710656L)); + expect(a - (-281474976710656L) == 2L - (-281474976710656L)); + expect(a * (-281474976710656L) == 2L * (-281474976710656L)); + expect(a / (-281474976710656L) == 2L / (-281474976710656L)); + expect(a % (-281474976710656L) == 2L % (-281474976710656L)); + expect((a & (-281474976710656L)) == (2L & (-281474976710656L))); + expect((a | (-281474976710656L)) == (2L | (-281474976710656L))); + expect((a ^ (-281474976710656L)) == (2L ^ (-281474976710656L))); + + a = 2L; + expect(a + 281474976710656L == 2L + 281474976710656L); + expect(a - 281474976710656L == 2L - 281474976710656L); + expect(a * 281474976710656L == 2L * 281474976710656L); + expect(a / 281474976710656L == 2L / 281474976710656L); + expect(a % 281474976710656L == 2L % 281474976710656L); + expect((a & 281474976710656L) == (2L & 281474976710656L)); + expect((a | 281474976710656L) == (2L | 281474976710656L)); + expect((a ^ 281474976710656L) == (2L ^ 281474976710656L)); + } + + { long x = 231; + expect((x >> 32) == 0); + expect((x >>> 32) == 0); + expect((x << 32) == 992137445376L); + + int shift = 32; + expect((x >> shift) == 0); + expect((x >>> shift) == 0); + expect((x << shift) == 992137445376L); + + long y = -231; + expect((y >> 32) == 0xffffffffffffffffL); + expect((y >>> 32) == 0xffffffffL); + } + + expect(Long.valueOf(231L) == 231L); + + { byte[] array = new byte[8]; + putLong(231, array, 0); + + expect((array[0] & 0xff) == 0); + expect((array[1] & 0xff) == 0); + expect((array[2] & 0xff) == 0); + expect((array[3] & 0xff) == 0); + expect((array[4] & 0xff) == 0); + expect((array[5] & 0xff) == 0); + expect((array[6] & 0xff) == 0); + expect((array[7] & 0xff) == 231); + + expect(getLong(array, 0) == 231); + } + + java.nio.ByteBuffer buffer = java.nio.ByteBuffer.allocate(8); + buffer.putLong(231); + buffer.flip(); + expect(buffer.getLong() == 231); + + expect(unsignedShiftRight32(231) == 0); + + { int[] x = new int[] { 1701899151 }; + int[] z = new int[x.length * 2]; + final long LONG_MASK = 0xffffffffL; + + int lastProductLowWord = 0; + for (int j=0, i=0; j>> 33); + z[i++] = (int) (product >>> 1); + lastProductLowWord = (int) product; + } + + expect(z[0] == 337192406); + expect(z[1] == -437261072); + } + + { long b = 1; + expect((b << 64) == 1); } + + { long b = 0xFFFFFFFFFFFFFFFFL; + expect((b >>> -1) == 1); } + + { long b = 0x10000000000L; + expect((b >> -63) == 0x8000000000L); } + + { long b = 1; int s = 64; + expect((b << s) == 1); } + + { long b = 0xFFFFFFFFFFFFFFFFL; int s = -1; + expect((b >>> s) == 1); } + + { long b = 0x10000000000L; int s = -63; + expect((b >> s) == 0x8000000000L); } + + { long b = 0xBEL; + expect((b & 0xFF) == 0xBEL); } + + { long b = 0xBEL; + expect((b >>> 0) == 0xBEL); } + + { long b = 0xBEL; + expect((b >> 0) == 0xBEL); } + + { long b = 0xBEL; + expect((b << 0) == 0xBEL); } + + { long b = 0xBEL; + expect(((b >>> 0) & 0xFF) == 0xBEL); } + + { long b = 0xBEL; int x = 0xFF; + expect((b & x) == 0xBEL); } + + { long b = 0xBEL; int x = 0; + expect((b >>> x) == 0xBEL); } + + { long b = 0xBEL; int x = 0; + expect((b >> x) == 0xBEL); } + + { long b = 0xBEL; int x = 0; + expect((b << x) == 0xBEL); } + + { long b = 0xBEL; int x = 0; int y = 0xFF; + expect(((b >>> x) & y) == 0xBEL); } + + { long b = 0xFFFFFFFFFFFFFFFFL; int s = 20; + expect((b >>> -s) == 0xFFFFF); + } + } + +} diff --git a/sgx-jvm/avian/test/MemoryRamp.java b/sgx-jvm/avian/test/MemoryRamp.java new file mode 100644 index 0000000000..2023a5483b --- /dev/null +++ b/sgx-jvm/avian/test/MemoryRamp.java @@ -0,0 +1,66 @@ +/** + * Demonstrates slow multithreaded memory access. + */ +public class MemoryRamp implements Runnable { + + private static final int ARRAY_SIZE = 10 * 1024 * 1024; //10 MB in byte + private static final boolean ACCESS_ARRAY = true; + + @Override + public void run() { + mem(); + } + + public static void main(String[] args) { + // get timing for single thread + long singleTime = mem(); + System.out.println("Single thread: " + singleTime + "ms"); + + // run the same method with different thread numbers + for (int threadCount : new int[] {2, 3, 4}) { + long time = memMulti(threadCount); + double timeFactor = 1.0 * singleTime * threadCount / time; + System.out.println(threadCount + " threads: " + time + "ms (" + timeFactor + "x)"); + } + } + + /** + * Creates and accesses a ARRAY_SIZE big byte[]. + * @return time to create and access array in milliseconds + */ + private static long mem() { + long start = System.currentTimeMillis(); + final byte[] array = new byte[ARRAY_SIZE]; + if (ACCESS_ARRAY) { + for (int i = 0; i < array.length; i++) { + //array[i] = (byte) 170; //write + byte x = array[i]; //read + } + } + return System.currentTimeMillis() - start; + } + + /** + * Starts multiple threads and runs mem() in each one. + * @return total time for all threads + */ + private static long memMulti(int numOfThreads) { + Thread[] threads = new Thread[numOfThreads]; + long start = System.currentTimeMillis(); + + for (int i = 0; i < threads.length; i++) { + threads[i] = new Thread(new MemoryRamp(), "mem-"); + threads[i].start(); + } + + try { + for (Thread thread : threads) { + thread.join(); + } + } + catch (InterruptedException iex) { + throw new RuntimeException(iex); + } + return System.currentTimeMillis() - start; + } +} diff --git a/sgx-jvm/avian/test/MessageFormatTest.java b/sgx-jvm/avian/test/MessageFormatTest.java new file mode 100644 index 0000000000..63914ee44e --- /dev/null +++ b/sgx-jvm/avian/test/MessageFormatTest.java @@ -0,0 +1,24 @@ +import java.text.MessageFormat; + +public class MessageFormatTest { + + private static void assertEquals(Object a, Object b) { + if(!a.equals(b)) { + throw new RuntimeException("[" + a + "] != [" + b + "]"); + } + } + + public static void main(String[] args) { + assertEquals("Hi there", MessageFormat.format("Hi there", "a")); + assertEquals("Hi there", MessageFormat.format("Hi {0}here", "t")); + assertEquals("Hi a!a!a", MessageFormat.format("Hi {0}!{0}!{0}", "a")); + assertEquals("Hi There", MessageFormat.format("{1} {0}", "There", "Hi")); + assertEquals("6 There 4", MessageFormat.format("{1} {2} {0}", 4, 6, "There")); + assertEquals("Zero and {0} aren't the same", MessageFormat.format("{0} and '{0}' aren''t the same","Zero")); + assertEquals("There are six grapes", MessageFormat.format("There are {0} grapes", "six")); + assertEquals("3 + 2 = 5", MessageFormat.format("{2} + {1} = {0}", 5, 2, 3)); + assertEquals("again and again and again", MessageFormat.format("{0} and {0} and {0}", "again")); + assertEquals("Joe's age is 30, not {0}", MessageFormat.format("Joe''s age is {0}, not '{0}'", 30)); + } + +} \ No newline at end of file diff --git a/sgx-jvm/avian/test/Misc.java b/sgx-jvm/avian/test/Misc.java new file mode 100644 index 0000000000..19195277aa --- /dev/null +++ b/sgx-jvm/avian/test/Misc.java @@ -0,0 +1,367 @@ +import java.io.IOException; +import java.net.URL; +import java.util.Enumeration; + +public class Misc { + private static class μClass { + public int μField; + + public void μMethod(int i) { + μField = i; + } + } + + private interface Bar { + public int baz(); + } + + private static abstract class Bim implements Bar { } + + private static class Baz extends Bim { + public int baz() { + return 42; + } + } + + private static class Static { + static { + staticRan = true; + } + + public static void run() { } + } + + private static boolean staticRan; + + private static int alpha; + private static int beta; + private static byte byte1, byte2, byte3; + + private static volatile int volatileStatic; + + private static volatile long volatileStaticLong; + + private final int NonStaticConstant = 42; + + private int gamma; + private int pajama; + private boolean boolean1; + private boolean boolean2; + private long time; + private volatile int volatileMember; + + public Misc() { + expect(! boolean1); + expect(! boolean2); + + time = 0xffffffffffffffffL; + + expect(! boolean1); + expect(! boolean2); + } + + private String foo(String s) { + return s; + } + + public String bar(String s) { + return s; + } + + private static String baz(String s) { + return s; + } + + private static void expect(boolean v) { + if (! v) throw new RuntimeException(); + } + + private synchronized byte sync() { + byte[] array = new byte[123]; + return array[42]; + } + + private static synchronized byte syncStatic(boolean throw_) { + byte[] array = new byte[123]; + if (throw_) { + throw new RuntimeException(); + } else { + return array[42]; + } + } + + public String toString() { + return super.toString(); + } + + private static int zap() { + return 42; + } + + private static int zip() { + return 5 + zap(); + } + + private static int zup() { + return zap() + 5; + } + + private static class Foo { + public int a; + public int b; + public int c; + public int[] array; + } + + private static int bar(int a, int b, int c) { + return a + b + c; + } + + private static Object gimmeNull() { + return null; + } + + private static Object queryDefault(Object default_) { + Object o = gimmeNull(); + return (o == null ? default_ : o); + } + + private static class Zam { + public void bim() { } + } + + private static class Zim { + public Object zum() { + return null; + } + } + + private static Zim zim = new Zim(); + + private static void zam() { + Zam z; + while ((z = (Zam) zim.zum()) != null) { + z.bim(); + } + } + + private static synchronized void testStaticNotify() { + Misc.class.notify(); + } + + public static void main(String[] args) throws Exception { + zam(); + + Bim bim = new Baz(); + expect(bim.baz() == 42); + + expect(queryDefault(new Object()) != null); + + { Foo foo = new Foo(); + int x = foo.a + foo.b + foo.c; + bar(foo.a, foo.b, foo.c); + } + + byte2 = 0; + expect(byte2 == 0); + + boolean v = Boolean.valueOf("true"); + + ClassLoader.getSystemClassLoader().toString(); + + testStaticNotify(); + + { Misc m = new Misc(); + m.toString(); + + expect(m.NonStaticConstant == 42); + + expect(m.time == 0xffffffffffffffffL); + long t = m.time; + expect(t == 0xffffffffffffffffL); + + String s = "hello"; + m.foo(s); + m.bar(s); + baz(s); + + m.sync(); + syncStatic(false); + try { + syncStatic(true); + } catch (RuntimeException e) { + e.printStackTrace(); + } + + int d = alpha; + beta = 42; + alpha = 43; + volatileStatic = 55; + volatileStaticLong = 9L; + int e = beta; + int f = alpha; + m.volatileMember = 23; + m.gamma = 44; + m.volatileMember = 27; + + expect(beta == 42); + expect(alpha == 43); + expect(m.gamma == 44); + expect(volatileStatic == 55); + expect(volatileStaticLong == 9L); + expect(m.volatileMember == 27); + } + + expect(zip() == 47); + expect(zup() == 47); + + { + Object a = new Object(); + Object b = new Object(); + expect(a != b); + + Object c = a; + Object d = b; + expect(c != d); + + c = (c == a) ? b : a; + d = (d == a) ? b : a; + + expect(c != d); + } + + { Foo foo = new Foo(); + foo.array = new int[3]; + foo.a = (foo.a + 1) % foo.array.length; + } + + { boolean foo = false; + boolean iconic = false; + do { + zap(); + iconic = foo ? true : false; + } while (foo); + zap(); + } + + { int x = 0; + if (x == 0) { + x = 1; + do { + int y = x; + x = 1; + } while (x != 1); + } + } + + System.out.println(new java.util.Date().toString()); + + System.out.println('x'); + System.out.println(true); + System.out.println(42); + System.out.println(123456789012345L); + System.out.println(75.62); + System.out.println(75.62d); + System.out.println(new char[] { 'h', 'i' }); + + expect(! (((Object) new int[0]) instanceof Object[])); + + { μClass μInstance = new μClass(); + μInstance.μMethod(8933); + expect(μInstance.μField == 8933); + } + + expect(new int[0] instanceof Cloneable); + expect(new int[0] instanceof java.io.Serializable); + + expect(new Object[0] instanceof Cloneable); + expect(new Object[0] instanceof java.io.Serializable); + + expect((Baz.class.getModifiers() & java.lang.reflect.Modifier.STATIC) + != 0); + + expect((Protected.class.getModifiers() & java.lang.reflect.Modifier.PUBLIC) + == 0); + + try { + int count = 0; + boolean test = false, extraDir = false; + ClassLoader loader = Misc.class.getClassLoader(); + Enumeration resources = loader.getResources("multi-classpath-test.txt"); + while (resources.hasMoreElements()) { + ++count; + String url = resources.nextElement().toString(); + if (url.contains("extra-dir")) { + extraDir = true; + } else if (url.contains("test")) { + test = true; + } + } + // This test is only relevant if multi-classpath-test.txt + // actually exists in somewhere under the classpath from which + // Misc.class was loaded. Since we run this test from an + // AOT-compiled boot image as well as straight from the + // filesystem, and the boot image does not contain + // multi-classpath-test.txt, we'll skip the test if it's not + // present. + if (count != 0) { + expect(count == 2); + expect(test); + expect(extraDir); + } + } catch (IOException e) { + throw new RuntimeException(e); + } + + // as of this writing, we don't support URLs on Android, since it + // pulls in a third-party library we don't include: + if (! "http://www.android.com/".equals + (System.getProperty("java.vendor.url"))) + { + expect(new URL("http://oss.readytalk.com") + .getHost().equals("oss.readytalk.com")); + } + + expect(java.util.Arrays.equals + (new byte[] { 0, 0, 0, 0 }, + java.net.InetAddress.getByName("0.0.0.0").getAddress())); + + expect(! staticRan); + Static.run(); + expect(staticRan); + + expect(System.getProperty("java.class.path").equals + (System.getProperties().getProperty("java.class.path"))); + + expect(System.getProperty("path.separator").equals + (System.getProperties().getProperty("path.separator"))); + + expect(System.getProperty("user.dir").equals + (System.getProperties().getProperty("user.dir"))); + + expect(System.getProperty("java.io.tmpdir").equals + (System.getProperties().getProperty("java.io.tmpdir"))); + + System.setProperty("buzzy.buzzy.bim.bam", "dippy dopey flim flam"); + + expect(System.getProperty("buzzy.buzzy.bim.bam").equals + (System.getProperties().getProperty("buzzy.buzzy.bim.bam"))); + + expect(System.getProperty("buzzy.buzzy.bim.bam").equals + ("dippy dopey flim flam")); + + System.getProperties().put("buzzy.buzzy.bim.bam", "yippy yappy yin yang"); + + expect(System.getProperty("buzzy.buzzy.bim.bam").equals + (System.getProperties().getProperty("buzzy.buzzy.bim.bam"))); + + expect(System.getProperty("buzzy.buzzy.bim.bam").equals + ("yippy yappy yin yang")); + + // just test that it's there; don't care what it returns: + Runtime.getRuntime().totalMemory(); + Runtime.getRuntime().maxMemory(); + } + + protected class Protected { } +} diff --git a/sgx-jvm/avian/test/NullPointer.java b/sgx-jvm/avian/test/NullPointer.java new file mode 100644 index 0000000000..8d3abdc6fa --- /dev/null +++ b/sgx-jvm/avian/test/NullPointer.java @@ -0,0 +1,132 @@ +public class NullPointer { + private int x; + private Object y; + + private static void throw_(Object o) { + o.toString(); + } + + private static void throwAndCatch(Object o) { + try { + o.toString(); + throw new RuntimeException(); + } catch (NullPointerException e) { + e.printStackTrace(); + } + } + + public static void main(String[] args) { + try { + ((Object) null).getClass(); + } catch (Exception e) { + e.printStackTrace(); + } + + try { + throw_(null); + throw new RuntimeException(); + } catch (NullPointerException e) { + e.printStackTrace(); + } + + throwAndCatch(null); + + // invokeinterface + try { + ((Runnable) null).run(); + throw new RuntimeException(); + } catch (NullPointerException e) { + e.printStackTrace(); + } + + // invokevirtual + try { + ((Object) null).toString(); + throw new RuntimeException(); + } catch (NullPointerException e) { + e.printStackTrace(); + } + + // arraylength + try { + int a = ((byte[]) null).length; + throw new RuntimeException(); + } catch (NullPointerException e) { + e.printStackTrace(); + } + + // iaload + try { + int a = ((byte[]) null)[42]; + throw new RuntimeException(); + } catch (NullPointerException e) { + e.printStackTrace(); + } + + // aaload + try { + Object a = ((Object[]) null)[42]; + throw new RuntimeException(); + } catch (NullPointerException e) { + e.printStackTrace(); + } + + // getfield (int) + try { + int a = ((NullPointer) null).x; + throw new RuntimeException(); + } catch (NullPointerException e) { + e.printStackTrace(); + } + + // getfield (Object) + try { + Object a = ((NullPointer) null).y; + throw new RuntimeException(); + } catch (NullPointerException e) { + e.printStackTrace(); + } + + // iastore + try { + ((byte[]) null)[42] = 42; + throw new RuntimeException(); + } catch (NullPointerException e) { + e.printStackTrace(); + } + + // aastore + try { + ((Object[]) null)[42] = null; + throw new RuntimeException(); + } catch (NullPointerException e) { + e.printStackTrace(); + } + + // putfield (int) + try { + ((NullPointer) null).x = 42; + throw new RuntimeException(); + } catch (NullPointerException e) { + e.printStackTrace(); + } + + // putfield (Object) + try { + ((NullPointer) null).y = null; + throw new RuntimeException(); + } catch (NullPointerException e) { + e.printStackTrace(); + } + + // monitorenter + try { + synchronized ((Object) null) { + int a = 42; + } + throw new RuntimeException(); + } catch (NullPointerException e) { + e.printStackTrace(); + } + } +} diff --git a/sgx-jvm/avian/test/Observe.java b/sgx-jvm/avian/test/Observe.java new file mode 100644 index 0000000000..75dc0063a8 --- /dev/null +++ b/sgx-jvm/avian/test/Observe.java @@ -0,0 +1,88 @@ +import java.util.Observer; +import java.util.Observable; + +public class Observe { + private static void expect(boolean v) { + if (! v) throw new RuntimeException(); + } + + private static class MyObservable extends Observable { + private String value; + + public MyObservable(String value) { + this.value = value; + } + + public void set(String newValue) { + if(!value.equals(newValue)) { + value = newValue; + setChanged(); + notifyObservers(value); + } + } + } + + private static class MyObserver implements Observer { + private int count = 0; + private Observable expectedObs; + private Object expectedValue = null; + private boolean expected = false; + + public MyObserver(Observable expectedObs) { + this.expectedObs = expectedObs; + } + + public void update(Observable obs, Object value) { + expect(expectedObs == expectedObs); + expect(expected); + expect(value == expectedValue); + expectNothing(); + } + + public void noUpdate() { + expect(!expected); + } + + public void expect(Object value) { + expected = true; + expectedValue = value; + } + + public void expectNothing() { + expected = false; + } + + } + + public static void main(String[] args) { + MyObservable obs = new MyObservable("test"); + MyObserver o = new MyObserver(obs); + MyObserver o2 = new MyObserver(obs); + + obs.set("a"); + + obs.addObserver(o); + o.expect("b"); + obs.set("b"); + o.noUpdate(); + + obs.addObserver(o2); + o.expect("c"); + o2.expect("c"); + obs.set("c"); + o.noUpdate(); + o2.noUpdate(); + + obs.deleteObserver(o); + o.expectNothing(); + o2.expect("d"); + obs.set("d"); + o2.noUpdate(); + + obs.deleteObserver(o2); + o.expectNothing(); + o2.expectNothing(); + obs.set("e"); + + } +} \ No newline at end of file diff --git a/sgx-jvm/avian/test/OutOfMemory.java b/sgx-jvm/avian/test/OutOfMemory.java new file mode 100644 index 0000000000..fbcb614fdf --- /dev/null +++ b/sgx-jvm/avian/test/OutOfMemory.java @@ -0,0 +1,62 @@ +public class OutOfMemory { + // assume a 128MB heap size: + private static final int Padding = 120 * 1024 * 1024; + + private static class Node { + Object value; + Node next; + } + + private static void bigObjects() { + Object[] root = null; + while (true) { + Object[] x = new Object[1024 * 1024]; + x[0] = root; + root = x; + } + } + + private static void littleObjects() { + byte[] padding = new byte[Padding]; + Node root = null; + while (true) { + Node x = new Node(); + x.next = root; + root = x; + } + } + + private static void bigAndLittleObjects() { + byte[] padding = new byte[Padding]; + Node root = null; + while (true) { + Node x = new Node(); + x.value = new Object[1024 * 1024]; + x.next = root; + root = x; + } + } + + public static void main(String[] args) { + try { + bigObjects(); + throw new RuntimeException(); + } catch (OutOfMemoryError e) { + e.printStackTrace(); + } + + try { + littleObjects(); + throw new RuntimeException(); + } catch (OutOfMemoryError e) { + e.printStackTrace(); + } + + try { + bigAndLittleObjects(); + throw new RuntimeException(); + } catch (OutOfMemoryError e) { + e.printStackTrace(); + } + } +} diff --git a/sgx-jvm/avian/test/Processes.java b/sgx-jvm/avian/test/Processes.java new file mode 100644 index 0000000000..372513f0c1 --- /dev/null +++ b/sgx-jvm/avian/test/Processes.java @@ -0,0 +1,31 @@ +import java.io.IOException; + +public class Processes { + public static void main(String[] args) { + long start = System.currentTimeMillis(); + try { + final Process p = Runtime.getRuntime().exec("sleep 10"); + new Thread() { + public void run() { + try { + Thread.sleep(100); + } catch(InterruptedException e) { + // ignore + } + p.destroy(); + } + }.start(); + try { + p.waitFor(); + } catch(InterruptedException e) { + // ignore + } + long stop = System.currentTimeMillis(); + if(stop - start > 5000) { + throw new RuntimeException("test failed; we didn't kill the process..."); + } + } catch(IOException e) { + throw new RuntimeException(e); + } + } +} diff --git a/sgx-jvm/avian/test/Proxies.java b/sgx-jvm/avian/test/Proxies.java new file mode 100644 index 0000000000..e52a0e7d68 --- /dev/null +++ b/sgx-jvm/avian/test/Proxies.java @@ -0,0 +1,42 @@ +import java.lang.reflect.Proxy; +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; + +public class Proxies { + private static void expect(boolean v) { + if (! v) throw new RuntimeException(); + } + + public static void main(String[] args) { + Foo foo = (Foo) Proxy.newProxyInstance + (Proxies.class.getClassLoader(), new Class[] { Foo.class }, + new InvocationHandler() { + public Object invoke(Object proxy, Method method, Object[] arguments) + { + if (method.getName().equals("bar")) { + return "bam"; + } else if (method.getName().equals("baz")) { + return ((Integer) arguments[0]) + 1; + } else if (method.getName().equals("bim")) { + return ((Long) arguments[0]) - 1L; + } else if (method.getName().equals("boom")) { + return ((String) arguments[0]).substring(1); + } else { + throw new IllegalArgumentException(); + } + } + }); + + expect(foo.bar().equals("bam")); + expect(foo.baz(42) == 43); + expect(foo.bim(42L) == 41L); + expect(foo.boom("hello").equals("ello")); + } + + private interface Foo { + public String bar(); + public int baz(int v); + public long bim(long v); + public String boom(String s); + } +} diff --git a/sgx-jvm/avian/test/QueueHelper.java b/sgx-jvm/avian/test/QueueHelper.java new file mode 100644 index 0000000000..3c9cc4c6fb --- /dev/null +++ b/sgx-jvm/avian/test/QueueHelper.java @@ -0,0 +1,149 @@ +import java.util.LinkedList; +import java.util.NoSuchElementException; +import java.util.Queue; + +public class QueueHelper { + private static void verify(boolean val) { + if (! val) { + throw new RuntimeException(); + } + } + + public static void main(String args[]) { + // prevents unit test failure + } + + public static void sizeTest(Queue q) { + verify(q.size() == 0); + + q.add(new Object()); + verify(q.size() == 1); + } + + public static void isEmptyTest(Queue q) { + verify(q.isEmpty()); + + q.add(new Object()); + verify(! q.isEmpty()); + } + + public static void addTest(Queue q) { + Object testObject = new Object(); + q.add(testObject); + + verify(q.size() == 1); + verify(q.peek() == testObject); + } + + public static void addAllTest(Queue q) { + LinkedList toAdd = new LinkedList(); + toAdd.add(new Object()); + toAdd.add(new Object()); + + q.addAll(toAdd); + + verify(q.size() == toAdd.size()); + while (! q.isEmpty()) { + verify(q.remove() == toAdd.remove()); + } + } + + public static void elementTest(Queue q) { + Object testObject = new Object(); + q.add(testObject); + + verify(q.element() == testObject); + } + + public static void elementFail(Queue q) { + try { + q.element(); + throw new RuntimeException("Exception should have thrown"); + } catch (NoSuchElementException e) { + // expected + } + } + + public static void removeTest(Queue q) { + Object testObject = new Object(); + q.add(testObject); + + verify(q.remove() == testObject); + } + + public static void removeEmptyFail(Queue q) { + try { + q.remove(); + throw new RuntimeException("Exception should have thrown"); + } catch (NoSuchElementException e) { + // expected + } + } + + public static void containsTest(Queue q) { + Object testObject = new Object(); + + verify(! q.contains(testObject)); + + q.add(testObject); + verify(q.contains(testObject)); + } + + public static void containsAllTest(Queue q) { + Object testObject = new Object(); + q.add(testObject); + + LinkedList testList = new LinkedList(); + testList.add(testObject); + testList.add(new Object()); + + verify(! q.containsAll(testList)); + + q.addAll(testList); + verify(q.containsAll(testList)); + } + + public static void removeObjectTest(Queue q) { + Object testObject = new Object(); + + verify(! q.remove(testObject)); + + q.add(testObject); + verify(q.remove(testObject)); + } + + public static void removeAllTest(Queue q) { + Object testObject = new Object(); + q.add(testObject); + + LinkedList testList = new LinkedList(); + testList.add(testObject); + testList.add(new Object()); + + verify(q.removeAll(testList)); + + q.addAll(testList); + verify(q.removeAll(testList)); + } + + public static void clearTest(Queue q) { + q.add(new Object()); + + q.clear(); + + verify(q.isEmpty()); + } + + public static void toArrayTest(Queue q) { + if (q.toArray().length != 0) { + throw new RuntimeException(); + } + + Object testObject = new Object(); + q.add(testObject); + + Object[] result = q.toArray(); + verify(result.length == 1); + verify(result[0] == testObject); + } +} diff --git a/sgx-jvm/avian/test/References.java b/sgx-jvm/avian/test/References.java new file mode 100644 index 0000000000..5557e5db1a --- /dev/null +++ b/sgx-jvm/avian/test/References.java @@ -0,0 +1,72 @@ +import java.lang.ref.ReferenceQueue; +import java.lang.ref.Reference; +import java.lang.ref.WeakReference; +import java.lang.ref.PhantomReference; +import java.util.WeakHashMap; + +public class References { + public static void main(String[] args) { + Object a = new Object(); + Object b = new Object(); + Object c = new Object(); + Object d = new Object(); + Object e = new Object(); + Object f = new Object(); + + ReferenceQueue q = new ReferenceQueue(); + + Reference ar = new WeakReference(a); + Reference br = new WeakReference(b, q); + Reference cr = new WeakReference(c, q); + Reference dr = new PhantomReference(d, q); + Reference er = new MyReference(e, q, "foo"); + + WeakHashMap map = new WeakHashMap(); + map.put(new Key("foo"), f); + + a = b = c = d = e = cr = null; + + System.out.println("a: " + ar.get()); + System.out.println("b: " + br.get()); + System.out.println("d: " + dr.get()); + System.out.println("e: " + er.get()); + System.out.println("f: " + map.get(new Key("foo"))); + + System.gc(); + + System.out.println("a: " + ar.get()); + System.out.println("b: " + br.get()); + System.out.println("d: " + dr.get()); + System.out.println("e: " + er.get()); + System.out.println("f: " + map.get(new Key("foo"))); + + for (Reference r = q.poll(); r != null; r = q.poll()) { + System.out.println("polled: " + r.get()); + } + } + + private static class MyReference extends WeakReference { + private final Object foo; + + public MyReference(Object target, ReferenceQueue queue, Object foo) { + super(target, queue); + this.foo = foo; + } + } + + private static class Key { + private final String name; + + public Key(String name) { + this.name = name; + } + + public int hashCode() { + return name.hashCode(); + } + + public boolean equals(Object o) { + return o instanceof Key && ((Key) o).name.equals(name); + } + } +} diff --git a/sgx-jvm/avian/test/Reflection.java b/sgx-jvm/avian/test/Reflection.java new file mode 100644 index 0000000000..39dc5c85a8 --- /dev/null +++ b/sgx-jvm/avian/test/Reflection.java @@ -0,0 +1,337 @@ +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.lang.reflect.InvocationTargetException; + +public class Reflection { + public static boolean booleanMethod() { + return true; + } + + public static byte byteMethod() { + return 1; + } + + public static char charMethod() { + return '2'; + } + + public static short shortMethod() { + return 3; + } + + public static int intMethod() { + return 4; + } + + public static float floatMethod() { + return 5.0f; + } + + public static long longMethod() { + return 6; + } + + public static double doubleMethod() { + return 7.0; + } + + public static void expect(boolean v) { + if (! v) throw new RuntimeException(); + } + + private static class Hello { + private class World { } + } + + private static void innerClasses() throws Exception { + Class c = Reflection.class; + Class[] inner = c.getDeclaredClasses(); + expect(2 == inner.length); + expect(Hello.class == inner[0] + || Hello.class == inner[1]); + } + + private int egads; + + private static void annotations() throws Exception { + Field egads = Reflection.class.getDeclaredField("egads"); + expect(egads.getAnnotation(Deprecated.class) == null); + } + + private Integer[] array; + + private Integer integer; + + public static Hello>.World> pinky; + + private static void genericType() throws Exception { + Field field = Reflection.class.getDeclaredField("egads"); + expect(field.getGenericType() == Integer.TYPE); + + field = Reflection.class.getField("pinky"); + expect("Reflection$Hello$World".equals(field.getType().getName())); + expect(field.getGenericType() instanceof ParameterizedType); + ParameterizedType type = (ParameterizedType) field.getGenericType(); + + expect(type.getRawType() instanceof Class); + Class clazz = (Class) type.getRawType(); + expect("Reflection$Hello$World".equals(clazz.getName())); + + expect(type.getOwnerType() instanceof ParameterizedType); + ParameterizedType owner = (ParameterizedType) type.getOwnerType(); + clazz = (Class) owner.getRawType(); + expect(clazz == Hello.class); + + Type[] args = type.getActualTypeArguments(); + expect(1 == args.length); + expect(args[0] instanceof ParameterizedType); + + ParameterizedType arg = (ParameterizedType) args[0]; + expect(arg.getRawType() instanceof Class); + clazz = (Class) arg.getRawType(); + expect("Reflection$Hello".equals(clazz.getName())); + + args = arg.getActualTypeArguments(); + expect(1 == args.length); + expect(args[0] == String.class); + } + + public static void throwOOME() { + throw new OutOfMemoryError(); + } + + public static void classType() throws Exception { + // Class types + expect(!Reflection.class.isAnonymousClass()); + expect(!Reflection.class.isLocalClass()); + expect(!Reflection.class.isMemberClass()); + + expect(Reflection.Hello.class.isMemberClass()); + + Cloneable anonymousLocal = new Cloneable() {}; + expect(anonymousLocal.getClass().isAnonymousClass()); + + class NamedLocal {} + expect(NamedLocal.class.isLocalClass()); + } + + public static void main(String[] args) throws Exception { + innerClasses(); + annotations(); + genericType(); + classType(); + + Class system = Class.forName("java.lang.System"); + Field out = system.getDeclaredField("out"); + Class output = Class.forName("java.io.PrintStream"); + Method println = output.getDeclaredMethod("println", String.class); + + println.invoke(out.get(null), "Hello, World!"); + + expect((Boolean) Reflection.class.getMethod("booleanMethod").invoke(null)); + + expect(1 == (Byte) Reflection.class.getMethod("byteMethod").invoke(null)); + + expect('2' == (Character) Reflection.class.getMethod + ("charMethod").invoke(null)); + + expect(3 == (Short) Reflection.class.getMethod + ("shortMethod").invoke(null)); + + expect(4 == (Integer) Reflection.class.getMethod + ("intMethod").invoke(null)); + + expect(5.0 == (Float) Reflection.class.getMethod + ("floatMethod").invoke(null)); + + expect(6 == (Long) Reflection.class.getMethod + ("longMethod").invoke(null)); + + expect(7.0 == (Double) Reflection.class.getMethod + ("doubleMethod").invoke(null)); + + { Class[][] array = new Class[][] { { Class.class } }; + expect("[Ljava.lang.Class;".equals(array[0].getClass().getName())); + expect(Class[].class == array[0].getClass()); + expect(array.getClass().getComponentType() == array[0].getClass()); + } + + { Reflection r = new Reflection(); + expect(r.egads == 0); + + Reflection.class.getDeclaredField("egads").set(r, (Integer)42); + expect(((Integer)Reflection.class.getDeclaredField("egads").get(r)) == 42); + + Reflection.class.getDeclaredField("egads").setInt(r, 43); + expect(Reflection.class.getDeclaredField("egads").getInt(r) == 43); + + Integer[] array = new Integer[0]; + Reflection.class.getDeclaredField("array").set(r, array); + expect(Reflection.class.getDeclaredField("array").get(r) == array); + + try { + Reflection.class.getDeclaredField("array").set(r, new Object()); + expect(false); + } catch (IllegalArgumentException e) { + // cool + } + + Integer integer = 45; + Reflection.class.getDeclaredField("integer").set(r, integer); + expect(Reflection.class.getDeclaredField("integer").get(r) == integer); + + try { + Reflection.class.getDeclaredField("integer").set(r, new Object()); + expect(false); + } catch (IllegalArgumentException e) { + // cool + } + + try { + Reflection.class.getDeclaredField("integer").set + (new Object(), integer); + expect(false); + } catch (IllegalArgumentException e) { + // cool + } + + try { + Reflection.class.getDeclaredField("integer").get(new Object()); + expect(false); + } catch (IllegalArgumentException e) { + // cool + } + } + + try { + Foo.class.getMethod("foo").invoke(null); + expect(false); + } catch (ExceptionInInitializerError e) { + expect(e.getCause() instanceof MyException); + } + + try { + Foo.class.getConstructor().newInstance(); + expect(false); + } catch (NoClassDefFoundError e) { + // cool + } + + try { + Foo.class.getField("foo").get(null); + expect(false); + } catch (NoClassDefFoundError e) { + // cool + } + + try { + Foo.class.getField("foo").set(null, (Integer)42); + expect(false); + } catch (NoClassDefFoundError e) { + // cool + } + + try { + Foo.class.getField("foo").set(null, new Object()); + expect(false); + } catch (IllegalArgumentException e) { + // cool + } catch (NoClassDefFoundError e) { + // cool + } + + { Method m = Reflection.class.getMethod("throwOOME"); + try { + m.invoke(null); + } catch(Throwable t) { + expect(t.getClass() == InvocationTargetException.class); + } + } + + expect((Foo.class.getMethod("toString").getModifiers() + & Modifier.PUBLIC) != 0); + + expect(avian.TestReflection.get(Baz.class.getField("foo"), new Baz()) + .equals(42)); + expect((Baz.class.getModifiers() & Modifier.PUBLIC) == 0); + + expect(B.class.getDeclaredMethods().length == 0); + + new Runnable() { + public void run() { + expect(getClass().getDeclaringClass() == null); + } + }.run(); + + expect(avian.testing.annotations.Test.class.getPackage().getName().equals + ("avian.testing.annotations")); + + expect(Baz.class.getField("foo").getAnnotation(Ann.class) == null); + expect(Baz.class.getField("foo").getAnnotations().length == 0); + + expect(new Runnable() { public void run() { } }.getClass() + .getEnclosingClass().equals(Reflection.class)); + + expect(new Runnable() { public void run() { } }.getClass() + .getEnclosingMethod().equals + (Reflection.class.getMethod + ("main", new Class[] { String[].class }))); + + Slithy.class.getMethod("tove", Gybe.class); + + try { + Slithy.class.getMethod("tove", Bandersnatch.class); + expect(false); + } catch (NoSuchMethodException e) { + // cool + } + + expect(C.class.getInterfaces().length == 1); + expect(C.class.getInterfaces()[0].equals(B.class)); + } + + protected static class Baz { + public int foo = 42; + } +} + +class Bandersnatch { } + +class Gybe extends Bandersnatch { } + +class Slithy { + public static void tove(Gybe gybe) { + // ignore + } +} + +class Foo { + static { + if (true) throw new MyException(); + } + + public Foo() { } + + public static int foo; + + public static void foo() { + // ignore + } +} + +class MyException extends RuntimeException { } + +interface A { + void foo(); +} + +interface B extends A { } + +class C implements B { + public void foo() { } +} + +@interface Ann { } diff --git a/sgx-jvm/avian/test/Regex.java b/sgx-jvm/avian/test/Regex.java new file mode 100644 index 0000000000..1409c67e3e --- /dev/null +++ b/sgx-jvm/avian/test/Regex.java @@ -0,0 +1,102 @@ +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class Regex { + private static void expect(boolean v) { + if (! v) throw new RuntimeException(); + } + + private static Matcher getMatcher(String regex, String string) { + return Pattern.compile(regex).matcher(string); + } + + private static void expectMatch(String regex, String string) { + expect(getMatcher(regex, string).matches()); + } + + private static void expectNoMatch(String regex, String string) { + expect(!getMatcher(regex, string).matches()); + } + + private static void expectGroups(String regex, String string, + String... groups) { + Matcher matcher = getMatcher(regex, string); + expect(matcher.matches()); + expect(matcher.groupCount() == groups.length); + for (int i = 1; i <= groups.length; ++i) { + if (groups[i - 1] == null) { + expect(matcher.group(i) == null); + } else { + expect(groups[i - 1].equals(matcher.group(i))); + } + } + } + + private static void expectFind(String regex, String string, + String... matches) + { + Matcher matcher = getMatcher(regex, string); + int i = 0; + while (i < matches.length) { + expect(matcher.find()); + expect(matches[i++].equals(matcher.group())); + } + expect(!matcher.find()); + } + + private static void expectSplit(String regex, String string, + String... list) + { + String[] array = Pattern.compile(regex).split(string); + expect(array.length == list.length); + for (int i = 0; i < list.length; ++ i) { + expect(list[i].equals(array[i])); + } + } + + public static void main(String[] args) { + expectMatch("a(bb)?a", "abba"); + expectNoMatch("a(bb)?a", "abbba"); + expectNoMatch("a(bb)?a", "abbaa"); + expectGroups("a(a*?)(a?)(a??)(a+)(a*)a", "aaaaaa", "", "a", "", "aaa", ""); + expectMatch("...", "abc"); + expectNoMatch(".", "\n"); + expectGroups("a(bb)*a", "abbbba", "bb"); + expectGroups("a(bb)?(bb)+a", "abba", null, "bb"); + expectFind(" +", "Hello , world! ", " ", " ", " "); + expectMatch("[0-9A-Fa-f]+", "08ef"); + expectNoMatch("[0-9A-Fa-f]+", "08@ef"); + expectGroups("(?:a)", "a"); + expectGroups("a|(b|c)", "a", (String)null); + expectGroups("a|(b|c)", "c", "c"); + expectGroups("(?=a)a", "a"); + expectGroups(".*(o)(?<=[A-Z][a-z]{1,4})", "Hello", "o"); + expectNoMatch("(?!a).", "a"); + expectMatch("[\\d]", "0"); + expectMatch("\\0777", "?7"); + expectMatch("\\a", "\007"); + expectMatch("\\\\", "\\"); + expectMatch("\\x4A", "J"); + expectMatch("\\x61", "a"); + expectMatch("\\078", "\0078"); + expectSplit("(?<=\\w)(?=\\W)|(?<=\\W)(?=\\w)", "a + b * x", + "a", " + ", "b", " * ", "x"); + expectMatch("[0-9[def]]", "f"); + expectNoMatch("[a-z&&[^d-f]]", "f"); + expectSplit("^H", "Hello\nHobbes!", "", "ello\nHobbes!"); + expectSplit("o.*?$", "Hello\r\nHobbes!", "Hello\r\nH"); + try { + expectSplit("\\b", "a+ b + c\nd", "", "a", "+ ", "b", " + ", "c", "\n", "d"); + } catch (RuntimeException e) { + // Java 8 changed the semantics of split, so if we're on 8, the + // above will fail and this will succeed: + expectSplit("\\b", "a+ b + c\nd", "a", "+ ", "b", " + ", "c", "\n", "d"); + } + expectSplit("\\B", "Hi Cal!", "H", "i C", "a", "l!"); + expectMatch("a{2,5}", "aaaa"); + expectGroups("a??(a{2,5}?)", "aaaa", "aaaa"); + expectGroups("a??(a{3}?)", "aaaa", "aaa"); + expectNoMatch("a(a{3}?)", "aaaaa"); + expectMatch("a(a{3,}?)", "aaaaa"); + } +} diff --git a/sgx-jvm/avian/test/Serialize.java b/sgx-jvm/avian/test/Serialize.java new file mode 100644 index 0000000000..95a2f279d2 --- /dev/null +++ b/sgx-jvm/avian/test/Serialize.java @@ -0,0 +1,231 @@ +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.Serializable; +import java.util.Properties; + +public class Serialize implements Serializable { + public static final long serialVersionUID = 1l; + public int dummy = 0x12345678; + private static void expect(boolean v) { + if (! v) throw new RuntimeException(); + } + + private static void expectEqual(boolean a, boolean b) { + expect(a == b); + } + + private static void expectEqual(int a, int b) { + expect(a == b); + } + + private static void expectEqual(String a, String b) { + expect(a.equals(b)); + } + + private static String pad(long number, int length) { + return pad(Long.toHexString(number), length, '0'); + } + + private static String pad(String s, int length, char padChar) { + length -= s.length(); + if (length <= 0) { + return s; + } + StringBuilder builder = new StringBuilder(); + while (length-- > 0) { + builder.append(padChar); + } + return builder.append(s).toString(); + } + + protected static void hexdump(byte[] a) { + StringBuilder builder = new StringBuilder(); + System.err.print(pad(0, 8) + " "); + for (int i = 0; i < a.length; i++) { + String hex = Integer.toHexString(a[i] & 0xff); + System.err.print(" " + (hex.length() == 1 ? "0" : "") + hex); + builder.append(a[i] < 0x20 || a[i] > 0x7f ? '.' : (char)a[i]); + if ((i & 0xf) == 0x7) { + System.err.print(" "); + } else if ((i & 0xf) == 0xf) { + System.err.println(" |" + builder + "|"); + builder.setLength(0); + System.err.print(pad(i + 1, 8) + " "); + } + } + for (int i = a.length & 0xf; i < 0x10; i++) { + System.err.print(" "); + if ((i & 0xf) == 0x7) { + System.err.print(" "); + } + } + System.err.println(" |" + builder + "|"); + } + + private static void expectEqual(byte[] a, int[] b) { + expect(a.length == b.length); + + for (int i = 0; i < a.length; ++i) { + expect(a[i] == (byte)b[i]); + } + } + + private static class MyMap implements Serializable { + private transient Properties properties = new Properties(); + + public final static long serialVersionUID = 0x0cc1f63e2d256ae6l; + + public int size() { + return properties.size(); + } + + public void put(String key, String value) { + properties.put(key, value); + } + + public String get(String key) { + return properties.getProperty(key); + } + + private void writeObject(ObjectOutputStream out) throws IOException { + out.defaultWriteObject(); + out.writeInt(size()); + for (Object key : properties.keySet()) { + out.writeObject(key); + out.writeObject(properties.get(key)); + } + } + + private void readObject(ObjectInputStream in) throws IOException { + try { + in.defaultReadObject(); + } catch (Exception e) { + // OpenJDK's defaultReadObject() can throw a ClassNotFoundException + throw new IOException(e); + } + properties = new Properties(); + int size = in.readInt(); + for (int i = 0; i < size; i++) try { + properties.put(in.readObject(), in.readObject()); + } catch (ClassNotFoundException e) { + throw new IOException(e); + } + } + } + + public static void main(String[] args) throws Exception { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + ObjectOutputStream out2 = new ObjectOutputStream(out); + out2.writeBoolean(true); + out2.flush(); + out2.writeByte(17); + out2.flush(); + out2.writeInt(0xcafebabe); + out2.flush(); + out2.writeUTF("Max & Möritz"); + out2.flush(); + out2.writeChar('É›'); + out2.flush(); + out2.writeObject(new Serialize()); + out2.close(); + byte[] array = out.toByteArray(); + expectEqual(array, new int[] { + // magic + 0xac, 0xed, + // version + 0x00, 0x05, + // blockdata, length + 0x77, 0x1, + // true + 1, + // blockdata, length + 0x77, 0x1, + // (byte)17 + 17, + // blockdata, length + 0x77, 0x4, + // 0xcafebabe + 0xca, 0xfe, 0xba, 0xbe, + // blockdata, length + 0x77, 0xf, + // "Max & Möritz" + 0x0, 0xd, 'M', 'a', 'x', ' ', '&', ' ', 'M', 0xc3, 0xb6, 'r', 'i', 't', 'z', + // blockdata, length + 0x77, 0x2, + // 'ö' + 0x02, 0x5b, + // object + 0x73, + // class desc, "Serialize" + 0x72, 0, 9, 'S', 'e', 'r', 'i', 'a', 'l', 'i', 'z', 'e', + // serialVersionUID + 0, 0, 0, 0, 0, 0, 0, 1, + // flags (SC_SERIALIZABLE) + 2, + // field count + 0x0, 0x1, + // int dummy + 'I', 0x0, 0x5, 'd', 'u', 'm', 'm', 'y', + // class annotation + 0x78, + // super class desc + 0x70, + // classdata[] + 0x12, 0x34, 0x56, 0x78 + }); + ByteArrayInputStream in = new ByteArrayInputStream(array); + ObjectInputStream in2 = new ObjectInputStream(in); + expectEqual(true, in2.readBoolean()); + expectEqual(17, in2.readByte()); + expectEqual(0xcafebabe, in2.readInt()); + expectEqual("Max & Möritz", in2.readUTF()); + expectEqual('É›', in2.readChar()); + Serialize unserialized = (Serialize) in2.readObject(); + expectEqual(0x12345678, unserialized.dummy); + in2.close(); + + out.reset(); + out2 = new ObjectOutputStream(out); + MyMap map = new MyMap(); + map.put("key", "value"); + out2.writeObject(map); + out2.close(); + array = out.toByteArray(); + expectEqual(array, new int[] { + // magic + 0xac, 0xed, + // version + 0x00, 0x05, + // object + 0x73, + // class desc "Serialize$MyMap" + 0x72, 0, 15, 'S', 'e', 'r', 'i', 'a', 'l', 'i', 'z', 'e', '$', + 'M', 'y', 'M', 'a', 'p', + // serial version UID: 0x0cc1f64e2d266ae6 + 0x0c, 0xc1, 0xf6, 0x3e, 0x2d, 0x25, 0x6a, 0xe6, + // flags: SC_SERIALIZABLE | SC_WRITE_METHOD + 0x03, + // no (non-transient) fields + 0, 0, + // class annotation + 0x78, + // super class desc + 0x70, + // custom TreeMap data written by TreeMap#writeObject + 0x77, 4, 0x00 , 0x00, 0x00, 0x01, // (int)1 (== map.size()) + 0x74, 0, 3, 'k', 'e', 'y', // "key" + 0x74, 0, 5, 'v', 'a', 'l', 'u', 'e', // "value" + // end block data + 0x78 + }); + in = new ByteArrayInputStream(array); + in2 = new ObjectInputStream(in); + map = (MyMap)in2.readObject(); + in2.close(); + expectEqual(1, map.size()); + expectEqual("value", (String)map.get("key")); + } +} diff --git a/sgx-jvm/avian/test/Simple.java b/sgx-jvm/avian/test/Simple.java new file mode 100644 index 0000000000..ce0c470e95 --- /dev/null +++ b/sgx-jvm/avian/test/Simple.java @@ -0,0 +1,11 @@ +public class Simple { + public static int size(long v, int radix) { + int size = 0; + for (long n = v; n != 0; n /= radix) ++size; + return size; + } + + public static void main(String[] args) { + size(42, 10); + } +} diff --git a/sgx-jvm/avian/test/Sockets.java b/sgx-jvm/avian/test/Sockets.java new file mode 100644 index 0000000000..9bce0e036e --- /dev/null +++ b/sgx-jvm/avian/test/Sockets.java @@ -0,0 +1,33 @@ +import java.net.SocketAddress; +import java.net.InetSocketAddress; +import java.nio.channels.SocketChannel; +import java.io.IOException; + +public class Sockets { + private static void expect(boolean v) { + if (! v) throw new RuntimeException(); + } + + public static void testFailedBind() throws Exception { + final String Hostname = "localhost"; + final int Port = 22046; // hopefully this port is unused + final SocketAddress Address = new InetSocketAddress(Hostname, Port); + final byte[] Message = "hello, world!".getBytes(); + + SocketChannel out = SocketChannel.open(); + try { + try { + out.connect(Address); + expect(false); + } catch(IOException e) { + // We're good. This previously triggered a vm assert, rather than an exception + } + } finally { + out.close(); + } + } + + public static void main(String[] args) throws Exception { + testFailedBind(); + } +} diff --git a/sgx-jvm/avian/test/StackOverflow.java b/sgx-jvm/avian/test/StackOverflow.java new file mode 100644 index 0000000000..e25e3819eb --- /dev/null +++ b/sgx-jvm/avian/test/StackOverflow.java @@ -0,0 +1,41 @@ +public class StackOverflow { + private static int add(int[] numbers, int offset, int length) { + if (length == 0) { + return 0; + } else { + return numbers[offset] + add(numbers, offset + 1, length - 1); + } + } + private static int add(int ... numbers) { + return add(numbers, 0, numbers.length); + } + + private static int test1() { + add(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); + return test1() + 1; + } + + private static int test2() { + return test3() + 1; + } + + private static int test3() { + return test2() + 1; + } + + public static void main(String[] args) { + try { + test1(); + throw new RuntimeException(); + } catch (StackOverflowError e) { + e.printStackTrace(); + } + + try { + test2(); + throw new RuntimeException(); + } catch (StackOverflowError e) { + e.printStackTrace(); + } + } +} diff --git a/sgx-jvm/avian/test/StringBuilderTest.java b/sgx-jvm/avian/test/StringBuilderTest.java new file mode 100644 index 0000000000..3060b4f975 --- /dev/null +++ b/sgx-jvm/avian/test/StringBuilderTest.java @@ -0,0 +1,65 @@ + +public class StringBuilderTest { + private static final int iterations = 1000; + + public static void main(String[] args) { + verifyAppendStrLength(); + verifyAppendCharLength(); + verifySubstring(); + } + + private static void verify(String srcStr, int iterations, String result) { + int expectedLength = srcStr.length() * iterations; + if (result.length() != expectedLength) { + throw new IllegalStateException("Incorrect length: " + result.length() + " vs " + expectedLength); + } + } + + private static void verify(String expected, String actual) { + if (! expected.equals(actual)) { + throw new IllegalStateException("Strings don't match, expected: " + expected + ", actual: " + actual); + } + } + + private static void verifyAppendStrLength() { + String fooStr = "foobar"; + + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < iterations; i++) { + sb.append(fooStr); + } + String result = sb.toString(); + + verify(fooStr, iterations, result); + } + + private static void verifyAppendCharLength() { + int iterations = 5000; + String fooStr = "foobar"; + char[] fooChars = new char[fooStr.length()]; + fooStr.getChars(0, fooStr.length(), fooChars, 0); + + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < iterations; i++) { + for (int j = 0; j < fooChars.length; j++) { + sb.append(fooChars[j]); + } + } + String result = sb.toString(); + + verify(fooStr, iterations, result); + } + + private static void verifySubstring() { + String fooStr = "foobar"; + StringBuilder sb = new StringBuilder(); + sb.append(fooStr); + sb.append(fooStr); + + String beginingSubString = sb.substring(0, fooStr.length()); + verify(fooStr, beginingSubString); + + String endSubString = sb.substring(fooStr.length()); + verify(fooStr, endSubString); + } +} diff --git a/sgx-jvm/avian/test/Strings.java b/sgx-jvm/avian/test/Strings.java new file mode 100644 index 0000000000..df3ca334ff --- /dev/null +++ b/sgx-jvm/avian/test/Strings.java @@ -0,0 +1,231 @@ +public class Strings { + private static void expect(boolean v) { + if (! v) throw new RuntimeException(); + } + + private static boolean equal(Object a, Object b) { + return a == b || (a != null && a.equals(b)); + } + + private static boolean arraysEqual(byte[] a, byte[] b) { + if (a.length != b.length) { + return false; + } + + for (int i = 0; i < a.length; ++i) { + if (a[i] != b[i]) { + return false; + } + } + + return true; + } + + private static byte[] append(byte[] a, byte[] b) { + byte[] c = new byte[a.length + b.length]; + for (int i = 0; i < a.length; ++i) { + c[i] = a[i]; + } + for (int i = 0; i < b.length; ++i) { + c[i + a.length] = b[i]; + } + return c; + } + + private static boolean arraysEqual(Object[] a, Object[] b) { + if (a.length != b.length) { + return false; + } + + for (int i = 0; i < a.length; ++i) { + if (! equal(a[i], b[i])) { + return false; + } + } + + return true; + } + + private static void testDecode(final boolean prematureEOS) throws Exception { + java.io.Reader r = new java.io.InputStreamReader + (new java.io.InputStream() { + int state = 0; + + public int read() { + throw new UnsupportedOperationException(); + } + + public int read(byte[] b, int offset, int length) { + if (length == 0) return 0; + + switch (state) { + case 0: + b[offset] = (byte) 0xc2; + state = 1; + return 1; + + case 1: + b[offset] = (byte) 0xae; + state = 2; + return 1; + + case 2: + b[offset] = (byte) 0xea; + state = 3; + return 1; + + case 3: + b[offset] = (byte) 0xba; + state = prematureEOS ? 5 : 4; + return 1; + + case 4: + b[offset] = (byte) 0xaf; + state = 5; + return 1; + + case 5: + return -1; + + default: + throw new RuntimeException(); + } + } + }, "UTF-8"); + + char[] buffer = new char[2]; + int offset = 0; + while (offset < buffer.length) { + int c = r.read(buffer, offset, buffer.length - offset); + if (c == -1) break; + offset += c; + } + + expect(new String(buffer, 0, offset).equals + (prematureEOS ? "\u00ae\ufffd" : "\u00ae\uaeaf")); + } + + public static void testTrivialPattern() throws Exception { + expect("?7".matches("\\0777")); + expect("\007".matches("\\a")); + expect("\\".matches("\\\\")); + expect("J".matches("\\x4A")); + expect("a".matches("\\x61")); + expect("\0078".matches("\\078")); + } + + public static void main(String[] args) throws Exception { + expect(new String(new byte[] { 99, 111, 109, 46, 101, 99, 111, 118, 97, + 116, 101, 46, 110, 97, 116, 46, 98, 117, + 115, 46, 83, 121, 109, 98, 111, 108 }) + .equals("com.ecovate.nat.bus.Symbol")); + + final String months = "Jan\u00aeFeb\u00aeMar\u00ae"; + expect(months.split("\u00ae").length == 3); + expect(months.replaceAll("\u00ae", ".").equals("Jan.Feb.Mar.")); + + // Java 8 changed the semantics of String.split relative to + // previous versions, therefore we accept multiple possible + // results: + expect(arraysEqual + ("xyz".split("", 0), new String[] { "", "x", "y", "z" }) + || arraysEqual + ("xyz".split("", 0), new String[] { "x", "y", "z" })); + expect(arraysEqual + ("xyz".split("", 1), new String[] { "xyz" })); + expect(arraysEqual + ("xyz".split("", 2), new String[] { "", "xyz" }) + || arraysEqual + ("xyz".split("", 2), new String[] { "x", "yz" })); + expect(arraysEqual + ("xyz".split("", 3), new String[] { "", "x", "yz" }) + || arraysEqual + ("xyz".split("", 3), new String[] { "x", "y", "z" })); + expect(arraysEqual + ("xyz".split("", 4), new String[] { "", "x", "y", "z" }) + || arraysEqual + ("xyz".split("", 4), new String[] { "x", "y", "z", "" })); + expect(arraysEqual + ("xyz".split("", 5), new String[] { "", "x", "y", "z", "" }) + || arraysEqual + ("xyz".split("", 5), new String[] { "x", "y", "z", "" })); + expect(arraysEqual + ("xyz".split("", 6), new String[] { "", "x", "y", "z", "" }) + || arraysEqual + ("xyz".split("", 6), new String[] { "x", "y", "z", "" })); + expect(arraysEqual + ("xyz".split("", -1), new String[] { "", "x", "y", "z", "" }) + || arraysEqual + ("xyz".split("", -1), new String[] { "x", "y", "z", "" })); + + expect(arraysEqual("".split("xyz", 0), new String[] { "" })); + expect(arraysEqual("".split("xyz", 1), new String[] { "" })); + expect(arraysEqual("".split("xyz", -1), new String[] { "" })); + + expect(arraysEqual("".split("", 0), new String[] { "" })); + expect(arraysEqual("".split("", 1), new String[] { "" })); + expect(arraysEqual("".split("", -1), new String[] { "" })); + + expect("foo_foofoo__foo".replaceAll("_", "__") + .equals("foo__foofoo____foo")); + + expect("foo_foofoo__foo".replaceFirst("_", "__") + .equals("foo__foofoo__foo")); + + expect("stereomime".matches("stereomime")); + expect(! "stereomime".matches("stereomim")); + expect(! "stereomime".matches("tereomime")); + expect(! "stereomime".matches("sterEomime")); + + StringBuilder sb = new StringBuilder(); + sb.append('$'); + sb.append('2'); + expect(sb.substring(1).equals("2")); + + expect(Character.forDigit(Character.digit('0', 10), 10) == '0'); + expect(Character.forDigit(Character.digit('9', 10), 10) == '9'); + expect(Character.forDigit(Character.digit('b', 16), 16) == 'b'); + expect(Character.forDigit(Character.digit('f', 16), 16) == 'f'); + expect(Character.forDigit(Character.digit('z', 36), 36) == 'z'); + + testDecode(false); + testDecode(true); + + expect + (java.text.MessageFormat.format + ("{0} enjoy {1} {2}. do {4}? {4} do?", + "I", "grape", "nuts", "foobar", + new Object() { public String toString() { return "you"; } }) + .equals("I enjoy grape nuts. do you? you do?")); + + { java.io.ByteArrayOutputStream bout = new java.io.ByteArrayOutputStream(); + java.io.PrintStream pout = new java.io.PrintStream(bout, true, "UTF-8"); + String s = "I ♥ grape nuts"; + System.out.println(s); + pout.println(s); + + expect + (arraysEqual + (bout.toByteArray(), + (s + System.getProperty("line.separator")).getBytes("UTF-8"))); + + expect + (arraysEqual + (bout.toByteArray(), append + (new byte[] { 73, 32, -30, -103, -91, 32, 103, 114, 97, 112, 101, + 32, 110, 117, 116, 115 }, + System.getProperty("line.separator").getBytes("UTF-8")))); + } + + expect("abc".lastIndexOf('b', 100) == 1); + + testTrivialPattern(); + + { String s = "hello, world!"; + java.nio.CharBuffer buffer = java.nio.CharBuffer.allocate(s.length()); + new java.io.InputStreamReader + (new java.io.ByteArrayInputStream(s.getBytes())).read(buffer); + expect(s.equals(new String(buffer.array()))); + } + } +} diff --git a/sgx-jvm/avian/test/Subroutine.java b/sgx-jvm/avian/test/Subroutine.java new file mode 100644 index 0000000000..e03686a9f5 --- /dev/null +++ b/sgx-jvm/avian/test/Subroutine.java @@ -0,0 +1,347 @@ +import avian.Stream; +import avian.ConstantPool; +import avian.ConstantPool.PoolEntry; +import avian.Assembler; +import avian.Assembler.FieldData; +import avian.Assembler.MethodData; + +import java.util.ArrayList; +import java.util.List; +import java.io.ByteArrayOutputStream; +import java.io.OutputStream; +import java.io.IOException; + +public class Subroutine { + private static void expect(boolean v) { + if (! v) throw new RuntimeException(); + } + + private static void stackMap(Object x) { + while (true) { + try { + try { + System.gc(); + } catch (DummyException e) { + // ignore + } finally { + x.toString(); + } + break; + } catch (DummyException e) { + // ignore + } + } + } + + private static byte[] makeTestCode(List pool) throws IOException { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + Stream.write2(out, 1); // max stack + Stream.write2(out, 1); // max locals + Stream.write4(out, 0); // length (we'll set the real value later) + + // 0: + Stream.write1(out, Assembler.ldc_w); + Stream.write2(out, ConstantPool.addString(pool, "foo") + 1); + + // 3: + Stream.write1(out, Assembler.astore_0); + + // 4: + Stream.write1(out, Assembler.invokestatic); + Stream.write2(out, ConstantPool.addMethodRef + (pool, "java/lang/System", "gc", "()V") + 1); + + // 7: + Stream.write1(out, Assembler.goto_); + Stream.write2(out, 9); // 16 + + // 10: + Stream.write1(out, Assembler.astore_0); + + // 11: + Stream.write1(out, Assembler.invokestatic); + Stream.write2(out, ConstantPool.addMethodRef + (pool, "java/lang/System", "gc", "()V") + 1); + + // 14: + Stream.write1(out, Assembler.ret); + Stream.write1(out, 0); + + // 16: + Stream.write1(out, Assembler.jsr); + Stream.write2(out, -6); // 10 + + // 19: + Stream.write1(out, Assembler.invokestatic); + Stream.write2(out, ConstantPool.addMethodRef + (pool, "java/lang/System", "gc", "()V") + 1); + + // 22: + Stream.write1(out, Assembler.return_); + + Stream.write2(out, 0); // exception handler table length + Stream.write2(out, 0); // attribute count + + byte[] result = out.toByteArray(); + Stream.set4(result, 4, result.length - 12); + + return result; + } + + private static Class makeTestClass() throws IOException { + List pool = new ArrayList(); + ByteArrayOutputStream out = new ByteArrayOutputStream(); + String name = "$SubroutineTest$"; + + Assembler.writeClass + (out, pool, ConstantPool.addClass(pool, name), + ConstantPool.addClass(pool, "java/lang/Object"), + new int[0], new FieldData[0], new MethodData[] + { new MethodData(Assembler.ACC_STATIC | Assembler.ACC_PUBLIC, + ConstantPool.addUtf8(pool, "test"), + ConstantPool.addUtf8(pool, "()V"), + makeTestCode(pool)) }); + + return new MyClassLoader(Subroutine.class.getClassLoader()) + .defineClass(name, out.toByteArray()); + } + + // These tests are intended to cover the jsr and ret instructions. + // However, recent Sun javac versions avoid generating these + // instructions by default, so we must compile this class using + // -source 1.2 -target 1.1 -XDjsrlimit=0. + // + // http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4381996 + // + + private static void test(boolean throw_, boolean predicate) { + int x = 42; + int y = 99; + int a = 0; + try { + try { + int z = x + y; + if (throw_) throw new DummyException(); + if (predicate) { + return; + } + Integer.valueOf(z).toString(); + } finally { + a = x + y; + System.gc(); + } + expect(a == x + y); + } catch (DummyException e) { + e.printStackTrace(); + } + } + + private static Object test2(int path) { + try { + try { + switch (path) { + case 1: + return new Object(); + + case 2: { + int a = 42; + return Integer.valueOf(a); + } + + case 3: + throw new DummyException(); + } + } finally { + System.gc(); + } + return null; + } catch (DummyException e) { + e.printStackTrace(); + return null; + } + } + + private static Object test3(int path1, int path2, int path3) { + try { + try { + switch (path1) { + case 1: + return new Object(); + + case 2: { + int a = 42; + return Integer.valueOf(a); + } + + case 3: + throw new DummyException(); + } + } finally { + try { + switch (path2) { + case 1: + return new Object(); + + case 2: { + int a = 42; + return Integer.valueOf(a); + } + + case 3: + throw new DummyException(); + } + } finally { + try { + switch (path3) { + case 1: + return new Object(); + + case 2: { + int a = 42; + return Integer.valueOf(a); + } + + case 3: + throw new DummyException(); + } + } finally { + System.gc(); + } + } + } + return null; + } catch (DummyException e) { + e.printStackTrace(); + return null; + } + } + + private static long test4(int path) { + try { + try { + switch (path) { + case 1: + return 0xFABFABFABFL; + + case 2: { + int a = 42; + return 52L; + } + + case 3: + throw new DummyException(); + } + } finally { + System.gc(); + } + return 0L; + } catch (DummyException e) { + e.printStackTrace(); + return 0L; + } + } + + private boolean test5(boolean predicate) { + try { + if (predicate) { + return false; + } + } finally { + synchronized (this) { + notifyAll(); + } + } + return true; + } + + private static int test6(boolean predicate) { + try { + if (predicate) { + return -2; + } + } finally { + return new Throwable().getStackTrace()[0].getLineNumber(); + } + } + + public static void main(String[] args) throws Exception { + test(false, false); + test(false, true); + test(true, false); + + String.valueOf(test2(1)); + String.valueOf(test2(2)); + String.valueOf(test2(3)); + + String.valueOf(test3(1, 1, 1)); + String.valueOf(test3(2, 1, 1)); + String.valueOf(test3(3, 1, 1)); + + String.valueOf(test3(1, 2, 1)); + String.valueOf(test3(2, 2, 1)); + String.valueOf(test3(3, 2, 1)); + + String.valueOf(test3(1, 3, 1)); + String.valueOf(test3(2, 3, 1)); + String.valueOf(test3(3, 3, 1)); + + String.valueOf(test3(1, 1, 2)); + String.valueOf(test3(2, 1, 2)); + String.valueOf(test3(3, 1, 2)); + + String.valueOf(test3(1, 2, 2)); + String.valueOf(test3(2, 2, 2)); + String.valueOf(test3(3, 2, 2)); + + String.valueOf(test3(1, 3, 2)); + String.valueOf(test3(2, 3, 2)); + String.valueOf(test3(3, 3, 2)); + + String.valueOf(test3(1, 1, 3)); + String.valueOf(test3(2, 1, 3)); + String.valueOf(test3(3, 1, 3)); + + String.valueOf(test3(1, 2, 3)); + String.valueOf(test3(2, 2, 3)); + String.valueOf(test3(3, 2, 3)); + + String.valueOf(test3(1, 3, 3)); + String.valueOf(test3(2, 3, 3)); + String.valueOf(test3(3, 3, 3)); + + String.valueOf(test4(1)); + String.valueOf(test4(2)); + String.valueOf(test4(3)); + + expect(test4(1) == 0xFABFABFABFL); + + new Subroutine().test5(true); + new Subroutine().test5(false); + + makeTestClass().getMethod("test", new Class[0]).invoke + (null, new Object[0]); + + stackMap(new Object()); + + { + int f = test6(false); + int t = test6(true); + System.out.println("line: " + f); + expect(f > 0); + expect(f == t); + } + + } + + private static class DummyException extends RuntimeException { } + + private static class MyClassLoader extends ClassLoader { + public MyClassLoader(ClassLoader parent) { + super(parent); + } + + public Class defineClass(String name, byte[] bytes) { + return super.defineClass(name, bytes, 0, bytes.length); + } + } +} diff --git a/sgx-jvm/avian/test/Switch.java b/sgx-jvm/avian/test/Switch.java new file mode 100644 index 0000000000..bb1c0a459f --- /dev/null +++ b/sgx-jvm/avian/test/Switch.java @@ -0,0 +1,66 @@ +public class Switch { + private static int table(int k) { + switch (k) { + case 0: + return 0; + case 1: + return 1; + case 2: + return 2; + case 9: + return 9; + case 10: + return 10; + case 11: + return 11; + case 12: + return 8; + case -5: + return 5; + default: + return 7; + } + } + + private static int lookup(int k) { + switch (k) { + case 0: + return 0; + case 45: + return 45; + case 46: + return 46; + case 47: + return -47; + case 200: + return 200; + case 244: + return 244; + case 245: + return 245; + default: + return 91; + } + } + + private static void expect(boolean v) { + if (! v) throw new RuntimeException(); + } + + public static void main(String[] args) { + expect(table(0) == 0); + expect(table(9) == 9); + expect(table(10) == 10); + expect(table(11) == 11); + expect(table(12) == 8); + expect(table(-5) == 5); + expect(table(-13) == 7); + + expect(lookup(0) == 0); + expect(lookup(45) == 45); + expect(lookup(46) == 46); + expect(lookup(47) == -47); + expect(lookup(245) == 245); + expect(lookup(246) == 91); + } +} diff --git a/sgx-jvm/avian/test/Threads.java b/sgx-jvm/avian/test/Threads.java new file mode 100644 index 0000000000..5f4860bd7b --- /dev/null +++ b/sgx-jvm/avian/test/Threads.java @@ -0,0 +1,94 @@ +public class Threads implements Runnable { + private static boolean success = false; + + private static void expect(boolean v) { + if (! v) throw new RuntimeException(); + } + + public static void main(String[] args) throws Exception { + ((Thread.UncaughtExceptionHandler) Thread.currentThread().getThreadGroup()) + .uncaughtException(Thread.currentThread(), new Exception()); + + { Threads test = new Threads(); + Thread thread = new Thread(test); + + synchronized (test) { + thread.start(); + test.wait(); + } + } + + { Thread thread = new Thread() { + public void run() { + while (true) { + System.out.print("."); + try { + sleep(1000); + } catch (Exception e) { + System.out.println("thread interrupted? " + interrupted()); + break; + } + } + } + }; + thread.start(); + + System.out.println("\nAbout to interrupt..."); + thread.interrupt(); + System.out.println("\nInterrupted!"); + } + + { Thread thread = new Thread() { + @Override + public void run() { + // do nothing + } + }; + + thread.start(); + thread.join(); + } + + System.out.println("finished; success? " + success); + + if (! success) { + System.exit(-1); + } + } + + public void run() { + int i = 0; + try { + expect(! Thread.holdsLock(this)); + synchronized (this) { + expect(Thread.holdsLock(this)); + + System.out.println("I'm running in a separate thread!"); + + Thread.yield(); // just to prove Thread.yield exists and is callable + + final int arrayCount = 16; + final int arraySize = 4; + System.out.println("Allocating and discarding " + arrayCount + + " arrays of " + arraySize + "MB each"); + for (; i < arrayCount; ++i) { + byte[] array = new byte[arraySize * 1024 * 1024]; + } + + long nap = 500; + System.out.println("sleeping for " + nap + " milliseconds"); + Thread.sleep(nap); + notifyAll(); + } + success = true; + } catch (Throwable e) { + System.err.println("caught something in second thread after " + i + + " iterations"); + e.printStackTrace(); + } finally { + synchronized (this) { + notifyAll(); + } + } + } +} diff --git a/sgx-jvm/avian/test/TimeUnitConversions.java b/sgx-jvm/avian/test/TimeUnitConversions.java new file mode 100644 index 0000000000..b681f60076 --- /dev/null +++ b/sgx-jvm/avian/test/TimeUnitConversions.java @@ -0,0 +1,117 @@ +import java.util.concurrent.TimeUnit; + +public class TimeUnitConversions { + private static void expect(long v1, long v2) { + if (v1 != v2) { + throw new RuntimeException(v1 + " != " + v2); + } + } + + private static void toNanoConversionTest() { + long expectedValue = 1; + expect(TimeUnit.NANOSECONDS.convert(1, TimeUnit.NANOSECONDS), expectedValue); + expectedValue *= 1000; + expect(TimeUnit.NANOSECONDS.convert(1, TimeUnit.MICROSECONDS), expectedValue); + expectedValue *= 1000; + expect(TimeUnit.NANOSECONDS.convert(1, TimeUnit.MILLISECONDS), expectedValue); + expectedValue *= 1000; + expect(TimeUnit.NANOSECONDS.convert(1, TimeUnit.SECONDS), expectedValue); + expectedValue *= 60; + expect(TimeUnit.NANOSECONDS.convert(1, TimeUnit.MINUTES), expectedValue); + expectedValue *= 60; + expect(TimeUnit.NANOSECONDS.convert(1, TimeUnit.HOURS), expectedValue); + expectedValue *= 24; + expect(TimeUnit.NANOSECONDS.convert(1, TimeUnit.DAYS), expectedValue); + } + + private static void toMicroConversionTest() { + long expectedValue = 1; + expect(TimeUnit.MICROSECONDS.convert(1000, TimeUnit.NANOSECONDS), expectedValue); + expect(TimeUnit.MICROSECONDS.convert(1, TimeUnit.MICROSECONDS), expectedValue); + expectedValue *= 1000; + expect(TimeUnit.MICROSECONDS.convert(1, TimeUnit.MILLISECONDS), expectedValue); + expectedValue *= 1000; + expect(TimeUnit.MICROSECONDS.convert(1, TimeUnit.SECONDS), expectedValue); + expectedValue *= 60; + expect(TimeUnit.MICROSECONDS.convert(1, TimeUnit.MINUTES), expectedValue); + expectedValue *= 60; + expect(TimeUnit.MICROSECONDS.convert(1, TimeUnit.HOURS), expectedValue); + expectedValue *= 24; + expect(TimeUnit.MICROSECONDS.convert(1, TimeUnit.DAYS), expectedValue); + } + + private static void toMilliConversionTest() { + long expectedValue = 1; + expect(TimeUnit.MILLISECONDS.convert(1000L * 1000, TimeUnit.NANOSECONDS), expectedValue); + expect(TimeUnit.MILLISECONDS.convert(1000, TimeUnit.MICROSECONDS), expectedValue); + expect(TimeUnit.MILLISECONDS.convert(1, TimeUnit.MILLISECONDS), expectedValue); + expectedValue *= 1000; + expect(TimeUnit.MILLISECONDS.convert(1, TimeUnit.SECONDS), expectedValue); + expectedValue *= 60; + expect(TimeUnit.MILLISECONDS.convert(1, TimeUnit.MINUTES), expectedValue); + expectedValue *= 60; + expect(TimeUnit.MILLISECONDS.convert(1, TimeUnit.HOURS), expectedValue); + expectedValue *= 24; + expect(TimeUnit.MILLISECONDS.convert(1, TimeUnit.DAYS), expectedValue); + } + + private static void toSecondConversionTest() { + long expectedValue = 1; + expect(TimeUnit.SECONDS.convert(1000L * 1000 * 1000, TimeUnit.NANOSECONDS), expectedValue); + expect(TimeUnit.SECONDS.convert(1000L * 1000, TimeUnit.MICROSECONDS), expectedValue); + expect(TimeUnit.SECONDS.convert(1000, TimeUnit.MILLISECONDS), expectedValue); + expect(TimeUnit.SECONDS.convert(1, TimeUnit.SECONDS), expectedValue); + expectedValue *= 60; + expect(TimeUnit.SECONDS.convert(1, TimeUnit.MINUTES), expectedValue); + expectedValue *= 60; + expect(TimeUnit.SECONDS.convert(1, TimeUnit.HOURS), expectedValue); + expectedValue *= 24; + expect(TimeUnit.SECONDS.convert(1, TimeUnit.DAYS), expectedValue); + } + + private static void toMinuteConversionTest() { + long expectedValue = 1; + expect(TimeUnit.MINUTES.convert(1000L * 1000 * 1000 * 60, TimeUnit.NANOSECONDS), expectedValue); + expect(TimeUnit.MINUTES.convert(1000L * 1000 * 60, TimeUnit.MICROSECONDS), expectedValue); + expect(TimeUnit.MINUTES.convert(1000L * 60, TimeUnit.MILLISECONDS), expectedValue); + expect(TimeUnit.MINUTES.convert(60, TimeUnit.SECONDS), expectedValue); + expect(TimeUnit.MINUTES.convert(1, TimeUnit.MINUTES), expectedValue); + expectedValue *= 60; + expect(TimeUnit.MINUTES.convert(1, TimeUnit.HOURS), expectedValue); + expectedValue *= 24; + expect(TimeUnit.MINUTES.convert(1, TimeUnit.DAYS), expectedValue); + } + + private static void toHourConversionTest() { + long expectedValue = 1; + expect(TimeUnit.HOURS.convert(1000L * 1000 * 1000 * 60 * 60, TimeUnit.NANOSECONDS), expectedValue); + expect(TimeUnit.HOURS.convert(1000L * 1000 * 60 * 60, TimeUnit.MICROSECONDS), expectedValue); + expect(TimeUnit.HOURS.convert(1000L * 60 * 60, TimeUnit.MILLISECONDS), expectedValue); + expect(TimeUnit.HOURS.convert(60L * 60, TimeUnit.SECONDS), expectedValue); + expect(TimeUnit.HOURS.convert(60, TimeUnit.MINUTES), expectedValue); + expect(TimeUnit.HOURS.convert(1, TimeUnit.HOURS), expectedValue); + expectedValue *= 24; + expect(TimeUnit.HOURS.convert(1, TimeUnit.DAYS), expectedValue); + } + + private static void toDayConversionTest() { + long expectedValue = 1; + expect(TimeUnit.DAYS.convert(1000L * 1000 * 1000 * 60 * 60 * 24, TimeUnit.NANOSECONDS), expectedValue); + expect(TimeUnit.DAYS.convert(1000L * 1000 * 60 * 60 * 24, TimeUnit.MICROSECONDS), expectedValue); + expect(TimeUnit.DAYS.convert(1000L * 60 * 60 * 24, TimeUnit.MILLISECONDS), expectedValue); + expect(TimeUnit.DAYS.convert(60L * 60 * 24, TimeUnit.SECONDS), expectedValue); + expect(TimeUnit.DAYS.convert(60L * 24, TimeUnit.MINUTES), expectedValue); + expect(TimeUnit.DAYS.convert(24, TimeUnit.HOURS), expectedValue); + expect(TimeUnit.DAYS.convert(1, TimeUnit.DAYS), expectedValue); + } + + public static void main(String[] args) { + toNanoConversionTest(); + toMicroConversionTest(); + toMilliConversionTest(); + toSecondConversionTest(); + toMinuteConversionTest(); + toHourConversionTest(); + toDayConversionTest(); + } +} diff --git a/sgx-jvm/avian/test/Trace.java b/sgx-jvm/avian/test/Trace.java new file mode 100644 index 0000000000..2b453f4cf9 --- /dev/null +++ b/sgx-jvm/avian/test/Trace.java @@ -0,0 +1,113 @@ +public class Trace implements Runnable { + private volatile boolean alive = true; + + private static void throwSomething() { + throw new RuntimeException(); + } + + private void bar(Object o) { + o.toString(); + } + + private void foo() { + { long a = 42; + long b = 25; + long c = a / b; + } + + try { + long a = 42; + long b = 0; + long c = a / b; + } catch (Exception e) { } + + try { + throw new Exception(); + } catch (Exception e) { } + + try { + throwSomething(); + } catch (Exception e) { } + + try { + Trace.class.getMethod("bar", Object.class).invoke(this, this); + } catch (Exception e) { } + } + + private static void dummy() { + byte[] a = new byte[10]; + byte[] b = new byte[10]; + System.arraycopy(a, 0, b, 0, 10); + } + + private static void tail1(int a, int b, int c, int d, int e, int f) { + dummy(); + } + + private static void tail2() { + tail1(1, 2, 3, 4, 5, 6); + tail1(1, 2, 3, 4, 5, 6); + } + + private static void test(Trace trace) { + tail1(1, 2, 3, 4, 5, 6); + tail2(); + trace.foo(); + } + + public void run() { + synchronized (this) { + notifyAll(); + } + + try { + for (int i = 0; i < 10000; ++i) { + test(this); + + if (i % 100 == 0) { + System.out.print("r"); + System.out.flush(); + synchronized (this) { + notifyAll(); + } + } + } + } finally { + synchronized (this) { + alive = false; + notifyAll(); + } + } + } + + public static void main(String[] args) throws Exception { + if ("true".equals(System.getenv("TRAVIS"))) { + // This test fails randomly on Travis-CI, though we've never + // been able to reproduce the failure elsewhere. So we disable + // it if we know we're running on Travis. + return; + } + + Trace trace = new Trace(); + Thread thread = new Thread(trace); + + synchronized (trace) { + thread.start(); + trace.wait(); + + int count = 0; + while (trace.alive) { + thread.getStackTrace(); + ++ count; + + if (count % 100 == 0) { + trace.wait(); + System.out.print("t"); + System.out.flush(); + } + } + + System.out.println("\ngot " + count + " traces"); + } + } +} diff --git a/sgx-jvm/avian/test/Tree.java b/sgx-jvm/avian/test/Tree.java new file mode 100644 index 0000000000..ec7c5cf41f --- /dev/null +++ b/sgx-jvm/avian/test/Tree.java @@ -0,0 +1,133 @@ +import java.util.Comparator; +import java.util.TreeSet; +import java.util.TreeMap; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Map; +import java.util.Iterator; + +public class Tree { + private static void expect(boolean v) { + if (! v) throw new RuntimeException(); + } + + private static String printList(TreeSet list) { + StringBuilder sb = new StringBuilder(); + + for (Object o : list) { + sb.append(o); + sb.append(", "); + } + sb.setLength(sb.length()-2); + return sb.toString(); + } + + private static String printMap(TreeMap map) { + StringBuilder sb = new StringBuilder(); + + for (Iterator it = map.entrySet().iterator(); it.hasNext();) { + Map.Entry e = it.next(); + sb.append(e.getKey()); + sb.append("="); + sb.append(e.getValue()); + if (it.hasNext()) { + sb.append(", "); + } + } + return sb.toString(); + } + + private static void isEqual(String s1, String s2) { + System.out.println(s1); + expect(s1.equals(s2)); + } + + private static class MyCompare implements Comparator { + public int compare(Integer o1, Integer o2) { + return o1.compareTo(o2); + } + } + + private static void ascendingIterator() { + TreeSet t = new TreeSet(); + t.add(7); + t.add(2); + t.add(9); + t.add(2); + Iterator iter = t.iterator(); + expect(2 == (int)iter.next()); + expect(7 == (int)iter.next()); + iter.remove(); + expect(9 == (int)iter.next()); + expect(!iter.hasNext()); + isEqual(printList(t), "2, 9"); + } + + private static void descendingIterator() { + TreeSet t = new TreeSet(); + t.add(7); + t.add(2); + t.add(9); + t.add(2); + Iterator iter = t.descendingIterator(); + expect(9 == (int)iter.next()); + expect(7 == (int)iter.next()); + iter.remove(); + expect(2 == (int)iter.next()); + expect(!iter.hasNext()); + isEqual(printList(t), "2, 9"); + } + + public static void main(String args[]) { + ascendingIterator(); + descendingIterator(); + TreeSet t1 = new TreeSet(new MyCompare()); + t1.add(5); t1.add(2); t1.add(1); t1.add(8); t1.add(3); + isEqual(printList(t1), "1, 2, 3, 5, 8"); + t1.add(4); + isEqual(printList(t1), "1, 2, 3, 4, 5, 8"); + t1.remove(3); + isEqual(printList(t1), "1, 2, 4, 5, 8"); + TreeSet t2 = new TreeSet(new Comparator() { + public int compare(String s1, String s2) { + return s1.compareTo(s2); + } + }); + t2.add("one"); t2.add("two"); t2.add("three"); t2.add("four"); t2.add("five"); + isEqual(printList(t2), "five, four, one, three, two"); + for (int i=0; i < 1000; i++) { + t2.add(Integer.toString(i)); + } + expect(t2.size() == 1005); + for (int i=0; i < 999; i++) { + t2.remove(Integer.toString(i)); + } + expect(t2.size() == 6); + t2.add("kappa"); + isEqual(printList(t2), "999, five, four, kappa, one, three, two"); + + TreeMap map = new TreeMap + (new Comparator() { + public int compare(String s1, String s2) { + return s1.compareTo(s2); + } + }); + + map.put("q", "Q"); + map.put("a", "A"); + map.put("b", "B"); + map.put("z", "Z"); + map.put("c", "C"); + map.put("y", "Y"); + + isEqual(printMap(map), "a=A, b=B, c=C, q=Q, y=Y, z=Z"); + + Collection list = new ArrayList(); + list.add(7); + list.add(2); + list.add(9); + list.add(2); + + isEqual(printList(new TreeSet(list)), "2, 7, 9"); + } +} diff --git a/sgx-jvm/avian/test/UnsafeTest.java b/sgx-jvm/avian/test/UnsafeTest.java new file mode 100644 index 0000000000..732c281a4a --- /dev/null +++ b/sgx-jvm/avian/test/UnsafeTest.java @@ -0,0 +1,171 @@ +import sun.misc.Unsafe; + +public class UnsafeTest { + private static void expect(boolean v) { + if (! v) throw new RuntimeException(); + } + + private static void unsafeThrow(Unsafe u) { + u.throwException(new Exception()); + } + + private static void unsafeCatch(Unsafe u) { + boolean success = false; + try { + unsafeThrow(u); + } catch(Exception e) { + expect(e.getClass() == Exception.class); + success = true; + } + expect(success); + } + + private static void unsafeMemory(Unsafe u) { + final long size = 64; + long memory = u.allocateMemory(size); + try { + for (int i = 0; i < size; ++i) + u.putByte(memory + i, (byte) 42); + + for (int i = 0; i < size; ++i) + expect(u.getByte(memory + i) == 42); + + for (int i = 0; i < size / 2; ++i) + u.putShort(memory + (i * 2), (short) -12345); + + for (int i = 0; i < size / 2; ++i) + expect(u.getShort(memory + (i * 2)) == -12345); + + for (int i = 0; i < size / 2; ++i) + u.putChar(memory + (i * 2), (char) 23456); + + for (int i = 0; i < size / 2; ++i) + expect(u.getChar(memory + (i * 2)) == 23456); + + for (int i = 0; i < size / 4; ++i) + u.putInt(memory + (i * 4), 0x12345678); + + for (int i = 0; i < size / 4; ++i) + expect(u.getInt(memory + (i * 4)) == 0x12345678); + + for (int i = 0; i < size / 4; ++i) + u.putFloat(memory + (i * 4), 1.2345678F); + + for (int i = 0; i < size / 4; ++i) + expect(u.getFloat(memory + (i * 4)) == 1.2345678F); + + for (int i = 0; i < size / 8; ++i) + u.putLong(memory + (i * 8), 0x1234567890ABCDEFL); + + for (int i = 0; i < size / 8; ++i) + expect(u.getLong(memory + (i * 8)) == 0x1234567890ABCDEFL); + + for (int i = 0; i < size / 8; ++i) + u.putDouble(memory + (i * 8), 1.23456789012345D); + + for (int i = 0; i < size / 8; ++i) + expect(u.getDouble(memory + (i * 8)) == 1.23456789012345D); + + for (int i = 0; i < size / 8; ++i) + u.putAddress(memory + (i * 8), 0x12345678); + + for (int i = 0; i < size / 8; ++i) + expect(u.getAddress(memory + (i * 8)) == 0x12345678); + } finally { + u.freeMemory(memory); + } + } + + private static void unsafeArray(Unsafe u) { + final int offset = u.arrayBaseOffset(long[].class); + final int scale = u.arrayIndexScale(long[].class); + final int size = 64; + final long[] array = new long[size]; + + for (int i = 0; i < size; ++i) + u.putBooleanVolatile(array, offset + (i * scale), i % 2 == 0); + + for (int i = 0; i < size; ++i) + expect(u.getBooleanVolatile(array, offset + (i * scale)) + == (i % 2 == 0)); + + for (int i = 0; i < size; ++i) + u.putByteVolatile(array, offset + (i * scale), (byte) 42); + + for (int i = 0; i < size; ++i) + expect(u.getByteVolatile(array, offset + (i * scale)) == 42); + + for (int i = 0; i < size; ++i) + u.putShortVolatile(array, offset + (i * scale), (short) -12345); + + for (int i = 0; i < size; ++i) + expect(u.getShortVolatile(array, offset + (i * scale)) == -12345); + + for (int i = 0; i < size; ++i) + u.putCharVolatile(array, offset + (i * scale), (char) 23456); + + for (int i = 0; i < size; ++i) + expect(u.getCharVolatile(array, offset + (i * scale)) == 23456); + + for (int i = 0; i < size; ++i) + u.putIntVolatile(array, offset + (i * scale), 0x12345678); + + for (int i = 0; i < size; ++i) + expect(u.getIntVolatile(array, offset + (i * scale)) == 0x12345678); + + for (int i = 0; i < size; ++i) + u.putFloatVolatile(array, offset + (i * scale), 1.2345678F); + + for (int i = 0; i < size; ++i) + expect(u.getFloatVolatile(array, offset + (i * scale)) == 1.2345678F); + + for (int i = 0; i < size; ++i) + u.putLongVolatile(array, offset + (i * scale), 0x1234567890ABCDEFL); + + for (int i = 0; i < size; ++i) + expect(u.getLongVolatile(array, offset + (i * scale)) + == 0x1234567890ABCDEFL); + + for (int i = 0; i < size; ++i) + u.putDoubleVolatile(array, offset + (i * scale), 1.23456789012345D); + + for (int i = 0; i < size; ++i) + expect(u.getDoubleVolatile(array, offset + (i * scale)) + == 1.23456789012345D); + } + + private static class Data { + public long longField; + public double doubleField; + } + + private static void unsafeObject(Unsafe u) throws Exception { + final long longOffset = u.objectFieldOffset + (Data.class.getField("longField")); + + final long doubleOffset = u.objectFieldOffset + (Data.class.getField("doubleField")); + + Data data = new Data(); + + u.putLong(data, longOffset, 0x1234567890ABCDEFL); + + u.putDouble(data, doubleOffset, 1.23456789012345D); + + expect(u.getLong(data, longOffset) == 0x1234567890ABCDEFL); + + expect(u.getDouble(data, doubleOffset) == 1.23456789012345D); + } + + public static void main(String[] args) throws Exception { + System.out.println("method count is " + + Unsafe.class.getDeclaredMethods().length); + + Unsafe u = avian.Machine.getUnsafe(); + + unsafeCatch(u); + unsafeMemory(u); + unsafeArray(u); + unsafeObject(u); + } +} diff --git a/sgx-jvm/avian/test/UrlTest.java b/sgx-jvm/avian/test/UrlTest.java new file mode 100644 index 0000000000..244d1ec45a --- /dev/null +++ b/sgx-jvm/avian/test/UrlTest.java @@ -0,0 +1,41 @@ +import java.net.MalformedURLException; +import java.net.URL; + +public class UrlTest { + private static String query="var1=val1&var2=val2"; + private static String path="/testpath"; + private static String domain="file://www.readytalk.com"; + private static String file=path + "?" + query; + private static URL url; + + private static void expect(boolean v) { + if (! v) throw new RuntimeException(); + } + + private static void setupURL() throws MalformedURLException { + StringBuilder builder = new StringBuilder(); + builder.append(domain); + builder.append(file); + url = new URL(builder.toString()); + } + + private static void testGetPath() { + expect(url.getPath().equals(path)); + } + + private static void testGetFile() { + expect(url.getFile().equals(file)); + } + + private static void testGetQuery() { + expect(url.getQuery().equals(query)); + } + + public static void main(String[] args) throws MalformedURLException { + setupURL(); + testGetPath(); + testGetFile(); + testGetQuery(); + } + +} diff --git a/sgx-jvm/avian/test/Zip.java b/sgx-jvm/avian/test/Zip.java new file mode 100644 index 0000000000..36d08b6ca2 --- /dev/null +++ b/sgx-jvm/avian/test/Zip.java @@ -0,0 +1,53 @@ +import java.io.InputStream; +import java.io.File; +import java.util.Enumeration; +import java.util.zip.ZipFile; +import java.util.zip.ZipEntry; + +public class Zip { + + private static String findJar(File directory) { + for (File file: directory.listFiles()) { + if (file.isFile()) { + if (file.getName().endsWith(".jar")) { + System.out.println + ("found " + file.getAbsolutePath() + " length " + file.length()); + + return file.getAbsolutePath(); + } + } else if (file.isDirectory()) { + String result = findJar(file); + if (result != null) { + return result; + } + } + } + return null; + } + + public static void main(String[] args) throws Exception { + ZipFile file = new ZipFile + (findJar(new File(System.getProperty("user.dir")))); + + try { + byte[] buffer = new byte[4096]; + for (Enumeration e = file.entries(); + e.hasMoreElements();) + { + ZipEntry entry = e.nextElement(); + InputStream in = file.getInputStream(entry); + try { + int size = 0; + int c; while ((c = in.read(buffer)) != -1) size += c; + System.out.println + (entry.getName() + " " + entry.getCompressedSize() + " " + size); + } finally { + in.close(); + } + } + } finally { + file.close(); + } + } + +} diff --git a/sgx-jvm/avian/test/ZipOutputStreamTest.java b/sgx-jvm/avian/test/ZipOutputStreamTest.java new file mode 100644 index 0000000000..61a0335ef0 --- /dev/null +++ b/sgx-jvm/avian/test/ZipOutputStreamTest.java @@ -0,0 +1,214 @@ +import java.io.BufferedReader; +import java.io.File; +import java.io.FileOutputStream; +import java.io.InputStreamReader; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.zip.*; + +public class ZipOutputStreamTest +{ + private static final String TEST1 = "test1.txt"; + private static final String TEST2 = "test2.txt"; + private static final String TEST3 = "test3.txt"; + private static final String TEST4 = "test4.txt"; + + private static final String TEST1_CONTENTS = "\"this is a test\""; + private static final String TEST2_CONTENTS = "this is a\nmulti-line test"; + private static final String TEST3_CONTENTS = "74 68 69 73 20 69 73 20 61 20 74 65 73 74"; + private static final String TEST4_CONTENTS = "01110100 01101000 01101001 01110011 00100000 01101001 01110011 00100000 01100001 00100000 01110100 01100101 01110011 01110100"; + + private static final String BYTE_ZIP_PREFIX = "zosByte"; + private static final String ARRAY_ZIP_PREFIX = "zosArray"; + private static final String ARRAY_OFFSET_LENGTH_ZIP_PREFIX = "zosArrayOffsetLength"; + private static final String ZIP_SUFFIX = ".zip"; + + private static final Map FILES_CONTENTS; + static + { + Map m = new HashMap(); + m.put(TEST1, TEST1_CONTENTS); + m.put(TEST2, TEST2_CONTENTS); + m.put(TEST3, TEST3_CONTENTS); + m.put(TEST4, TEST4_CONTENTS); + FILES_CONTENTS = Collections.unmodifiableMap(m); + } + + private static enum WriteStyle { + Byte(ARRAY_ZIP_PREFIX), + Array(ARRAY_ZIP_PREFIX), + ArrayOffsetLength(ARRAY_OFFSET_LENGTH_ZIP_PREFIX); + + public final String prefix; + + private WriteStyle(String prefix) { + this.prefix = prefix; + } + } + private static byte[] buffer = new byte[1024]; + + private static void expect(boolean v) { + if (! v) throw new RuntimeException(); + } + + public static void main(String[] args) + throws Exception + { + List zipFiles = new ArrayList(2); + + try { + // Test byte-at-a-time write function + File f1 = createZip(WriteStyle.Byte); + zipFiles.add(f1); + verifyContents(f1.getAbsolutePath()); + // Test arraw write function + File f2 = createZip(WriteStyle.Array); + zipFiles.add(f2); + verifyContents(f2.getAbsolutePath()); + // Test arraw write function + File f3 = createZip(WriteStyle.ArrayOffsetLength); + zipFiles.add(f3); + verifyContents(f3.getAbsolutePath()); + } finally { + // Remove the created zip files + cleanUp(zipFiles); + } + } + + private static File createZip(WriteStyle writeStyle) + throws Exception + { + FileOutputStream outputStream = null; + ZipOutputStream zipContents = null; + + try + { + // Create a temporary zip file for this test + String prefix = writeStyle.prefix; + File outputZip = File.createTempFile(prefix, ZIP_SUFFIX); + + System.out.println("Created " + outputZip.getAbsolutePath()); + + // Prepare the streams + outputStream = new FileOutputStream(outputZip); + zipContents = new ZipOutputStream(outputStream); + + // Zip the file contents (convert directly from string to bytes) + long startTime = System.currentTimeMillis(); + for (Map.Entry f : FILES_CONTENTS.entrySet()) + { + String name = f.getKey(); + String contents = f.getValue(); + + System.out.println("Zipping " + name + "..."); + ZipEntry entry = new ZipEntry(name); + zipContents.putNextEntry(entry); + + byte[] bytesToWrite = contents.getBytes(); + + switch (writeStyle) { + case Byte: { + // Use the 1-parameter write method; takes a single byte + for (int i = 0; i < bytesToWrite.length; i++) + { + zipContents.write(bytesToWrite[i]); + } + } break; + + case Array: { + // Use 3-parameter write method; takes a buffer, offset, and length + zipContents.write(bytesToWrite); + } break; + + case ArrayOffsetLength: { + // Use 3-parameter write method; takes a buffer, offset, and length + zipContents.write(bytesToWrite, 0 , bytesToWrite.length); + } break; + + default: throw new RuntimeException("unexpected write style: " + writeStyle); + } + + // Done with this file + zipContents.closeEntry(); + System.out.println("Done"); + } + + // All files have been written + long endTime = System.currentTimeMillis(); + System.out.println("Finished " + outputZip.getName() + " in " + ((endTime - startTime) / 1000.0) + " seconds"); + return outputZip; + } + finally + { + if (zipContents != null) + zipContents.close(); + if (outputStream != null) + outputStream.close(); + } + } + + private static void verifyContents(String zipName) + throws Exception + { + System.out.println("Verify " + zipName); + ZipFile zf = null; + BufferedReader reader = null; + int numFilesInZip = 0; + + try + { + String line; + String contents; + + // Get the contents of each file in the zip + zf = new ZipFile(zipName); + for (Enumeration e = zf.entries(); e.hasMoreElements();) + { + ZipEntry entry = e.nextElement(); + reader = new BufferedReader(new InputStreamReader(zf.getInputStream(entry))); + contents = ""; + numFilesInZip += 1; + + while ((line = reader.readLine()) != null) + { + if (contents.length() > 0) + { + contents += "\n"; + } + contents += line; + } + reader.close(); + + // Assert that this file's contents are correct + expect(contents.equals(FILES_CONTENTS.get(entry.getName()))); + } + zf.close(); + + // Assert that the zip contained the correct number of files + expect(numFilesInZip == FILES_CONTENTS.size()); + } + finally + { + if (zf != null) + zf.close(); + if (reader != null) + reader.close(); + } + } + + private static void cleanUp(List zipFiles) + throws Exception + { + for (File f : zipFiles) + { + if (f.exists()) + { + f.delete(); + } + } + } +} diff --git a/sgx-jvm/avian/test/avian/TestReflection.java b/sgx-jvm/avian/test/avian/TestReflection.java new file mode 100644 index 0000000000..7b17dff52b --- /dev/null +++ b/sgx-jvm/avian/test/avian/TestReflection.java @@ -0,0 +1,9 @@ +package avian; + +import java.lang.reflect.Field; + +public class TestReflection { + public static Object get(Field field, Object target) throws Exception { + return field.get(target); + } +} diff --git a/sgx-jvm/avian/test/avian/testing/Asserts.java b/sgx-jvm/avian/test/avian/testing/Asserts.java new file mode 100644 index 0000000000..ed0ce5ec95 --- /dev/null +++ b/sgx-jvm/avian/test/avian/testing/Asserts.java @@ -0,0 +1,67 @@ +package avian.testing; + +import java.util.Collection; + +public class Asserts { + + public static void assertEquals(byte first, byte second) { + if(first != second) { + throw new RuntimeException(first+" is not equals to: "+second); + } + } + + public static void assertEquals(short first, short second) { + if(first != second) { + throw new RuntimeException(first+" is not equals to: "+second); + } + } + + public static void assertEquals(int first, int second) { + if(first != second) { + throw new RuntimeException(first+" is not equals to: "+second); + } + } + + public static void assertEquals(long first, long second) { + if(first != second) { + throw new RuntimeException(first+" is not equals to: "+second); + } + } + + public static void assertEquals(float first, float second) { + if(first != second) { + throw new RuntimeException(first+" is not equals to: "+second); + } + } + + public static void assertEquals(double first, double second) { + if(first != second) { + throw new RuntimeException(first+" is not equals to: "+second); + } + } + + + + + + public static void assertEquals(Object first, Object second) { + if(first == null && second == null) { + return; + } + if(!first.equals(second)) { + throw new RuntimeException(first+" is not equals to: "+second); + } + } + + public static void assertTrue(boolean flag) { + if (!flag) { + throw new RuntimeException("Error: "+flag+" is not True"); + } + } + + public static void assertContains(Enum element, Collection collection) { + if (!collection.contains(element)) { + throw new RuntimeException("expected " + element + " in the collection:"+collection); + } + } +} diff --git a/sgx-jvm/avian/test/avian/testing/annotations/Color.java b/sgx-jvm/avian/test/avian/testing/annotations/Color.java new file mode 100644 index 0000000000..f054b0420a --- /dev/null +++ b/sgx-jvm/avian/test/avian/testing/annotations/Color.java @@ -0,0 +1,5 @@ +package avian.testing.annotations; + +public enum Color { + Red, Yellow, Blue +} \ No newline at end of file diff --git a/sgx-jvm/avian/test/avian/testing/annotations/Test.java b/sgx-jvm/avian/test/avian/testing/annotations/Test.java new file mode 100644 index 0000000000..24b8229480 --- /dev/null +++ b/sgx-jvm/avian/test/avian/testing/annotations/Test.java @@ -0,0 +1,9 @@ +package avian.testing.annotations; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +@Retention(RetentionPolicy.RUNTIME) +public @interface Test { + public String value() default "Hello, world!"; +} diff --git a/sgx-jvm/avian/test/avian/testing/annotations/TestComplex.java b/sgx-jvm/avian/test/avian/testing/annotations/TestComplex.java new file mode 100644 index 0000000000..4e271cc9d9 --- /dev/null +++ b/sgx-jvm/avian/test/avian/testing/annotations/TestComplex.java @@ -0,0 +1,14 @@ +package avian.testing.annotations; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +@Retention(RetentionPolicy.RUNTIME) +public @interface TestComplex { + public Test[] arrayValue(); + public Class classValue(); + public String stringValue(); + public char charValue(); + public double doubleValue(); +} + diff --git a/sgx-jvm/avian/test/avian/testing/annotations/TestEnum.java b/sgx-jvm/avian/test/avian/testing/annotations/TestEnum.java new file mode 100644 index 0000000000..f8a252fd54 --- /dev/null +++ b/sgx-jvm/avian/test/avian/testing/annotations/TestEnum.java @@ -0,0 +1,8 @@ +package avian.testing.annotations; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +@Retention(RetentionPolicy.RUNTIME) +public @interface TestEnum { + public Color value(); +} \ No newline at end of file diff --git a/sgx-jvm/avian/test/avian/testing/annotations/TestInteger.java b/sgx-jvm/avian/test/avian/testing/annotations/TestInteger.java new file mode 100644 index 0000000000..b7ec78d0bc --- /dev/null +++ b/sgx-jvm/avian/test/avian/testing/annotations/TestInteger.java @@ -0,0 +1,8 @@ +package avian.testing.annotations; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +@Retention(RetentionPolicy.RUNTIME) +public @interface TestInteger { + public int value(); +} \ No newline at end of file diff --git a/sgx-jvm/avian/test/ci.sh b/sgx-jvm/avian/test/ci.sh new file mode 100755 index 0000000000..a82e95c3eb --- /dev/null +++ b/sgx-jvm/avian/test/ci.sh @@ -0,0 +1,109 @@ +#!/usr/bin/env bash + +set -eo pipefail + +root_dir=$(pwd) + +flags="use-werror=true ${@}" + +is-mac() { + if [[ $(uname -s) == "Darwin" || ${TRAVIS_OS_NAME} == "osx" ]]; then + return 0 + fi + return 1 +} + +install-deps() { + if is-mac; then + echo "------ Installing dependencies for Mac ------" + else + echo "------ Installing dependencies for Linux ------" + sudo apt-get update -qq + sudo apt-get install -y libc6-dev-i386 mingw-w64 gcc-mingw-w64-x86-64 g++-mingw-w64-i686 binutils-mingw-w64-x86-64 lib32z1-dev zlib1g-dev g++-mingw-w64-x86-64 + fi +} + +run() { + echo '===============================================' + if [ ! $(pwd) = ${root_dir} ]; then + printf "cd $(pwd); " + fi + echo "${@}" + echo '===============================================' + "${@}" +} + +run_cmake() { + mkdir -p cmake-build + rm -rf cmake-build/* + cd cmake-build + run cmake ${@} .. + run make -j4 check + cd .. +} + +publish() { + local platforms="${1}" + local arches="${2}" + + local platform + for platform in ${platforms}; do + local arch + for arch in ${arches}; do + echo "------ Publishing ${platform}-${arch} ------" + ./gradlew artifactoryPublish -Pplatform=${platform} -Parch=${arch} + done + done +} + +has_flag() { + local arg=${1} + + local f + for f in ${flags}; do + local key=$(echo $f | awk -F '=' '{print $1}') + if [ ${key} = ${arg} ]; then + return 0 + fi + done + return 1 +} + +### START ### + +install-deps + +if [[ "${1}" == "PUBLISH" ]]; then + if is-mac; then + publish "macosx" "i386 x86_64" + elif [[ $(uname -s) == "Linux" ]]; then + publish "linux windows" "i386 x86_64" + fi +else + if [[ $(uname -o) != "Cygwin" ]]; then + run_cmake -DCMAKE_BUILD_TYPE=Debug + fi + + make_target=test + + if ! has_flag arch; then + run make ${flags} jdk-test + fi + + run make ${flags} ${make_target} + run make ${flags} mode=debug ${make_target} + run make ${flags} process=interpret ${make_target} + + if has_flag openjdk-src || ! has_flag openjdk; then + run make ${flags} mode=debug bootimage=true ${make_target} + run make ${flags} bootimage=true ${make_target} + run make ${flags} bootimage=true bootimage-test=true ${make_target} + fi + + if ! has_flag openjdk && ! has_flag android && ! has_flag arch; then + run make ${flags} openjdk=$JAVA_HOME ${make_target} + fi + + run make ${flags} tails=true continuations=true heapdump=true ${make_target} + run make ${flags} codegen-targets=all +fi diff --git a/sgx-jvm/avian/test/extra/ComposableContinuations.java b/sgx-jvm/avian/test/extra/ComposableContinuations.java new file mode 100644 index 0000000000..d33d39693b --- /dev/null +++ b/sgx-jvm/avian/test/extra/ComposableContinuations.java @@ -0,0 +1,93 @@ +package extra; + +import static avian.Continuations.shift; +import static avian.Cell.cons; +import static avian.Cell.equal; + +import avian.Cell; +import avian.Function; +import avian.Continuations; + +import java.util.concurrent.Callable; + +public class ComposableContinuations { + private static void expect(boolean v) { + if (! v) throw new RuntimeException(); + } + + public static void main(String[] args) throws Exception { + expect(2 * Continuations.reset(new Callable() { + public Integer call() throws Exception { + return 1 + shift + (new Function,Integer>() { + public Integer call(Function continuation) + throws Exception + { + return continuation.call(5); + } + }); + } + }) == 12); + + expect(1 + Continuations.reset(new Callable() { + public Integer call() throws Exception { + return 2 * shift + (new Function,Integer>() { + public Integer call(Function continuation) + throws Exception + { + return continuation.call(continuation.call(4)); + } + }); + } + }) == 17); + + expect + (equal + (Continuations.,Cell>reset + (new Callable>() { + public Cell call() throws Exception { + shift(new Function,Cell>, + Cell>() + { + public Cell call + (Function,Cell> continuation) + throws Exception + { + return cons(1, continuation.call(null)); + } + }); + + shift(new Function,Cell>, + Cell>() + { + public Cell call + (Function,Cell> continuation) + throws Exception + { + return cons(2, continuation.call(null)); + } + }); + + return null; + } + }), cons(1, cons(2, null)))); + + expect + (equal + (Continuations.reset + (new Callable() { + public String call() throws Exception { + return new String + (shift(new Function,Integer>() { + public Integer call(Function continuation) + throws Exception + { + return Integer.parseInt + (continuation.call(new byte[] { 0x34, 0x32 })); + } + }), "UTF-8"); + } + }), 42)); + } +} diff --git a/sgx-jvm/avian/test/extra/Continuations.java b/sgx-jvm/avian/test/extra/Continuations.java new file mode 100644 index 0000000000..1186c43a4a --- /dev/null +++ b/sgx-jvm/avian/test/extra/Continuations.java @@ -0,0 +1,58 @@ +package extra; + +import static avian.Continuations.callWithCurrentContinuation; + +import avian.Function; +import avian.Callback; + +public class Continuations { + private static void expect(boolean v) { + if (! v) throw new RuntimeException(); + } + + public static void main(String[] args) throws Exception { + expect + (callWithCurrentContinuation + (new Function,Integer>() { + public Integer call(Callback continuation) { + continuation.handleResult(42); + throw new AssertionError(); + } + }) == 42); + + expect + (callWithCurrentContinuation + (new Function,Integer>() { + public Integer call(Callback continuation) { + return 43; + } + }) == 43); + + try { + callWithCurrentContinuation(new Function,Integer>() { + public Integer call(Callback continuation) { + continuation.handleException(new MyException()); + throw new AssertionError(); + } + }); + throw new AssertionError(); + } catch (MyException e) { + e.printStackTrace(); + } + + try { + callWithCurrentContinuation(new Function,Integer>() { + public Integer call(Callback continuation) + throws MyException + { + throw new MyException(); + } + }); + throw new AssertionError(); + } catch (MyException e) { + e.printStackTrace(); + } + } + + private static class MyException extends Exception { } +} diff --git a/sgx-jvm/avian/test/extra/Coroutines.java b/sgx-jvm/avian/test/extra/Coroutines.java new file mode 100644 index 0000000000..3afd2dce73 --- /dev/null +++ b/sgx-jvm/avian/test/extra/Coroutines.java @@ -0,0 +1,93 @@ +package extra; + +import static avian.Continuations.callWithCurrentContinuation; + +import avian.Function; +import avian.Callback; + +public class Coroutines { + private static void expect(boolean v) { + if (! v) throw new RuntimeException(); + } + + private static void produce(Consumer consumer) throws Exception { + System.out.println("produce \"a\""); + consumer.consume('a'); + + System.out.println("produce \"b\""); + consumer.consume('b'); + + System.out.println("produce \"c\""); + consumer.consume('c'); + } + + private static void consume(Producer producer) throws Exception { + char v = producer.produce(); + System.out.println("consume \"" + v + "\""); + expect(v == 'a'); + + v = producer.produce(); + System.out.println("consume \"" + v + "\""); + expect(v == 'b'); + + v = producer.produce(); + System.out.println("consume \"" + v + "\""); + expect(v == 'c'); + } + + public static void main(String[] args) throws Exception { + final CoroutineState state = new CoroutineState(); + + final Consumer consumer = new Consumer() { + public void consume(final Character c) throws Exception { + callWithCurrentContinuation(new Function,Object>() { + public Object call(Callback continuation) { + state.produceNext = continuation; + + state.consumeNext.handleResult(c); + + throw new AssertionError(); + } + }); + } + }; + + final Producer producer = new Producer() { + final Function,Character> receiver + = new Function,Character>() { + public Character call(Callback continuation) + throws Exception + { + state.consumeNext = continuation; + + if (state.produceNext == null) { + Coroutines.produce(consumer); + } else { + state.produceNext.handleResult(null); + } + + throw new AssertionError(); + } + }; + + public Character produce() throws Exception { + return callWithCurrentContinuation(receiver); + } + }; + + consume(producer); + } + + private static class CoroutineState { + public Callback produceNext; + public Callback consumeNext; + } + + private interface Producer { + public T produce() throws Exception; + } + + private interface Consumer { + public void consume(T value) throws Exception; + } +} diff --git a/sgx-jvm/avian/test/extra/DumpStats.java b/sgx-jvm/avian/test/extra/DumpStats.java new file mode 100644 index 0000000000..73b9170bed --- /dev/null +++ b/sgx-jvm/avian/test/extra/DumpStats.java @@ -0,0 +1,159 @@ +package extra; + +import java.io.PrintStream; +import java.io.InputStream; +import java.io.FileInputStream; +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.EOFException; +import java.util.Map; +import java.util.HashMap; +import java.util.Comparator; +import java.util.Arrays; + +/** + * This is a simple utility to generate and print statistics from a + * heap dump generated by Avian's heapdump.cpp. The output is a list + * of classes (identified by number in the case of anonymous, + * VM-internal classes), each followed by (1) the total memory + * footprint of all instances of the class in machine words, and (2) + * the number of instances. The output is ordered by instance memory + * footprint. + */ +public class DumpStats { + private static final int Root = 0; + private static final int Size = 1; + private static final int ClassName = 2; + private static final int Push = 3; + private static final int Pop = 4; + + private static int readInt(InputStream in) throws IOException { + int b1 = in.read(); + int b2 = in.read(); + int b3 = in.read(); + int b4 = in.read(); + if (b4 == -1) throw new EOFException(); + return (int) ((b1 << 24) | (b2 << 16) | (b3 << 8) | (b4)); + } + + private static String readString(InputStream in) throws IOException { + int count = readInt(in); + byte[] b = new byte[count]; + int offset = 0; + int c; + while ((c = in.read(b, offset, b.length - offset)) != -1 + && offset < b.length) + { + offset += c; + } + if (offset != b.length) throw new EOFException(); + return new String(b); + } + + private static Record record(Map map, int key) { + Record r = map.get(key); + if (r == null) { + map.put(key, r = new Record(key)); + } + return r; + } + + private static Map read(InputStream in) + throws IOException + { + boolean done = false; + boolean popped = false; + int size = 0; + int last = 0; + Map map = new HashMap(); + + while (! done) { + int flag = in.read(); + switch (flag) { + case Root: { + last = readInt(in); + popped = false; + } break; + + case ClassName: { + record(map, last).name = readString(in); + } break; + + case Push: { + last = readInt(in); + if (! popped) { + Record r = record(map, last); + r.footprint += size; + ++ r.count; + } + popped = false; + } break; + + case Pop: { + popped = true; + } break; + + case Size: { + size = readInt(in); + } break; + + case -1: + done = true; + break; + + default: + throw new RuntimeException("bad flag: " + flag); + } + } + + return map; + } + + private static void usageAndExit() { + System.err.println("usage: java DumpStats "); + } + + public static void main(String[] args) throws Exception { + if (args.length != 2) { + usageAndExit(); + } + + Map map = read + (new BufferedInputStream(new FileInputStream(args[0]))); + + Record[] array = map.values().toArray(new Record[map.size()]); + Arrays.sort(array, new Comparator() { + public int compare(Record a, Record b) { + return b.footprint - a.footprint; + } + }); + + int wordSize = Integer.parseInt(args[1]); + + int footprint = 0; + int count = 0; + for (Record r: array) { + if (r.name == null) { + r.name = String.valueOf(r.key); + } + System.out.println + (r.name + ": " + (r.footprint * wordSize) + " " + r.count); + footprint += r.footprint; + count += r.count; + } + + System.out.println(); + System.out.println("total: " + (footprint * wordSize) + " " + count); + } + + private static class Record { + public final int key; + public String name; + public int footprint; + public int count; + + public Record(int key) { + this.key = key; + } + } +} diff --git a/sgx-jvm/avian/test/extra/DynamicWind.java b/sgx-jvm/avian/test/extra/DynamicWind.java new file mode 100644 index 0000000000..bbc305842c --- /dev/null +++ b/sgx-jvm/avian/test/extra/DynamicWind.java @@ -0,0 +1,338 @@ +package extra; + +import static avian.Continuations.callWithCurrentContinuation; +import static avian.Continuations.dynamicWind; + +import avian.Function; +import avian.Callback; + +import java.util.concurrent.Callable; + +public class DynamicWind { + private int before; + private int task; + private int after; + private int continuationCount; + private Callback continuationReference; + + private static void expect(boolean v) { + if (! v) throw new RuntimeException(); + } + + private void unwindTest(final Callable unwind) throws Exception { + System.out.println("unwindTest enter"); + + try { + expect(dynamicWind(new Runnable() { + public void run() { + System.out.println("unwindTest before"); + + expect(before == 0); + expect(task == 0); + expect(after == 0); + + before = 1; + } + }, new Callable() { + public Integer call() throws Exception { + System.out.println("unwindTest thunk"); + + expect(before == 1); + expect(task == 0); + expect(after == 0); + + task = 1; + + return unwind.call(); + } + }, + new Runnable() { + public void run() { + System.out.println("unwindTest after"); + + expect(before == 1); + expect(task == 1); + expect(after == 0); + + after = 1; + } + }) == 42); + } catch (MyException e) { + e.printStackTrace(); + } + + System.out.println("unwindTest expect"); + + expect(before == 1); + expect(task == 1); + expect(after == 1); + + System.out.println("unwindTest exit"); + } + + private void normalUnwind() throws Exception { + unwindTest(new Callable() { + public Integer call() { + return 42; + } + }); + } + + private void exceptionUnwind() throws Exception { + unwindTest(new Callable() { + public Integer call() throws Exception { + throw new MyException(); + } + }); + } + + private void continuationUnwindTest + (final Function,Integer> receiver) + throws Exception + { + System.out.println("continuationUnwindTest enter"); + + try { + expect + (callWithCurrentContinuation + (new Function,Integer>() { + public Integer call(final Callback continuation) + throws Exception + { + unwindTest(new Callable() { + public Integer call() throws Exception { + return receiver.call(continuation); + } + }); + throw new AssertionError(); + } + }) == 42); + } catch (MyException e) { + e.printStackTrace(); + } + + System.out.println("continuationUnwindTest expect"); + + expect(before == 1); + expect(task == 1); + expect(after == 1); + + System.out.println("continuationUnwindTest exit"); + } + + private void continuationResultUnwind() throws Exception { + continuationUnwindTest(new Function,Integer>() { + public Integer call(final Callback continuation) { + continuation.handleResult(42); + throw new AssertionError(); + } + }); + } + + private void continuationExceptionUnwind() throws Exception { + continuationUnwindTest(new Function,Integer>() { + public Integer call(final Callback continuation) { + continuation.handleException(new MyException()); + throw new AssertionError(); + } + }); + } + + private void rewindTest(final Callable unwind, Runnable rewind) + throws Exception + { + System.out.println("rewindTest enter"); + + int value; + try { + value = dynamicWind(new Runnable() { + public void run() { + System.out.println("rewindTest before"); + + expect(before == continuationCount); + expect(task == continuationCount); + expect(after == continuationCount); + + ++ before; + } + }, new Callable() { + public Integer call() throws Exception { + System.out.println("rewindTest thunk"); + + expect(before == 1); + expect(task == 0); + expect(after == 0); + + task = 1; + + return callWithCurrentContinuation + (new Function,Integer>() { + public Integer call(final Callback continuation) + throws Exception + { + continuationReference = continuation; + return unwind.call(); + } + }); + } + }, new Runnable() { + public void run() { + System.out.println("rewindTest after"); + + expect(before == continuationCount + 1); + expect(task == 1); + expect(after == continuationCount); + + ++ after; + } + }); + } catch (MyException e) { + value = e.value; + } + + System.out.println("rewindTest expect"); + + expect(value == continuationCount); + + if (value == 0) { + System.out.println("rewindTest expect 0"); + + expect(before == 1); + expect(task == 1); + expect(after == 1); + + continuationCount = 1; + rewind.run(); + throw new AssertionError(); + } else { + System.out.println("rewindTest expect 1"); + + expect(value == 1); + expect(before == 2); + expect(task == 1); + expect(after == 2); + } + + System.out.println("rewindTest exit"); + } + + private void continuationResultRewind() throws Exception { + rewindTest(new Callable() { + public Integer call() { + return 0; + } + }, new Runnable() { + public void run() { + continuationReference.handleResult(1); + } + }); + } + + private void continuationExceptionRewind() throws Exception { + rewindTest(new Callable() { + public Integer call() throws Exception { + throw new MyException(0); + } + }, new Runnable() { + public void run() { + continuationReference.handleException(new MyException(1)); + } + }); + } + + private void continuationResultUnwindAndRewind() throws Exception { + rewindTest(new Callable() { + public Integer call() { + return 0; + } + }, new Runnable() { + public void run() { + try { + new DynamicWind().unwindTest(new Callable() { + public Integer call() { + continuationReference.handleResult(1); + throw new AssertionError(); + } + }); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + }); + } + + private void continuationExceptionUnwindAndRewind() throws Exception { + rewindTest(new Callable() { + public Integer call() throws Exception { + throw new MyException(0); + } + }, new Runnable() { + public void run() { + try { + new DynamicWind().unwindTest(new Callable() { + public Integer call() { + continuationReference.handleException(new MyException(1)); + throw new AssertionError(); + } + }); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + }); + } + + private void continuationResultUnwindAndRewindWithShared() throws Exception { + unwindTest(new Callable() { + public Integer call() throws Exception { + new DynamicWind().continuationResultUnwindAndRewind(); + return 42; + } + }); + } + + private void continuationExceptionUnwindAndRewindWithShared() + throws Exception + { + unwindTest(new Callable() { + public Integer call() throws Exception { + new DynamicWind().continuationExceptionUnwindAndRewind(); + return 42; + } + }); + } + + public static void main(String[] args) throws Exception { + new DynamicWind().normalUnwind(); + + new DynamicWind().exceptionUnwind(); + + new DynamicWind().continuationResultUnwind(); + + new DynamicWind().continuationExceptionUnwind(); + + new DynamicWind().continuationResultRewind(); + + new DynamicWind().continuationExceptionRewind(); + + new DynamicWind().continuationResultUnwindAndRewind(); + + new DynamicWind().continuationExceptionUnwindAndRewind(); + + new DynamicWind().continuationResultUnwindAndRewindWithShared(); + + new DynamicWind().continuationExceptionUnwindAndRewindWithShared(); + } + + private static class MyException extends Exception { + public final int value; + + public MyException() { + this(0); + } + + public MyException(int value) { + this.value = value; + } + } +} diff --git a/sgx-jvm/avian/test/extra/Memory.java b/sgx-jvm/avian/test/extra/Memory.java new file mode 100644 index 0000000000..b2e8cfbfea --- /dev/null +++ b/sgx-jvm/avian/test/extra/Memory.java @@ -0,0 +1,172 @@ +package extra; + +import java.util.Collection; +import java.util.Comparator; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.TreeSet; + +public class Memory { + private static final int ITERATION_COUNT=1; + + private static class Item { + private static int instanceCount=0; + private final int index; + private final int val; + public Item(int i) { val = i; index = instanceCount++; } + public int value() { return val; } + public int index() { return index; } + } + + private static void traceFunc(String s) { + if (false) { + System.out.println(s); + } + } + + private static void expect(boolean v) { + if (! v) throw new RuntimeException(); + } + + private static int runningSum(Item[] items) { + int sum=0; + for (Item item : items) { + sum += item.value(); + } + return sum; + } + + private static int runningSum(Collection items) { + int sum=0; + for (Item item : items) { + sum += item.value(); + } + return sum; + } + + private static final void testArray() { + traceFunc("testArray()"); + Item[] items = new Item[1750]; + + for (int iter=0; iter < ITERATION_COUNT; iter++) { + for (int i=0; i < 1000; i++) { + items[i] = new Item(1); + } + for (int i=0; i < 500; i++) { + items[i+1000] = new Item(4); + } + for (int i=0; i < 250; i++) { + items[i+1500] = new Item(9); + } + expect(runningSum(items) == (1000*1 + 500*4 + 250*9)); + Item[] zeroItems = new Item[300]; + for (int i=0; i < 300; i++) { + zeroItems[i] = new Item(0); + } + System.arraycopy(zeroItems, 0, items, 900, zeroItems.length); + for (int i=0; i < 10000; i++) { + items[0] = new Item(1); + } + expect(runningSum(items) == (900*1 + 300*4 + 250*9)); + for (int i=0; i < 300; i++) { + zeroItems[i] = new Item((i+900) < 1000 ? 1 : 4); + } + for (int i=0; i < 10000; i++) { + items[0] = new Item(1); + } + expect(runningSum(items) == (900*1 + 300*4 + 250*9)); + System.arraycopy(zeroItems, 0, items, 900, zeroItems.length); + expect(runningSum(items) == (1000*1 + 500*4 + 250*9)); + for (int i=0; i < 1750; i++) { + items[i] = null; + } + } + } + + private static final void testHashMap() { + traceFunc("testHashMap()"); + HashMap items = new HashMap(); + for (int iter=0; iter < ITERATION_COUNT; iter++) { + for (int i=0; i < 1000; i++) { + items.put(i, new Item(1)); + } + for (int i=0; i < 500; i++) { + items.put(i+1000, new Item(4)); + } + for (int i=0; i < 250; i++) { + items.put(i+1500, new Item(9)); + } + expect(runningSum(items.values()) == (1000*1 + 500*4 + 250*9)); + for (int i = 900; i < 1200; i++) { + items.remove(i); + } + expect(runningSum(items.values()) == (900*1 + 300*4 + 250*9)); + for (int i = 900; i < 1200; i++) { + items.put(i, new Item(i < 1000 ? 1 : 4)); + } + expect(runningSum(items.values()) == (1000*1 + 500*4 + 250*9)); + items.clear(); + } + } + + private static final void testLinkedList() { + traceFunc("testLinkedList()"); + LinkedList items = new LinkedList(); + for (int iter=0; iter < ITERATION_COUNT; iter++) { + for (int i=0; i < 1000; i++) { + items.add(new Item(1)); + } + for (int i=0; i < 500; i++) { + items.add(new Item(4)); + } + for (int i=0; i < 250; i++) { + items.add(new Item(9)); + } + expect(runningSum(items) == (1000*1 + 500*4 + 250*9)); + for (int i = 1199; i >= 900; i--) { + items.remove(i); + } + expect(runningSum(items) == (900*1 + 300*4 + 250*9)); + for (int i = 900; i < 1200; i++) { + items.add(new Item(i < 1000 ? 1 : 4)); + } + expect(runningSum(items) == (1000*1 + 500*4 + 250*9)); + items.clear(); + } + } + + private static final void testTreeSet() { + traceFunc("testTreeSet()"); + TreeSet items = new TreeSet(new Comparator() { + public int compare(Item i1, Item i2) { + int r = i1.value() - i2.value(); + if (r == 0) { + return i1.index() - i2.index(); + } + return r; + } + }); + for (int iter=0; iter < ITERATION_COUNT; iter++) { + for (int i=0; i < 1000; i++) { + items.add(new Item(1)); + } + for (int i=0; i < 500; i++) { + items.add(new Item(4)); + } + for (int i=0; i < 250; i++) { + items.add(new Item(9)); + } + expect(runningSum(items) == (1000*1 + 500*4 + 250*9)); + items.clear(); + } + } + + public static void main(String args[]) { + for (int i=0; i < 10; i++) { + testArray(); + testHashMap(); + testLinkedList(); + testTreeSet(); + } + } +} diff --git a/sgx-jvm/avian/test/extra/PrintDump.java b/sgx-jvm/avian/test/extra/PrintDump.java new file mode 100644 index 0000000000..8f43f419c9 --- /dev/null +++ b/sgx-jvm/avian/test/extra/PrintDump.java @@ -0,0 +1,101 @@ +package extra; + +import java.io.PrintStream; +import java.io.InputStream; +import java.io.FileInputStream; +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.EOFException; + +/** + * This is a simple utility to print the contents of a heap dump + * generated by Avian's heapdump.cpp in a human-readable format. + */ +public class PrintDump { + private static final int Root = 0; + private static final int Size = 1; + private static final int ClassName = 2; + private static final int Push = 3; + private static final int Pop = 4; + + private static void indent(PrintStream out, int level) { + for (; level > 0; --level) out.print(" "); + } + + private static int readInt(InputStream in) throws IOException { + int b1 = in.read(); + int b2 = in.read(); + int b3 = in.read(); + int b4 = in.read(); + if (b4 == -1) throw new EOFException(); + return (int) ((b1 << 24) | (b2 << 16) | (b3 << 8) | (b4)); + } + + private static String readString(InputStream in) throws IOException { + int count = readInt(in); + byte[] b = new byte[count]; + int offset = 0; + int c; + while ((c = in.read(b, offset, b.length - offset)) != -1 + && offset < b.length) + { + offset += c; + } + if (offset != b.length) throw new EOFException(); + return new String(b); + } + + private static void pipe(InputStream in, PrintStream out) + throws IOException + { + boolean done = false; + boolean popped = false; + int level = 0; + while (! done) { + int flag = in.read(); + switch (flag) { + case Root: { + out.print("\nroot " + readInt(in)); + popped = false; + } break; + + case ClassName: { + out.print(" class " + readString(in)); + } break; + + case Push: { + ++ level; + out.println(); + indent(out, level); + if (! popped) { + out.print("first "); + } + out.print("child " + readInt(in)); + popped = false; + } break; + + case Pop: { + -- level; + popped = true; + } break; + + case Size: { + out.print(" size " + readInt(in)); + } break; + + case -1: + out.println(); + out.flush(); + done = true; + break; + + default: + throw new RuntimeException("bad flag: " + flag); + } + } + } + + public static void main(String[] args) throws Exception { + pipe(new BufferedInputStream(new FileInputStream(args[0])), System.out); + } +} diff --git a/sgx-jvm/avian/test/extra/QueryDump.java b/sgx-jvm/avian/test/extra/QueryDump.java new file mode 100644 index 0000000000..156cd64d36 --- /dev/null +++ b/sgx-jvm/avian/test/extra/QueryDump.java @@ -0,0 +1,358 @@ +package extra; + +import java.io.PrintStream; +import java.io.InputStream; +import java.io.FileInputStream; +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.EOFException; +import java.util.Set; +import java.util.HashSet; +import java.util.Map; +import java.util.HashMap; +import java.util.Comparator; +import java.util.Arrays; +import java.util.List; +import java.util.ArrayList; +import java.util.Iterator; + +public class QueryDump { + private static final int Root = 0; + private static final int Size = 1; + private static final int ClassName = 2; + private static final int Push = 3; + private static final int Pop = 4; + + private static int readInt(InputStream in) throws IOException { + int b1 = in.read(); + int b2 = in.read(); + int b3 = in.read(); + int b4 = in.read(); + if (b4 == -1) throw new EOFException(); + return (int) ((b1 << 24) | (b2 << 16) | (b3 << 8) | (b4)); + } + + private static String readString(InputStream in) throws IOException { + int count = readInt(in); + byte[] b = new byte[count]; + int offset = 0; + int c; + while ((c = in.read(b, offset, b.length - offset)) != -1 + && offset < b.length) + { + offset += c; + } + if (offset != b.length) throw new EOFException(); + return new String(b); + } + + private static Record record(Map map, int key) { + Record r = map.get(key); + if (r == null) { + map.put(key, r = new Record(key)); + } + return r; + } + + private static void push(List stack, T value) { + stack.add(value); + } + + private static T pop(List stack) { + return stack.remove(stack.size() - 1); + } + + private static T peek(List stack, int offset) { + return stack.get(stack.size() - 1 - offset); + } + + private static T peek(List stack) { + return peek(stack, 0); + } + + private static Set nodes(Record record) { + if (record.nodes == null) { + record.nodes = new HashSet(2); + } + return record.nodes; + } + + private static void query(Map nodes, Record[] query, + List stack, int index) + { + Node node = nodes.get(peek(stack, index).key); + if (node != null) { + int base = node.index(); + for (int i = base + 1; i < query.length; ++i) { + int peek = index + i - base; + if (peek < stack.size()) { + Instance instance = peek(stack, peek); + if (query[i] == instance.record) { + TreeNode next = (TreeNode) nodes.get(instance); + if (next == null) { + nodes.put(instance.key, next = new TreeNode(instance, i)); + } + next.children.add(node); + node = next; + } else { + return; + } + } else { + return; + } + } + + if (index + query.length - base < stack.size()) { + nodes(peek(stack, index + query.length - base).record).add(node); + } + } + } + + private static void query(Map nodes, Record[] query, + List stack) + { + if (stack.size() > 1) { + Instance instance = peek(stack, 1); + if (instance != null && instance.record == query[0]) { + Node node = nodes.get(instance.key); + if (node == null) { + nodes.put(instance.key, new LeafNode(instance)); + query(nodes, query, stack, 1); + } + return; + } + } + + query(nodes, query, stack, 0); + } + + private static Map read(InputStream in, + String[] queryClasses) + throws IOException + { + boolean done = false; + boolean popped = false; + Map records = new HashMap(); + Map nodes = new HashMap(); + List stack = new ArrayList(); + Record[] query = new Record[queryClasses.length]; + + Record roots = new Record(-1, ""); + records.put(roots.key, roots); + + while (! done) { + int flag = in.read(); + switch (flag) { + case Root: { + stack.clear(); + push(stack, new Instance(readInt(in))); + + query(nodes, query, stack); + + popped = false; + // System.out.println("root " + last); + } break; + + case ClassName: { + String name = readString(in); + Record r = record(records, peek(stack).key); + r.name = name; + + for (int i = 0; i < queryClasses.length; ++i) { + if (queryClasses[i].equals(name)) { + query[i] = r; + } + } + + query(nodes, query, stack); + } break; + + case Push: { + int key = readInt(in); + + if (! popped) { + peek(stack).record = record(records, key); + } + + push(stack, new Instance(key)); + + query(nodes, query, stack); + + popped = false; + } break; + + case Pop: { + pop(stack); + + popped = true; + } break; + + case Size: { + peek(stack).size = readInt(in); + } break; + + case -1: + done = true; + break; + + default: + throw new RuntimeException("bad flag: " + flag); + } + } + + return records; + } + + private static String[] copy(String[] array, int offset, int length) { + String[] copy = new String[length]; + if (length > 0) { + System.arraycopy(array, offset, copy, 0, length); + } + + return copy; + } + + private static void visitLeaves(Set nodes, LeafVisitor visitor) { + for (Node n: nodes) { + n.visitLeaves(visitor); + } + } + + private static void usageAndExit() { + System.err.println("usage: java QueryDump " + + " ..."); + } + + public static void main(String[] args) throws Exception { + if (args.length < 3) { + usageAndExit(); + } + + Map map = read + (new BufferedInputStream(new FileInputStream(args[0])), + copy(args, 2, args.length - 2)); + + for (Iterator it = map.values().iterator(); it.hasNext();) { + final Record r = it.next(); + if (r.nodes == null) { + it.remove(); + } else { + visitLeaves(r.nodes, new LeafVisitor() { + private Set set = new HashSet(); + + public void visit(LeafNode node) { + if (! set.contains(node.instance)) { + r.footprint += node.instance.size; + ++ r.count; + } + set.add(node.instance); + } + }); + } + } + + Record[] array = map.values().toArray(new Record[map.size()]); + Arrays.sort(array, new Comparator() { + public int compare(Record a, Record b) { + return b.footprint - a.footprint; + } + }); + + int wordSize = Integer.parseInt(args[1]); + + int footprint = 0; + int count = 0; + for (Record r: array) { + if (r.name == null) { + r.name = String.valueOf(r.key); + } + System.out.println + (r.name + ": " + (r.footprint * wordSize) + " " + r.count); + footprint += r.footprint; + count += r.count; + } + + System.out.println(); + System.out.println("total: " + (footprint * wordSize) + " " + count); + } + + private static class Record { + public final int key; + public String name; + public int footprint; + public int count; + public Set nodes; + + public Record(int key) { + this(key, null); + } + + public Record(int key, String name) { + this.key = key; + this.name = name; + } + + public String toString() { + return name; + } + } + + private static class Instance { + public final int key; + public int size; + public Record record; + + public Instance(int key) { + this.key = key; + } + + public String toString() { + return "[" + key + " " + record + "]"; + } + } + + public interface Node { + public void visitLeaves(LeafVisitor visitor); + public int index(); + } + + public static class LeafNode implements Node { + public final Instance instance; + + public LeafNode(Instance instance) { + this.instance = instance; + } + + public void visitLeaves(LeafVisitor visitor) { + visitor.visit(this); + } + + public int index() { + return 0; + } + } + + public static class TreeNode implements Node { + public final Instance instance; + public final int index; + + public final Set children = new HashSet(2); + + public TreeNode(Instance instance, int index) { + this.instance = instance; + this.index = index; + } + + public void visitLeaves(LeafVisitor visitor) { + QueryDump.visitLeaves(children, visitor); + } + + public int index() { + return index; + } + } + + public interface LeafVisitor { + public void visit(LeafNode node); + } +} diff --git a/sgx-jvm/avian/test/extra/RuntimeExec.java b/sgx-jvm/avian/test/extra/RuntimeExec.java new file mode 100644 index 0000000000..23adbb9105 --- /dev/null +++ b/sgx-jvm/avian/test/extra/RuntimeExec.java @@ -0,0 +1,59 @@ +package extra; + +import java.lang.Runtime; +import java.lang.Process; + +public class RuntimeExec { + public static void main(String[] args) throws java.io.IOException, java.lang.InterruptedException { + Runtime runtime = Runtime.getRuntime(); + String ieStr = null; + String charmapStr = null; + String[] firefox = new String[2]; + + if(System.getProperty("os.name").equals("windows")){ + System.out.println("Executing internet explorer"); + ieStr = "\"c:\\program files\\internet explorer\\iexplore.exe\" http://www.google.com"; + } else { + System.out.println("Executing Firefox using string"); + ieStr = "firefox http://www.google.com"; + } + Process ie = runtime.exec(ieStr); + + if(System.getProperty("os.name").equals("windows")){ + System.out.println("Executing firefox"); + firefox[0] = "c:\\program files\\mozilla firefox\\firefox.exe"; + firefox[1] = "http://www.google.com"; + } else { + System.out.println("Executing Firefox using array"); + firefox[0] = "firefox"; + firefox[1] = "http://www.google.com"; + } + Process ff = runtime.exec(firefox); + + boolean ffSuccess = false; + boolean ieSuccess = false; + while(!(ieSuccess && ffSuccess)){ + if(!ffSuccess){ + try{ + System.out.println("Exit value from string exec: " + ff.exitValue()); + ffSuccess = true; + } catch(IllegalThreadStateException e) {} + } + if(!ieSuccess){ + try{ + System.out.println("Exit value from array exec: " + ie.exitValue()); + ieSuccess = true; + } catch(IllegalThreadStateException e) {} + } + } + if(System.getProperty("os.name").equals("windows")){ + System.out.println("Executing and waiting for charmap"); + charmapStr = "c:\\windows\\system32\\charmap.exe"; + } else { + System.out.println("Executing and waiting for firefox"); + charmapStr = "firefox http://www.google.com"; + } + Process cm = runtime.exec(charmapStr); + System.out.println("Exit value: " + cm.waitFor()); + } +} diff --git a/sgx-jvm/avian/test/extra/SendFile.java b/sgx-jvm/avian/test/extra/SendFile.java new file mode 100644 index 0000000000..da77a33a21 --- /dev/null +++ b/sgx-jvm/avian/test/extra/SendFile.java @@ -0,0 +1,73 @@ +package extra; + +import java.net.InetSocketAddress; +import java.nio.ByteBuffer; +import java.io.IOException; +import java.nio.channels.Selector; +import java.nio.channels.SelectionKey; +import java.nio.channels.SocketChannel; +import java.io.OutputStream; +import java.io.FileInputStream; + +public class SendFile { + private static class SocketOutputStream extends OutputStream { + private final SocketChannel channel; + private final Selector selector; + public SocketOutputStream(String host, int port) throws Exception { + channel = SocketChannel.open(); + channel.connect(new InetSocketAddress(host, port)); + channel.configureBlocking(false); + selector = Selector.open(); + channel.register(selector, SelectionKey.OP_WRITE, null); + } + + public void close() throws IOException { + channel.close(); + } + + public void write(int c) { + throw new RuntimeException("Do not use!"); + } + public void write(byte[] buffer, int offset, int length) + throws IOException { + ByteBuffer buf = ByteBuffer.wrap(buffer); + buf.position(offset); + buf.limit(offset+length); + while (buf.hasRemaining()) { + selector.select(10000); + for (SelectionKey key : selector.selectedKeys()) { + if (key.isWritable() && (key.channel() == channel)) { + channel.write(buf); + } + } + } + } + } + + public static void sendFile(String file, String host, int port) + throws Exception { + System.out.println("Sending " + file); + OutputStream os = new SocketOutputStream(host, port); + FileInputStream is = new FileInputStream(file); + byte[] buf = new byte[16384]; + int count=-1; + while ((count = is.read(buf)) >= 0) { + os.write(buf, 0, count); + } + is.close(); + os.close(); + } + + public static void main(String args[]) { + if (args.length != 2) { + System.out.println("Usage: SendFile file host"); + } else { + try { + sendFile(args[0], args[1], 8988); + } catch (Exception ex) { + ex.printStackTrace(); + } + } + } +} + diff --git a/sgx-jvm/avian/test/extra/SendServer.java b/sgx-jvm/avian/test/extra/SendServer.java new file mode 100644 index 0000000000..5f60c962c1 --- /dev/null +++ b/sgx-jvm/avian/test/extra/SendServer.java @@ -0,0 +1,92 @@ +package extra; + +import java.net.InetSocketAddress; +import java.nio.ByteBuffer; +import java.nio.channels.SelectionKey; +import java.nio.channels.Selector; +import java.nio.channels.ServerSocketChannel; +import java.nio.channels.SocketChannel; + +public class SendServer { + private static char cIndex = 'A'; + private static ByteBuffer inBuf = ByteBuffer.allocate(8192); + + private static void dumpByteBuffer(char note, ByteBuffer buf) { + System.out.println(note + ": Buffer position: " + buf.position() + " limit: " + + buf.limit() + " capacity: " + buf.capacity() + " remaining: " + + buf.remaining()); + } + + private static class Connection { + private final char myIndex; + private final java.io.FileOutputStream fos; + + public Connection() throws Exception { + myIndex = cIndex++; + fos = new java.io.FileOutputStream("dump." + myIndex); + } + + public void handleRead(SocketChannel channel) throws Exception { + int count = -1; + while ((count = channel.read(inBuf)) > 0) { + System.out.println(myIndex + ": read " + count); + } + inBuf.flip(); + fos.write(inBuf.array(), inBuf.arrayOffset()+inBuf.position(), inBuf.remaining()); + inBuf.position(inBuf.limit()); + if (count < 0) { + System.out.println(myIndex + ": Closing channel"); + fos.close(); + channel.close(); + } +// dumpByteBuffer(myIndex, inBuf); + inBuf.compact(); + } + } + + public void runMainLoop() throws Exception { + boolean keepRunning = true; + int port = 8988; + ServerSocketChannel serverChannel = ServerSocketChannel.open(); + try { + serverChannel.configureBlocking(false); + serverChannel.socket().bind(new InetSocketAddress("0.0.0.0", port)); + Selector selector = Selector.open(); + serverChannel.register(selector, SelectionKey.OP_ACCEPT, null); + while (keepRunning) { + System.out.println("Running main loop"); + selector.select(10000); + for (SelectionKey key : selector.selectedKeys()) { + if (key.isAcceptable()) { + System.out.println("Accepting new connection"); + SocketChannel c = ((ServerSocketChannel) key.channel()).accept(); + if (c != null) { + c.configureBlocking(false); + c.register(selector, SelectionKey.OP_READ, new Connection()); + } + } else { + SocketChannel c = (SocketChannel) key.channel(); + if (c.isOpen() && key.isReadable()) { + Connection connection = (Connection)key.attachment(); + connection.handleRead(c); + } + } + } + selector.selectedKeys().clear(); + } + } finally { + serverChannel.close(); + } + } + + public static void main(String args[]) { + try { + System.out.println("Starting server"); + if (args.length > 0) { + new SendServer().runMainLoop(); + } + } catch (Exception ex) { + ex.printStackTrace(); + } + } +} diff --git a/sgx-jvm/avian/test/extra/Sockets.java b/sgx-jvm/avian/test/extra/Sockets.java new file mode 100644 index 0000000000..75cd278982 --- /dev/null +++ b/sgx-jvm/avian/test/extra/Sockets.java @@ -0,0 +1,41 @@ +package extra; + +import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.OutputStreamWriter; +import java.net.Socket; +import java.net.UnknownHostException; + +public class Sockets { + + /** + * @param args + * @throws IOException + * @throws UnknownHostException + */ + public static void main(String[] args) throws UnknownHostException, + IOException { + System.out.print("Requesting... " + args[0] + "\n"); + Socket sock = new Socket(args[0], 80); + try { + BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(sock.getOutputStream())); + String request = "GET /?gws_rd=cr HTTP/1.1\r\n" + + "Host: " + args[0] + "\r\n" + "Accept: */*\r\n" + + "User-Agent: Java\r\n" + "Connection: close\r\n" + "\r\n"; + bw.write(request); + bw.flush(); + + BufferedReader br = new BufferedReader(new InputStreamReader(sock.getInputStream())); + String read = null; + while ((read = br.readLine()) != null) { + System.out.println(read); + } + bw.close(); + } finally { + sock.close(); + } + } + +} \ No newline at end of file diff --git a/sgx-jvm/avian/test/extra/Tails.java b/sgx-jvm/avian/test/extra/Tails.java new file mode 100644 index 0000000000..a99655531a --- /dev/null +++ b/sgx-jvm/avian/test/extra/Tails.java @@ -0,0 +1,49 @@ +package extra; + +public class Tails { + private static final int Limit = 1000000; + + private static void expect(boolean v) { + if (! v) throw new RuntimeException(); + } + + private static int staticMethod(Interface i, int n) { + if (n < Limit) { + return i.interfaceMethod(n + 1); + } else { + return leafMethod(n); + } + } + + private static int leafMethod(int n) { + expect(new Throwable().getStackTrace().length == 2); + + return n; + } + + public static void main(String[] args) { + expect(staticMethod(new Foo(), 0) == Limit); + } + + private interface Interface { + public int interfaceMethod(int n); + } + + private static class Foo implements Interface { + public int interfaceMethod(int n) { + if (n < Limit) { + return virtualMethod(n + 1, 1, 2, 3, 4, 5); + } else { + return leafMethod(n); + } + } + + public int virtualMethod(int n, int a, int b, int c, int d, int e) { + if (n < Limit) { + return staticMethod(this, n + 1); + } else { + return leafMethod(n); + } + } + } +} diff --git a/sgx-jvm/avian/test/jni.cpp b/sgx-jvm/avian/test/jni.cpp new file mode 100644 index 0000000000..18e418ab92 --- /dev/null +++ b/sgx-jvm/avian/test/jni.cpp @@ -0,0 +1,228 @@ +#include +#include "jni-util.h" + +extern "C" JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void*) +{ + JNIEnv* e; + if (vm->GetEnv(reinterpret_cast(&e), JNI_VERSION_1_6) != JNI_OK) { + return -1; + } + + jclass c = e->FindClass("JNI"); + if (c == 0) { + return -1; + } + + e->SetStaticBooleanField( + c, e->GetStaticFieldID(c, "onLoadCalled", "Z"), true); + + return JNI_VERSION_1_6; +} + +extern "C" JNIEXPORT jdouble JNICALL Java_JNI_addDoubles(JNIEnv*, + jclass, + jdouble a1, + jdouble a2, + jdouble a3, + jdouble a4, + jdouble a5, + jdouble a6, + jdouble a7, + jdouble a8, + jdouble a9, + jdouble a10, + jdouble a11, + jdouble a12, + jdouble a13, + jdouble a14, + jdouble a15, + jdouble a16, + jdouble a17, + jdouble a18, + jdouble a19, + jdouble a20) +{ + return a1 + a2 + a3 + a4 + a5 + a6 + a7 + a8 + a9 + a10 + a11 + a12 + a13 + + a14 + a15 + a16 + a17 + a18 + a19 + a20; +} + +extern "C" JNIEXPORT jfloat JNICALL Java_JNI_addFloats(JNIEnv*, + jclass, + jfloat a1, + jfloat a2, + jfloat a3, + jfloat a4, + jfloat a5, + jfloat a6, + jfloat a7, + jfloat a8, + jfloat a9, + jfloat a10, + jfloat a11, + jfloat a12, + jfloat a13, + jfloat a14, + jfloat a15, + jfloat a16, + jfloat a17, + jfloat a18, + jfloat a19, + jfloat a20) +{ + return a1 + a2 + a3 + a4 + a5 + a6 + a7 + a8 + a9 + a10 + a11 + a12 + a13 + + a14 + a15 + a16 + a17 + a18 + a19 + a20; +} + +extern "C" JNIEXPORT jdouble JNICALL Java_JNI_addMix(JNIEnv*, + jclass, + jfloat a1, + jdouble a2, + jfloat a3, + jdouble a4, + jfloat a5, + jfloat a6, + jfloat a7, + jfloat a8, + jfloat a9, + jfloat a10, + jfloat a11, + jfloat a12, + jfloat a13, + jfloat a14, + jfloat a15, + jdouble a16, + jfloat a17, + jfloat a18, + jfloat a19, + jfloat a20) +{ + return a1 + a2 + a3 + a4 + a5 + a6 + a7 + a8 + a9 + a10 + a11 + a12 + a13 + + a14 + a15 + a16 + a17 + a18 + a19 + a20; +} + +extern "C" JNIEXPORT jint JNICALL + Java_JNI_addStackBoundary2(JNIEnv*, jclass, jobject, jobject, jobject, + jint i1, jint i2) +{ + return i1 + i2; +} + +extern "C" JNIEXPORT jint JNICALL + Java_JNI_addStackBoundary3(JNIEnv*, jclass, jobject, jobject, jobject, + jint i1, jint i2, jint i3) +{ + return i1 + i2 + i3; +} + +extern "C" JNIEXPORT jint JNICALL + Java_JNI_addStackBoundary4(JNIEnv*, jclass, jobject, jobject, jobject, + jint i1, jint i2, jint i3, jint i4) +{ + return i1 + i2 + i3 + i4; +} + +extern "C" JNIEXPORT jint JNICALL + Java_JNI_addStackBoundary5(JNIEnv*, jclass, jobject, jobject, jobject, + jint i1, jint i2, jint i3, jint i4, jint i5) +{ + return i1 + i2 + i3 + i4 + i5; +} + +extern "C" JNIEXPORT jint JNICALL + Java_JNI_addStackBoundary6(JNIEnv*, jclass, jobject, jobject, jobject, + jint i1, jint i2, jint i3, jint i4, jint i5, jint i6) +{ + return i1 + i2 + i3 + i4 + i5 + i6; +} + +extern "C" JNIEXPORT jfloat JNICALL + Java_JNI_doEcho__F(JNIEnv* e, jclass c, jfloat f) +{ + jvalue value; + value.f = f; + jvalue array[] = {value}; + return e->CallStaticFloatMethodA( + c, e->GetStaticMethodID(c, "echo", "(F)F"), array); +} + +extern "C" JNIEXPORT jdouble JNICALL + Java_JNI_doEcho__D(JNIEnv* e, jclass c, jdouble f) +{ + jvalue value; + value.d = f; + jvalue array[] = {value}; + return e->CallStaticDoubleMethodA( + c, e->GetStaticMethodID(c, "echo", "(D)D"), array); +} + +extern "C" JNIEXPORT jlong JNICALL + Java_JNI_fromReflectedMethod(JNIEnv* e, jclass, jobject method) +{ + return reinterpret_cast(e->FromReflectedMethod(method)); +} + +extern "C" JNIEXPORT jobject JNICALL + Java_JNI_toReflectedMethod(JNIEnv* e, + jclass, + jclass c, + jlong id, + jboolean isStatic) +{ + return e->ToReflectedMethod(c, reinterpret_cast(id), isStatic); +} + +extern "C" JNIEXPORT jint JNICALL + Java_JNI_callStaticIntMethod(JNIEnv* e, jclass, jclass c, jlong id) +{ + return e->CallStaticIntMethod(c, reinterpret_cast(id)); +} + +extern "C" JNIEXPORT jobject JNICALL + Java_JNI_newObject(JNIEnv* e, jclass, jclass c, jlong id) +{ + return e->NewObject(c, reinterpret_cast(id)); +} + +extern "C" JNIEXPORT jlong JNICALL + Java_JNI_fromReflectedField(JNIEnv* e, jclass, jobject field) +{ + return reinterpret_cast(e->FromReflectedField(field)); +} + +extern "C" JNIEXPORT jobject JNICALL + Java_JNI_toReflectedField(JNIEnv* e, + jclass, + jclass c, + jlong id, + jboolean isStatic) +{ + return e->ToReflectedField(c, reinterpret_cast(id), isStatic); +} + +extern "C" JNIEXPORT jint JNICALL + Java_JNI_getStaticIntField(JNIEnv* e, jclass, jclass c, jlong id) +{ + return e->GetStaticIntField(c, reinterpret_cast(id)); +} + +extern "C" JNIEXPORT jobject JNICALL + Java_JNI_testLocalRef(JNIEnv* e, jclass, jobject o) +{ + return e->NewLocalRef(o); +} + +extern "C" JNIEXPORT jobject JNICALL + Java_Buffers_allocateNative(JNIEnv* e, jclass, jint capacity) +{ + void* p = allocate(e, capacity); + if (p == 0) + return 0; + + return e->NewDirectByteBuffer(p, capacity); +} + +extern "C" JNIEXPORT void JNICALL + Java_Buffers_freeNative(JNIEnv* e, jclass, jobject b) +{ + free(e->GetDirectBufferAddress(b)); +} diff --git a/sgx-jvm/avian/test/test.sh b/sgx-jvm/avian/test/test.sh new file mode 100644 index 0000000000..0bd3db7d68 --- /dev/null +++ b/sgx-jvm/avian/test/test.sh @@ -0,0 +1,60 @@ +#!/bin/sh + +vg="nice valgrind --leak-check=full --num-callers=32 \ +--freelist-vol=100000000 --error-exitcode=1" + +ld_path=${1}; shift +unit_tester=${1}; shift +vm=${1}; shift +mode=${1}; shift +flags=${1}; shift +tests=${@} + +log=log.txt + +if [ -n "${ld_path}" ]; then + export ${ld_path} +fi + +echo -n "" >${log} + +printf "%20s------- Unit tests -------\n" "" +${unit_tester} 2>>${log} +if [ "${?}" != "0" ]; then + trouble=1 + echo "unit tests failed!" +fi + +echo + +printf "%20s------- Java tests -------\n" "" +for test in ${tests}; do + printf "%32s: " "${test}" + + case ${mode} in + debug|debug-fast|fast|small ) + ${vm} ${flags} ${test} >>${log} 2>&1;; + + stress* ) + ${vg} ${vm} ${flags} ${test} \ + >>${log} 2>&1;; + + * ) + echo "unknown mode: ${mode}" >&2 + exit 1;; + esac + + if [ "${?}" = "0" ]; then + echo "success" + else + echo "fail" + trouble=1 + fi +done + +echo + +if [ -n "${trouble}" ]; then + printf "see ${log} for output\n" + exit -1 +fi diff --git a/sgx-jvm/avian/unittest/CMakeLists.txt b/sgx-jvm/avian/unittest/CMakeLists.txt new file mode 100644 index 0000000000..d810e3ffba --- /dev/null +++ b/sgx-jvm/avian/unittest/CMakeLists.txt @@ -0,0 +1,23 @@ + +include_directories (${CMAKE_CURRENT_SOURCE_DIR}) + +add_executable (avian_unittest + test-harness.cpp + + codegen/assembler-test.cpp + codegen/registers-test.cpp + + util/arg-parser-test.cpp +) + +target_link_libraries (avian_unittest + avian_codegen + avian_codegen_x86 + avian_system + avian_heap + avian_util + ${PLATFORM_LIBS} +) + +add_test(NAME avian_unittest COMMAND avian_unittest) +add_dependencies(check avian_unittest) diff --git a/sgx-jvm/avian/unittest/codegen/assembler-test.cpp b/sgx-jvm/avian/unittest/codegen/assembler-test.cpp new file mode 100644 index 0000000000..614135949a --- /dev/null +++ b/sgx-jvm/avian/unittest/codegen/assembler-test.cpp @@ -0,0 +1,84 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#include + +#include "avian/common.h" +#include +#include +#include "avian/target.h" + +#include +#include +#include +#include + +#include "test-harness.h" + +using namespace avian::codegen; +using namespace vm; + +class BasicEnv { + public: + System* s; + Heap* heap; + Architecture* arch; + + BasicEnv() + : s(makeSystem()), + heap(makeHeap(s, 32 * 1024)), + arch(makeArchitectureNative(s, true)) + { + arch->acquire(); + } + + ~BasicEnv() + { + arch->release(); + s->dispose(); + } +}; + +class Asm { + public: + Zone zone; + Assembler* a; + + Asm(BasicEnv& env) + : zone(env.heap, 8192), a(env.arch->makeAssembler(env.heap, &zone)) + { + } + + ~Asm() + { + a->dispose(); + } +}; + +TEST(BasicAssembler) +{ + BasicEnv env; + Asm a(env); +} + +TEST(ArchitecturePlan) +{ + BasicEnv env; + + for (int op = (int)lir::Call; op < (int)lir::AlignedJump; op++) { + bool thunk; + OperandMask mask; + env.arch->plan( + (lir::UnaryOperation)op, vm::TargetBytesPerWord, mask, &thunk); + assertFalse(thunk); + assertNotEqual(static_cast(0), mask.typeMask); + assertNotEqual(static_cast(0), (uint64_t)mask.lowRegisterMask); + } +} diff --git a/sgx-jvm/avian/unittest/codegen/registers-test.cpp b/sgx-jvm/avian/unittest/codegen/registers-test.cpp new file mode 100644 index 0000000000..4aa982c940 --- /dev/null +++ b/sgx-jvm/avian/unittest/codegen/registers-test.cpp @@ -0,0 +1,47 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#include + +#include + +#include "test-harness.h" + +using namespace avian::codegen; +using namespace vm; + +TEST(RegisterIterator) +{ + BoundedRegisterMask regs(0x55); + assertEqual(0, regs.start); + assertEqual(7, regs.limit); + + for(int i = 0; i < 64; i++) { + assertEqual(i, BoundedRegisterMask(static_cast(1) << i).start); + assertEqual(i + 1, BoundedRegisterMask(static_cast(1) << i).limit); + } + + auto it = regs.begin(); + auto end = regs.end(); + + assertTrue(it != end); + assertEqual(6, (*it).index()); + ++it; + assertTrue(it != end); + assertEqual(4, (*it).index()); + ++it; + assertTrue(it != end); + assertEqual(2, (*it).index()); + ++it; + assertTrue(it != end); + assertEqual(0, (*it).index()); + ++it; + assertFalse(it != end); +} diff --git a/sgx-jvm/avian/unittest/test-harness.cpp b/sgx-jvm/avian/unittest/test-harness.cpp new file mode 100644 index 0000000000..2a8d4c2986 --- /dev/null +++ b/sgx-jvm/avian/unittest/test-harness.cpp @@ -0,0 +1,53 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#include + +#include "test-harness.h" + +// since we aren't linking against libstdc++, we must implement this +// ourselves: +extern "C" void __cxa_pure_virtual(void) +{ + abort(); +} + +Test* Test::first = 0; +Test** Test::last = &first; + +Test::Test(const char* name) : next(0), failures(0), runs(0), name(name) +{ + *last = this; + last = &next; +} + +bool Test::runAll() +{ + int failures = 0; + for (Test* t = Test::first; t; t = t->next) { + printf("%32s: ", t->name); + t->run(); + failures += t->failures; + if (t->failures > 0) { + printf("failure\n"); + } else { + printf("success\n"); + } + } + return failures == 0; +} + +int main(int argc UNUSED, char** argv UNUSED) +{ + if (Test::runAll()) { + return 0; + } + return 1; +} diff --git a/sgx-jvm/avian/unittest/test-harness.h b/sgx-jvm/avian/unittest/test-harness.h new file mode 100644 index 0000000000..10b3f0259a --- /dev/null +++ b/sgx-jvm/avian/unittest/test-harness.h @@ -0,0 +1,119 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#ifndef TEST_HARNESS_H +#define TEST_HARNESS_H + +#include "avian/common.h" +#include + +class Test { + private: + Test* next; + static Test* first; + static Test** last; + + friend int main(int argc, char** argv); + + void print(uint64_t value) + { + fprintf(stderr, "%p", reinterpret_cast(value)); + } + + void print(uint32_t value) + { + fprintf(stderr, "%p", reinterpret_cast(value)); + } + + void print(uint8_t value) + { + print(static_cast(value)); + } + + void print(bool value) + { + fprintf(stderr, "%s", value ? "true" : "false"); + } + + int failures; + int runs; + + protected: + template + void assertEqual(T expected, T actual) + { + if (expected != actual) { + fprintf(stderr, "assertion failure, expected: "); + print(expected); + fprintf(stderr, ", actual: "); + print(actual); + fprintf(stderr, "\n"); + failures++; + } + runs++; + } + + void assertEqual(const char* expected, const char* actual) + { + if ((expected == 0 && actual != 0) || (expected != 0 && actual == 0) + || strcmp(expected, actual) != 0) { + fprintf(stderr, + "assertion failure, expected: \"%s\", actual: \"%s\"\n", + expected, + actual); + failures++; + } + runs++; + } + + template + void assertNotEqual(T expected, T actual) + { + if (expected == actual) { + fprintf(stderr, "assertion failure, expected: not "); + print(expected); + fprintf(stderr, ", actual: "); + print(actual); + fprintf(stderr, "\n"); + failures++; + } + runs++; + } + + void assertTrue(bool value) + { + assertEqual(true, value); + } + + void assertFalse(bool value) + { + assertEqual(false, value); + } + + public: + const char* const name; + Test(const char* name); + + virtual void run() = 0; + + static bool runAll(); +}; + +#define TEST(name) \ + class name##TestClass : public Test { \ + public: \ + name##TestClass() : Test(#name) \ + { \ + } \ + virtual void run(); \ + } name##TestInstance; \ + void name##TestClass::run() + +#endif // TEST_HARNESS_H diff --git a/sgx-jvm/avian/unittest/util/arg-parser-test.cpp b/sgx-jvm/avian/unittest/util/arg-parser-test.cpp new file mode 100644 index 0000000000..11fdb5e929 --- /dev/null +++ b/sgx-jvm/avian/unittest/util/arg-parser-test.cpp @@ -0,0 +1,49 @@ +/* Copyright (c) 2008-2015, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#include + +#include "avian/common.h" + +#include + +#include "test-harness.h" + +using namespace avian::util; + +TEST(ArgParser) +{ + { + ArgParser parser; + Arg arg1(parser, false, "arg1", ""); + Arg required2(parser, true, "required2", ""); + const char* args[] + = {"myExecutable", "-arg1", "myValue1", "-required2", "myRequired2", 0}; + assertTrue(parser.parse(sizeof(args) / sizeof(char*) - 1, args)); + assertEqual("myValue1", arg1.value); + assertEqual("myRequired2", required2.value); + } + + { + ArgParser parser; + Arg arg1(parser, false, "arg1", ""); + Arg required2(parser, true, "required2", ""); + const char* args[] = {"myExecutable", "-arg1", "myValue1", "-required2", 0}; + assertFalse(parser.parse(sizeof(args) / sizeof(char*) - 1, args)); + } + + { + ArgParser parser; + Arg arg1(parser, false, "arg1", ""); + Arg required2(parser, true, "required2", ""); + const char* args[] = {"myExecutable", "-arg1", "myValue1", 0}; + assertFalse(parser.parse(sizeof(args) / sizeof(char*) - 1, args)); + } +} diff --git a/sgx-jvm/avian/valgrind.supp b/sgx-jvm/avian/valgrind.supp new file mode 100644 index 0000000000..89e9ef784b --- /dev/null +++ b/sgx-jvm/avian/valgrind.supp @@ -0,0 +1,50 @@ + +{ + + Memcheck:Cond + obj:/lib/ld-2.3.6.so +} + +{ + + Memcheck:Cond + obj:/lib/ld-2.6.so +} + +{ + + Memcheck:Addr4 + obj:/lib/ld-2.3.6.so +} + +{ + + Memcheck:Addr8 + obj:/lib/ld-2.3.6.so +} + +# { +# +# Memcheck:Param +# write(buf) +# obj:* +# } + +# { +# +# Memcheck:Param +# writev(vector[...]) +# obj:* +# } + +# { +# +# Memcheck:Cond +# obj:* +# } + +# { +# +# Memcheck:Value8 +# obj:* +# } diff --git a/sgx-jvm/avian/vm.pro b/sgx-jvm/avian/vm.pro new file mode 100644 index 0000000000..ebc6f7c7e0 --- /dev/null +++ b/sgx-jvm/avian/vm.pro @@ -0,0 +1,135 @@ +# proguard include file (http://proguard.sourceforge.net) + +# we call the values method reflectively in Enum.valueOf(): + +-keepclassmembers public class * extends java.lang.Enum { + public static *** values(); + } + +# the VM depends on the fixed layout of the following classes: + +-keepclassmembers class java.lang.Class { !static ; } +-keepclassmembers class java.lang.ClassLoader { !static ; } +-keepclassmembers class java.lang.String { !static ; } +-keepclassmembers class java.lang.Thread { !static ; } +-keepclassmembers class java.lang.ThreadGroup { !static ; } +-keepclassmembers class java.lang.StackTraceElement { !static ; } +-keepclassmembers class java.lang.Throwable { !static ; } +-keepclassmembers class java.lang.Byte { !static ; } +-keepclassmembers class java.lang.Boolean { !static ; } +-keepclassmembers class java.lang.Short { !static ; } +-keepclassmembers class java.lang.Character { !static ; } +-keepclassmembers class java.lang.Integer { !static ; } +-keepclassmembers class java.lang.Long { !static ; } +-keepclassmembers class java.lang.Float { !static ; } +-keepclassmembers class java.lang.Double { !static ; } +-keepclassmembers class java.lang.ref.Reference { !static ; } +-keepclassmembers class java.lang.ref.ReferenceQueue { !static ; } +-keepclassmembers class java.lang.ref.WeakReference { !static ; } +-keepclassmembers class java.lang.ref.PhantomReference { !static ; } +-keepclassmembers class java.lang.reflect.Field { !static ; } +-keepclassmembers class java.lang.reflect.Method { !static ; } +-keepclassmembers class java.lang.reflect.Constructor { !static ; } +-keepclassmembers class java.lang.reflect.AccessibleObject { !static ; } +-keepclassmembers class sun.reflect.ConstantPool { !static ; } +-keepclassmembers class avian.VMClass { !static ; } +-keepclassmembers class avian.VMMethod { !static ; } +-keepclassmembers class avian.VMField { !static ; } +-keepclassmembers class avian.ClassAddendum { !static ; } +-keepclassmembers class avian.MethodAddendum { !static ; } +-keepclassmembers class avian.FieldAddendum { !static ; } +-keepclassmembers class avian.Continuations$Continuation { !static ; } +-keepclassmembers class avian.Continuations$UnwindResult { !static ; } + +# the VM may throw instances of the following: + +-keep public class avian.IncompatibleContinuationException +-keep public class java.lang.Exception +-keep public class java.lang.RuntimeException +-keep public class java.lang.IllegalStateException +-keep public class java.lang.IllegalArgumentException +-keep public class java.lang.IllegalMonitorStateException +-keep public class java.lang.IllegalThreadStateException +-keep public class java.lang.IndexOutOfBoundsException +-keep public class java.lang.ArrayIndexOutOfBoundsException +-keep public class java.lang.ArrayStoreException +-keep public class java.lang.NegativeArraySizeException +-keep public class java.lang.CloneNotSupportedException +-keep public class java.lang.ClassCastException +-keep public class java.lang.ClassNotFoundException +-keep public class java.lang.NullPointerException +-keep public class java.lang.ArithmeticException +-keep public class java.lang.InterruptedException +-keep public class java.lang.StackOverflowError +-keep public class java.lang.NoSuchFieldError +-keep public class java.lang.NoSuchMethodError +-keep public class java.lang.AbstractMethodError +-keep public class java.lang.UnsatisfiedLinkError +-keep public class java.lang.ExceptionInInitializerError +-keep public class java.lang.OutOfMemoryError +-keep public class java.lang.IncompatibleClassChangeError +-keep public class java.lang.reflect.InvocationTargetException +-keep public class java.io.IOException +-keep public class java.io.FileNotFoundException +-keep public class java.net.SocketException +-keep public class java.net.UnknownHostException +-keep public class java.util.Locale + +# ClassLoader.getSystemClassloader() depends on the existence of this class: + +-keep class avian.SystemClassLoader + +# the VM references these classes by name, so protect them from obfuscation: + +-keepnames public class java.lang.** +-keepnames public class avian.** + +# Don't optimize calls to ResourceBundle +-keep,allowshrinking,allowobfuscation public class java.util.ResourceBundle { + public static java.util.ResourceBundle getBundle(...); +} + +# musn't obfuscate native method names: + +-keepclasseswithmembernames class * { + native ; + } + +# Thread.run is called by name in the VM + +-keepclassmembers class java.lang.Thread { + private static void run(java.lang.Thread); + public void run(); + } + +# when continuations are enabled, the VM may call these methods by name: + +-keepclassmembers class avian.Continuations { + *** wind(...); + *** rewind(...); + } + +-keepclassmembernames class avian.CallbackReceiver { + *** receive(...); + } + +# the above methods include these classes in their signatures: + +-keepnames public class avian.Callback +-keepnames public class java.util.concurrent.Callable + +# Proguard gets confused about clone() and array classes (http://sourceforge.net/tracker/index.php?func=detail&aid=2851344&group_id=54750&atid=474704): + +-keepclassmembers class java.lang.Object { + protected java.lang.Object clone(); + } + +# called by name in the VM: + +-keepclassmembers class java.lang.ClassLoader { + public java.lang.Class loadClass(java.lang.String); + } + + -keepclassmembers class avian.Classes { + public java.security.ProtectionDomain getProtectionDomain(avian.VMClass); + } diff --git a/sgx-jvm/linux-sgx/.gitignore b/sgx-jvm/linux-sgx/.gitignore new file mode 100644 index 0000000000..89a3585dc9 --- /dev/null +++ b/sgx-jvm/linux-sgx/.gitignore @@ -0,0 +1,19 @@ +#object file +*.o + +#library +*.a + +#share object +*.so +*.so.* + +#generated proxy +*_u.c +*_u.h +*_t.c +*_t.h + +#output files +/build/ +/linux/installer/bin/*.bin diff --git a/sgx-jvm/linux-sgx/CONTRIBUTING.md b/sgx-jvm/linux-sgx/CONTRIBUTING.md new file mode 100644 index 0000000000..660066e7e9 --- /dev/null +++ b/sgx-jvm/linux-sgx/CONTRIBUTING.md @@ -0,0 +1,79 @@ +# Contributing + +## Issues + +GitHub Issues tracks SGX SDK and PSW design and development issues, bugs, and feature requests. +For usage, installation, or other requests for help, please use the [01.org](https://01.org/intel-software-guard-extensions/forum/forum) forum instead. + +When reporting a bug, please provide the following information, where applicable: + +* What are the steps to reproduce the bug? +* Can you reproduce the bug using the latest [master](https://github.com/01org/linux-sgx/tree/master)? +* What CPU, platform, operating system/distribution, and SGX driver are you running? The more specific, the better. +* For crashes, please provide the backtrace (use gdb). + + +### Contribution Guide + +We accept contributions as pull requests on GitHub. More detailed guidelines will be added later. Please follow these simple rules for now: + +* A PR should have a clear purpose, and do one thing only, and nothing more. This will enable us review your PR more quickly. +* Each commit in PR should be a small, atomic change representing one step in development. +* Please squash intermediate steps within PR for bugfixes, style cleanups, reversions, etc., so they would not appear in merged PR history. +* Please explain anything non-obvious from the code in comments, commit messages, or the PR description, as appropriate. + +### License + +linux-sgx is licensed under the terms in [LICENSE](https://github.com/01org/linux-sgx/blob/master/License.txt). By contributing to the project, you agree to the license and copyright terms therein and release your contribution under these terms. + +### Sign your work + +Please use the sign-off line at the end of the patch. Your signature certifies that you wrote the patch or otherwise have the right to pass it on as an open-source patch. The rules are pretty simple: if you can certify +the below (from [developercertificate.org](http://developercertificate.org/)): + +``` +Developer Certificate of Origin +Version 1.1 + +Copyright (C) 2004, 2006 The Linux Foundation and its contributors. +660 York Street, Suite 102, +San Francisco, CA 94110 USA + +Everyone is permitted to copy and distribute verbatim copies of this +license document, but changing it is not allowed. + +Developer's Certificate of Origin 1.1 + +By making a contribution to this project, I certify that: + +(a) The contribution was created in whole or in part by me and I + have the right to submit it under the open source license + indicated in the file; or + +(b) The contribution is based upon previous work that, to the best + of my knowledge, is covered under an appropriate open source + license and I have the right under that license to submit that + work with modifications, whether created in whole or in part + by me, under the same open source license (unless I am + permitted to submit under a different license), as indicated + in the file; or + +(c) The contribution was provided directly to me by some other + person who certified (a), (b) or (c) and I have not modified + it. + +(d) I understand and agree that this project and the contribution + are public and that a record of the contribution (including all + personal information I submit with it, including my sign-off) is + maintained indefinitely and may be redistributed consistent with + this project or the open source license(s) involved. +``` + +Then you just add a line to every git commit message: + + Signed-off-by: Joe Smith + +Use your real name (sorry, no pseudonyms or anonymous contributions.) + +If you set your `user.name` and `user.email` git configs, you can sign your +commit automatically with `git commit -s`. diff --git a/sgx-jvm/linux-sgx/License.txt b/sgx-jvm/linux-sgx/License.txt new file mode 100644 index 0000000000..ea9d767559 --- /dev/null +++ b/sgx-jvm/linux-sgx/License.txt @@ -0,0 +1,1396 @@ +BSD License + +Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + * Neither the name of Intel Corporation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +================================================================= + +SGX Eclipse plug-in is licensed under Eclipse Public License-v1.0 +http://www.eclipse.org/legal/epl-v10.html + + + +============================================================== + +libsgx_le.signed.so, libsgx_pce.signed.so, libsgx_pve.signed.so and libsgx_qe.signed.so are licensed as Intel redistributable binary firmware and other blobs. + + +Copyright (c) Intel Corporation. + +Redistribution. Redistribution and use in binary form, without +modification, are permitted provided that the following conditions are +met: + +* Redistributions must reproduce the above copyright notice and the + following disclaimer in the documentation and/or other materials + provided with the distribution. +* Neither the name of Intel Corporation nor the names of its suppliers + may be used to endorse or promote products derived from this software + without specific prior written permission. +* No reverse engineering, decompilation, or disassembly of this software + is permitted. + +Limited patent license. Intel Corporation grants a world-wide, +royalty-free, non-exclusive license under patents it now or hereafter +owns or controls to make, have made, use, import, offer to sell and +sell ("Utilize") this software, but solely to the extent that any +such patent is necessary to Utilize the software alone, or in +combination with an operating system licensed under an approved Open +Source license as listed by the Open Source Initiative at +http://opensource.org/licenses. The patent license shall not apply to +any other combinations which include this software. No hardware per +se is licensed hereunder. + +DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND +CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, +BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR +TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE +USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +DAMAGE. + + + +=========================================================================================================================================================== + +SGX software for Linux also uses third-party projects that may be distributed under different licenses. Please see below for details. + + +1. Android Open Source Project + +Copyright (C) 2012 The Android Open Source Project +All rights reserved. +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: +Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. +Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + + +2. compiler_rt + +The compiler_rt library is dual licensed under both the University of Illinois +"BSD-Like" license and the MIT license. As a user of this code you may choose +to use it under either license. As a contributor, you agree to allow your code +to be used under both. + +Full text of the relevant licenses is included below. + +============================================================================= + +University of Illinois/NCSA +Open Source License + +Copyright (c) 2009-2013 by the contributors listed in CREDITS.TXT + +All rights reserved. + +Developed by: + + LLVM Team + + University of Illinois at Urbana-Champaign + + http://llvm.org + +Permission is hereby granted, free of charge, to any person obtaining a copy of this +software and associated documentation files (the "Software"), to deal with the +Software without restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the +Software, and to permit persons to whom the Software is furnished to do so, subject +to the following conditions: + +- Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimers. + +- Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimers in the documentation and/or +other materials provided with the distribution. + +- Neither the names of the LLVM Team, University of Illinois at Urbana-Champaign, +nor the names of its contributors may be used to endorse or romote products derived +from this Software without specific prior written permission. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE CONTRIBUTORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT +OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS WITH THE SOFTWARE. + +============================================================================= + +Copyright (c) 2009-2013 by the contributors listed in CREDITS.TXT + +Permission is hereby granted, free of charge, to any person obtaining a copy of this +software and associated documentation files (the "Software"), to deal in the Software +without restriction, including without limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or +substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +============================================================================= +Copyrights and Licenses for Third Party Software Distributed with LLVM: +============================================================================= +The LLVM software contains code written by third parties. Such software will have its +own individual LICENSE.TXT file in the directory in which it appears. +This file will describe the copyrights, license, and restrictions which apply to that code. + +The disclaimer of warranty in the University of Illinois Open Source License applies to all +code in the LLVM Distribution, and nothing in any of the other licenses gives permission to +use the names of the LLVM Team or the University of Illinois to endorse or promote products +derived from this Software. + +The following pieces of software have additional or alternate copyrights, licenses, and/or +restrictions: + +Program Directory +------- --------- +mach_override lib/interception/mach_override + + + +3. DLmalloc + + +Public domain +http://g.oswego.edu/dl/html/malloc.html + +CC0 1.0 Universal + +CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE LEGAL SERVICES. +DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN ATTORNEY-CLIENT RELATIONSHIP. +CREATIVE COMMONS PROVIDES THIS INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS +MAKES NO WARRANTIES REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS +PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM THE USE OF +THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED HEREUNDER. + +Statement of Purpose +The laws of most jurisdictions throughout the world automatically confer exclusive +Copyright and Related Rights (defined below) upon the creator and subsequent owner(s) +(each and all, an "owner") of an original work of authorship and/or a database (each, +a "Work"). +Certain owners wish to permanently relinquish those rights to a Work for the purpose +of contributing to a commons of creative, cultural and scientific works ("Commons") +that the public can reliably and without fear of later claims of infringement build +upon, modify, incorporate in other works, reuse and redistribute as freely as possible +in any form whatsoever and for any purposes, including without limitation commercial +purposes. These owners may contribute to the Commons to promote the ideal of a free +culture and the further production of creative, cultural and scientific works, or to +gain reputation or greater distribution for their Work in part through the use and +efforts of others. +For these and/or other purposes and motivations, and without any expectation of +additional consideration or compensation, the person associating CC0 with a Work +(the "Affirmer"), to the extent that he or she is an owner of Copyright and Related +Rights in the Work, voluntarily elects to apply CC0 to the Work and publicly distribute +the Work under its terms, with knowledge of his or her Copyright and Related Rights +in the Work and the meaning and intended legal effect of CC0 on those rights. +1. Copyright and Related Rights. A Work made available under CC0 may be protected by +copyright and related or neighboring rights ("Copyright and Related Rights"). +Copyright and Related Rights include, but are not limited to, the following: +i. the right to reproduce, adapt, distribute, perform, display, communicate, + and translate a Work; +ii. moral rights retained by the original author(s) and/or performer(s); +iii. publicity and privacy rights pertaining to a person's image or likeness +depicted in a Work; +iv. rights protecting against unfair competition in regards to a Work, subject +to the limitations in paragraph 4(a), below; +v. rights protecting the extraction, dissemination, use and reuse of data in a Work; +vi. database rights (such as those arising under Directive 96/9/EC of the European +Parliament and of the Council of 11 March 1996 on the legal protection of databases, +and under any national implementation thereof, including any amended or successor +version of such directive); and +vii. other similar, equivalent or corresponding rights throughout the world based on +applicable law or treaty, and any national implementations thereof. +2. Waiver. To the greatest extent permitted by, but not in contravention of, applicable +law, Affirmer hereby overtly, fully, permanently, irrevocably and unconditionally waives, +abandons, and surrenders all of Affirmer's Copyright and Related Rights and associated +claims and causes of action, whether now known or unknown (including existing as well as +future claims and causes of action), in the Work (i) in all territories worldwide, (ii) for +the maximum duration provided by applicable law or treaty (including future time extensions), + (iii) in any current or future medium and for any number of copies, and (iv) for any purpose + whatsoever, including without limitation commercial, advertising or promotional purposes +(the "Waiver"). Affirmer makes the Waiver for the benefit of each member of the public at +large and to the detriment of Affirmer's heirs and successors, fully intending that such +Waiver shall not be subject to revocation, rescission, cancellation, termination, or any +other legal or equitable action to disrupt the quiet enjoyment of the Work by the public +as contemplated by Affirmer's express Statement of Purpose. +3. Public License Fallback. Should any part of the Waiver for any reason be judged legally +invalid or ineffective under applicable law, then the Waiver shall be preserved to the +maximum extent permitted taking into account Affirmer's express Statement of Purpose. In +addition, to the extent the Waiver is so judged Affirmer hereby grants to each affected +person a royalty-free, non transferable, non sublicensable, non exclusive, irrevocable +and unconditional license to exercise Affirmer's Copyright and Related Rights in the +Work (i) in all territories worldwide, (ii) for the maximum duration provided by applicable +law or treaty (including future time extensions), (iii) in any current or future medium and +for any number of copies, and (iv) for any purpose whatsoever, including without limitation +commercial, advertising or promotional purposes (the "License"). The License shall be deemed +effective as of the date CC0 was applied by Affirmer to the Work. Should any part of the +License for any reason be judged legally invalid or ineffective under applicable law, such +partial invalidity or ineffectiveness shall not invalidate the remainder of the License, +and in such case Affirmer hereby affirms that he or she will not (i) exercise any of his +or her remaining Copyright and Related Rights in the Work or (ii) assert any associated +claims and causes of action with respect to the Work, in either case contrary to Affirmer's +express Statement of Purpose. +4. Limitations and Disclaimers. +a. No trademark or patent rights held by Affirmer are waived, abandoned, surrendered, +licensed or otherwise affected by this document. +b. Affirmer offers the Work as-is and makes no representations or warranties of any +kind concerning the Work, express, implied, statutory or otherwise, including without limitation +warranties of title, merchantability, fitness for a particular purpose, non infringement, or +the absence of latent or other defects, accuracy, or the present or absence of errors, whether +or not discoverable, all to the greatest extent permissible under applicable law. +c. Affirmer disclaims responsibility for clearing rights of other persons that may apply + +to the Work or any use thereof, including without limitation any person's Copyright and Related +Rights in the Work. Further, Affirmer disclaims responsibility for obtaining any necessary +consents, permissions or other rights required for any use of the Work. +d. Affirmer understands and acknowledges that Creative Commons is not a party to this +document and has no duty or obligation with respect to this CC0 or use of the Work. + + + + +4. FreeBSD + +http://www.freebsd.org/ + +The FreeBSD* Copyright +Copyright 1992-2013 The FreeBSD Project. All rights reserved. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: +1. Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. +THIS SOFTWARE IS PROVIDED BY THE FREEBSD PROJECT ``AS IS'' AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +SHALL THE FREEBSD PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +The views and conclusions contained in the software and documentation are those +of the authors and should not be interpreted as representing official policies, +either expressed or implied, of the FreeBSD Project. + + + + +5. libcxxrt + +The BSD License + +Copyright 2010-2011 PathScale, Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this list + of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, this + list of conditions and the following disclaimer in the documentation and/or other + materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +DAMAGE. + +The views and conclusions contained in the software and documentation are those of +the authors and should not be interpreted as representing official policies, either +expressed or implied, of PathScale, Inc. + + + + + +6. NetBSD + +=============================================================================================== + +/*- + * Copyright (c) 2008 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +________________________________________ +For complete copyright and licensing terms, see: http://www.netbsd.org/about/redistribution.html + + + + +7. OpenBSD + +http://openbsd.org/ + +OpenBSD* Copyright Policy +________________________________________ +- Goal +Copyright law is complex, OpenBSD* policy is simple - OpenBSD strives to maintain the spirit +of the original Berkeley Unix copyrights. +OpenBSD can exist as it does today because of the example set by the Computer Systems Research +Group at Berkeley and the battles which they and others fought to create a relatively +un-encumbered Unix source distribution. +The ability of a freely redistributable "Berkeley" Unix to move forward on a competitive +basis with other operating systems depends on the willingness of the various development +groups to exchange code amongst themselves and with other projects. Understanding the legal +issues surrounding copyright is fundamental to the ability to exchange and re-distribute code, +while honoring the spirit of the copyright and concept of attribution is fundamental to +promoting the cooperation of the people involved. +- The Berkeley* Copyright +The Berkeley* copyright poses no restrictions on private or commercial use of the software +and imposes only simple and uniform requirements for maintaining copyright notices in +redistributed versions and crediting the originator of the material only in advertising. +For instance: + * Copyright (c) 1982, 1986, 1990, 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * +Berkeley rescinded the 3rd term (the advertising term) on 22 July 1999. Verbatim copies +of the Berkeley license in the OpenBSD tree have that term removed. In addition, many +3rd-party BSD-style licenses consist solely of the first two terms. +Because the OpenBSD copyright imposes no conditions beyond those imposed by the Berkeley +copyright, OpenBSD can hope to share the same wide distribution and applicability as the +Berkeley distributions. It follows however, that OpenBSD cannot include material which +includes copyrights which are more restrictive than the Berkeley copyright, or must +relegate this material to a secondary status, i.e. OpenBSD as a whole is freely +redistributable, but some optional components may not be. +- Copyright Law +While the overall subject of copyright law is far beyond the scope of this document, some +basics are in order. Under the current copyright law, copyrights are implicit in the +creation of a new work and reside with the creator, unless otherwise assigned. In general +the copyright applies only to the new work, not the material the work was derived from, +nor those portions of the derivative material included in the new work. +Copyright law admits to three general categories of works: +Original Work +A new work that is not derived from an existing work. +Derivative Work +Work that is derived from, includes or amends existing works. +Compilations +A work that is a compilation of existing new and derivative works. +The fundamental concept is that there is primacy of the copyright, that is a copyright of a +derivative work does not affect the rights held by the owner of the copyright of the original +work, rather only the part added. Likewise the copyright of a compilation does not affect the +rights of the owner of the included works, only the compilation as an entity. +It is vitally important to understand that copyrights are broad protections as defined by +national and international copyright law. The "copyright notices" usually included in source +files are not copyrights, but rather notices that a party asserts that they hold copyright +to the material or to part of the material. Typically these notices are associated with +license terms which grant permissions subject to copyright law and with disclaimers that +state the position of the copyright holder/distributor with respect to liability surrounding +use of the material. +- Permissions - the flip side +Because copyrights arise from the creation of a work, rather than through a registration process, +there needs to be a practical way to extend permission to use a work beyond what might be allowed +by "fair use" provisions of the copyright laws. +This permission typically takes the form of a "release" or "license" included in the work, which +grants the additional uses beyond those granted by copyright law, usually subject to a variety of +conditions. At one extreme sits "public domain" where the originator asserts that he imposes no +restrictions on use of the material, at the other restrictive clauses that actually grant no +additional rights or impose restrictive, discriminatory or impractical conditions on use of the +work. +Again, an important point to note is that the release and conditions can only apply to the +portion of the work that was originated by the copyright holder - the holder of a copyright +on a derivative work can neither grant additional permissions for use of the original work, +nor impose more restrictive conditions for use of that work. +Because copyright arises from the creation of a work and not the text or a registration process, +removing or altering a copyright notice or associated release terms has no bearing on the +existence of the copyright, rather all that is accomplished is to cast doubt upon whatever rights +the person making the modifications had to use the material in the first place. Likewise, adding +terms and conditions in conflict with the original terms and conditions does not supersede them, +rather it casts doubts on the rights of the person making the amendments to use the material and +creates confusion as to whether anyone can use the amended version or derivatives thereof. +Finally, releases are generally binding on the material that they are distributed with. This means +that if the originator of a work distributes that work with a release granting certain permissions, +those permissions apply as stated, without discrimination, to all persons legitimately possessing +a copy of the work. That means that having granted a permission, the copyright holder can not +retroactively say that an individual or class of individuals are no longer granted those permissions. +Likewise should the copyright holder decide to "go commercial" he can not revoke permissions already +granted for the use of the work as distributed, though he may impose more restrictive permissions in +his future distributions of that work. +- Specific Cases +This section attempts to summarize the position of OpenBSD relative to some commonly encountered +copyrights. +Berkeley* +The Berkeley copyright is the model for the OpenBSD copyright. It retains the rights of the +copyright holder, while imposing minimal conditions on the use of the copyrighted material. +Material with Berkeley copyrights, or copyrights closely adhering to the Berkeley model can +generally be included in OpenBSD. +AT&T* +As part of its settlement with AT&T*, Berkeley included an AT&T copyright notice on some of the +files in 4.4BSD lite and lite2. The terms of this license are identical to the standard Berkeley +license. +Additionally, OpenBSD includes some other AT&T code with non-restrictive copyrights, such as the +reference implementation of awk. +Caldera* +Caldera* (now known as the SCO group) is the current owner of the Unix code copyrights. On 23 +January 2002, the original Unix code (versions 1 through seven, including 32V) was freed by Caldera. +This code is now available under a 4-term BSD-style license. As a result, it is now possible to +incorporate real Unix code into OpenBSD (though this code is quite old and generally requires significant +changes to bring it up to date). +DEC*, Sun*, other manufacturers/software houses. +In general OpenBSD does not include material copyrighted by manufacturers or software houses. +Material may be included where the copyright owner has granted general permission for reuse +without conditions, with terms similar to the Berkeley copyright, or where the material is the +product of an employee and the employer's copyright notice effectively releases any rights they +might have to the work. +Carnegie-Mellon* (CMU, Mach) +The Carnegie-Mellon copyright is similar to the Berkeley copyright, except that it requests that +derivative works be made available to Carnegie-Mellon. Because this is only a request and not a +condition, such material can still be included in OpenBSD. It should be noted that existing +versions of Mach are still subject to AT&T copyrights, which prevents the general distribution +of Mach sources. +Apache* +The original Apache* copyright is similar to the Berkeley copyright, except that it stipulates +that products derived from the code may not have "Apache" in their name. The purpose of this +clause is to avoid a situation in which another party releases a modified version of the code +named in such a way to make users think that it is the "official" version. This is not an issue +with OpenBSD because OpenBSD is a Compilation, and not a Derived Work. Source code published under +version 2 of the Apache license cannot be included into OpenBSD. As a consequence, OpenBSD now +maintains its own version of Apache based on version 1.3.29. The OpenBSD version includes many +enhancements and bugfixes. +ISC* +The ISC* copyright is functionally equivalent to a two-term BSD copyright with language removed +that is made unnecessary by the Berne convention. This is the preferred license for new code +incorporated into OpenBSD. A sample license is included in the source tree as +/usr/src/share/misc/license.template. +GNU* General Public License, GPL, LGPL, copyleft, etc. +The GNU* Public License and licenses modeled on it impose the restriction that source code must +be distributed or made available for all works that are derivatives of the GNU copyrighted code. +While this may be a noble strategy in terms of software sharing, it is a condition that is +typically unacceptable for commercial use of software. As a consequence, software bound by the +GPL terms can not be included in the kernel or "runtime" of OpenBSD, though software subject to + GPL terms may be included as development tools or as part of the system that are "optional" as +long as such use does not result in OpenBSD as a whole becoming subject to the GPL terms. +As an example, GCC and other GNU tools are included in the OpenBSD tool chain. However, it is +quite possible to distribute a system for many applications without a tool chain, or the +distributor can choose to include a tool chain as an optional bundle which conforms to the +GPL terms. +NetBSD* +Much of OpenBSD is originally based on and evolved from NetBSD*, since some of the OpenBSD +developers were involved in the NetBSD project. The general NetBSD license terms are compatible +with the Berkeley license and permit such use. Material subject only to the general NetBSD license +can generally be included in OpenBSD. +In the past, NetBSD has included material copyrighted by individuals who have imposed license +conditions beyond that of the general NetBSD license, but granted the NetBSD Foundation license +to distribute the material. Such material can not be included in OpenBSD as long as the conditions +imposed are at odds with the OpenBSD license terms or releases from those terms are offered on a +discriminatory basis. +FreeBSD* +Most of FreeBSD* is also based on Berkeley licensed material or includes copyright notices based +on the Berkeley model. Such material can be included in OpenBSD, while those parts that are subject +to GPL or various individual copyright terms that are at odds with the OpenBSD license can not be +included in OpenBSD. +Linux* +Most of Linux* is subject to GPL style licensing terms and therefore can not be included in +OpenBSD. Individual components may be eligible, subject to the terms of the originator's copyright +notices. Note that Linux "distributions" may also be subject to additional copyright claims of the +distributing organization, either as a compilation or on material included that is not part of the +Linux core. +X*, XFree86*, X.Org* +X*, X.Org* or XFree86* are not parts of OpenBSD, rather X.Org and parts of XFree86 3.3.6 are +distributed with many OpenBSD ports as a convenience to the user, subject to applicable license +terms. +Shareware, Charityware, Freeware, etc. +Most "shareware" copyright notices impose conditions for redistribution, use or visibility that +are at conflict with the OpenBSD project goals. Review on a case-by-case basis is required as to +whether the wording of the conditions is acceptable in terms of conditions being requested vs. +demanded and whether the spirit of the conditions is compatible with goals of the OpenBSD project. +Public Domain +While material that is truly entered into the "Public Domain" can be included in OpenBSD, review +is required on a case by case basis. Frequently the "public domain" assertion is made by someone +who does not really hold all rights under Copyright law to grant that status or there are a variety +of conditions imposed on use. For a work to be truly in the "Public Domain" all rights are abandoned +and the material is offered without restrictions. + + + + +8. Openssl + + +http://www.openssl.org/ + + LICENSE ISSUES + ============== + + The OpenSSL* toolkit stays under a dual license, i.e. both the conditions of + the OpenSSL License and the original SSLeay license apply to the toolkit. + See below for the actual license texts. Actually both licenses are BSD-style + Open Source licenses. In case of any license issues related to OpenSSL + please contact openssl-core@openssl.org. + + OpenSSL License + --------------- + +/* ==================================================================== + * Copyright (c) 1998-2011 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + + Original SSLeay* License + ----------------------- + +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + + + + +9. Protocol Buffers + +Protocol Buffers - Google's data interchange format +Copyright 2008 Google Inc. All rights reserved. +http://code.google.com/p/protobuf/ +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: +1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, this + list of conditions and the following disclaimer in the documentation and/or other + materials provided with the distribution. +3. Neither the name of the Google Inc. nor the names of its contributors may be used + to endorse or promote products derived from this software without specific prior + written permission. +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +SUCH DAMAGE. + + + + +10. rdrand + +Intel Sample Source Code license. + +This license governs use of the accompanying software. By installing or +copying all or any part of the software components in this package, you +("you" or "Licensee") agree to the terms of this agreement. Do +not install or copy the software until you have carefully read and +agreed to the following terms and conditions. If you do not agree to the +terms of this agreement, promptly return the software to Intel +Corporation ("Intel"). + +1. Definitions: + +A. "Materials" are defined as the software (including the +Redistributables and Sample Source as defined herein), documentation, +and other materials, including any updates and upgrade thereto, that are +provided to you under this Agreement. + +B. "Redistributables" are the files listed in the "redist.txt" file that +is included in the Materials or are otherwise clearly identified as +redistributable files by Intel. + +C. "Sample Source" is the source code file(s) that: (i) +demonstrate(s) certain functions for particular purposes; (ii) are +identified as sample source code; and (iii) are provided hereunder in +source code form. + +D. "Intel's Licensed Patent Claims" means those claims of +Intel's patents that (a) are infringed by the Sample Source or +Redistributables, alone and not in combination, in their unmodified +form, as furnished by Intel to Licensee and (b) Intel has the right to +license. + +2. License Grant: Subject to all of the terms and conditions of this +Agreement: + +A. Intel grants to you a non-exclusive, non-assignable, copyright +license to use the Material for your internal development purposes only. + +B. Intel grants to you a non-exclusive, non-assignable copyright license +to reproduce the Sample Source, prepare derivative works of the Sample +Source and distribute the Sample Source or any derivative works thereof +that you create, as part of the product or application you develop using +the Materials. + +C. Intel grants to you a non-exclusive, non-assignable copyright license +to distribute the Redistributables, or any portions thereof, as part of +the product or application you develop using the Materials. + +D. Intel grants Licensee a non-transferable, non-exclusive, worldwide, +non-sublicenseable license under Intel's Licensed Patent Claims to +make, use, sell, and import the Sample Source and the Redistributables. + +3. Conditions and Limitations: + +A. This license does not grant you any rights to use Intel's name, +logo or trademarks. + +B. Title to the Materials and all copies thereof remain with Intel. The +Materials are copyrighted and are protected by United States copyright +laws. You will not remove any copyright notice from the Materials. You +agree to prevent any unauthorized copying of the Materials. Except as +expressly provided herein, Intel does not grant any express or implied +right to you under Intel patents, copyrights, trademarks, or trade +secret information. + +C. You may NOT: (i) use or copy the Materials except as provided in this +Agreement; (ii) rent or lease the Materials to any third party; (iii) +assign this Agreement or transfer the Materials without the express +written consent of Intel; (iv) modify, adapt, or translate the Materials +in whole or in part except as provided in this Agreement; (v) reverse +engineer, decompile, or disassemble the Materials not provided to you in +source code form; or (vii) distribute, sublicense or transfer the source +code form of any components of the Materials and derivatives thereof to +any third party except as provided in this Agreement. + +D. Platform Limitation - The licenses granted in section 2 extend only +to the software or derivative works that you create that run directly on +a Microsoft Windows operating system product, Microsoft run-time +technology (such as the .NET Framework or Silverlight), or Microsoft +application platform (such as Microsoft Office or Microsoft Dynamics). + +4. No Warranty: + +THE MATERIALS ARE PROVIDED "AS IS". INTEL DISCLAIMS ALL EXPRESS OR +IMPLIED WARRANTIES WITH RESPECT TO THEM, INCLUDING ANY IMPLIED +WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, AND FITNESS FOR ANY +PARTICULAR PURPOSE. + +5. LIMITATION OF LIABILITY: NEITHER INTEL NOR ITS SUPPLIERS SHALL BE +LIABLE FOR ANY DAMAGES WHATSOEVER (INCLUDING, WITHOUT LIMITATION, +DAMAGES FOR LOSS OF BUSINESS PROFITS, BUSINESS INTERRUPTION, LOSS OF +BUSINESS INFORMATION, OR OTHER LOSS) ARISING OUT OF THE USE OF OR +INABILITY TO USE THE SOFTWARE, EVEN IF INTEL HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. BECAUSE SOME JURISDICTIONS PROHIBIT THE +EXCLUSION OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL +DAMAGES, THE ABOVE LIMITATION MAY NOT APPLY TO YOU. + +6. USER SUBMISSIONS: You agree that any material, information or other +communication, including all data, images, sounds, text, and other +things embodied therein, you transmit or post to an Intel website or +provide to Intel under this Agreement will be considered +non-confidential ("Communications"). Intel will have no confidentiality +obligations with respect to the Communications. You agree that Intel and +its designees will be free to copy, modify, create derivative works, +publicly display, disclose, distribute, license and sublicense through +multiple tiers of distribution and licensees, incorporate and otherwise +use the Communications, including derivative works thereto, for any and +all commercial or non-commercial purposes + +7. TERMINATION OF THIS LICENSE: This Agreement becomes effective on the +date you accept this Agreement and will continue until terminated as +provided for in this Agreement. Intel may terminate this license at any +time if you are in breach of any of its terms and conditions. Upon +termination, you will immediately return to Intel or destroy the +Materials and all copies thereof. + +8. U.S. GOVERNMENT RESTRICTED RIGHTS: The Materials are provided with +"RESTRICTED RIGHTS". Use, duplication or disclosure by the Government is +subject to restrictions set forth in FAR52.227-14 and DFAR252.227-7013 +et seq. or its successor. Use of the Materials by the Government +constitutes acknowledgment of Intel's rights in them. + +9. APPLICABLE LAWS: Any claim arising under or relating to this +Agreement shall be governed by the internal substantive laws of the +State of Delaware, without regard to principles of conflict of laws. You +may not export the Materials in violation of applicable export laws. + + + + + + + + +11. SQLite + +http://sqlite.org/ + +SQLite* Copyright + +All of the code and documentation in SQLite has been dedicated to the public +domain by the authors. All code authors, and representatives of the companies +they work for, have signed affidavits dedicating their contributions to the +public domain and originals of those signed affidavits are stored in a firesafe +at the main offices of Hwaci. Anyone is free to copy, modify, publish, use, +compile, sell, or distribute the original SQLite code, either in source code +form or as a compiled binary, for any purpose, commercial or non-commercial, +and by any means. +The previous paragraph applies to the deliverable code and documentation in +SQLite - those parts of the SQLite library that you actually bundle and ship +with a larger application. Some scripts used as part of the build process +(for example the "configure" scripts generated by autoconf) might fall under +other open-source licenses. Nothing from these build scripts ever reaches the +final deliverable SQLite library, however, and so the licenses associated with +those scripts should not be a factor in assessing your rights to copy and use +the SQLite library. +All of the deliverable code in SQLite has been written from scratch. No code +has been taken from other projects or from the open internet. Every line of +code can be traced back to its original author, and all of those authors have +public domain dedications on file. So the SQLite code base is clean and is +uncontaminated with licensed code from other projects. + + + + + + + +12. STLPort + +License Agreement + +Boris Fomitchev grants Licensee a non-exclusive, non-transferable, + +royalty-free license to use STLport* and its documentation without +fee. + +By downloading, using, +or copying STLport or any portion thereof, +Licensee agrees to abide by the intellectual +property laws and all +other applicable laws of the United States of America, and to all of + +the terms and conditions of this Agreement. + +Licensee shall maintain the following copyright +and permission notices +on STLport sources and its documentation unchanged: + +Copyright 1999,2000 +Boris Fomitchev + +This material is provided "as is", with absolutely no warranty +expressed or +implied. Any use is at your own risk. + +Permission to use or copy this software for any purpose +is hereby +granted without fee, provided the above notices are retained on all +copies. Permission +to modify the code and to distribute modified code +is granted, provided the above notices are +retained, and a notice that +the code was modified is included with the above copyright notice. + + +The Licensee may distribute binaries compiled with STLport whether +original or modified) without +any royalties or restrictions. + +The Licensee may distribute original or modified STLport sources, + +provided that: + + - The conditions indicated in the above permission notice are met; + - The +following copyright notices are retained when present, and + conditions provided in +accompanying permission notices are met : + +Copyright 1994 Hewlett-Packard Company +Copyright +1996,97 Silicon Graphics Computer Systems, Inc. +Copyright 1997 Moscow Center for SPARC +Technology. + + Permission to use, copy, modify, distribute and sell this software + and its +documentation for any purpose is hereby granted without fee, + provided that the above +copyright notice appear in all copies and + that both that copyright notice and this permission +notice appear in + supporting documentation. Hewlett-Packard Company makes no + representations +about the suitability of this software for any + purpose. It is provided "as is" without +express or implied warranty. + + Permission to use, copy, modify, distribute and sell this +software + and its documentation for any purpose is hereby granted without fee, + provided that +the above copyright notice appear in all copies and + that both that copyright notice and this +permission notice appear in + supporting documentation. Silicon Graphics makes no representations + +about the suitability of this software for any purpose. It is + provided "as is" without express +or implied warranty. + + Permission to use, copy, modify, distribute and sell this software + and +its documentation for any purpose is hereby granted without fee, + provided that the above +copyright notice appear in all copies and + that both that copyright notice and this permission +notice appear in + supporting documentation. Moscow Center for SPARC Technology?makes + no +representations about the suitability of this software for any + purpose. It is provided "as is" +without express or implied warranty. + + + +http://www.stlport.org/doc/license.html + + + + + + +13. TinyXML + +http://www.grinninglizard.com/tinyxml/ + + +The zlib/libpng License +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the +use of this software. +Permission is granted to anyone to use this software for any purpose, including +commercial applications, and to alter it and redistribute it freely, subject to +the following restrictions: +1. The origin of this software must not be misrepresented; you must not claim + that you wrote the original software. If you use this software in a product, + an acknowledgment in the product documentation would be appreciated but is + not required. +2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. + + + + + +14. libunwind + +Copyright (C) 1996 X Consortium +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +Except as contained in this notice, the name of the X Consortium shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from the X Consortium. +X Window System is a trademark of X Consortium, Inc. + + + +15. ittnotify library + +BSD/GPLv2 dual license + +Copyright (c) 2011, Intel Corporation +All rights reserved. +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + Neither the name of the Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + + +The GNU General Public License (GPL) +Version 2, June 1991 +Copyright (C) 1989, 1991 Free Software Foundation, Inc. +59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +Everyone is permitted to copy and distribute verbatim copies +of this license document, but changing it is not allowed. +Preamble +The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. +When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. +To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. +For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. +We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. +Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. +Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. +The precise terms and conditions for copying, distribution and modification follow. +TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + + + +16. EPID SDK + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + + + +17. Eclipse Plug-in + +Eclipse Public License - v 1.0 + +THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. + +1. DEFINITIONS + +"Contribution" means: + +a) in the case of the initial Contributor, the initial code and documentation distributed under this Agreement, and +b) in the case of each subsequent Contributor: +i) changes to the Program, and +ii) additions to the Program; +where such changes and/or additions to the Program originate from and are distributed by that particular Contributor. A Contribution 'originates' from a Contributor if it was added to the Program by such Contributor itself or anyone acting on such Contributor's behalf. Contributions do not include additions to the Program which: (i) are separate modules of software distributed in conjunction with the Program under their own license agreement, and (ii) are not derivative works of the Program. +"Contributor" means any person or entity that distributes the Program. + +"Licensed Patents" mean patent claims licensable by a Contributor which are necessarily infringed by the use or sale of its Contribution alone or when combined with the Program. + +"Program" means the Contributions distributed in accordance with this Agreement. + +"Recipient" means anyone who receives the Program under this Agreement, including all Contributors. + +2. GRANT OF RIGHTS + +a) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, distribute and sublicense the Contribution of such Contributor, if any, and such derivative works, in source code and object code form. +b) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed Patents to make, use, sell, offer to sell, import and otherwise transfer the Contribution of such Contributor, if any, in source code and object code form. This patent license shall apply to the combination of the Contribution and the Program if, at the time the Contribution is added by the Contributor, such addition of the Contribution causes such combination to be covered by the Licensed Patents. The patent license shall not apply to any other combinations which include the Contribution. No hardware per se is licensed hereunder. +c) Recipient understands that although each Contributor grants the licenses to its Contributions set forth herein, no assurances are provided by any Contributor that the Program does not infringe the patent or other intellectual property rights of any other entity. Each Contributor disclaims any liability to Recipient for claims brought by any other entity based on infringement of intellectual property rights or otherwise. As a condition to exercising the rights and licenses granted hereunder, each Recipient hereby assumes sole responsibility to secure any other intellectual property rights needed, if any. For example, if a third party patent license is required to allow Recipient to distribute the Program, it is Recipient's responsibility to acquire that license before distributing the Program. +d) Each Contributor represents that to its knowledge it has sufficient copyright rights in its Contribution, if any, to grant the copyright license set forth in this Agreement. +3. REQUIREMENTS + +A Contributor may choose to distribute the Program in object code form under its own license agreement, provided that: + +a) it complies with the terms and conditions of this Agreement; and +b) its license agreement: +i) effectively disclaims on behalf of all Contributors all warranties and conditions, express and implied, including warranties or conditions of title and non-infringement, and implied warranties or conditions of merchantability and fitness for a particular purpose; +ii) effectively excludes on behalf of all Contributors all liability for damages, including direct, indirect, special, incidental and consequential damages, such as lost profits; +iii) states that any provisions which differ from this Agreement are offered by that Contributor alone and not by any other party; and +iv) states that source code for the Program is available from such Contributor, and informs licensees how to obtain it in a reasonable manner on or through a medium customarily used for software exchange. +When the Program is made available in source code form: + +a) it must be made available under this Agreement; and +b) a copy of this Agreement must be included with each copy of the Program. +Contributors may not remove or alter any copyright notices contained within the Program. + +Each Contributor must identify itself as the originator of its Contribution, if any, in a manner that reasonably allows subsequent Recipients to identify the originator of the Contribution. + +4. COMMERCIAL DISTRIBUTION + +Commercial distributors of software may accept certain responsibilities with respect to end users, business partners and the like. While this license is intended to facilitate the commercial use of the Program, the Contributor who includes the Program in a commercial product offering should do so in a manner which does not create potential liability for other Contributors. Therefore, if a Contributor includes the Program in a commercial product offering, such Contributor ("Commercial Contributor") hereby agrees to defend and indemnify every other Contributor ("Indemnified Contributor") against any losses, damages and costs (collectively "Losses") arising from claims, lawsuits and other legal actions brought by a third party against the Indemnified Contributor to the extent caused by the acts or omissions of such Commercial Contributor in connection with its distribution of the Program in a commercial product offering. The obligations in this section do not apply to any claims or Losses relating to any actual or alleged intellectual property infringement. In order to qualify, an Indemnified Contributor must: a) promptly notify the Commercial Contributor in writing of such claim, and b) allow the Commercial Contributor to control, and cooperate with the Commercial Contributor in, the defense and any related settlement negotiations. The Indemnified Contributor may participate in any such claim at its own expense. + +For example, a Contributor might include the Program in a commercial product offering, Product X. That Contributor is then a Commercial Contributor. If that Commercial Contributor then makes performance claims, or offers warranties related to Product X, those performance claims and warranties are such Commercial Contributor's responsibility alone. Under this section, the Commercial Contributor would have to defend claims against the other Contributors related to those performance claims and warranties, and if a court requires any other Contributor to pay any damages as a result, the Commercial Contributor must pay those damages. + +5. NO WARRANTY + +EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the appropriateness of using and distributing the Program and assumes all risks associated with its exercise of rights under this Agreement , including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and unavailability or interruption of operations. + +6. DISCLAIMER OF LIABILITY + +EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + +7. GENERAL + +If any provision of this Agreement is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this Agreement, and without further action by the parties hereto, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable. + +If Recipient institutes patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Program itself (excluding combinations of the Program with other software or hardware) infringes such Recipient's patent(s), then such Recipient's rights granted under Section 2(b) shall terminate as of the date such litigation is filed. + +All Recipient's rights under this Agreement shall terminate if it fails to comply with any of the material terms or conditions of this Agreement and does not cure such failure in a reasonable period of time after becoming aware of such noncompliance. If all Recipient's rights under this Agreement terminate, Recipient agrees to cease use and distribution of the Program as soon as reasonably practicable. However, Recipient's obligations under this Agreement and any licenses granted by Recipient relating to the Program shall continue and survive. + +Everyone is permitted to copy and distribute copies of this Agreement, but in order to avoid inconsistency the Agreement is copyrighted and may only be modified in the following manner. The Agreement Steward reserves the right to publish new versions (including revisions) of this Agreement from time to time. No one other than the Agreement Steward has the right to modify this Agreement. The Eclipse Foundation is the initial Agreement Steward. The Eclipse Foundation may assign the responsibility to serve as the Agreement Steward to a suitable separate entity. Each new version of the Agreement will be given a distinguishing version number. The Program (including Contributions) may always be distributed subject to the version of the Agreement under which it was received. In addition, after a new version of the Agreement is published, Contributor may elect to distribute the Program (including its Contributions) under the new version. Except as expressly stated in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to the intellectual property of any Contributor under this Agreement, whether expressly, by implication, estoppel or otherwise. All rights in the Program not expressly granted under this Agreement are reserved. + +This Agreement is governed by the laws of the State of New York and the intellectual property laws of the United States of America. No party to this Agreement will bring a legal action under this Agreement more than one year after the cause of action arose. Each party waives its rights to a jury trial in any resulting litigation. diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build.sh b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build.sh new file mode 100755 index 0000000000..e4bd19a937 --- /dev/null +++ b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build.sh @@ -0,0 +1,251 @@ +#!/bin/bash +export PATH=/home/jenkins/jdk/bin/:$PATH + + +# Get the Eclipse launcher and build script to use +set -x +set -e + +TRUNK_HOME=$(cd $(pwd)/../../ ; pwd) +#gives you the posibility to overwrite eclipse, if you do not use URL +[ -n "${ECLIPSE_HOME}" ] || { echo "using default ECLIPSE_HOME=${TRUNK_HOME}/eclipse"; ECLIPSE_HOME=${TRUNK_HOME}/eclipse; } + + +BUILD_RELEASE_ID_PREFIX=Linux_SGX_1.5 + +if [ "$RELEASE_ID" != "${RELEASE_ID%$BUILD_RELEASE_ID_PREFIX*}" ]; then + echo "$BUILD_RELEASE_ID_PREFIX IS in $RELEASE_ID, so it is an triggered build. Change the RELEASE_ID to an accepted form." + temp=${RELEASE_ID#$BUILD_RELEASE_ID_PREFIX} + RELEASE_ID=v`echo ${temp} | tr -d _ | tr -d -` +else + echo "$BUILD_RELEASE_ID_PREFIX is NOT in $RELEASE_ID. Keeping the user specified RELEASE_ID." +fi + +function main() { + validate-jenkins-parameters + cleanupPreBuild + checkEnvironment + buildPlugin + archivePlugin +} + +function validate-jenkins-parameters { + validate-parameter "DELETE_CURRENT_ECLIPSE" "$DELETE_CURRENT_ECLIPSE" + [[ "ECLIPSE_DOWNLOAD_URL" != "" ]] && + echo "[WARNING] ECLIPSE_DOWNLOAD_URL is not set; assume eclipse archive is already downloaded" +} + +function validate-parameter { + local NAME="$1" + local VALUE="$2" + [[ ! -z "$VALUE" ]] || { + echo "Mandatory Jenkins parameter '\$$NAME' not set !" + exit 1 + } +} + +function cleanupPreBuild() { + ./clean.sh + + [[ "false" == "${DELETE_CURRENT_ECLIPSE}" ]] || { + forceRemoveEclipse + } +} + +function forceRemoveEclipse() { + pushd ${TRUNK_HOME} + rm -fr eclipse + popd +} + +function checkEnvironment() { + if [ ! -d "${ECLIPSE_HOME}" ]; then + echo "Eclipse does not exist" + echo "Downloading eclipse" + + getEclipse + fi + + if [ -z "$RELEASE_ID" ]; then + echo "Mandatory variable RELEASE_ID not defined; exiting" + exit + fi +} + +function getEclipse() { + local eclipseArchiveURL="${ECLIPSE_DOWNLOAD_URL}" + + pushd $TRUNK_HOME + cleanupEclipseArchive + downloadEclipse "${eclipseArchiveURL}" + unzipEclipse + installPDE + cleanupEclipseArchive + popd +} + +function cleanupEclipseArchive() { + find . -maxdepth 1 -mindepth 1 -name "*eclipse*.zip*" | xargs rm -f +} + +function downloadEclipse() { + local URL="$1" + if [[ "$1" != "" ]] ; then + echo " wget --no-proxy "$1"" + wget --no-proxy "$1" + else + echo "skip downloaded empty url" + fi + +} + +function unzipEclipse() { + pwd + rm -fr eclipse + local eclipseArchiveName="$(find . -maxdepth 1 -mindepth 1 -name "*eclipse*.zip*")" + unzip "${eclipseArchiveName}" + + [[ -d eclipse ]] || { + echo "Eclipse directory does not exist!" + exit + } + +# local eclipseFolderName=${eclipseArchiveName%.zip} +# local eclipseArchiveName="eclipse" +# mv "${eclipseFolderName}" eclipse +} + +function installPDE() { +echo "~~~~>" +pwd +${ECLIPSE_HOME}/eclipse -nosplash \ + -application org.eclipse.equinox.p2.director \ + -repository http://download.eclipse.org/eclipse/updates/4.4 \ + -destination ${ECLIPSE_HOME} \ + -installIU org.eclipse.pde.source.feature.group \ + -installIU org.eclipse.pde.feature.group +} + +function preBuild() { + local BUILDDIR="$1" + local BUILDDIRWORK="$2" + + local SITEFILE="$BUILDDIRWORK/sites/site.xml" + local FEATUREDIR="$BUILDDIRWORK/features" + local FEATUREFILE="feature.xml" + local PLUGINDIR="$BUILDDIRWORK/plugins" + local PLUGINFILE="META-INF/MANIFEST.MF" + + local ROOTDIR=$(dirname "$0")"/.." + local VERSION=$(awk '/STRFILEVER/ {print $3}' ${ROOTDIR}/common/inc/internal/se_version.h|sed 's/^\"\(.*\)\"$/\1/') + VERSION=$(echo "$VERSION" | awk -F'.' '{for(i=1; i<=NF&&i<=3; i++) if(i==1){version=$i} else{version=version"."$i}}; END{print version}') + + if [[ "$VERSION" =~ ^[0-9]{1,}(.[0-9]{1,}){2}$ ]]; then + rm -fr "$BUILDDIRWORK" + cp -fr "$BUILDDIR" "$BUILDDIRWORK" + + #site.xml + sed -i "s#[0-9]\{1,\}\(\.[0-9]\{1,\}\)\{0,2\}\.qualifier#$VERSION\.qualifier#g" "$SITEFILE" + + #feature + for DIR in $(ls "$FEATUREDIR"); do + sed -i "s#[0-9]\{1,\}\(\.[0-9]\{1,\}\)\{0,2\}\.qualifier#$VERSION\.qualifier#g" "$FEATUREDIR/$DIR/$FEATUREFILE" + done + + #plugin + for DIR in $(ls "$PLUGINDIR"); do + sed -i "s#[0-9]\{1,\}\(\.[0-9]\{1,\}\)\{0,2\}\.qualifier#$VERSION\.qualifier#g" "$PLUGINDIR/$DIR/$PLUGINFILE" + done + fi +} + +function postBuild() { + local BUILDDIR="$1" + local BUILDDIRWORK="$2" + local UPDATESITEDIR="updatesite" + + if [[ -d "$BUILDDIRWORK" ]] && [[ -d "$BUILDDIRWORK/$UPDATESITEDIR" ]]; then + rm -fr "$BUILDDIR/$UPDATESITEDIR" + cp -fr "$BUILDDIRWORK/$UPDATESITEDIR" "$BUILDDIR/$UPDATESITEDIR" + rm -fr "$BUILDDIRWORK" + fi +} + +function buildPlugin() { + pwd + + echo "PWD=`pwd`" + echo "ECLIPSE_HOME=$ECLIPSE_HOME" + + #BASELOCATION="$PWD/target_platform" + BASELOCATION="$ECLIPSE_HOME" + BUILDVERSION="$RELEASE_ID" + BUILDDIR="$PWD/build_directory" + BUILDDIRWORK="$PWD/.build_directory" + BUILDCONFIG="$PWD/build_config" + LAUNCHER=`findFirst "$ECLIPSE_HOME"/plugins/org.eclipse.equinox.launcher_*.jar` + BUILDFILE=`findFirst "$ECLIPSE_HOME"/plugins/org.eclipse.pde.build_*/scripts/build.xml` + + # make sure we found valid files + if [ ! -f "$LAUNCHER" ]; then + echo "Installation Error: Eclipse plugin org.eclipse.equinox.launcher...jar not detected. " \ + "Found '$LAUNCHER'. Aborting." + exit 1 + fi + if [ ! -f "$BUILDFILE" ]; then + echo "Installation Error: Eclipse build file org.eclipse.pde.build_.../scripts/build.xml " \ + "not detected. Found '$BUILDFILE'. Aborting." + exit 1 + fi + + preBuild "$BUILDDIR" "$BUILDDIRWORK" + + # + # -- Print configuration used and actually execute the build -- + # + echo "Eclipse configuration found:" + echo " Eclipse Home: $ECLIPSE_HOME" + echo " Launcher: $LAUNCHER" + echo " Build File: $BUILDFILE" + echo " Build Config: $BUILDCONFIG" + echo " Base Location: $BASELOCATION" + echo " Build Directory: $BUILDDIRWORK" + echo " Build Version: $BUILDVERSION" + echo " Java: " $(which java) + java -version + +# CURRENT_DIR=$(pwd) +# ${ECLIPSE_HOME}/eclipse -application org.eclipse.equinox.p2.publisher.FeaturesAndBundlesPublisher -metadataRepository file:/${CURRENT_DIR}/build_directory/updatesite/sgx-eclipse-plugin -artifactRepository file:/${CURRENT_DIR}/build_directory/updatesite/featuresAndBundles -source ${CURRENT_DIR}/build_directory/ -config gtk.linux.x86 -compress -publishArtifacts +# cp ./build_directory/updatesite/featuresAndBundles/artifacts.jar ./build_directory/updatesite/sgx-eclipse-plugin/ + + java \ + -jar $LAUNCHER \ + -application org.eclipse.ant.core.antRunner \ + -buildfile $BUILDFILE \ + -DbuildDirectory=$BUILDDIRWORK \ + -DbaseLocation=$BASELOCATION \ + -Dbuilder=$BUILDCONFIG \ + -DforceContextQualifier=$BUILDVERSION \ + -v -v -v -v + + postBuild "$BUILDDIR" "$BUILDDIRWORK" +} + +function findFirst() { + echo "enter Find First, $@" 1>&2 + for i in "$@"; do + if [ -f "$i" ]; then + echo "found $i" 1>&2 + echo "$i" + return + fi + done +} + +function archivePlugin() { + pushd build_directory/updatesite/sgx-eclipse-plugin + zip -r Intel-sgx-eclipse-plugin.zip * + popd +} + +main diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_config/allElements.xml b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_config/allElements.xml new file mode 100644 index 0000000000..0bb5016556 --- /dev/null +++ b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_config/allElements.xml @@ -0,0 +1,52 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_config/build.properties b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_config/build.properties new file mode 100644 index 0000000000..beda7eaf99 --- /dev/null +++ b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_config/build.properties @@ -0,0 +1,307 @@ + +############################################################################### +# Copyright (c) 2003, 2011 IBM Corporation and others. +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Eclipse Public License v1.0 +# which accompanies this distribution, and is available at +# http://www.eclipse.org/legal/epl-v10.html +# +# Contributors: +# IBM Corporation - initial API and implementation +# Compuware Corporation - Sebastien Angers +# - Enabled additional mirror slicingOptions in Headless PDE Build +# - Enabled 'raw' attribute for mirror step in Headless PDE Build +# - https://bugs.eclipse.org/338878 +############################################################################### +##################### +# Parameters describing how and where to execute the build. +# Typical users need only update the following properties: +# baseLocation - where things you are building against are installed +# bootclasspath - The base jars to compile against (typicaly rt.jar) +# configs - the list of {os, ws, arch} configurations to build. +# +# Of course any of the settings here can be overridden by spec'ing +# them on the command line (e.g., -DbaseLocation=d:/eclipse + +#The type of the top level element we are building, generally "feature" +topLevelElementType = feature +#The id of the top level element we are building +# the following feature will not be include in the final archive +topLevelElementId = com.intel.sgx.build.driver + +############# PRODUCT/PACKAGING CONTROL ############# +#product=/plugin or feature id/path/to/.product +#product=com.intel.sgx.feature +runPackager=false + +#Set the name of the archive that will result from the product build. +#archiveNamePrefix= + +# The prefix that will be used in the generated archive. +archivePrefix=sgx-eclipse-plugin + +# The location underwhich all of the build output will be collected. +collectingFolder=${archivePrefix} + +# The list of {os, ws, arch} configurations to build. This +# value is a '&' separated list of ',' separate triples. For example, +# configs=win32,win32,x86 & linux,motif,x86 +# By default the value is *,*,* +configs = *, *, * +#configs=win32, win32, x86 & \ +# win32,win32,x86_64 & \ +# win32,win32,wpf & \ +# linux, gtk, ppc & \ +# linux, gtk, x86 & \ +# linux, gtk, x86_64 & \ +# linux, motif, x86 & \ +# solaris, motif, sparc & \ +# solaris, gtk, sparc & \ +# aix, motif, ppc & \ +# hpux, motif, ia64_32 & \ +# macosx, carbon, ppc & \ +# macosx, carbon, x86 & \ +# macosx, cocoa, ppc & \ +# macosx, cocoa, x86 & \ +# macosx, cocoa, x86_64 + +# By default PDE creates one archive (result) per entry listed in the configs property. +# Setting this value to true will cause PDE to only create one output containing all +# artifacts for all the platforms listed in the configs property. +# To control the output format for the group, add a "group, group, group - " entry to the +# archivesFormat. +#groupConfigurations=true + +#The format of the archive. By default a zip is created using antZip. +#The list can only contain the configuration for which the desired format is different than zip. +#archivesFormat=win32, win32, x86 - antZip& \ +# linux, gtk, ppc - antZip &\ +# linux, gtk, x86 - antZip& \ +# linux, gtk, x86_64 - antZip& \ +# linux, motif, x86 - antZip& \ +# solaris, motif, sparc - antZip& \ +# solaris, gtk, sparc - antZip& \ +# aix, motif, ppc - antZip& \ +# hpux, motif, PA_RISC - antZip& \ +# macosx, carbon, ppc - antZip + +#Allow cycles involving at most one bundle that needs to be compiled with the rest being binary bundles. +allowBinaryCycles = true + +#Sort bundles depenedencies across all features instead of just within a given feature. +#flattenDependencies = true + +#Parallel compilation, requires flattenedDependencies=true +#parallelCompilation=true +#parallelThreadCount= +#parallelThreadsPerProcessor= + +#Set to true if you want the output to be ready for an update jar (no site.xml generated) +outputUpdateJars = true + +#Set to true for Jnlp generation +#codebase should be a URL that will be used as the root of all relative URLs in the output. +#generateJnlp=false +#jnlp.codebase= +#jnlp.j2se= +#jnlp.locale= +#jnlp.generateOfflineAllowed=true or false generate attribute in the generated features +#jnlp.configs=${configs} #uncomment to filter the content of the generated jnlp files based on the configuration being built + +#Set to true if you want to sign jars +#signJars=false +#sign.alias= +#sign.keystore= +#sign.storepass= +#sign.keypass= + +#Arguments to send to the zip executable +zipargs= + +#Arguments to send to the tar executable +tarargs= + +#individualSourceBundles=true + +#Control the creation of a file containing the version included in each configuration - on by default +#generateVersionsLists=false + +############ REPO MIRROR OPTIONS CONTROL ############ +# Default values for the slicingOptions and raw attribute of the p2.mirror Ant target used to generate the p2 repo (buildRepo) +# Note that the default values used by PDE/Build are different from the default values for p2.mirror's slicingOptions and raw attribute +# See http://help.eclipse.org/topic//org.eclipse.platform.doc.isv/guide/p2_repositorytasks.htm for the details +# of each setting. +#p2.mirror.slicing.filter= +#p2.mirror.slicing.followOnlyFilteredRequirements=false +#p2.mirror.slicing.followStrict=false +#p2.mirror.slicing.includeFeatures=true +#p2.mirror.slicing.includeNonGreedy=false +#p2.mirror.slicing.includeOptional=true +#p2.mirror.slicing.platformFilter= +#p2.mirror.slicing.latestVersionOnly=false + +#p2.mirror.raw=false + +############## SOURCE BUNDLE CONTROL ################ +# Set this property to have source bundles created and output into build repository. +# This does NOT put them in the build output (e.g., product) itself. +# Valid values are: not set, built, all. +# built = only source for bundles that are actually built/compiled in this run are output +# all = all available source is collected and output +#sourceBundleMode=all + +# When outputting autogenerated source bundles a feature is created to contain all the automatic +# source bundles. Typically this feature is not needed and can be ignored. As such, it is given a default +# name and version. These properties can be used to override the defaults. +# sourceBundleTemplateFeature - can specify an existing feature which will be augmented to form the generated source feature +# sourceBundleFeatureId - will be the id of generated source feature which contains all the generated source bundles, default value +# is sourceBundleTemplateFeature + ".source" if sourceBundleTemplateFeature is specified +#sourceBundleTemplateFeature= +#sourceBundleFeatureId= +#sourceBundleFeatureVersion= + +############## BUILD NAMING CONTROL ################ +# The directory into which the build elements are fetched and where +# the build takes place. +#buildDirectory= + +# Type of build. Used in naming the build output. Typically this value is +# one of I, N, M, S, ... +buildType=build + +# ID of the build. Used in naming the build output. +buildId=${forceContextQualifier} + +# Label for the build. Used in naming the build output +buildLabel=${buildId} + +# Timestamp for the build. Used in naming the build output +timestamp=007 + +#The value to be used for the qualifier of a plugin or feature when you want to override the value computed by pde. +#The value will only be applied to plugin or features indicating build.properties, qualifier = context +#forceContextQualifier= + +#Enable / disable the generation of a suffix for the features that use .qualifier. +#The generated suffix is computed according to the content of the feature +#generateFeatureVersionSuffix=true + +############# BASE CONTROL ############# +# Settings for the base Eclipse components and Java class libraries +# against which you are building. +# Base location for anything the build needs to compile against. For example, +# in most RCP app or a plug-in, the baseLocation should be the location of a previously +# installed Eclipse against which the application or plug-in code will be compiled and the RCP delta pack. + +base= +#baseLocation= + +#Folder containing repositories whose content is needed to compile against +#repoBaseLocation=${base}/repos +#Folder where the content of the repositories from ${repoBaseLocation} will be made available as a form suitable to be compiled against +#transformedRepoLocation=${base}/transformedRepos + +#Os/Ws/Arch/nl of the eclipse specified by baseLocation +baseos=win32 +basews=win32 +basearch=x86 + +#this property indicates whether you want the set of plug-ins and features to be considered during the build to be limited to the ones reachable from the features / plugins being built +filteredDependencyCheck=false + +#this property indicates whether the resolution should be done in development mode (i.e. ignore multiple bundles with singletons) +resolution.devMode=false + +#pluginPath is a list of locations in which to find plugins and features. This list is separated by the platform file separator (; or :) +#a location is one of: +#- the location of the jar or folder that is the plugin or feature : /path/to/foo.jar or /path/to/foo +#- a directory that contains a /plugins or /features subdirectory +#- the location of a feature.xml, or for 2.1 style plugins, the plugin.xml or fragment.xml +#pluginPath= + +skipBase=true +eclipseURL= +eclipseBuildId= +eclipseBaseURL=${eclipseURL}/eclipse-platform-${eclipseBuildId}-win32.zip + + +############# MAP FILE CONTROL ################ +# This section defines CVS tags to use when fetching the map files from the repository. +# If you want to fetch the map file from repository / location, change the getMapFiles target in the customTargets.xml + +skipMaps=true +mapsRepo=:pserver:anonymous@example.com/path/to/repo +mapsRoot=path/to/maps +mapsCheckoutTag=HEAD + +#tagMaps=true +mapsTagTag=v${buildId} + + +############ REPOSITORY CONTROL ############### +# This section defines properties parameterizing the repositories where plugins, fragments +# bundles and features are being obtained from. + +# The tags to use when fetching elements to build. +# By default thebuilder will use whatever is in the maps. +# This value takes the form of a comma separated list of repository identifier (like used in the map files) and the +# overriding value +# For example fetchTag=CVS=HEAD, SVN=v20050101 +# fetchTag=HEAD +skipFetch=true + + +############# JAVA COMPILER OPTIONS ############## +# The location of the Java jars to compile against. Typically the rt.jar for your JDK/JRE +#bootclasspath=${java.home}/lib/rt.jar + +# specific JRE locations to compile against. These values are used to compile bundles specifying a +# Bundle-RequiredExecutionEnvironment. Uncomment and set values for environments that you support +#CDC-1.0/Foundation-1.0= /path/to/rt.jar +#CDC-1.1/Foundation-1.1= +#OSGi/Minimum-1.0= +#OSGi/Minimum-1.1= +#JRE-1.1= +#J2SE-1.2= +#J2SE-1.3= +#J2SE-1.4= +#J2SE-1.5= +#JavaSE-1.6= +#PersonalJava-1.1= +#PersonalJava-1.2= +#CDC-1.0/PersonalBasis-1.0= +#CDC-1.0/PersonalJava-1.0= +#CDC-1.1/PersonalBasis-1.1= +#CDC-1.1/PersonalJava-1.1= + +# Specify the output format of the compiler log when eclipse jdt is used +logExtension=.log + +# Whether or not to include debug info in the output jars +javacDebugInfo=false + +# Whether or not to fail the build if there are compiler errors +javacFailOnError=true + +# Enable or disable verbose mode of the compiler +javacVerbose=true + +# Extra arguments for the compiler. These are specific to the java compiler being used. +#compilerArg= + +# Default value for the version of the source code. This value is used when compiling plug-ins that do not set the Bundle-RequiredExecutionEnvironment or set javacSource in build.properties +javacSource=1.6 + +# Default value for the version of the byte code targeted. This value is used when compiling plug-ins that do not set the Bundle-RequiredExecutionEnvironment or set javacTarget in build.properties. +javacTarget=1.6 + +################### CUSTOM PROPERTIES ####################################### +# repository location for update site +# comment out - this is passed in from command line +updateSiteSource=${buildDirectory}/sites +# where to place update site build +#updateSiteRoot=${user.home}/www/no_crawl/ +updateSiteRoot=${buildDirectory}/updatesite +updateSiteFolder=${archivePrefix} +updateSiteDestination=${updateSiteRoot}/${updateSiteFolder} + diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_config/buildUpdateSite.xml b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_config/buildUpdateSite.xml new file mode 100644 index 0000000000..a01006f811 --- /dev/null +++ b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_config/buildUpdateSite.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_config/customAssembly.xml b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_config/customAssembly.xml new file mode 100644 index 0000000000..ebe2861da3 --- /dev/null +++ b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_config/customAssembly.xml @@ -0,0 +1,66 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_config/customTargets.xml b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_config/customTargets.xml new file mode 100644 index 0000000000..0a7316b142 --- /dev/null +++ b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_config/customTargets.xml @@ -0,0 +1,208 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/features/com.intel.sgx.feature/.project b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/features/com.intel.sgx.feature/.project new file mode 100644 index 0000000000..2320c4af2d --- /dev/null +++ b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/features/com.intel.sgx.feature/.project @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + com.intel.sgx.feature + + + + + + org.eclipse.pde.FeatureBuilder + + + + + + org.eclipse.pde.FeatureNature + + diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/features/com.intel.sgx.feature/build.properties b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/features/com.intel.sgx.feature/build.properties new file mode 100644 index 0000000000..6fe048450c --- /dev/null +++ b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/features/com.intel.sgx.feature/build.properties @@ -0,0 +1,15 @@ +######################################################################### +# Copyright (c) 2016 Intel Corporation. # +# # +# All rights reserved. This program and the accompanying materials # +# are made available under the terms of the Eclipse Public License v1.0 # +# which accompanies this distribution, and is available at # +# http://www.eclipse.org/legal/epl-v10.html # +# # +# Contributors: # +# Intel Corporation - initial implementation and documentation # +######################################################################### + +bin.includes = feature.xml,\ + build.properties +generate.plugin@com.intel.sgx.source = com.intel.sgx.feature diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/features/com.intel.sgx.feature/feature.xml b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/features/com.intel.sgx.feature/feature.xml new file mode 100644 index 0000000000..f9047a713e --- /dev/null +++ b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/features/com.intel.sgx.feature/feature.xml @@ -0,0 +1,145 @@ + + + + + + + + + + + + + + + + The Software Guard Extensions Plug-in enables Independent Service +Vendors in developing Linux applications +with Software Guard Extensions. The Plug-in extends the C/C++ Development +tools Plug-in to allow ISVs develop secure extensions in C or +C++. The Plug-in also allows conversion of an Linux Application +project into an Linux Application project with Software Guard +Extensions. +Using the Plug-in features and SGX Plug-in Menu options, a developer +can modify the Signing keys and Enclave Configuration for an +Enclave project and can add enclaves inside a project with SGX Nature. +Once development is complete, the developer can build the Enclave +and the Linux project using the SGX SDK for Linux with Release/Debug Configurations in Simulation/Hardware +mode and Hardware Prerelease mode. + + + + All rights reserved with Intel Corporation and its Licensors. + + + + Eclipse Public License - v 1.0 + +THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. + +1. DEFINITIONS + +"Contribution" means: + +a) in the case of the initial Contributor, the initial code and documentation distributed under this Agreement, and +b) in the case of each subsequent Contributor: +i) changes to the Program, and +ii) additions to the Program; +where such changes and/or additions to the Program originate from and are distributed by that particular Contributor. A Contribution 'originates' from a Contributor if it was added to the Program by such Contributor itself or anyone acting on such Contributor's behalf. Contributions do not include additions to the Program which: (i) are separate modules of software distributed in conjunction with the Program under their own license agreement, and (ii) are not derivative works of the Program. +"Contributor" means any person or entity that distributes the Program. + +"Licensed Patents" mean patent claims licensable by a Contributor which are necessarily infringed by the use or sale of its Contribution alone or when combined with the Program. + +"Program" means the Contributions distributed in accordance with this Agreement. + +"Recipient" means anyone who receives the Program under this Agreement, including all Contributors. + +2. GRANT OF RIGHTS + +a) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, distribute and sublicense the Contribution of such Contributor, if any, and such derivative works, in source code and object code form. +b) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed Patents to make, use, sell, offer to sell, import and otherwise transfer the Contribution of such Contributor, if any, in source code and object code form. This patent license shall apply to the combination of the Contribution and the Program if, at the time the Contribution is added by the Contributor, such addition of the Contribution causes such combination to be covered by the Licensed Patents. The patent license shall not apply to any other combinations which include the Contribution. No hardware per se is licensed hereunder. +c) Recipient understands that although each Contributor grants the licenses to its Contributions set forth herein, no assurances are provided by any Contributor that the Program does not infringe the patent or other intellectual property rights of any other entity. Each Contributor disclaims any liability to Recipient for claims brought by any other entity based on infringement of intellectual property rights or otherwise. As a condition to exercising the rights and licenses granted hereunder, each Recipient hereby assumes sole responsibility to secure any other intellectual property rights needed, if any. For example, if a third party patent license is required to allow Recipient to distribute the Program, it is Recipient's responsibility to acquire that license before distributing the Program. +d) Each Contributor represents that to its knowledge it has sufficient copyright rights in its Contribution, if any, to grant the copyright license set forth in this Agreement. +3. REQUIREMENTS + +A Contributor may choose to distribute the Program in object code form under its own license agreement, provided that: + +a) it complies with the terms and conditions of this Agreement; and +b) its license agreement: +i) effectively disclaims on behalf of all Contributors all warranties and conditions, express and implied, including warranties or conditions of title and non-infringement, and implied warranties or conditions of merchantability and fitness for a particular purpose; +ii) effectively excludes on behalf of all Contributors all liability for damages, including direct, indirect, special, incidental and consequential damages, such as lost profits; +iii) states that any provisions which differ from this Agreement are offered by that Contributor alone and not by any other party; and +iv) states that source code for the Program is available from such Contributor, and informs licensees how to obtain it in a reasonable manner on or through a medium customarily used for software exchange. +When the Program is made available in source code form: + +a) it must be made available under this Agreement; and +b) a copy of this Agreement must be included with each copy of the Program. +Contributors may not remove or alter any copyright notices contained within the Program. + +Each Contributor must identify itself as the originator of its Contribution, if any, in a manner that reasonably allows subsequent Recipients to identify the originator of the Contribution. + +4. COMMERCIAL DISTRIBUTION + +Commercial distributors of software may accept certain responsibilities with respect to end users, business partners and the like. While this license is intended to facilitate the commercial use of the Program, the Contributor who includes the Program in a commercial product offering should do so in a manner which does not create potential liability for other Contributors. Therefore, if a Contributor includes the Program in a commercial product offering, such Contributor ("Commercial Contributor") hereby agrees to defend and indemnify every other Contributor ("Indemnified Contributor") against any losses, damages and costs (collectively "Losses") arising from claims, lawsuits and other legal actions brought by a third party against the Indemnified Contributor to the extent caused by the acts or omissions of such Commercial Contributor in connection with its distribution of the Program in a commercial product offering. The obligations in this section do not apply to any claims or Losses relating to any actual or alleged intellectual property infringement. In order to qualify, an Indemnified Contributor must: a) promptly notify the Commercial Contributor in writing of such claim, and b) allow the Commercial Contributor to control, and cooperate with the Commercial Contributor in, the defense and any related settlement negotiations. The Indemnified Contributor may participate in any such claim at its own expense. + +For example, a Contributor might include the Program in a commercial product offering, Product X. That Contributor is then a Commercial Contributor. If that Commercial Contributor then makes performance claims, or offers warranties related to Product X, those performance claims and warranties are such Commercial Contributor's responsibility alone. Under this section, the Commercial Contributor would have to defend claims against the other Contributors related to those performance claims and warranties, and if a court requires any other Contributor to pay any damages as a result, the Commercial Contributor must pay those damages. + +5. NO WARRANTY + +EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the appropriateness of using and distributing the Program and assumes all risks associated with its exercise of rights under this Agreement , including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and unavailability or interruption of operations. + +6. DISCLAIMER OF LIABILITY + +EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + +7. GENERAL + +If any provision of this Agreement is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this Agreement, and without further action by the parties hereto, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable. + +If Recipient institutes patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Program itself (excluding combinations of the Program with other software or hardware) infringes such Recipient's patent(s), then such Recipient's rights granted under Section 2(b) shall terminate as of the date such litigation is filed. + +All Recipient's rights under this Agreement shall terminate if it fails to comply with any of the material terms or conditions of this Agreement and does not cure such failure in a reasonable period of time after becoming aware of such noncompliance. If all Recipient's rights under this Agreement terminate, Recipient agrees to cease use and distribution of the Program as soon as reasonably practicable. However, Recipient's obligations under this Agreement and any licenses granted by Recipient relating to the Program shall continue and survive. + +Everyone is permitted to copy and distribute copies of this Agreement, but in order to avoid inconsistency the Agreement is copyrighted and may only be modified in the following manner. The Agreement Steward reserves the right to publish new versions (including revisions) of this Agreement from time to time. No one other than the Agreement Steward has the right to modify this Agreement. The Eclipse Foundation is the initial Agreement Steward. The Eclipse Foundation may assign the responsibility to serve as the Agreement Steward to a suitable separate entity. Each new version of the Agreement will be given a distinguishing version number. The Program (including Contributions) may always be distributed subject to the version of the Agreement under which it was received. In addition, after a new version of the Agreement is published, Contributor may elect to distribute the Program (including its Contributions) under the new version. Except as expressly stated in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to the intellectual property of any Contributor under this Agreement, whether expressly, by implication, estoppel or otherwise. All rights in the Program not expressly granted under this Agreement are reserved. + +This Agreement is governed by the laws of the State of New York and the intellectual property laws of the United States of America. No party to this Agreement will bring a legal action under this Agreement more than one year after the cause of action arose. Each party waives its rights to a jury trial in any resulting litigation. + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx.userguide/.classpath b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx.userguide/.classpath new file mode 100644 index 0000000000..791c66decf --- /dev/null +++ b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx.userguide/.classpath @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx.userguide/.project b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx.userguide/.project new file mode 100644 index 0000000000..76c2e17b70 --- /dev/null +++ b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx.userguide/.project @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + com.intel.sgx.userguide + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + + org.eclipse.pde.PluginNature + org.eclipse.jdt.core.javanature + + diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx.userguide/META-INF/MANIFEST.MF b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx.userguide/META-INF/MANIFEST.MF new file mode 100644 index 0000000000..5db6ad6bff --- /dev/null +++ b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx.userguide/META-INF/MANIFEST.MF @@ -0,0 +1,11 @@ +License: Eclipse Public License Version 1.0 ("EPL") +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: SGX Eclipse Plugin Userguide +Bundle-SymbolicName: com.intel.sgx.userguide;singleton:=true +Bundle-Version: 1.0.1.qualifier +Bundle-Activator: com.intel.sgx.userguide.Activator +Bundle-Vendor: INTEL +Require-Bundle: org.eclipse.ui, + org.eclipse.core.runtime +Bundle-ActivationPolicy: lazy diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx.userguide/build.properties b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx.userguide/build.properties new file mode 100644 index 0000000000..b148cda4b4 --- /dev/null +++ b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx.userguide/build.properties @@ -0,0 +1,19 @@ +######################################################################### +# Copyright (c) 2016 Intel Corporation. # +# # +# All rights reserved. This program and the accompanying materials # +# are made available under the terms of the Eclipse Public License v1.0 # +# which accompanies this distribution, and is available at # +# http://www.eclipse.org/legal/epl-v10.html # +# # +# Contributors: # +# Intel Corporation - initial implementation and documentation # +######################################################################### + +source.. = src/ +output.. = bin/ +bin.includes = plugin.xml,\ + META-INF/,\ + .,\ + html/,\ + *.xml diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx.userguide/html/Resources/Images/A_Generated_Trusted_Library.png b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx.userguide/html/Resources/Images/A_Generated_Trusted_Library.png new file mode 100644 index 0000000000..d6cb5308c4 Binary files /dev/null and b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx.userguide/html/Resources/Images/A_Generated_Trusted_Library.png differ diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx.userguide/html/Resources/Images/Add_New_Intel_SGX_Enclave_Dialog.png b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx.userguide/html/Resources/Images/Add_New_Intel_SGX_Enclave_Dialog.png new file mode 100644 index 0000000000..c857d80377 Binary files /dev/null and b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx.userguide/html/Resources/Images/Add_New_Intel_SGX_Enclave_Dialog.png differ diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx.userguide/html/Resources/Images/Add_New_SGX_Static_Trusted_Library_Dialog.png b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx.userguide/html/Resources/Images/Add_New_SGX_Static_Trusted_Library_Dialog.png new file mode 100644 index 0000000000..8fd22a4260 Binary files /dev/null and b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx.userguide/html/Resources/Images/Add_New_SGX_Static_Trusted_Library_Dialog.png differ diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx.userguide/html/Resources/Images/Add_Repository_Dialog.png b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx.userguide/html/Resources/Images/Add_Repository_Dialog.png new file mode 100644 index 0000000000..3d5dd178e5 Binary files /dev/null and b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx.userguide/html/Resources/Images/Add_Repository_Dialog.png differ diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx.userguide/html/Resources/Images/Add_SGX_Nature.png b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx.userguide/html/Resources/Images/Add_SGX_Nature.png new file mode 100644 index 0000000000..d6dbf14a6d Binary files /dev/null and b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx.userguide/html/Resources/Images/Add_SGX_Nature.png differ diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx.userguide/html/Resources/Images/Add_SGX_Untrusted_Module.png b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx.userguide/html/Resources/Images/Add_SGX_Untrusted_Module.png new file mode 100644 index 0000000000..deec5090e3 Binary files /dev/null and b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx.userguide/html/Resources/Images/Add_SGX_Untrusted_Module.png differ diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx.userguide/html/Resources/Images/Configurations_Specific_to_Intel_SGX_Technology.png b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx.userguide/html/Resources/Images/Configurations_Specific_to_Intel_SGX_Technology.png new file mode 100644 index 0000000000..f36ca69c05 Binary files /dev/null and b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx.userguide/html/Resources/Images/Configurations_Specific_to_Intel_SGX_Technology.png differ diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx.userguide/html/Resources/Images/Configure_SGX_Hardware_Release_Mode.png b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx.userguide/html/Resources/Images/Configure_SGX_Hardware_Release_Mode.png new file mode 100644 index 0000000000..f7151654d0 Binary files /dev/null and b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx.userguide/html/Resources/Images/Configure_SGX_Hardware_Release_Mode.png differ diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx.userguide/html/Resources/Images/Copying_the_Untrusted_Module_to_a_Project.png b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx.userguide/html/Resources/Images/Copying_the_Untrusted_Module_to_a_Project.png new file mode 100644 index 0000000000..fb363ea78d Binary files /dev/null and b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx.userguide/html/Resources/Images/Copying_the_Untrusted_Module_to_a_Project.png differ diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx.userguide/html/Resources/Images/Customization_of_SGX_build_command.png b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx.userguide/html/Resources/Images/Customization_of_SGX_build_command.png new file mode 100644 index 0000000000..a9c509501b Binary files /dev/null and b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx.userguide/html/Resources/Images/Customization_of_SGX_build_command.png differ diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx.userguide/html/Resources/Images/Down_Arrow_Button.png b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx.userguide/html/Resources/Images/Down_Arrow_Button.png new file mode 100644 index 0000000000..fccabba54e Binary files /dev/null and b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx.userguide/html/Resources/Images/Down_Arrow_Button.png differ diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx.userguide/html/Resources/Images/Enclave_Configuration_Settings.png b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx.userguide/html/Resources/Images/Enclave_Configuration_Settings.png new file mode 100644 index 0000000000..42217bd097 Binary files /dev/null and b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx.userguide/html/Resources/Images/Enclave_Configuration_Settings.png differ diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx.userguide/html/Resources/Images/Generate_Signed_Enclave_Dialog.png b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx.userguide/html/Resources/Images/Generate_Signed_Enclave_Dialog.png new file mode 100644 index 0000000000..9eebe98c66 Binary files /dev/null and b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx.userguide/html/Resources/Images/Generate_Signed_Enclave_Dialog.png differ diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx.userguide/html/Resources/Images/Generate_Signed_Enclave_Dialog_with_Pre_configurations.png b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx.userguide/html/Resources/Images/Generate_Signed_Enclave_Dialog_with_Pre_configurations.png new file mode 100644 index 0000000000..538d68743a Binary files /dev/null and b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx.userguide/html/Resources/Images/Generate_Signed_Enclave_Dialog_with_Pre_configurations.png differ diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx.userguide/html/Resources/Images/Generated_Sample_Untrusted_Application.png b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx.userguide/html/Resources/Images/Generated_Sample_Untrusted_Application.png new file mode 100644 index 0000000000..7e7c609d61 Binary files /dev/null and b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx.userguide/html/Resources/Images/Generated_Sample_Untrusted_Application.png differ diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx.userguide/html/Resources/Images/Generated_Skeleton_for_an_Enclave.png b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx.userguide/html/Resources/Images/Generated_Skeleton_for_an_Enclave.png new file mode 100644 index 0000000000..55e27af3ab Binary files /dev/null and b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx.userguide/html/Resources/Images/Generated_Skeleton_for_an_Enclave.png differ diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx.userguide/html/Resources/Images/Generating_Hash_Completion_Dialog.png b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx.userguide/html/Resources/Images/Generating_Hash_Completion_Dialog.png new file mode 100644 index 0000000000..032c17a2ea Binary files /dev/null and b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx.userguide/html/Resources/Images/Generating_Hash_Completion_Dialog.png differ diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx.userguide/html/Resources/Images/Import_or_Re_Generate_Enclave_Signing_Key.png b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx.userguide/html/Resources/Images/Import_or_Re_Generate_Enclave_Signing_Key.png new file mode 100644 index 0000000000..d954544841 Binary files /dev/null and b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx.userguide/html/Resources/Images/Import_or_Re_Generate_Enclave_Signing_Key.png differ diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx.userguide/html/Resources/Images/Intel_SGX_Configurations.png b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx.userguide/html/Resources/Images/Intel_SGX_Configurations.png new file mode 100644 index 0000000000..f7151654d0 Binary files /dev/null and b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx.userguide/html/Resources/Images/Intel_SGX_Configurations.png differ diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx.userguide/html/Resources/Images/Intel_SGX_Tools.png b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx.userguide/html/Resources/Images/Intel_SGX_Tools.png new file mode 100644 index 0000000000..fb9ec29775 Binary files /dev/null and b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx.userguide/html/Resources/Images/Intel_SGX_Tools.png differ diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx.userguide/html/Resources/Images/Makefile_for_Intel_SGX.png b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx.userguide/html/Resources/Images/Makefile_for_Intel_SGX.png new file mode 100644 index 0000000000..466558cb4c Binary files /dev/null and b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx.userguide/html/Resources/Images/Makefile_for_Intel_SGX.png differ diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx.userguide/html/Resources/Images/New_Project.png b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx.userguide/html/Resources/Images/New_Project.png new file mode 100644 index 0000000000..f7f391f6d6 Binary files /dev/null and b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx.userguide/html/Resources/Images/New_Project.png differ diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx.userguide/html/Resources/Images/Project_Explorer.png b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx.userguide/html/Resources/Images/Project_Explorer.png new file mode 100644 index 0000000000..94913f3980 Binary files /dev/null and b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx.userguide/html/Resources/Images/Project_Explorer.png differ diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx.userguide/html/Resources/Images/Project_Menu.png b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx.userguide/html/Resources/Images/Project_Menu.png new file mode 100644 index 0000000000..659f0d92f3 Binary files /dev/null and b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx.userguide/html/Resources/Images/Project_Menu.png differ diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx.userguide/html/Resources/Images/SGX_Preference_Page.png b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx.userguide/html/Resources/Images/SGX_Preference_Page.png new file mode 100644 index 0000000000..90170646b4 Binary files /dev/null and b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx.userguide/html/Resources/Images/SGX_Preference_Page.png differ diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx.userguide/html/Resources/Images/Sample_Application.png b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx.userguide/html/Resources/Images/Sample_Application.png new file mode 100644 index 0000000000..9c25b62823 Binary files /dev/null and b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx.userguide/html/Resources/Images/Sample_Application.png differ diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx.userguide/html/Resources/Images/Select_Configuration_File.png b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx.userguide/html/Resources/Images/Select_Configuration_File.png new file mode 100644 index 0000000000..a5fb4f811b Binary files /dev/null and b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx.userguide/html/Resources/Images/Select_Configuration_File.png differ diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx.userguide/html/Resources/Images/The_Location_of_the_Plugin_zip_Archive.png b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx.userguide/html/Resources/Images/The_Location_of_the_Plugin_zip_Archive.png new file mode 100644 index 0000000000..afa17c33eb Binary files /dev/null and b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx.userguide/html/Resources/Images/The_Location_of_the_Plugin_zip_Archive.png differ diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx.userguide/html/Resources/Images/The_Result_of_Running_Samples_Generated_for_Enclaves.png b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx.userguide/html/Resources/Images/The_Result_of_Running_Samples_Generated_for_Enclaves.png new file mode 100644 index 0000000000..2f3a03acc5 Binary files /dev/null and b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx.userguide/html/Resources/Images/The_Result_of_Running_Samples_Generated_for_Enclaves.png differ diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx.userguide/html/Resources/Images/Two_StepSigne_Enclave_Generate_Hash.png b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx.userguide/html/Resources/Images/Two_StepSigne_Enclave_Generate_Hash.png new file mode 100644 index 0000000000..7b9b49b640 Binary files /dev/null and b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx.userguide/html/Resources/Images/Two_StepSigne_Enclave_Generate_Hash.png differ diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx.userguide/html/Resources/Images/Two_Step_Sign_Enclave_Menu.png b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx.userguide/html/Resources/Images/Two_Step_Sign_Enclave_Menu.png new file mode 100644 index 0000000000..374fd094fd Binary files /dev/null and b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx.userguide/html/Resources/Images/Two_Step_Sign_Enclave_Menu.png differ diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx.userguide/html/Resources/Stylesheets/intel_css_styles.css b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx.userguide/html/Resources/Stylesheets/intel_css_styles.css new file mode 100644 index 0000000000..859063f2e1 --- /dev/null +++ b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx.userguide/html/Resources/Stylesheets/intel_css_styles.css @@ -0,0 +1,470 @@ +/*************************************************************************/ +/* Copyright (c) 2016 Intel Corporation. */ +/* */ +/* All rights reserved. This program and the accompanying materials */ +/* are made available under the terms of the Eclipse Public License v1.0 */ +/* which accompanies this distribution, and is available at */ +/* http://www.eclipse.org/legal/epl-v10.html */ +/* */ +/* Contributors: */ +/* Intel Corporation - initial implementation and documentation */ +/*************************************************************************/ +/**/ + +/*begin-old-version{{*/ + +body +{ + color: #333333; + background-color: #ffffff; + font-family: "Intel Clear", Verdana, Arial, sans-serif; + margin-left: 30px; + margin-right: 30px; + margin-bottom: 7%; + color: #333333; + background-color: #ffffff; + font-family: "Intel Clear", Verdana, Arial, sans-serif; + margin-left: 30px; + margin-right: 30px; + margin-bottom: 7%; + font-size: 12pt; +} + +.RevUpdate +{ + background-color: #FFFF99; + font-weight: normal; + line-height: 100%; + background-color: #FFFF99; + font-weight: normal; + line-height: 100%; +} + +.NonStdFortran +{ + color: #007F00; + color: #007F00; +} + +body.OH_VSIP_body +{ + margin-left: 30px; + margin-left: 30px; +} + +DIV.OH_outerContent +{ + border: 0px none #FFFFFF; + border: 0px none #ffffff; +} + +h1 +{ + color: #0071c5; + font-size: 15pt; + font-weight: normal; + padding-bottom: 1px; + margin-left: 0pt; + margin-bottom: 0px; + color: #0071c5; + font-size: 15pt; + font-weight: normal; + padding-bottom: 1px; + margin-left: 0pt; + margin-bottom: 0px; +} + +h1.firsttitle +{ + font-weight: normal; + border-bottom: 0 none; + margin-left: 0; + font-size: 18pt; + border-bottom: 1px solid #0071c5; + line-height: 100%; + padding-bottom: 10px; + margin-bottom: 20px; + margin-top: 20px; + font-weight: normal; + border-bottom: 0 none; + margin-left: 0; + font-size: 18pt; + border-bottom: 1px solid #0071c5; + line-height: 100%; + padding-bottom: 10px; + margin-bottom: 20px; + margin-top: 20px; +} + +h2 +{ + color: #0071c5; + margin-top: 15pt; + margin-bottom: 5pt; + font-size: 12pt; + color: #0071c5; + margin-top: 15pt; + margin-bottom: 5pt; + font-size: 12pt; +} + +h3 +{ + color: #333333; + font-weight: bold; + margin-top: 15pt; + margin-bottom: 5pt; + font-size: 11pt; + color: #333333; + font-weight: bold; + margin-top: 15pt; + margin-bottom: 5pt; + font-size: 11pt; +} + +h4 +{ + color: #0071c5; + margin-top: 10pt; + margin-bottom: 5pt; + padding-left: 0px; + font-size: 10pt; + color: #0071c5; + margin-top: 10pt; + margin-bottom: 5pt; + padding-left: 0px; + font-size: 10pt; +} + +h5 +{ + color: #0071c5; + margin-top: 10pt; + margin-bottom: 5pt; + padding-left: 0px; + font-size: 10pt; + color: #0071c5; + margin-top: 10pt; + margin-bottom: 5pt; + padding-left: 0px; + font-size: 10pt; +} + +h6 +{ + color: #0071c5; + margin-top: 10pt; + margin-bottom: 5pt; + padding-left: 0px; + font-size: 10pt; + color: #0071c5; + margin-top: 10pt; + margin-bottom: 5pt; + padding-left: 0px; + font-size: 10pt; +} + +.relinfo +{ + padding-left: 30px; + padding-left: 30px; +} + +.tablecap +{ + color: #0071c5; +} + +caption +{ + font-weight: bold; + text-align: left; + font-weight: bold; + text-align: left; + font-size: 12pt; +} + +.figcap +{ + margin-left: 24px; + font-size: 10pt; + font-weight: bold; + text-align: center; + margin-left: 24px; + font-size: 10pt; + font-weight: bold; + text-align: center; +} + +.sectiontitle +{ + padding-left: 0px; + padding-left: 0px; +} + +.linklist +{ + padding-left: 0px; + padding-left: 0px; +} + +h1.topictitle1 +{ + color: #0071c5; + font-size: 18pt; + margin-left: 0pt; + margin-bottom: 15px; + color: #0071c5; + font-size: 18pt; + margin-left: 0pt; + margin-bottom: 15px; +} + +#header_text +{ + color: #0071C5; + text-align: right; + color: #0071C5; + text-align: right; +} + +.titlepage +{ + margin-right: 15%; + margin-right: 15%; +} + +.familylinks +{ + margin-top: 1em; + margin-top: 1em; +} + +a.start +{ + font-size: 18pt; + text-decoration: underline; + font-size: 18pt; + text-decoration: underline; +} + +a.underlined +{ + text-decoration: underline; + text-decoration: underline; +} + +.shortdesc +{ + font-size: inherit; + padding-left: inherit; + line-height: 16pt; + margin-top: 0px; + margin-bottom: 0.5em; + font-size: inherit; + padding-left: inherit; + line-height: 16pt; + margin-top: 0px; + margin-bottom: 0.5em; +} + +.shortdesc-it +{ + font-style: italic; + font-style: italic; +} + +p +{ + margin-left: 0px; + line-height: 120%; + margin-top: 0; + margin-bottom: 10px; + margin-left: 0px; + line-height: 120%; + margin-top: 0; + margin-bottom: 10px; + font-size: 12pt; +} + +.p +{ + font-size: inherit; + margin-left: 0px; + line-height: 170%; + margin-top: 0; + margin-bottom: 5pt; + padding-left: 0pt; + font-size: inherit; + margin-left: 0px; + line-height: 170%; + margin-top: 0; + margin-bottom: 5pt; + padding-left: 0pt; +} + +table +{ + margin-bottom: 5pt; + border-collapse: collapse; + margin-left: 0px; + margin-top: 0.3em; + font-size: 10pt; + margin-bottom: 5pt; + border-collapse: collapse; + margin-left: 0px; + margin-top: 0.3em; + font-size: 10pt; +} + +tr +{ + vertical-align: top; + vertical-align: top; +} + +DIV.Note +{ + margin-top: 20pt; + margin-bottom: 20pt; + margin-right: 0.46cm; + padding-left: 5px; + border-top-style: solid; + border-top-width: 1px; + border-bottom-style: solid; + border-bottom-width: 1px; + font-size: 10pt; +} + +p.NoteTipHead +{ + font-weight: bold; + font-style: italic; + margin-top: 9pt; + margin-bottom: 3pt; + line-height: 15pt; + margin-left: 0.202cm; + font-family: "Verdana", "sans-serif"; + text-transform: uppercase; + text-align: justify; + font-size: 12pt; +} + +MadCap|xref +{ + color: #0860a8; + mc-format: '{paratext}'; + text-decoration: none; + font-size: 12pt; +} + +div.NoteCont +{ + border-bottom-style: solid; + border-bottom-width: 1px; + border-top-style: solid; + border-top-width: 1px; + font-size: 10pt; +} + +p.figcap +{ + text-align: left; + font-size: 12pt; +} + +th +{ + text-align: left; + font-size: 12pt; +} + +ul +{ + font-size: 12pt; +} + +ol +{ + font-size: 12pt; +} + +li +{ + font-size: 12pt; +} + +b +{ + font-size: 12pt; +} + +code +{ + font-size: 12pt; +} + +a:link +{ + color: #0071c5; + text-decoration: none; + color: #0071c5; + text-decoration: none; +} + +a:visited +{ + color: #0071c5; + text-decoration: none; + color: #0071c5; + text-decoration: none; +} + +a:hover +{ + color: #00aeef; + text-decoration: underline; + color: #00aeef; + text-decoration: underline; +} + +a:active +{ + color: #0071c5; + text-decoration: underline; + color: #0071c5; + text-decoration: underline; +} + +a.start:visited +{ + color: #0071c5; + text-decoration: underline; + color: #0071c5; + text-decoration: underline; +} + +a.start:active +{ + color: #0071c5; + text-decoration: underline; + color: #0071c5; + text-decoration: underline; +} + +a.underlined:visited +{ + color: #0071c5; + text-decoration: underline; + color: #0071c5; + text-decoration: underline; +} + +a.underlined:active +{ + color: #0071c5; + text-decoration: underline; + color: #0071c5; + text-decoration: underline; +} + diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx.userguide/html/content.html b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx.userguide/html/content.html new file mode 100644 index 0000000000..c934419af6 --- /dev/null +++ b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx.userguide/html/content.html @@ -0,0 +1,557 @@ + + + + + + + + + +
+

Introduction

+

This Developer Guide is intended for use by Independent Service Vendors who wish to harden their Linux* applications using Intel(R) SGX Technology, code named Intel(R) Software Guard Extensions. The guide describes the procedure for installation of Intel(R) SGX Plugin for Eclipse* IDE and development of Intel(R) SGX components using the plugin. The Intel(R) SGX Plugin for Eclipse leverages on the Intel(R) Software Guard Extensions SDK, which is a collection of APIs, libraries and tools that enable you to develop, build and debug Intel(R) SGX applications in C/C++.

+

To learn more about the Intel(R) Software Guard Extensions SDK, see the Intel(R) Software Guard Extensions SDK for Linux* OS Developer Reference.

 
+
+

Introducing Intel(R) Software Guard Extensions

+

Intel(R) Software Guard Extensions is a new Intel technology, whose objective is to enable a high level of protection of secrets. It operates by allocating hardware-protected memory where code and data reside. The protected memory area within an application process is called an enclave. Data within the enclave memory can only be accessed by code that resides within that enclave. Enclave code can be invoked by special instructions.

+

An enclave can be built and loaded as a shared object.

+

Throughout this document, Intel(R) SGX refers to Intel(R) Software Guard Extensions.

+

An Intel(R) SGX application design is different from the design of non- Intel(R) SGX application as it specifies dividing the application into two logical parts:

+
    +
  • Trusted part. The code that accesses the secret resides here and it is called an enclave. More than one enclave can exist in an application.
  • +
  • Untrusted part. This includes the rest of the modules in the application, that is outside in an enclave.
  • +
+

The trusted components and untrusted components are developed as separate modules.

+

The trusted part or the enclave is implemented in C or C++. It is supplied as a collection of functions and data packaged in the form of a dynamically loaded library, a DLL in Windows* OS and a shared object in Linux* OS. It may be supplied either as a pre-built signed library or as a signed shared library built during compilation of the untrusted component.

+

Enclave functions within an enclave library are wrapped by auto-generated proxy and bridge functions that simplify the mechanism of using the Intel(R) SGX technology by developers.

+

The role of these functions is to handle the following tasks:

+
    +
  • Call an enclave function from untrusted code, also called an ECALL (enclave call).
  • +
  • Call an untrusted function from within an enclave, also called an OCALL (outside call).
  • +
  • Handle interrupts.
  • +
  • Handle exceptions.
  • +
+

The proxy and bridge functions are generated by the sgx_edger8r tool provided by Intel(R) SGX SDK. It reads an edl file (Enclave Descriptor Language) which describes the functions that form the trusted and untrusted component boundaries within the application.

+

After the enclave is built, a signed version of it is created using the tool sgx_sign also provided by Intel(R) SGX SDK. It is this signed version may be loaded and executed in the encrypted memory.

+

Enclaves may have some specific properties which are added as meta-information during the signing process. The meta-information is stored in one configuration xml file per enclave. See more details about meta-information in Intel(R) Software Guard Extensions SDK for Linux* OS Developer Reference.

+
+
+

Introducing Intel(R) Software Guard Extensions Eclipse* Plug-in

+

The Intel(R) Software Guard Extensions Eclipse* Plug-in helps the enclave developer to maintain enclaves and untrusted related code inside Eclipse* C/C++ projects. To use this support, add SGX nature to the C/C++ project. See Adding SGX Nature to a Project for details.

+

Once the SGX nature is added to a project, you will have access to the SGX commands. SGX nature adds also a folder called sgx to the root of the project, and a Makefile inside it. All resources of the project managed by Intel(R) Software Guard Extensions Eclipse Plug-inare located inside this directory. You can build and run enclaves related code using GNU* Make tool through the Makefile.

+

The plugin is generating minimal but ready-to-work code skeletons, complete with their own Makefile having all the required make targets as to call sgx_edger8r tool to generate the proxies and bridges, compile these source, generate a shared object and finally, to sign the enclave with the sgx_sign tool. This provide a starting point you may build upon.

+
+
+

Getting Started with Intel(R) Software Guard Extensions Eclipse* Plug-in

+

This section contains steps to set up your Intel(R) Software Guard Extensions Eclipse* Plug-in on a Linux* system, including necessary softwares, steps to install the product, and steps to configure your preferred product directory.

+

• Pre-requisites

+

• Installing Intel(R) Software Guard Extensions Eclipse* Plug-in

+

• Configuring Intel(R) Software Guard Extensions Eclipse* Plug-in

 
+
+

Pre-requisites

+

To use Intel(R) Software Guard Extensions Eclipse Plug-in, install the following softwares:

+
    +
  • Eclipse* Mars 1 with CDT IDE for C/C++ Developpers (version 4.5.1). To use this version, install Java* Development Kit (JDK) or Java* Runtime Environment (JRE) version 1.8 or above.
  • +
  • gcc/g++ tools
  • +
  • Openssl*
  • +
  • Intel(R) SGX SDK for Linux* OS
  • +
+
+
+

Installing Intel(R) Software Guard Extensions Eclipse* Plug-in

+

Install Intel(R) Software Guard Extensions Eclipse* Plug-in as a regular Eclipse Plugin:

+
    +
  1. Download the zip archive of Intel(R) Software Guard Extensions Eclipse Plug-in from Intel Site
  2. +
  3. +

    Go to Help menu -> Install New Software. Click the Add button for the Work with field to open the Add Repository dialog as shown in the following graphic:

    +

    + +

    +

    Add Repository Dialog

    +
  4. +
  5. +

    Enter SGX Archive in the Name field . Click the Archive... button and select the location of the downloaded archive as shown in the following graphic:

    +

    + +

    +

    The Location of the Plugin zip Archive

    +
  6. +
  7. Press OK to add the archive as a repository.
  8. +
  9. In the Install dialog, select the Software Guard Extensions Plugin check-box and proceed with the usual steps.
  10. +
+
+
+

Configuring Intel(R) Software Guard Extensions Eclipse* Plug-in

+

If you do not install Intel(R) SGX SDK for Linux* OS in the default location, you need to specify the path for Intel SGX SDK using the following steps:

+
    +
  1. +

    Go to Window menu ->Preferences. Enter SGX in the filter text field to quickly locate the SGX Preferences page.

    +

    + +

    +

    SGX Preference Page

    +
  2. +
  3. Enter the path for Intel SGX SDK for Linux OS in the SGX SDK Directory field.
  4. +
+
+
+

Command Reference

+

This topic provides the command reference for the following scenarios of using Intel(R) Software Guard Extensions Eclipse* Plug-in:

+
    +
  • Adding SGX nature to a project
  • +
  • Adding an SGX enclave
  • +
  • Adding an SGX trusted library
  • +
  • Adding an SGX untrusted module
  • +
  • Updating SGX enclave signing key
  • +
  • Updating enclave configuration files
  • +
  • Two steps sign enclave
  • +
+

All commands brought by Intel(R) Software Guard Extensions Eclipse Plug-in are available by right-clicking on the Project root in Project explorer view in menu Software Guard Extension Tools:

 

Project Explorer

 
+
+

Adding SGX Nature to a Project

+

The nature of an Eclipse project is a concept defined by an Eclipse Platform which allows a plug-in to tag a project as a specific kind of project. Intel(R) Software Guard Extensions uses an SGX nature to add SGX-specific behavior to projects. Project natures are defined by plug-ins, and are typically added or removed per-project when the user performs some action defined by the plug-in.

+

To use Intel(R) Software Guard Extensions Eclipse Plug-in in your project, you need to add SGX nature to it. You may either add SGX nature to a pre-existing C/C++ project or create a project with SGX nature from start. See Adding SGX Nature to a non-SGX project and Creating a New C/C++ Project with SGX Nature for how to complete these tasks.

+
+
+

Adding SGX Nature to a non-SGX project

+

When you have a C/C++ project created without Intel SGX, you cannot use Intel SGX support. In this case, you need to add SGX nature to this project to use Intel SGX support:

+
    +
  1. Right-click on the project root
  2. +
  3. +

    Select Software Guard Extension Tools → Add SGX Nature

    +

    + +

    +

    Add SGX Nature

    +
  4. +
+

After you add the SGX nature to your project, you should see:

+
    +
  • +

    A subdirectory sgx in the project which contains a Makefile file.

    +

    + +

    +

    Makefile for Intel(R) SGX

    +
  • +
  • +

    The Intel SGX tools as shown in the following graphic:

    +

    + +

    +

    Intel(R) SGX Tools

    +
  • +
  • +

    New configurations specific to SGX technology. You may see the configurations for the project by clicking to the down arrow of button usually found at the top of the Eclipse window:

    +

    + +

    +

    Configurations Specific to Intel(R) SGX Technology

    +
  • +
+
+
+

Creating a New C/C++ Project with SGX Nature

+

You can create a new project with SGX nature. To create such a project, follow these steps:

+
    +
  1. +

    Open a standard Eclipse new project: File menu → Project... . If you have installed Intel® Software Guard Extensions Eclipse Plug-in, you can see the category C/C++ with SGX Enabled in the New Project dialog.

    +

    + +

    +

    New Project

    +

    This category has 2 sub-categories, SGX C project and SGX C++ project. These sub-categories are similar to the sub-categories C Project and C++ Project of standard C/C++ category.

    +
  2. +
  3. Select one of the 2 sub-categories, SGX C project or SGX C++ project, and click Next.
  4. +
  5. Complete creating the project using the regular process of creating a standard C or C++ project.
  6. +
+
+

NOTE:

+

Projects created following the subcategories under C/C++ with SGX Enabled are identical with their standard counterparts, except that they have SGX Nature added. There is no difference between creating a C or C++ project with SGX enabled, or creating a standard C/C++ project and launch Add SGX nature from it, as described in precedent paragraph.

+
+
+
+

Adding an SGX Enclave

+

After you add the SGX nature to a project, you can start creating a minimal but complete skeleton for a new enclave:

+
    +
  1. Right-click on the project root in Project Explorer.
  2. +
  3. +

    Open the dialog Add New SGX Enclave by selecting Software Guard Extensions Tools → Add SGX Enclave from the contextual menu.

    +

    + +

    +

    Add New Intel® SGX Enclave Dialog

    +
  4. +
  5. +

    Choose a name for the enclave in Enclave name field. This name is used in the process of generation of the skeleton to give unicity to the source files and the name of the resulting executable, so you can add more than one enclave to the same project.

    +
      +
    • +

      If you do not select the Generate sample untrusted application checkbox, the plugin generates only a trusted file and a Makefile fragment to build and compile the trusted part. See the following graphic. All the code for the enclave, including build Makefile, is put in a directory <root>/sgx/enclave_<name> . C/C++ code for the enclave proper are in <root>/sgx/enclave_<name>/trusted.

      +

      + +

      +

      Generated Skeleton for an Enclave. The option to Generate Sample was not Used

      +
    • +
    • +

      If you select Generate sample untrusted application checkbox, a simple ready to work sample application is generated, including untrusted stubs and implementation for a sample OCALL and ECALL.

      +

      + +

      +

      Generated Sample Untrusted Application

      +
    • +
    +
  6. +
+
+

NOTE:

+

If you select the Generate sample untrusted application checkbox, ecalls from the untrusted part are not be resolved by Eclipse C/C++ indexer. These functions are marked with a red line. The declaration of these ecalls resides in the unstrusted stub header which is generated during the build proces and is not indexed by Eclipse. To resolve this problem, right-click on project root and select Index → Freshen All Files.

+
+
+
+

Adding an SGX Trusted Library

+

Trusted Static Libraries helps enclave author have libraries of shared code to be reused by enclaves, in exactly the same manner as usual static libxxx.a libraries are used to share code between regular non-SGX applications. The plugin adds a command to generate the skeleton of a trusted shared library.

+

To add a new SGX Trusted Library:

+
    +
  1. +

    Open Add New SGX Static Trusted Library dialog by right-click on the root of the project and select the appropriate command from Software Guard Extensions Tools menu:

    +

    + +

    +

    Add New SGX Static Trusted Library Dialog

    +
  2. +
  3. +

    Choose a name for the library and click OK. A skeleton for a trusted library is generated in directory <root>/sgx/trustedlib_<name>:

    +

    + +

    +

    A Generated Trusted Library

    +
  4. +
+
+
+

Adding an SGX Untrusted Module

+

Add an untrusted module to generate the untrusted stubs so you use an enclave, provided you have access to its .edl file. The enclave might have been built in the current project or in a different project.

+

To use trusted functionality of an enclave for which its *.edl is known, use the command Add SGX Untrusted Module:

+
    +
  1. +

    Open dialog Add Sgx Untrusted Module by right-click-ing the project root in Package Explorer and chose the command from Software Guard Extension Tools.

    +

    + +

    +

    Add SGX Untrusted Module

    +
  2. +
  3. +

    Use the Browse button to navigate the file system using a file dialog, and click OK. The untrusted module is copied to <root>/sgx/untrusted_<edl file name>. The selected *.edl is copied to the project.

    +

    + +

    +

    Copying the Untrusted Module to a Project

    +
  4. +
+
+
+

Updating SGX Enclave Signing Key

+

All skeletons enclave samples produced by the plugin contain a sample signing key. You might want to import another sign key that you already have, or generate a new one. Use the command Update SGX Enclave Signing Key to complete this task.

+
    +
  1. Choose Update SGX Enclave Signing Key by right-click on the project in Project Explorer -> Software Guard Extension Tools menu. The Import or (Re)Generate Enclave Signing Key dialog appears.
  2. +
  3. In the Import or (Re)Generate Enclave Signing Key dialog, click Select to open a file dialog to select the output key.
  4. +
  5. +

    Click Improt Key to update a selected signing key by copying another existing key or click Generate Key to update the selected signing key by generating a new key. In both cases, the new signature key is put into the file in text field Enclave Signing Key.

    +

    + +

    +

    Import or (Re)Generate Enclave Signing Key

    +
  6. +
  7. Click OK to update the enclave signing key.
  8. +
+

Under the hood, a new key is generated using openssl*, which needs to be installed on the machine:

+

openssl genrsa -out ../../../encl1_private.pem.key.pem -3 3072 +

+

+
+
+

Updating Enclave Configuration Files

+

A configuration file is an important part in the definition of an enclave. Intel(R) SGX SDK signer tool requires such *.xml configuration file as necessary input.

+

To update this configuration file, use the Update Config command:

+
    +
  1. +

    Right-click on the root project, Software Extension Guards Tools->Select Config File.

    +

    + +

    +

    Select Configuration File

    +
  2. +
  3. +

    Click OK or double-click the selected configuration file to open the Enclave Configuration Settings dialog.

    +

    + +

    +

    Enclave Configuration Settings

    +

    For details on the meaning of the fields, see Intel(R) Software Guard Extensions Developer Guide.

    +
  4. +
+
+
+

Two Steps Sign Enclave

+

To help you develop enclaves, Intel(R) Software Guard Extensions Eclipse Plug-in generates all required structure including:

+
    +
  • c/c++ files and header files
  • +
  • .edl file
  • +
  • *.config.xml file
  • +
  • a sample Makefile
  • +
  • a sample signing key
  • +
+

While these structure might be appropriate for development and debugging, you need a 2-step process to integrate your own signing schema for generating production enclaves.

+
    +
  1. Generate hash: the signer tool generates signing material from the unsigned compiled enclave and from the configuration file for the enclave. The signed material comes as an opaque sequence of bytes which are put in a file with extension .hex. This file is used with the external signing facility. You come back with a signature for the .hex file plus the public key of your signing facility, and proceed to Step 2.
  2. +
  3. Generate signed enclaves : the signer tool generates the final signed enclave.
  4. +
+

To complete this task, provide the following input parameters:

+
    +
  • The unsigned enclave
  • +
  • The configuration file
  • +
  • The output file produced when you generate hash (the .hex file)
  • +
  • The files produced by the external signing facility: the signature of the .hex file and public key for it
  • +
  • The plugin checks if the input parameters are consistent:
  • +
  • The .hex file matches the unsigned enclave and the configuration file,
  • +
  • The signed material is verified with the public key
  • +
+

If the parameters are consistenet, the production signed enclave is produced.

+
+

NOTE:

+

If you generate signed enclave right after generating hash, you can only enter the parameters specific for generating signed enclave.

+
+

To use the two-step signing function, activate the configuration SGX Hardware Release mode. When this configuration is active, the compilation does not produce a signed enclave, as in the other SGX configurations; the process only produces unsigned enclaves.

+

+ +

+

Configure SGX Hardware Release Mode

+

When you configure the plugin in the SGX Hardware Release Mode, you can see the Generate Hash and Generate Signed Enclave options through Software Guard Extension Tools->Two Step Sign Enclave.

+

+ +

+

Two Step Sign Enclave Menu

+
+
+

Generate Hash

+

Generating hash is the first step in the 2-Steps signing process.To generate hash, use the following steps:

+
    +
  1. +

    Right-click on project root, go to Software Guard Extensions Tools menu → Two StepSigne Enclave → Generate Hash

    +

    + +

    +

    Two StepSigne Enclave - Generate Hash

    +
  2. +
  3. In the Generate Hash dialog, enter the required inputs to the corresponding fields:
    • Enter the path to the compiled enclave to be signed in the Enclave Path field. Click Select Enclave to open a file dialog to select the enclave.
    • In the Hash File Location field , enter the path of the output file that will contain signing materials. By default this file has the same file name as the unsigned enclave, with .hex extension added. To change the path, click Select File Path to open a file dialog to select the file path.
    • In the Configuration File path field, enter the path of the configuration filefor the generated hash. Click Select Config to open a dialog to select from all enclave configuration files in the project (similar with the one of the command Update Config).
  4. +
  5. +

    Click OK after you fill in all the fields. The Intel(R) SGX SDK is launched under the hood with the provided parameters and the hash file is generated. A dialog box appears to confirm the completion:

    +

    + +

    +

    Generating Hash Completion Dialog

    +
  6. +
+

You complete the first step, generating hash, in the two step signing enclave. The *.hex file may be signed with the external facility, which generates a signature for it and a public verification key.

+

If you click OK, the Generate Signed Enclave dialog appears. The required fileds in this dialog have been pre-configured with the paths of the unsigned enclave, the configuration file and of the *.hex file. To generated the final signed enclave ready for production immediately, click OK.

+

+ +

+

Generate Signed Enclave Dialog with Pre-configurations

+

If you click Cancel in the Generate Signed Enclave dialog, you can continue the signing process later using the Generate Signed Enclave command.

+
+
+

Generate Signed Enclaves

+

Generating signed enclave is the second step in the 2-Steps signing process. You should have the following files to complete this step:

+
    +
  • The .hex file generated with Generate Hash command
  • +
  • The files produced from the external signing facility
  • +
  • The signature of the .hex file
  • +
  • The public verification key
  • +
+

To generate signed encalves, use the following steps:

+
    +
  1. +

    Right-click on the project root, and go to Software Guard Extensions Tools menu → Two Step Sign Enclave → Generate Signed Enclave.

    +

    + +

    +

    Generate Signed Enclave Dialog

    +
  2. +
  3. Enter the inputs to all the fields and click OK.
  4. +
+
+
+

Building and Running SGX Code

+

This section describes the following topics about building and running SGX code:

+
    +
  • SGX build configurations
  • +
  • Running samples generated for enclaves
  • +
 
+
+

SGX Build Configurations

+

There are usually two types of builds that a regular non-SGX project defines:

+
    +
  • Debug
  • +
  • Release
  • +
+

SGX-enabled projects add to this picture support to build and test SGX-enabled application on non-SGX platforms (or emulator) using simulation libraries. This approach doubles the set of build types, creating four possible combinations. For these combinations, you need to use different sets of compilation and linking flags and link different libraries.

+

The non-debug hardware build is meant to give production code, so it requires the maximum attention when signed. The Two Steps Sign schema is required for production enclaves, which involves an external signing facility, not part of Intel SGX SDK. The other configurations are not meant for production but they have to be signed too. The simplest and more convenient Single Step schema is used for them.

+

Again for testing purpose, you might want to experiment with a non-production enclave built with release compilation and linking flags, on a real hardware SGX-enabled platform. That would be an enclave built exactly as a production enclave, except for the sign process which would be Single Step. To support the construction of such enclave, there is a hardware non-debug build configuration dubbed Prerelease.

+

So there are five SGX related configurations when SGX Nature is added to a project:

+

+ +

+

Intel(R) SGX Configurations

+

The following table resumes the existing SGX configurations and relate them with compilation/linking flags (debug/non-debug) and signing scheme (single vs. two steps):

+

Intel(R) SGX Configurations

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Configuration NameSimulation?Debug?Signing Schema
SGX Hardware DebugHardwareDebugSingle Step
SGX Hardware Pre-releaseHardwareNon-debugSingle Step
SGX Hardware ReleaseHardwareNon-debugTwo Step
SGX SimulationSimulationNon-debugSingle Step
SGX SimulationDebug SimulationDebugSingle step
+

Intel® Software Guard Extensions Eclipse Plug-in uses standard GNU* make tool to build the trusted and the untrusted code, using the generated file sgx/Makefile.

+

This fact does not impose any restriction on the build tool chosen for the hosting project. Intel® Software Guard Extensions Eclipse* Plug-in uses its own build configurations which do not interfere with the configurations that you might have in your project.

+

When SGX configurations are selected, by default only code under <root>/sgx directory get built.

+

You can customize SGX configurations as any other Eclipse build configurations from the project properties dialog. For example:

+
    +
  1. Right-click in Project Explorer Properties → C/C++ Build
  2. +
  3. Uncheck the Use default build command checkbox.
  4. +
+

Then you can customize and integrate SGX build process. You can use Makefile instead of sgx/Makefile in the example shown in the following figure:

+

+ +

+

Customization of SGX Build Command

+

The build process is done using standard Eclipse interface for build, by example from the main Project menu:

+

+ +

+

Project Menu

+
+
+

Running Samples Generated for Enclaves

+

Intel(R) Software Guard Extensions Eclipse* Plugin provides an option to generate a sample application together with the enclave code when the enclave is created. After the project is build, the sample application is built also and ready to run. You can see the sample application named sample in the enclave directory in Project Explorer. You can run this sample as a local C/C++ application as shown in the following figure:

+

+ +

+

Sample Application

+

See the result of the execution in Eclipse console window as shown below:

+

+ +

+

The Result of Running Samples Generated for Enclaves

+
+ + diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx.userguide/plugin.xml b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx.userguide/plugin.xml new file mode 100644 index 0000000000..533d28bf13 --- /dev/null +++ b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx.userguide/plugin.xml @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx.userguide/src/com/intel/sgx/userguide/Activator.java b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx.userguide/src/com/intel/sgx/userguide/Activator.java new file mode 100644 index 0000000000..f10dec9896 --- /dev/null +++ b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx.userguide/src/com/intel/sgx/userguide/Activator.java @@ -0,0 +1,73 @@ +/////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2016 Intel Corporation. // +// // +// All rights reserved. This program and the accompanying materials // +// are made available under the terms of the Eclipse Public License v1.0 // +// which accompanies this distribution, and is available at // +// http://www.eclipse.org/legal/epl-v10.html // +// // +// Contributors: // +// Intel Corporation - initial implementation and documentation // +/////////////////////////////////////////////////////////////////////////// + +package com.intel.sgx.userguide; + +import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.ui.plugin.AbstractUIPlugin; +import org.osgi.framework.BundleContext; + +/** + * The activator class controls the plug-in life cycle + */ +public class Activator extends AbstractUIPlugin { + + // The plug-in ID + public static final String PLUGIN_ID = "com.intel.sgx.userguide"; //$NON-NLS-1$ + + // The shared instance + private static Activator plugin; + + /** + * The constructor + */ + public Activator() { + } + + /* + * (non-Javadoc) + * @see org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext) + */ + public void start(BundleContext context) throws Exception { + super.start(context); + plugin = this; + } + + /* + * (non-Javadoc) + * @see org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext) + */ + public void stop(BundleContext context) throws Exception { + plugin = null; + super.stop(context); + } + + /** + * Returns the shared instance + * + * @return the shared instance + */ + public static Activator getDefault() { + return plugin; + } + + /** + * Returns an image descriptor for the image file at the given + * plug-in relative path + * + * @param path the path + * @return the image descriptor + */ + public static ImageDescriptor getImageDescriptor(String path) { + return imageDescriptorFromPlugin(PLUGIN_ID, path); + } +} diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx.userguide/toc.xml b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx.userguide/toc.xml new file mode 100644 index 0000000000..9a31c4b5b2 --- /dev/null +++ b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx.userguide/toc.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/.classpath b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/.classpath new file mode 100644 index 0000000000..6c009435ce --- /dev/null +++ b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/.classpath @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/.project b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/.project new file mode 100644 index 0000000000..aec7e39589 --- /dev/null +++ b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/.project @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + com.intel.sgx + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + + org.eclipse.pde.PluginNature + org.eclipse.jdt.core.javanature + + diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/.settings/org.eclipse.jdt.core.prefs b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000000..a698e59674 --- /dev/null +++ b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,12 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 +org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve +org.eclipse.jdt.core.compiler.compliance=1.8 +org.eclipse.jdt.core.compiler.debug.lineNumber=generate +org.eclipse.jdt.core.compiler.debug.localVariable=generate +org.eclipse.jdt.core.compiler.debug.sourceFile=generate +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.source=1.8 diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/META-INF/MANIFEST.MF b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/META-INF/MANIFEST.MF new file mode 100644 index 0000000000..f06f84d713 --- /dev/null +++ b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/META-INF/MANIFEST.MF @@ -0,0 +1,26 @@ +License: Eclipse Public License Version 1.0 ("EPL") +bundle-ManifestVersion: 2 +Bundle-Name: %Bundle-Name +Bundle-SymbolicName: com.intel.sgx;singleton:=true +Bundle-Version: 1.0.1.qualifier +Bundle-Activator: com.intel.sgx.Activator +Bundle-Vendor: %Bundle-Vendor +Require-Bundle: org.eclipse.cdt.core;bundle-version="5.11.0", + org.eclipse.core.runtime;bundle-version="3.11.1", + org.eclipse.ui;bundle-version="3.107.0", + org.eclipse.cdt.managedbuilder.ui;bundle-version="8.2.2", + org.eclipse.cdt.managedbuilder.core;bundle-version="8.3.0", + org.eclipse.core.resources;bundle-version="3.10.1", + org.eclipse.cdt.ui;bundle-version="5.11.0", + org.eclipse.core.expressions;bundle-version="3.5.0", + org.eclipse.ui.ide;bundle-version="3.11.0" +Bundle-ActivationPolicy: lazy +Export-Package: com.intel.sgx, + com.intel.sgx.build, + com.intel.sgx.dialogs, + com.intel.sgx.discovery, + com.intel.sgx.handlers, + com.intel.sgx.natures, + com.intel.sgx.preferences, + com.intel.sgx.templates +Bundle-RequiredExecutionEnvironment: JavaSE-1.8 diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/OSGI-INF/l10n/bundle.properties b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/OSGI-INF/l10n/bundle.properties new file mode 100644 index 0000000000..171c78c844 --- /dev/null +++ b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/OSGI-INF/l10n/bundle.properties @@ -0,0 +1,15 @@ +######################################################################### +# Copyright (c) 2016 Intel Corporation. # +# # +# All rights reserved. This program and the accompanying materials # +# are made available under the terms of the Eclipse Public License v1.0 # +# which accompanies this distribution, and is available at # +# http://www.eclipse.org/legal/epl-v10.html # +# # +# Contributors: # +# Intel Corporation - initial implementation and documentation # +######################################################################### + + +Bundle-Vendor = Intel Corporation +Bundle-Name = SGX(R) Linux Eclipse Plugin \ No newline at end of file diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/build.properties b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/build.properties new file mode 100644 index 0000000000..d055ac2fdc --- /dev/null +++ b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/build.properties @@ -0,0 +1,24 @@ +######################################################################### +# Copyright (c) 2016 Intel Corporation. # +# # +# All rights reserved. This program and the accompanying materials # +# are made available under the terms of the Eclipse Public License v1.0 # +# which accompanies this distribution, and is available at # +# http://www.eclipse.org/legal/epl-v10.html # +# # +# Contributors: # +# Intel Corporation - initial implementation and documentation # +######################################################################### + + +source.. = src/ +output.. = bin/ +bin.includes = META-INF/,\ + .,\ + plugin.xml,\ + templates/,\ + discovery/,\ + build.properties,\ + OSGI-INF/,\ + OSGI-INF/l10n/bundle.properties +jre.compilation.profile = JavaSE-1.8 diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/discovery/test.c b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/discovery/test.c new file mode 100644 index 0000000000..139597f9cb --- /dev/null +++ b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/discovery/test.c @@ -0,0 +1,2 @@ + + diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/discovery/test.cpp b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/discovery/test.cpp new file mode 100644 index 0000000000..139597f9cb --- /dev/null +++ b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/discovery/test.cpp @@ -0,0 +1,2 @@ + + diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/plugin.xml b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/plugin.xml new file mode 100644 index 0000000000..86a2ba5d05 --- /dev/null +++ b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/plugin.xml @@ -0,0 +1,786 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + An C project, with SGX Commands and Configurations + + + + + + An C++ project, with SGX Commands and Configurations + + + + + + diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/src/com/intel/sgx/Activator.java b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/src/com/intel/sgx/Activator.java new file mode 100644 index 0000000000..580330b423 --- /dev/null +++ b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/src/com/intel/sgx/Activator.java @@ -0,0 +1,75 @@ +/////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2016 Intel Corporation. // +// // +// All rights reserved. This program and the accompanying materials // +// are made available under the terms of the Eclipse Public License v1.0 // +// which accompanies this distribution, and is available at // +// http://www.eclipse.org/legal/epl-v10.html // +// // +// Contributors: // +// Intel Corporation - initial implementation and documentation // +/////////////////////////////////////////////////////////////////////////// + +package com.intel.sgx; + +import java.net.URL; + +import org.eclipse.core.runtime.FileLocator; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Path; +import org.eclipse.core.runtime.Status; +import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.ui.plugin.AbstractUIPlugin; +import org.osgi.framework.Bundle; +import org.osgi.framework.BundleContext; + +/** + * The activator class controls the plug-in life cycle + */ +public class Activator extends AbstractUIPlugin { + + public static final String PLUGIN_ID = "com.intel.sgx";//$NON-NLS-1$ + + private static Activator plugin; + + public Activator() { + } + + public void start(BundleContext context) throws Exception { + super.start(context); + plugin = this; + } + + public void stop(BundleContext context) throws Exception { + plugin = null; + super.stop(context); + } + + public static Activator getDefault() { + return plugin; + } + + public static ImageDescriptor getImageDescriptor(String path) { + return imageDescriptorFromPlugin(PLUGIN_ID, path); + } + + public static void log(Exception e) { + plugin.getLog().log(newStatus(e)); + } + + public static IStatus newStatus(Exception e) { + return new Status(IStatus.ERROR, PLUGIN_ID, e.getMessage(), e); + } + + public static URL findFile(Path path) { + return FileLocator.find(plugin.getBundle(), path, null); + } + + public static Bundle getBundle(String id){ + for(Bundle bundle : plugin.getBundle().getBundleContext().getBundles()){ + if(bundle.getSymbolicName().equals(id)) + return bundle; + } + return null; + } +} diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/src/com/intel/sgx/CConfigurationDataProvider2.java b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/src/com/intel/sgx/CConfigurationDataProvider2.java new file mode 100644 index 0000000000..59cdc66e33 --- /dev/null +++ b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/src/com/intel/sgx/CConfigurationDataProvider2.java @@ -0,0 +1,46 @@ +/////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2016 Intel Corporation. // +// // +// All rights reserved. This program and the accompanying materials // +// are made available under the terms of the Eclipse Public License v1.0 // +// which accompanies this distribution, and is available at // +// http://www.eclipse.org/legal/epl-v10.html // +// // +// Contributors: // +// Intel Corporation - initial implementation and documentation // +/////////////////////////////////////////////////////////////////////////// + + +package com.intel.sgx; + +import org.eclipse.cdt.core.settings.model.ICConfigurationDescription; +import org.eclipse.cdt.core.settings.model.extension.CConfigurationData; +import org.eclipse.cdt.core.settings.model.extension.CConfigurationDataProvider; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; + +public class CConfigurationDataProvider2 extends CConfigurationDataProvider { + + public CConfigurationDataProvider2() { + } + + @Override + public CConfigurationData loadConfiguration(ICConfigurationDescription des, + IProgressMonitor monitor) throws CoreException { + return null; + } + + @Override + public CConfigurationData createConfiguration( + ICConfigurationDescription des, + ICConfigurationDescription baseDescription, + CConfigurationData baseData, boolean clone, IProgressMonitor monitor) + throws CoreException { + return null; + } + + @Override + public void removeConfiguration(ICConfigurationDescription des, + CConfigurationData data, IProgressMonitor monitor) { + } +} diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/src/com/intel/sgx/Messages.java b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/src/com/intel/sgx/Messages.java new file mode 100644 index 0000000000..d4133b2962 --- /dev/null +++ b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/src/com/intel/sgx/Messages.java @@ -0,0 +1,37 @@ +/////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2016 Intel Corporation. // +// // +// All rights reserved. This program and the accompanying materials // +// are made available under the terms of the Eclipse Public License v1.0 // +// which accompanies this distribution, and is available at // +// http://www.eclipse.org/legal/epl-v10.html // +// // +// Contributors: // +// Intel Corporation - initial implementation and documentation // +/////////////////////////////////////////////////////////////////////////// + + +package com.intel.sgx; + +import org.eclipse.osgi.util.NLS; + +public class Messages extends NLS { + + private static final String BUNDLE_NAME = "com.intel.sgx.messages";//$NON-NLS-1$ + + /* + * TODO - These Strings can be used all through the package to control what messages are displayed. + * Todo here is to identify any message that needs to be made configurable. + */ + public static String CreateNativeFolders_No_folders; + public static String CreateNativeFolders_Missing_project_name; + public static String CreateNativeFolders_Project_does_not_exist; + + static{ + //Bundle initialization. + NLS.initializeMessages(BUNDLE_NAME, Messages.class); + } + + private Messages(){ + } +} diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/src/com/intel/sgx/SdkPathVariableProvider.java b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/src/com/intel/sgx/SdkPathVariableProvider.java new file mode 100644 index 0000000000..43f13da5f9 --- /dev/null +++ b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/src/com/intel/sgx/SdkPathVariableProvider.java @@ -0,0 +1,70 @@ +/////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2016 Intel Corporation. // +// // +// All rights reserved. This program and the accompanying materials // +// are made available under the terms of the Eclipse Public License v1.0 // +// which accompanies this distribution, and is available at // +// http://www.eclipse.org/legal/epl-v10.html // +// // +// Contributors: // +// Intel Corporation - initial implementation and documentation // +/////////////////////////////////////////////////////////////////////////// + + +package com.intel.sgx; +import java.io.File; + +import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.variableresolvers.PathVariableResolver; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.Path; +import org.eclipse.jface.preference.IPreferenceStore; + +import com.intel.sgx.preferences.PreferenceConstants; +import com.intel.sgx.preferences.SGXPreferencePage; + +public class SdkPathVariableProvider extends PathVariableResolver { + + public SdkPathVariableProvider() { + super(); + } + + @Override + public String[] getVariableNames(String variable, IResource resource) { + String variableNames[] = {"SGX_SDK_DIR_PATH"}; + return (variableNames); + } + + @Override + public String getValue(String variable, IResource resource) { + if(variable.equals("SGX_SDK_DIR_PATH")) { + IPreferenceStore store = Activator.getDefault().getPreferenceStore(); + String SDKPath = store.getString(PreferenceConstants.SDK_PATH); + IPath SDKCanonicalPath= new Path(SDKPath); + return(SDKCanonicalPath.append("Include").toOSString()); + } + return null; + } + + public static String getSGXSdkLocation() { + return Activator.getDefault().getPreferenceStore().getString(PreferenceConstants.SDK_PATH); + } + + public static boolean isSGXSdkLocationValid() { + String location = getSGXSdkLocation(); + if (location.length() == 0) + return false; + + return isValidSGXSdkLocation(location); + } + + public static boolean isValidSGXSdkLocation(String location) { + File dir = new File(location); + if (!dir.isDirectory()) + return false; + + return new PreferenceConstants.SGXSDK64Descriptor(dir).getSignerPath().canExecute() + || new PreferenceConstants.SGXSDK32Descriptor(dir).getSignerPath().canExecute(); + } + +} diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/src/com/intel/sgx/build/SGXSDKCommandLauncher.java b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/src/com/intel/sgx/build/SGXSDKCommandLauncher.java new file mode 100644 index 0000000000..c0eb394532 --- /dev/null +++ b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/src/com/intel/sgx/build/SGXSDKCommandLauncher.java @@ -0,0 +1,38 @@ +/////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2016 Intel Corporation. // +// // +// All rights reserved. This program and the accompanying materials // +// are made available under the terms of the Eclipse Public License v1.0 // +// which accompanies this distribution, and is available at // +// http://www.eclipse.org/legal/epl-v10.html // +// // +// Contributors: // +// Intel Corporation - initial implementation and documentation // +/////////////////////////////////////////////////////////////////////////// + + +/** + * This class follows the same solution provided in the NDK_PLUGIN for NDKCommandLauncher. + */ +package com.intel.sgx.build; + +import org.eclipse.cdt.core.CommandLauncher; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.Path; + +import com.intel.sgx.SdkPathVariableProvider; +/** + * This launches the sgx-ndk-build. + */ +public class SGXSDKCommandLauncher extends CommandLauncher { + + @Override + public Process execute(IPath commandPath, String[] args, String[] env, IPath changeToDirectory, + IProgressMonitor monitor) + throws CoreException { + + return super.execute(commandPath, args, env, changeToDirectory, monitor); + } +} diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/src/com/intel/sgx/dialogs/AddEnclaveFileDialog.java b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/src/com/intel/sgx/dialogs/AddEnclaveFileDialog.java new file mode 100644 index 0000000000..e663a1c390 --- /dev/null +++ b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/src/com/intel/sgx/dialogs/AddEnclaveFileDialog.java @@ -0,0 +1,126 @@ +/////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2016 Intel Corporation. // +// // +// All rights reserved. This program and the accompanying materials // +// are made available under the terms of the Eclipse Public License v1.0 // +// which accompanies this distribution, and is available at // +// http://www.eclipse.org/legal/epl-v10.html // +// // +// Contributors: // +// Intel Corporation - initial implementation and documentation // +/////////////////////////////////////////////////////////////////////////// + + +package com.intel.sgx.dialogs; + +import javax.swing.JOptionPane; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Group; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.Text; + +import com.intel.sgx.handlers.AddEnclave; + +public class AddEnclaveFileDialog extends SGXDialogBase { + + private Text fileNameField; + private AddEnclave addHandler; + private boolean generateApp = true; + + public AddEnclaveFileDialog(Shell shell, AddEnclave addHandler) { + super(shell); + this.addHandler = addHandler; + this.shell = shell; + // setShellStyle(SWT.RESIZE | SWT.TITLE); + } + + public boolean generateApp() + { + return generateApp; + } + + @Override + protected Control createDialogArea(Composite parent) { + Composite composite = (Composite) super.createDialogArea(parent); + final GridLayout gridLayout = new GridLayout(1,false); + composite.setLayout(gridLayout); + + final Group container = new Group(composite, SWT.NONE); + container.setLayout(new GridLayout(3,false)); + GridData innergrid1 = new GridData(GridData.FILL_HORIZONTAL); + innergrid1.horizontalSpan = 3; + container.setLayoutData(innergrid1); + + addLabel(container, "Enter the name of the Enclave. Make sure the name is unique within the hosting application."); + + final Label fileNameLabel = new Label(container, SWT.NONE); + fileNameLabel.setText("Enclave name:"); + fileNameLabel.setLayoutData(new GridData(GridData.BEGINNING,GridData.CENTER, false, false)); + + fileNameField = new Text(container,SWT.SINGLE | SWT.BORDER); + GridData textGridData1 = new GridData(GridData.FILL_HORIZONTAL); + textGridData1.minimumWidth = 400; + textGridData1.grabExcessHorizontalSpace = true; + fileNameField.setLayoutData(textGridData1); + + Button generateUntrustedApp = new Button(container, SWT.CHECK); + generateUntrustedApp.setText("Generate sample untrusted application?"); + generateUntrustedApp.setLayoutData(new GridData(GridData.BEGINNING, GridData.END, false, false, 3, 1)); + generateUntrustedApp.setSelection(true); + + generateUntrustedApp.addSelectionListener(new SelectionAdapter() { + + @Override + public void widgetSelected(SelectionEvent event) { + Button btn = (Button) event.getSource(); + generateApp = btn.getSelection(); + } + }); + + container.layout(); + composite.layout(); + return composite; + } + + @Override + protected void configureShell(Shell newShell) { + super.configureShell(newShell); + newShell.setText("Add New SGX Enclave Dialog"); + newShell.layout(); + } + + @Override + protected + void okPressed() { + addHandler.edlFilename = fileNameField.getText(); + if(!fileNameField.getText().isEmpty() + ){ + if(Character.isDigit(fileNameField.getText().charAt(0))) + { + JOptionPane.showMessageDialog(null, "Enclave names starting with digits are not allowed.", "Error", + JOptionPane.ERROR_MESSAGE); + } + else + super.okPressed(); + } + } + + @Override + protected Point getInitialSize(){ + return new Point(675,200); + } + + public String getFileName() { + return fileNameField.getText(); + } +} diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/src/com/intel/sgx/dialogs/AddTrustedStaticLibFileDialog.java b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/src/com/intel/sgx/dialogs/AddTrustedStaticLibFileDialog.java new file mode 100644 index 0000000000..b353c716c8 --- /dev/null +++ b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/src/com/intel/sgx/dialogs/AddTrustedStaticLibFileDialog.java @@ -0,0 +1,109 @@ +/////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2016 Intel Corporation. // +// // +// All rights reserved. This program and the accompanying materials // +// are made available under the terms of the Eclipse Public License v1.0 // +// which accompanies this distribution, and is available at // +// http://www.eclipse.org/legal/epl-v10.html // +// // +// Contributors: // +// Intel Corporation - initial implementation and documentation // +/////////////////////////////////////////////////////////////////////////// + + +package com.intel.sgx.dialogs; + +import javax.swing.JOptionPane; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Group; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.Text; + +import com.intel.sgx.handlers.AddTrustedStaticLib; + +public class AddTrustedStaticLibFileDialog extends SGXDialogBase { + + private Text fileNameField; + private AddTrustedStaticLib addHandler; + private boolean generateApp = false; + + public AddTrustedStaticLibFileDialog(Shell shell, AddTrustedStaticLib addHandler) { + super(shell); + this.addHandler = addHandler; + this.shell = shell; + // setShellStyle(SWT.RESIZE | SWT.TITLE); + } + + public boolean generateApp() + { + return generateApp; + } + + @Override + protected Control createDialogArea(Composite parent) { + Composite composite = (Composite) super.createDialogArea(parent); + final GridLayout gridLayout = new GridLayout(1,false); + composite.setLayout(gridLayout); + + final Group container = new Group(composite, SWT.NONE); + container.setLayout(new GridLayout(3,false)); + GridData innergrid1 = new GridData(GridData.FILL_HORIZONTAL); + innergrid1.horizontalSpan = 3; + container.setLayoutData(innergrid1); + + addLabel(container, "Enter the name of the Static Trusted Library."); + addLabel(container, "Make sure the name is unique within the hosting application."); + + final Label fileNameLabel = new Label(container, SWT.NONE); + fileNameLabel.setText("Static Trusted Library Name:"); + fileNameLabel.setLayoutData(new GridData(GridData.BEGINNING,GridData.CENTER, false, false)); + + fileNameField = new Text(container,SWT.SINGLE | SWT.BORDER); + GridData textGridData1 = new GridData(GridData.FILL_HORIZONTAL); + textGridData1.minimumWidth = 400; + textGridData1.grabExcessHorizontalSpace = true; + fileNameField.setLayoutData(textGridData1); + + composite.layout(); + + return composite; + } + + @Override + protected void configureShell(Shell newShell) { + super.configureShell(newShell); + newShell.setText("Add New SGX Static Trusted Library Dialog"); + } + + @Override + protected + void okPressed(){ + addHandler.edlFilename = fileNameField.getText(); + if(!fileNameField.getText().isEmpty() + ){ + if(Character.isDigit(fileNameField.getText().charAt(0))) + { + JOptionPane.showMessageDialog(null, "Enclave names starting with digits are not allowed.", "Error", + JOptionPane.ERROR_MESSAGE); + } + else + super.okPressed(); + } + } + + @Override + protected Point getInitialSize(){ + return new Point(675,200); + } + + public String getFileName() { + return fileNameField.getText(); + } +} diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/src/com/intel/sgx/dialogs/AddUntrustedModuleDialog.java b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/src/com/intel/sgx/dialogs/AddUntrustedModuleDialog.java new file mode 100644 index 0000000000..15779d4651 --- /dev/null +++ b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/src/com/intel/sgx/dialogs/AddUntrustedModuleDialog.java @@ -0,0 +1,138 @@ +/////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2016 Intel Corporation. // +// // +// All rights reserved. This program and the accompanying materials // +// are made available under the terms of the Eclipse Public License v1.0 // +// which accompanies this distribution, and is available at // +// http://www.eclipse.org/legal/epl-v10.html // +// // +// Contributors: // +// Intel Corporation - initial implementation and documentation // +/////////////////////////////////////////////////////////////////////////// + + +package com.intel.sgx.dialogs; + +import java.io.File; + +import javax.swing.JOptionPane; + +import org.eclipse.jface.dialogs.Dialog; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.FileDialog; +import org.eclipse.swt.widgets.Group; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.Text; + +import com.intel.sgx.handlers.AddUntrustedModule; + +public class AddUntrustedModuleDialog extends Dialog { + + private Text fileNameField,makeFilePathField; + private Shell shell; + private AddUntrustedModule addHandler; + private boolean generateApp = false; + + public AddUntrustedModuleDialog(Shell shell, AddUntrustedModule addHandler) { + super(shell); + this.addHandler = addHandler; + this.shell = shell; + //setShellStyle(SWT.RESIZE | SWT.TITLE); + } + + public boolean generateApp() + { + return generateApp; + } + + @Override + protected Control createDialogArea(Composite parent) { + Composite composite = (Composite) super.createDialogArea(parent); + final GridLayout gridLayout = new GridLayout(1,false); + composite.setLayout(gridLayout); + + final Group container = new Group(composite, SWT.NONE); + container.setLayout(new GridLayout(3,false)); + GridData innergrid1 = new GridData(GridData.FILL_HORIZONTAL); + innergrid1.horizontalSpan = 3; + container.setLayoutData(innergrid1); + + final Label messageLabel = new Label(container, SWT.NONE); + messageLabel.setLayoutData(new GridData(GridData.BEGINNING, GridData.CENTER, false, false, 3, 1)); + messageLabel.setText("Enter the path to the Enclave Descriptor file (*.edl) of the enclave to host."); + + + final Label fileNameLabel = new Label(container, SWT.NONE); + fileNameLabel.setText("Filename:"); + fileNameLabel.setLayoutData(new GridData(GridData.BEGINNING,GridData.CENTER, false, false)); + + + fileNameField = new Text(container,SWT.SINGLE | SWT.BORDER); + GridData textGridData1 = new GridData(GridData.FILL_HORIZONTAL); + textGridData1.minimumWidth = 400; + textGridData1.grabExcessHorizontalSpace = true; + fileNameField.setLayoutData(textGridData1); + + final Button browseButton = new Button(container, SWT.PUSH); + browseButton.setText("Browse"); + GridData buttonGridData1 = new GridData(GridData.END); + buttonGridData1.horizontalAlignment = SWT.RIGHT; + buttonGridData1.horizontalSpan = 1; + buttonGridData1.minimumWidth = 120; + browseButton.setLayoutData(buttonGridData1); + browseButton.addSelectionListener(new SelectionListener() { + @Override + public void widgetSelected(SelectionEvent event) { + String result = null; + shell = new Shell(); + FileDialog dialog = new FileDialog(shell, SWT.OPEN); + dialog.setFilterExtensions(new String [] {"*.edl"}); + dialog.setFilterPath(""); + result = dialog.open(); + fileNameField.setText(result); + } + + @Override + public void widgetDefaultSelected(SelectionEvent e) { + } + }); + + return composite; + } + + @Override + protected void configureShell(Shell newShell) { + super.configureShell(newShell); + newShell.setText("Add SGX Untrusted Module."); + } + + @Override + protected + void okPressed(){ + addHandler.edlFilename = fileNameField.getText(); + if(!fileNameField.getText().isEmpty()) + if((new File(fileNameField.getText())).isFile()) + super.okPressed(); + else + JOptionPane.showMessageDialog(null, "EDL file does not exist.", "Error", + JOptionPane.ERROR_MESSAGE); + } + + @Override + protected Point getInitialSize(){ + return new Point(675,200); + } + + public String getFileName() { + return fileNameField.getText(); + } +} diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/src/com/intel/sgx/dialogs/EnclaveConfigDialog.java b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/src/com/intel/sgx/dialogs/EnclaveConfigDialog.java new file mode 100644 index 0000000000..20595f8095 --- /dev/null +++ b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/src/com/intel/sgx/dialogs/EnclaveConfigDialog.java @@ -0,0 +1,257 @@ +/////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2016 Intel Corporation. // +// // +// All rights reserved. This program and the accompanying materials // +// are made available under the terms of the Eclipse Public License v1.0 // +// which accompanies this distribution, and is available at // +// http://www.eclipse.org/legal/epl-v10.html // +// // +// Contributors: // +// Intel Corporation - initial implementation and documentation // +/////////////////////////////////////////////////////////////////////////// + + +package com.intel.sgx.dialogs; + +import org.eclipse.jface.preference.JFacePreferences; +import org.eclipse.jface.resource.JFaceResources; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.ModifyEvent; +import org.eclipse.swt.events.ModifyListener; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Combo; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Group; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.Text; + +import com.intel.sgx.handlers.EnclaveConfigHandler; + +public class EnclaveConfigDialog extends SGXDialogBase { + + @SuppressWarnings("unused") + private Shell shell; + private EnclaveConfigHandler enclaveConfig; + private Label statusLabel; + private Text prodID; + private Text isvSvn; + private Text threadStackSize; + private Text globalHeapSize; + private Text tcsNum; + private Combo tcsPolicy; + private Button disableDebug; + + public EnclaveConfigDialog(Shell parentshell,EnclaveConfigHandler enclaveConfigHandler) { + super(parentshell); + this.shell = parentshell; + this.enclaveConfig = enclaveConfigHandler; + setShellStyle(SWT.RESIZE | SWT.TITLE); + } + + @Override + protected Control createDialogArea(Composite parent) { + + Composite container = (Composite) super.createDialogArea(parent); + final GridLayout gridLayout = new GridLayout(3,false); + container.setLayout(gridLayout); + + final Group groupLabel1 = new Group(container, SWT.None); + groupLabel1.setLayout(new GridLayout(3,false)); + GridData innergrid1 = new GridData(GridData.FILL_HORIZONTAL); + innergrid1.horizontalSpan = 3; + groupLabel1.setLayoutData(innergrid1); + + Label warningLabel = new Label(groupLabel1,SWT.BEGINNING | SWT.WRAP); + warningLabel.setText("Note: Use this Menu to change the Enclave settings."); + + statusLabel = new Label(container,SWT.BEGINNING | SWT.WRAP); + GridData statusGrid = new GridData(GridData.FILL_HORIZONTAL); + statusGrid.horizontalSpan = 3; + statusLabel.setLayoutData(statusGrid); + statusLabel.setText(""); + statusLabel.setForeground(JFaceResources.getColorRegistry().get(JFacePreferences.ERROR_COLOR)); + + final Group groupLabel2 = new Group(container, SWT.None); + groupLabel2.setLayout(new GridLayout(3,false)); + groupLabel2.setText("Modify the Enclave Settings here..."); + GridData innergrid = new GridData(GridData.FILL_HORIZONTAL); + innergrid.horizontalSpan = 3; + groupLabel2.setLayoutData(innergrid); + + final Label messageLabel0 = new Label(groupLabel2, SWT.NONE); + messageLabel0.setText("Product ID:"); + messageLabel0.setLayoutData(new GridData(GridData.BEGINNING)); + + prodID = new Text(groupLabel2, SWT.SINGLE | SWT.BORDER); + GridData gridData = new GridData(GridData.FILL_HORIZONTAL); + gridData.horizontalSpan = 2; + gridData.widthHint = 400; + prodID.setLayoutData(gridData); + prodID.setText(enclaveConfig.prodId); + prodID.addModifyListener(new ModifyListener() { + @Override + public void modifyText(ModifyEvent modifyEvent) { + statusLabel.setText(""); + enclaveConfig.prodId = prodID.getText(); + } + }); + + final Label messageLabel1 = new Label(groupLabel2, SWT.NONE); + messageLabel1.setText("ISV SVN:"); + messageLabel1.setLayoutData(new GridData(GridData.BEGINNING)); + + isvSvn = new Text(groupLabel2, SWT.SINGLE | SWT.BORDER); + isvSvn.setLayoutData(gridData); + isvSvn.setText(enclaveConfig.isvSvn); + isvSvn.addModifyListener(new ModifyListener() { + @Override + public void modifyText(ModifyEvent modifyEvent) { + statusLabel.setText(""); + enclaveConfig.isvSvn = isvSvn.getText(); + } + }); + + final Label messageLabel2 = new Label(groupLabel2, SWT.NONE); + messageLabel2.setText("Thread Stack Size:"); + messageLabel2.setLayoutData(new GridData(GridData.BEGINNING)); + + threadStackSize = new Text(groupLabel2, SWT.SINGLE | SWT.BORDER); + threadStackSize.setLayoutData(gridData); + threadStackSize.setText(enclaveConfig.threadStackSize); + threadStackSize.addModifyListener(new ModifyListener() { + @Override + public void modifyText(ModifyEvent modifyEvent) { + enclaveConfig.threadStackSize = threadStackSize.getText(); + if(!(threadStackSize.getText().matches("0x[0-9a-fA-F]{1,}000"))) + { + statusLabel.setText("Error: The Thread Stack Size value must be Page Aligned."); + } + else + { + if(!(enclaveConfig.globalHeapSize.matches("0x[0-9a-fA-F]{1,}000"))) + statusLabel.setText("Error: The Global Heap Size value must be Page Aligned."); + else + statusLabel.setText(""); + } + } + }); + + final Label messageLabel3 = new Label(groupLabel2, SWT.NONE); + messageLabel3.setText("Global Heap Size:"); + messageLabel3.setLayoutData(new GridData(GridData.BEGINNING)); + + globalHeapSize = new Text(groupLabel2, SWT.SINGLE | SWT.BORDER); + globalHeapSize.setLayoutData(gridData); + globalHeapSize.setText(enclaveConfig.globalHeapSize); + globalHeapSize.addModifyListener(new ModifyListener() { + @Override + public void modifyText(ModifyEvent modifyEvent) { + enclaveConfig.globalHeapSize = globalHeapSize.getText(); + if(!(globalHeapSize.getText().matches("0x[0-9a-fA-F]{1,}000"))) + { + statusLabel.setText("Error: The Global Heap Size value must be Page Aligned."); + } + else + { + if(!(enclaveConfig.threadStackSize.matches("0x[0-9a-fA-F]{1,}000"))) + statusLabel.setText("Error: The Thread Stack Size value must be Page Aligned."); + else + statusLabel.setText(""); + + } + } + }); + + final Label messageLabel4 = new Label(groupLabel2, SWT.NONE); + messageLabel4.setText("TCS Number:"); + messageLabel4.setLayoutData(new GridData(GridData.BEGINNING)); + + tcsNum = new Text(groupLabel2, SWT.SINGLE | SWT.BORDER); + tcsNum.setLayoutData(gridData); + tcsNum.setText(enclaveConfig.tcsNum); + tcsNum.addModifyListener(new ModifyListener() { + @Override + public void modifyText(ModifyEvent modifyEvent) { + statusLabel.setText(""); + enclaveConfig.tcsNum = tcsNum.getText(); + } + }); + + final Label messageLabel5 = new Label(groupLabel2, SWT.NONE); + messageLabel5.setText("TCS Policy:"); + messageLabel5.setLayoutData(new GridData(GridData.BEGINNING)); + + final String[] items = {"Unbound","Bound"}; + tcsPolicy = new Combo(groupLabel2, SWT.DROP_DOWN | SWT.READ_ONLY | SWT.BORDER); + tcsPolicy.setItems(items); + String item = items[Integer.parseInt(enclaveConfig.tcsPolicy)]; + int index = tcsPolicy.indexOf(item); + tcsPolicy.select(index < 0 ? 0 : index); + tcsPolicy.setLayoutData(gridData); + tcsPolicy.addSelectionListener(new SelectionAdapter() { + public void widgetSelected(SelectionEvent e){ + statusLabel.setText(""); + enclaveConfig.tcsPolicy = (tcsPolicy.getSelectionIndex() == 0 ? "0" : "1"); + } + }); + + + final Label messageLabel6 = new Label(groupLabel2, SWT.NONE); + messageLabel6.setText("Disable Debug:"); + messageLabel6.setLayoutData(new GridData(GridData.BEGINNING)); + + disableDebug = new Button(groupLabel2,SWT.CHECK); + GridData gridData1 = new GridData(GridData.FILL_HORIZONTAL); + disableDebug.setLayoutData(gridData1); + disableDebug.setSelection(enclaveConfig.disableDebug.equals("1")?true:false); + disableDebug.addSelectionListener(new SelectionAdapter(){ + public void widgetSelected(SelectionEvent e){ + statusLabel.setText(""); + enclaveConfig.disableDebug = disableDebug.getSelection()?"1":"0"; + } + }); + + if(statusLabel.getText() != null){ + statusLabel.setVisible(true); + } + else{ + statusLabel.setVisible(false); + } + + return container; + } + + @Override + protected void configureShell(Shell newShell) { + super.configureShell(newShell); + newShell.setText("Enclave Configuration Settings:"); + } + + @Override + protected Point getInitialSize(){ + return new Point(450,400); + } + + @Override + protected + void okPressed(){ + enclaveConfig.prodId = this.prodID.getText(); + enclaveConfig.isvSvn = this.isvSvn.getText(); + enclaveConfig.threadStackSize = this.threadStackSize.getText(); + enclaveConfig.globalHeapSize = this.globalHeapSize.getText(); + enclaveConfig.tcsNum = this.tcsNum.getText(); + enclaveConfig.tcsPolicy = this.tcsPolicy.getSelectionIndex() == 0 ? "0" : "1"; + enclaveConfig.disableDebug = disableDebug.getSelection()?"1":"0"; + + + if((statusLabel.getText() == "") && (enclaveConfig.globalHeapSize.matches("0x[0-9a-fA-F]{1,}000")) && (enclaveConfig.threadStackSize.matches("0x[0-9a-fA-F]{1,}000"))) + super.okPressed(); + } +} diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/src/com/intel/sgx/dialogs/RemoveEnclaveFileDialog.java b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/src/com/intel/sgx/dialogs/RemoveEnclaveFileDialog.java new file mode 100644 index 0000000000..6db3d2e1c4 --- /dev/null +++ b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/src/com/intel/sgx/dialogs/RemoveEnclaveFileDialog.java @@ -0,0 +1,122 @@ +/////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2016 Intel Corporation. // +// // +// All rights reserved. This program and the accompanying materials // +// are made available under the terms of the Eclipse Public License v1.0 // +// which accompanies this distribution, and is available at // +// http://www.eclipse.org/legal/epl-v10.html // +// // +// Contributors: // +// Intel Corporation - initial implementation and documentation // +/////////////////////////////////////////////////////////////////////////// + + +package com.intel.sgx.dialogs; + +import org.eclipse.jface.dialogs.Dialog; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.DirectoryDialog; +//import org.eclipse.swt.widgets.FileDialog; +import org.eclipse.swt.widgets.Group; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.Text; + +import com.intel.sgx.handlers.RemoveEnclave; + +public class RemoveEnclaveFileDialog extends Dialog{ + + private Text fileNameField; + private Shell shell; + private RemoveEnclave removeHandler; + + public RemoveEnclaveFileDialog(Shell shell, RemoveEnclave removeHandler) { + super(shell); + this.removeHandler = removeHandler; + this.shell = shell; + setShellStyle(SWT.RESIZE | SWT.TITLE); + } + + @Override + protected Control createDialogArea(Composite parent) { + Composite composite = (Composite) super.createDialogArea(parent); + final GridLayout gridLayout = new GridLayout(1,false); + composite.setLayout(gridLayout); + + final Group container = new Group(composite, SWT.None); + container.setLayout(new GridLayout(3,false)); + GridData innergrid1 = new GridData(GridData.FILL_HORIZONTAL); + innergrid1.horizontalSpan = 3; + container.setLayoutData(innergrid1); + container.setText("Path to Enclave directory:"); + + final Label messageLabel = new Label(container, SWT.NONE); + messageLabel.setLayoutData(new GridData(GridData.BEGINNING, GridData.CENTER, false, false, 3, 1)); + messageLabel.setText("Enter the name of the Enclave Or Navigate to the Enclave folder to be removed from the host."); + + final Label fileNameLabel = new Label(container, SWT.NONE); + fileNameLabel.setLayoutData(new GridData(GridData.BEGINNING,GridData.CENTER, false, false)); + fileNameLabel.setText("Enclave Name:"); + + fileNameField = new Text(container, SWT.SINGLE | SWT.BORDER); + GridData textGridData1 = new GridData(GridData.FILL_HORIZONTAL); + textGridData1.minimumWidth = 400; + textGridData1.grabExcessHorizontalSpace = true; + fileNameField.setLayoutData(textGridData1); + + final Button browseButton = new Button(container, SWT.PUSH); + browseButton.setText("Browse"); + GridData buttonGridData1 = new GridData(GridData.END); + buttonGridData1.horizontalAlignment = SWT.RIGHT; + buttonGridData1.horizontalSpan = 1; + buttonGridData1.minimumWidth = 120; + browseButton.setLayoutData(buttonGridData1); + browseButton.addSelectionListener(new SelectionListener() { + @Override + public void widgetSelected(SelectionEvent event) { + String result = fileNameField.getText(); + + DirectoryDialog dialog = new DirectoryDialog(shell, SWT.OPEN); + dialog.setMessage("Select the Enclave Directory to remove."); + dialog.setFilterPath(""); + result = dialog.open(); + fileNameField.setText(result); + } + + @Override + public void widgetDefaultSelected(SelectionEvent e) { + } + }); + + return container; + } + @Override + protected void configureShell(Shell newShell) { + super.configureShell(newShell); + newShell.setText("Remove an Imported Enclave"); + } + + @Override + protected void okPressed(){ + removeHandler.edlFilename = fileNameField.getText(); + if(!fileNameField.getText().isEmpty()) + super.okPressed(); + } + + @Override + protected Point getInitialSize(){ + return new Point(675,205); + } + + public String getFileName() { + return fileNameField.getText(); + } +} diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/src/com/intel/sgx/dialogs/SGXDialogBase.java b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/src/com/intel/sgx/dialogs/SGXDialogBase.java new file mode 100644 index 0000000000..4b49a8bb31 --- /dev/null +++ b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/src/com/intel/sgx/dialogs/SGXDialogBase.java @@ -0,0 +1,222 @@ +/////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2016 Intel Corporation. // +// // +// All rights reserved. This program and the accompanying materials // +// are made available under the terms of the Eclipse Public License v1.0 // +// which accompanies this distribution, and is available at // +// http://www.eclipse.org/legal/epl-v10.html // +// // +// Contributors: // +// Intel Corporation - initial implementation and documentation // +/////////////////////////////////////////////////////////////////////////// + + +package com.intel.sgx.dialogs; + +import java.io.InputStream; +import java.util.Scanner; + +import org.eclipse.core.resources.IContainer; +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.runtime.IAdaptable; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.jface.dialogs.Dialog; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.window.IShellProvider; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Group; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.Text; +import org.eclipse.ui.IWorkbenchWindow; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.dialogs.FilteredResourcesSelectionDialog; + +import com.intel.sgx.Activator; + +public abstract class SGXDialogBase extends Dialog { + + protected Shell shell; + public Text configFileField; + public static FilteredResourcesSelectionDialog dialogForConfig(Shell shell) { + // final IContainer container = ResourcesPlugin.getWorkspace().getRoot(); + + final IContainer container = SGXDialogBase.getCurrentProject(); + + FilteredResourcesSelectionDialog d = new FilteredResourcesSelectionDialog( + shell, false, container, IResource.FILE) { + { + setInitialPattern("**"); + } + + @Override + protected IStatus validateItem(Object item) { + // return Status.OK_STATUS; + IFile f = (IFile) item; + if (f.getParent() instanceof IProject) { + return new Status(IStatus.ERROR, Activator.PLUGIN_ID, + "The selected resource has to be part of the source folder"); + } + + + return super.validateItem(item); + } + + protected ItemsFilter createFilter() { + return new ResourceFilter(container, true, IResource.FILE) { + + @Override + public boolean matchItem(Object item) { + return isConfigFile(item); + } + + private boolean isConfigFile(Object item) { + if (!(item.toString().endsWith(".xml") && super + .matchItem(item))) { + return false; + } + try { + IFile iFile = (IFile) item; + return streamContainsString(iFile.getContents(), + ""); + } catch (Throwable e) { + return false; + } + } + + }; + + } + + public boolean streamContainsString(InputStream is, + String searchString) { + Scanner streamScanner = new Scanner(is); + if (streamScanner.findWithinHorizon(searchString, 0) != null) { + return true; + } else { + return false; + } + } + + }; + return d; + } + + + + protected SelectionListener configFileSelectionListener = new SelectionListener() { + @Override + public void widgetSelected(SelectionEvent event) { + + FilteredResourcesSelectionDialog d = dialogForConfig(shell); + d.setTitle("Select Config File"); + if (d.open() == Dialog.OK) { + IFile target = (IFile) d.getResult()[0]; + configFileField.setText(target.getLocation().toOSString()); + } + ; + } + + @Override + public void widgetDefaultSelected(SelectionEvent arg0) { + // TODO Auto-generated method stub + + } + + }; + + public SGXDialogBase(Shell parentShell) { + super(parentShell); + } + + public SGXDialogBase(IShellProvider parentShell) { + super(parentShell); + } + + protected Text addGroup(Composite composite, String title, String subtitle, + String label, String selectButtonLabel, SelectionListener selectionListener) { + final Group container = new Group(composite, SWT.None); + container.setLayout(new GridLayout(3, false)); + GridData innergrid1 = new GridData(GridData.FILL_HORIZONTAL); + innergrid1.horizontalSpan = 3; + container.setLayoutData(innergrid1); + container.setText(title); + + final Label messageLabel = new Label(container, SWT.NONE); + messageLabel.setLayoutData(new GridData(GridData.BEGINNING, + GridData.CENTER, false, false, 3, 1)); + messageLabel.setText(subtitle); + + final Label messageLabel1 = new Label(container, SWT.NONE); + messageLabel1.setText(label); + messageLabel1.setLayoutData(new GridData(GridData.BEGINNING)); + + Text directoryNameField = new Text(container, SWT.SINGLE | SWT.BORDER); + GridData gridData = new GridData(GridData.FILL_HORIZONTAL); + gridData.horizontalSpan = 1; + gridData.widthHint = 400; + directoryNameField.setLayoutData(gridData); + + final Button selectButton = new Button(container, SWT.PUSH); + selectButton.setText(selectButtonLabel); + GridData buttonGridData = new GridData(GridData.END); + buttonGridData.horizontalAlignment = SWT.RIGHT; + buttonGridData.horizontalSpan = 1; + buttonGridData.minimumWidth = 120; + selectButton.setLayoutData(buttonGridData); + selectButton.addSelectionListener(selectionListener); + return directoryNameField; + } + + + public IPath getCurrentProjectPath() { + IProject project = getCurrentProject(); + + IPath path = null; + if (project != null) { + path = project.getLocation(); + } + return path; + } + + static public IProject getCurrentProject() { + IProject project = null; + + + IWorkbenchWindow window = PlatformUI.getWorkbench() + .getActiveWorkbenchWindow(); + if (window != null) { + IStructuredSelection selection = (IStructuredSelection) window + .getSelectionService().getSelection(); + Object firstElement = selection.getFirstElement(); + if (firstElement instanceof IAdaptable) { + project = (IProject) ((IAdaptable) firstElement) + .getAdapter(IProject.class); + } + } + return project; + } + + @Override + protected void configureShell(Shell newShell){ + super.configureShell(newShell); + } + + protected void addLabel(final Group container, String labelText) { + final Label messageLabel = new Label(container, SWT.NONE); + messageLabel.setLayoutData(new GridData(GridData.BEGINNING, GridData.CENTER, false, false, 3, 1)); + messageLabel.setText(labelText); + } + +} diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/src/com/intel/sgx/dialogs/TwoStepSignDialogBase.java b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/src/com/intel/sgx/dialogs/TwoStepSignDialogBase.java new file mode 100644 index 0000000000..07d25c7321 --- /dev/null +++ b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/src/com/intel/sgx/dialogs/TwoStepSignDialogBase.java @@ -0,0 +1,174 @@ +/////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2016 Intel Corporation. // +// // +// All rights reserved. This program and the accompanying materials // +// are made available under the terms of the Eclipse Public License v1.0 // +// which accompanies this distribution, and is available at // +// http://www.eclipse.org/legal/epl-v10.html // +// // +// Contributors: // +// Intel Corporation - initial implementation and documentation // +/////////////////////////////////////////////////////////////////////////// + + +package com.intel.sgx.dialogs; + +import java.io.File; +import java.util.Scanner; + +import javax.swing.JOptionPane; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.widgets.FileDialog; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.Text; + +public abstract class TwoStepSignDialogBase extends SGXDialogBase { + + public Text enclaveFileField; + public Text hashFileField; + public Text externalSignPublicKeyFileField; + public Text externalSignedHashFileField; + public Text outputSignedEnclaveFileField; + + public TwoStepSignDialogBase(Shell parentShell) { + super(parentShell); + setShellStyle(SWT.RESIZE | SWT.TITLE); + this.shell = TwoStepSignDialogBase.this.getParentShell(); + + } + + // for each field, a corresponding listener + protected SelectionListener enclaveFileSelectionListener = new SelectionListener() { + @Override + public void widgetSelected(SelectionEvent event) { + String result = enclaveFileField.getText(); + FileDialog dialog = new FileDialog(shell, SWT.OPEN); + + + + dialog.setFilterExtensions(new String[]{"*.so"} ); + dialog.setFilterPath(getCurrentProjectPath().toOSString()); + + if (result != null && !result.isEmpty()) { + dialog.setFilterPath(new File(result).getParent()); + } else { + dialog.setFilterPath(getCurrentProjectPath().toOSString()); + } + + result = dialog.open(); + + enclaveFileField.setText(result); + + hashFileField.setText(result + ".hex"); + + if (outputSignedEnclaveFileField != null){ + String outputSignedEnclavePath = result; + if(outputSignedEnclavePath.endsWith(".so")) + { + outputSignedEnclavePath = + outputSignedEnclavePath.substring(0,outputSignedEnclavePath.length() - ".so".length()); + outputSignedEnclaveFileField.setText(outputSignedEnclavePath+".signed.so"); + } + + } + + + + } + + @Override + public void widgetDefaultSelected(SelectionEvent arg0) { + } + }; + + protected SelectionListener hashFileSelectionListener = new SelectionListener() { + @Override + public void widgetSelected(SelectionEvent event) { + String result = hashFileField.getText(); + + FileDialog dialog = new FileDialog(shell, SWT.OPEN); + + if (result != null && !result.isEmpty()) { + dialog.setFilterPath(new File(result).getParent()); + } else { + dialog.setFilterPath(getCurrentProjectPath().toOSString()); + } + + result = dialog.open(); + + hashFileField.setText(result); + } + + @Override + public void widgetDefaultSelected(SelectionEvent arg0) { + } + + }; + + protected SelectionListener publicKeyLocationSelectionListener = new SelectionListener() { + @Override + public void widgetSelected(SelectionEvent event) { + String result = externalSignPublicKeyFileField.getText(); + FileDialog dialog = new FileDialog(shell, SWT.OPEN); + dialog.setFilterExtensions(new String [] {"*.pem", "*"}); + dialog.setFilterPath(getCurrentProjectPath().toOSString()); + result = dialog.open(); + externalSignPublicKeyFileField.setText(result); + } + @Override + public void widgetDefaultSelected(SelectionEvent e) { + } + }; + + protected SelectionListener externalSignedHashFileSelectionListener = new SelectionListener() { + @Override + public void widgetSelected(SelectionEvent event) { + String result = externalSignedHashFileField.getText(); + FileDialog dialog = new FileDialog(shell, SWT.OPEN); + dialog.setFilterPath(getCurrentProjectPath().toOSString()); + result = dialog.open(); + externalSignedHashFileField.setText(result); + } + @Override + public void widgetDefaultSelected(SelectionEvent e) { + } + }; + + protected SelectionListener outputSignedEnclaveListener = new SelectionListener() { + @Override + public void widgetSelected(SelectionEvent event) { + String result = outputSignedEnclaveFileField.getText(); + FileDialog dialog = new FileDialog(shell, SWT.OPEN); + + + dialog.setFilterExtensions(new String[]{"*.so", } ); + dialog.setFilterPath(getCurrentProjectPath().toOSString()); + + if (result != null && !result.isEmpty()) { + dialog.setFilterPath(new File(result).getParent()); + } else { + dialog.setFilterPath(getCurrentProjectPath().toOSString()); + } + + result = dialog.open(); + + outputSignedEnclaveFileField.setText(result); + + } + + @Override + public void widgetDefaultSelected(SelectionEvent arg0) { + } + }; + + + @Override + protected void configureShell(Shell newShell) { + super.configureShell(newShell); + } + + +} diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/src/com/intel/sgx/dialogs/TwoStepSignStep1Dialog1.java b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/src/com/intel/sgx/dialogs/TwoStepSignStep1Dialog1.java new file mode 100644 index 0000000000..fdba448164 --- /dev/null +++ b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/src/com/intel/sgx/dialogs/TwoStepSignStep1Dialog1.java @@ -0,0 +1,72 @@ +/////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2016 Intel Corporation. // +// // +// All rights reserved. This program and the accompanying materials // +// are made available under the terms of the Eclipse Public License v1.0 // +// which accompanies this distribution, and is available at // +// http://www.eclipse.org/legal/epl-v10.html // +// // +// Contributors: // +// Intel Corporation - initial implementation and documentation // +/////////////////////////////////////////////////////////////////////////// + + +package com.intel.sgx.dialogs; + +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Shell; + +import com.intel.sgx.handlers.TwoStepSignHandlerBase; + +public class TwoStepSignStep1Dialog1 extends TwoStepSignDialogBase { + + final private TwoStepSignHandlerBase handler; + + public TwoStepSignStep1Dialog1(Shell parentShell, TwoStepSignHandlerBase handler) { + super(parentShell); + this.handler = handler; + } + + @Override + protected Control createDialogArea(Composite parent) { + Composite composite = (Composite) super.createDialogArea(parent); + final GridLayout gridLayout = new GridLayout(1, false); + composite.setLayout(gridLayout); + + enclaveFileField = addGroup(composite, "Unsigned Enclave Path:", + "Select Enclave for which to generate the Hash.", + "Enclave Path:", "Select Enclave", enclaveFileSelectionListener); + + hashFileField = addGroup(composite, "Generate Hash:", + "Select Location to Output Hash File.", "Hash File Location:", + "Select File Path", hashFileSelectionListener); + + configFileField = addGroup(composite, "Configuration File:", + "Select Input Configuration XML File. ", + "Configuration File:", "Select Config", + configFileSelectionListener); + + composite.pack(true); + return composite; + } + + @Override + protected void okPressed() { + handler.enclaveFile = enclaveFileField.getText(); + handler.hashFile = hashFileField.getText(); + handler.configFile = configFileField.getText(); + + super.okPressed(); + } + + @Override + protected void configureShell(Shell newShell) { + super.configureShell(newShell); + newShell.setText("Two Step Enclave Sign - Generate Hash"); + } + + + +} diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/src/com/intel/sgx/dialogs/TwoStepSignStep1Dialog2.java b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/src/com/intel/sgx/dialogs/TwoStepSignStep1Dialog2.java new file mode 100644 index 0000000000..4c2852f9f4 --- /dev/null +++ b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/src/com/intel/sgx/dialogs/TwoStepSignStep1Dialog2.java @@ -0,0 +1,89 @@ +/////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2016 Intel Corporation. // +// // +// All rights reserved. This program and the accompanying materials // +// are made available under the terms of the Eclipse Public License v1.0 // +// which accompanies this distribution, and is available at // +// http://www.eclipse.org/legal/epl-v10.html // +// // +// Contributors: // +// Intel Corporation - initial implementation and documentation // +/////////////////////////////////////////////////////////////////////////// + + +package com.intel.sgx.dialogs; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Group; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Shell; + +public class TwoStepSignStep1Dialog2 extends TwoStepSignDialogBase { + + final private String hashFile; + + public TwoStepSignStep1Dialog2(Shell parentShell, String hashFile) { + super(parentShell); + this.hashFile = hashFile; + } + + @Override + protected Control createDialogArea(Composite parent) { + Composite composite = (Composite) super.createDialogArea(parent); + final GridLayout gridLayout = new GridLayout(1,false); + composite.setLayout(gridLayout); + + addGroup1(composite); + addGroup3(composite); + + + return composite; + } + + private void addGroup1(Composite composite) { + final Group container = new Group(composite, SWT.None); + container.setLayout(new GridLayout(3,false)); + GridData innergrid1 = new GridData(GridData.FILL_HORIZONTAL); + innergrid1.horizontalSpan = 3; + container.setLayoutData(innergrid1); + container.setText("Hash File:"); + + final Label messageLabel = new Label(container, SWT.NONE); + messageLabel.setLayoutData(new GridData(GridData.BEGINNING, GridData.CENTER, false, false, 3, 1)); + messageLabel.setText("Hash File Generated at Location:"); + + final Label messageLabel1 = new Label(container, SWT.NONE); + messageLabel1.setText(hashFile); + + messageLabel1.setLayoutData(new GridData(GridData.BEGINNING)); + } + + private void addGroup3(Composite composite) { + final Group container3 = new Group(composite, SWT.None); + container3.setLayout(new GridLayout(3,false)); + GridData innergrid3 = new GridData(GridData.FILL_HORIZONTAL); + innergrid3.horizontalSpan = 3; + container3.setLayoutData(innergrid3); + container3.setText("Generate Signed Enclave (Step-2):"); + + final Label messageLabel4 = new Label(container3, SWT.NONE); + messageLabel4.setLayoutData(new GridData(GridData.BEGINNING, GridData.CENTER, false, false, 3, 1)); + messageLabel4.setText("To Generate Signed Enclave Now: Click OK"); + + final Label messageLabel5 = new Label(container3, SWT.NONE); + messageLabel5.setLayoutData(new GridData(GridData.CENTER, GridData.END, false, false, 3, 1)); + messageLabel5.setText("To Generate Signed Enclave Later: Click Cancel"); + } + + @Override + protected void configureShell(Shell newShell) { + super.configureShell(newShell); + newShell.setText("Two Step Enclave Sign - Generate Hash"); + } + + +} diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/src/com/intel/sgx/dialogs/TwoStepSignStep1Dialog3.java b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/src/com/intel/sgx/dialogs/TwoStepSignStep1Dialog3.java new file mode 100644 index 0000000000..976f1c21b3 --- /dev/null +++ b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/src/com/intel/sgx/dialogs/TwoStepSignStep1Dialog3.java @@ -0,0 +1,105 @@ +/////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2016 Intel Corporation. // +// // +// All rights reserved. This program and the accompanying materials // +// are made available under the terms of the Eclipse Public License v1.0 // +// which accompanies this distribution, and is available at // +// http://www.eclipse.org/legal/epl-v10.html // +// // +// Contributors: // +// Intel Corporation - initial implementation and documentation // +/////////////////////////////////////////////////////////////////////////// + + +package com.intel.sgx.dialogs; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Group; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Shell; + +import com.intel.sgx.handlers.TwoStepSignHandlerBase; + +public class TwoStepSignStep1Dialog3 extends TwoStepSignDialogBase { + + final private TwoStepSignHandlerBase handler; + + public TwoStepSignStep1Dialog3(Shell parentShell, TwoStepSignHandlerBase handler) { + super(parentShell); + this.handler = handler; + } + + protected Control createDialogArea(Composite parent) { + Composite composite = (Composite) super.createDialogArea(parent); + final GridLayout gridLayout = new GridLayout(1, false); + composite.setLayout(gridLayout); + + addInfoGroup(composite); + + externalSignPublicKeyFileField = addGroup(composite, "Public Key:", + "Select the Public Key file obtained from signing facility", + "Public Key:", "Select", publicKeyLocationSelectionListener); + + externalSignedHashFileField = addGroup(composite, "Signature:", + "Select the Signature file obtained from signing facility.", + "Signature:", + "Select", externalSignedHashFileSelectionListener); + + + outputSignedEnclaveFileField = addGroup(composite, "Signed Enclave:", + "Select where to save the output Signed Enclave.", + "Signed Enclave:", + "Select", outputSignedEnclaveListener); + + return composite; + } + + protected void addInfoGroup(Composite composite) { + final Group container = new Group(composite, SWT.None); + container.setLayout(new GridLayout(3,false)); + GridData innergrid1 = new GridData(GridData.FILL_HORIZONTAL); + innergrid1.horizontalSpan = 3; + container.setLayoutData(innergrid1); + container.setText("Hash and Enclave:"); + + + addInfoKeyValue(container, "Enclave File:", handler.enclaveFile); + addInfoKeyValue(container, "Config File:", handler.configFile); + addInfoKeyValue(container, "Hash File:", handler.hashFile); + } + + private void addInfoKeyValue(final Group container, String key, + String value) { + final Label messageLabel2 = new Label(container, SWT.NONE); + messageLabel2.setLayoutData(new GridData(GridData.BEGINNING, GridData.CENTER, false, false, 3, 1)); + messageLabel2.setText(key); + + final Label messageLabel3 = new Label(container, SWT.NONE); + messageLabel3.setText(value); + messageLabel3.setLayoutData(new GridData(GridData.BEGINNING)); + } + + @Override + protected void okPressed() { + handler.externalSignPublicKeyFile = externalSignPublicKeyFileField.getText(); + handler.externallySignedHashFile = externalSignedHashFileField.getText(); + handler.outputSignedEnclaveFile = outputSignedEnclaveFileField.getText(); + super.okPressed(); + } + + + + @Override + protected void configureShell(Shell newShell) { + super.configureShell(newShell); + newShell.setText("Two Step Enclave Sign - Generate Signed Enclave"); + } + + + + +} diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/src/com/intel/sgx/dialogs/TwoStepSignStep2Dialog.java b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/src/com/intel/sgx/dialogs/TwoStepSignStep2Dialog.java new file mode 100644 index 0000000000..acd9e99627 --- /dev/null +++ b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/src/com/intel/sgx/dialogs/TwoStepSignStep2Dialog.java @@ -0,0 +1,92 @@ +/////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2016 Intel Corporation. // +// // +// All rights reserved. This program and the accompanying materials // +// are made available under the terms of the Eclipse Public License v1.0 // +// which accompanies this distribution, and is available at // +// http://www.eclipse.org/legal/epl-v10.html // +// // +// Contributors: // +// Intel Corporation - initial implementation and documentation // +/////////////////////////////////////////////////////////////////////////// + + +package com.intel.sgx.dialogs; + +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Shell; + +import com.intel.sgx.handlers.TwoStepSignHandlerBase; +import com.intel.sgx.handlers.TwoStepSignStep2; + +public class TwoStepSignStep2Dialog extends TwoStepSignDialogBase{ + + final private TwoStepSignHandlerBase handler; + + + public TwoStepSignStep2Dialog(Shell parentShell, TwoStepSignHandlerBase handler) { + super(parentShell); + this.handler = handler; + } + + + @Override + protected Control createDialogArea(Composite parent) { + Composite composite = (Composite) super.createDialogArea(parent); + final GridLayout gridLayout = new GridLayout(1,false); + composite.setLayout(gridLayout); + + + + enclaveFileField= addGroup(composite, "Enclave:", + "Select the unsigned enclave file", + "Unsigned Enclave File:", "Select", enclaveFileSelectionListener); + + configFileField = addGroup(composite, "Configuration File:", + "Select Input Configuration XML File. ", + "Configuration File:", "Select Config", + configFileSelectionListener); + + hashFileField= addGroup(composite, "Hash:", + "Select the Hash file obtained from previous step", + "Hash File:", "Select", hashFileSelectionListener); + + externalSignPublicKeyFileField= addGroup(composite, "Public Key:", + "Select the Public Key file obtained from external signing facility", + "Public Key:", "Select", publicKeyLocationSelectionListener); + + externalSignedHashFileField = addGroup(composite, "Signature:", + "Select the Signature file obtained from signing facility.", + "Signature:", + "Select", externalSignedHashFileSelectionListener); + + outputSignedEnclaveFileField = addGroup(composite, "Signed Enclave:", + "Select where to save the output Signed Enclave.", + "Signed Enclave:", + "Select", outputSignedEnclaveListener); + + return composite; + } + + + @Override + protected void okPressed() { + handler.enclaveFile = enclaveFileField.getText(); + handler.hashFile = hashFileField.getText(); + handler.configFile = configFileField.getText(); + handler.externalSignPublicKeyFile = externalSignPublicKeyFileField.getText(); + handler.externallySignedHashFile = externalSignedHashFileField.getText(); + handler.outputSignedEnclaveFile = outputSignedEnclaveFileField.getText(); + + super.okPressed(); + } + + @Override + protected void configureShell(Shell newShell) { + super.configureShell(newShell); + newShell.setText("Two Step Enclave Sign - Generate Signed Enclave"); + } + +} diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/src/com/intel/sgx/dialogs/UpdateSignKeyDialog.java b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/src/com/intel/sgx/dialogs/UpdateSignKeyDialog.java new file mode 100644 index 0000000000..502fb2dcfa --- /dev/null +++ b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/src/com/intel/sgx/dialogs/UpdateSignKeyDialog.java @@ -0,0 +1,191 @@ +/////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2016 Intel Corporation. // +// // +// All rights reserved. This program and the accompanying materials // +// are made available under the terms of the Eclipse Public License v1.0 // +// which accompanies this distribution, and is available at // +// http://www.eclipse.org/legal/epl-v10.html // +// // +// Contributors: // +// Intel Corporation - initial implementation and documentation // +/////////////////////////////////////////////////////////////////////////// + + +package com.intel.sgx.dialogs; + +import java.io.File; + +import javax.swing.JOptionPane; + +import org.eclipse.jface.dialogs.InputDialog; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.FileDialog; +import org.eclipse.swt.widgets.Group; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.Text; + +import com.intel.sgx.handlers.UpdateSigningKey; + +public class UpdateSignKeyDialog extends SGXDialogBase { + + private Shell shell; + public Text sourceKeyFileField; + public Text destinationKeyFileField; + public static boolean regenerate = false; + + private final SelectionListener destinationKeyFileSelectionListener = new SelectionListener() { + @Override + public void widgetSelected(SelectionEvent event) { + String result = destinationKeyFileField.getText(); + FileDialog dialog = new FileDialog(shell, SWT.OPEN); + dialog.setFilterPath(getCurrentProjectPath().toOSString()); + dialog.setFilterExtensions(new String [] {"*.pem", "*"}); + result = dialog.open(); + destinationKeyFileField.setText(result); + } + @Override + public void widgetDefaultSelected(SelectionEvent e) { + } + }; + + private final SelectionListener sourceKeyFileSelectionListener = new SelectionListener() { + @Override + public void widgetSelected(SelectionEvent event) { + String result = sourceKeyFileField.getText(); + FileDialog dialog = new FileDialog(shell, SWT.OPEN); + dialog.setFilterExtensions(new String [] {"*.pem", "*"}); + dialog.setFilterPath(getCurrentProjectPath().toOSString()); + result = dialog.open(); + sourceKeyFileField.setText(result); + } + @Override + public void widgetDefaultSelected(SelectionEvent e) { + } + }; + final private UpdateSigningKey handler; + + public UpdateSignKeyDialog(Shell parentShell, UpdateSigningKey handler) { + super(parentShell); + this.shell = parentShell; + this.handler = handler; + setShellStyle(SWT.RESIZE | SWT.TITLE); + } + + @Override + protected Control createDialogArea(Composite parent) { + Composite composite = (Composite) super.createDialogArea(parent); + final GridLayout gridLayout = new GridLayout(1,false); + composite.setLayout(gridLayout); + + destinationKeyFileField = addGroup(composite, "Enclave Signing Key:", + "Select the Signing Key to be Updated or Generated.", + "Enclave Signing Key:", "Select", destinationKeyFileSelectionListener); + + sourceKeyFileField = addGroup(composite, "Import:", + "To import your own Signing Key use the Import Signing Key option.", + "Import Signing Key:", "Import Key", sourceKeyFileSelectionListener); + + addGroup2(composite); + + return composite; + } + + protected void addGroup2(Composite composite) { + final Group container2 = new Group(composite, SWT.None); + container2.setLayout(new GridLayout(3,false)); + GridData innergrid2 = new GridData(GridData.FILL_HORIZONTAL); + innergrid2.horizontalSpan = 3; + container2.setLayoutData(innergrid2); + container2.setText("Generate:"); + + final Label messageLabel3 = new Label(container2, SWT.NONE); + messageLabel3.setLayoutData(new GridData(GridData.BEGINNING, GridData.CENTER, false, false, 3, 1)); + messageLabel3.setText("To Generate a new Signing Key use the Generate Signing Key option."); + + Label warningLabel2 = new Label(container2,SWT.FILL | SWT.WRAP); + warningLabel2.setText("Generate a new Signing Key:"); + warningLabel2.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + + Label dummy2 = new Label(container2,0); + dummy2.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + final Button updateSigningKey = new Button(container2, SWT.PUSH); + updateSigningKey.setText("Generate Key"); + GridData buttonGridData2 = new GridData(GridData.END); + buttonGridData2.horizontalAlignment = SWT.RIGHT; + buttonGridData2.horizontalSpan = 1; + buttonGridData2.minimumWidth = 120; + updateSigningKey.setLayoutData(buttonGridData2); + updateSigningKey.addSelectionListener(new SelectionListener() { + @Override + public void widgetSelected(SelectionEvent event) { + if( !destinationKeyFileField.getText().isEmpty()) + { + regenerate = true; + UpdateSignKeyDialog.this.setReturnCode(InputDialog.OK); + okPressed(); + UpdateSignKeyDialog.this.close(); + } + else + JOptionPane.showMessageDialog(null, "Enclave Signing Key field is not provided.", "Error", + JOptionPane.ERROR_MESSAGE); + } + + @Override + public void widgetDefaultSelected(SelectionEvent e) { + } + }); + } + + + @Override + protected void configureShell(Shell newShell) { + super.configureShell(newShell); + newShell.setText("Import or (Re)Generate Enclave Signing Key"); + } + + @Override + protected void okPressed() { + + handler.sourceKeyFile = sourceKeyFileField.getText(); + handler.destinationKeyFile = destinationKeyFileField.getText(); + if((!sourceKeyFileField.getText().isEmpty() && !destinationKeyFileField.getText().isEmpty() && + (new File(sourceKeyFileField.getText())).isFile()) + || regenerate == true ) + { + System.out.println("regenerate = " + regenerate); + super.okPressed(); + } + else + { + if(sourceKeyFileField.getText().isEmpty() && destinationKeyFileField.getText().isEmpty()) + JOptionPane.showMessageDialog(null, "Enclave Signing Key and Import Singing Key are not provided.", "Error", + JOptionPane.ERROR_MESSAGE); + else + { + if(sourceKeyFileField.getText().isEmpty()) + JOptionPane.showMessageDialog(null, "Import Singing Key is not provided.", "Error", + JOptionPane.ERROR_MESSAGE); + else + if(!(new File(sourceKeyFileField.getText())).isFile()) + JOptionPane.showMessageDialog(null, "Invalid Import Singing Key.", "Error", + JOptionPane.ERROR_MESSAGE); + + if(destinationKeyFileField.getText().isEmpty()) + JOptionPane.showMessageDialog(null, "Enclave Signing Key is not provided.", "Error", + JOptionPane.ERROR_MESSAGE); + } + } + + } + + + +} diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/src/com/intel/sgx/discovery/SGXSDKDiscoveredPathInfo.java b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/src/com/intel/sgx/discovery/SGXSDKDiscoveredPathInfo.java new file mode 100644 index 0000000000..2c48b2fb39 --- /dev/null +++ b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/src/com/intel/sgx/discovery/SGXSDKDiscoveredPathInfo.java @@ -0,0 +1,202 @@ +/////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2016 Intel Corporation. // +// // +// All rights reserved. This program and the accompanying materials // +// are made available under the terms of the Eclipse Public License v1.0 // +// which accompanies this distribution, and is available at // +// http://www.eclipse.org/legal/epl-v10.html // +// // +// Contributors: // +// Intel Corporation - initial implementation and documentation // +/////////////////////////////////////////////////////////////////////////// + + +package com.intel.sgx.discovery; + +import java.util.List; +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; +import java.io.IOException; +import java.io.PrintStream; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; +import java.util.Map.Entry; + +import org.eclipse.cdt.core.CCorePlugin; +import org.eclipse.cdt.core.model.CoreModel; +import org.eclipse.cdt.make.core.scannerconfig.IDiscoveredPathManager.IDiscoveredPathInfo; +import org.eclipse.cdt.make.core.scannerconfig.IDiscoveredPathManager.IDiscoveredScannerInfoSerializable; +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.Path; + +import com.intel.sgx.Activator; +/* + * This code has been taken from the NDK plugin for Linux. If there is an update to this code there, then refactor this code. + */ +public class SGXSDKDiscoveredPathInfo implements IDiscoveredPathInfo { + + private final IProject mProject; + private long mLastUpdate = IFile.NULL_STAMP; + private IPath[] mIncludePaths; + private Map mSymbols; + private boolean mNeedReindexing = false; + private static final IPath LINUX_MK = new Path("sgx/Makefile"); + + //Keys for preferences + // public static final String LAST_UPDATE = "lastUpdate"; //$NON-NLS-1$ + + + public SGXSDKDiscoveredPathInfo(IProject project) { + this.mProject = project; + load(); + } + + @Override + public IProject getProject() { + return mProject; + } + + @Override + public IPath[] getIncludePaths() { + if (mNeedReindexing) { + CCorePlugin.getIndexManager().reindex(CoreModel.getDefault().create(mProject)); + mNeedReindexing = false; + } + return mIncludePaths; + } + + void setIncludePaths(List pathStrings) { + mIncludePaths = new IPath[pathStrings.size()]; + int i = 0; + for (String path : pathStrings) + mIncludePaths[i++] = new Path(path); + mNeedReindexing = true; + } + + @Override + public Map getSymbols() { + if (mSymbols == null) + mSymbols = new HashMap(); + return mSymbols; + } + + void setSymbols(Map symbols) { + this.mSymbols = symbols; + } + + @Override + public IDiscoveredScannerInfoSerializable getSerializable() { + return null; + } + + public void update(IProgressMonitor monitor) throws CoreException { + if (!needUpdating()) + return; + + new SGXSDKDiscoveryUpdater(this).runUpdate(monitor); + + if (mIncludePaths != null && mSymbols != null) { + recordUpdate(); + save(); + } + } + + private boolean needUpdating() { + + + if (mLastUpdate == IFile.NULL_STAMP) { + return true; + } + + return mProject.getFile(LINUX_MK).getLocalTimeStamp() > mLastUpdate; + } + + private void recordUpdate() { + mLastUpdate = mProject.getFile(LINUX_MK).getLocalTimeStamp(); + } + + public void delete() { + mLastUpdate = IFile.NULL_STAMP; + } + + private File getInfoFile() { + File stateLoc = Activator.getDefault().getStateLocation().toFile(); + return new File(stateLoc, mProject.getName() + ".pathInfo"); //$NON-NLS-1$ + } + + private void save() { + try { + File infoFile = getInfoFile(); + infoFile.getParentFile().mkdirs(); + PrintStream out = new PrintStream(infoFile); + + out.print("t,"); //$NON-NLS-1$ + out.print(mLastUpdate); + out.println(); + + for (IPath include : mIncludePaths) { + out.print("i,"); //$NON-NLS-1$ + out.print(include.toPortableString()); + out.println(); + } + + for (Entry symbol : mSymbols.entrySet()) { + out.print("d,"); //$NON-NLS-1$ + out.print(symbol.getKey()); + out.print(","); //$NON-NLS-1$ + out.print(symbol.getValue()); + out.println(); + } + + out.close(); + } catch (IOException e) { + Activator.log(e); + } + + } + + private void load() { + try { + File infoFile = getInfoFile(); + if (!infoFile.exists()) + return; + + long timestamp = IFile.NULL_STAMP; + List includes = new ArrayList(); + Map defines = new HashMap(); + + BufferedReader reader = new BufferedReader(new FileReader(infoFile)); + for (String line = reader.readLine(); line != null; line = reader.readLine()) { + switch (line.charAt(0)) { + case 't': + timestamp = Long.valueOf(line.substring(2)); + break; + case 'i': + includes.add(Path.fromPortableString(line.substring(2))); + break; + case 'd': + int n = line.indexOf(',', 2); + if (n == -1) + defines.put(line.substring(2), ""); //$NON-NLS-1$ + else + defines.put(line.substring(2, n), line.substring(n + 1)); + break; + } + } + reader.close(); + + mLastUpdate = timestamp; + mIncludePaths = includes.toArray(new IPath[includes.size()]); + mSymbols = defines; + } catch (IOException e) { + Activator.log(e); + } + } + +} diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/src/com/intel/sgx/discovery/SGXSDKDiscoveryUpdater.java b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/src/com/intel/sgx/discovery/SGXSDKDiscoveryUpdater.java new file mode 100644 index 0000000000..4c10fccdcc --- /dev/null +++ b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/src/com/intel/sgx/discovery/SGXSDKDiscoveryUpdater.java @@ -0,0 +1,310 @@ +/////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2016 Intel Corporation. // +// // +// All rights reserved. This program and the accompanying materials // +// are made available under the terms of the Eclipse Public License v1.0 // +// which accompanies this distribution, and is available at // +// http://www.eclipse.org/legal/epl-v10.html // +// // +// Contributors: // +// Intel Corporation - initial implementation and documentation // +/////////////////////////////////////////////////////////////////////////// + + +package com.intel.sgx.discovery; + +import java.io.BufferedReader; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.net.URISyntaxException; +import java.net.URL; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +import org.eclipse.cdt.core.CCorePlugin; +import org.eclipse.cdt.core.envvar.IEnvironmentVariable; +import org.eclipse.cdt.core.envvar.IEnvironmentVariableManager; +import org.eclipse.cdt.core.settings.model.ICConfigurationDescription; +import org.eclipse.cdt.managedbuilder.core.IBuilder; +import org.eclipse.cdt.managedbuilder.core.IManagedBuildInfo; +import org.eclipse.cdt.managedbuilder.core.ManagedBuildManager; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.FileLocator; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.Path; + +import com.intel.sgx.Activator; +import com.intel.sgx.build.SGXSDKCommandLauncher; + +/* + * This code has been taken from the NDK plugin for Linux. If there is an update to this code there, then refactor this code. + */ +public class SGXSDKDiscoveryUpdater { + private final SGXSDKDiscoveredPathInfo mPathInfo; + private final IProject mProject; + + private boolean mCPlusPlus = false; + private String mCommand; + private List mArguments = new ArrayList(); + + public SGXSDKDiscoveryUpdater(SGXSDKDiscoveredPathInfo pathInfo) { + mPathInfo = pathInfo; + mProject = pathInfo.getProject(); + } + + public void runUpdate(IProgressMonitor monitor) throws CoreException { + try { + // Run make -nB to get the list of commands + IPath commandPath = new Path("make"); //$NON-NLS-1$ + String[] args = {"-f", "sgx/Makefile", "-n", "-B" }; //$NON-NLS-1$ + String[] env = calcEnvironment(); + File projectDir = new File(mProject.getLocationURI()); + IPath changeToDirectory = new Path(projectDir.getAbsolutePath()); + Process proc = new SGXSDKCommandLauncher().execute(commandPath, args, env,changeToDirectory, monitor); + if (proc == null) { + return; + } + + BufferedReader reader = new BufferedReader(new InputStreamReader(proc.getInputStream())); + String line = reader.readLine(); + while (line != null) { + checkBuildLine(line); + line = reader.readLine(); + } + + if (mCommand == null) { + return; + } + + // Run the unique commands with special gcc options to extract the + // symbols and paths + // -E -P -v -dD + mArguments.add("-E"); //$NON-NLS-1$ + mArguments.add("-P"); //$NON-NLS-1$ + mArguments.add("-v"); //$NON-NLS-1$ + mArguments.add("-dD"); //$NON-NLS-1$ + + URL url = Activator.findFile(new Path("discovery/" + (mCPlusPlus ? "test.cpp" : "test.c"))); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + File testFile = new File(FileLocator.toFileURL(url).toURI()); + String testFileName = testFile.getAbsolutePath().replace('\\', '/'); + mArguments.add(testFileName); + + args = mArguments.toArray(new String[mArguments.size()]); + proc = new SGXSDKCommandLauncher().execute(new Path(mCommand), args, env,changeToDirectory, monitor); + + final InputStream errStream = proc.getErrorStream(); + new Thread() { + @Override + public void run() { + checkIncludes(errStream); + }; + }.start(); + + checkDefines(proc.getInputStream()); + } catch (IOException e) { + throw new CoreException(Activator.newStatus(e)); + } catch (URISyntaxException e) { + throw new CoreException(Activator.newStatus(e)); + } + } + + private String[] calcEnvironment() throws CoreException { + IManagedBuildInfo info = ManagedBuildManager.getBuildInfo(mProject); + IBuilder builder = info.getDefaultConfiguration().getBuilder(); + HashMap envMap = new HashMap(); + if (builder.appendEnvironment()) { + ICConfigurationDescription cfgDes = ManagedBuildManager.getDescriptionForConfiguration(builder.getParent().getParent()); + IEnvironmentVariableManager mngr = CCorePlugin.getDefault().getBuildEnvironmentManager(); + IEnvironmentVariable[] vars = mngr.getVariables(cfgDes, true); + for (IEnvironmentVariable var : vars) { + envMap.put(var.getName(), var.getValue()); + } + } + // Add variables from build info + Map builderEnv = builder.getExpandedEnvironment(); + if (builderEnv != null) + envMap.putAll(builderEnv); + List strings = new ArrayList(envMap.size()); + for (Entry entry : envMap.entrySet()) { + StringBuffer buffer = new StringBuffer(entry.getKey()); + buffer.append('=').append(entry.getValue()); + strings.add(buffer.toString()); + } + return strings.toArray(new String[strings.size()]); + } + + private static class Line { + private final String line; + private int pos; + + public Line(String line) { + this.line = line; + } + + public Line(String line, int pos) { + this(line); + this.pos = pos; + } + + public String getToken() { + skipWhiteSpace(); + if (pos == line.length()) + return null; + + int start = pos; + boolean inQuote = false; + + while (true) { + char c = line.charAt(pos); + if (c == ' ') { + if (!inQuote) + return line.substring(start, pos); + } else if (c == '"') { + inQuote = !inQuote; + } + + if (++pos == line.length()) + return null; + } + + } + + private String getRemaining() { + if (pos == line.length()) + return null; + + skipWhiteSpace(); + String rc = line.substring(pos); + pos = line.length(); + return rc; + } + + private void skipWhiteSpace() { + while (true) { + if (pos == line.length()) + return; + char c = line.charAt(pos); + if (c == ' ') + pos++; + else + return; + } + } + } + + private void checkBuildLine(String text) { + Line line = new Line(text); + String cmd = line.getToken(); + if (cmd == null) { + return; + } else if (cmd.endsWith("g++")) { //$NON-NLS-1$ + if (mCommand == null || !mCPlusPlus) { + mCommand = cmd; + mCPlusPlus = true; + } + gatherOptions(line); + } else if (cmd.endsWith("gcc")) { //$NON-NLS-1$ + if (mCommand == null){ + mCommand = cmd; + } + gatherOptions(line); + } + + } + + private void gatherOptions(Line line) { + for (String option = line.getToken(); option != null; option = line.getToken()) { + if (option.startsWith("-")) { //$NON-NLS-1$ + // only look at options + if (option.equals("-I")) { //$NON-NLS-1$ + String dir = line.getToken(); + if (dir != null) + addArg(option + dir); + } else if (option.startsWith("-I")) { //$NON-NLS-1$ + addArg(option); + } else if (option.equals("-D")) { //$NON-NLS-1$ + String def = line.getToken(); + if (def != null) + addArg(option + def); + } else if (option.startsWith("-D")) { //$NON-NLS-1$ + addArg(option); + } else if (option.startsWith("-f")) { //$NON-NLS-1$ + addArg(option); + } else if (option.startsWith("-m")) { //$NON-NLS-1$ + addArg(option); + } else if (option.startsWith("--sysroot")) { //$NON-NLS-1$ + addArg(option); + } + } + } + } + + private void addArg(String arg) { + if (!mArguments.contains(arg)) + mArguments.add(arg); + } + + private void checkIncludes(InputStream in) { + try { + List includes = new ArrayList(); + boolean inIncludes1 = false; + boolean inIncludes2 = false; + BufferedReader reader = new BufferedReader(new InputStreamReader(in)); + String line = reader.readLine(); + while (line != null) { + if (!inIncludes1) { + if (line.equals("#include \"...\" search starts here:")) //$NON-NLS-1$ + inIncludes1 = true; + } else { + if (!inIncludes2) { + if (line.equals("#include <...> search starts here:")) //$NON-NLS-1$ + inIncludes2 = true; + else + includes.add(line.trim()); + } else { + if (line.equals("End of search list.")) { //$NON-NLS-1$ + mPathInfo.setIncludePaths(includes); + } else { + includes.add(line.trim()); + } + } + } + line = reader.readLine(); + } + } catch (IOException e) { + Activator.log(e); + } + } + + private void checkDefines(InputStream in) { + try { + Map defines = new HashMap(); + BufferedReader reader = new BufferedReader(new InputStreamReader(in)); + String line = reader.readLine(); + while (line != null) { + if (line.startsWith("#define")) { //$NON-NLS-1$ + Line l = new Line(line, 7); + String var = l.getToken(); + if (var == null) + continue; + String value = l.getRemaining(); + if (value == null) + value = ""; //$NON-NLS-1$ + defines.put(var, value); + } + line = reader.readLine(); + } + mPathInfo.setSymbols(defines); + } catch (IOException e) { + Activator.log(e); + } + } + +} diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/src/com/intel/sgx/discovery/SGXSDKScannerInfoCollector.java b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/src/com/intel/sgx/discovery/SGXSDKScannerInfoCollector.java new file mode 100644 index 0000000000..fb21bff5cf --- /dev/null +++ b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/src/com/intel/sgx/discovery/SGXSDKScannerInfoCollector.java @@ -0,0 +1,103 @@ +/////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2016 Intel Corporation. // +// // +// All rights reserved. This program and the accompanying materials // +// are made available under the terms of the Eclipse Public License v1.0 // +// which accompanies this distribution, and is available at // +// http://www.eclipse.org/legal/epl-v10.html // +// // +// Contributors: // +// Intel Corporation - initial implementation and documentation // +/////////////////////////////////////////////////////////////////////////// + + +package com.intel.sgx.discovery; + +import java.util.List; +import java.util.Map; + +import org.eclipse.cdt.make.core.scannerconfig.IDiscoveredPathManager.IDiscoveredPathInfo; +import org.eclipse.cdt.make.core.scannerconfig.IScannerInfoCollector3; +import org.eclipse.cdt.make.core.scannerconfig.IScannerInfoCollectorCleaner; +import org.eclipse.cdt.make.core.scannerconfig.InfoContext; +import org.eclipse.cdt.make.core.scannerconfig.ScannerInfoTypes; +import org.eclipse.cdt.managedbuilder.scannerconfig.IManagedScannerInfoCollector; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; + +/* + * This code has been taken from the NDK plugin for Linux. If there is an update to this code there, then refactor this code. + */ +public class SGXSDKScannerInfoCollector implements IScannerInfoCollector3,IScannerInfoCollectorCleaner,IManagedScannerInfoCollector{ + + private SGXSDKDiscoveredPathInfo sgxPathInfo; + + @Override + public void setProject(IProject project) { + throw new Error("Not implemented"); + } + + @Override + public void updateScannerConfiguration(IProgressMonitor monitor) + throws CoreException { + sgxPathInfo.update(monitor); + } + + @Override + public IDiscoveredPathInfo createPathInfoObject() { + return sgxPathInfo; + } + + @Override + public void contributeToScannerConfig(Object resource, @SuppressWarnings("rawtypes") Map scannerInfo) { + throw new Error("Not implemented"); + } + + @SuppressWarnings("rawtypes") + @Override + public List getCollectedScannerInfo(Object resource, ScannerInfoTypes type) { + throw new Error("Not implemented"); + } + + @Override + public Map getDefinedSymbols() { + throw new Error("Not implemented"); + } + + @Override + public List getIncludePaths() { + throw new Error("Not implemented"); + } + + @Override + public void deleteAllPaths(IResource resource) { + throw new Error("Not implemented"); + } + + @Override + public void deleteAllSymbols(IResource resource) { + throw new Error("Not implemented"); + } + + @Override + public void deletePath(IResource resource, String path) { + throw new Error("Not implemented"); + } + + @Override + public void deleteSymbol(IResource resource, String symbol) { + throw new Error("Not implemented"); + } + + @Override + public void deleteAll(IResource resource) { + sgxPathInfo.delete(); + } + + @Override + public void setInfoContext(InfoContext context) { + sgxPathInfo = new SGXSDKDiscoveredPathInfo(context.getProject()); + } +} diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/src/com/intel/sgx/handlers/AddEnclave.java b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/src/com/intel/sgx/handlers/AddEnclave.java new file mode 100644 index 0000000000..e998de690b --- /dev/null +++ b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/src/com/intel/sgx/handlers/AddEnclave.java @@ -0,0 +1,213 @@ +/////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2016 Intel Corporation. // +// // +// All rights reserved. This program and the accompanying materials // +// are made available under the terms of the Eclipse Public License v1.0 // +// which accompanies this distribution, and is available at // +// http://www.eclipse.org/legal/epl-v10.html // +// // +// Contributors: // +// Intel Corporation - initial implementation and documentation // +/////////////////////////////////////////////////////////////////////////// + + +package com.intel.sgx.handlers; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.Map; + +import org.eclipse.cdt.core.templateengine.TemplateCore; +import org.eclipse.cdt.core.templateengine.TemplateEngine; +import org.eclipse.cdt.managedbuilder.core.ManagedBuildManager; +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.core.commands.IHandler; +import org.eclipse.core.commands.IHandlerListener; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IConfigurationElement; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.NullProgressMonitor; +import org.eclipse.core.runtime.Path; +import org.eclipse.core.runtime.Platform; +import org.eclipse.jface.dialogs.InputDialog; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.ui.handlers.HandlerUtil; + +import com.intel.sgx.Activator; +import com.intel.sgx.dialogs.AddEnclaveFileDialog; +import com.intel.sgx.preferences.PreferenceConstants; + +public class AddEnclave extends ModuleCreationBaseHandler implements IHandler { + + public String edlFilename = ""; + public String linuxMakePath = ""; + @Override + public void addHandlerListener(IHandlerListener handlerListener) { + } + + @Override + public void dispose() { + } + + @Override + public Object execute(ExecutionEvent event) throws ExecutionException { + String edlBasename,linuxPath,enclaveBasename; + IProject project = null; + + // Display display = Display.getCurrent(); + // Shell shell = new Shell(display); + Shell shell = null; + AddEnclaveFileDialog dialog = new AddEnclaveFileDialog(shell, this); + if (dialog.open() != InputDialog.OK) { + return null; + } + + if((edlFilename.isEmpty())){ + System.err.println("No Enclave selected to Import."); + return null; + } + + edlBasename = edlFilename; + ISelection selection = HandlerUtil.getCurrentSelection(event); + Object element = null; + if (selection instanceof IStructuredSelection) { + element = ((IStructuredSelection) selection).getFirstElement(); + if (element instanceof IResource) { + project = ((IResource) element).getProject(); + } + } + if (!project.exists()) { + System.err.println("Error: Project not found"); + return null; + } + + for (IConfigurationElement i : Platform.getExtensionRegistry().getConfigurationElementsFor("org.eclipse.core.resources.projectNature")){ + } + + + + + IPath linuxMkRelPath = (Path.fromOSString(linuxMakePath)).makeRelativeTo(project.getLocation().append("sgx").append("enclave_"+edlBasename)); + + + if(linuxMkRelPath.removeLastSegments(1).lastSegment().toString().equalsIgnoreCase("sgx")){ + linuxPath = linuxMkRelPath.removeLastSegments(3).toOSString(); + enclaveBasename = linuxMkRelPath.removeLastSegments(2).lastSegment().toString(); + } + + else{ + linuxPath = linuxMkRelPath.removeLastSegments(2).toOSString(); + enclaveBasename = linuxMkRelPath.removeLastSegments(1).lastSegment().toString(); + } + + IProgressMonitor monitor = new NullProgressMonitor(); + TemplateCore template = null; + if(isCPProject(project)) + if(dialog.generateApp()) + { + template = TemplateEngine.getDefault().getTemplateById("SGXEnclaveC++WithSample"); + } + else + { + template = TemplateEngine.getDefault().getTemplateById("SGXEnclaveC++Minimal"); + } + else + if(dialog.generateApp()) + { + template = TemplateEngine.getDefault().getTemplateById("SGXEnclaveCWithSample"); + } + else + { + template = TemplateEngine.getDefault().getTemplateById("SGXEnclaveCMinimal"); + } + + Map valueStore = template.getValueStore(); + valueStore.put("projectName", project.getName()); + valueStore.put("workspacePath", linuxPath); + valueStore.put("baseName", enclaveBasename); + valueStore.put("enclaveName",edlFilename); + valueStore.put("EnclaveName",capitalize(edlFilename)); + valueStore.put("ENCLAVENAME",edlFilename.toUpperCase()); + valueStore.put("SdkPathFromPlugin", Activator.getDefault().getPreferenceStore().getString(PreferenceConstants.SDK_PATH)); + + IStatus[] statuses = template.executeTemplateProcesses(monitor, false); + for(IStatus e: statuses) + { + } + + ManagedBuildManager.saveBuildInfo(project, true); + try { + project.refreshLocal(IResource.DEPTH_INFINITE, null); + } catch (CoreException e) { + Activator.log(e); + e.printStackTrace(); + } + + + return null; + } + + private String capitalize(final String line) { + return Character.toUpperCase(line.charAt(0)) + line.substring(1); + } + + @Override + public boolean isEnabled() { + return true; + } + + @Override + public boolean isHandled() { + return true; + } + + @Override + public void removeHandlerListener(IHandlerListener handlerListener) { + } + + public void setFilename(String filename) { + edlFilename = filename; + } + + + + + public static void copyFile(File source, File dest) throws IOException { + byte[] bytes = new byte[4092]; + if (source != null && dest != null) { + if (source.isFile()) { + FileInputStream in = null; + FileOutputStream out = null; + try { + in = new FileInputStream(source); + out = new FileOutputStream(dest); + int len; + while ((len = in.read(bytes)) != -1) { + out.write(bytes, 0, len); + } + } catch (Exception e) { + Activator.log(e); + System.err.println("Error: " + e.toString()); + } finally { + try { + if (in != null) + in.close(); + } finally { + if (out != null) + out.close(); + } + } + } + } + } + +} diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/src/com/intel/sgx/handlers/AddSGXNature.java b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/src/com/intel/sgx/handlers/AddSGXNature.java new file mode 100644 index 0000000000..569b608adb --- /dev/null +++ b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/src/com/intel/sgx/handlers/AddSGXNature.java @@ -0,0 +1,163 @@ +/////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2016 Intel Corporation. // +// // +// All rights reserved. This program and the accompanying materials // +// are made available under the terms of the Eclipse Public License v1.0 // +// which accompanies this distribution, and is available at // +// http://www.eclipse.org/legal/epl-v10.html // +// // +// Contributors: // +// Intel Corporation - initial implementation and documentation // +/////////////////////////////////////////////////////////////////////////// + + +package com.intel.sgx.handlers; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.lang.reflect.InvocationTargetException; +import java.util.Map; + +import org.eclipse.cdt.core.templateengine.TemplateCore; +import org.eclipse.cdt.core.templateengine.TemplateEngine; +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.core.commands.IHandler; +import org.eclipse.core.commands.IHandlerListener; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IProjectDescription; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.IWorkspace; +//import org.eclipse.core.resources.IWorkspaceRunnable; +//import org.eclipse.core.resources.IWorkspaceRunnable; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.NullProgressMonitor; +//import org.eclipse.jface.operation.IRunnableWithProgress; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.ui.handlers.HandlerUtil; + +import com.intel.sgx.Activator; +import com.intel.sgx.natures.SGXNature; + +public class AddSGXNature implements IHandler { + + private IProject project; + + public AddSGXNature() { + project = null; + } + + @Override + public void addHandlerListener(IHandlerListener arg0) { + } + + @Override + public void dispose() { + } + + @Override + public Object execute(ExecutionEvent event) throws ExecutionException { + ISelection selection = HandlerUtil.getCurrentSelection(event); + Object element = null; + if (selection instanceof IStructuredSelection) { + element = ((IStructuredSelection) selection).getFirstElement(); + if (element instanceof IResource) { + project = ((IResource) element).getProject(); + } + } + if (!project.exists()) { + System.err.println("Error: Project not found"); + return null; + } else { + try { + TemplateCore template = TemplateEngine.getDefault().getTemplateById("AddSGXNature"); + + Map valueStore = template.getValueStore(); + valueStore.put("projectName",project.getName()); + valueStore.put("baseName",project.getName()); + + IProgressMonitor monitor = new NullProgressMonitor(); + template.executeTemplateProcesses(monitor, false); + + IWorkspace workspace = ResourcesPlugin.getWorkspace(); + try{ + IProjectDescription description = project.getDescription(); + String[] natures = description.getNatureIds(); + + String[] newNatures = new String[natures.length + 1]; + System.arraycopy(natures, 0, newNatures, 0, natures.length); + newNatures[natures.length] = SGXNature.NATURE_ID; + IStatus status = workspace.validateNatureSet(newNatures); + + if (status.getCode() == IStatus.OK) { + description.setNatureIds(newNatures); + project.setDescription(description, null); + } + + project.refreshLocal(IResource.DEPTH_ONE,null); + } catch(CoreException e){ + Activator.log(e); + throw new InvocationTargetException(e); + } + } catch(InvocationTargetException e){ + Activator.log(e); + e.printStackTrace(); + } + + try { + project.refreshLocal(IResource.DEPTH_INFINITE,null); + } catch (CoreException e) { + e.printStackTrace(); + } + } + return null; + } + + @Override + public boolean isEnabled() { + return true; + } + + @Override + public boolean isHandled() { + return true; + } + + @Override + public void removeHandlerListener(IHandlerListener arg0) { + } + + public static void copyFile(File source, File dest) throws IOException { + byte[] bytes = new byte[4092]; + if (source != null && dest != null) { + if (source.isFile()) { + FileInputStream in = null; + FileOutputStream out = null; + try { + in = new FileInputStream(source); + out = new FileOutputStream(dest); + int len; + while ((len = in.read(bytes)) != -1) { + out.write(bytes, 0, len); + } + } catch (Exception e) { + System.err.println("Error: " + e.toString()); + + } finally { + try { + if (in != null) + in.close(); + } finally { + if (out != null) + out.close(); + } + } + } + } + } +} diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/src/com/intel/sgx/handlers/AddTrustedStaticLib.java b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/src/com/intel/sgx/handlers/AddTrustedStaticLib.java new file mode 100644 index 0000000000..efeeeedd3a --- /dev/null +++ b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/src/com/intel/sgx/handlers/AddTrustedStaticLib.java @@ -0,0 +1,193 @@ +/////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2016 Intel Corporation. // +// // +// All rights reserved. This program and the accompanying materials // +// are made available under the terms of the Eclipse Public License v1.0 // +// which accompanies this distribution, and is available at // +// http://www.eclipse.org/legal/epl-v10.html // +// // +// Contributors: // +// Intel Corporation - initial implementation and documentation // +/////////////////////////////////////////////////////////////////////////// + + +package com.intel.sgx.handlers; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.Map; + +import org.eclipse.cdt.core.templateengine.TemplateCore; +import org.eclipse.cdt.core.templateengine.TemplateEngine; +import org.eclipse.cdt.managedbuilder.core.ManagedBuildManager; +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.core.commands.IHandler; +import org.eclipse.core.commands.IHandlerListener; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IConfigurationElement; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.NullProgressMonitor; +import org.eclipse.core.runtime.Path; +import org.eclipse.core.runtime.Platform; +import org.eclipse.jface.dialogs.InputDialog; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.ui.handlers.HandlerUtil; + +import com.intel.sgx.Activator; +import com.intel.sgx.dialogs.AddTrustedStaticLibFileDialog; +import com.intel.sgx.preferences.PreferenceConstants; + +public class AddTrustedStaticLib extends ModuleCreationBaseHandler implements IHandler { + + public String edlFilename = ""; + public String linuxMakePath = ""; + + @Override + public void addHandlerListener(IHandlerListener handlerListener) { + } + + @Override + public void dispose() { + } + + @Override + public Object execute(ExecutionEvent event) throws ExecutionException { + String edlBasename,linuxPath,enclaveBasename; + IProject project = null; + + // Display display = Display.getCurrent(); + // Shell shell = new Shell(display); + Shell shell = null; + AddTrustedStaticLibFileDialog dialog = new AddTrustedStaticLibFileDialog(shell, this); + if (dialog.open() != InputDialog.OK) { + return null; + } + + if((edlFilename.isEmpty() )){ + System.err.println("No Enclave selected to Import."); + return null; + } + + edlBasename = edlFilename; + ISelection selection = HandlerUtil.getCurrentSelection(event); + Object element = null; + if (selection instanceof IStructuredSelection) { + element = ((IStructuredSelection) selection).getFirstElement(); + if (element instanceof IResource) { + project = ((IResource) element).getProject(); + } + } + if (!project.exists()) { + System.err.println("Error: Project not found"); + return null; + } + + for (IConfigurationElement i : Platform.getExtensionRegistry().getConfigurationElementsFor("org.eclipse.core.resources.projectNature")){ + } + + + + + IPath linuxMkRelPath = (Path.fromOSString(linuxMakePath)).makeRelativeTo(project.getLocation().append("sgx").append("enclave_"+edlBasename)); + + + if(linuxMkRelPath.removeLastSegments(1).lastSegment().toString().equalsIgnoreCase("sgx")){ + linuxPath = linuxMkRelPath.removeLastSegments(3).toOSString(); + enclaveBasename = linuxMkRelPath.removeLastSegments(2).lastSegment().toString(); + } + + else{ + linuxPath = linuxMkRelPath.removeLastSegments(2).toOSString(); + enclaveBasename = linuxMkRelPath.removeLastSegments(1).lastSegment().toString(); + } + + IProgressMonitor monitor = new NullProgressMonitor(); + TemplateCore template = null; + if(isCPProject(project)) + template = TemplateEngine.getDefault().getTemplateById("SGXTrustedStaticLibraryC++Minimal"); + else + template = TemplateEngine.getDefault().getTemplateById("SGXTrustedStaticLibraryCMinimal"); + + Map valueStore = template.getValueStore(); + valueStore.put("projectName", project.getName()); + valueStore.put("workspacePath", linuxPath); + valueStore.put("baseName", enclaveBasename); + valueStore.put("enclaveName",edlFilename); + valueStore.put("EnclaveName",capitalize(edlFilename)); + valueStore.put("ENCLAVENAME",edlFilename.toUpperCase()); + valueStore.put("SdkPathFromPlugin", Activator.getDefault().getPreferenceStore().getString(PreferenceConstants.SDK_PATH)); + + IStatus[] statuses = template.executeTemplateProcesses(monitor, false); + + + ManagedBuildManager.saveBuildInfo(project, true); + try { + project.refreshLocal(IResource.DEPTH_INFINITE, null); + } catch (CoreException e) { + Activator.log(e); + e.printStackTrace(); + } + return null; + } + + private String capitalize(final String line) { + return Character.toUpperCase(line.charAt(0)) + line.substring(1); + } + + @Override + public boolean isEnabled() { + return true; + } + + @Override + public boolean isHandled() { + return true; + } + + @Override + public void removeHandlerListener(IHandlerListener handlerListener) { + } + + public void setFilename(String filename) { + edlFilename = filename; + } + + public static void copyFile(File source, File dest) throws IOException { + byte[] bytes = new byte[4092]; + if (source != null && dest != null) { + if (source.isFile()) { + FileInputStream in = null; + FileOutputStream out = null; + try { + in = new FileInputStream(source); + out = new FileOutputStream(dest); + int len; + while ((len = in.read(bytes)) != -1) { + out.write(bytes, 0, len); + } + } catch (Exception e) { + Activator.log(e); + System.err.println("Error: " + e.toString()); + } finally { + try { + if (in != null) + in.close(); + } finally { + if (out != null) + out.close(); + } + } + } + } + } + +} diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/src/com/intel/sgx/handlers/AddUntrustedModule.java b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/src/com/intel/sgx/handlers/AddUntrustedModule.java new file mode 100644 index 0000000000..4ebf8da34c --- /dev/null +++ b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/src/com/intel/sgx/handlers/AddUntrustedModule.java @@ -0,0 +1,231 @@ +/////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2016 Intel Corporation. // +// // +// All rights reserved. This program and the accompanying materials // +// are made available under the terms of the Eclipse Public License v1.0 // +// which accompanies this distribution, and is available at // +// http://www.eclipse.org/legal/epl-v10.html // +// // +// Contributors: // +// Intel Corporation - initial implementation and documentation // +/////////////////////////////////////////////////////////////////////////// + + +package com.intel.sgx.handlers; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.Map; + + + +import org.eclipse.cdt.core.templateengine.TemplateCore; +import org.eclipse.cdt.core.templateengine.TemplateEngine; +import org.eclipse.cdt.managedbuilder.core.ManagedBuildManager; +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.core.commands.IHandler; +import org.eclipse.core.commands.IHandlerListener; + +import org.eclipse.core.resources.IFolder; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.NullProgressMonitor; +import org.eclipse.core.runtime.Path; + +import org.eclipse.jface.dialogs.InputDialog; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.ui.handlers.HandlerUtil; + +import com.intel.sgx.Activator; +import com.intel.sgx.dialogs.AddUntrustedModuleDialog; +import com.intel.sgx.preferences.PreferenceConstants; + +public class AddUntrustedModule extends ModuleCreationBaseHandler implements IHandler { + + public String edlFilename = ""; + public String libPath = ""; + private IPath edlCanonicalFilename; + private IPath libCanonicalPathname; + + @Override + public void addHandlerListener(IHandlerListener handlerListener) { + } + + @Override + public void dispose() { + } + + @Override + public Object execute(ExecutionEvent event) throws ExecutionException { + String edlBasename,edlPath,linuxLibPath,modulePath,enclaveBasename; + IProject project = null; + + //Display display = Display.getCurrent(); + Shell shell = null; + + AddUntrustedModuleDialog dialog = new AddUntrustedModuleDialog(shell, this); + if (dialog.open() != InputDialog.OK) { + return null; + } + + if((edlFilename.isEmpty() && libPath.isEmpty())){ + System.err.println("No Enclave selected to Import."); + return null; + } + if( edlFilename.isEmpty() ){ + System.err.println("Edl File not selected."); + return null; + } + edlCanonicalFilename = Path.fromOSString(edlFilename); + if (!edlCanonicalFilename.getFileExtension().toLowerCase().equals("edl")) { + System.err.println("Error: EDL file extension = "+ edlCanonicalFilename.getFileExtension()); + return null; + } + edlBasename = edlCanonicalFilename.removeFileExtension().lastSegment(); + + + ISelection selection = HandlerUtil.getCurrentSelection(event); + Object element = null; + if (selection instanceof IStructuredSelection) { + element = ((IStructuredSelection) selection).getFirstElement(); + if (element instanceof IResource) { + project = ((IResource) element).getProject(); + } + } + if (!project.exists()) { + System.err.println("Error: Project not found"); + return null; + } + + IPath targetRelPath = project.getProjectRelativePath().append("sgx").append("untrusted_" + edlBasename); + + try { + for (int i = 1; i <= targetRelPath.segmentCount(); i++) { + IFolder subfolder = project.getFolder(targetRelPath.uptoSegment(i)); + + if (!subfolder.exists()) { + subfolder.create(true, true, null); + } + } + } catch (CoreException e) { + System.err.println("Error: Error creating enclave directory."); + Activator.log(e); + e.printStackTrace(); + } + + IPath edlRelPath = (Path.fromOSString(edlFilename)).makeRelativeTo(project.getLocation().append("sgx")); + edlPath = edlRelPath.toOSString(); + IPath linuxLibRelPath = (Path.fromOSString(libPath)).makeRelativeTo(project.getLocation().append("sgx")); + + if(linuxLibRelPath.removeLastSegments(1).lastSegment().toString().equalsIgnoreCase("sgx")){ + linuxLibPath = linuxLibRelPath.removeLastSegments(3).toOSString(); + modulePath = linuxLibRelPath.removeFirstSegments(linuxLibRelPath.segmentCount()-3).removeLastSegments(1).toOSString(); + } + else if(linuxLibRelPath.removeLastSegments(1).lastSegment().toString().equalsIgnoreCase("src")){ + linuxLibPath = linuxLibRelPath.removeLastSegments(3).toOSString(); + modulePath = linuxLibRelPath.removeFirstSegments(linuxLibRelPath.segmentCount()-3).removeLastSegments(1).toOSString(); + } + else{ + linuxLibPath = linuxLibRelPath.removeLastSegments(2).toOSString(); + modulePath = linuxLibRelPath.removeFirstSegments(linuxLibRelPath.segmentCount()-2).removeLastSegments(1).toOSString(); + } + + IProgressMonitor monitor = new NullProgressMonitor(); + TemplateCore template = null; + if(isCPProject(project)) + template = TemplateEngine.getDefault().getTemplateById("SGXUntrustedModuleC++Minimal"); + else + template = TemplateEngine.getDefault().getTemplateById("SGXUntrustedModuleCMinimal"); + + + + Map valueStore = template.getValueStore(); + + + valueStore.put("projectName", project.getName()); + valueStore.put("sourcepath",linuxLibPath); + valueStore.put("edlPath", edlPath); + valueStore.put("baseName", edlBasename); + valueStore.put("workspacePath", linuxLibPath);//deprecate + valueStore.put("modPath", modulePath); + valueStore.put("ENCLAVENAME",edlBasename.toUpperCase()); + valueStore.put("libPath",libPath); + valueStore.put("SdkPathFromPlugin", Activator.getDefault().getPreferenceStore().getString(PreferenceConstants.SDK_PATH)); + + IStatus[] statuses = template.executeTemplateProcesses(monitor, false); + + try { + copyFile(new File(edlFilename), project.getLocation().append("sgx").append("untrusted_"+edlBasename).append(edlBasename+".edl").toFile()); + } catch (IOException e1) { + e1.printStackTrace(); + } + + + ManagedBuildManager.saveBuildInfo(project, true); + try { + project.refreshLocal(IResource.DEPTH_INFINITE, null); + } catch (CoreException e) { + Activator.log(e); + e.printStackTrace(); + } + return null; + } + + @Override + public boolean isEnabled() { + return true; + } + + @Override + public boolean isHandled() { + return true; + } + + @Override + public void removeHandlerListener(IHandlerListener handlerListener) { + } + + public void setFilename(String filename) { + edlFilename = filename; + } + + public static void copyFile(File source, File dest) throws IOException { + byte[] bytes = new byte[4092]; + if (source != null && dest != null) { + if (source.isFile()) { + FileInputStream in = null; + FileOutputStream out = null; + try { + in = new FileInputStream(source); + out = new FileOutputStream(dest); + int len; + while ((len = in.read(bytes)) != -1) { + out.write(bytes, 0, len); + } + } catch (Exception e) { + Activator.log(e); + System.err.println("Error: " + e.toString()); + } finally { + try { + if (in != null) + in.close(); + } finally { + if (out != null) + out.close(); + } + } + } + } + } + +} diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/src/com/intel/sgx/handlers/EnclaveConfigHandler.java b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/src/com/intel/sgx/handlers/EnclaveConfigHandler.java new file mode 100644 index 0000000000..fffa912c4f --- /dev/null +++ b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/src/com/intel/sgx/handlers/EnclaveConfigHandler.java @@ -0,0 +1,156 @@ +/////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2016 Intel Corporation. // +// // +// All rights reserved. This program and the accompanying materials // +// are made available under the terms of the Eclipse Public License v1.0 // +// which accompanies this distribution, and is available at // +// http://www.eclipse.org/legal/epl-v10.html // +// // +// Contributors: // +// Intel Corporation - initial implementation and documentation // +/////////////////////////////////////////////////////////////////////////// + + +package com.intel.sgx.handlers; + +import java.io.File; +import java.io.IOException; +import java.util.Map; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; + +import org.eclipse.cdt.core.templateengine.TemplateCore; +import org.eclipse.cdt.core.templateengine.TemplateEngine; +import org.eclipse.core.commands.IHandlerListener; +import org.eclipse.core.resources.IFile; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.NullProgressMonitor; +import org.eclipse.jface.dialogs.Dialog; +import org.eclipse.jface.dialogs.InputDialog; +import org.eclipse.ui.dialogs.FilteredResourcesSelectionDialog; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import org.xml.sax.SAXException; + +import com.intel.sgx.Activator; +import com.intel.sgx.dialogs.EnclaveConfigDialog; +import com.intel.sgx.dialogs.SGXDialogBase; + +public class EnclaveConfigHandler extends SGXHandler { + + public String prodId; + public String isvSvn; + public String threadStackSize; + public String globalHeapSize; + public String tcsNum; + public String tcsPolicy; + public String disableDebug; + private IFile configPath; + + @Override + public void addHandlerListener(IHandlerListener arg0) { + } + + @Override + public void dispose() { + } + + @Override + public Object executeSGXStuff() throws CancelException, ErrorException { + + FilteredResourcesSelectionDialog d = SGXDialogBase + .dialogForConfig(shell); + d.setTitle("Select Config File"); + if (d.open() != Dialog.OK) { + cancel(); + } + + configPath = ((IFile) d.getResult()[0]); + + readConfig(configPath.getLocation()); + EnclaveConfigDialog dialog = new EnclaveConfigDialog(shell, this); + if (dialog.open() != InputDialog.OK) { + return null; + } + writeConfig(); + refreshProject(); + + return null; + } + + protected void writeConfig() { + IProgressMonitor monitor = new NullProgressMonitor(); + TemplateCore template = TemplateEngine.getDefault().getTemplateById("SGXEnclaveConfig"); + + Map valueStore = template.getValueStore(); + valueStore.put("projectName", project.getName()); + valueStore.put("configFile", configPath.getProjectRelativePath().toOSString()); + valueStore.put("ProdID", this.prodId); + valueStore.put("IsvSvn", this.isvSvn); + valueStore.put("ThreadStackSize", this.threadStackSize); + valueStore.put("GlobalHeapSize", this.globalHeapSize); + valueStore.put("TcsNumber", this.tcsNum); + valueStore.put("TcsPolicy", this.tcsPolicy); + valueStore.put("DisableDebug", this.disableDebug); + IStatus[] result = template.executeTemplateProcesses(monitor, true); + + for (IStatus status: result) { + } + } + + + + protected void readConfig(IPath configPath) throws ErrorException { + + try { + String xmlFile = configPath.toString(); + File configFile = new File(xmlFile); + DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance(); + DocumentBuilder dBuilder; + dBuilder = dbFactory.newDocumentBuilder(); + Document doc = dBuilder.parse(configFile); + doc.getDocumentElement().normalize(); + + NodeList nList = doc.getElementsByTagName("EnclaveConfiguration"); + Node nNode = nList.item(0); + + if (nNode.getNodeType() == Node.ELEMENT_NODE) { + Element e = (Element) nNode; + this.prodId = e.getElementsByTagName("ProdID").item(0) + .getTextContent(); + this.isvSvn = e.getElementsByTagName("ISVSVN").item(0) + .getTextContent(); + this.threadStackSize = e.getElementsByTagName("StackMaxSize") + .item(0).getTextContent(); + this.globalHeapSize = e.getElementsByTagName("HeapMaxSize") + .item(0).getTextContent(); + this.tcsNum = e.getElementsByTagName("TCSNum").item(0) + .getTextContent(); + this.tcsPolicy = e.getElementsByTagName("TCSPolicy").item(0) + .getTextContent(); + this.disableDebug = e.getElementsByTagName("DisableDebug") + .item(0).getTextContent(); + } + + } catch (ParserConfigurationException e) { + Activator.log(e); + e.printStackTrace(); + quitWithError("Could not parse '"+configPath.toOSString()+"'"); + } catch (SAXException e) { + Activator.log(e); + e.printStackTrace(); + quitWithError("Could not parse '"+configPath.toOSString()+"'"); + } catch (IOException e) { + Activator.log(e); + e.printStackTrace(); + quitWithError("Could not read'"+configPath.toOSString()+"'"); + } + + } +} diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/src/com/intel/sgx/handlers/ModuleCreationBaseHandler.java b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/src/com/intel/sgx/handlers/ModuleCreationBaseHandler.java new file mode 100644 index 0000000000..708208c6cb --- /dev/null +++ b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/src/com/intel/sgx/handlers/ModuleCreationBaseHandler.java @@ -0,0 +1,39 @@ +/////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2016 Intel Corporation. // +// // +// All rights reserved. This program and the accompanying materials // +// are made available under the terms of the Eclipse Public License v1.0 // +// which accompanies this distribution, and is available at // +// http://www.eclipse.org/legal/epl-v10.html // +// // +// Contributors: // +// Intel Corporation - initial implementation and documentation // +/////////////////////////////////////////////////////////////////////////// + + +package com.intel.sgx.handlers; + +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IProjectDescription; +import org.eclipse.core.runtime.CoreException; + +public class ModuleCreationBaseHandler { + public boolean isCPProject(IProject project) + { + boolean isCPProject = false; + IProjectDescription description; + try { + description = project.getDescription(); + String[] natures = description.getNatureIds(); + for(String nature: natures){ + if(nature.equals("org.eclipse.cdt.core.ccnature")) + isCPProject = true; + } + } catch (CoreException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + return isCPProject; + + } +} diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/src/com/intel/sgx/handlers/RemoveEnclave.java b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/src/com/intel/sgx/handlers/RemoveEnclave.java new file mode 100644 index 0000000000..058e622996 --- /dev/null +++ b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/src/com/intel/sgx/handlers/RemoveEnclave.java @@ -0,0 +1,169 @@ +/////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2016 Intel Corporation. // +// // +// All rights reserved. This program and the accompanying materials // +// are made available under the terms of the Eclipse Public License v1.0 // +// which accompanies this distribution, and is available at // +// http://www.eclipse.org/legal/epl-v10.html // +// // +// Contributors: // +// Intel Corporation - initial implementation and documentation // +/////////////////////////////////////////////////////////////////////////// + + +package com.intel.sgx.handlers; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; + +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.core.commands.IHandler; +import org.eclipse.core.commands.IHandlerListener; +import org.eclipse.core.resources.IFolder; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.Path; +import org.eclipse.jface.dialogs.InputDialog; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.ui.handlers.HandlerUtil; + +import com.intel.sgx.Activator; +import com.intel.sgx.dialogs.RemoveEnclaveFileDialog; + +public class RemoveEnclave implements IHandler { + + public String edlFilename = ""; + private IPath edlCanonicalFilename; + + @Override + public void addHandlerListener(IHandlerListener handlerListener) { + } + + @Override + public void dispose() { + } + + @Override + public Object execute(ExecutionEvent event) throws ExecutionException { + String edlBasename; + IProject project = null; + + // Display display = Display.getCurrent(); + // Shell shell = new Shell(display); + + RemoveEnclaveFileDialog dialog = new RemoveEnclaveFileDialog(null, this); + + if (dialog.open() != InputDialog.OK) { + return null; + } + + edlCanonicalFilename = Path.fromOSString(edlFilename); + edlBasename = edlCanonicalFilename.lastSegment(); + + if(edlBasename.isEmpty()){ + return null; + } + + ISelection selection = HandlerUtil.getCurrentSelection(event); + Object element = null; + if(selection instanceof IStructuredSelection) { + element = ((IStructuredSelection)selection).getFirstElement(); + if (element instanceof IResource) { + project= ((IResource)element).getProject(); + } + } + if (!project.exists()) { + System.err.println("Error: Project not found"); + return null; + } + + IPath targetRelPath = project.getProjectRelativePath().append("sgx").append("enclave_" + edlBasename); + + try { + for (int i=1;i<=targetRelPath.segmentCount();i++) { + IFolder subfolder = project.getFolder(targetRelPath.uptoSegment(i)); + + if (subfolder.exists()){ + if(subfolder.getProjectRelativePath().toOSString().contains("enclave_"+edlBasename)){ + subfolder.delete(true, true, null); + break; + } + } + } + targetRelPath = project.getProjectRelativePath().append("sgx").append(edlBasename); + for (int i=1;i<=targetRelPath.segmentCount();i++) { + IFolder subfolder = project.getFolder(targetRelPath.uptoSegment(i)); + + if (subfolder.exists()){ + if(subfolder.getProjectRelativePath().toOSString().contains(edlBasename)){ + subfolder.delete(true, true, null); + break; + } + } + } + } catch (Exception e) { + Activator.log(e); + } + + try { + project.refreshLocal(IResource.DEPTH_INFINITE, null); + } catch (CoreException e) { + Activator.log(e); + } catch (IllegalArgumentException e){ + Activator.log(e); + } + + return null; + } + + @Override + public boolean isEnabled() { + return true; + } + + @Override + public boolean isHandled() { + return true; + } + + @Override + public void removeHandlerListener(IHandlerListener handlerListener) { + } + + public static void copyFile(File source, File dest) throws IOException { + byte[] bytes = new byte[4092]; + if (source != null && dest != null) { + if (source.isFile()) { + FileInputStream in = null; + FileOutputStream out = null; + try { + in = new FileInputStream(source); + out = new FileOutputStream(dest); + int len; + while ((len = in.read(bytes)) != -1) { + out.write(bytes, 0, len); + } + } catch (Exception e) { + System.err.println("Error: " + e.toString()); + Activator.log(e); + } finally { + try { + if (in != null) + in.close(); + } finally { + if (out != null) + out.close(); + } + } + } + } + } +} diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/src/com/intel/sgx/handlers/SGXHandler.java b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/src/com/intel/sgx/handlers/SGXHandler.java new file mode 100644 index 0000000000..bfd5bcb551 --- /dev/null +++ b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/src/com/intel/sgx/handlers/SGXHandler.java @@ -0,0 +1,206 @@ +/////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2016 Intel Corporation. // +// // +// All rights reserved. This program and the accompanying materials // +// are made available under the terms of the Eclipse Public License v1.0 // +// which accompanies this distribution, and is available at // +// http://www.eclipse.org/legal/epl-v10.html // +// // +// Contributors: // +// Intel Corporation - initial implementation and documentation // +/////////////////////////////////////////////////////////////////////////// + + +package com.intel.sgx.handlers; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; + +import javax.swing.JOptionPane; + +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.core.commands.IHandler; +import org.eclipse.core.commands.IHandlerListener; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.handlers.HandlerUtil; + +/** + * Utility base class for all Handlers The derived classes must implement + * executeSgxStuff() instead of execute(). The user may call methods cancel(), + * quitWithError() & info() + * + * @author mlutescu + * + */ +public abstract class SGXHandler implements IHandler { + + public String projectPath = null; + protected IProject project; + protected Shell shell; + + /** + * Throwing this IS an error. Means that the process can't continue + * + * @author mlutescu + * + */ + static protected class ErrorException extends Exception { + + public ErrorException(String message) { + super(message); + } + + } + + /** + * Throwing this is not an error; just signals stop of execution because the + * user cancels + * + * @author mlutescu + * + */ + static protected class CancelException extends Exception { + + public CancelException() { + super(); + } + + } + + @Override + public final Object execute(ExecutionEvent event) throws ExecutionException { + try { + initializeShell(); + initializeProject(event); + return executeSGXStuff(); + } catch (ErrorException e) { + e.printStackTrace(); + } catch (CancelException e) { + // do nothing by design ; it's Ok to not handle this exception. + } + return null; + } + + protected abstract Object executeSGXStuff() throws ErrorException, + CancelException; + + public SGXHandler() { + super(); + } + + public static void copyFile(File source, File dest) throws ErrorException { + byte[] bytes = new byte[4092]; + if (source != null && dest != null) { + if (source.isFile()) { + FileInputStream in = null; + FileOutputStream out = null; + try { + in = new FileInputStream(source); + out = new FileOutputStream(dest); + int len; + while ((len = in.read(bytes)) != -1) { + out.write(bytes, 0, len); + } + } catch (IOException e) { + System.err.println("Error: " + e.toString()); + quitWithError("Could not copy from\n" + "'" + + source.getAbsolutePath() + "'\n" + "to\n" + "'" + + dest.getAbsolutePath()); + } finally { + try { + if (in != null) { + in.close(); + } + } catch (IOException e) { + e.printStackTrace(); + } finally { + if (out != null) { + try { + out.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + } + } + } + } + + protected static void quitWithError(String message) throws ErrorException { + JOptionPane.showMessageDialog(null, message, "Two Step Enclave Sign", + JOptionPane.ERROR_MESSAGE); + throw new ErrorException(message); + } + + static protected void cancel() throws CancelException { + throw new CancelException(); + } + + protected void initializeProject(ExecutionEvent event) + throws ErrorException { + project = null; + ISelection selection = HandlerUtil.getCurrentSelection(event); + Object element = null; + if (selection instanceof IStructuredSelection) { + element = ((IStructuredSelection) selection).getFirstElement(); + if (element instanceof IResource) { + project = ((IResource) element).getProject(); + } + } + + if (!project.exists()) { + quitWithError("Project not found"); + } + + } + + @Override + public boolean isEnabled() { + return true; + } + + @Override + public boolean isHandled() { + return true; + } + + @Override + public void removeHandlerListener(IHandlerListener arg0) { + } + + @Override + public void addHandlerListener(IHandlerListener arg0) { + } + + @Override + public void dispose() { + } + + protected void initializeShell() { + shell = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(); + } + + protected void refreshProject() throws ErrorException { + try { + project.refreshLocal(IResource.DEPTH_INFINITE, null); + } catch (CoreException e1) { + quitWithError(e1.getLocalizedMessage()); + } + } + + protected void info(String windowName, String message) { + JOptionPane.showMessageDialog(null, message,windowName, + JOptionPane.INFORMATION_MESSAGE); + } + +} diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/src/com/intel/sgx/handlers/SGXSDKWizardHandler.java b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/src/com/intel/sgx/handlers/SGXSDKWizardHandler.java new file mode 100644 index 0000000000..b445c5ea8a --- /dev/null +++ b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/src/com/intel/sgx/handlers/SGXSDKWizardHandler.java @@ -0,0 +1,38 @@ +/////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2016 Intel Corporation. // +// // +// All rights reserved. This program and the accompanying materials // +// are made available under the terms of the Eclipse Public License v1.0 // +// which accompanies this distribution, and is available at // +// http://www.eclipse.org/legal/epl-v10.html // +// // +// Contributors: // +// Intel Corporation - initial implementation and documentation // +/////////////////////////////////////////////////////////////////////////// + + +package com.intel.sgx.handlers; + +import org.eclipse.cdt.managedbuilder.core.IToolChain; +import org.eclipse.cdt.managedbuilder.core.ManagedBuildManager; +import org.eclipse.cdt.managedbuilder.ui.wizards.STDWizardHandler; + +public class SGXSDKWizardHandler extends STDWizardHandler { + + public SGXSDKWizardHandler() { + super(null, null); + } + + + @Override + public IToolChain[] getSelectedToolChains() { + IToolChain[] tcs = ManagedBuildManager.getRealToolChains(); + for (IToolChain tc : tcs) { + if (tc.getId().equals("com.intel.sgx.SGXtoolChain")) + return new IToolChain[] { + tc + }; + } + return super.getSelectedToolChains(); + } +} diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/src/com/intel/sgx/handlers/TwoStepSignHandlerBase.java b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/src/com/intel/sgx/handlers/TwoStepSignHandlerBase.java new file mode 100644 index 0000000000..59ae2eb7a4 --- /dev/null +++ b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/src/com/intel/sgx/handlers/TwoStepSignHandlerBase.java @@ -0,0 +1,196 @@ +/////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2016 Intel Corporation. // +// // +// All rights reserved. This program and the accompanying materials // +// are made available under the terms of the Eclipse Public License v1.0 // +// which accompanies this distribution, and is available at // +// http://www.eclipse.org/legal/epl-v10.html // +// // +// Contributors: // +// Intel Corporation - initial implementation and documentation // +/////////////////////////////////////////////////////////////////////////// + + +package com.intel.sgx.handlers; + +import java.io.BufferedReader; +import java.io.File; +import java.io.IOException; +import java.io.InputStreamReader; + +import com.intel.sgx.preferences.PreferenceConstants; + +public abstract class TwoStepSignHandlerBase extends SGXHandler { + + public String hashFile = null; + public String configFile = null; + public String enclaveFile = null; + public String externalSignPublicKeyFile = null; + public String externallySignedHashFile = null; + public String outputSignedEnclaveFile = null; + + protected File signtool; + + public TwoStepSignHandlerBase() { + super(); + } + + protected void executeGenData() throws ErrorException { + validateConfigFile(); + validateEnclaveFile(); + + refreshProject(); + executeSignTool(new String[] { "gendata", + "-enclave", enclaveFile, + "-config", configFile, + "-out", hashFile }); + refreshProject(); + + validateHashFile(); + + } + + protected void executeCatSig() throws ErrorException { + validateEnclaveFile(); + validateConfigFile(); + validateHashFile(); + + validateExternalSignPublicKeyFile(); + validateExternallySignedHashFile(); + + executeSignTool("catsig", + // enclave data: + "-enclave", enclaveFile, + "-config", configFile, + // previously generated: + "-unsigned", hashFile, + // externally generated + "-key", externalSignPublicKeyFile, + "-sig", externallySignedHashFile, + // output + "-out", outputSignedEnclaveFile + + ); + + refreshProject(); + + validateOutputSignedEnclaveFile(); + + info("Two Step Enclave Sign","Enclave signed successfully !"); + } + + void initializeSigntool() throws ErrorException { + signtool = PreferenceConstants.getSDKDescriptor().getSignerPath(); + if (!signtool.exists() || signtool.isDirectory()) { + quitWithError("Error generating hash! Sign Tool Not Found !\n Please make sure to have written in the box the value for SGX SDK Directory in Window->Preferences->SGX Preferences. \n Usually the path is in /opt/intel/sgxsdk/" ); + } + + } + + protected void validateEnclaveFile() throws ErrorException { + File enclave = new File(enclaveFile); + if (!enclave.exists() || enclave.isDirectory()) { + quitWithError("Error generating hash! Unsigned Enclave File Not Found! Try building the enclave first"); + } + } + + protected void validateConfigFile() throws ErrorException { + if (configFile == null || configFile.isEmpty()) { + quitWithError("Error Enclave Configuration File Not Found !"); + } + File config = new File(configFile); + if (!config.exists() || config.isDirectory()) { + quitWithError("Enclave Config File Not Found !"); + } + } + + protected void validateExternallySignedHashFile() throws ErrorException { + if (externallySignedHashFile == null || externallySignedHashFile.isEmpty()) { + quitWithError("Error signing enclave! Signature File Not Found !"); + } + + File signature = new File(externallySignedHashFile); + if (!signature.exists() || signature.isDirectory()) { + quitWithError("Error signing enclave! Signature File Not Found !"); + } + } + + protected void validateExternalSignPublicKeyFile() throws ErrorException { + if (externalSignPublicKeyFile == null || externalSignPublicKeyFile.isEmpty()) { + quitWithError("Public Key File Not Found !"); + } + + File publickkey = new File(externalSignPublicKeyFile); + if (!publickkey.exists() || publickkey.isDirectory()) { + quitWithError("Error signing enclave! Public Key File Not Found !"); + } + } + + private void validateOutputSignedEnclaveFile() throws ErrorException { + if(outputSignedEnclaveFile == null || outputSignedEnclaveFile.isEmpty()) + { + quitWithError("Output Signed File Not Found !"); + } + File outputSignedEnclave = new File(outputSignedEnclaveFile); + if(!outputSignedEnclave.exists() || outputSignedEnclave.isDirectory()) + { + quitWithError("Output Signed File Not Found !"); + } + + // TODO Auto-generated method stub + + } + + protected void validateHashFile() throws ErrorException { + if(hashFile == null || hashFile.isEmpty()) + { + quitWithError("Hash File Not Found !"); + } + File hash = new File(hashFile); + if(!hash.exists() || hash.isDirectory()) + { + quitWithError("Hash File Not Found !"); + } + } + + + protected void executeSignTool(String... args) throws ErrorException { + + Process q; + try { + + String[] allArgs = new String[args.length+1]; + allArgs[0] = signtool.getAbsolutePath(); + System.arraycopy(args, 0, allArgs, 1, args.length); + + for (String arg : args){ + } + String fullOutput = ""; + q = Runtime.getRuntime().exec(allArgs); + + BufferedReader stdInput = new BufferedReader(new InputStreamReader( + q.getInputStream())); + BufferedReader stdErr = new BufferedReader(new InputStreamReader( + q.getErrorStream())); + String s = null; + while ((s = stdInput.readLine()) != null) { + } + String[] out = new String[20]; + int i = 0; + while ((out[i] = stdErr.readLine()) != null) { + fullOutput += out[i]+"\n"; + i++; + } + String result = out[i - 1]; + + if (!result.equals("Succeed.")) { + // quitWithError("Error generating hash! " + out[i - 2]); + quitWithError("Error generating hash! " + fullOutput); + } + } catch (IOException e) { + quitWithError(e.getLocalizedMessage()); + } + + } + +} diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/src/com/intel/sgx/handlers/TwoStepSignStep1.java b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/src/com/intel/sgx/handlers/TwoStepSignStep1.java new file mode 100644 index 0000000000..cb2f3649bd --- /dev/null +++ b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/src/com/intel/sgx/handlers/TwoStepSignStep1.java @@ -0,0 +1,74 @@ +/////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2016 Intel Corporation. // +// // +// All rights reserved. This program and the accompanying materials // +// are made available under the terms of the Eclipse Public License v1.0 // +// which accompanies this distribution, and is available at // +// http://www.eclipse.org/legal/epl-v10.html // +// // +// Contributors: // +// Intel Corporation - initial implementation and documentation // +/////////////////////////////////////////////////////////////////////////// + + +package com.intel.sgx.handlers; + +import org.eclipse.jface.dialogs.InputDialog; + +import com.intel.sgx.dialogs.SGXDialogBase; +import com.intel.sgx.dialogs.TwoStepSignStep1Dialog1; +import com.intel.sgx.dialogs.TwoStepSignStep1Dialog2; +import com.intel.sgx.dialogs.TwoStepSignStep1Dialog3; + +// Generate Hash +public class TwoStepSignStep1 extends TwoStepSignHandlerBase { + + public TwoStepSignStep1() { + } + + @Override + protected Object executeSGXStuff() throws ErrorException, CancelException { + + initializeSigntool(); + + showDialog1(); + showDialog2(); + showDialog3(); + return null; + } + + private void showDialog1() throws CancelException, ErrorException { + + TwoStepSignStep1Dialog1 dialog1 = new TwoStepSignStep1Dialog1(shell, this); + if (dialog1.open() != InputDialog.OK) { + cancel(); + } + + executeGenData(); + + } + + private void showDialog2() throws CancelException { + TwoStepSignStep1Dialog2 dialog2 = new TwoStepSignStep1Dialog2(shell, + hashFile); + + if (dialog2.open() != InputDialog.OK) { + cancel(); + } + } + + protected void showDialog3() throws CancelException, ErrorException { + SGXDialogBase dialog3 = new TwoStepSignStep1Dialog3(shell, this); + if (dialog3.open() != InputDialog.OK) { + cancel(); + } + + validateExternalSignPublicKeyFile(); + + validateExternallySignedHashFile(); + + executeCatSig(); + + } + +} diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/src/com/intel/sgx/handlers/TwoStepSignStep2.java b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/src/com/intel/sgx/handlers/TwoStepSignStep2.java new file mode 100644 index 0000000000..f19738036c --- /dev/null +++ b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/src/com/intel/sgx/handlers/TwoStepSignStep2.java @@ -0,0 +1,39 @@ +/////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2016 Intel Corporation. // +// // +// All rights reserved. This program and the accompanying materials // +// are made available under the terms of the Eclipse Public License v1.0 // +// which accompanies this distribution, and is available at // +// http://www.eclipse.org/legal/epl-v10.html // +// // +// Contributors: // +// Intel Corporation - initial implementation and documentation // +/////////////////////////////////////////////////////////////////////////// + + +package com.intel.sgx.handlers; + +import org.eclipse.jface.dialogs.InputDialog; + +import com.intel.sgx.dialogs.TwoStepSignStep2Dialog; + +// Sign +public class TwoStepSignStep2 extends TwoStepSignHandlerBase { + + public TwoStepSignStep2() { + } + + @Override + protected Object executeSGXStuff() throws ErrorException, CancelException { + initializeSigntool(); + + TwoStepSignStep2Dialog dialog = new TwoStepSignStep2Dialog(shell, this); + if(dialog.open() != InputDialog.OK) { + cancel(); + } + + executeCatSig(); + return null; + } + +} diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/src/com/intel/sgx/handlers/UpdateSigningKey.java b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/src/com/intel/sgx/handlers/UpdateSigningKey.java new file mode 100644 index 0000000000..68870ea3cf --- /dev/null +++ b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/src/com/intel/sgx/handlers/UpdateSigningKey.java @@ -0,0 +1,101 @@ +/////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2016 Intel Corporation. // +// // +// All rights reserved. This program and the accompanying materials // +// are made available under the terms of the Eclipse Public License v1.0 // +// which accompanies this distribution, and is available at // +// http://www.eclipse.org/legal/epl-v10.html // +// // +// Contributors: // +// Intel Corporation - initial implementation and documentation // +/////////////////////////////////////////////////////////////////////////// + + +package com.intel.sgx.handlers; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileInputStream; +//import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStreamReader; +//import java.security.KeyPair; +//import java.security.KeyPairGenerator; +//import java.security.NoSuchAlgorithmException; + +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.core.commands.IHandler; +import org.eclipse.core.commands.IHandlerListener; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.Path; +import org.eclipse.jface.dialogs.InputDialog; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.handlers.HandlerUtil; + +//import org.bouncycastle.openssl.PEMWriter; +import com.intel.sgx.Activator; +import com.intel.sgx.dialogs.UpdateSignKeyDialog; + +public class UpdateSigningKey extends SGXHandler { + + public String sourceKeyFile = null; + public String destinationKeyFile = null; + public String projectPath = null; + + @Override + protected Object executeSGXStuff() throws ErrorException, CancelException { + + UpdateSignKeyDialog dialog = new UpdateSignKeyDialog(shell, this); + int result = dialog.open(); + if (result != InputDialog.OK) { + cancel(); + } + + if(UpdateSignKeyDialog.regenerate == false) + { + IPath sourceFile = Path.fromOSString(sourceKeyFile); + IPath destFile = Path.fromOSString(destinationKeyFile); + copyFile(sourceFile.toFile(), destFile.toFile()); + refreshProject(); + info("Update SGX Enclave Signing Key","copied \n'" + sourceKeyFile + "' into \n'" + destFile + "'"); + } else { + UpdateSignKeyDialog.regenerate = false; + try { + Process q; + String opensslCmd = "openssl genrsa -out " + destinationKeyFile + + " -3 3072"; + q = Runtime.getRuntime().exec(opensslCmd); + BufferedReader stdInput = new BufferedReader( + new InputStreamReader(q.getInputStream())); + BufferedReader stdErr = new BufferedReader( + new InputStreamReader(q.getErrorStream())); + String s = null; + while ((s = stdInput.readLine()) != null) { + } + while ((s = stdErr.readLine()) != null) { + } + project.refreshLocal(IResource.DEPTH_INFINITE, null); + if (q.exitValue() == 0){ + info("Update SGX Enclave Signing Key","'"+destinationKeyFile+"'"+" was generated!"); + } else { + quitWithError("Could not generate '"+destinationKeyFile+"'!!!"); + } + } catch (IOException e) { + Activator.log(e); + e.printStackTrace(); + } catch (CoreException e) { + Activator.log(e); + e.printStackTrace(); + } + } + return null; + } +} diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/src/com/intel/sgx/handlers/about.html b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/src/com/intel/sgx/handlers/about.html new file mode 100644 index 0000000000..a3b9ace448 --- /dev/null +++ b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/src/com/intel/sgx/handlers/about.html @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + +About + + +

About This Content

+ +

June 22, 2007

+

License

+ +

The Eclipse Foundation makes available all content in this plug-in ("Content"). Unless otherwise +indicated below, the Content is provided to you under the terms and conditions of the +Eclipse Public License Version 1.0 ("EPL"). A copy of the EPL is available +at http://www.eclipse.org/legal/epl-v10.html. +For purposes of the EPL, "Program" will mean the Content.

+ +

If you did not receive this Content directly from the Eclipse Foundation, the Content is +being redistributed by another party ("Redistributor") and different terms and conditions may +apply to your use of any object code in the Content. Check the Redistributor's license that was +provided with the Content. If no such license exists, contact the Redistributor. Unless otherwise +indicated below, the terms and conditions of the EPL still apply to any source code in the Content +and such source code may be obtained at http://www.eclipse.org.

+ + diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/src/com/intel/sgx/messages.properties b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/src/com/intel/sgx/messages.properties new file mode 100644 index 0000000000..c0011fadda --- /dev/null +++ b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/src/com/intel/sgx/messages.properties @@ -0,0 +1,16 @@ +######################################################################### +# Copyright (c) 2016 Intel Corporation. # +# # +# All rights reserved. This program and the accompanying materials # +# are made available under the terms of the Eclipse Public License v1.0 # +# which accompanies this distribution, and is available at # +# http://www.eclipse.org/legal/epl-v10.html # +# # +# Contributors: # +# Intel Corporation - initial implementation and documentation # +######################################################################### + + +CreateNativeFolders_No_folders=No folders. +CreateNativeFolders_Missing_project_name=Missing project Name. +CreateNativeFolders_Project_does_not_exist=Project does not exist. diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/src/com/intel/sgx/natures/SGXCCNature.java b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/src/com/intel/sgx/natures/SGXCCNature.java new file mode 100644 index 0000000000..fde7f7d29c --- /dev/null +++ b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/src/com/intel/sgx/natures/SGXCCNature.java @@ -0,0 +1,45 @@ +/////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2016 Intel Corporation. // +// // +// All rights reserved. This program and the accompanying materials // +// are made available under the terms of the Eclipse Public License v1.0 // +// which accompanies this distribution, and is available at // +// http://www.eclipse.org/legal/epl-v10.html // +// // +// Contributors: // +// Intel Corporation - initial implementation and documentation // +/////////////////////////////////////////////////////////////////////////// + + +package com.intel.sgx.natures; + +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IProjectNature; +import org.eclipse.core.runtime.CoreException; + +public class SGXCCNature implements IProjectNature { + + private IProject project; + public static final String NATURE_ID = "com.intel.sgx.sgxccnature"; + + public SGXCCNature() { + } + + @Override + public void configure() throws CoreException { + } + + @Override + public void deconfigure() throws CoreException { + } + + @Override + public IProject getProject() { + return project; + } + + @Override + public void setProject(IProject project) { + this.project = project; + } +} diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/src/com/intel/sgx/natures/SGXNature.java b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/src/com/intel/sgx/natures/SGXNature.java new file mode 100644 index 0000000000..8db687e029 --- /dev/null +++ b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/src/com/intel/sgx/natures/SGXNature.java @@ -0,0 +1,45 @@ +/////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2016 Intel Corporation. // +// // +// All rights reserved. This program and the accompanying materials // +// are made available under the terms of the Eclipse Public License v1.0 // +// which accompanies this distribution, and is available at // +// http://www.eclipse.org/legal/epl-v10.html // +// // +// Contributors: // +// Intel Corporation - initial implementation and documentation // +/////////////////////////////////////////////////////////////////////////// + + +package com.intel.sgx.natures; + +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IProjectNature; +import org.eclipse.core.runtime.CoreException; + +public class SGXNature implements IProjectNature { + + private IProject project; + public static final String NATURE_ID = "com.intel.sgx.sgxnature"; + + public SGXNature() { + } + + @Override + public void configure() throws CoreException { + } + + @Override + public void deconfigure() throws CoreException { + } + + @Override + public IProject getProject() { + return project; + } + + @Override + public void setProject(IProject project) { + this.project = project; + } +} diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/src/com/intel/sgx/natures/SGXStaticCCNature.java b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/src/com/intel/sgx/natures/SGXStaticCCNature.java new file mode 100644 index 0000000000..0d642ee5c8 --- /dev/null +++ b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/src/com/intel/sgx/natures/SGXStaticCCNature.java @@ -0,0 +1,45 @@ +/////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2016 Intel Corporation. // +// // +// All rights reserved. This program and the accompanying materials // +// are made available under the terms of the Eclipse Public License v1.0 // +// which accompanies this distribution, and is available at // +// http://www.eclipse.org/legal/epl-v10.html // +// // +// Contributors: // +// Intel Corporation - initial implementation and documentation // +/////////////////////////////////////////////////////////////////////////// + + +package com.intel.sgx.natures; + +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IProjectNature; +import org.eclipse.core.runtime.CoreException; + +public class SGXStaticCCNature implements IProjectNature { + + private IProject project; + public static final String NATURE_ID = "com.intel.sgx.sgxstaticccnature"; + + public SGXStaticCCNature() { + } + + @Override + public void configure() throws CoreException { + } + + @Override + public void deconfigure() throws CoreException { + } + + @Override + public IProject getProject() { + return project; + } + + @Override + public void setProject(IProject project) { + this.project = project; + } +} diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/src/com/intel/sgx/preferences/ISDKDescriptor.java b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/src/com/intel/sgx/preferences/ISDKDescriptor.java new file mode 100644 index 0000000000..ec8b274912 --- /dev/null +++ b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/src/com/intel/sgx/preferences/ISDKDescriptor.java @@ -0,0 +1,29 @@ +/////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2016 Intel Corporation. // +// // +// All rights reserved. This program and the accompanying materials // +// are made available under the terms of the Eclipse Public License v1.0 // +// which accompanies this distribution, and is available at // +// http://www.eclipse.org/legal/epl-v10.html // +// // +// Contributors: // +// Intel Corporation - initial implementation and documentation // +/////////////////////////////////////////////////////////////////////////// + + +package com.intel.sgx.preferences; + +import java.io.File; + + +public interface ISDKDescriptor { + + public abstract File getSdkDir(); + + public abstract File getToolsDir(); + + public abstract File getSignerPath(); + + public abstract File getEdger8rPath(); + +} diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/src/com/intel/sgx/preferences/PreferenceConstants.java b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/src/com/intel/sgx/preferences/PreferenceConstants.java new file mode 100644 index 0000000000..5ce1abc9cc --- /dev/null +++ b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/src/com/intel/sgx/preferences/PreferenceConstants.java @@ -0,0 +1,112 @@ +/////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2016 Intel Corporation. // +// // +// All rights reserved. This program and the accompanying materials // +// are made available under the terms of the Eclipse Public License v1.0 // +// which accompanies this distribution, and is available at // +// http://www.eclipse.org/legal/epl-v10.html // +// // +// Contributors: // +// Intel Corporation - initial implementation and documentation // +/////////////////////////////////////////////////////////////////////////// + + +package com.intel.sgx.preferences; + +import java.io.File; + +import org.eclipse.jface.preference.IPreferenceStore; + +import com.intel.sgx.Activator; + +/** + * Constant definitions for plug-in preferences + */ +public class PreferenceConstants { + + public static final String SDK_PATH = "SDKPathPreference"; + + public static ISDKDescriptor getSDKDescriptor() { + IPreferenceStore store = Activator.getDefault().getPreferenceStore(); + File sdkDir = new File(store.getString(PreferenceConstants.SDK_PATH)); + + if (System.getProperty("os.arch").contains("64")) { + return new SGXSDK64Descriptor(sdkDir); + } else { + return new SGXSDK32Descriptor(sdkDir); + } + } + + + static public class SGXSDK32Descriptor implements ISDKDescriptor { + private final File sdkDir; + private final File toolDir; + private final File signerPath; + private final File edger8rPath; + + public SGXSDK32Descriptor(File location){ + this.sdkDir = location; + this.toolDir = new File(location, "bin/x86"); + this.signerPath = new File(toolDir, "sgx_sign"); + this.edger8rPath = new File(toolDir, "sgx_edger8r"); + } + + @Override + public File getSdkDir() { + return sdkDir; + } + + @Override + public File getToolsDir() { + return toolDir; + } + + @Override + public File getSignerPath() { + return signerPath; + } + + @Override + public File getEdger8rPath() { + return edger8rPath; + } + + } + + + static public class SGXSDK64Descriptor implements ISDKDescriptor { + private final File sdkDir; + private final File toolDir; + private final File signerPath; + private final File edger8rPath; + + public SGXSDK64Descriptor(File sdkDir){ + this.sdkDir = sdkDir; + this.toolDir = new File(sdkDir, "bin/x64"); + this.signerPath = new File(toolDir, "sgx_sign"); + this.edger8rPath = new File(toolDir, "sgx_edger8r"); + } + + @Override + public File getSdkDir() { + return sdkDir; + } + + @Override + public File getToolsDir() { + return toolDir; + } + + @Override + public File getSignerPath() { + return signerPath; + } + + @Override + public File getEdger8rPath() { + return edger8rPath; + } + + } + +} diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/src/com/intel/sgx/preferences/PreferenceInitializer.java b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/src/com/intel/sgx/preferences/PreferenceInitializer.java new file mode 100644 index 0000000000..b85d5e5299 --- /dev/null +++ b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/src/com/intel/sgx/preferences/PreferenceInitializer.java @@ -0,0 +1,32 @@ +/////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2016 Intel Corporation. // +// // +// All rights reserved. This program and the accompanying materials // +// are made available under the terms of the Eclipse Public License v1.0 // +// which accompanies this distribution, and is available at // +// http://www.eclipse.org/legal/epl-v10.html // +// // +// Contributors: // +// Intel Corporation - initial implementation and documentation // +/////////////////////////////////////////////////////////////////////////// + + +package com.intel.sgx.preferences; + +import com.intel.sgx.Activator; + +import org.eclipse.core.runtime.preferences.AbstractPreferenceInitializer; +import org.eclipse.jface.preference.IPreferenceStore; + +/** + * Class used to initialize default preference values. + */ +public class PreferenceInitializer extends AbstractPreferenceInitializer { + + public void initializeDefaultPreferences() { + IPreferenceStore store = Activator.getDefault().getPreferenceStore(); + store.setDefault(PreferenceConstants.SDK_PATH, ""); + Activator.getDefault().getPreferenceStore().setValue(PreferenceConstants.SDK_PATH, "/opt/intel/sgxsdk"); + Activator.getDefault().getPreferenceStore().setDefault(PreferenceConstants.SDK_PATH, "/opt/intel/sgxsdk"); + } +} diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/src/com/intel/sgx/preferences/SGXPreferencePage.java b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/src/com/intel/sgx/preferences/SGXPreferencePage.java new file mode 100644 index 0000000000..bbf6608a71 --- /dev/null +++ b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/src/com/intel/sgx/preferences/SGXPreferencePage.java @@ -0,0 +1,110 @@ +/////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2016 Intel Corporation. // +// // +// All rights reserved. This program and the accompanying materials // +// are made available under the terms of the Eclipse Public License v1.0 // +// which accompanies this distribution, and is available at // +// http://www.eclipse.org/legal/epl-v10.html // +// // +// Contributors: // +// Intel Corporation - initial implementation and documentation // +/////////////////////////////////////////////////////////////////////////// + + +package com.intel.sgx.preferences; + +import org.eclipse.jface.preference.DirectoryFieldEditor; +import org.eclipse.jface.preference.FieldEditorPreferencePage; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Text; +import org.eclipse.ui.IWorkbench; +import org.eclipse.ui.IWorkbenchPreferencePage; + +import com.intel.sgx.Activator; +import com.intel.sgx.SdkPathVariableProvider; + +/** + * This class represents a preference page that + * is contributed to the Preferences dialog. By + * subclassing FieldEditorPreferencePage, we + * can use the field support built into JFace that allows + * us to create a page that is small and knows how to + * save, restore and apply itself. + *

+ * This page is used to modify preferences only. They + * are stored in the preference store that belongs to + * the main plug-in class. That way, preferences can + * be accessed directly via the preference store. + */ + +public class SGXPreferencePage + extends FieldEditorPreferencePage + implements IWorkbenchPreferencePage { + + private SGXSdkDirectoryFieldEditor sgxSdkDirectoryEditor; + + public SGXPreferencePage() { + super(GRID); + setPreferenceStore(Activator.getDefault().getPreferenceStore()); + setDescription("SGX Preferences"); + } + + /** + * Creates the field editors. Field editors are abstractions of + * the common GUI blocks needed to manipulate various types + * of preferences. Each field editor knows how to save and + * restore itself. + */ + + @Override + protected void createFieldEditors() { + sgxSdkDirectoryEditor = new SGXSdkDirectoryFieldEditor(PreferenceConstants.SDK_PATH, + "&SGX SDK Directory:", getFieldEditorParent()); + addField(sgxSdkDirectoryEditor); + } + + /* + * Validates whether the path entered in the SGX SDK Preferences points to the SGX SDK or not. + */ + private static class SGXSdkDirectoryFieldEditor extends DirectoryFieldEditor { + public SGXSdkDirectoryFieldEditor(String name, String labelText, Composite parent) { + super(name, labelText, parent); + setEmptyStringAllowed(true); + } + + @Override + protected boolean doCheckState() { + if (!super.doCheckState()) { + setErrorMessage("SGX Preferences: Not a Valid directory"); + return false; + } + + String dirname = getTextControl().getText().trim(); + if (!dirname.isEmpty() && !SdkPathVariableProvider.isValidSGXSdkLocation(dirname)) { + setErrorMessage("SGX SDK: Not a Valid SGX SDK directory"); + return false; + } + return true; + } + + @Override + public Text getTextControl(Composite parent) { + setValidateStrategy(VALIDATE_ON_KEY_STROKE); + return super.getTextControl(parent); + } + } + + @Override + public void init(IWorkbench workbench) { + } + + @Override + public void dispose() { + super.dispose(); + + if (sgxSdkDirectoryEditor != null) { + sgxSdkDirectoryEditor.dispose(); + sgxSdkDirectoryEditor = null; + } + } +} diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/src/com/intel/sgx/templates/CreateNativeFolders.java b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/src/com/intel/sgx/templates/CreateNativeFolders.java new file mode 100644 index 0000000000..d493e146fe --- /dev/null +++ b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/src/com/intel/sgx/templates/CreateNativeFolders.java @@ -0,0 +1,230 @@ +/////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2016 Intel Corporation. // +// // +// All rights reserved. This program and the accompanying materials // +// are made available under the terms of the Eclipse Public License v1.0 // +// which accompanies this distribution, and is available at // +// http://www.eclipse.org/legal/epl-v10.html // +// // +// Contributors: // +// Intel Corporation - initial implementation and documentation // +/////////////////////////////////////////////////////////////////////////// + + +package com.intel.sgx.templates; + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.cdt.core.CCorePlugin; +import org.eclipse.cdt.core.model.CoreModel; +import org.eclipse.cdt.core.model.ICProject; +import org.eclipse.cdt.core.model.IPathEntry; +import org.eclipse.cdt.core.settings.model.CIncludePathEntry; +import org.eclipse.cdt.core.settings.model.ICConfigurationDescription; +import org.eclipse.cdt.core.settings.model.ICFolderDescription; +import org.eclipse.cdt.core.settings.model.ICLanguageSetting; +import org.eclipse.cdt.core.settings.model.ICLanguageSettingEntry; +import org.eclipse.cdt.core.settings.model.ICProjectDescription; +import org.eclipse.cdt.core.settings.model.ICSettingEntry; +import org.eclipse.cdt.core.templateengine.TemplateCore; +import org.eclipse.cdt.core.templateengine.process.ProcessArgument; +import org.eclipse.cdt.core.templateengine.process.ProcessFailureException; +import org.eclipse.cdt.core.templateengine.process.ProcessRunner; +import org.eclipse.cdt.managedbuilder.core.IConfiguration; +import org.eclipse.cdt.managedbuilder.core.ManagedBuildManager; +import org.eclipse.cdt.managedbuilder.internal.core.Configuration; +import org.eclipse.cdt.managedbuilder.internal.core.ManagedProject; +import org.eclipse.core.resources.IFolder; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.Path; + +import com.intel.sgx.Activator; +import com.intel.sgx.Messages; +import com.intel.sgx.preferences.PreferenceConstants; + +@SuppressWarnings("restriction") +public class CreateNativeFolders extends ProcessRunner { + + @Override + public void process(TemplateCore template, ProcessArgument[] args, + String processId, IProgressMonitor monitor) + throws ProcessFailureException { + String projectName = null; + String[] sourceFolders = null; + String[] outputFolders = null; + + for (ProcessArgument arg : args) { + String argName = arg.getName(); + if (argName.equals("projectName")) { + projectName = arg.getSimpleValue(); + } else if (argName.equals("sourceFolders")) { + sourceFolders = arg.getSimpleArrayValue(); + } else if (argName.equals("outputFolders")) { + outputFolders = arg.getSimpleArrayValue(); + } + } + + if (projectName == null) + throw new ProcessFailureException( + Messages.CreateNativeFolders_Missing_project_name); + + IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject(projectName); + if (!project.exists()) + throw new ProcessFailureException( + Messages.CreateNativeFolders_Project_does_not_exist); + + if (sourceFolders == null && outputFolders == null) + throw new ProcessFailureException( + Messages.CreateNativeFolders_No_folders); + + try { + ICProject cproject = CCorePlugin.getDefault().getCoreModel() + .create(project); + IPathEntry[] pathEntries = cproject.getRawPathEntries(); + List newEntries = new ArrayList( + pathEntries.length); + for (IPathEntry pathEntry : pathEntries) { + if (pathEntry.getEntryKind() != IPathEntry.CDT_SOURCE + && pathEntry.getEntryKind() != IPathEntry.CDT_OUTPUT) { + newEntries.add(pathEntry); + } + } + if (sourceFolders != null) + for (String sourceFolder : sourceFolders) { + IFolder folder = project.getFolder(new Path(sourceFolder)); + if (!folder.exists()) + folder.create(true, true, monitor); + newEntries.add(CoreModel.newSourceEntry(folder + .getFullPath())); + } + if (outputFolders != null) + for (String outputFolder : outputFolders) { + IFolder folder = project.getFolder(new Path(outputFolder)); + if (!folder.exists()) + folder.create(true, true, monitor); + newEntries.add(CoreModel.newOutputEntry(folder + .getFullPath())); + } + cproject.setRawPathEntries( + newEntries.toArray(new IPathEntry[newEntries.size()]), + monitor); + + // IConfiguration[] configs = managedProject.getConfigurations(); + // for(IConfiguration conf:configs){ + // managedProject.removeConfiguration(conf.getId()); + + // } + + IConfiguration conSimDebug = ManagedBuildManager + .getExtensionConfiguration("com.intel.sgx.configuration.Sim.Debug"); + IConfiguration conSimRelease = ManagedBuildManager + .getExtensionConfiguration("com.intel.sgx.configuration.Sim.Release"); + IConfiguration conHwDebug = ManagedBuildManager + .getExtensionConfiguration("com.intel.sgx.configuration.HW.Debug"); + IConfiguration conHwPrerelease = ManagedBuildManager + .getExtensionConfiguration("com.intel.sgx.configuration.HW.Prerelease"); + IConfiguration conHwRelease = ManagedBuildManager + .getExtensionConfiguration("com.intel.sgx.configuration.HW.Release"); + + addConfigurationToProject(project, conSimDebug); + addConfigurationToProject(project, conSimRelease); + addConfigurationToProject(project, conHwDebug); + addConfigurationToProject(project, conHwPrerelease); + addConfigurationToProject(project, conHwRelease); + + + changeProjectConfiguration(project, conSimDebug); + + project.refreshLocal(IResource.DEPTH_INFINITE, null); + } catch (CoreException e) { + throw new ProcessFailureException(e); + } + } + + void addConfigurationToProject(IProject project, IConfiguration config) { + createConfiguration(project, config); + addSGXIncludePathsToConfiguration(project, config); + } + + private void addSGXIncludePathsToConfiguration(IProject project, + IConfiguration config) { + ICProjectDescription projectDescription = CoreModel.getDefault() + .getProjectDescription(project, true); + ICConfigurationDescription configDecriptions[] = projectDescription + .getConfigurations(); + for (ICConfigurationDescription configDescription : configDecriptions) { + ICFolderDescription projectRoot = configDescription + .getRootFolderDescription(); + + ICLanguageSetting[] settings = projectRoot.getLanguageSettings(); + for (ICLanguageSetting setting : settings) { + + if (!"org.eclipse.cdt.core.gcc".equals(setting.getLanguageId()) && !"org.eclipse.cdt.core.g++".equals(setting.getLanguageId()) ) { + continue; + } + List includes = new ArrayList(); + + includes.add(new CIncludePathEntry( Activator.getDefault().getPreferenceStore().getString(PreferenceConstants.SDK_PATH) + + "/include/", + ICSettingEntry.LOCAL)); + + setting.setSettingEntries(ICSettingEntry.INCLUDE_PATH, includes); + } + } + try { + CoreModel.getDefault().setProjectDescription(project, + projectDescription); + } catch (CoreException e) { + e.printStackTrace(); + } + + } + + private void createConfiguration(IProject project, + IConfiguration config) { + ManagedProject managedProject = (ManagedProject) ManagedBuildManager.getBuildInfo(project) + .getManagedProject();; + + + Configuration cloneConfig1 = (Configuration) config; + Configuration cfg1 = new Configuration(managedProject, cloneConfig1, + cloneConfig1.getId(), false, false); + String target = cfg1.getArtifactName(); + if (target == null || target.length() == 0) + cfg1.setArtifactName(managedProject.getDefaultArtifactName()); + + cfg1.exportArtifactInfo(); + + ManagedBuildManager.saveBuildInfo(project, true); + } + + private void changeProjectConfiguration(IProject project, + IConfiguration conSimDebug) { + ICProjectDescription prjd = CCorePlugin.getDefault() + .getProjectDescriptionManager().getProjectDescription(project); + ICConfigurationDescription[] configs = prjd.getConfigurations(); + if (configs != null && configs.length > 0) { + for (ICConfigurationDescription config : configs) { + if (config.getConfiguration().getId() + .equals(conSimDebug.getId())) { + config.setActive(); + try { + CoreModel.getDefault().setProjectDescription(project, + prjd); + } catch (CoreException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + break; + } + } + } + + } + +} diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/src/com/intel/sgx/templates/SetCCNature.java b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/src/com/intel/sgx/templates/SetCCNature.java new file mode 100644 index 0000000000..e85476b288 --- /dev/null +++ b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/src/com/intel/sgx/templates/SetCCNature.java @@ -0,0 +1,77 @@ +/////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2016 Intel Corporation. // +// // +// All rights reserved. This program and the accompanying materials // +// are made available under the terms of the Eclipse Public License v1.0 // +// which accompanies this distribution, and is available at // +// http://www.eclipse.org/legal/epl-v10.html // +// // +// Contributors: // +// Intel Corporation - initial implementation and documentation // +/////////////////////////////////////////////////////////////////////////// + + +package com.intel.sgx.templates; + +import org.eclipse.cdt.core.templateengine.TemplateCore; +import org.eclipse.cdt.core.templateengine.process.ProcessArgument; +import org.eclipse.cdt.core.templateengine.process.ProcessFailureException; +import org.eclipse.cdt.core.templateengine.process.ProcessRunner; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IProjectDescription; +import org.eclipse.core.resources.IWorkspace; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; + +import com.intel.sgx.Activator; +import com.intel.sgx.natures.SGXNature; + +public class SetCCNature extends ProcessRunner { + + public SetCCNature() { + } + + @Override + public void process(TemplateCore template, ProcessArgument[] args, + String processId, IProgressMonitor monitor) + throws ProcessFailureException { + String projectName = null; + IProject project = null; + + for(ProcessArgument arg: args){ + String argName = arg.getName(); + if(argName.equals("projectName")){ + projectName = arg.getSimpleValue(); + } + } + + + project = ResourcesPlugin.getWorkspace().getRoot().getProject(projectName); + IWorkspace workspace = project.getWorkspace(); + IProjectDescription description; + try { + description = project.getDescription(); + + String[] natures = description.getNatureIds(); + String[] newNatures = new String[natures.length+1]; + System.arraycopy(natures,0,newNatures,0,natures.length); + newNatures[natures.length] = SGXNature.NATURE_ID; + IStatus status = workspace.validateNatureSet(newNatures); + + if(status.getCode() == IStatus.OK) + { + + description.setNatureIds(newNatures); + project.setDescription(description, null); + } + else { + System.err.println("Incorrect Project Nature. Please check Project Settings."); + } + } catch (CoreException e) { + Activator.log(e); + e.printStackTrace(); + } + } +} diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/src/com/intel/sgx/templates/SetStaticCCNature.java b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/src/com/intel/sgx/templates/SetStaticCCNature.java new file mode 100644 index 0000000000..449a575262 --- /dev/null +++ b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/src/com/intel/sgx/templates/SetStaticCCNature.java @@ -0,0 +1,75 @@ +/////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2016 Intel Corporation. // +// // +// All rights reserved. This program and the accompanying materials // +// are made available under the terms of the Eclipse Public License v1.0 // +// which accompanies this distribution, and is available at // +// http://www.eclipse.org/legal/epl-v10.html // +// // +// Contributors: // +// Intel Corporation - initial implementation and documentation // +/////////////////////////////////////////////////////////////////////////// + + +package com.intel.sgx.templates; + +import org.eclipse.cdt.core.templateengine.TemplateCore; +import org.eclipse.cdt.core.templateengine.process.ProcessArgument; +import org.eclipse.cdt.core.templateengine.process.ProcessFailureException; +import org.eclipse.cdt.core.templateengine.process.ProcessRunner; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IProjectDescription; +import org.eclipse.core.resources.IWorkspace; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; + +import com.intel.sgx.Activator; +import com.intel.sgx.natures.SGXStaticCCNature; + +public class SetStaticCCNature extends ProcessRunner { + + public SetStaticCCNature() { + } + + @Override + public void process(TemplateCore template, ProcessArgument[] args, + String processId, IProgressMonitor monitor) + throws ProcessFailureException { + + String projectName = null; + IProject project = null; + + for(ProcessArgument arg: args){ + String argName = arg.getName(); + if(argName.equals("projectName")){ + projectName = arg.getSimpleValue(); + } + } + + project = ResourcesPlugin.getWorkspace().getRoot().getProject(projectName); + IWorkspace workspace = project.getWorkspace(); + IProjectDescription description; + try { + description = project.getDescription(); + + String[] natures = description.getNatureIds(); + String[] newNatures = new String[natures.length+1]; + System.arraycopy(natures,0,newNatures,0,natures.length); + newNatures[natures.length] = SGXStaticCCNature.NATURE_ID; + IStatus status = workspace.validateNatureSet(newNatures); + + if(status.getCode() == IStatus.OK) + { + description.setNatureIds(newNatures); + project.setDescription(description, null); + } + else + System.err.println("Incorrect Project Nature. Please check Project Settings."); + } catch (CoreException e) { + Activator.log(e); + e.printStackTrace(); + } + } +} diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/src/com/intel/sgx/testers/SGXPropertyTester.java b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/src/com/intel/sgx/testers/SGXPropertyTester.java new file mode 100644 index 0000000000..1b876c79c6 --- /dev/null +++ b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/src/com/intel/sgx/testers/SGXPropertyTester.java @@ -0,0 +1,79 @@ +/////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2016 Intel Corporation. // +// // +// All rights reserved. This program and the accompanying materials // +// are made available under the terms of the Eclipse Public License v1.0 // +// which accompanies this distribution, and is available at // +// http://www.eclipse.org/legal/epl-v10.html // +// // +// Contributors: // +// Intel Corporation - initial implementation and documentation // +/////////////////////////////////////////////////////////////////////////// + + +package com.intel.sgx.testers; + +import java.util.regex.Pattern; + +import org.eclipse.cdt.managedbuilder.core.IManagedBuildInfo; +import org.eclipse.cdt.managedbuilder.core.ManagedBuildManager; +import org.eclipse.core.expressions.PropertyTester; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; +import org.eclipse.jface.viewers.StructuredSelection; + +public class SGXPropertyTester extends PropertyTester { + + private static final Pattern isRelease = Pattern.compile(".*Release.*"); + private static final Pattern isHW = Pattern.compile(".*Hardware.*"); + private static final Pattern isPreRelease = Pattern.compile(".*Prerelease.*");; + + public SGXPropertyTester() { + super(); + + // TODO Auto-generated constructor stub + } + + @Override + public boolean test(Object receiver, String property, Object[] args, + Object expectedValue) { + + + + + + if (property.equals("twoStepsActive")) { + IProject project = getProjectOfSelectedItem(receiver); + IManagedBuildInfo buildInfo = ManagedBuildManager.getBuildInfo(project); + return isHW(buildInfo) && isRelease(buildInfo) && !isPreRelease(buildInfo); + + } else if (property.equals("sgxNatureAdded")) { + IProject project = getProjectOfSelectedItem(receiver); + return true; + } else { + return false; + } + } + + private IProject getProjectOfSelectedItem(Object receiver) { + StructuredSelection selection = (StructuredSelection) receiver; + IResource resource = (IResource) selection.getFirstElement(); + IProject project = resource.getProject(); + return project; + } + + boolean isHW(IManagedBuildInfo buildInfo){ + return isHW.matcher(buildInfo.getConfigurationName()).matches(); + } + + + + boolean isRelease(IManagedBuildInfo buildInfo){ + return isRelease.matcher(buildInfo.getConfigurationName()).matches(); + } + + boolean isPreRelease(IManagedBuildInfo buildInfo){ + return isPreRelease.matcher(buildInfo.getConfigurationName()).matches(); + } + +} diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/src/com/intel/sgx/wizards/SGXCCProjectWizard.java b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/src/com/intel/sgx/wizards/SGXCCProjectWizard.java new file mode 100644 index 0000000000..be6ec1e51b --- /dev/null +++ b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/src/com/intel/sgx/wizards/SGXCCProjectWizard.java @@ -0,0 +1,145 @@ +/////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2016 Intel Corporation. // +// // +// All rights reserved. This program and the accompanying materials // +// are made available under the terms of the Eclipse Public License v1.0 // +// which accompanies this distribution, and is available at // +// http://www.eclipse.org/legal/epl-v10.html // +// // +// Contributors: // +// Intel Corporation - initial implementation and documentation // +/////////////////////////////////////////////////////////////////////////// + + +package com.intel.sgx.wizards; + +import java.net.URI; +import java.util.Map; + +import org.eclipse.cdt.core.templateengine.TemplateCore; +import org.eclipse.cdt.core.templateengine.TemplateEngine; +import org.eclipse.cdt.ui.wizards.CCProjectWizard; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IProjectDescription; +import org.eclipse.core.resources.IWorkspace; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IConfigurationElement; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.NullProgressMonitor; + +import com.intel.sgx.natures.SGXNature; + +public class SGXCCProjectWizard extends CCProjectWizard { + + private IProject project; + + @Override + protected boolean setCreated() throws CoreException { + boolean result = super.setCreated(); + doIt(project, new NullProgressMonitor()); + return result; + } + + @Override + public boolean performFinish() { + + return super.performFinish(); + } + + @Override + public void setInitializationData(IConfigurationElement config, + String propertyName, Object data) throws CoreException { + // TODO Auto-generated method stub + super.setInitializationData(config, propertyName, data); + } + + @Override + public IProject createIProject(String name, URI location) + throws CoreException { + // TODO Auto-generated method stub + return super.createIProject(name, location); + + } + + @Override + public IProject createIProject(String name, URI location, + IProgressMonitor monitor) throws CoreException { + project = super.createIProject(name, location, monitor); + return project; + } + + @Override + public String[] getExtensions() { + // TODO Auto-generated method stub + return super.getExtensions(); + } + + public SGXCCProjectWizard() { + // TODO Auto-generated constructor stub + } + + @Override + public String[] getNatures() { + // TODO Auto-generated method stub + return super.getNatures(); + } + + @Override + protected IProject continueCreation(IProject prj) { + // TODO Auto-generated method stub + return super.continueCreation(prj); + } + + @Override + public String[] getContentTypeIDs() { + // TODO Auto-generated method stub + return super.getContentTypeIDs(); + } + + @Override + public IProject getProject(boolean defaults) { + // TODO Auto-generated method stub + return super.getProject(defaults); + } + + @Override + public String[] getLanguageIDs() { + // TODO Auto-generated method stub + return super.getLanguageIDs(); + } + + void doIt(IProject project, IProgressMonitor monitor) throws CoreException { + TemplateCore template = TemplateEngine.getDefault().getTemplateById( + "AddSGXNature"); + Map valueStore = template.getValueStore(); + valueStore.put("projectName", project.getName()); + valueStore.put("baseName", project.getName()); + template.executeTemplateProcesses(monitor, false); + + IWorkspace workspace = ResourcesPlugin.getWorkspace(); + IProjectDescription description = project.getDescription(); + String[] natures = description.getNatureIds(); + + String[] newNatures = new String[natures.length + 1]; + System.arraycopy(natures, 0, newNatures, 0, natures.length); + newNatures[natures.length] = SGXNature.NATURE_ID; + IStatus status = workspace.validateNatureSet(newNatures); + + if (status.getCode() == IStatus.OK) { + description.setNatureIds(newNatures); + project.setDescription(description, null); + } else { + System.err + .println("Incorrect Project Nature. Please check Project Settings.");// TODO + // throw + // an + // exception + // here. + System.err.println("Status is: " + status.getCode()); + } + + // project.refreshLocal(IResource.DEPTH_ONE,null); + } +} diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/src/com/intel/sgx/wizards/SGXCProjectWizard.java b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/src/com/intel/sgx/wizards/SGXCProjectWizard.java new file mode 100644 index 0000000000..14ec8f8284 --- /dev/null +++ b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/src/com/intel/sgx/wizards/SGXCProjectWizard.java @@ -0,0 +1,146 @@ +/////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2016 Intel Corporation. // +// // +// All rights reserved. This program and the accompanying materials // +// are made available under the terms of the Eclipse Public License v1.0 // +// which accompanies this distribution, and is available at // +// http://www.eclipse.org/legal/epl-v10.html // +// // +// Contributors: // +// Intel Corporation - initial implementation and documentation // +/////////////////////////////////////////////////////////////////////////// + + +package com.intel.sgx.wizards; + +import java.net.URI; +import java.util.Map; + +import org.eclipse.cdt.core.templateengine.TemplateCore; +import org.eclipse.cdt.core.templateengine.TemplateEngine; +import org.eclipse.cdt.ui.wizards.CProjectWizard; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IProjectDescription; +import org.eclipse.core.resources.IWorkspace; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IConfigurationElement; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.NullProgressMonitor; + +import com.intel.sgx.natures.SGXNature; + +public class SGXCProjectWizard extends CProjectWizard { + + private IProject project; + + @Override + protected boolean setCreated() throws CoreException { + boolean result = super.setCreated(); + doIt(project, new NullProgressMonitor()); + return result; + } + + @Override + public boolean performFinish() { + + return super.performFinish(); + } + + @Override + public void setInitializationData(IConfigurationElement config, + String propertyName, Object data) throws CoreException { + // TODO Auto-generated method stub + super.setInitializationData(config, propertyName, data); + } + + @Override + public IProject createIProject(String name, URI location) + throws CoreException { + // TODO Auto-generated method stub + return super.createIProject(name, location); + + } + + @Override + public IProject createIProject(String name, URI location, + IProgressMonitor monitor) throws CoreException { + project = super.createIProject(name, location, monitor); + return project; + } + + @Override + public String[] getExtensions() { + // TODO Auto-generated method stub + return super.getExtensions(); + } + + public SGXCProjectWizard() { + // TODO Auto-generated constructor stub + } + + @Override + public String[] getNatures() { + // TODO Auto-generated method stub + return super.getNatures(); + } + + @Override + protected IProject continueCreation(IProject prj) { + // TODO Auto-generated method stub + return super.continueCreation(prj); + } + + @Override + public String[] getContentTypeIDs() { + // TODO Auto-generated method stub + return super.getContentTypeIDs(); + } + + @Override + public IProject getProject(boolean defaults) { + // TODO Auto-generated method stub + return super.getProject(defaults); + } + + @Override + public String[] getLanguageIDs() { + // TODO Auto-generated method stub + return super.getLanguageIDs(); + } + + void doIt(IProject project, IProgressMonitor monitor) throws CoreException { + TemplateCore template = TemplateEngine.getDefault().getTemplateById( + "AddSGXNature"); + Map valueStore = template.getValueStore(); + valueStore.put("projectName", project.getName()); + valueStore.put("baseName", project.getName()); + template.executeTemplateProcesses(monitor, false); + + IWorkspace workspace = ResourcesPlugin.getWorkspace(); + IProjectDescription description = project.getDescription(); + String[] natures = description.getNatureIds(); + for (String nature : natures) { + } + + String[] newNatures = new String[natures.length + 1]; + System.arraycopy(natures, 0, newNatures, 0, natures.length); + newNatures[natures.length] = SGXNature.NATURE_ID; + IStatus status = workspace.validateNatureSet(newNatures); + + if (status.getCode() == IStatus.OK) { + description.setNatureIds(newNatures); + project.setDescription(description, null); + } else { + System.err + .println("Incorrect Project Nature. Please check Project Settings.");// TODO + // throw + // an + // exception + // here. + System.err.println("Status is: " + status.getCode()); + } + + } +} diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/templates/SGX.gif b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/templates/SGX.gif new file mode 100644 index 0000000000..21156bbf96 Binary files /dev/null and b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/templates/SGX.gif differ diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/templates/SGXtemplates/c++/minimal/enclavetemplate.xml b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/templates/SGXtemplates/c++/minimal/enclavetemplate.xml new file mode 100644 index 0000000000..40d4b6b13a --- /dev/null +++ b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/templates/SGXtemplates/c++/minimal/enclavetemplate.xml @@ -0,0 +1,61 @@ + + + + + + + + + + + + + diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/templates/SGXtemplates/c++/minimal/trustedstatictemplate.xml b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/templates/SGXtemplates/c++/minimal/trustedstatictemplate.xml new file mode 100644 index 0000000000..7b8649b17c --- /dev/null +++ b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/templates/SGXtemplates/c++/minimal/trustedstatictemplate.xml @@ -0,0 +1,52 @@ + + + + + + + + + + + + + diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/templates/SGXtemplates/c++/minimal/untrusted_module_template.xml b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/templates/SGXtemplates/c++/minimal/untrusted_module_template.xml new file mode 100644 index 0000000000..537100987e --- /dev/null +++ b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/templates/SGXtemplates/c++/minimal/untrusted_module_template.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/templates/SGXtemplates/c++/with_sample/enclavetemplate.xml b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/templates/SGXtemplates/c++/with_sample/enclavetemplate.xml new file mode 100644 index 0000000000..7d9527dafb --- /dev/null +++ b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/templates/SGXtemplates/c++/with_sample/enclavetemplate.xml @@ -0,0 +1,76 @@ + + + + + + + + + + + + + diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/templates/SGXtemplates/c/minimal/enclavetemplate.xml b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/templates/SGXtemplates/c/minimal/enclavetemplate.xml new file mode 100644 index 0000000000..c32e20347a --- /dev/null +++ b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/templates/SGXtemplates/c/minimal/enclavetemplate.xml @@ -0,0 +1,61 @@ + + + + + + + + + + + + + diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/templates/SGXtemplates/c/minimal/trustedstatictemplate.xml b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/templates/SGXtemplates/c/minimal/trustedstatictemplate.xml new file mode 100644 index 0000000000..6fc320cbba --- /dev/null +++ b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/templates/SGXtemplates/c/minimal/trustedstatictemplate.xml @@ -0,0 +1,51 @@ + + + + + + + + + + + + + diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/templates/SGXtemplates/c/minimal/untrusted_module_template.xml b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/templates/SGXtemplates/c/minimal/untrusted_module_template.xml new file mode 100644 index 0000000000..b8aec6e666 --- /dev/null +++ b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/templates/SGXtemplates/c/minimal/untrusted_module_template.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/templates/SGXtemplates/c/with_sample/enclavetemplate.xml b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/templates/SGXtemplates/c/with_sample/enclavetemplate.xml new file mode 100644 index 0000000000..66344d6636 --- /dev/null +++ b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/templates/SGXtemplates/c/with_sample/enclavetemplate.xml @@ -0,0 +1,76 @@ + + + + + + + + + + + + + diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/templates/SGXtemplates/common/addnaturetemplate.xml b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/templates/SGXtemplates/common/addnaturetemplate.xml new file mode 100644 index 0000000000..9cf5663e3c --- /dev/null +++ b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/templates/SGXtemplates/common/addnaturetemplate.xml @@ -0,0 +1,46 @@ + + + + + + + + + + + + + diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/templates/SGXtemplates/configtemplate.xml b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/templates/SGXtemplates/configtemplate.xml new file mode 100644 index 0000000000..7ce22c45e3 --- /dev/null +++ b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/templates/SGXtemplates/configtemplate.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/templates/SGXtemplates/ctemplate.xml b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/templates/SGXtemplates/ctemplate.xml new file mode 100644 index 0000000000..ed5cbba697 --- /dev/null +++ b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/templates/SGXtemplates/ctemplate.xml @@ -0,0 +1,83 @@ + + + + + + + + + + + + + + diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/templates/SGXtemplates/cxxstaticlibtemplate.xml b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/templates/SGXtemplates/cxxstaticlibtemplate.xml new file mode 100644 index 0000000000..8ad900de61 --- /dev/null +++ b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/templates/SGXtemplates/cxxstaticlibtemplate.xml @@ -0,0 +1,109 @@ + + + + + + + + + + + + + diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/templates/SGXtemplates/cxxtemplate.xml b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/templates/SGXtemplates/cxxtemplate.xml new file mode 100644 index 0000000000..a07ed1479c --- /dev/null +++ b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/templates/SGXtemplates/cxxtemplate.xml @@ -0,0 +1,44 @@ + + + + + + + + + + + + + diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/templates/SGXtemplates/template.properties b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/templates/SGXtemplates/template.properties new file mode 100644 index 0000000000..9ef4fcdf31 --- /dev/null +++ b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/templates/SGXtemplates/template.properties @@ -0,0 +1,63 @@ +######################################################################### +# Copyright (c) 2016 Intel Corporation. # +# # +# All rights reserved. This program and the accompanying materials # +# are made available under the terms of the Eclipse Public License v1.0 # +# which accompanies this distribution, and is available at # +# http://www.eclipse.org/legal/epl-v10.html # +# # +# Contributors: # +# Intel Corporation - initial implementation and documentation # +######################################################################### + SGX.author=Intel + + #Add Nature template Values + SGX.naturetemplate.title.description=A Software Guard Extensions Project template. + SGX.naturetemplate.title.label=SGX Project + SGX.naturetemplate.title.id=AddSGXNature + + #Enclave Config template Values + SGX.enclaveconfig.template.title.description=A Software Guard Extensions Configuration template. + SGX.enclaveconfig.template.title.label=SGX Enclave Configuration + SGX.enclaveconfig.template.title.id=SGXEnclaveConfig + + #Untrusted Module template values + SGX.untrustedModule.template.title.description= A Software Guard Extensions Untrusted Module template. + SGX.untrustedModule.template.title.label=SGX Untrusted Module + + #Enclave template values + SGX.enclave.template.title.description= A Software Guard Extensions Project template. + SGX.enclave.template.title.label=SGX Project + SGX.enclave.template.title.id=SGXProject + + #C template Values + SGX.Ctemplate.title.description=A Software Guard Extensions C Enclave Project template. + SGX.Ctemplate.title.label=SGX C Enclave Project + SGX.Ctemplate.title.id=SGXCProject + SGX.Ctemplate.enclaveSettings.label=Enclave Settings + SGX.Ctemplate.enclaveSettings.description=Initial settings required for a new enclave. + + #C Static lib template Values + SGX.CStatictemplate.title.description=A Software Guard Extensions C Enclave Project template. + SGX.CStatictemplate.title.label=SGX C Enclave Library Project + SGX.CStatictemplate.title.id=SGXCEnclaveLibProject + SGX.CStatictemplate.enclaveSettings.label=Enclave Settings + SGX.CStatictemplate.enclaveSettings.description=Initial settings required for a new enclave Library. + SGX.CStatictemplate.requiresEdl.label=Requires EDL + SGX.CStatictemplate.requiresEdl.description=De-select this option to create an Non-SGX trusted static library without an Edl file. By default, the project creates an Enclave library with an Edl file. + + #CXX template Values + SGX.CXXtemplate.title.description=A Software Guard Extensions C++ Enclave Project template. + SGX.CXXtemplate.title.label=C/C++ Project with SGX Nature + SGX.CXXtemplate.title.id=SGXCPPProject + SGX.CXXtemplate.enclaveSettings.label=Enclave Settings + SGX.CXXtemplate.enclaveSettings.description=Initial settings required for a new enclave. + + #CXX Static lib template Values + SGX.CXXStatictemplate.title.description=A Software Guard Extensions C++ Enclave Library Project template. + SGX.CXXStatictemplate.title.label=SGX C++ Enclave Library Project + SGX.CXXStatictemplate.title.id=SGXCPPEnclaveLibProject + SGX.CXXStatictemplate.enclaveSettings.label=Enclave Settings + SGX.CXXStatictemplate.enclaveSettings.description=Initial settings required for a new enclave Library. + SGX.CXXStatictemplate.requiresEdl.label=Requires EDL + SGX.CXXStatictemplate.requiresEdl.description=De-select this option to create an Non-SGX trusted static library without an Edl file. By default, the project creates an Enclave library with an Edl file. diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/templates/newmngc_app.gif b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/templates/newmngc_app.gif new file mode 100644 index 0000000000..23b0284f84 Binary files /dev/null and b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/templates/newmngc_app.gif differ diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/templates/newmngcc_app.gif b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/templates/newmngcc_app.gif new file mode 100644 index 0000000000..4b39411daf Binary files /dev/null and b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/templates/newmngcc_app.gif differ diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/templates/resources/Basename.config.xml b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/templates/resources/Basename.config.xml new file mode 100644 index 0000000000..6210afff28 --- /dev/null +++ b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/templates/resources/Basename.config.xml @@ -0,0 +1,9 @@ + + $(ProdID) + $(IsvSvn) + $(ThreadStackSize) + $(GlobalHeapSize) + $(TcsNumber) + $(TcsPolicy) + $(DisableDebug) + diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/templates/resources/Basename_private.pem b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/templates/resources/Basename_private.pem new file mode 100644 index 0000000000..790839d391 --- /dev/null +++ b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/templates/resources/Basename_private.pem @@ -0,0 +1,39 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIG4wIBAAKCAYEA8DLzZJpN7sN5J1PtKZAqWFeW+0/pPJVWRKEB8lfqXGJ0YIjG +1o0g0/+60ktlm0vVdWSqepmpRpTB2ZZjxxc+JHfZGQnvmlGx6qQxSFS9u+S8mSzD +MknsquLVsi7rojq34dTwSckMg0KQ/sGmsV6EgsUnldhdcPOJ8+NaaqtmAmjHYIpK +jLo3pJz0e7NqKvzE2YhmZZjrIZBNFHxX/lrQ36lW6Obp8xj9CqUMZp+2+/ntdFSl +7u9BK5y3ZHh8hUx6PkHfV8f1h9iG1jroINrrQwhftKmcsg/DPG7NOnjK/EvFaBku +6p0pnmeJM6VUihaLWYNAAjylVmMysenAjl4jsSzQeIe5idoPzYonCuAcASj8utgz +4OxxMHFYAXzgc2An6jp700NOgmYdhtoTMCUjohyd+RHJoSNJpE+ocKPVM72xucJB +o8dK55kI2/E19EVm59UyhXs2YGIjswziMK94H9KSl+TRthny7wYKju09lbdQAGid +rZcYTv2LVYP1Q5IDAgEDAoIBgQCgIfeYZt6fLPtvjUjGYBw65Q9SNUYoY47Ya1ah +j/GS7E2VsISPCMCNVSc23O5nh+OjmHGnERuEYyvmZEKEuiltpTtmBp+8NnacbXYw +OH59QyhmHdd22/MclzkhdJ0W0c/r40rb212s1wtUgRnLlFhXLhpj5ZOgolv37Obx +x5lW8ITrBtxd0XptvfhSd5wcqIM7sERDu0drtYi4UuVUPIs/xjnwmfFMu1NcbghE +ann9UUj4OG6fSityaHpC+v2uMvrexpJP3csYY/VbrYdzlp9GLHkm9mM3Y1tSYoU4 +GhsLstDSHIOZ5f2trh+Re6759SktXi+E9B4xQvJwwVAufmfU0aVESHtJDllt+UOK +LfINb3SmXX8uINqAlees+xJDm/ZcA8vvWWioD8Hv6c47qzrYH1JwvTJtk3G3orFs +syZe7KYwUUBxTREmTCdWoeHC9Hou4MxgiyViPl5SbIUz4yqJgcr3gPtoSRhwvY3v +r1GyeyRuB0CsAun5TQCcx31XwssCgcEA/hK8i1nKvEaTJ5GX9bGZo7BtjWftuGfa +qk0b4aZLWBeoJpGgivolaloTYE+aBAhPMFNKo9HT357o9SW48yk0kyReywJj6HBf +b82TSjt9wXmeo+6cE7EO7k1sINoJnlRiDkWqdpZLzty24dWMN27oXjO2ELUmAgnT +M8rzcshlhRsp/OSD+kIyEfVstx3H3hzPDMyHsNnlPv0Jycdp+1YfANLOaog+JHUZ +Kwb90RF2ePXnLbt2ts0N03kuJKgqS6xbAoHBAPIFR1Sheib8A6UlBP3HYrYVPGzQ +GiaS35aN6YSrVxKn5AZcyPjKB6+IRnkcNA8efmUirhb8pCzf3hOiD1V3U17N+ccY +nLPUKjjGrnFfsyuILx1dWQgKGoFDEF0qO2+h1FHvH3Wm5bdxw70l0Z81Yv+57D9A +1/q8S90QqtrOtiA/jnRj3P+RfxwxYSLgm3G54JS3eEPQmQ4HjG2isGeEmVC9E7ob +GnU3NRrit9ZUzJEIsi2iRfTFq4WQ3EWwjvRBeQKBwQCpYdMHkTHS2bdvtmVOdmZt +IEkI7/PQRTxxiL1BGYeQD8VvC8BcpsOcPAzq37wCsDTK4jHCi+KVFJtOGSX3cM23 +bZSHVu1FoD+f3mIxfP6A+78X9GgNILSe3kgV5rEUOEFe2RxPDt00kySWjl16SfA+ +zSQLI26sBozNMfeh2u5YvMaomFf8LCFhTkh6E9qUEzSzMwUgkUN/U1vb2kanjr9V +4d7xsClto2Ycr1Pgtk77TpoefPnPM16M+3QYcBwycucCgcEAoVjaOGumxKgCbhit +/oTseWN9neARbwyVDwlGWHI6DG/tWZMwpdwFH7Au+2gitL7+7hceuf3CyJU+t8Ff +jk+M6d6mhLsTIo1xey8e9j/Mx7AfaOjmBVwRq4IK6MbSSmvi4UoU+RnuekvX026L +v3jsqnvy1NXlUdLdPgsckd8kFX+0TZfoqmD/aCDrbJW89nvrDc+lgosQtAUISRcg +RQMQ4H4NJry8TiTOEex6juMzC1shc8GD+IPHrmCS2SBfTYD7AoHAOYqsSbLvkhWP +JCx3wicFIY4y+eJW2hNK19ho+PEcrmu7+HKZHMU7oslsoSnme5mMomK9pZnY8KSy +px0D13XyUmEmZluxKcdUDC6mRWH4qkPt/9DGbzHwNLfla+KbxoNLi7F6U5XU5J/6 +NzZeO9HrLzHy1ck/0xUDU7Y+WWniMbUdlOpXSd+SsZtKomRhnc+QljYqSJplJL7f +mfnQ4stcY3RcPHGwfDOQT9sVk0hoIGXKCzEl217Iw1P8UwKvBbNe +-----END RSA PRIVATE KEY----- diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/templates/sgx/SGXEnclave/makefiles/c++/sgx_t.mk b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/templates/sgx/SGXEnclave/makefiles/c++/sgx_t.mk new file mode 100644 index 0000000000..41aaf26fa4 --- /dev/null +++ b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/templates/sgx/SGXEnclave/makefiles/c++/sgx_t.mk @@ -0,0 +1,127 @@ +######## SGX SDK Settings ######## +SGX_SDK ?= $(SdkPathFromPlugin) +SGX_MODE ?= SIM +SGX_ARCH ?= x64 + +ifeq ($(shell getconf LONG_BIT), 32) + SGX_ARCH := x86 +else ifeq ($(findstring -m32, $(CXXFLAGS)), -m32) + SGX_ARCH := x86 +endif + +ifeq ($(SGX_ARCH), x86) + SGX_COMMON_CFLAGS := -m32 + SGX_LIBRARY_PATH := $(SGX_SDK)/lib + SGX_ENCLAVE_SIGNER := $(SGX_SDK)/bin/x86/sgx_sign + SGX_EDGER8R := $(SGX_SDK)/bin/x86/sgx_edger8r +else + SGX_COMMON_CFLAGS := -m64 + SGX_LIBRARY_PATH := $(SGX_SDK)/lib64 + SGX_ENCLAVE_SIGNER := $(SGX_SDK)/bin/x64/sgx_sign + SGX_EDGER8R := $(SGX_SDK)/bin/x64/sgx_edger8r +endif + +ifeq ($(SGX_DEBUG), 1) +ifeq ($(SGX_PRERELEASE), 1) +$(error Cannot set SGX_DEBUG and SGX_PRERELEASE at the same time!!) +endif +endif + +ifeq ($(SGX_DEBUG), 1) + SGX_COMMON_CFLAGS += -O0 -g +else + SGX_COMMON_CFLAGS += -O2 +endif + +ifneq ($(SGX_MODE), HW) + Trts_Library_Name := sgx_trts_sim + Service_Library_Name := sgx_tservice_sim +else + Trts_Library_Name := sgx_trts + Service_Library_Name := sgx_tservice +endif + +Crypto_Library_Name := sgx_tcrypto + +$(EnclaveName)_Cpp_Files := trusted/$(enclaveName).cpp +$(EnclaveName)_C_Files := +$(EnclaveName)_Include_Paths := -IInclude -Itrusted -I$(SGX_SDK)/include -I$(SGX_SDK)/include/tlibc -I$(SGX_SDK)/include/stlport + + +Flags_Just_For_C := -Wno-implicit-function-declaration -std=c11 +Common_C_Cpp_Flags := $(SGX_COMMON_CFLAGS) -nostdinc -fvisibility=hidden -fpie -fstack-protector $($(EnclaveName)_Include_Paths) -fno-builtin-printf -I. +$(EnclaveName)_C_Flags := $(Flags_Just_For_C) $(Common_C_Cpp_Flags) +$(EnclaveName)_Cpp_Flags := $(Common_C_Cpp_Flags) -std=c++11 -nostdinc++ -fno-builtin-printf -I. + +$(EnclaveName)_Cpp_Flags := $($(EnclaveName)_Cpp_Flags) -fno-builtin-printf + +$(EnclaveName)_Link_Flags := $(SGX_COMMON_CFLAGS) -Wl,--no-undefined -nostdlib -nodefaultlibs -nostartfiles -L$(SGX_LIBRARY_PATH) \ + -Wl,--whole-archive -l$(Trts_Library_Name) -Wl,--no-whole-archive \ + -Wl,--start-group -lsgx_tstdc -lsgx_tstdcxx -l$(Crypto_Library_Name) -l$(Service_Library_Name) -Wl,--end-group \ + -Wl,-Bstatic -Wl,-Bsymbolic -Wl,--no-undefined \ + -Wl,-pie,-eenclave_entry -Wl,--export-dynamic \ + -Wl,--defsym,__ImageBase=0 \ + -Wl,--version-script=trusted/$(enclaveName).lds + +$(EnclaveName)_Cpp_Objects := $($(EnclaveName)_Cpp_Files:.cpp=.o) +$(EnclaveName)_C_Objects := $($(EnclaveName)_C_Files:.c=.o) + +ifeq ($(SGX_MODE), HW) +ifneq ($(SGX_DEBUG), 1) +ifneq ($(SGX_PRERELEASE), 1) +Build_Mode = HW_RELEASE +endif +endif +endif + + +.PHONY: all run + +ifeq ($(Build_Mode), HW_RELEASE) +all: $(enclaveName).so + @echo "Build enclave $(enclaveName).so [$(Build_Mode)|$(SGX_ARCH)] success!" + @echo + @echo "*********************************************************************************************************************************************************" + @echo "PLEASE NOTE: In this mode, please sign the $(enclaveName).so first using Two Step Sign mechanism before you run the app to launch and access the enclave." + @echo "*********************************************************************************************************************************************************" + @echo + + +else +all: $(enclaveName).signed.so +endif + +run: all +ifneq ($(Build_Mode), HW_RELEASE) + @$(CURDIR)/app + @echo "RUN => app [$(SGX_MODE)|$(SGX_ARCH), OK]" +endif + + +######## $(enclaveName) Objects ######## + +trusted/$(enclaveName)_t.c: $(SGX_EDGER8R) ./trusted/$(enclaveName).edl + @cd ./trusted && $(SGX_EDGER8R) --trusted ../trusted/$(enclaveName).edl --search-path ../trusted --search-path $(SGX_SDK)/include + @echo "GEN => $@" + +trusted/$(enclaveName)_t.o: ./trusted/$(enclaveName)_t.c + @$(CC) $($(EnclaveName)_C_Flags) -c $< -o $@ + @echo "CC <= $<" + +trusted/%.o: trusted/%.cpp + @$(CXX) $($(EnclaveName)_Cpp_Flags) -c $< -o $@ + @echo "CXX <= $<" + +trusted/%.o: trusted/%.c + @$(CC) $($(EnclaveName)_C_Flags) -c $< -o $@ + @echo "CC <= $<" + +$(enclaveName).so: trusted/$(enclaveName)_t.o $($(EnclaveName)_Cpp_Objects) $($(EnclaveName)_C_Objects) + @$(CXX) $^ -o $@ $($(EnclaveName)_Link_Flags) + @echo "LINK => $@" + +$(enclaveName).signed.so: $(enclaveName).so + @$(SGX_ENCLAVE_SIGNER) sign -key trusted/$(enclaveName)_private.pem -enclave $(enclaveName).so -out $@ -config trusted/$(enclaveName).config.xml + @echo "SIGN => $@" +clean: + @rm -f $(enclaveName).* trusted/$(enclaveName)_t.* $($(EnclaveName)_Cpp_Objects) $($(EnclaveName)_C_Objects) diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/templates/sgx/SGXEnclave/makefiles/c++/sgx_u.mk b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/templates/sgx/SGXEnclave/makefiles/c++/sgx_u.mk new file mode 100644 index 0000000000..201963cb07 --- /dev/null +++ b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/templates/sgx/SGXEnclave/makefiles/c++/sgx_u.mk @@ -0,0 +1,129 @@ +######## SGX SDK Settings ######## +SGX_SDK ?= $(SdkPathFromPlugin) +SGX_MODE ?= SIM +SGX_ARCH ?= x64 +UNTRUSTED_DIR=untrusted + +ifeq ($(shell getconf LONG_BIT), 32) + SGX_ARCH := x86 +else ifeq ($(findstring -m32, $(CXXFLAGS)), -m32) + SGX_ARCH := x86 +endif + +ifeq ($(SGX_ARCH), x86) + SGX_COMMON_CFLAGS := -m32 + SGX_LIBRARY_PATH := $(SGX_SDK)/lib + SGX_ENCLAVE_SIGNER := $(SGX_SDK)/bin/x86/sgx_sign + SGX_EDGER8R := $(SGX_SDK)/bin/x86/sgx_edger8r +else + SGX_COMMON_CFLAGS := -m64 + SGX_LIBRARY_PATH := $(SGX_SDK)/lib64 + SGX_ENCLAVE_SIGNER := $(SGX_SDK)/bin/x64/sgx_sign + SGX_EDGER8R := $(SGX_SDK)/bin/x64/sgx_edger8r +endif + +ifeq ($(SGX_DEBUG), 1) +ifeq ($(SGX_PRERELEASE), 1) +$(error Cannot set SGX_DEBUG and SGX_PRERELEASE at the same time!!) +endif +endif + +ifeq ($(SGX_DEBUG), 1) + SGX_COMMON_CFLAGS += -O0 -g +else + SGX_COMMON_CFLAGS += -O2 +endif + +######## App Settings ######## + +ifneq ($(SGX_MODE), HW) + Urts_Library_Name := sgx_urts_sim +else + Urts_Library_Name := sgx_urts +endif + +# App_Cpp_Files := App/App.cpp $(wildcard App/Edger8rSyntax/*.cpp) $(wildcard App/TrustedLibrary/*.cpp) +App_Cpp_Files := $(UNTRUSTED_DIR)/sample.cpp # $(wildcard App/TrustedLibrary/*.cpp) +App_Include_Paths := -IInclude -I$(UNTRUSTED_DIR) -I$(SGX_SDK)/include + +App_C_Flags := $(SGX_COMMON_CFLAGS) -fPIC -Wno-attributes $(App_Include_Paths) + +# Three configuration modes - Debug, prerelease, release +# Debug - Macro DEBUG enabled. +# Prerelease - Macro NDEBUG and EDEBUG enabled. +# Release - Macro NDEBUG enabled. +ifeq ($(SGX_DEBUG), 1) + App_C_Flags += -DDEBUG -UNDEBUG -UEDEBUG +else ifeq ($(SGX_PRERELEASE), 1) + App_C_Flags += -DNDEBUG -DEDEBUG -UDEBUG +else + App_C_Flags += -DNDEBUG -UEDEBUG -UDEBUG +endif + +App_Cpp_Flags := $(App_C_Flags) -std=c++11 +App_Link_Flags := $(SGX_COMMON_CFLAGS) -L$(SGX_LIBRARY_PATH) -l$(Urts_Library_Name) -lpthread + +ifneq ($(SGX_MODE), HW) + App_Link_Flags += -lsgx_uae_service_sim +else + App_Link_Flags += -lsgx_uae_service +endif + +App_Cpp_Objects := $(App_Cpp_Files:.cpp=.o) + + + +ifeq ($(SGX_MODE), HW) +ifneq ($(SGX_DEBUG), 1) +ifneq ($(SGX_PRERELEASE), 1) +Build_Mode = HW_RELEASE +endif +endif +endif + + +.PHONY: all run + +ifeq ($(Build_Mode), HW_RELEASE) +all: sample + @echo "Build sample [$(Build_Mode)|$(SGX_ARCH)] success!" + @echo + @echo "*********************************************************************************************************************************************************" + @echo "PLEASE NOTE: In this mode, please sign the $(enclaveName).so first using Two Step Sign mechanism before you run the app to launch and access the enclave." + @echo "*********************************************************************************************************************************************************" + @echo + + +else +all: sample +endif + +run: all +ifneq ($(Build_Mode), HW_RELEASE) + @$(CURDIR)/sample + @echo "RUN => sample [$(SGX_MODE)|$(SGX_ARCH), OK]" +endif + +######## App Objects ######## + +$(UNTRUSTED_DIR)/$(enclaveName)_u.c: $(SGX_EDGER8R) trusted/$(enclaveName).edl + @cd $(UNTRUSTED_DIR) && $(SGX_EDGER8R) --untrusted ../trusted/$(enclaveName).edl --search-path ../trusted --search-path $(SGX_SDK)/include + @echo "GEN => $@" + +$(UNTRUSTED_DIR)/$(enclaveName)_u.o: $(UNTRUSTED_DIR)/$(enclaveName)_u.c + @$(CC) $(App_C_Flags) -c $< -o $@ + @echo "CC <= $<" + +$(UNTRUSTED_DIR)/%.o: $(UNTRUSTED_DIR)/%.cpp + @$(CXX) $(App_Cpp_Flags) -c $< -o $@ + @echo "CXX <= $<" + +sample: $(UNTRUSTED_DIR)/$(enclaveName)_u.o $(App_Cpp_Objects) + @$(CXX) $^ -o $@ $(App_Link_Flags) + @echo "LINK => $@" + + +.PHONY: clean + +clean: + @rm -f sample $(App_Cpp_Objects) $(UNTRUSTED_DIR)/$(enclaveName)_u.* diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/templates/sgx/SGXEnclave/makefiles/c++/sgx_u.without_app.mk b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/templates/sgx/SGXEnclave/makefiles/c++/sgx_u.without_app.mk new file mode 100644 index 0000000000..00aed4b876 --- /dev/null +++ b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/templates/sgx/SGXEnclave/makefiles/c++/sgx_u.without_app.mk @@ -0,0 +1,71 @@ +######## SGX SDK Settings ######## +SGX_SDK ?= $(SdkPathFromPlugin) +SGX_MODE ?= SIM +SGX_ARCH ?= x64 +UNTRUSTED_DIR=untrusted + +ifeq ($(shell getconf LONG_BIT), 32) + SGX_ARCH := x86 +else ifeq ($(findstring -m32, $(CXXFLAGS)), -m32) + SGX_ARCH := x86 +endif + +ifeq ($(SGX_ARCH), x86) + SGX_COMMON_CFLAGS := -m32 + SGX_EDGER8R := $(SGX_SDK)/bin/x86/sgx_edger8r +else + SGX_COMMON_CFLAGS := -m64 + SGX_EDGER8R := $(SGX_SDK)/bin/x64/sgx_edger8r +endif + +ifeq ($(SGX_DEBUG), 1) +ifeq ($(SGX_PRERELEASE), 1) +$(error Cannot set SGX_DEBUG and SGX_PRERELEASE at the same time!!) +endif +endif + +ifeq ($(SGX_DEBUG), 1) + SGX_COMMON_CFLAGS += -O0 -g +else + SGX_COMMON_CFLAGS += -O2 +endif + +######## App Settings ######## + +App_Include_Paths := -IInclude -I$(UNTRUSTED_DIR) -I$(SGX_SDK)/include + +App_C_Flags := $(SGX_COMMON_CFLAGS) -fPIC -Wno-attributes $(App_Include_Paths) + +# Three configuration modes - Debug, prerelease, release +# Debug - Macro DEBUG enabled. +# Prerelease - Macro NDEBUG and EDEBUG enabled. +# Release - Macro NDEBUG enabled. +ifeq ($(SGX_DEBUG), 1) + App_C_Flags += -DDEBUG -UNDEBUG -UEDEBUG +else ifeq ($(SGX_PRERELEASE), 1) + App_C_Flags += -DNDEBUG -DEDEBUG -UDEBUG +else + App_C_Flags += -DNDEBUG -UEDEBUG -UDEBUG +endif + +App_Cpp_Flags := $(App_C_Flags) -std=c++11 + +.PHONY: all run + +all: $(UNTRUSTED_DIR)/$(enclaveName)_u.o + +######## App Objects ######## + +$(UNTRUSTED_DIR)/$(enclaveName)_u.c: $(SGX_EDGER8R) trusted/$(enclaveName).edl + @mkdir -p $(UNTRUSTED_DIR) + @cd $(UNTRUSTED_DIR) && $(SGX_EDGER8R) --untrusted ../trusted/$(enclaveName).edl --search-path ../trusted --search-path $(SGX_SDK)/include + @echo "GEN => $@" + +$(UNTRUSTED_DIR)/$(enclaveName)_u.o: $(UNTRUSTED_DIR)/$(enclaveName)_u.c + @$(CC) $(App_C_Flags) -c $< -o $@ + @echo "CC <= $<" + +.PHONY: clean + +clean: + @rm -f $(UNTRUSTED_DIR)/$(enclaveName)_u.* diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/templates/sgx/SGXEnclave/makefiles/c/sgx_t.mk b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/templates/sgx/SGXEnclave/makefiles/c/sgx_t.mk new file mode 100644 index 0000000000..3851c1de3b --- /dev/null +++ b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/templates/sgx/SGXEnclave/makefiles/c/sgx_t.mk @@ -0,0 +1,115 @@ +######## SGX SDK Settings ######## +SGX_SDK ?= $(SdkPathFromPlugin) +SGX_MODE ?= SIM +SGX_ARCH ?= x64 + +ifeq ($(shell getconf LONG_BIT), 32) + SGX_ARCH := x86 +else ifeq ($(findstring -m32, $(CXXFLAGS)), -m32) + SGX_ARCH := x86 +endif + +ifeq ($(SGX_ARCH), x86) + SGX_COMMON_CFLAGS := -m32 + SGX_LIBRARY_PATH := $(SGX_SDK)/lib + SGX_ENCLAVE_SIGNER := $(SGX_SDK)/bin/x86/sgx_sign + SGX_EDGER8R := $(SGX_SDK)/bin/x86/sgx_edger8r +else + SGX_COMMON_CFLAGS := -m64 + SGX_LIBRARY_PATH := $(SGX_SDK)/lib64 + SGX_ENCLAVE_SIGNER := $(SGX_SDK)/bin/x64/sgx_sign + SGX_EDGER8R := $(SGX_SDK)/bin/x64/sgx_edger8r +endif + +ifeq ($(SGX_DEBUG), 1) +ifeq ($(SGX_PRERELEASE), 1) +$(error Cannot set SGX_DEBUG and SGX_PRERELEASE at the same time!!) +endif +endif + +ifeq ($(SGX_DEBUG), 1) + SGX_COMMON_CFLAGS += -O0 -g +else + SGX_COMMON_CFLAGS += -O2 +endif + +ifneq ($(SGX_MODE), HW) + Trts_Library_Name := sgx_trts_sim + Service_Library_Name := sgx_tservice_sim +else + Trts_Library_Name := sgx_trts + Service_Library_Name := sgx_tservice +endif + +Crypto_Library_Name := sgx_tcrypto + +$(EnclaveName)_C_Files := trusted/$(enclaveName).c +$(EnclaveName)_Include_Paths := -IInclude -Itrusted -I$(SGX_SDK)/include -I$(SGX_SDK)/include/tlibc -I$(SGX_SDK)/include/stlport + +Flags_Just_For_C := -Wno-implicit-function-declaration -std=c11 +Common_C_Cpp_Flags := $(SGX_COMMON_CFLAGS) -nostdinc -fvisibility=hidden -fpie -fstack-protector $($(EnclaveName)_Include_Paths) -fno-builtin-printf -I. +$(EnclaveName)_C_Flags := $(Flags_Just_For_C) $(Common_C_Cpp_Flags) + +$(EnclaveName)_Link_Flags := $(SGX_COMMON_CFLAGS) -Wl,--no-undefined -nostdlib -nodefaultlibs -nostartfiles -L$(SGX_LIBRARY_PATH) \ + -Wl,--whole-archive -l$(Trts_Library_Name) -Wl,--no-whole-archive \ + -Wl,--start-group -lsgx_tstdc -lsgx_tstdcxx -l$(Crypto_Library_Name) -l$(Service_Library_Name) -Wl,--end-group \ + -Wl,-Bstatic -Wl,-Bsymbolic -Wl,--no-undefined \ + -Wl,-pie,-eenclave_entry -Wl,--export-dynamic \ + -Wl,--defsym,__ImageBase=0 \ + -Wl,--version-script=trusted/$(enclaveName).lds + +$(EnclaveName)_C_Objects := $($(EnclaveName)_C_Files:.c=.o) + +ifeq ($(SGX_MODE), HW) +ifneq ($(SGX_DEBUG), 1) +ifneq ($(SGX_PRERELEASE), 1) +Build_Mode = HW_RELEASE +endif +endif +endif + + +.PHONY: all run + +ifeq ($(Build_Mode), HW_RELEASE) +all: $(enclaveName).so + @echo "Build enclave $(enclaveName).so [$(Build_Mode)|$(SGX_ARCH)] success!" + @echo + @echo "*********************************************************************************************************************************************************" + @echo "PLEASE NOTE: In this mode, please sign the $(enclaveName).so first using Two Step Sign mechanism before you run the app to launch and access the enclave." + @echo "*********************************************************************************************************************************************************" + @echo +else +all: $(enclaveName).signed.so +endif + +run: all +ifneq ($(Build_Mode), HW_RELEASE) + @$(CURDIR)/app + @echo "RUN => app [$(SGX_MODE)|$(SGX_ARCH), OK]" +endif + + +######## $(enclaveName) Objects ######## + +trusted/$(enclaveName)_t.c: $(SGX_EDGER8R) ./trusted/$(enclaveName).edl + @cd ./trusted && $(SGX_EDGER8R) --trusted ../trusted/$(enclaveName).edl --search-path ../trusted --search-path $(SGX_SDK)/include + @echo "GEN => $@" + +trusted/$(enclaveName)_t.o: ./trusted/$(enclaveName)_t.c + @$(CC) $($(EnclaveName)_C_Flags) -c $< -o $@ + @echo "CC <= $<" + +trusted/%.o: trusted/%.c + @$(CC) $($(EnclaveName)_C_Flags) -c $< -o $@ + @echo "CC <= $<" + +$(enclaveName).so: trusted/$(enclaveName)_t.o $($(EnclaveName)_C_Objects) + @$(CXX) $^ -o $@ $($(EnclaveName)_Link_Flags) + @echo "LINK => $@" + +$(enclaveName).signed.so: $(enclaveName).so + @$(SGX_ENCLAVE_SIGNER) sign -key trusted/$(enclaveName)_private.pem -enclave $(enclaveName).so -out $@ -config trusted/$(enclaveName).config.xml + @echo "SIGN => $@" +clean: + @rm -f $(enclaveName).* trusted/$(enclaveName)_t.* $($(EnclaveName)_C_Objects) diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/templates/sgx/SGXEnclave/makefiles/c/sgx_u.mk b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/templates/sgx/SGXEnclave/makefiles/c/sgx_u.mk new file mode 100644 index 0000000000..70d293e363 --- /dev/null +++ b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/templates/sgx/SGXEnclave/makefiles/c/sgx_u.mk @@ -0,0 +1,126 @@ +######## SGX SDK Settings ######## +SGX_SDK ?= $(SdkPathFromPlugin) +SGX_MODE ?= SIM +SGX_ARCH ?= x64 +UNTRUSTED_DIR=untrusted + +ifeq ($(shell getconf LONG_BIT), 32) + SGX_ARCH := x86 +else ifeq ($(findstring -m32, $(CXXFLAGS)), -m32) + SGX_ARCH := x86 +endif + +ifeq ($(SGX_ARCH), x86) + SGX_COMMON_CFLAGS := -m32 + SGX_LIBRARY_PATH := $(SGX_SDK)/lib + SGX_ENCLAVE_SIGNER := $(SGX_SDK)/bin/x86/sgx_sign + SGX_EDGER8R := $(SGX_SDK)/bin/x86/sgx_edger8r +else + SGX_COMMON_CFLAGS := -m64 + SGX_LIBRARY_PATH := $(SGX_SDK)/lib64 + SGX_ENCLAVE_SIGNER := $(SGX_SDK)/bin/x64/sgx_sign + SGX_EDGER8R := $(SGX_SDK)/bin/x64/sgx_edger8r +endif + +ifeq ($(SGX_DEBUG), 1) +ifeq ($(SGX_PRERELEASE), 1) +$(error Cannot set SGX_DEBUG and SGX_PRERELEASE at the same time!!) +endif +endif + +ifeq ($(SGX_DEBUG), 1) + SGX_COMMON_CFLAGS += -O0 -g +else + SGX_COMMON_CFLAGS += -O2 +endif + +######## App Settings ######## + +ifneq ($(SGX_MODE), HW) + Urts_Library_Name := sgx_urts_sim +else + Urts_Library_Name := sgx_urts +endif + +App_C_Files := $(UNTRUSTED_DIR)/sample.c +App_Include_Paths := -IInclude -I$(UNTRUSTED_DIR) -I$(SGX_SDK)/include + +App_C_Flags := $(SGX_COMMON_CFLAGS) -fPIC -Wno-attributes $(App_Include_Paths) + +# Three configuration modes - Debug, prerelease, release +# Debug - Macro DEBUG enabled. +# Prerelease - Macro NDEBUG and EDEBUG enabled. +# Release - Macro NDEBUG enabled. +ifeq ($(SGX_DEBUG), 1) + App_C_Flags += -DDEBUG -UNDEBUG -UEDEBUG +else ifeq ($(SGX_PRERELEASE), 1) + App_C_Flags += -DNDEBUG -DEDEBUG -UDEBUG +else + App_C_Flags += -DNDEBUG -UEDEBUG -UDEBUG +endif + +App_Link_Flags := $(SGX_COMMON_CFLAGS) -L$(SGX_LIBRARY_PATH) -l$(Urts_Library_Name) -lpthread + +ifneq ($(SGX_MODE), HW) + App_Link_Flags += -lsgx_uae_service_sim +else + App_Link_Flags += -lsgx_uae_service +endif + +App_C_Objects := $(App_C_Files:.c=.o) + + + +ifeq ($(SGX_MODE), HW) +ifneq ($(SGX_DEBUG), 1) +ifneq ($(SGX_PRERELEASE), 1) +Build_Mode = HW_RELEASE +endif +endif +endif + + +.PHONY: all run + +ifeq ($(Build_Mode), HW_RELEASE) +all: sample + @echo "Build sample [$(Build_Mode)|$(SGX_ARCH)] success!" + @echo + @echo "*********************************************************************************************************************************************************" + @echo "PLEASE NOTE: In this mode, please sign the $(enclaveName).so first using Two Step Sign mechanism before you run the app to launch and access the enclave." + @echo "*********************************************************************************************************************************************************" + @echo + +else +all: sample +endif + +run: all +ifneq ($(Build_Mode), HW_RELEASE) + @$(CURDIR)/sample + @echo "RUN => sample [$(SGX_MODE)|$(SGX_ARCH), OK]" +endif + +######## App Objects ######## + +$(UNTRUSTED_DIR)/$(enclaveName)_u.c: $(SGX_EDGER8R) trusted/$(enclaveName).edl + @cd $(UNTRUSTED_DIR) && $(SGX_EDGER8R) --untrusted ../trusted/$(enclaveName).edl --search-path ../trusted --search-path $(SGX_SDK)/include + @echo "GEN => $@" + +$(UNTRUSTED_DIR)/$(enclaveName)_u.o: $(UNTRUSTED_DIR)/$(enclaveName)_u.c + @$(CC) $(App_C_Flags) -c $< -o $@ + @echo "CC <= $<" + +$(UNTRUSTED_DIR)/%.o: $(UNTRUSTED_DIR)/%.c + @$(CXX) $(App_C_Flags) -c $< -o $@ + @echo "CXX <= $<" + +sample: $(UNTRUSTED_DIR)/$(enclaveName)_u.o $(App_C_Objects) + @$(CXX) $^ -o $@ $(App_Link_Flags) + @echo "LINK => $@" + + +.PHONY: clean + +clean: + @rm -f sample $(App_C_Objects) $(UNTRUSTED_DIR)/$(enclaveName)_u.* diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/templates/sgx/SGXEnclave/makefiles/c/sgx_u.without_app.mk b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/templates/sgx/SGXEnclave/makefiles/c/sgx_u.without_app.mk new file mode 100644 index 0000000000..f9eee94c69 --- /dev/null +++ b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/templates/sgx/SGXEnclave/makefiles/c/sgx_u.without_app.mk @@ -0,0 +1,70 @@ +######## SGX SDK Settings ######## +SGX_SDK ?= $(SdkPathFromPlugin) +SGX_MODE ?= SIM +SGX_ARCH ?= x64 +UNTRUSTED_DIR=untrusted + +ifeq ($(shell getconf LONG_BIT), 32) + SGX_ARCH := x86 +else ifeq ($(findstring -m32, $(CXXFLAGS)), -m32) + SGX_ARCH := x86 +endif + +ifeq ($(SGX_ARCH), x86) + SGX_COMMON_CFLAGS := -m32 + SGX_EDGER8R := $(SGX_SDK)/bin/x86/sgx_edger8r +else + SGX_COMMON_CFLAGS := -m64 + SGX_EDGER8R := $(SGX_SDK)/bin/x64/sgx_edger8r +endif + +ifeq ($(SGX_DEBUG), 1) +ifeq ($(SGX_PRERELEASE), 1) +$(error Cannot set SGX_DEBUG and SGX_PRERELEASE at the same time!!) +endif +endif + +ifeq ($(SGX_DEBUG), 1) + SGX_COMMON_CFLAGS += -O0 -g +else + SGX_COMMON_CFLAGS += -O2 +endif + +######## App Settings ######## + +App_Include_Paths := -IInclude -I$(UNTRUSTED_DIR) -I$(SGX_SDK)/include + +App_C_Flags := $(SGX_COMMON_CFLAGS) -fPIC -Wno-attributes $(App_Include_Paths) + +# Three configuration modes - Debug, prerelease, release +# Debug - Macro DEBUG enabled. +# Prerelease - Macro NDEBUG and EDEBUG enabled. +# Release - Macro NDEBUG enabled. +ifeq ($(SGX_DEBUG), 1) + App_C_Flags += -DDEBUG -UNDEBUG -UEDEBUG +else ifeq ($(SGX_PRERELEASE), 1) + App_C_Flags += -DNDEBUG -DEDEBUG -UDEBUG +else + App_C_Flags += -DNDEBUG -UEDEBUG -UDEBUG +endif + + +.PHONY: all run + +all: $(UNTRUSTED_DIR)/$(enclaveName)_u.o + +######## App Objects ######## + +$(UNTRUSTED_DIR)/$(enclaveName)_u.c: $(SGX_EDGER8R) trusted/$(enclaveName).edl + @mkdir -p $(UNTRUSTED_DIR) + @cd $(UNTRUSTED_DIR) && $(SGX_EDGER8R) --untrusted ../trusted/$(enclaveName).edl --search-path ../trusted --search-path $(SGX_SDK)/include + @echo "GEN => $@" + +$(UNTRUSTED_DIR)/$(enclaveName)_u.o: $(UNTRUSTED_DIR)/$(enclaveName)_u.c + @$(CC) $(App_C_Flags) -c $< -o $@ + @echo "CC <= $<" + +.PHONY: clean + +clean: + @rm -f $(UNTRUSTED_DIR)/$(enclaveName)_u.* diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/templates/sgx/SGXEnclave/makefiles/common/Makefile b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/templates/sgx/SGXEnclave/makefiles/common/Makefile new file mode 100644 index 0000000000..3defedc4c8 --- /dev/null +++ b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/templates/sgx/SGXEnclave/makefiles/common/Makefile @@ -0,0 +1,8 @@ +all: + $(MAKE) -f sgx_u.mk all + $(MAKE) -f sgx_t.mk all + +clean: + $(MAKE) -f sgx_u.mk clean + $(MAKE) -f sgx_t.mk clean + diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/templates/sgx/SGXEnclave/trusted/Enclave1.config.xml b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/templates/sgx/SGXEnclave/trusted/Enclave1.config.xml new file mode 100644 index 0000000000..1b2f224567 --- /dev/null +++ b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/templates/sgx/SGXEnclave/trusted/Enclave1.config.xml @@ -0,0 +1,9 @@ + + 0 + 0 + 0x40000 + 0x100000 + 10 + 1 + 0 + diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/templates/sgx/SGXEnclave/trusted/Enclave1.cpp b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/templates/sgx/SGXEnclave/trusted/Enclave1.cpp new file mode 100644 index 0000000000..78f55c1553 --- /dev/null +++ b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/templates/sgx/SGXEnclave/trusted/Enclave1.cpp @@ -0,0 +1,26 @@ +#include +#include /* vsnprintf */ + +#include "$(enclaveName).h" +#include "$(enclaveName)_t.h" /* print_string */ + +/* + * printf: + * Invokes OCALL to display the enclave buffer to the terminal. + */ +void printf(const char *fmt, ...) +{ + char buf[BUFSIZ] = {'\0'}; + va_list ap; + va_start(ap, fmt); + vsnprintf(buf, BUFSIZ, fmt, ap); + va_end(ap); + ocall_$(enclaveName)_sample(buf); +} + +int ecall_$(enclaveName)_sample() +{ + printf("IN $(ENCLAVENAME)\n"); + return 0; +} + diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/templates/sgx/SGXEnclave/trusted/Enclave1.edl b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/templates/sgx/SGXEnclave/trusted/Enclave1.edl new file mode 100644 index 0000000000..e97f447eb3 --- /dev/null +++ b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/templates/sgx/SGXEnclave/trusted/Enclave1.edl @@ -0,0 +1,18 @@ +/* $(enclaveName).edl - Top EDL file. */ + +enclave { + + /* + * ocall_$(enclaveName)_sample - invokes OCALL to display string buffer inside the enclave. + * [in]: copy the string buffer to App outside. + * [string]: specifies 'str' is a NULL terminated buffer. + */ + untrusted { + void ocall_$(enclaveName)_sample([in, string] const char *str); + }; + + + trusted { + public int ecall_$(enclaveName)_sample(); + }; +}; diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/templates/sgx/SGXEnclave/trusted/Enclave1.h b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/templates/sgx/SGXEnclave/trusted/Enclave1.h new file mode 100644 index 0000000000..2d29332f3f --- /dev/null +++ b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/templates/sgx/SGXEnclave/trusted/Enclave1.h @@ -0,0 +1,17 @@ +#ifndef _$(ENCLAVENAME)_H_ +#define _$(ENCLAVENAME)_H_ + +#include +#include + +#if defined(__cplusplus) +extern "C" { +#endif + +void printf(const char *fmt, ...); + +#if defined(__cplusplus) +} +#endif + +#endif /* !_$(ENCLAVENAME)_H_ */ diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/templates/sgx/SGXEnclave/trusted/Enclave1.lds b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/templates/sgx/SGXEnclave/trusted/Enclave1.lds new file mode 100644 index 0000000000..9019f79f5d --- /dev/null +++ b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/templates/sgx/SGXEnclave/trusted/Enclave1.lds @@ -0,0 +1,9 @@ +$(enclaveName).so +{ + global: + g_global_data_sim; + g_global_data; + $(enclaveName)_entry; + local: + *; +}; diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/templates/sgx/SGXEnclave/trusted/Enclave1_minimal.cpp b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/templates/sgx/SGXEnclave/trusted/Enclave1_minimal.cpp new file mode 100644 index 0000000000..79700c42b7 --- /dev/null +++ b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/templates/sgx/SGXEnclave/trusted/Enclave1_minimal.cpp @@ -0,0 +1,7 @@ +#include "$(enclaveName)_t.h" /* print_string */ + +int ecall_$(enclaveName)_sample() +{ + return 0; +} + diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/templates/sgx/SGXEnclave/trusted/Enclave1_minimal.edl b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/templates/sgx/SGXEnclave/trusted/Enclave1_minimal.edl new file mode 100644 index 0000000000..f332f81910 --- /dev/null +++ b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/templates/sgx/SGXEnclave/trusted/Enclave1_minimal.edl @@ -0,0 +1,10 @@ +/* $(enclaveName).edl - Top EDL file. */ + +enclave { + untrusted { + }; + + trusted { + public int ecall_$(enclaveName)_sample(); + }; +}; diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/templates/sgx/SGXEnclave/trusted/Enclave1_private.pem b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/templates/sgx/SGXEnclave/trusted/Enclave1_private.pem new file mode 100644 index 0000000000..529d07be35 --- /dev/null +++ b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/templates/sgx/SGXEnclave/trusted/Enclave1_private.pem @@ -0,0 +1,39 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIG4gIBAAKCAYEAroOogvsj/fZDZY8XFdkl6dJmky0lRvnWMmpeH41Bla6U1qLZ +AmZuyIF+mQC/cgojIsrBMzBxb1kKqzATF4+XwPwgKz7fmiddmHyYz2WDJfAjIveJ +ZjdMjM4+EytGlkkJ52T8V8ds0/L2qKexJ+NBLxkeQLfV8n1mIk7zX7jguwbCG1Pr +nEMdJ3Sew20vnje+RsngAzdPChoJpVsWi/K7cettX/tbnre1DL02GXc5qJoQYk7b +3zkmhz31TgFrd9VVtmUGyFXAysuSAb3EN+5VnHGr0xKkeg8utErea2FNtNIgua8H +ONfm9Eiyaav1SVKzPHlyqLtcdxH3I8Wg7yqMsaprZ1n5A1v/levxnL8+It02KseD +5HqV4rf/cImSlCt3lpRg8U5E1pyFQ2IVEC/XTDMiI3c+AR+w2jSRB3Bwn9zJtFlW +KHG3m1xGI4ck+Lci1JvWWLXQagQSPtZTsubxTQNx1gsgZhgv1JHVZMdbVlAbbRMC +1nSuJNl7KPAS/VfzAgEDAoIBgHRXxaynbVP5gkO0ug6Qw/E27wzIw4SmjsxG6Wpe +K7kfDeRskKxESdsA/xCrKkwGwhcx1iIgS5+Qscd1Yg+1D9X9asd/P7waPmWoZd+Z +AhlKwhdPsO7PiF3e1AzHhGQwsUTt/Y/aSI1MpHBvy2/s1h9mFCslOUxTmWw0oj/Q +ldIEgWeNR72CE2+jFIJIyml6ftnb6qzPiga8Bm48ubKh0kvySOqnkmnPzgh+JBD6 +JnBmtZbfPT97bwTT+N6rnPqOOApvfHPf15kWI8yDbprG1l4OCUaIUH1AszxLd826 +5IPM+8gINLRDP1MA6azECPjTyHXhtnSIBZCyWSVkc05vYmNXYUNiXWMajcxW9M02 +wKzFELO8NCEAkaTPxwo4SCyIjUxiK1LbQ9h8PSy4c1+gGP4LAMR8xqP4QKg6zdu9 +osUGG/xRe/uufgTBFkcjqBHtK5L5VI0jeNIUAgW/6iNbYXjBMJ0GfauLs+g1VsOm +WfdgXzsb9DYdMa0OXXHypmV4GwKBwQDUwQj8RKJ6c8cT4vcWCoJvJF00+RFL+P3i +Gx2DLERxRrDa8AVGfqaCjsR+3vLgG8V/py+z+dxZYSqeB80Qeo6PDITcRKoeAYh9 +xlT3LJOS+k1cJcEmlbbO2IjLkTmzSwa80fWexKu8/Xv6vv15gpqYl1ngYoqJM3pd +vzmTIOi7MKSZ0WmEQavrZj8zK4endE3v0eAEeQ55j1GImbypSf7Idh7wOXtjZ7WD +Dg6yWDrri+AP/L3gClMj8wsAxMV4ZR8CgcEA0fzDHkFa6raVOxWnObmRoDhAtE0a +cjUj976NM5yyfdf2MrKy4/RhdTiPZ6b08/lBC/+xRfV3xKVGzacm6QjqjZrUpgHC +0LKiZaMtccCJjLtPwQd0jGQEnKfMFaPsnhOc5y8qVkCzVOSthY5qhz0XNotHHFmJ +gffVgB0iqrMTvSL7IA2yqqpOqNRlhaYhNl8TiFP3gIeMtVa9rZy31JPgT2uJ+kfo +gV7sdTPEjPWZd7OshGxWpT6QfVDj/T9T7L6tAoHBAI3WBf2DFvxNL2KXT2QHAZ9t +k3imC4f7U+wSE6zILaDZyzygA4RUbwG0gv8/TJVn2P/Eynf76DuWHGlaiLWnCbSz +Az2DHBQBBaku409zDQym3j1ugMRjzzSQWzJg0SIyBH3hTmnYcn3+Uqcp/lEBvGW6 +O+rsXFt3pukqJmIV8HzLGGaLm62BHUeZf3dyWm+i3p/hQAL7Xvu04QW70xuGqdr5 +afV7p5eaeQIJXyGQJ0eylV/90+qxjMKiB1XYg6WYvwKBwQCL/ddpgOdHJGN8uRom +e7Zq0Csi3hGheMKlKbN3vcxT5U7MdyHtTZZOJbTvxKNNUNYH/8uD+PqDGNneb29G +BfGzvI3EASyLIcGZF3OhKwZd0jUrWk2y7Vhob91jwp2+t73vdMbkKyI4mHOuXvGv +fg95si9oO7EBT+Oqvhccd2J+F1IVXncccYnF4u5ZGWt5lLewN/pVr7MjjykeaHqN +t+rfnQam2psA6fL4zS2zTmZPzR2tnY8Y1GBTi0Ko1OKd1HMCgcAb5cB/7/AQlhP9 +yQa04PLH9ygQkKKptZp7dy5WcWRx0K/hAHRoi2aw1wZqfm7VBNu2SLcs90kCCCxp +6C5sfJi6b8NpNbIPC+sc9wsFr7pGo9SFzQ78UlcWYK2Gu2FxlMjonhka5hvo4zvg +WxlpXKEkaFt3gLd92m/dMqBrHfafH7VwOJY2zT3WIpjwuk0ZzmRg5p0pG/svVQEH +NZmwRwlopysbR69B/n1nefJ84UO50fLh5s5Zr3gBRwbWNZyzhXk= +-----END RSA PRIVATE KEY----- diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/templates/sgx/SGXEnclave/untrusted/sample.cpp b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/templates/sgx/SGXEnclave/untrusted/sample.cpp new file mode 100644 index 0000000000..58b28a8509 --- /dev/null +++ b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/templates/sgx/SGXEnclave/untrusted/sample.cpp @@ -0,0 +1,247 @@ +#include +#include + +#include +#include +#include +#include + +# define MAX_PATH FILENAME_MAX + + +#include +#include "sample.h" + +#include "$(enclaveName)_u.h" + + + +/* Global EID shared by multiple threads */ +sgx_enclave_id_t global_eid = 0; + +typedef struct _sgx_errlist_t { + sgx_status_t err; + const char *msg; + const char *sug; /* Suggestion */ +} sgx_errlist_t; + +/* Error code returned by sgx_create_enclave */ +static sgx_errlist_t sgx_errlist[] = { + { + SGX_ERROR_UNEXPECTED, + "Unexpected error occurred.", + NULL + }, + { + SGX_ERROR_INVALID_PARAMETER, + "Invalid parameter.", + NULL + }, + { + SGX_ERROR_OUT_OF_MEMORY, + "Out of memory.", + NULL + }, + { + SGX_ERROR_ENCLAVE_LOST, + "Power transition occurred.", + "Please refer to the sample \"PowerTransition\" for details." + }, + { + SGX_ERROR_INVALID_ENCLAVE, + "Invalid enclave image.", + NULL + }, + { + SGX_ERROR_INVALID_ENCLAVE_ID, + "Invalid enclave identification.", + NULL + }, + { + SGX_ERROR_INVALID_SIGNATURE, + "Invalid enclave signature.", + NULL + }, + { + SGX_ERROR_OUT_OF_EPC, + "Out of EPC memory.", + NULL + }, + { + SGX_ERROR_NO_DEVICE, + "Invalid SGX device.", + "Please make sure SGX module is enabled in the BIOS, and install SGX driver afterwards." + }, + { + SGX_ERROR_MEMORY_MAP_CONFLICT, + "Memory map conflicted.", + NULL + }, + { + SGX_ERROR_INVALID_METADATA, + "Invalid enclave metadata.", + NULL + }, + { + SGX_ERROR_DEVICE_BUSY, + "SGX device was busy.", + NULL + }, + { + SGX_ERROR_INVALID_VERSION, + "Enclave version was invalid.", + NULL + }, + { + SGX_ERROR_INVALID_ATTRIBUTE, + "Enclave was not authorized.", + NULL + }, + { + SGX_ERROR_ENCLAVE_FILE_ACCESS, + "Can't open enclave file.", + NULL + }, +}; + +/* Check error conditions for loading enclave */ +void print_error_message(sgx_status_t ret) +{ + size_t idx = 0; + size_t ttl = sizeof sgx_errlist/sizeof sgx_errlist[0]; + + for (idx = 0; idx < ttl; idx++) { + if(ret == sgx_errlist[idx].err) { + if(NULL != sgx_errlist[idx].sug) + printf("Info: %s\n", sgx_errlist[idx].sug); + printf("Error: %s\n", sgx_errlist[idx].msg); + break; + } + } + + if (idx == ttl) + printf("Error: Unexpected error occurred.\n"); +} + +/* Initialize the enclave: + * Step 1: retrive the launch token saved by last transaction + * Step 2: call sgx_create_enclave to initialize an enclave instance + * Step 3: save the launch token if it is updated + */ +int initialize_enclave(void) +{ + char token_path[MAX_PATH] = {'\0'}; + sgx_launch_token_t token = {0}; + sgx_status_t ret = SGX_ERROR_UNEXPECTED; + int updated = 0; + /* Step 1: retrive the launch token saved by last transaction */ + + /* try to get the token saved in $HOME */ + const char *home_dir = getpwuid(getuid())->pw_dir; + if (home_dir != NULL && + (strlen(home_dir)+strlen("/")+sizeof(TOKEN_FILENAME)+1) <= MAX_PATH) { + /* compose the token path */ + strncpy(token_path, home_dir, strlen(home_dir)); + strncat(token_path, "/", strlen("/")); + strncat(token_path, TOKEN_FILENAME, sizeof(TOKEN_FILENAME)+1); + } else { + /* if token path is too long or $HOME is NULL */ + strncpy(token_path, TOKEN_FILENAME, sizeof(TOKEN_FILENAME)); + } + + FILE *fp = fopen(token_path, "rb"); + if (fp == NULL && (fp = fopen(token_path, "wb")) == NULL) { + printf("Warning: Failed to create/open the launch token file \"%s\".\n", token_path); + } + printf("token_path: %s\n", token_path); + if (fp != NULL) { + /* read the token from saved file */ + size_t read_num = fread(token, 1, sizeof(sgx_launch_token_t), fp); + if (read_num != 0 && read_num != sizeof(sgx_launch_token_t)) { + /* if token is invalid, clear the buffer */ + memset(&token, 0x0, sizeof(sgx_launch_token_t)); + printf("Warning: Invalid launch token read from \"%s\".\n", token_path); + } + } + + /* Step 2: call sgx_create_enclave to initialize an enclave instance */ + /* Debug Support: set 2nd parameter to 1 */ + + ret = sgx_create_enclave($(ENCLAVENAME)_FILENAME, SGX_DEBUG_FLAG, &token, &updated, &global_eid, NULL); + + if (ret != SGX_SUCCESS) { + print_error_message(ret); + if (fp != NULL) fclose(fp); + + return -1; + } + + /* Step 3: save the launch token if it is updated */ + + if (updated == FALSE || fp == NULL) { + /* if the token is not updated, or file handler is invalid, do not perform saving */ + if (fp != NULL) fclose(fp); + return 0; + } + + /* reopen the file with write capablity */ + fp = freopen(token_path, "wb", fp); + if (fp == NULL) return 0; + size_t write_num = fwrite(token, 1, sizeof(sgx_launch_token_t), fp); + if (write_num != sizeof(sgx_launch_token_t)) + printf("Warning: Failed to save launch token to \"%s\".\n", token_path); + fclose(fp); + + return 0; +} + +/* OCall functions */ +void ocall_$(enclaveName)_sample(const char *str) +{ + /* Proxy/Bridge will check the length and null-terminate + * the input string to prevent buffer overflow. + */ + printf("%s", str); +} + + +/* Application entry */ +int SGX_CDECL main(int argc, char *argv[]) +{ + (void)(argc); + (void)(argv); + + /* Changing dir to where the executable is.*/ + char absolutePath [MAX_PATH]; + char *ptr = NULL; + + ptr = realpath(dirname(argv[0]),absolutePath); + + if( chdir(absolutePath) != 0) + abort(); + + /* Initialize the enclave */ + if(initialize_enclave() < 0){ + + return -1; + } + + sgx_status_t ret = SGX_ERROR_UNEXPECTED; + int ecall_return = 0; + + ret = ecall_$(enclaveName)_sample(global_eid, &ecall_return); + if (ret != SGX_SUCCESS) + abort(); + + if (ecall_return == 0) { + printf("Application ran with success\n"); + } + else + { + printf("Application failed %d \n", ecall_return); + } + + sgx_destroy_enclave(global_eid); + + return ecall_return; +} diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/templates/sgx/SGXEnclave/untrusted/sample.h b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/templates/sgx/SGXEnclave/untrusted/sample.h new file mode 100644 index 0000000000..a0fb5e780e --- /dev/null +++ b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/templates/sgx/SGXEnclave/untrusted/sample.h @@ -0,0 +1,34 @@ +#ifndef _APP_H_ +#define _APP_H_ + +#include +#include +#include +#include + +#include "sgx_error.h" /* sgx_status_t */ +#include "sgx_eid.h" /* sgx_enclave_id_t */ + +#ifndef TRUE +# define TRUE 1 +#endif + +#ifndef FALSE +# define FALSE 0 +#endif + + +# define TOKEN_FILENAME "enclave.token" +# define $(ENCLAVENAME)_FILENAME "$(enclaveName).signed.so" + +extern sgx_enclave_id_t global_eid; /* global enclave id */ + +#if defined(__cplusplus) +extern "C" { +#endif + +#if defined(__cplusplus) +} +#endif + +#endif /* !_APP_H_ */ diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/templates/sgx/SGXNature/Makefile b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/templates/sgx/SGXNature/Makefile new file mode 100644 index 0000000000..5a67151653 --- /dev/null +++ b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/templates/sgx/SGXNature/Makefile @@ -0,0 +1,17 @@ +ALL_UNTRUSTED_MK=$(shell find . -name '*sgx_u.mk') +ALL_TRUSTED_MK=$(shell find . -name '*sgx_t.mk') +ALL_STATIC_MK=$(shell find . -name '*sgx_t_static.mk') + + + +.PHONY: all clean run + + +all clean: + $(foreach U_MK, $(ALL_UNTRUSTED_MK), $(MAKE) -C $(shell dirname $(U_MK)) -f $(shell basename $(U_MK)) $@;) + $(foreach T_MK, $(ALL_TRUSTED_MK), $(MAKE) -C $(shell dirname $(T_MK)) -f $(shell basename $(T_MK)) $@;) + $(foreach U_MK, $(ALL_STATIC_MK), $(MAKE) -C $(shell dirname $(U_MK)) -f $(shell basename $(U_MK)) $@;) + +run: + $(foreach U_MK, $(ALL_UNTRUSTED_MK), $(MAKE) -C $(shell dirname $(U_MK)) -f $(shell basename $(U_MK)) $@;) + diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/templates/sgx/SGXTrustedStaticLibrary/makefiles/c++/sgx_t_static.mk b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/templates/sgx/SGXTrustedStaticLibrary/makefiles/c++/sgx_t_static.mk new file mode 100644 index 0000000000..62ff91ff93 --- /dev/null +++ b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/templates/sgx/SGXTrustedStaticLibrary/makefiles/c++/sgx_t_static.mk @@ -0,0 +1,105 @@ +######## SGX SDK Settings ######## +SGX_SDK ?= $(SdkPathFromPlugin) +SGX_MODE ?= SIM +SGX_ARCH ?= x64 + +ifeq ($(shell getconf LONG_BIT), 32) + SGX_ARCH := x86 +else ifeq ($(findstring -m32, $(CXXFLAGS)), -m32) + SGX_ARCH := x86 +endif + +ifeq ($(SGX_ARCH), x86) + SGX_COMMON_CFLAGS := -m32 + SGX_LIBRARY_PATH := $(SGX_SDK)/lib + SGX_ENCLAVE_SIGNER := $(SGX_SDK)/bin/x86/sgx_sign + SGX_EDGER8R := $(SGX_SDK)/bin/x86/sgx_edger8r +else + SGX_COMMON_CFLAGS := -m64 + SGX_LIBRARY_PATH := $(SGX_SDK)/lib64 + SGX_ENCLAVE_SIGNER := $(SGX_SDK)/bin/x64/sgx_sign + SGX_EDGER8R := $(SGX_SDK)/bin/x64/sgx_edger8r +endif + +ifeq ($(SGX_DEBUG), 1) +ifeq ($(SGX_PRERELEASE), 1) +$(error Cannot set SGX_DEBUG and SGX_PRERELEASE at the same time!!) +endif +endif + +ifeq ($(SGX_DEBUG), 1) + SGX_COMMON_CFLAGS += -O0 -g +else + SGX_COMMON_CFLAGS += -O2 +endif + +ifneq ($(SGX_MODE), HW) + Trts_Library_Name := sgx_trts_sim + Service_Library_Name := sgx_tservice_sim +else + Trts_Library_Name := sgx_trts + Service_Library_Name := sgx_tservice +endif + +Crypto_Library_Name := sgx_tcrypto + +$(EnclaveName)_Cpp_Files := static_trusted/$(enclaveName).cpp +$(EnclaveName)_C_Files := +$(EnclaveName)_Include_Paths := -IInclude -I$(EnclaveName) -I$(SGX_SDK)/include -I$(SGX_SDK)/include/tlibc -I$(SGX_SDK)/include/stlport + +Flags_Just_For_C := -Wno-implicit-function-declaration -std=c11 +Common_C_Cpp_Flags := $(SGX_COMMON_CFLAGS) -nostdinc -fvisibility=hidden -fpie -fstack-protector $($(EnclaveName)_Include_Paths) -fno-builtin-printf -I. +$(EnclaveName)_C_Flags := $(Flags_Just_For_C) $(Common_C_Cpp_Flags) +$(EnclaveName)_Cpp_Flags := $(Common_C_Cpp_Flags) -std=c++11 -nostdinc++ -fno-builtin-printf -I. + +$(EnclaveName)_Cpp_Flags := $($(EnclaveName)_Cpp_Flags) -fno-builtin-printf + +$(EnclaveName)_Link_Flags := $(SGX_COMMON_CFLAGS) -Wl,--no-undefined -nostdlib -nodefaultlibs -nostartfiles -L$(SGX_LIBRARY_PATH) \ + -Wl,--whole-archive -l$(Trts_Library_Name) -Wl,--no-whole-archive \ + -Wl,--start-group -lsgx_tstdc -lsgx_tstdcxx -l$(Crypto_Library_Name) -l$(Service_Library_Name) -Wl,--end-group \ + -Wl,-Bstatic -Wl,-Bsymbolic -Wl,--no-undefined \ + -Wl,-pie,-eenclave_entry -Wl,--export-dynamic \ + -Wl,--defsym,__ImageBase=0 \ + -Wl,--version-script=trusted/$(enclaveName).lds + + +$(EnclaveName)_Cpp_Objects := $($(EnclaveName)_Cpp_Files:.cpp=.o) +$(EnclaveName)_C_Objects := $($(EnclaveName)_C_Files:.c=.o) + +ifeq ($(SGX_MODE), HW) +ifneq ($(SGX_DEBUG), 1) +ifneq ($(SGX_PRERELEASE), 1) +Build_Mode = HW_RELEASE +endif +endif +endif + + +.PHONY: all run + +all: lib$(enclaveName).sgx.static.lib.a + +######## $(enclaveName) Objects ######## + +static_trusted/$(enclaveName)_t.h: $(SGX_EDGER8R) ./static_trusted/$(enclaveName).edl + @cd ./static_trusted && $(SGX_EDGER8R) --header-only --trusted ../static_trusted/$(enclaveName).edl --search-path ../static_trusted --search-path $(SGX_SDK)/include + @echo "GEN => $@" + +static_trusted/$(enclaveName)_t.o: ./trusted/$(enclaveName)_t.c + @$(CC) $($(EnclaveName)_C_Flags) -c $< -o $@ + @echo "CC <= $<" + +static_trusted/%.o: static_trusted/%.cpp + @$(CXX) $($(EnclaveName)_Include_Paths) $($(EnclaveName)_Cpp_Flags) -c $< -o $@ + @echo "CXX <= $<" + +static_trusted/%.o: static_trusted/%.c + @$(CC) $($(EnclaveName)_C_Flags) -c $< -o $@ + @echo "CC <= $<" + +lib$(enclaveName).sgx.static.lib.a: static_trusted/$(enclaveName)_t.h $($(EnclaveName)_Cpp_Objects) $($(EnclaveName)_C_Objects) + ar rcs lib$(enclaveName).sgx.static.lib.a $($(EnclaveName)_Cpp_Objects) $($(EnclaveName)_C_Objects) + @echo "LINK => $@" + +clean: + @rm -f $(enclaveName).* static_trusted/$(enclaveName)_t.* $($(EnclaveName)_Cpp_Objects) $($(EnclaveName)_C_Objects) diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/templates/sgx/SGXTrustedStaticLibrary/makefiles/c++/sgx_u.without_app.mk b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/templates/sgx/SGXTrustedStaticLibrary/makefiles/c++/sgx_u.without_app.mk new file mode 100644 index 0000000000..c0d0c6778a --- /dev/null +++ b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/templates/sgx/SGXTrustedStaticLibrary/makefiles/c++/sgx_u.without_app.mk @@ -0,0 +1,71 @@ +######## SGX SDK Settings ######## +SGX_SDK ?= $(SdkPathFromPlugin) +SGX_MODE ?= SIM +SGX_ARCH ?= x64 +UNTRUSTED_DIR=untrusted + +ifeq ($(shell getconf LONG_BIT), 32) + SGX_ARCH := x86 +else ifeq ($(findstring -m32, $(CXXFLAGS)), -m32) + SGX_ARCH := x86 +endif + +ifeq ($(SGX_ARCH), x86) + SGX_COMMON_CFLAGS := -m32 + SGX_EDGER8R := $(SGX_SDK)/bin/x86/sgx_edger8r +else + SGX_COMMON_CFLAGS := -m64 + SGX_EDGER8R := $(SGX_SDK)/bin/x64/sgx_edger8r +endif + +ifeq ($(SGX_DEBUG), 1) +ifeq ($(SGX_PRERELEASE), 1) +$(error Cannot set SGX_DEBUG and SGX_PRERELEASE at the same time!!) +endif +endif + +ifeq ($(SGX_DEBUG), 1) + SGX_COMMON_CFLAGS += -O0 -g +else + SGX_COMMON_CFLAGS += -O2 +endif + +######## App Settings ######## + +App_Include_Paths := -IInclude -I$(UNTRUSTED_DIR) -I$(SGX_SDK)/include + +App_C_Flags := $(SGX_COMMON_CFLAGS) -fPIC -Wno-attributes $(App_Include_Paths) + +# Three configuration modes - Debug, prerelease, release +# Debug - Macro DEBUG enabled. +# Prerelease - Macro NDEBUG and EDEBUG enabled. +# Release - Macro NDEBUG enabled. +ifeq ($(SGX_DEBUG), 1) + App_C_Flags += -DDEBUG -UNDEBUG -UEDEBUG +else ifeq ($(SGX_PRERELEASE), 1) + App_C_Flags += -DNDEBUG -DEDEBUG -UDEBUG +else + App_C_Flags += -DNDEBUG -UEDEBUG -UDEBUG +endif + +App_Cpp_Flags := $(App_C_Flags) -std=c++11 + +.PHONY: all run + +all: $(UNTRUSTED_DIR)/$(enclaveName)_u.o + +######## App Objects ######## + +$(UNTRUSTED_DIR)/$(enclaveName)_u.c: $(SGX_EDGER8R) static_trusted/$(enclaveName).edl + @mkdir -p $(UNTRUSTED_DIR) + @cd $(UNTRUSTED_DIR) && $(SGX_EDGER8R) --untrusted ../static_trusted/$(enclaveName).edl --search-path ../static_trusted --search-path $(SGX_SDK)/include + @echo "GEN => $@" + +$(UNTRUSTED_DIR)/$(enclaveName)_u.o: $(UNTRUSTED_DIR)/$(enclaveName)_u.c + @$(CC) $(App_C_Flags) -c $< -o $@ + @echo "CC <= $<" + +.PHONY: clean + +clean: + @rm -f $(UNTRUSTED_DIR)/$(enclaveName)_u.* diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/templates/sgx/SGXTrustedStaticLibrary/makefiles/c/sgx_t_static.mk b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/templates/sgx/SGXTrustedStaticLibrary/makefiles/c/sgx_t_static.mk new file mode 100644 index 0000000000..e3dbd8f7f5 --- /dev/null +++ b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/templates/sgx/SGXTrustedStaticLibrary/makefiles/c/sgx_t_static.mk @@ -0,0 +1,95 @@ +######## SGX SDK Settings ######## +SGX_SDK ?= $(SdkPathFromPlugin) +SGX_MODE ?= SIM +SGX_ARCH ?= x64 + +ifeq ($(shell getconf LONG_BIT), 32) + SGX_ARCH := x86 +else ifeq ($(findstring -m32, $(CXXFLAGS)), -m32) + SGX_ARCH := x86 +endif + +ifeq ($(SGX_ARCH), x86) + SGX_COMMON_CFLAGS := -m32 + SGX_LIBRARY_PATH := $(SGX_SDK)/lib + SGX_ENCLAVE_SIGNER := $(SGX_SDK)/bin/x86/sgx_sign + SGX_EDGER8R := $(SGX_SDK)/bin/x86/sgx_edger8r +else + SGX_COMMON_CFLAGS := -m64 + SGX_LIBRARY_PATH := $(SGX_SDK)/lib64 + SGX_ENCLAVE_SIGNER := $(SGX_SDK)/bin/x64/sgx_sign + SGX_EDGER8R := $(SGX_SDK)/bin/x64/sgx_edger8r +endif + +ifeq ($(SGX_DEBUG), 1) +ifeq ($(SGX_PRERELEASE), 1) +$(error Cannot set SGX_DEBUG and SGX_PRERELEASE at the same time!!) +endif +endif + +ifeq ($(SGX_DEBUG), 1) + SGX_COMMON_CFLAGS += -O0 -g +else + SGX_COMMON_CFLAGS += -O2 +endif + +ifneq ($(SGX_MODE), HW) + Trts_Library_Name := sgx_trts_sim + Service_Library_Name := sgx_tservice_sim +else + Trts_Library_Name := sgx_trts + Service_Library_Name := sgx_tservice +endif + +Crypto_Library_Name := sgx_tcrypto + +$(EnclaveName)_C_Files := static_trusted/$(enclaveName).c +$(EnclaveName)_Include_Paths := -IInclude -I$(EnclaveName) -I$(SGX_SDK)/include -I$(SGX_SDK)/include/tlibc -I$(SGX_SDK)/include/stlport + +Flags_Just_For_C := -Wno-implicit-function-declaration -std=c11 +Common_C_Cpp_Flags := $(SGX_COMMON_CFLAGS) -nostdinc -fvisibility=hidden -fpie -fstack-protector $($(EnclaveName)_Include_Paths) -fno-builtin-printf -I. +$(EnclaveName)_C_Flags := $(Flags_Just_For_C) $(Common_C_Cpp_Flags) + +$(EnclaveName)_Link_Flags := $(SGX_COMMON_CFLAGS) -Wl,--no-undefined -nostdlib -nodefaultlibs -nostartfiles -L$(SGX_LIBRARY_PATH) \ + -Wl,--whole-archive -l$(Trts_Library_Name) -Wl,--no-whole-archive \ + -Wl,--start-group -lsgx_tstdc -lsgx_tstdcxx -l$(Crypto_Library_Name) -l$(Service_Library_Name) -Wl,--end-group \ + -Wl,-Bstatic -Wl,-Bsymbolic -Wl,--no-undefined \ + -Wl,-pie,-eenclave_entry -Wl,--export-dynamic \ + -Wl,--defsym,__ImageBase=0 \ + -Wl,--version-script=trusted/$(enclaveName).lds + +$(EnclaveName)_C_Objects := $($(EnclaveName)_C_Files:.c=.o) + +ifeq ($(SGX_MODE), HW) +ifneq ($(SGX_DEBUG), 1) +ifneq ($(SGX_PRERELEASE), 1) +Build_Mode = HW_RELEASE +endif +endif +endif + + +.PHONY: all run + +all: lib$(enclaveName).sgx.static.lib.a + +######## $(enclaveName) Objects ######## + +static_trusted/$(enclaveName)_t.h: $(SGX_EDGER8R) ./static_trusted/$(enclaveName).edl + @cd ./static_trusted && $(SGX_EDGER8R) --header-only --trusted ../static_trusted/$(enclaveName).edl --search-path ../static_trusted --search-path $(SGX_SDK)/include + @echo "GEN => $@" + +static_trusted/$(enclaveName)_t.o: ./trusted/$(enclaveName)_t.c + @$(CC) $($(EnclaveName)_C_Flags) -c $< -o $@ + @echo "CC <= $<" + +static_trusted/%.o: static_trusted/%.c + @$(CC) $($(EnclaveName)_C_Flags) -c $< -o $@ + @echo "CC <= $<" + +lib$(enclaveName).sgx.static.lib.a: static_trusted/$(enclaveName)_t.h $($(EnclaveName)_C_Objects) + ar rcs lib$(enclaveName).sgx.static.lib.a $($(EnclaveName)_Cpp_Objects) $($(EnclaveName)_C_Objects) + @echo "LINK => $@" + +clean: + @rm -f $(enclaveName).* static_trusted/$(enclaveName)_t.* $($(EnclaveName)_C_Objects) diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/templates/sgx/SGXTrustedStaticLibrary/makefiles/c/sgx_u.without_app.mk b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/templates/sgx/SGXTrustedStaticLibrary/makefiles/c/sgx_u.without_app.mk new file mode 100644 index 0000000000..e8a5508339 --- /dev/null +++ b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/templates/sgx/SGXTrustedStaticLibrary/makefiles/c/sgx_u.without_app.mk @@ -0,0 +1,70 @@ +######## SGX SDK Settings ######## +SGX_SDK ?= $(SdkPathFromPlugin) +SGX_MODE ?= SIM +SGX_ARCH ?= x64 +UNTRUSTED_DIR=untrusted + +ifeq ($(shell getconf LONG_BIT), 32) + SGX_ARCH := x86 +else ifeq ($(findstring -m32, $(CXXFLAGS)), -m32) + SGX_ARCH := x86 +endif + +ifeq ($(SGX_ARCH), x86) + SGX_COMMON_CFLAGS := -m32 + SGX_EDGER8R := $(SGX_SDK)/bin/x86/sgx_edger8r +else + SGX_COMMON_CFLAGS := -m64 + SGX_EDGER8R := $(SGX_SDK)/bin/x64/sgx_edger8r +endif + +ifeq ($(SGX_DEBUG), 1) +ifeq ($(SGX_PRERELEASE), 1) +$(error Cannot set SGX_DEBUG and SGX_PRERELEASE at the same time!!) +endif +endif + +ifeq ($(SGX_DEBUG), 1) + SGX_COMMON_CFLAGS += -O0 -g +else + SGX_COMMON_CFLAGS += -O2 +endif + +######## App Settings ######## + +App_Include_Paths := -IInclude -I$(UNTRUSTED_DIR) -I$(SGX_SDK)/include + +App_C_Flags := $(SGX_COMMON_CFLAGS) -fPIC -Wno-attributes $(App_Include_Paths) + +# Three configuration modes - Debug, prerelease, release +# Debug - Macro DEBUG enabled. +# Prerelease - Macro NDEBUG and EDEBUG enabled. +# Release - Macro NDEBUG enabled. +ifeq ($(SGX_DEBUG), 1) + App_C_Flags += -DDEBUG -UNDEBUG -UEDEBUG +else ifeq ($(SGX_PRERELEASE), 1) + App_C_Flags += -DNDEBUG -DEDEBUG -UDEBUG +else + App_C_Flags += -DNDEBUG -UEDEBUG -UDEBUG +endif + + +.PHONY: all run + +all: $(UNTRUSTED_DIR)/$(enclaveName)_u.o + +######## App Objects ######## + +$(UNTRUSTED_DIR)/$(enclaveName)_u.c: $(SGX_EDGER8R) static_trusted/$(enclaveName).edl + @mkdir -p $(UNTRUSTED_DIR) + @cd $(UNTRUSTED_DIR) && $(SGX_EDGER8R) --untrusted ../static_trusted/$(enclaveName).edl --search-path ../static_trusted --search-path $(SGX_SDK)/include + @echo "GEN => $@" + +$(UNTRUSTED_DIR)/$(enclaveName)_u.o: $(UNTRUSTED_DIR)/$(enclaveName)_u.c + @$(CC) $(App_C_Flags) -c $< -o $@ + @echo "CC <= $<" + +.PHONY: clean + +clean: + @rm -f $(UNTRUSTED_DIR)/$(enclaveName)_u.* diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/templates/sgx/SGXTrustedStaticLibrary/makefiles/common/Makefile b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/templates/sgx/SGXTrustedStaticLibrary/makefiles/common/Makefile new file mode 100644 index 0000000000..3defedc4c8 --- /dev/null +++ b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/templates/sgx/SGXTrustedStaticLibrary/makefiles/common/Makefile @@ -0,0 +1,8 @@ +all: + $(MAKE) -f sgx_u.mk all + $(MAKE) -f sgx_t.mk all + +clean: + $(MAKE) -f sgx_u.mk clean + $(MAKE) -f sgx_t.mk clean + diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/templates/sgx/SGXTrustedStaticLibrary/makefiles/common/Makefile.without_app b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/templates/sgx/SGXTrustedStaticLibrary/makefiles/common/Makefile.without_app new file mode 100644 index 0000000000..28aa5c8f1e --- /dev/null +++ b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/templates/sgx/SGXTrustedStaticLibrary/makefiles/common/Makefile.without_app @@ -0,0 +1,8 @@ +all: + $(MAKE) -f sgx_u.mk all + $(MAKE) -f sgx_t_static.mk all + +clean: + $(MAKE) -f sgx_u.mk clean + $(MAKE) -f sgx_t.mk clean + diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/templates/sgx/SGXTrustedStaticLibrary/static_trusted/Enclave2_minimal.cpp b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/templates/sgx/SGXTrustedStaticLibrary/static_trusted/Enclave2_minimal.cpp new file mode 100644 index 0000000000..79700c42b7 --- /dev/null +++ b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/templates/sgx/SGXTrustedStaticLibrary/static_trusted/Enclave2_minimal.cpp @@ -0,0 +1,7 @@ +#include "$(enclaveName)_t.h" /* print_string */ + +int ecall_$(enclaveName)_sample() +{ + return 0; +} + diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/templates/sgx/SGXTrustedStaticLibrary/static_trusted/Enclave2_minimal.edl b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/templates/sgx/SGXTrustedStaticLibrary/static_trusted/Enclave2_minimal.edl new file mode 100644 index 0000000000..7af749e545 --- /dev/null +++ b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/templates/sgx/SGXTrustedStaticLibrary/static_trusted/Enclave2_minimal.edl @@ -0,0 +1,11 @@ +/* $(enclaveName).edl - Top EDL file. */ + +enclave { + + untrusted { + }; + + trusted { + public int ecall_$(enclaveName)_sample(); + }; +}; diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/templates/sgx/SGXUntrustedModule/makefiles/c++/sgx_u.without_app.mk b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/templates/sgx/SGXUntrustedModule/makefiles/c++/sgx_u.without_app.mk new file mode 100644 index 0000000000..0db9ce0ab5 --- /dev/null +++ b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/templates/sgx/SGXUntrustedModule/makefiles/c++/sgx_u.without_app.mk @@ -0,0 +1,75 @@ +######## SGX SDK Settings ######## +SGX_SDK ?= $(SdkPathFromPlugin) +SGX_MODE ?= SIM +SGX_ARCH ?= x64 +UNTRUSTED_DIR=untrusted +SGX_EDL_FILE := $(baseName).edl + +ifeq ($(shell getconf LONG_BIT), 32) + SGX_ARCH := x86 +else ifeq ($(findstring -m32, $(CXXFLAGS)), -m32) + SGX_ARCH := x86 +endif + +ifeq ($(SGX_ARCH), x86) + SGX_COMMON_CFLAGS := -m32 + SGX_EDGER8R := $(SGX_SDK)/bin/x86/sgx_edger8r +else + SGX_COMMON_CFLAGS := -m64 + SGX_EDGER8R := $(SGX_SDK)/bin/x64/sgx_edger8r +endif + +ifeq ($(SGX_DEBUG), 1) +ifeq ($(SGX_PRERELEASE), 1) +$(error Cannot set SGX_DEBUG and SGX_PRERELEASE at the same time!!) +endif +endif + +ifeq ($(SGX_DEBUG), 1) + SGX_COMMON_CFLAGS += -O0 -g +else + SGX_COMMON_CFLAGS += -O2 +endif + +######## App Settings ######## + +App_Include_Paths := -IInclude -I$(UNTRUSTED_DIR) -I$(SGX_SDK)/include + +App_C_Flags := $(SGX_COMMON_CFLAGS) -fPIC -Wno-attributes $(App_Include_Paths) + +# Three configuration modes - Debug, prerelease, release +# Debug - Macro DEBUG enabled. +# Prerelease - Macro NDEBUG and EDEBUG enabled. +# Release - Macro NDEBUG enabled. +ifeq ($(SGX_DEBUG), 1) + App_C_Flags += -DDEBUG -UNDEBUG -UEDEBUG +else ifeq ($(SGX_PRERELEASE), 1) + App_C_Flags += -DNDEBUG -DEDEBUG -UDEBUG +else + App_C_Flags += -DNDEBUG -UEDEBUG -UDEBUG +endif + +App_Cpp_Flags := $(App_C_Flags) -std=c++11 + +.PHONY: all run + +all: $(UNTRUSTED_DIR)/$(baseName)_u.o $(UNTRUSTED_DIR)/$(baseName).o + +######## App Objects ######## + +$(UNTRUSTED_DIR)/$(baseName)_u.c: $(SGX_EDGER8R) $(SGX_EDL_FILE) + @mkdir -p $(UNTRUSTED_DIR) && cd $(UNTRUSTED_DIR) && $(SGX_EDGER8R) --untrusted $(SGX_EDL_FILE) --search-path .. --search-path $(SGX_SDK)/include + @echo "GEN => $@" + +$(UNTRUSTED_DIR)/$(baseName)_u.o: $(UNTRUSTED_DIR)/$(baseName)_u.c + @$(CC) $(App_C_Flags) -c $< -o $@ + @echo "CC <= $<" + +$(UNTRUSTED_DIR)/$(baseName).o: $(UNTRUSTED_DIR)/$(baseName).cpp + @$(CC) $(App_Cpp_Flags) -c $< -o $@ + @echo "CC <= $<" + +.PHONY: clean + +clean: + @rm -f $(UNTRUSTED_DIR)/$(baseName)_u.* $(UNTRUSTED_DIR)/$(baseName).o diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/templates/sgx/SGXUntrustedModule/makefiles/c/sgx_u.without_app.mk b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/templates/sgx/SGXUntrustedModule/makefiles/c/sgx_u.without_app.mk new file mode 100644 index 0000000000..cce0dfec11 --- /dev/null +++ b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/templates/sgx/SGXUntrustedModule/makefiles/c/sgx_u.without_app.mk @@ -0,0 +1,75 @@ +######## SGX SDK Settings ######## +SGX_SDK ?= $(SdkPathFromPlugin) +SGX_MODE ?= SIM +SGX_ARCH ?= x64 +UNTRUSTED_DIR=untrusted +SGX_EDL_FILE := $(baseName).edl + +ifeq ($(shell getconf LONG_BIT), 32) + SGX_ARCH := x86 +else ifeq ($(findstring -m32, $(CXXFLAGS)), -m32) + SGX_ARCH := x86 +endif + +ifeq ($(SGX_ARCH), x86) + SGX_COMMON_CFLAGS := -m32 + SGX_EDGER8R := $(SGX_SDK)/bin/x86/sgx_edger8r +else + SGX_COMMON_CFLAGS := -m64 + SGX_EDGER8R := $(SGX_SDK)/bin/x64/sgx_edger8r +endif + +ifeq ($(SGX_DEBUG), 1) +ifeq ($(SGX_PRERELEASE), 1) +$(error Cannot set SGX_DEBUG and SGX_PRERELEASE at the same time!!) +endif +endif + +ifeq ($(SGX_DEBUG), 1) + SGX_COMMON_CFLAGS += -O0 -g +else + SGX_COMMON_CFLAGS += -O2 +endif + +######## App Settings ######## + +App_Include_Paths := -IInclude -I$(UNTRUSTED_DIR) -I$(SGX_SDK)/include + +App_C_Flags := $(SGX_COMMON_CFLAGS) -fPIC -Wno-attributes $(App_Include_Paths) + +# Three configuration modes - Debug, prerelease, release +# Debug - Macro DEBUG enabled. +# Prerelease - Macro NDEBUG and EDEBUG enabled. +# Release - Macro NDEBUG enabled. +ifeq ($(SGX_DEBUG), 1) + App_C_Flags += -DDEBUG -UNDEBUG -UEDEBUG +else ifeq ($(SGX_PRERELEASE), 1) + App_C_Flags += -DNDEBUG -DEDEBUG -UDEBUG +else + App_C_Flags += -DNDEBUG -UEDEBUG -UDEBUG +endif + +App_Cpp_Flags := $(App_C_Flags) -std=c++11 + +.PHONY: all run + +all: $(UNTRUSTED_DIR)/$(baseName)_u.o $(UNTRUSTED_DIR)/$(baseName).o + +######## App Objects ######## + +$(UNTRUSTED_DIR)/$(baseName)_u.c: $(SGX_EDGER8R) $(SGX_EDL_FILE) + @mkdir -p $(UNTRUSTED_DIR) && cd $(UNTRUSTED_DIR) && $(SGX_EDGER8R) --untrusted $(SGX_EDL_FILE) --search-path .. --search-path $(SGX_SDK)/include + @echo "GEN => $@" + +$(UNTRUSTED_DIR)/$(baseName)_u.o: $(UNTRUSTED_DIR)/$(baseName)_u.c + @$(CC) $(App_C_Flags) -c $< -o $@ + @echo "CC <= $<" + +$(UNTRUSTED_DIR)/$(baseName).o: $(UNTRUSTED_DIR)/$(baseName).c + @$(CC) $(App_C_Flags) -c $< -o $@ + @echo "CC <= $<" + +.PHONY: clean + +clean: + @rm -f $(UNTRUSTED_DIR)/$(baseName)_u.* $(UNTRUSTED_DIR)/$(baseName).o diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/templates/sgx/SGXUntrustedModule/makefiles/common/Makefile b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/templates/sgx/SGXUntrustedModule/makefiles/common/Makefile new file mode 100644 index 0000000000..af0747ec6d --- /dev/null +++ b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/templates/sgx/SGXUntrustedModule/makefiles/common/Makefile @@ -0,0 +1,6 @@ +all: + $(MAKE) -f sgx_u.mk all + +clean: + $(MAKE) -f sgx_u.mk clean + diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/templates/sgx/SGXUntrustedModule/untrusted/untrusted_module.cpp b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/templates/sgx/SGXUntrustedModule/untrusted/untrusted_module.cpp new file mode 100644 index 0000000000..f4d2acdc38 --- /dev/null +++ b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/plugins/com.intel.sgx/templates/sgx/SGXUntrustedModule/untrusted/untrusted_module.cpp @@ -0,0 +1 @@ +#include "$(baseName)_u.h" diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/sites/site.xml b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/sites/site.xml new file mode 100644 index 0000000000..3c3d422d7b --- /dev/null +++ b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/build_directory/sites/site.xml @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + This website hosts an evaluation version of the Eclipse Plug-in developed for Secure Guard Extensions Application development for Linux platforms. + + + + + + SGX Eclipse Plugin 1.0.1.qualifier + + diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/clean.sh b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/clean.sh new file mode 100755 index 0000000000..ba0f7bc78a --- /dev/null +++ b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/clean.sh @@ -0,0 +1,20 @@ +# clean input directories to make sure there's nothing left from previous run + +rm -rfv ./build_directory/features/com.intel.sgx.build.driver +rm -fv build_directory/*.properties +rm -fv build_directory/*.xml +rm -fv build_directory/plugins/com.intel.sgx/build.xml +rm -fv build_directory/plugins/com.intel.sgx.userguide/build.xml +rm -rfv build_directory/plugins/com.intel.sgx/bin +rm -rfv build_directory/plugins/com.intel.sgx.userguide/bin +rm -rfv build_directory/plugins/com.intel.sgx.source_1.0.0.* +rm -rfv build_directory/features/com.intel.sgx.source +rm -fv build_directory/features/com.intel.sgx.feature/build.xml +rm -fv build_directory/features/com.intel.sgx.feature/*.zip +rm -rfv build_directory/nestedJars +rm -rfv build_directory/updatesite/sgx-eclipse-plugin +find . -name "*.zip" ! -name "eclipse_mars.v4.5.1_x64.zip" | xargs rm -rfv +find . -name "javaCompiler*" | xargs rm -rfv +find . -name "@*" | xargs rm -rfv +find build_directory -maxdepth 1 -mindepth 1 | grep -v "features" | grep -v "plugins" | grep -v "sites" | grep -v "updatesite" | xargs rm -frv + diff --git a/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/readme.txt b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/readme.txt new file mode 100644 index 0000000000..1430d35772 --- /dev/null +++ b/sgx-jvm/linux-sgx/Linux_SGXEclipsePlugin/readme.txt @@ -0,0 +1,22 @@ +The eclipse plugin build from command line requires the following variables to be set. + +$ECLIPSE_HOME - Path to eclipse home. In order to build the plugin eclipse needs to be installed. +$RELEASE_ID - The release id for the plugin. The release id should be changed for each source codes updates. +$DELETE_CURRENT_ECLIPSE - Delete current eclipse or not. Generally this variable is set to false. + +The following plugins are pre-requisites to be installed in Eclipse before trying to build the plugin. + +1. Eclipse IDE for C/C++ Developers 4.5.1.20150917-1200 (tested_version) +2. Eclipse PDE Plug-in Developer Resources 3.11.1.v20150904-0345 (tested_version) + +run ./build.sh from command line under current directory. +Once the build script is run, the folder build_directory/updatesite/sgx-eclipse-plugin contains the update site. This is the path that needs to be provided to the eclipse while doing installation. + +If the sgx eclipse plugin is already installed to eclipse and to build and install a newer version, uninstall the old version and start eclipse with the -clean option. +Then try to build the new version of the plugin and install it in eclipse. + +http://wiki.eclipse.org/FAQ_How_do_I_remove_a_plug-in%3F + +The plugin has been tested with the following Eclipse ADT version + +Build: v22.3.0-887826 diff --git a/sgx-jvm/linux-sgx/Makefile b/sgx-jvm/linux-sgx/Makefile new file mode 100644 index 0000000000..9cd3ab3a08 --- /dev/null +++ b/sgx-jvm/linux-sgx/Makefile @@ -0,0 +1,58 @@ +# +# Copyright (C) 2011-2016 Intel Corporation. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# + +include buildenv.mk +.PHONY: all psw sdk clean rebuild sdk_install_pkg psw_install_pkg + +all: sdk psw + +psw: sdk + $(MAKE) -C psw/ USE_OPT_LIBS=$(USE_OPT_LIBS) + +sdk: + $(MAKE) -C sdk/ USE_OPT_LIBS=$(USE_OPT_LIBS) + +# Generate SE SDK Install package +sdk_install_pkg: sdk + ./linux/installer/bin/build-installpkg.sh sdk + +psw_install_pkg: psw + ./linux/installer/bin/build-installpkg.sh psw + +clean: + @$(MAKE) -C sdk/ clean + @$(MAKE) -C psw/ clean + @$(RM) -r $(ROOT_DIR)/build + @$(RM) -r linux/installer/bin/sgx_linux*.bin + +rebuild: + $(MAKE) clean + $(MAKE) all diff --git a/sgx-jvm/linux-sgx/README.md b/sgx-jvm/linux-sgx/README.md new file mode 100644 index 0000000000..efacc00610 --- /dev/null +++ b/sgx-jvm/linux-sgx/README.md @@ -0,0 +1,179 @@ +Intel(R) Software Guard Extensions for Linux\* OS +================================================ + +# linux-sgx + +Introduction +------------ +Intel(R) Software Guard Extensions (Intel(R) SGX) is an Intel technology for application developers seeking to protect select code and data from disclosure or modification. + +The Linux SGX software stack is comprised of the SGX driver, the SGX SDK, and the SGX Platform Software. The SGX SDK and SGX PSW are hosted in the [linux-sgx](https://github.com/01org/linux-sgx) project. + +The [linux-sgx-driver](https://github.com/01org/linux-sgx-driver) project hosts the out-of-tree driver for the Linux SGX software stack, which will be used until the driver upstreaming process is complete. + +License +------- +See License.txt for details. + +Contributing +------- +See CONTRIBUTING.md for details. + +Documentation +------------- +- [Intel(R) SGX for Linux\* OS][1] project home page on [01.org](https://01.org) +- [Intel(R) SGX Programming Reference][2] +[1]: https://01.org/intel-softwareguard-extensions +[2]: https://software.intel.com/sites/default/files/managed/48/88/329298-002.pdf + +Build and Install the Intel(R) SGX Driver +----------------------------------------- +Follow the instructions in the [linux-sgx-driver](https://github.com/01org/linux-sgx-driver) project to build and install the SGX driver. + +Build the Intel(R) SGX SDK and Intel(R) SGX PSW Package +------------------------------------------------------- +###Prerequisites: +- Ensure that you have the following required operating systems: + Ubuntu\* Desktop-14.04-LTS 64bits +- Use the following command to install the required tools to build Intel(R) SGX SDK: +``` + $ sudo apt-get install build-essential ocaml automake autoconf libtool +``` +- Use the following command to install additional required tools to build Intel(R) SGX PSW: +``` + $ sudo apt-get install libcurl4-openssl-dev protobuf-compiler protobuf-c-compiler libprotobuf-dev libprotobuf-c0-dev +``` +- Use the script ``download_prebuilt.sh`` inside source code package to download prebuilt binaries to prebuilt folder + You may need set https proxy for wget tool used by the script (such as ``export https_proxy=http://test-proxy:test-port``) +``` + $ ./download_prebuilt.sh +``` + +###Build the Intel(R) SGX SDK and Intel(R) SGX PSW +The following steps describe how to build the Intel SGX SDK and PSW. You can build the project according to your requirement. +- To build both Intel SGX SDK and PSW with default configuration, enter the following command: + You can find the tools and libraries generated in the `build/linux` directory. + **Note**: You can also go to the sdk folder and use the `make` command to build the Intel SGX SDK component only. However, the building of PSW component is dependent on the building result of Intel SGX SDK. +``` + $ make +``` + +- The default build uses precompiled optimized libraries which have been downloaded by the script ``./download_prebuilt.sh``. + You can also use the non-optimized source code version implementation instead by entering the following command: +``` + $ make USE_OPT_LIBS=0 +``` +- To build Intel SGX SDK and PSW with debug information, enter the following command: +``` + $ make DEBUG=1 +``` +- To clean the files generated by previous `make` command, enter the following command: +``` + $ make clean +``` + +- The build above uses prebuilt Intel(R) Architecture Enclaves(LE/PvE/QE/PCE) - the files ``psw/ae/data/prebuilt/libsgx_*.signed.so``, which have been signed by Intel in advance. + To build those binaries by yourself (without a signature), first you need to build both Intel SGX SDK and PSW with the default configuration. After that, you can build each Architecture Enclave by using the `make` command from the corresponding folder: +``` + $ cd psw/ae/le + $ make +``` + +###Build Intel(R) SGX SDK Installer +To build Intel(R) SGX SDK installer, enter the following command: +``` +$ make sdk_install_pkg +``` +You can find the generated Intel SGX SDK installer ``sgx_linux_x64_sdk_${version}.bin`` located under `linux/installer/bin/`, where `${version}` refers to the version number. +You could also make an SGX SDK installer with non-optimized source code for crypto library by +``` +$ make sdk_install_pkg USE_OPT_LIBS=0 +``` + +###Build Intel(R) SGX PSW Installer +To build Intel(R) SGX PSW installer, enter the following command: +``` +$ make psw_install_pkg +``` +You can find the generated Intel SGX PSW installer ``sgx_linux_x64_psw_${version}.bin`` located under `linux/installer/bin/`, where `${version}` refers to the version number. +You could also make an SGX PSW intaller with non-optimized source code for crypto library by +``` +$ make psw_install_pkg USE_OPT_LIBS=0 +``` +Install Intel(R) SGX SDK +------------------------ +###Prerequisites +- Ensure that you have the following required operating systems: + Ubuntu\* Desktop-14.04-LTS 64bits +- Use the following command to install the required tool to use Intel(R) SGX SDK: +``` + $ sudo apt-get install build-essential +``` + +###Install Intel(R) SGX SDK +To install Intel(R) SGX SDK, execute the installer with root privilege: +``` +$ cd linux/installer/bin +$ sudo ./sgx_linux_x64_sdk_${version}.bin +``` +###Test Intel(R) SGX SDK Package with the Sample Codes +- Copy the sample codes installed by Intel(R) SGX SDK package into your work folder, such as +``` + $ cp -r /opt/intel/sgxsdk/SampleCode ~ +``` +- Compile and run each sample codes in the simulation mode to make sure the package works well. +``` + $ cd SampleCode/LocalAttestation + $ make + $ ./app +``` + Use similar commands for other sample codes. + +###Compile and Run the Sample Codes in the Hardware Mode +If you use an SGX hardware enabled machine, you need to run the sample codes in the hardware mode. +Ensure that you install SGX driver and Intel(R) SGX PSW installer on the machine. +See the topic, Install Intel(R) SGX PSW, on how to install the PSW package. +- Copy the sample codes installed by the Intel(R) SGX SDK package into your work folder, such as +``` + $ cp -r /opt/intel/sgxsdk/SampleCode ~ +``` +- Compile and run each sample codes in the debug mode. +``` + $ cd SampleCode/LocalAttestation + $ make SGX_MODE=HW SGX_DEBUG=1 + $ ./app +``` + Use similar commands for other sample codes. + +Install Intel(R) SGX PSW +------------------------ +###Prerequisites +- Ensure that you have the following required operating systems: + Ubuntu\* Desktop-14.04-LTS 64bits +- Ensure that you have the following required hardware: + 6th Generation Intel(R) Core(TM) Processor (code named Skylake) +- Configure the system with the **SGX hardware enabled** option and install SGX driver in advance. + See the topic, Build and Install the Intel(R) SGX Driver, on how to install the SGX driver. +- Install the library using the following command: +``` + $ sudo apt-get install libcurl4-openssl-dev libprotobuf-dev libprotobuf-c0-dev +``` + +###Install Intel(R) SGX PSW +To install Intel(R) SGX PSW, execute the installer with root privilege: +``` +$ cd linux/installer/bin +$ sudo ./sgx_linux_x64_psw_${version}.bin +``` + +###Start or Stop aesmd Service +The Intel(R) SGX PSW installer installs an aesmd service in your machine which is running in a special linux account aesmd. +To stop the service: `$ sudo service aesmd stop` +To start the service: `$ sudo service aesmd start` +To restart the service: `$ sudo service aesmd restart` + +###Configure the Proxy for aesmd Service +The aesmd service uses HTTP protocol to initialize some services. +If proxy is required for HTTP protocol, you may need manually setup the proxy for aesmd service. +You should manually edit file `/etc/aesmd.conf` (refer the comment in the file) to set the proxy for aesmd service. +After you configure the proxy, you need to restart the service to enable the proxy. diff --git a/sgx-jvm/linux-sgx/SampleCode/LocalAttestation/.cproject b/sgx-jvm/linux-sgx/SampleCode/LocalAttestation/.cproject new file mode 100644 index 0000000000..be4d65295c --- /dev/null +++ b/sgx-jvm/linux-sgx/SampleCode/LocalAttestation/.cproject @@ -0,0 +1,219 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sgx-jvm/linux-sgx/SampleCode/LocalAttestation/.project b/sgx-jvm/linux-sgx/SampleCode/LocalAttestation/.project new file mode 100644 index 0000000000..df8b1a4d24 --- /dev/null +++ b/sgx-jvm/linux-sgx/SampleCode/LocalAttestation/.project @@ -0,0 +1,28 @@ + + + LocalAttestation + + + + + + org.eclipse.cdt.managedbuilder.core.genmakebuilder + clean,full,incremental, + + + + + org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder + full,incremental, + + + + + + org.eclipse.cdt.core.cnature + org.eclipse.cdt.managedbuilder.core.managedBuildNature + org.eclipse.cdt.managedbuilder.core.ScannerConfigNature + org.eclipse.cdt.core.ccnature + com.intel.sgx.sgxnature + + diff --git a/sgx-jvm/linux-sgx/SampleCode/LocalAttestation/App/App.cpp b/sgx-jvm/linux-sgx/SampleCode/LocalAttestation/App/App.cpp new file mode 100644 index 0000000000..92b5ec0b6c --- /dev/null +++ b/sgx-jvm/linux-sgx/SampleCode/LocalAttestation/App/App.cpp @@ -0,0 +1,450 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + + +// App.cpp : Defines the entry point for the console application. +#include +#include +#include "../Enclave1/Enclave1_u.h" +#include "../Enclave2/Enclave2_u.h" +#include "../Enclave3/Enclave3_u.h" +#include "sgx_eid.h" +#include "sgx_urts.h" +#define __STDC_FORMAT_MACROS +#include + + +#define UNUSED(val) (void)(val) +#define TCHAR char +#define _TCHAR char +#define _T(str) str +#define scanf_s scanf +#define _tmain main + +extern std::mapg_enclave_id_map; + + +sgx_enclave_id_t e1_enclave_id = 0; +sgx_enclave_id_t e2_enclave_id = 0; +sgx_enclave_id_t e3_enclave_id = 0; + +#define ENCLAVE1_PATH "libenclave1.so" +#define ENCLAVE2_PATH "libenclave2.so" +#define ENCLAVE3_PATH "libenclave3.so" + +void waitForKeyPress() +{ + char ch; + int temp; + printf("\n\nHit a key....\n"); + temp = scanf_s("%c", &ch); +} + +uint32_t load_enclaves() +{ + uint32_t enclave_temp_no; + int ret, launch_token_updated; + sgx_launch_token_t launch_token; + + enclave_temp_no = 0; + + ret = sgx_create_enclave(ENCLAVE1_PATH, SGX_DEBUG_FLAG, &launch_token, &launch_token_updated, &e1_enclave_id, NULL); + if (ret != SGX_SUCCESS) { + return ret; + } + + enclave_temp_no++; + g_enclave_id_map.insert(std::pair(e1_enclave_id, enclave_temp_no)); + + ret = sgx_create_enclave(ENCLAVE2_PATH, SGX_DEBUG_FLAG, &launch_token, &launch_token_updated, &e2_enclave_id, NULL); + if (ret != SGX_SUCCESS) { + return ret; + } + + enclave_temp_no++; + g_enclave_id_map.insert(std::pair(e2_enclave_id, enclave_temp_no)); + + ret = sgx_create_enclave(ENCLAVE3_PATH, SGX_DEBUG_FLAG, &launch_token, &launch_token_updated, &e3_enclave_id, NULL); + if (ret != SGX_SUCCESS) { + return ret; + } + + enclave_temp_no++; + g_enclave_id_map.insert(std::pair(e3_enclave_id, enclave_temp_no)); + + + + return SGX_SUCCESS; +} + +int _tmain(int argc, _TCHAR* argv[]) +{ + uint32_t ret_status; + sgx_status_t status; + + UNUSED(argc); + UNUSED(argv); + + if(load_enclaves() != SGX_SUCCESS) + { + printf("\nLoad Enclave Failure"); + } + + printf("\nAvaliable Enclaves"); + printf("\nEnclave1 - EnclaveID %" PRIx64, e1_enclave_id); + printf("\nEnclave2 - EnclaveID %" PRIx64, e2_enclave_id); + printf("\nEnclave3 - EnclaveID %" PRIx64, e3_enclave_id); + + do + { + //Test Create session between Enclave1(Source) and Enclave2(Destination) + status = Enclave1_test_create_session(e1_enclave_id, &ret_status, e1_enclave_id, e2_enclave_id); + if (status!=SGX_SUCCESS) + { + printf("Enclave1_test_create_session Ecall failed: Error code is %x", status); + break; + } + else + { + if(ret_status==0) + { + printf("\n\nSecure Channel Establishment between Source (E1) and Destination (E2) Enclaves successful !!!"); + } + else + { + printf("\nSession establishment and key exchange failure between Source (E1) and Destination (E2): Error code is %x", ret_status); + break; + } + } + + //Test Enclave to Enclave call between Enclave1(Source) and Enclave2(Destination) + status = Enclave1_test_enclave_to_enclave_call(e1_enclave_id, &ret_status, e1_enclave_id, e2_enclave_id); + if (status!=SGX_SUCCESS) + { + printf("Enclave1_test_enclave_to_enclave_call Ecall failed: Error code is %x", status); + break; + } + else + { + if(ret_status==0) + { + printf("\n\nEnclave to Enclave Call between Source (E1) and Destination (E2) Enclaves successful !!!"); + } + else + { + printf("\n\nEnclave to Enclave Call failure between Source (E1) and Destination (E2): Error code is %x", ret_status); + break; + } + } + //Test message exchange between Enclave1(Source) and Enclave2(Destination) + status = Enclave1_test_message_exchange(e1_enclave_id, &ret_status, e1_enclave_id, e2_enclave_id); + if (status!=SGX_SUCCESS) + { + printf("Enclave1_test_message_exchange Ecall failed: Error code is %x", status); + break; + } + else + { + if(ret_status==0) + { + printf("\n\nMessage Exchange between Source (E1) and Destination (E2) Enclaves successful !!!"); + } + else + { + printf("\n\nMessage Exchange failure between Source (E1) and Destination (E2): Error code is %x", ret_status); + break; + } + } + //Test Create session between Enclave1(Source) and Enclave3(Destination) + status = Enclave1_test_create_session(e1_enclave_id, &ret_status, e1_enclave_id, e3_enclave_id); + if (status!=SGX_SUCCESS) + { + printf("Enclave1_test_create_session Ecall failed: Error code is %x", status); + break; + } + else + { + if(ret_status==0) + { + printf("\n\nSecure Channel Establishment between Source (E1) and Destination (E3) Enclaves successful !!!"); + } + else + { + printf("\n\nSession establishment and key exchange failure between Source (E1) and Destination (E3): Error code is %x", ret_status); + break; + } + } + //Test Enclave to Enclave call between Enclave1(Source) and Enclave3(Destination) + status = Enclave1_test_enclave_to_enclave_call(e1_enclave_id, &ret_status, e1_enclave_id, e3_enclave_id); + if (status!=SGX_SUCCESS) + { + printf("Enclave1_test_enclave_to_enclave_call Ecall failed: Error code is %x", status); + break; + } + else + { + if(ret_status==0) + { + printf("\n\nEnclave to Enclave Call between Source (E1) and Destination (E3) Enclaves successful !!!"); + } + else + { + printf("\n\nEnclave to Enclave Call failure between Source (E1) and Destination (E3): Error code is %x", ret_status); + break; + } + } + //Test message exchange between Enclave1(Source) and Enclave3(Destination) + status = Enclave1_test_message_exchange(e1_enclave_id, &ret_status, e1_enclave_id, e3_enclave_id); + if (status!=SGX_SUCCESS) + { + printf("Enclave1_test_message_exchange Ecall failed: Error code is %x", status); + break; + } + else + { + if(ret_status==0) + { + printf("\n\nMessage Exchange between Source (E1) and Destination (E3) Enclaves successful !!!"); + } + else + { + printf("\n\nMessage Exchange failure between Source (E1) and Destination (E3): Error code is %x", ret_status); + break; + } + } + + //Test Create session between Enclave2(Source) and Enclave3(Destination) + status = Enclave2_test_create_session(e2_enclave_id, &ret_status, e2_enclave_id, e3_enclave_id); + if (status!=SGX_SUCCESS) + { + printf("Enclave2_test_create_session Ecall failed: Error code is %x", status); + break; + } + else + { + if(ret_status==0) + { + printf("\n\nSecure Channel Establishment between Source (E2) and Destination (E3) Enclaves successful !!!"); + } + else + { + printf("\n\nSession establishment and key exchange failure between Source (E2) and Destination (E3): Error code is %x", ret_status); + break; + } + } + //Test Enclave to Enclave call between Enclave2(Source) and Enclave3(Destination) + status = Enclave2_test_enclave_to_enclave_call(e2_enclave_id, &ret_status, e2_enclave_id, e3_enclave_id); + if (status!=SGX_SUCCESS) + { + printf("Enclave2_test_enclave_to_enclave_call Ecall failed: Error code is %x", status); + break; + } + else + { + if(ret_status==0) + { + printf("\n\nEnclave to Enclave Call between Source (E2) and Destination (E3) Enclaves successful !!!"); + } + else + { + printf("\n\nEnclave to Enclave Call failure between Source (E2) and Destination (E3): Error code is %x", ret_status); + break; + } + } + //Test message exchange between Enclave2(Source) and Enclave3(Destination) + status = Enclave2_test_message_exchange(e2_enclave_id, &ret_status, e2_enclave_id, e3_enclave_id); + if (status!=SGX_SUCCESS) + { + printf("Enclave2_test_message_exchange Ecall failed: Error code is %x", status); + break; + } + else + { + if(ret_status==0) + { + printf("\n\nMessage Exchange between Source (E2) and Destination (E3) Enclaves successful !!!"); + } + else + { + printf("\n\nMessage Exchange failure between Source (E2) and Destination (E3): Error code is %x", ret_status); + break; + } + } + + //Test Create session between Enclave3(Source) and Enclave1(Destination) + status = Enclave3_test_create_session(e3_enclave_id, &ret_status, e3_enclave_id, e1_enclave_id); + if (status!=SGX_SUCCESS) + { + printf("Enclave3_test_create_session Ecall failed: Error code is %x", status); + break; + } + else + { + if(ret_status==0) + { + printf("\n\nSecure Channel Establishment between Source (E3) and Destination (E1) Enclaves successful !!!"); + } + else + { + printf("\n\nSession establishment and key exchange failure between Source (E3) and Destination (E1): Error code is %x", ret_status); + break; + } + } + //Test Enclave to Enclave call between Enclave3(Source) and Enclave1(Destination) + status = Enclave3_test_enclave_to_enclave_call(e3_enclave_id, &ret_status, e3_enclave_id, e1_enclave_id); + if (status!=SGX_SUCCESS) + { + printf("Enclave3_test_enclave_to_enclave_call Ecall failed: Error code is %x", status); + break; + } + else + { + if(ret_status==0) + { + printf("\n\nEnclave to Enclave Call between Source (E3) and Destination (E1) Enclaves successful !!!"); + } + else + { + printf("\n\nEnclave to Enclave Call failure between Source (E3) and Destination (E1): Error code is %x", ret_status); + break; + } + } + //Test message exchange between Enclave3(Source) and Enclave1(Destination) + status = Enclave3_test_message_exchange(e3_enclave_id, &ret_status, e3_enclave_id, e1_enclave_id); + if (status!=SGX_SUCCESS) + { + printf("Enclave3_test_message_exchange Ecall failed: Error code is %x", status); + break; + } + else + { + if(ret_status==0) + { + printf("\n\nMessage Exchange between Source (E3) and Destination (E1) Enclaves successful !!!"); + } + else + { + printf("\n\nMessage Exchange failure between Source (E3) and Destination (E1): Error code is %x", ret_status); + break; + } + } + + + //Test Closing Session between Enclave1(Source) and Enclave2(Destination) + status = Enclave1_test_close_session(e1_enclave_id, &ret_status, e1_enclave_id, e2_enclave_id); + if (status!=SGX_SUCCESS) + { + printf("Enclave1_test_close_session Ecall failed: Error code is %x", status); + break; + } + else + { + if(ret_status==0) + { + printf("\n\nClose Session between Source (E1) and Destination (E2) Enclaves successful !!!"); + } + else + { + printf("\n\nClose session failure between Source (E1) and Destination (E2): Error code is %x", ret_status); + break; + } + } + //Test Closing Session between Enclave1(Source) and Enclave3(Destination) + status = Enclave1_test_close_session(e1_enclave_id, &ret_status, e1_enclave_id, e3_enclave_id); + if (status!=SGX_SUCCESS) + { + printf("Enclave1_test_close_session Ecall failed: Error code is %x", status); + break; + } + else + { + if(ret_status==0) + { + printf("\n\nClose Session between Source (E1) and Destination (E3) Enclaves successful !!!"); + } + else + { + printf("\n\nClose session failure between Source (E1) and Destination (E3): Error code is %x", ret_status); + break; + } + } + //Test Closing Session between Enclave2(Source) and Enclave3(Destination) + status = Enclave2_test_close_session(e2_enclave_id, &ret_status, e2_enclave_id, e3_enclave_id); + if (status!=SGX_SUCCESS) + { + printf("Enclave2_test_close_session Ecall failed: Error code is %x", status); + break; + } + else + { + if(ret_status==0) + { + printf("\n\nClose Session between Source (E2) and Destination (E3) Enclaves successful !!!"); + } + else + { + printf("\n\nClose session failure between Source (E2) and Destination (E3): Error code is %x", ret_status); + break; + } + } + //Test Closing Session between Enclave3(Source) and Enclave1(Destination) + status = Enclave3_test_close_session(e3_enclave_id, &ret_status, e3_enclave_id, e1_enclave_id); + if (status!=SGX_SUCCESS) + { + printf("Enclave3_test_close_session Ecall failed: Error code is %x", status); + break; + } + else + { + if(ret_status==0) + { + printf("\n\nClose Session between Source (E3) and Destination (E1) Enclaves successful !!!"); + } + else + { + printf("\n\nClose session failure between Source (E3) and Destination (E1): Error code is %x", ret_status); + break; + } + } + +#pragma warning (push) +#pragma warning (disable : 4127) + }while(0); +#pragma warning (pop) + + sgx_destroy_enclave(e1_enclave_id); + sgx_destroy_enclave(e2_enclave_id); + sgx_destroy_enclave(e3_enclave_id); + + waitForKeyPress(); + + return 0; +} diff --git a/sgx-jvm/linux-sgx/SampleCode/LocalAttestation/Enclave1/Enclave1.config.xml b/sgx-jvm/linux-sgx/SampleCode/LocalAttestation/Enclave1/Enclave1.config.xml new file mode 100644 index 0000000000..436860dd50 --- /dev/null +++ b/sgx-jvm/linux-sgx/SampleCode/LocalAttestation/Enclave1/Enclave1.config.xml @@ -0,0 +1,11 @@ + + 0 + 0 + 0x40000 + 0x100000 + 1 + 1 + 0 + 0 + 0xFFFFFFFF + diff --git a/sgx-jvm/linux-sgx/SampleCode/LocalAttestation/Enclave1/Enclave1.cpp b/sgx-jvm/linux-sgx/SampleCode/LocalAttestation/Enclave1/Enclave1.cpp new file mode 100644 index 0000000000..c662516d1d --- /dev/null +++ b/sgx-jvm/linux-sgx/SampleCode/LocalAttestation/Enclave1/Enclave1.cpp @@ -0,0 +1,373 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + + +// Enclave1.cpp : Defines the exported functions for the .so application +#include "sgx_eid.h" +#include "Enclave1_t.h" +#include "EnclaveMessageExchange.h" +#include "error_codes.h" +#include "Utility_E1.h" +#include "sgx_thread.h" +#include "sgx_dh.h" +#include + +#define UNUSED(val) (void)(val) + +std::mapg_src_session_info_map; + +static uint32_t e1_foo1_wrapper(ms_in_msg_exchange_t *ms, size_t param_lenth, char** resp_buffer, size_t* resp_length); + +//Function pointer table containing the list of functions that the enclave exposes +const struct { + size_t num_funcs; + const void* table[1]; +} func_table = { + 1, + { + (const void*)e1_foo1_wrapper, + } +}; + +//Makes use of the sample code function to establish a secure channel with the destination enclave (Test Vector) +uint32_t test_create_session(sgx_enclave_id_t src_enclave_id, + sgx_enclave_id_t dest_enclave_id) +{ + ATTESTATION_STATUS ke_status = SUCCESS; + dh_session_t dest_session_info; + + //Core reference code function for creating a session + ke_status = create_session(src_enclave_id, dest_enclave_id, &dest_session_info); + + //Insert the session information into the map under the corresponding destination enclave id + if(ke_status == SUCCESS) + { + g_src_session_info_map.insert(std::pair(dest_enclave_id, dest_session_info)); + } + memset(&dest_session_info, 0, sizeof(dh_session_t)); + return ke_status; +} + +//Makes use of the sample code function to do an enclave to enclave call (Test Vector) +uint32_t test_enclave_to_enclave_call(sgx_enclave_id_t src_enclave_id, + sgx_enclave_id_t dest_enclave_id) +{ + ATTESTATION_STATUS ke_status = SUCCESS; + uint32_t var1,var2; + uint32_t target_fn_id, msg_type; + char* marshalled_inp_buff; + size_t marshalled_inp_buff_len; + char* out_buff; + size_t out_buff_len; + dh_session_t *dest_session_info; + size_t max_out_buff_size; + char* retval; + + var1 = 0x4; + var2 = 0x5; + target_fn_id = 0; + msg_type = ENCLAVE_TO_ENCLAVE_CALL; + max_out_buff_size = 50; + + //Marshals the input parameters for calling function foo1 in Enclave2 into a input buffer + ke_status = marshal_input_parameters_e2_foo1(target_fn_id, msg_type, var1, var2, &marshalled_inp_buff, &marshalled_inp_buff_len); + if(ke_status != SUCCESS) + { + return ke_status; + } + + //Search the map for the session information associated with the destination enclave id of Enclave2 passed in + std::map::iterator it = g_src_session_info_map.find(dest_enclave_id); + if(it != g_src_session_info_map.end()) + { + dest_session_info = &it->second; + } + else + { + SAFE_FREE(marshalled_inp_buff); + return INVALID_SESSION; + } + + //Core Reference Code function + ke_status = send_request_receive_response(src_enclave_id, dest_enclave_id, dest_session_info, marshalled_inp_buff, + marshalled_inp_buff_len, max_out_buff_size, &out_buff, &out_buff_len); + + + if(ke_status != SUCCESS) + { + SAFE_FREE(marshalled_inp_buff); + SAFE_FREE(out_buff); + return ke_status; + } + + //Un-marshal the return value and output parameters from foo1 of Enclave 2 + ke_status = unmarshal_retval_and_output_parameters_e2_foo1(out_buff, &retval); + if(ke_status != SUCCESS) + { + SAFE_FREE(marshalled_inp_buff); + SAFE_FREE(out_buff); + return ke_status; + } + + SAFE_FREE(marshalled_inp_buff); + SAFE_FREE(out_buff); + SAFE_FREE(retval); + return SUCCESS; +} + +//Makes use of the sample code function to do a generic secret message exchange (Test Vector) +uint32_t test_message_exchange(sgx_enclave_id_t src_enclave_id, + sgx_enclave_id_t dest_enclave_id) +{ + ATTESTATION_STATUS ke_status = SUCCESS; + uint32_t target_fn_id, msg_type; + char* marshalled_inp_buff; + size_t marshalled_inp_buff_len; + char* out_buff; + size_t out_buff_len; + dh_session_t *dest_session_info; + size_t max_out_buff_size; + char* secret_response; + uint32_t secret_data; + + target_fn_id = 0; + msg_type = MESSAGE_EXCHANGE; + max_out_buff_size = 50; + secret_data = 0x12345678; //Secret Data here is shown only for purpose of demonstration. + + //Marshals the secret data into a buffer + ke_status = marshal_message_exchange_request(target_fn_id, msg_type, secret_data, &marshalled_inp_buff, &marshalled_inp_buff_len); + if(ke_status != SUCCESS) + { + return ke_status; + } + //Search the map for the session information associated with the destination enclave id passed in + std::map::iterator it = g_src_session_info_map.find(dest_enclave_id); + if(it != g_src_session_info_map.end()) + { + dest_session_info = &it->second; + } + else + { + SAFE_FREE(marshalled_inp_buff); + return INVALID_SESSION; + } + + //Core Reference Code function + ke_status = send_request_receive_response(src_enclave_id, dest_enclave_id, dest_session_info, marshalled_inp_buff, + marshalled_inp_buff_len, max_out_buff_size, &out_buff, &out_buff_len); + if(ke_status != SUCCESS) + { + SAFE_FREE(marshalled_inp_buff); + SAFE_FREE(out_buff); + return ke_status; + } + + //Un-marshal the secret response data + ke_status = umarshal_message_exchange_response(out_buff, &secret_response); + if(ke_status != SUCCESS) + { + SAFE_FREE(marshalled_inp_buff); + SAFE_FREE(out_buff); + return ke_status; + } + + SAFE_FREE(marshalled_inp_buff); + SAFE_FREE(out_buff); + SAFE_FREE(secret_response); + return SUCCESS; +} + + +//Makes use of the sample code function to close a current session +uint32_t test_close_session(sgx_enclave_id_t src_enclave_id, + sgx_enclave_id_t dest_enclave_id) +{ + dh_session_t dest_session_info; + ATTESTATION_STATUS ke_status = SUCCESS; + //Search the map for the session information associated with the destination enclave id passed in + std::map::iterator it = g_src_session_info_map.find(dest_enclave_id); + if(it != g_src_session_info_map.end()) + { + dest_session_info = it->second; + } + else + { + return NULL; + } + + //Core reference code function for closing a session + ke_status = close_session(src_enclave_id, dest_enclave_id); + + //Erase the session information associated with the destination enclave id + g_src_session_info_map.erase(dest_enclave_id); + return ke_status; +} + +//Function that is used to verify the trust of the other enclave +//Each enclave can have its own way verifying the peer enclave identity +extern "C" uint32_t verify_peer_enclave_trust(sgx_dh_session_enclave_identity_t* peer_enclave_identity) +{ + if(!peer_enclave_identity) + { + return INVALID_PARAMETER_ERROR; + } + if(peer_enclave_identity->isv_prod_id != 0 || !(peer_enclave_identity->attributes.flags & SGX_FLAGS_INITTED)) + // || peer_enclave_identity->attributes.xfrm !=3)// || peer_enclave_identity->mr_signer != xx //TODO: To be hardcoded with values to check + { + return ENCLAVE_TRUST_ERROR; + } + else + { + return SUCCESS; + } +} + + +//Dispatcher function that calls the approriate enclave function based on the function id +//Each enclave can have its own way of dispatching the calls from other enclave +extern "C" uint32_t enclave_to_enclave_call_dispatcher(char* decrypted_data, + size_t decrypted_data_length, + char** resp_buffer, + size_t* resp_length) +{ + ms_in_msg_exchange_t *ms; + uint32_t (*fn1)(ms_in_msg_exchange_t *ms, size_t, char**, size_t*); + if(!decrypted_data || !resp_length) + { + return INVALID_PARAMETER_ERROR; + } + ms = (ms_in_msg_exchange_t *)decrypted_data; + if(ms->target_fn_id >= func_table.num_funcs) + { + return INVALID_PARAMETER_ERROR; + } + fn1 = (uint32_t (*)(ms_in_msg_exchange_t*, size_t, char**, size_t*))func_table.table[ms->target_fn_id]; + return fn1(ms, decrypted_data_length, resp_buffer, resp_length); +} + +//Operates on the input secret and generates the output secret +uint32_t get_message_exchange_response(uint32_t inp_secret_data) +{ + uint32_t secret_response; + + //User should use more complex encryption method to protect their secret, below is just a simple example + secret_response = inp_secret_data & 0x11111111; + + return secret_response; + +} + +//Generates the response from the request message +extern "C" uint32_t message_exchange_response_generator(char* decrypted_data, + char** resp_buffer, + size_t* resp_length) +{ + ms_in_msg_exchange_t *ms; + uint32_t inp_secret_data; + uint32_t out_secret_data; + if(!decrypted_data || !resp_length) + { + return INVALID_PARAMETER_ERROR; + } + ms = (ms_in_msg_exchange_t *)decrypted_data; + + if(umarshal_message_exchange_request(&inp_secret_data,ms) != SUCCESS) + return ATTESTATION_ERROR; + + out_secret_data = get_message_exchange_response(inp_secret_data); + + if(marshal_message_exchange_response(resp_buffer, resp_length, out_secret_data) != SUCCESS) + return MALLOC_ERROR; + + return SUCCESS; + +} + + +static uint32_t e1_foo1(external_param_struct_t *p_struct_var) +{ + if(!p_struct_var) + { + return INVALID_PARAMETER_ERROR; + } + (p_struct_var->var1)++; + (p_struct_var->var2)++; + (p_struct_var->p_internal_struct->ivar1)++; + (p_struct_var->p_internal_struct->ivar2)++; + + return (p_struct_var->var1 + p_struct_var->var2 + p_struct_var->p_internal_struct->ivar1 + p_struct_var->p_internal_struct->ivar2); +} + +//Function which is executed on request from the source enclave +static uint32_t e1_foo1_wrapper(ms_in_msg_exchange_t *ms, + size_t param_lenth, + char** resp_buffer, + size_t* resp_length) +{ + UNUSED(param_lenth); + + uint32_t ret; + size_t len_data, len_ptr_data; + external_param_struct_t *p_struct_var; + internal_param_struct_t internal_struct_var; + + if(!ms || !resp_length) + { + return INVALID_PARAMETER_ERROR; + } + + p_struct_var = (external_param_struct_t*)malloc(sizeof(external_param_struct_t)); + if(!p_struct_var) + return MALLOC_ERROR; + + p_struct_var->p_internal_struct = &internal_struct_var; + + if(unmarshal_input_parameters_e1_foo1(p_struct_var, ms) != SUCCESS)//can use the stack + { + SAFE_FREE(p_struct_var); + return ATTESTATION_ERROR; + } + + ret = e1_foo1(p_struct_var); + + len_data = sizeof(external_param_struct_t) - sizeof(p_struct_var->p_internal_struct); + len_ptr_data = sizeof(internal_struct_var); + + if(marshal_retval_and_output_parameters_e1_foo1(resp_buffer, resp_length, ret, p_struct_var, len_data, len_ptr_data) != SUCCESS) + { + SAFE_FREE(p_struct_var); + return MALLOC_ERROR; + } + SAFE_FREE(p_struct_var); + return SUCCESS; +} + diff --git a/sgx-jvm/linux-sgx/SampleCode/LocalAttestation/Enclave1/Enclave1.edl b/sgx-jvm/linux-sgx/SampleCode/LocalAttestation/Enclave1/Enclave1.edl new file mode 100644 index 0000000000..378965cd11 --- /dev/null +++ b/sgx-jvm/linux-sgx/SampleCode/LocalAttestation/Enclave1/Enclave1.edl @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +enclave { + include "sgx_eid.h" + from "../LocalAttestationCode/LocalAttestationCode.edl" import *; + from "sgx_tstdc.edl" import *; + trusted{ + public uint32_t test_create_session(sgx_enclave_id_t src_enclave_id, sgx_enclave_id_t dest_enclave_id); + public uint32_t test_enclave_to_enclave_call(sgx_enclave_id_t src_enclave_id, sgx_enclave_id_t dest_enclave_id); + public uint32_t test_message_exchange(sgx_enclave_id_t src_enclave_id, sgx_enclave_id_t dest_enclave_id); + public uint32_t test_close_session(sgx_enclave_id_t src_enclave_id, sgx_enclave_id_t dest_enclave_id); + }; + +}; diff --git a/sgx-jvm/linux-sgx/SampleCode/LocalAttestation/Enclave1/Enclave1_private.pem b/sgx-jvm/linux-sgx/SampleCode/LocalAttestation/Enclave1/Enclave1_private.pem new file mode 100644 index 0000000000..75d7f88cb9 --- /dev/null +++ b/sgx-jvm/linux-sgx/SampleCode/LocalAttestation/Enclave1/Enclave1_private.pem @@ -0,0 +1,39 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIG4wIBAAKCAYEAuJh4w/KzndQhzEqwH6Ut/3BmOom5CN117KT1/cemEbDLPhn0 +c5yjAfe4NL1qtGqz0RTK9X9BBSi89b6BrsM9S6c2cUJaeYAPrAtJ+IuzN/5BAmmf +RXbPccETd7rHvDdQ9KBRjCipTx+H0D5nOB76S5PZPVrduwrCmSqVFmLNVWWfPYQx +YewbJ2QfEfioICZFYR0Jou38mJqDTl+CH0gLAuQ4n1kdpQ3VGymzt3oUiPzf5ImJ +oZh5HjarRRiWV+cyNyXYJTnx0dOtFQDgd8HhniagbRB0ZOIt6599JjMkWGkVP0Ni +U/NIlXG5musU35GfLB8MbTcxblMNm9sMYz1R8y/eAreoPTXUhtK8NG2TEywRh3UP +RF9/jM9WczjQXxJ3RznKOwNVwg4cRY2AOqD2vb1iGSqyc/WMzVULgfclkcScp75/ +Auz9Y6473CQvaxyrseSWHGwCG7KG1GxYE8Bg8T6OlYD4mzKggoMdwVLAzUepRaPZ +5hqRDZzbTGUxJ+GLAgEDAoIBgHsQUIKhzRPiwTLcdWpuHqpK7tGxJgXo+Uht+VPa +brZ13NQRTaJobKv6es3TnHhHIotjMfj/gK4bKKPUVnSCKN0aJEuBkaZVX8gHhqWy +d3qpgKxGai5PNPaAt6UnL9LPi03ANl1wcN9qWorURNAUpt0NO348k9IHLGYcY2RB +3jjuaikCy5adZ2+YFLalxWrELkC+BmyeqGW8V4mVAWowB1dC0Go7aRiz42dxInpR +YwX96phbsRZlphQkci4QZDqaIFg3ndzTO5bo704zaMcbWtEjmFrYRyb519tRoDkN +Y0rGwOxFANeRV5dSfGGLm7K5JztiuHN0nMu3PhY4LOV0SeZ4+5sYn0LzB2nyKqgy +/c3AA2OG34DEdGxxh94kD66iKFVPyJG38/gnu9CsGmrLl3n4fgutPEVIbPdSSjex +4Y9EQfcnqImPxTrpP9CqD208VPcQHD/uy8s9q3961Ew3RPdHMZ8amIJdXkOmPEme +KZ7SG+VENBaj8r038iq1mPzcWwKBwQDcvJg75LfVuKX+cWMrTO2+MFVcEFiZ/NB/ +gh7mgL6lCleROVa9P6iR2Wn6vHq8nP5BkChehm/rXEG78fgXEMoArimF7FrrICfI +4yB0opDJz/tWrE/62impN7OR8Ce+RQThFj4RTnibQEEVt++JMUXFiMKLdWDSpC2i +tNWnlTOb7d89bk0yk62IoLElCZK/MIMxkCHBKW6YgrmvlPJKQwpA6Z3wQbUpE6Rb +9f8xJfxZGEJPH0s3Ds9A0CVuEt8OOXcCgcEA1hXTHhhgmb2gIUJgIcvrpkDmiLux +EG6ZoyLt6h5QwzScS6KKU1mcoJyVDd0wlt7mEXrPYYHWUWPuvpTQ8/4ZGMw7FCZe +bakhnwRbw36FlLwRG35wCF6nQO1XFBKRGto15ivfTyDvMpJBdtNpET5NwT/ifDF3 +OWS7t6TGhtcfnvBad5S1AgGoAq+q/huFiBGpDbxJ+1xh0lNL5Z8nVypvPWomNpde +rpLuwRPEIb+GBfQ9Hp5AjRXVsPjKnkHsnl2NAoHBAJMoZX1DJTklw/72Qhzd89Qg +OOgK5bv94FUBae8Afxixj7YmOdN/xbaQ8VHS/H29/tZgGumu9UeS1n1L+roLMVXJ +cQPy50dqxTCXavhsYIaKp48diqc8G8YlImFKxSmDWJYO1AuJpbzVgLklSlt2LoOw +gbJOQIxtc8HN48UOImfz6ij0M3cNHlsVy24GYdTLAiEKwStw9GWse8pjTDGCBtXx +E/WBI3C3wuf5VMtuqDtlgYoU3M9fNNXgGPQMlLQmTwKBwQCOuTdpZZW708AWLEAW +h/Ju1e8F0nYK9GZswfPxaYsszb2HwbGM5mhrEw4JPiBklJlg/IpBATmLl/R/DeCi +qWYQiCdixD7zxhZqAufXqa5jKAtnqaAFlG+AnjoNYbYR5s6ZcpTfa0ohttZPN5tg +1DPWKpb9dk97mH0lGIRZ5L+/Sub6YyNWq8VXH8dUElkFYRtefYankuvhjN1Dv2+P +cZ9+RsQkZOnJt0nWDS1r1QQD+Ci/FCsIuTkgpdxpgUhpk7MCgcEAkfkmaBDb7DG2 +Kc39R6ZZuPnV10w+WOpph7ugwcguG/E0wGq+jFWv6HFckCPeHT4BNtOk8Dem/kPp +teF51eAuFWEefj2tScvlSBBPcnla+WzMWXrlxVnajTt73w+oT2Ql//WhgREpsNfx +SvU80YPVu4GJfl+hhxBifLx+0FM20OESW93qFRc3p040bNrDY9JIZuly/y5zaiBa +mRZF9H8P+x3Lu5AJpdXQEOMZ/XJ/xkoWWjbTojkmgOmmZSMLd5Te +-----END RSA PRIVATE KEY----- diff --git a/sgx-jvm/linux-sgx/SampleCode/LocalAttestation/Enclave1/Utility_E1.cpp b/sgx-jvm/linux-sgx/SampleCode/LocalAttestation/Enclave1/Utility_E1.cpp new file mode 100644 index 0000000000..9c2247b716 --- /dev/null +++ b/sgx-jvm/linux-sgx/SampleCode/LocalAttestation/Enclave1/Utility_E1.cpp @@ -0,0 +1,222 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "sgx_eid.h" +#include "EnclaveMessageExchange.h" +#include "error_codes.h" +#include "Utility_E1.h" +#include "stdlib.h" +#include "string.h" + +uint32_t marshal_input_parameters_e2_foo1(uint32_t target_fn_id, uint32_t msg_type, uint32_t var1, uint32_t var2, char** marshalled_buff, size_t* marshalled_buff_len) +{ + ms_in_msg_exchange_t *ms; + size_t param_len, ms_len; + char *temp_buff; + + param_len = sizeof(var1)+sizeof(var2); + temp_buff = (char*)malloc(param_len); + if(!temp_buff) + return MALLOC_ERROR; + + memcpy(temp_buff,&var1,sizeof(var1)); + memcpy(temp_buff+sizeof(var1),&var2,sizeof(var2)); + ms_len = sizeof(ms_in_msg_exchange_t) + param_len; + ms = (ms_in_msg_exchange_t *)malloc(ms_len); + if(!ms) + { + SAFE_FREE(temp_buff); + return MALLOC_ERROR; + } + ms->msg_type = msg_type; + ms->target_fn_id = target_fn_id; + ms->inparam_buff_len = (uint32_t)param_len; + memcpy(&ms->inparam_buff, temp_buff, param_len); + *marshalled_buff = (char*)ms; + *marshalled_buff_len = ms_len; + SAFE_FREE(temp_buff); + return SUCCESS; +} + +uint32_t unmarshal_retval_and_output_parameters_e2_foo1(char* out_buff, char** retval) +{ + size_t retval_len; + ms_out_msg_exchange_t *ms; + if(!out_buff) + return INVALID_PARAMETER_ERROR; + ms = (ms_out_msg_exchange_t *)out_buff; + retval_len = ms->retval_len; + *retval = (char*)malloc(retval_len); + if(!*retval) + return MALLOC_ERROR; + + memcpy(*retval, ms->ret_outparam_buff, retval_len); + return SUCCESS; +} + +uint32_t unmarshal_input_parameters_e1_foo1(external_param_struct_t *pstruct, ms_in_msg_exchange_t* ms) +{ + char* buff; + size_t len; + if(!pstruct || !ms) + return INVALID_PARAMETER_ERROR; + + buff = ms->inparam_buff; + len = ms->inparam_buff_len; + if(len != (sizeof(pstruct->var1)+sizeof(pstruct->var2)+sizeof(pstruct->p_internal_struct->ivar1)+sizeof(pstruct->p_internal_struct->ivar2))) + return ATTESTATION_ERROR; + + memcpy(&pstruct->var1, buff, sizeof(pstruct->var1)); + memcpy(&pstruct->var2, buff + sizeof(pstruct->var1), sizeof(pstruct->var2)); + memcpy(&pstruct->p_internal_struct->ivar1, buff+(sizeof(pstruct->var1)+sizeof(pstruct->var2)), sizeof(pstruct->p_internal_struct->ivar1)); + memcpy(&pstruct->p_internal_struct->ivar2, buff+(sizeof(pstruct->var1)+sizeof(pstruct->var2)+sizeof(pstruct->p_internal_struct->ivar1)), sizeof(pstruct->p_internal_struct->ivar2)); + + return SUCCESS; +} + +uint32_t marshal_retval_and_output_parameters_e1_foo1(char** resp_buffer, size_t* resp_length, uint32_t retval, external_param_struct_t *p_struct_var, size_t len_data, size_t len_ptr_data) +{ + ms_out_msg_exchange_t *ms; + size_t param_len, ms_len, ret_param_len;; + char *temp_buff; + int* addr; + char* struct_data; + size_t retval_len; + + if(!resp_length || !p_struct_var) + return INVALID_PARAMETER_ERROR; + + retval_len = sizeof(retval); + struct_data = (char*)p_struct_var; + param_len = len_data + len_ptr_data; + ret_param_len = param_len + retval_len; + addr = *(int **)(struct_data + len_data); + temp_buff = (char*)malloc(ret_param_len); + if(!temp_buff) + return MALLOC_ERROR; + + memcpy(temp_buff, &retval, sizeof(retval)); + memcpy(temp_buff + sizeof(retval), struct_data, len_data); + memcpy(temp_buff + sizeof(retval) + len_data, addr, len_ptr_data); + ms_len = sizeof(ms_out_msg_exchange_t) + ret_param_len; + ms = (ms_out_msg_exchange_t *)malloc(ms_len); + if(!ms) + { + SAFE_FREE(temp_buff); + return MALLOC_ERROR; + } + ms->retval_len = (uint32_t)retval_len; + ms->ret_outparam_buff_len = (uint32_t)ret_param_len; + memcpy(&ms->ret_outparam_buff, temp_buff, ret_param_len); + *resp_buffer = (char*)ms; + *resp_length = ms_len; + + SAFE_FREE(temp_buff); + return SUCCESS; +} + +uint32_t marshal_message_exchange_request(uint32_t target_fn_id, uint32_t msg_type, uint32_t secret_data, char** marshalled_buff, size_t* marshalled_buff_len) +{ + ms_in_msg_exchange_t *ms; + size_t secret_data_len, ms_len; + if(!marshalled_buff_len) + return INVALID_PARAMETER_ERROR; + secret_data_len = sizeof(secret_data); + ms_len = sizeof(ms_in_msg_exchange_t) + secret_data_len; + ms = (ms_in_msg_exchange_t *)malloc(ms_len); + if(!ms) + return MALLOC_ERROR; + + ms->msg_type = msg_type; + ms->target_fn_id = target_fn_id; + ms->inparam_buff_len = (uint32_t)secret_data_len; + memcpy(&ms->inparam_buff, &secret_data, secret_data_len); + *marshalled_buff = (char*)ms; + *marshalled_buff_len = ms_len; + return SUCCESS; +} + +uint32_t umarshal_message_exchange_request(uint32_t* inp_secret_data, ms_in_msg_exchange_t* ms) +{ + char* buff; + size_t len; + if(!inp_secret_data || !ms) + return INVALID_PARAMETER_ERROR; + buff = ms->inparam_buff; + len = ms->inparam_buff_len; + if(len != sizeof(uint32_t)) + return ATTESTATION_ERROR; + + memcpy(inp_secret_data, buff, sizeof(uint32_t)); + + return SUCCESS; +} + +uint32_t marshal_message_exchange_response(char** resp_buffer, size_t* resp_length, uint32_t secret_response) +{ + ms_out_msg_exchange_t *ms; + size_t secret_response_len, ms_len; + size_t retval_len, ret_param_len; + if(!resp_length) + return INVALID_PARAMETER_ERROR; + secret_response_len = sizeof(secret_response); + retval_len = secret_response_len; + ret_param_len = secret_response_len; + ms_len = sizeof(ms_out_msg_exchange_t) + ret_param_len; + ms = (ms_out_msg_exchange_t *)malloc(ms_len); + if(!ms) + return MALLOC_ERROR; + + ms->retval_len = (uint32_t)retval_len; + ms->ret_outparam_buff_len = (uint32_t)ret_param_len; + memcpy(&ms->ret_outparam_buff, &secret_response, secret_response_len); + *resp_buffer = (char*)ms; + *resp_length = ms_len; + return SUCCESS; +} + +uint32_t umarshal_message_exchange_response(char* out_buff, char** secret_response) +{ + size_t retval_len; + ms_out_msg_exchange_t *ms; + if(!out_buff) + return INVALID_PARAMETER_ERROR; + ms = (ms_out_msg_exchange_t *)out_buff; + retval_len = ms->retval_len; + *secret_response = (char*)malloc(retval_len); + if(!*secret_response) + { + return MALLOC_ERROR; + } + memcpy(*secret_response, ms->ret_outparam_buff, retval_len); + return SUCCESS; +} + diff --git a/sgx-jvm/linux-sgx/SampleCode/LocalAttestation/Enclave1/Utility_E1.h b/sgx-jvm/linux-sgx/SampleCode/LocalAttestation/Enclave1/Utility_E1.h new file mode 100644 index 0000000000..7af49b6814 --- /dev/null +++ b/sgx-jvm/linux-sgx/SampleCode/LocalAttestation/Enclave1/Utility_E1.h @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef UTILITY_E1_H__ +#define UTILITY_E1_H__ + +#include "stdint.h" + +typedef struct _internal_param_struct_t +{ + uint32_t ivar1; + uint32_t ivar2; +}internal_param_struct_t; + +typedef struct _external_param_struct_t +{ + uint32_t var1; + uint32_t var2; + internal_param_struct_t *p_internal_struct; +}external_param_struct_t; + +#ifdef __cplusplus +extern "C" { +#endif + +uint32_t marshal_input_parameters_e2_foo1(uint32_t target_fn_id, uint32_t msg_type, uint32_t var1, uint32_t var2, char** marshalled_buff, size_t* marshalled_buff_len); +uint32_t unmarshal_retval_and_output_parameters_e2_foo1(char* out_buff, char** retval); +uint32_t unmarshal_input_parameters_e1_foo1(external_param_struct_t *pstruct, ms_in_msg_exchange_t* ms); +uint32_t marshal_retval_and_output_parameters_e1_foo1(char** resp_buffer, size_t* resp_length, uint32_t retval, external_param_struct_t *p_struct_var, size_t len_data, size_t len_ptr_data); +uint32_t marshal_message_exchange_request(uint32_t target_fn_id, uint32_t msg_type, uint32_t secret_data, char** marshalled_buff, size_t* marshalled_buff_len); +uint32_t umarshal_message_exchange_request(uint32_t* inp_secret_data, ms_in_msg_exchange_t* ms); +uint32_t marshal_message_exchange_response(char** resp_buffer, size_t* resp_length, uint32_t secret_response); +uint32_t umarshal_message_exchange_response(char* out_buff, char** secret_response); +#ifdef __cplusplus + } +#endif +#endif diff --git a/sgx-jvm/linux-sgx/SampleCode/LocalAttestation/Enclave2/Enclave2.config.xml b/sgx-jvm/linux-sgx/SampleCode/LocalAttestation/Enclave2/Enclave2.config.xml new file mode 100644 index 0000000000..3317e37a37 --- /dev/null +++ b/sgx-jvm/linux-sgx/SampleCode/LocalAttestation/Enclave2/Enclave2.config.xml @@ -0,0 +1,11 @@ + + 0 + 0 + 0x40000 + 0x100000 + 1 + 1 + 0 + 0 + 0xFFFFFFFF + diff --git a/sgx-jvm/linux-sgx/SampleCode/LocalAttestation/Enclave2/Enclave2.cpp b/sgx-jvm/linux-sgx/SampleCode/LocalAttestation/Enclave2/Enclave2.cpp new file mode 100644 index 0000000000..537957f68c --- /dev/null +++ b/sgx-jvm/linux-sgx/SampleCode/LocalAttestation/Enclave2/Enclave2.cpp @@ -0,0 +1,339 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + + +// Enclave2.cpp : Defines the exported functions for the DLL application +#include "sgx_eid.h" +#include "Enclave2_t.h" +#include "EnclaveMessageExchange.h" +#include "error_codes.h" +#include "Utility_E2.h" +#include "sgx_thread.h" +#include "sgx_dh.h" +#include + +#define UNUSED(val) (void)(val) + +std::mapg_src_session_info_map; + +static uint32_t e2_foo1_wrapper(ms_in_msg_exchange_t *ms, size_t param_lenth, char** resp_buffer, size_t* resp_length); + +//Function pointer table containing the list of functions that the enclave exposes +const struct { + size_t num_funcs; + const void* table[1]; +} func_table = { + 1, + { + (const void*)e2_foo1_wrapper, + } +}; + +//Makes use of the sample code function to establish a secure channel with the destination enclave +uint32_t test_create_session(sgx_enclave_id_t src_enclave_id, + sgx_enclave_id_t dest_enclave_id) +{ + ATTESTATION_STATUS ke_status = SUCCESS; + dh_session_t dest_session_info; + //Core reference code function for creating a session + ke_status = create_session(src_enclave_id, dest_enclave_id,&dest_session_info); + if(ke_status == SUCCESS) + { + //Insert the session information into the map under the corresponding destination enclave id + g_src_session_info_map.insert(std::pair(dest_enclave_id, dest_session_info)); + } + memset(&dest_session_info, 0, sizeof(dh_session_t)); + return ke_status; +} + +//Makes use of the sample code function to do an enclave to enclave call (Test Vector) +uint32_t test_enclave_to_enclave_call(sgx_enclave_id_t src_enclave_id, + sgx_enclave_id_t dest_enclave_id) +{ + ATTESTATION_STATUS ke_status = SUCCESS; + param_struct_t *p_struct_var, struct_var; + uint32_t target_fn_id, msg_type; + char* marshalled_inp_buff; + size_t marshalled_inp_buff_len; + char* out_buff; + size_t out_buff_len; + dh_session_t *dest_session_info; + size_t max_out_buff_size; + char* retval; + + max_out_buff_size = 50; + target_fn_id = 0; + msg_type = ENCLAVE_TO_ENCLAVE_CALL; + + struct_var.var1 = 0x3; + struct_var.var2 = 0x4; + p_struct_var = &struct_var; + + //Marshals the input parameters for calling function foo1 in Enclave3 into a input buffer + ke_status = marshal_input_parameters_e3_foo1(target_fn_id, msg_type, p_struct_var, &marshalled_inp_buff, &marshalled_inp_buff_len); + if(ke_status != SUCCESS) + { + return ke_status; + } + + //Search the map for the session information associated with the destination enclave id passed in + std::map::iterator it = g_src_session_info_map.find(dest_enclave_id); + if(it != g_src_session_info_map.end()) + { + dest_session_info = &it->second; + } + else + { + SAFE_FREE(marshalled_inp_buff); + return INVALID_SESSION; + } + + //Core Reference Code function + ke_status = send_request_receive_response(src_enclave_id, dest_enclave_id, dest_session_info, marshalled_inp_buff, + marshalled_inp_buff_len, max_out_buff_size, &out_buff, &out_buff_len); + + if(ke_status != SUCCESS) + { + SAFE_FREE(marshalled_inp_buff); + SAFE_FREE(out_buff); + return ke_status; + } + + //Un-marshal the return value and output parameters from foo1 of Enclave3 + ke_status = unmarshal_retval_and_output_parameters_e3_foo1(out_buff, p_struct_var, &retval); + if(ke_status != SUCCESS) + { + SAFE_FREE(marshalled_inp_buff); + SAFE_FREE(out_buff); + return ke_status; + } + + SAFE_FREE(marshalled_inp_buff); + SAFE_FREE(out_buff); + SAFE_FREE(retval); + return SUCCESS; +} + +//Makes use of the sample code function to do a generic secret message exchange (Test Vector) +uint32_t test_message_exchange(sgx_enclave_id_t src_enclave_id, + sgx_enclave_id_t dest_enclave_id) +{ + ATTESTATION_STATUS ke_status = SUCCESS; + uint32_t target_fn_id, msg_type; + char* marshalled_inp_buff; + size_t marshalled_inp_buff_len; + char* out_buff; + size_t out_buff_len; + dh_session_t *dest_session_info; + size_t max_out_buff_size; + char* secret_response; + uint32_t secret_data; + + target_fn_id = 0; + msg_type = MESSAGE_EXCHANGE; + max_out_buff_size = 50; + secret_data = 0x12345678; //Secret Data here is shown only for purpose of demonstration. + + //Marshals the secret data into a buffer + ke_status = marshal_message_exchange_request(target_fn_id, msg_type, secret_data, &marshalled_inp_buff, &marshalled_inp_buff_len); + if(ke_status != SUCCESS) + { + return ke_status; + } + //Search the map for the session information associated with the destination enclave id passed in + std::map::iterator it = g_src_session_info_map.find(dest_enclave_id); + if(it != g_src_session_info_map.end()) + { + dest_session_info = &it->second; + } + else + { + SAFE_FREE(marshalled_inp_buff); + return INVALID_SESSION; + } + + //Core Reference Code function + ke_status = send_request_receive_response(src_enclave_id, dest_enclave_id, dest_session_info, marshalled_inp_buff, + marshalled_inp_buff_len, max_out_buff_size, &out_buff, &out_buff_len); + if(ke_status != SUCCESS) + { + SAFE_FREE(marshalled_inp_buff); + SAFE_FREE(out_buff); + return ke_status; + } + + //Un-marshal the secret response data + ke_status = umarshal_message_exchange_response(out_buff, &secret_response); + if(ke_status != SUCCESS) + { + SAFE_FREE(marshalled_inp_buff); + SAFE_FREE(out_buff); + return ke_status; + } + + SAFE_FREE(marshalled_inp_buff); + SAFE_FREE(out_buff); + SAFE_FREE(secret_response); + return SUCCESS; +} + + +//Makes use of the sample code function to close a current session +uint32_t test_close_session(sgx_enclave_id_t src_enclave_id, + sgx_enclave_id_t dest_enclave_id) +{ + dh_session_t dest_session_info; + ATTESTATION_STATUS ke_status = SUCCESS; + //Search the map for the session information associated with the destination enclave id passed in + std::map::iterator it = g_src_session_info_map.find(dest_enclave_id); + if(it != g_src_session_info_map.end()) + { + dest_session_info = it->second; + } + else + { + return NULL; + } + //Core reference code function for closing a session + ke_status = close_session(src_enclave_id, dest_enclave_id); + + //Erase the session information associated with the destination enclave id + g_src_session_info_map.erase(dest_enclave_id); + return ke_status; +} + +//Function that is used to verify the trust of the other enclave +//Each enclave can have its own way verifying the peer enclave identity +extern "C" uint32_t verify_peer_enclave_trust(sgx_dh_session_enclave_identity_t* peer_enclave_identity) +{ + if(!peer_enclave_identity) + { + return INVALID_PARAMETER_ERROR; + } + if(peer_enclave_identity->isv_prod_id != 0 || !(peer_enclave_identity->attributes.flags & SGX_FLAGS_INITTED)) + // || peer_enclave_identity->attributes.xfrm !=3)// || peer_enclave_identity->mr_signer != xx //TODO: To be hardcoded with values to check + { + return ENCLAVE_TRUST_ERROR; + } + else + { + return SUCCESS; + } +} + +//Dispatch function that calls the approriate enclave function based on the function id +//Each enclave can have its own way of dispatching the calls from other enclave +extern "C" uint32_t enclave_to_enclave_call_dispatcher(char* decrypted_data, + size_t decrypted_data_length, + char** resp_buffer, + size_t* resp_length) +{ + ms_in_msg_exchange_t *ms; + uint32_t (*fn1)(ms_in_msg_exchange_t *ms, size_t, char**, size_t*); + if(!decrypted_data || !resp_length) + { + return INVALID_PARAMETER_ERROR; + } + ms = (ms_in_msg_exchange_t *)decrypted_data; + if(ms->target_fn_id >= func_table.num_funcs) + { + return INVALID_PARAMETER_ERROR; + } + fn1 = (uint32_t (*)(ms_in_msg_exchange_t*, size_t, char**, size_t*))func_table.table[ms->target_fn_id]; + return fn1(ms, decrypted_data_length, resp_buffer, resp_length); +} + +//Operates on the input secret and generates the output secret +uint32_t get_message_exchange_response(uint32_t inp_secret_data) +{ + uint32_t secret_response; + + //User should use more complex encryption method to protect their secret, below is just a simple example + secret_response = inp_secret_data & 0x11111111; + + return secret_response; + +} + +//Generates the response from the request message +extern "C" uint32_t message_exchange_response_generator(char* decrypted_data, + char** resp_buffer, + size_t* resp_length) +{ + ms_in_msg_exchange_t *ms; + uint32_t inp_secret_data; + uint32_t out_secret_data; + if(!decrypted_data || !resp_length) + { + return INVALID_PARAMETER_ERROR; + } + ms = (ms_in_msg_exchange_t *)decrypted_data; + + if(umarshal_message_exchange_request(&inp_secret_data,ms) != SUCCESS) + return ATTESTATION_ERROR; + + out_secret_data = get_message_exchange_response(inp_secret_data); + + if(marshal_message_exchange_response(resp_buffer, resp_length, out_secret_data) != SUCCESS) + return MALLOC_ERROR; + + return SUCCESS; + +} + +static uint32_t e2_foo1(uint32_t var1, uint32_t var2) +{ + return(var1 + var2); +} + +//Function which is executed on request from the source enclave +static uint32_t e2_foo1_wrapper(ms_in_msg_exchange_t *ms, + size_t param_lenth, + char** resp_buffer, + size_t* resp_length) +{ + UNUSED(param_lenth); + + uint32_t var1,var2,ret; + if(!ms || !resp_length) + { + return INVALID_PARAMETER_ERROR; + } + if(unmarshal_input_parameters_e2_foo1(&var1, &var2, ms) != SUCCESS) + return ATTESTATION_ERROR; + + ret = e2_foo1(var1, var2); + + if(marshal_retval_and_output_parameters_e2_foo1(resp_buffer, resp_length, ret) != SUCCESS ) + return MALLOC_ERROR; //can set resp buffer to null here + + return SUCCESS; +} diff --git a/sgx-jvm/linux-sgx/SampleCode/LocalAttestation/Enclave2/Enclave2.edl b/sgx-jvm/linux-sgx/SampleCode/LocalAttestation/Enclave2/Enclave2.edl new file mode 100644 index 0000000000..9ef5c33e4c --- /dev/null +++ b/sgx-jvm/linux-sgx/SampleCode/LocalAttestation/Enclave2/Enclave2.edl @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + + +enclave { + include "sgx_eid.h" + from "../LocalAttestationCode/LocalAttestationCode.edl" import *; + from "sgx_tstdc.edl" import *; + trusted{ + public uint32_t test_create_session(sgx_enclave_id_t src_enclave_id, sgx_enclave_id_t dest_enclave_id); + public uint32_t test_enclave_to_enclave_call(sgx_enclave_id_t src_enclave_id, sgx_enclave_id_t dest_enclave_id); + public uint32_t test_message_exchange(sgx_enclave_id_t src_enclave_id, sgx_enclave_id_t dest_enclave_id); + public uint32_t test_close_session(sgx_enclave_id_t src_enclave_id, sgx_enclave_id_t dest_enclave_id); + }; +}; diff --git a/sgx-jvm/linux-sgx/SampleCode/LocalAttestation/Enclave2/Enclave2_private.pem b/sgx-jvm/linux-sgx/SampleCode/LocalAttestation/Enclave2/Enclave2_private.pem new file mode 100644 index 0000000000..529d07be35 --- /dev/null +++ b/sgx-jvm/linux-sgx/SampleCode/LocalAttestation/Enclave2/Enclave2_private.pem @@ -0,0 +1,39 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIG4gIBAAKCAYEAroOogvsj/fZDZY8XFdkl6dJmky0lRvnWMmpeH41Bla6U1qLZ +AmZuyIF+mQC/cgojIsrBMzBxb1kKqzATF4+XwPwgKz7fmiddmHyYz2WDJfAjIveJ +ZjdMjM4+EytGlkkJ52T8V8ds0/L2qKexJ+NBLxkeQLfV8n1mIk7zX7jguwbCG1Pr +nEMdJ3Sew20vnje+RsngAzdPChoJpVsWi/K7cettX/tbnre1DL02GXc5qJoQYk7b +3zkmhz31TgFrd9VVtmUGyFXAysuSAb3EN+5VnHGr0xKkeg8utErea2FNtNIgua8H +ONfm9Eiyaav1SVKzPHlyqLtcdxH3I8Wg7yqMsaprZ1n5A1v/levxnL8+It02KseD +5HqV4rf/cImSlCt3lpRg8U5E1pyFQ2IVEC/XTDMiI3c+AR+w2jSRB3Bwn9zJtFlW +KHG3m1xGI4ck+Lci1JvWWLXQagQSPtZTsubxTQNx1gsgZhgv1JHVZMdbVlAbbRMC +1nSuJNl7KPAS/VfzAgEDAoIBgHRXxaynbVP5gkO0ug6Qw/E27wzIw4SmjsxG6Wpe +K7kfDeRskKxESdsA/xCrKkwGwhcx1iIgS5+Qscd1Yg+1D9X9asd/P7waPmWoZd+Z +AhlKwhdPsO7PiF3e1AzHhGQwsUTt/Y/aSI1MpHBvy2/s1h9mFCslOUxTmWw0oj/Q +ldIEgWeNR72CE2+jFIJIyml6ftnb6qzPiga8Bm48ubKh0kvySOqnkmnPzgh+JBD6 +JnBmtZbfPT97bwTT+N6rnPqOOApvfHPf15kWI8yDbprG1l4OCUaIUH1AszxLd826 +5IPM+8gINLRDP1MA6azECPjTyHXhtnSIBZCyWSVkc05vYmNXYUNiXWMajcxW9M02 +wKzFELO8NCEAkaTPxwo4SCyIjUxiK1LbQ9h8PSy4c1+gGP4LAMR8xqP4QKg6zdu9 +osUGG/xRe/uufgTBFkcjqBHtK5L5VI0jeNIUAgW/6iNbYXjBMJ0GfauLs+g1VsOm +WfdgXzsb9DYdMa0OXXHypmV4GwKBwQDUwQj8RKJ6c8cT4vcWCoJvJF00+RFL+P3i +Gx2DLERxRrDa8AVGfqaCjsR+3vLgG8V/py+z+dxZYSqeB80Qeo6PDITcRKoeAYh9 +xlT3LJOS+k1cJcEmlbbO2IjLkTmzSwa80fWexKu8/Xv6vv15gpqYl1ngYoqJM3pd +vzmTIOi7MKSZ0WmEQavrZj8zK4endE3v0eAEeQ55j1GImbypSf7Idh7wOXtjZ7WD +Dg6yWDrri+AP/L3gClMj8wsAxMV4ZR8CgcEA0fzDHkFa6raVOxWnObmRoDhAtE0a +cjUj976NM5yyfdf2MrKy4/RhdTiPZ6b08/lBC/+xRfV3xKVGzacm6QjqjZrUpgHC +0LKiZaMtccCJjLtPwQd0jGQEnKfMFaPsnhOc5y8qVkCzVOSthY5qhz0XNotHHFmJ +gffVgB0iqrMTvSL7IA2yqqpOqNRlhaYhNl8TiFP3gIeMtVa9rZy31JPgT2uJ+kfo +gV7sdTPEjPWZd7OshGxWpT6QfVDj/T9T7L6tAoHBAI3WBf2DFvxNL2KXT2QHAZ9t +k3imC4f7U+wSE6zILaDZyzygA4RUbwG0gv8/TJVn2P/Eynf76DuWHGlaiLWnCbSz +Az2DHBQBBaku409zDQym3j1ugMRjzzSQWzJg0SIyBH3hTmnYcn3+Uqcp/lEBvGW6 +O+rsXFt3pukqJmIV8HzLGGaLm62BHUeZf3dyWm+i3p/hQAL7Xvu04QW70xuGqdr5 +afV7p5eaeQIJXyGQJ0eylV/90+qxjMKiB1XYg6WYvwKBwQCL/ddpgOdHJGN8uRom +e7Zq0Csi3hGheMKlKbN3vcxT5U7MdyHtTZZOJbTvxKNNUNYH/8uD+PqDGNneb29G +BfGzvI3EASyLIcGZF3OhKwZd0jUrWk2y7Vhob91jwp2+t73vdMbkKyI4mHOuXvGv +fg95si9oO7EBT+Oqvhccd2J+F1IVXncccYnF4u5ZGWt5lLewN/pVr7MjjykeaHqN +t+rfnQam2psA6fL4zS2zTmZPzR2tnY8Y1GBTi0Ko1OKd1HMCgcAb5cB/7/AQlhP9 +yQa04PLH9ygQkKKptZp7dy5WcWRx0K/hAHRoi2aw1wZqfm7VBNu2SLcs90kCCCxp +6C5sfJi6b8NpNbIPC+sc9wsFr7pGo9SFzQ78UlcWYK2Gu2FxlMjonhka5hvo4zvg +WxlpXKEkaFt3gLd92m/dMqBrHfafH7VwOJY2zT3WIpjwuk0ZzmRg5p0pG/svVQEH +NZmwRwlopysbR69B/n1nefJ84UO50fLh5s5Zr3gBRwbWNZyzhXk= +-----END RSA PRIVATE KEY----- diff --git a/sgx-jvm/linux-sgx/SampleCode/LocalAttestation/Enclave2/Utility_E2.cpp b/sgx-jvm/linux-sgx/SampleCode/LocalAttestation/Enclave2/Utility_E2.cpp new file mode 100644 index 0000000000..962c68f922 --- /dev/null +++ b/sgx-jvm/linux-sgx/SampleCode/LocalAttestation/Enclave2/Utility_E2.cpp @@ -0,0 +1,213 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "sgx_eid.h" +#include "EnclaveMessageExchange.h" +#include "error_codes.h" +#include "Utility_E2.h" +#include "stdlib.h" +#include "string.h" + +uint32_t marshal_input_parameters_e3_foo1(uint32_t target_fn_id, uint32_t msg_type, param_struct_t *p_struct_var, char** marshalled_buff, size_t* marshalled_buff_len) +{ + ms_in_msg_exchange_t *ms; + size_t param_len, ms_len; + char *temp_buff; + if(!p_struct_var || !marshalled_buff_len) + return INVALID_PARAMETER_ERROR; + param_len = sizeof(param_struct_t); + temp_buff = (char*)malloc(param_len); + if(!temp_buff) + return MALLOC_ERROR; + memcpy(temp_buff, p_struct_var, sizeof(param_struct_t)); //can be optimized + ms_len = sizeof(ms_in_msg_exchange_t) + param_len; + ms = (ms_in_msg_exchange_t *)malloc(ms_len); + if(!ms) + { + SAFE_FREE(temp_buff); + return MALLOC_ERROR; + } + ms->msg_type = msg_type; + ms->target_fn_id = target_fn_id; + ms->inparam_buff_len = (uint32_t)param_len; + memcpy(&ms->inparam_buff, temp_buff, param_len); + *marshalled_buff = (char*)ms; + *marshalled_buff_len = ms_len; + SAFE_FREE(temp_buff); + return SUCCESS; +} + +uint32_t unmarshal_retval_and_output_parameters_e3_foo1(char* out_buff, param_struct_t *p_struct_var, char** retval) +{ + size_t retval_len; + ms_out_msg_exchange_t *ms; + if(!out_buff) + return INVALID_PARAMETER_ERROR; + ms = (ms_out_msg_exchange_t *)out_buff; + retval_len = ms->retval_len; + *retval = (char*)malloc(retval_len); + if(!*retval) + { + return MALLOC_ERROR; + } + memcpy(*retval, ms->ret_outparam_buff, retval_len); + memcpy(&p_struct_var->var1, (ms->ret_outparam_buff) + retval_len, sizeof(p_struct_var->var1)); + memcpy(&p_struct_var->var2, (ms->ret_outparam_buff) + retval_len + sizeof(p_struct_var->var1), sizeof(p_struct_var->var2)); + return SUCCESS; +} + + +uint32_t unmarshal_input_parameters_e2_foo1(uint32_t* var1, uint32_t* var2, ms_in_msg_exchange_t* ms) +{ + char* buff; + size_t len; + if(!var1 || !var2 || !ms) + return INVALID_PARAMETER_ERROR; + + buff = ms->inparam_buff; + len = ms->inparam_buff_len; + + if(len != (sizeof(*var1) + sizeof(*var2))) + return ATTESTATION_ERROR; + + memcpy(var1, buff, sizeof(*var1)); + memcpy(var2, buff + sizeof(*var1), sizeof(*var2)); + + return SUCCESS; +} + +uint32_t marshal_retval_and_output_parameters_e2_foo1(char** resp_buffer, size_t* resp_length, uint32_t retval) +{ + ms_out_msg_exchange_t *ms; + size_t ret_param_len, ms_len; + char *temp_buff; + size_t retval_len; + if(!resp_length) + return INVALID_PARAMETER_ERROR; + retval_len = sizeof(retval); + ret_param_len = retval_len; //no out parameters + temp_buff = (char*)malloc(ret_param_len); + if(!temp_buff) + return MALLOC_ERROR; + + memcpy(temp_buff, &retval, sizeof(retval)); + ms_len = sizeof(ms_out_msg_exchange_t) + ret_param_len; + ms = (ms_out_msg_exchange_t *)malloc(ms_len); + if(!ms) + { + SAFE_FREE(temp_buff); + return MALLOC_ERROR; + } + ms->retval_len = (uint32_t)retval_len; + ms->ret_outparam_buff_len = (uint32_t)ret_param_len; + memcpy(&ms->ret_outparam_buff, temp_buff, ret_param_len); + *resp_buffer = (char*)ms; + *resp_length = ms_len; + SAFE_FREE(temp_buff); + return SUCCESS; +} + +uint32_t marshal_message_exchange_request(uint32_t target_fn_id, uint32_t msg_type, uint32_t secret_data, char** marshalled_buff, size_t* marshalled_buff_len) +{ + ms_in_msg_exchange_t *ms; + size_t secret_data_len, ms_len; + if(!marshalled_buff_len) + return INVALID_PARAMETER_ERROR; + secret_data_len = sizeof(secret_data); + ms_len = sizeof(ms_in_msg_exchange_t) + secret_data_len; + ms = (ms_in_msg_exchange_t *)malloc(ms_len); + if(!ms) + return MALLOC_ERROR; + + ms->msg_type = msg_type; + ms->target_fn_id = target_fn_id; + ms->inparam_buff_len = (uint32_t)secret_data_len; + memcpy(&ms->inparam_buff, &secret_data, secret_data_len); + *marshalled_buff = (char*)ms; + *marshalled_buff_len = ms_len; + return SUCCESS; +} + +uint32_t umarshal_message_exchange_request(uint32_t* inp_secret_data, ms_in_msg_exchange_t* ms) +{ + char* buff; + size_t len; + if(!inp_secret_data || !ms) + return INVALID_PARAMETER_ERROR; + buff = ms->inparam_buff; + len = ms->inparam_buff_len; + if(len != sizeof(uint32_t)) + return ATTESTATION_ERROR; + + memcpy(inp_secret_data, buff, sizeof(uint32_t)); + + return SUCCESS; +} + + +uint32_t marshal_message_exchange_response(char** resp_buffer, size_t* resp_length, uint32_t secret_response) +{ + ms_out_msg_exchange_t *ms; + size_t secret_response_len, ms_len; + size_t retval_len, ret_param_len; + if(!resp_length) + return INVALID_PARAMETER_ERROR; + secret_response_len = sizeof(secret_response); + retval_len = secret_response_len; + ret_param_len = secret_response_len; + ms_len = sizeof(ms_out_msg_exchange_t) + ret_param_len; + ms = (ms_out_msg_exchange_t *)malloc(ms_len); + if(!ms) + return MALLOC_ERROR; + ms->retval_len = (uint32_t)retval_len; + ms->ret_outparam_buff_len = (uint32_t)ret_param_len; + memcpy(&ms->ret_outparam_buff, &secret_response, secret_response_len); + *resp_buffer = (char*)ms; + *resp_length = ms_len; + return SUCCESS; +} + +uint32_t umarshal_message_exchange_response(char* out_buff, char** secret_response) +{ + size_t retval_len; + ms_out_msg_exchange_t *ms; + if(!out_buff) + return INVALID_PARAMETER_ERROR; + ms = (ms_out_msg_exchange_t *)out_buff; + retval_len = ms->retval_len; + *secret_response = (char*)malloc(retval_len); + if(!*secret_response) + { + return MALLOC_ERROR; + } + memcpy(*secret_response, ms->ret_outparam_buff, retval_len); + return SUCCESS; +} diff --git a/sgx-jvm/linux-sgx/SampleCode/LocalAttestation/Enclave2/Utility_E2.h b/sgx-jvm/linux-sgx/SampleCode/LocalAttestation/Enclave2/Utility_E2.h new file mode 100644 index 0000000000..17b88cdea2 --- /dev/null +++ b/sgx-jvm/linux-sgx/SampleCode/LocalAttestation/Enclave2/Utility_E2.h @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef UTILITY_E2_H__ +#define UTILITY_E2_H__ +#include "stdint.h" + +typedef struct _param_struct_t +{ + uint32_t var1; + uint32_t var2; +}param_struct_t; + +#ifdef __cplusplus +extern "C" { +#endif + +uint32_t marshal_input_parameters_e3_foo1(uint32_t target_fn_id, uint32_t msg_type, param_struct_t *p_struct_var, char** marshalled_buff, size_t* marshalled_buff_len); +uint32_t unmarshal_retval_and_output_parameters_e3_foo1(char* out_buff, param_struct_t *p_struct_var, char** retval); +uint32_t unmarshal_input_parameters_e2_foo1(uint32_t* var1, uint32_t* var2, ms_in_msg_exchange_t* ms); +uint32_t marshal_retval_and_output_parameters_e2_foo1(char** resp_buffer, size_t* resp_length, uint32_t retval); +uint32_t marshal_message_exchange_request(uint32_t target_fn_id, uint32_t msg_type, uint32_t secret_data, char** marshalled_buff, size_t* marshalled_buff_len); +uint32_t umarshal_message_exchange_request(uint32_t* inp_secret_data, ms_in_msg_exchange_t* ms); +uint32_t marshal_message_exchange_response(char** resp_buffer, size_t* resp_length, uint32_t secret_response); +uint32_t umarshal_message_exchange_response(char* out_buff, char** secret_response); + +#ifdef __cplusplus + } +#endif +#endif + diff --git a/sgx-jvm/linux-sgx/SampleCode/LocalAttestation/Enclave3/Enclave3.config.xml b/sgx-jvm/linux-sgx/SampleCode/LocalAttestation/Enclave3/Enclave3.config.xml new file mode 100644 index 0000000000..436860dd50 --- /dev/null +++ b/sgx-jvm/linux-sgx/SampleCode/LocalAttestation/Enclave3/Enclave3.config.xml @@ -0,0 +1,11 @@ + + 0 + 0 + 0x40000 + 0x100000 + 1 + 1 + 0 + 0 + 0xFFFFFFFF + diff --git a/sgx-jvm/linux-sgx/SampleCode/LocalAttestation/Enclave3/Enclave3.cpp b/sgx-jvm/linux-sgx/SampleCode/LocalAttestation/Enclave3/Enclave3.cpp new file mode 100644 index 0000000000..cc15bc4aa7 --- /dev/null +++ b/sgx-jvm/linux-sgx/SampleCode/LocalAttestation/Enclave3/Enclave3.cpp @@ -0,0 +1,366 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + + +// Enclave3.cpp : Defines the exported functions for the DLL application +#include "sgx_eid.h" +#include "Enclave3_t.h" +#include "EnclaveMessageExchange.h" +#include "error_codes.h" +#include "Utility_E3.h" +#include "sgx_thread.h" +#include "sgx_dh.h" +#include + +#define UNUSED(val) (void)(val) + +std::mapg_src_session_info_map; + +static uint32_t e3_foo1_wrapper(ms_in_msg_exchange_t *ms, size_t param_lenth, char** resp_buffer, size_t* resp_length); + +//Function pointer table containing the list of functions that the enclave exposes +const struct { + size_t num_funcs; + const void* table[1]; +} func_table = { + 1, + { + (const void*)e3_foo1_wrapper, + } +}; + +//Makes use of the sample code function to establish a secure channel with the destination enclave +uint32_t test_create_session(sgx_enclave_id_t src_enclave_id, + sgx_enclave_id_t dest_enclave_id) +{ + ATTESTATION_STATUS ke_status = SUCCESS; + dh_session_t dest_session_info; + //Core reference code function for creating a session + ke_status = create_session(src_enclave_id, dest_enclave_id,&dest_session_info); + if(ke_status == SUCCESS) + { + //Insert the session information into the map under the corresponding destination enclave id + g_src_session_info_map.insert(std::pair(dest_enclave_id, dest_session_info)); + } + memset(&dest_session_info, 0, sizeof(dh_session_t)); + return ke_status; +} + +//Makes use of the sample code function to do an enclave to enclave call (Test Vector) +uint32_t test_enclave_to_enclave_call(sgx_enclave_id_t src_enclave_id, + sgx_enclave_id_t dest_enclave_id) +{ + ATTESTATION_STATUS ke_status = SUCCESS; + external_param_struct_t *p_struct_var, struct_var; + internal_param_struct_t internal_struct_var; + uint32_t target_fn_id, msg_type; + char* marshalled_inp_buff; + size_t marshalled_inp_buff_len; + char* out_buff; + size_t out_buff_len; + dh_session_t *dest_session_info; + size_t max_out_buff_size; + char* retval; + + max_out_buff_size = 50; + msg_type = ENCLAVE_TO_ENCLAVE_CALL; + target_fn_id = 0; + internal_struct_var.ivar1 = 0x5; + internal_struct_var.ivar2 = 0x6; + struct_var.var1 = 0x3; + struct_var.var2 = 0x4; + struct_var.p_internal_struct = &internal_struct_var; + p_struct_var = &struct_var; + + size_t len_data = sizeof(struct_var) - sizeof(struct_var.p_internal_struct); + size_t len_ptr_data = sizeof(internal_struct_var); + + //Marshals the input parameters for calling function foo1 in Enclave1 into a input buffer + ke_status = marshal_input_parameters_e1_foo1(target_fn_id, msg_type, p_struct_var, len_data, + len_ptr_data, &marshalled_inp_buff, &marshalled_inp_buff_len); + + if(ke_status != SUCCESS) + { + return ke_status; + } + + //Search the map for the session information associated with the destination enclave id passed in + std::map::iterator it = g_src_session_info_map.find(dest_enclave_id); + if(it != g_src_session_info_map.end()) + { + dest_session_info = &it->second; + } + else + { + SAFE_FREE(marshalled_inp_buff); + return INVALID_SESSION; + } + + //Core Reference Code function + ke_status = send_request_receive_response(src_enclave_id, dest_enclave_id, dest_session_info, + marshalled_inp_buff, marshalled_inp_buff_len, max_out_buff_size, &out_buff, &out_buff_len); + + if(ke_status != SUCCESS) + { + SAFE_FREE(marshalled_inp_buff); + SAFE_FREE(out_buff); + return ke_status; + } + + ////Un-marshal the return value and output parameters from foo1 of Enclave1 + ke_status = unmarshal_retval_and_output_parameters_e1_foo1(out_buff, p_struct_var, &retval); + if(ke_status != SUCCESS) + { + SAFE_FREE(marshalled_inp_buff); + SAFE_FREE(out_buff); + return ke_status; + } + + SAFE_FREE(marshalled_inp_buff); + SAFE_FREE(out_buff); + SAFE_FREE(retval); + return SUCCESS; +} + +//Makes use of the sample code function to do a generic secret message exchange (Test Vector) +uint32_t test_message_exchange(sgx_enclave_id_t src_enclave_id, + sgx_enclave_id_t dest_enclave_id) +{ + ATTESTATION_STATUS ke_status = SUCCESS; + uint32_t target_fn_id, msg_type; + char* marshalled_inp_buff; + size_t marshalled_inp_buff_len; + char* out_buff; + size_t out_buff_len; + dh_session_t *dest_session_info; + size_t max_out_buff_size; + char* secret_response; + uint32_t secret_data; + + target_fn_id = 0; + msg_type = MESSAGE_EXCHANGE; + max_out_buff_size = 50; + secret_data = 0x12345678; //Secret Data here is shown only for purpose of demonstration. + + //Marshals the parameters into a buffer + ke_status = marshal_message_exchange_request(target_fn_id, msg_type, secret_data, &marshalled_inp_buff, &marshalled_inp_buff_len); + if(ke_status != SUCCESS) + { + return ke_status; + } + //Search the map for the session information associated with the destination enclave id passed in + std::map::iterator it = g_src_session_info_map.find(dest_enclave_id); + if(it != g_src_session_info_map.end()) + { + dest_session_info = &it->second; + } + else + { + SAFE_FREE(marshalled_inp_buff); + return INVALID_SESSION; + } + + //Core Reference Code function + ke_status = send_request_receive_response(src_enclave_id, dest_enclave_id, dest_session_info, marshalled_inp_buff, + marshalled_inp_buff_len, max_out_buff_size, &out_buff, &out_buff_len); + + if(ke_status != SUCCESS) + { + SAFE_FREE(marshalled_inp_buff); + SAFE_FREE(out_buff); + return ke_status; + } + //Un-marshal the secret response data + ke_status = umarshal_message_exchange_response(out_buff, &secret_response); + if(ke_status != SUCCESS) + { + SAFE_FREE(marshalled_inp_buff); + SAFE_FREE(out_buff); + return ke_status; + } + + SAFE_FREE(marshalled_inp_buff); + SAFE_FREE(out_buff); + SAFE_FREE(secret_response); + return SUCCESS; +} + + +//Makes use of the sample code function to close a current session +uint32_t test_close_session(sgx_enclave_id_t src_enclave_id, + sgx_enclave_id_t dest_enclave_id) +{ + dh_session_t dest_session_info; + ATTESTATION_STATUS ke_status = SUCCESS; + //Search the map for the session information associated with the destination enclave id passed in + std::map::iterator it = g_src_session_info_map.find(dest_enclave_id); + if(it != g_src_session_info_map.end()) + { + dest_session_info = it->second; + } + else + { + return NULL; + } + //Core reference code function for closing a session + ke_status = close_session(src_enclave_id, dest_enclave_id); + + //Erase the session information associated with the destination enclave id + g_src_session_info_map.erase(dest_enclave_id); + return ke_status; +} + +//Function that is used to verify the trust of the other enclave +//Each enclave can have its own way verifying the peer enclave identity +extern "C" uint32_t verify_peer_enclave_trust(sgx_dh_session_enclave_identity_t* peer_enclave_identity) +{ + if(!peer_enclave_identity) + { + return INVALID_PARAMETER_ERROR; + } + if(peer_enclave_identity->isv_prod_id != 0 || !(peer_enclave_identity->attributes.flags & SGX_FLAGS_INITTED)) + // || peer_enclave_identity->attributes.xfrm !=3)// || peer_enclave_identity->mr_signer != xx //TODO: To be hardcoded with values to check + { + return ENCLAVE_TRUST_ERROR; + } + else + { + return SUCCESS; + } +} + + +//Dispatch function that calls the approriate enclave function based on the function id +//Each enclave can have its own way of dispatching the calls from other enclave +extern "C" uint32_t enclave_to_enclave_call_dispatcher(char* decrypted_data, + size_t decrypted_data_length, + char** resp_buffer, + size_t* resp_length) +{ + ms_in_msg_exchange_t *ms; + uint32_t (*fn1)(ms_in_msg_exchange_t *ms, size_t, char**, size_t*); + if(!decrypted_data || !resp_length) + { + return INVALID_PARAMETER_ERROR; + } + ms = (ms_in_msg_exchange_t *)decrypted_data; + if(ms->target_fn_id >= func_table.num_funcs) + { + return INVALID_PARAMETER_ERROR; + } + fn1 = (uint32_t (*)(ms_in_msg_exchange_t*, size_t, char**, size_t*))func_table.table[ms->target_fn_id]; + return fn1(ms, decrypted_data_length, resp_buffer, resp_length); +} + +//Operates on the input secret and generates the output secret +uint32_t get_message_exchange_response(uint32_t inp_secret_data) +{ + uint32_t secret_response; + + //User should use more complex encryption method to protect their secret, below is just a simple example + secret_response = inp_secret_data & 0x11111111; + + return secret_response; + +} +//Generates the response from the request message +extern "C" uint32_t message_exchange_response_generator(char* decrypted_data, + char** resp_buffer, + size_t* resp_length) +{ + ms_in_msg_exchange_t *ms; + uint32_t inp_secret_data; + uint32_t out_secret_data; + if(!decrypted_data || !resp_length) + { + return INVALID_PARAMETER_ERROR; + } + ms = (ms_in_msg_exchange_t *)decrypted_data; + + if(umarshal_message_exchange_request(&inp_secret_data,ms) != SUCCESS) + return ATTESTATION_ERROR; + + out_secret_data = get_message_exchange_response(inp_secret_data); + + if(marshal_message_exchange_response(resp_buffer, resp_length, out_secret_data) != SUCCESS) + return MALLOC_ERROR; + + return SUCCESS; + +} + + +static uint32_t e3_foo1(param_struct_t *p_struct_var) +{ + if(!p_struct_var) + { + return INVALID_PARAMETER_ERROR; + } + p_struct_var->var1++; + p_struct_var->var2++; + + return(p_struct_var->var1 * p_struct_var->var2); +} + +//Function which is executed on request from the source enclave +static uint32_t e3_foo1_wrapper(ms_in_msg_exchange_t *ms, + size_t param_lenth, + char** resp_buffer, + size_t* resp_length) +{ + UNUSED(param_lenth); + + uint32_t ret; + param_struct_t *p_struct_var; + if(!ms || !resp_length) + { + return INVALID_PARAMETER_ERROR; + } + p_struct_var = (param_struct_t*)malloc(sizeof(param_struct_t)); + if(!p_struct_var) + return MALLOC_ERROR; + + if(unmarshal_input_parameters_e3_foo1(p_struct_var, ms) != SUCCESS) + { + SAFE_FREE(p_struct_var); + return ATTESTATION_ERROR; + } + + ret = e3_foo1(p_struct_var); + + if(marshal_retval_and_output_parameters_e3_foo1(resp_buffer, resp_length, ret, p_struct_var) != SUCCESS) + { + SAFE_FREE(p_struct_var); + return MALLOC_ERROR; + } + SAFE_FREE(p_struct_var); + return SUCCESS; +} diff --git a/sgx-jvm/linux-sgx/SampleCode/LocalAttestation/Enclave3/Enclave3.edl b/sgx-jvm/linux-sgx/SampleCode/LocalAttestation/Enclave3/Enclave3.edl new file mode 100644 index 0000000000..7584ee7945 --- /dev/null +++ b/sgx-jvm/linux-sgx/SampleCode/LocalAttestation/Enclave3/Enclave3.edl @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +enclave { + include "sgx_eid.h" + from "../LocalAttestationCode/LocalAttestationCode.edl" import *; + from "sgx_tstdc.edl" import *; + trusted{ + public uint32_t test_create_session(sgx_enclave_id_t src_enclave_id, sgx_enclave_id_t dest_enclave_id); + public uint32_t test_enclave_to_enclave_call(sgx_enclave_id_t src_enclave_id, sgx_enclave_id_t dest_enclave_id); + public uint32_t test_message_exchange(sgx_enclave_id_t src_enclave_id, sgx_enclave_id_t dest_enclave_id); + public uint32_t test_close_session(sgx_enclave_id_t src_enclave_id, sgx_enclave_id_t dest_enclave_id); + }; +}; diff --git a/sgx-jvm/linux-sgx/SampleCode/LocalAttestation/Enclave3/Enclave3_private.pem b/sgx-jvm/linux-sgx/SampleCode/LocalAttestation/Enclave3/Enclave3_private.pem new file mode 100644 index 0000000000..b8ace89eb3 --- /dev/null +++ b/sgx-jvm/linux-sgx/SampleCode/LocalAttestation/Enclave3/Enclave3_private.pem @@ -0,0 +1,39 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIG4wIBAAKCAYEA0MvI9NpdP4GEqCvtlJQv00OybzTXzxBhPu/257VYt9cYw/ph +BN1WRyxBBcrZs15xmcvlb3xNmFGWs4w5oUgrFBNgi6g+CUOCsj0cM8xw7P/y3K0H +XaZUf+T3CXCp8NvlkZHzfdWAFA5lGGR9g6kmuk7SojE3h87Zm1KjPU/PvAe+BaMU +trlRr4gPNVnu19Vho60xwuswPxfl/pBFUIk7qWEUR3l2hiqWMeLgf3Ays/WSnkXA +uijwPt5g0hxsgIlyDrI3jKbf0zkFB56jvPwSykfU8aw4Gkbo5qSZxUAKnwH2L8Uf +yM6inBaaYtM79icRwsu45Yt6X0GAt7CSb/1TKBrnm5exmK1sug3YSQ/YuK1FYawU +vIaDD0YfzOndTNVBewA+Hr5xNPvqGJoRKHuGbyu2lI9jrKYpVxQWsmx38wnxF6kE +zX6N4m7KZiLeLpDdBVQtLuOzIdIE4wT3t/ckeqElxO/1Ut9bj765GcTTrYwMKHRw +ukWIH7ZtHtAjj0KzAgEDAoIBgQCLMoX4kZN/q63Fcp5jDXU3gnb0zeU0tZYp9U9F +I5B6j2XX/ECt6OQvctYD3JEiPvZmh+5KUt5li7nNCCZrhXINYkBdGtQGLQHMKL13 +3aCd//c9yK+TxDhVQ09boHFLPUO2YUz+jlVitENlmFOtG28m3zcWy3paieZnjGzT +iop9Wn6ubLh50OEfsAojkUnlOOvCc3aB8iAqD+6ptYOLBifGQLgvpk8EHGQhQer/ +oCHNTmG+2SsmxfV/Pus2vZ2rBkrUbZU0hwrnvKOIPhnt3Qwtmx9xsC67jF+MpWko +UisJXC27FAGz2gpIGMhBp35HEppwG9hhCuMQdK2g62bvweyr1tC4qOVdQrKvhksN +r6CMjS9eSXvmWdF7lU4oxStN0V56/LICSIsLbggUaxTPKhAVEgfTSqwEJoQuFA3Q +4GmgTydPhcRH1L/lhbWJqZQm7V1Gt+5i5J6iATD32uNQQ2iZi5GsUhr+jZC+WlE5 +6lS813cRNiaK52HIk62bG7IXOksCgcEA+6RxZhQ5GaCPYZNsk7TqxqsKopXKoYAr +2R4KWuexJTd+1kcNMk0ETX8OSgpY2cYL2uPFWmdutxPpLfpr8S2u92Da/Wxs70Ti +QSb0426ybTmnS5L7nOnGOHiddXILhW175liAszTeoR7nQ6vpr9YjfcnrXiB8bKIm +akft2DQoxrBPzEe9tA8gfkyDTsSG2j7kncSbvYRtkKcJOmmypotVU6uhRPSrSXCc +J59uBQkg6Bk4CKA1mz8ctG07MluFY0/ZAoHBANRpZlfIFl39gFmuEER7lb80GySO +J190LbqOca3dGOvAMsDgEAi6juJyX7ZNpbHFHj++LvmTtw9+kxhVDBcswS7304kt +7J2EfnGdctEZtXif1wiq30YWAp1tjRpQENKtt9wssmgcwgK39rZNiEHmStHGv3l+ +5TnKPKeuFCDnsLvi5lQYoK2wTYvZtsjf+Rnt7H17q90IV54pMjTS8BkGskCkKf2A +IYuaZkqX0T3cM6ovoYYDAU6rWL5rrYPLEwkbawKBwQCnwvZEDXtmawpBDPMNI0cv +HLHBuTHBAB07aVw8mnYYz6nkL14hiK2I/17cBuXmhAfnQoORmknPYptz/Ef2HnSk +6zyo8vNKLewrb03s9Hbze8TdDKe98S7QUGj49rJY86fu5asiIz8WFJotHUZ1OWz+ +hpzpav2dwW7xhUk6zXCEdYqIL9PNX2r+3azfLa88Ke2+gxJ+WEkLGgYm8SHEXOON +HRYt+HIw9b1vv56uBhXwENAFwCO81L3Nnid2565CNTsCgcEAjZuZj9q5k/5VkR61 +gv0Of3gSGF7E6k1z0bRLyT4QnSrMgJVgBdG0lvbqeYkZIS4UKn7J+7fPX6m3ZY4I +D3MrdKU3sMlIaQL+9mj3NhEjpb/ksHHqLrlXE55eEYq14cklPXMhmr3WrHqkeYkF +gUQx4S8qUP9De9wob8liwJp10pdEOBBrHnWJB+Z52z/7Zp6dqP0dPgWPvsYheIyg +EK8hgG1xU6rBB7xEMbqLfpLNHB/BBAIA3xzl1EfJAodiBhJHAoHAeTS2znDHYayI +TvK86tBAPVORiBVTSdRUONdGF3dipo24hyeyrI5MtiOoMc3sKWXnSTkDQWa3WiPx +qStBmmO/SbGTuz7T6+oOwGeMiYzYBe87Ayn8Y0KYYshFikieJbGusHjUlIGmCVPy +UHrDMYGwFGUGBwW47gBsnZa+YPHtxWCPDe/U80et2Trx0RXJJQPmupAVMSiJWObI +9k5gRU+xDqkHanyD1gkGGwhFTUNX94EJEOdQEWw3hxLnVtePoke/ +-----END RSA PRIVATE KEY----- diff --git a/sgx-jvm/linux-sgx/SampleCode/LocalAttestation/Enclave3/Utility_E3.cpp b/sgx-jvm/linux-sgx/SampleCode/LocalAttestation/Enclave3/Utility_E3.cpp new file mode 100644 index 0000000000..97cf9b0ce6 --- /dev/null +++ b/sgx-jvm/linux-sgx/SampleCode/LocalAttestation/Enclave3/Utility_E3.cpp @@ -0,0 +1,223 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "sgx_eid.h" +#include "EnclaveMessageExchange.h" +#include "error_codes.h" +#include "Utility_E3.h" +#include "stdlib.h" +#include "string.h" + +uint32_t marshal_input_parameters_e1_foo1(uint32_t target_fn_id, uint32_t msg_type, external_param_struct_t *p_struct_var, size_t len_data, size_t len_ptr_data, char** marshalled_buff, size_t* marshalled_buff_len) +{ + ms_in_msg_exchange_t *ms; + size_t param_len, ms_len; + char *temp_buff; + int* addr; + char* struct_data; + if(!p_struct_var || !marshalled_buff_len) + return INVALID_PARAMETER_ERROR; + struct_data = (char*)p_struct_var; + temp_buff = (char*)malloc(len_data + len_ptr_data); + if(!temp_buff) + return MALLOC_ERROR; + memcpy(temp_buff, struct_data, len_data); + addr = *(int **)(struct_data + len_data); + memcpy(temp_buff + len_data, addr, len_ptr_data); //can be optimized + param_len = len_data + len_ptr_data; + ms_len = sizeof(ms_in_msg_exchange_t) + param_len; + ms = (ms_in_msg_exchange_t *)malloc(ms_len); + if(!ms) + { + SAFE_FREE(temp_buff); + return MALLOC_ERROR; + } + ms->msg_type = msg_type; + ms->target_fn_id = target_fn_id; + ms->inparam_buff_len = (uint32_t)param_len; + memcpy(&ms->inparam_buff, temp_buff, param_len); + *marshalled_buff = (char*)ms; + *marshalled_buff_len = ms_len; + + SAFE_FREE(temp_buff); + return SUCCESS; +} + +uint32_t marshal_retval_and_output_parameters_e3_foo1(char** resp_buffer, size_t* resp_length, uint32_t retval, param_struct_t *p_struct_var) +{ + ms_out_msg_exchange_t *ms; + size_t ret_param_len, ms_len; + char *temp_buff; + size_t retval_len; + if(!resp_length || !p_struct_var) + return INVALID_PARAMETER_ERROR; + retval_len = sizeof(retval); + ret_param_len = sizeof(retval) + sizeof(param_struct_t); + temp_buff = (char*)malloc(ret_param_len); + if(!temp_buff) + return MALLOC_ERROR; + memcpy(temp_buff, &retval, sizeof(retval)); + memcpy(temp_buff + sizeof(retval), p_struct_var, sizeof(param_struct_t)); + ms_len = sizeof(ms_out_msg_exchange_t) + ret_param_len; + ms = (ms_out_msg_exchange_t *)malloc(ms_len); + if(!ms) + { + SAFE_FREE(temp_buff); + return MALLOC_ERROR; + } + ms->retval_len = (uint32_t)retval_len; + ms->ret_outparam_buff_len = (uint32_t)ret_param_len; + memcpy(&ms->ret_outparam_buff, temp_buff, ret_param_len); + *resp_buffer = (char*)ms; + *resp_length = ms_len; + SAFE_FREE(temp_buff); + return SUCCESS; +} + +uint32_t unmarshal_input_parameters_e3_foo1(param_struct_t *pstruct, ms_in_msg_exchange_t* ms) +{ + char* buff; + size_t len; + if(!pstruct || !ms) + return INVALID_PARAMETER_ERROR; + buff = ms->inparam_buff; + len = ms->inparam_buff_len; + + if(len != (sizeof(pstruct->var1) + sizeof(pstruct->var2))) + return ATTESTATION_ERROR; + + memcpy(&pstruct->var1, buff, sizeof(pstruct->var1)); + memcpy(&pstruct->var2, buff + sizeof(pstruct->var1), sizeof(pstruct->var2)); + + return SUCCESS; +} + + +uint32_t unmarshal_retval_and_output_parameters_e1_foo1(char* out_buff, external_param_struct_t *p_struct_var, char** retval) +{ + size_t retval_len; + ms_out_msg_exchange_t *ms; + if(!out_buff || !p_struct_var) + return INVALID_PARAMETER_ERROR; + ms = (ms_out_msg_exchange_t *)out_buff; + retval_len = ms->retval_len; + *retval = (char*)malloc(retval_len); + if(!*retval) + { + return MALLOC_ERROR; + } + memcpy(*retval, ms->ret_outparam_buff, retval_len); + memcpy(&p_struct_var->var1, (ms->ret_outparam_buff) + retval_len, sizeof(p_struct_var->var1)); + memcpy(&p_struct_var->var2, (ms->ret_outparam_buff) + retval_len + sizeof(p_struct_var->var1), sizeof(p_struct_var->var2)); + memcpy(&p_struct_var->p_internal_struct->ivar1, (ms->ret_outparam_buff) + retval_len + sizeof(p_struct_var->var1)+ sizeof(p_struct_var->var2), sizeof(p_struct_var->p_internal_struct->ivar1)); + memcpy(&p_struct_var->p_internal_struct->ivar2, (ms->ret_outparam_buff) + retval_len + sizeof(p_struct_var->var1)+ sizeof(p_struct_var->var2) + sizeof(p_struct_var->p_internal_struct->ivar1), sizeof(p_struct_var->p_internal_struct->ivar2)); + return SUCCESS; +} + + +uint32_t marshal_message_exchange_request(uint32_t target_fn_id, uint32_t msg_type, uint32_t secret_data, char** marshalled_buff, size_t* marshalled_buff_len) +{ + ms_in_msg_exchange_t *ms; + size_t secret_data_len, ms_len; + if(!marshalled_buff_len) + return INVALID_PARAMETER_ERROR; + secret_data_len = sizeof(secret_data); + ms_len = sizeof(ms_in_msg_exchange_t) + secret_data_len; + ms = (ms_in_msg_exchange_t *)malloc(ms_len); + if(!ms) + return MALLOC_ERROR; + + ms->msg_type = msg_type; + ms->target_fn_id = target_fn_id; + ms->inparam_buff_len = (uint32_t)secret_data_len; + memcpy(&ms->inparam_buff, &secret_data, secret_data_len); + + *marshalled_buff = (char*)ms; + *marshalled_buff_len = ms_len; + return SUCCESS; +} + +uint32_t umarshal_message_exchange_request(uint32_t* inp_secret_data, ms_in_msg_exchange_t* ms) +{ + char* buff; + size_t len; + if(!inp_secret_data || !ms) + return INVALID_PARAMETER_ERROR; + buff = ms->inparam_buff; + len = ms->inparam_buff_len; + + if(len != sizeof(uint32_t)) + return ATTESTATION_ERROR; + + memcpy(inp_secret_data, buff, sizeof(uint32_t)); + + return SUCCESS; +} + +uint32_t marshal_message_exchange_response(char** resp_buffer, size_t* resp_length, uint32_t secret_response) +{ + ms_out_msg_exchange_t *ms; + size_t secret_response_len, ms_len; + size_t retval_len, ret_param_len; + if(!resp_length) + return INVALID_PARAMETER_ERROR; + secret_response_len = sizeof(secret_response); + retval_len = secret_response_len; + ret_param_len = secret_response_len; + ms_len = sizeof(ms_out_msg_exchange_t) + ret_param_len; + ms = (ms_out_msg_exchange_t *)malloc(ms_len); + if(!ms) + return MALLOC_ERROR; + ms->retval_len = (uint32_t)retval_len; + ms->ret_outparam_buff_len = (uint32_t)ret_param_len; + memcpy(&ms->ret_outparam_buff, &secret_response, secret_response_len); + *resp_buffer = (char*)ms; + *resp_length = ms_len; + return SUCCESS; +} + +uint32_t umarshal_message_exchange_response(char* out_buff, char** secret_response) +{ + size_t retval_len; + ms_out_msg_exchange_t *ms; + if(!out_buff) + return INVALID_PARAMETER_ERROR; + ms = (ms_out_msg_exchange_t *)out_buff; + retval_len = ms->retval_len; + *secret_response = (char*)malloc(retval_len); + if(!*secret_response) + { + return MALLOC_ERROR; + } + memcpy(*secret_response, ms->ret_outparam_buff, retval_len); + return SUCCESS; +} + diff --git a/sgx-jvm/linux-sgx/SampleCode/LocalAttestation/Enclave3/Utility_E3.h b/sgx-jvm/linux-sgx/SampleCode/LocalAttestation/Enclave3/Utility_E3.h new file mode 100644 index 0000000000..83ba2d6f65 --- /dev/null +++ b/sgx-jvm/linux-sgx/SampleCode/LocalAttestation/Enclave3/Utility_E3.h @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef UTILITY_E3_H__ +#define UTILITY_E3_H__ + +#include "stdint.h" + + +typedef struct _internal_param_struct_t +{ + uint32_t ivar1; + uint32_t ivar2; +}internal_param_struct_t; + +typedef struct _external_param_struct_t +{ + uint32_t var1; + uint32_t var2; + internal_param_struct_t *p_internal_struct; +}external_param_struct_t; + +typedef struct _param_struct_t +{ + uint32_t var1; + uint32_t var2; +}param_struct_t; + +#ifdef __cplusplus +extern "C" { +#endif + +uint32_t marshal_input_parameters_e1_foo1(uint32_t target_fn_id, uint32_t msg_type, external_param_struct_t *p_struct_var, size_t len_data, size_t len_ptr_data, char** marshalled_buff, size_t* marshalled_buff_len); +uint32_t unmarshal_retval_and_output_parameters_e1_foo1(char* out_buff, external_param_struct_t *p_struct_var, char** retval); +uint32_t unmarshal_input_parameters_e3_foo1(param_struct_t *pstruct, ms_in_msg_exchange_t* ms); +uint32_t marshal_retval_and_output_parameters_e3_foo1(char** resp_buffer, size_t* resp_length, uint32_t retval, param_struct_t *p_struct_var); +uint32_t marshal_message_exchange_request(uint32_t target_fn_id, uint32_t msg_type, uint32_t secret_data, char** marshalled_buff, size_t* marshalled_buff_len); +uint32_t umarshal_message_exchange_request(uint32_t* inp_secret_data, ms_in_msg_exchange_t* ms); +uint32_t marshal_message_exchange_response(char** resp_buffer, size_t* resp_length, uint32_t secret_response); +uint32_t umarshal_message_exchange_response(char* out_buff, char** secret_response); + +#ifdef __cplusplus + } +#endif +#endif diff --git a/sgx-jvm/linux-sgx/SampleCode/LocalAttestation/Include/dh_session_protocol.h b/sgx-jvm/linux-sgx/SampleCode/LocalAttestation/Include/dh_session_protocol.h new file mode 100644 index 0000000000..bc92ee4d6c --- /dev/null +++ b/sgx-jvm/linux-sgx/SampleCode/LocalAttestation/Include/dh_session_protocol.h @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef _DH_SESSION_PROROCOL_H +#define _DH_SESSION_PROROCOL_H + +#include "sgx_ecp_types.h" +#include "sgx_key.h" +#include "sgx_report.h" +#include "sgx_attributes.h" + +#define NONCE_SIZE 16 +#define MAC_SIZE 16 + +#define MSG_BUF_LEN sizeof(ec_pub_t)*2 +#define MSG_HASH_SZ 32 + + +//Session information structure +typedef struct _la_dh_session_t +{ + uint32_t session_id; //Identifies the current session + uint32_t status; //Indicates session is in progress, active or closed + union + { + struct + { + sgx_dh_session_t dh_session; + }in_progress; + + struct + { + sgx_key_128bit_t AEK; //Session Key + uint32_t counter; //Used to store Message Sequence Number + }active; + }; +} dh_session_t; + + +#endif diff --git a/sgx-jvm/linux-sgx/SampleCode/LocalAttestation/LocalAttestationCode/EnclaveMessageExchange.cpp b/sgx-jvm/linux-sgx/SampleCode/LocalAttestation/LocalAttestationCode/EnclaveMessageExchange.cpp new file mode 100644 index 0000000000..a32e3e2197 --- /dev/null +++ b/sgx-jvm/linux-sgx/SampleCode/LocalAttestation/LocalAttestationCode/EnclaveMessageExchange.cpp @@ -0,0 +1,721 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + + +#include "sgx_trts.h" +#include "sgx_utils.h" +#include "EnclaveMessageExchange.h" +#include "sgx_eid.h" +#include "error_codes.h" +#include "sgx_ecp_types.h" +#include "sgx_thread.h" +#include +#include "dh_session_protocol.h" +#include "sgx_dh.h" +#include "sgx_tcrypto.h" +#include "LocalAttestationCode_t.h" + +#ifdef __cplusplus +extern "C" { +#endif + +uint32_t enclave_to_enclave_call_dispatcher(char* decrypted_data, size_t decrypted_data_length, char** resp_buffer, size_t* resp_length); +uint32_t message_exchange_response_generator(char* decrypted_data, char** resp_buffer, size_t* resp_length); +uint32_t verify_peer_enclave_trust(sgx_dh_session_enclave_identity_t* peer_enclave_identity); + +#ifdef __cplusplus +} +#endif + +#define MAX_SESSION_COUNT 16 + +//number of open sessions +uint32_t g_session_count = 0; + +ATTESTATION_STATUS generate_session_id(uint32_t *session_id); +ATTESTATION_STATUS end_session(sgx_enclave_id_t src_enclave_id); + +//Array of open session ids +session_id_tracker_t *g_session_id_tracker[MAX_SESSION_COUNT]; + +//Map between the source enclave id and the session information associated with that particular session +std::mapg_dest_session_info_map; + +//Create a session with the destination enclave +ATTESTATION_STATUS create_session(sgx_enclave_id_t src_enclave_id, + sgx_enclave_id_t dest_enclave_id, + dh_session_t *session_info) +{ + sgx_dh_msg1_t dh_msg1; //Diffie-Hellman Message 1 + sgx_key_128bit_t dh_aek; // Session Key + sgx_dh_msg2_t dh_msg2; //Diffie-Hellman Message 2 + sgx_dh_msg3_t dh_msg3; //Diffie-Hellman Message 3 + uint32_t session_id; + uint32_t retstatus; + sgx_status_t status = SGX_SUCCESS; + sgx_dh_session_t sgx_dh_session; + sgx_dh_session_enclave_identity_t responder_identity; + + if(!session_info) + { + return INVALID_PARAMETER_ERROR; + } + + memset(&dh_aek,0, sizeof(sgx_key_128bit_t)); + memset(&dh_msg1, 0, sizeof(sgx_dh_msg1_t)); + memset(&dh_msg2, 0, sizeof(sgx_dh_msg2_t)); + memset(&dh_msg3, 0, sizeof(sgx_dh_msg3_t)); + memset(session_info, 0, sizeof(dh_session_t)); + + //Intialize the session as a session initiator + status = sgx_dh_init_session(SGX_DH_SESSION_INITIATOR, &sgx_dh_session); + if(SGX_SUCCESS != status) + { + return status; + } + + //Ocall to request for a session with the destination enclave and obtain session id and Message 1 if successful + status = session_request_ocall(&retstatus, src_enclave_id, dest_enclave_id, &dh_msg1, &session_id); + if (status == SGX_SUCCESS) + { + if ((ATTESTATION_STATUS)retstatus != SUCCESS) + return ((ATTESTATION_STATUS)retstatus); + } + else + { + return ATTESTATION_SE_ERROR; + } + //Process the message 1 obtained from desination enclave and generate message 2 + status = sgx_dh_initiator_proc_msg1(&dh_msg1, &dh_msg2, &sgx_dh_session); + if(SGX_SUCCESS != status) + { + return status; + } + + //Send Message 2 to Destination Enclave and get Message 3 in return + status = exchange_report_ocall(&retstatus, src_enclave_id, dest_enclave_id, &dh_msg2, &dh_msg3, session_id); + if (status == SGX_SUCCESS) + { + if ((ATTESTATION_STATUS)retstatus != SUCCESS) + return ((ATTESTATION_STATUS)retstatus); + } + else + { + return ATTESTATION_SE_ERROR; + } + + //Process Message 3 obtained from the destination enclave + status = sgx_dh_initiator_proc_msg3(&dh_msg3, &sgx_dh_session, &dh_aek, &responder_identity); + if(SGX_SUCCESS != status) + { + return status; + } + + // Verify the identity of the destination enclave + if(verify_peer_enclave_trust(&responder_identity) != SUCCESS) + { + return INVALID_SESSION; + } + + memcpy(session_info->active.AEK, &dh_aek, sizeof(sgx_key_128bit_t)); + session_info->session_id = session_id; + session_info->active.counter = 0; + session_info->status = ACTIVE; + memset(&dh_aek,0, sizeof(sgx_key_128bit_t)); + return status; +} + +//Handle the request from Source Enclave for a session +ATTESTATION_STATUS session_request(sgx_enclave_id_t src_enclave_id, + sgx_dh_msg1_t *dh_msg1, + uint32_t *session_id ) +{ + dh_session_t session_info; + sgx_dh_session_t sgx_dh_session; + sgx_status_t status = SGX_SUCCESS; + + if(!session_id || !dh_msg1) + { + return INVALID_PARAMETER_ERROR; + } + //Intialize the session as a session responder + status = sgx_dh_init_session(SGX_DH_SESSION_RESPONDER, &sgx_dh_session); + if(SGX_SUCCESS != status) + { + return status; + } + + //get a new SessionID + if ((status = (sgx_status_t)generate_session_id(session_id)) != SUCCESS) + return status; //no more sessions available + + //Allocate memory for the session id tracker + g_session_id_tracker[*session_id] = (session_id_tracker_t *)malloc(sizeof(session_id_tracker_t)); + if(!g_session_id_tracker[*session_id]) + { + return MALLOC_ERROR; + } + + memset(g_session_id_tracker[*session_id], 0, sizeof(session_id_tracker_t)); + g_session_id_tracker[*session_id]->session_id = *session_id; + session_info.status = IN_PROGRESS; + + //Generate Message1 that will be returned to Source Enclave + status = sgx_dh_responder_gen_msg1((sgx_dh_msg1_t*)dh_msg1, &sgx_dh_session); + if(SGX_SUCCESS != status) + { + SAFE_FREE(g_session_id_tracker[*session_id]); + return status; + } + memcpy(&session_info.in_progress.dh_session, &sgx_dh_session, sizeof(sgx_dh_session_t)); + //Store the session information under the correspoding source enlave id key + g_dest_session_info_map.insert(std::pair(src_enclave_id, session_info)); + + return status; +} + +//Verify Message 2, generate Message3 and exchange Message 3 with Source Enclave +ATTESTATION_STATUS exchange_report(sgx_enclave_id_t src_enclave_id, + sgx_dh_msg2_t *dh_msg2, + sgx_dh_msg3_t *dh_msg3, + uint32_t session_id) +{ + + sgx_key_128bit_t dh_aek; // Session key + dh_session_t *session_info; + ATTESTATION_STATUS status = SUCCESS; + sgx_dh_session_t sgx_dh_session; + sgx_dh_session_enclave_identity_t initiator_identity; + + if(!dh_msg2 || !dh_msg3) + { + return INVALID_PARAMETER_ERROR; + } + + memset(&dh_aek,0, sizeof(sgx_key_128bit_t)); + do + { + //Retreive the session information for the corresponding source enclave id + std::map::iterator it = g_dest_session_info_map.find(src_enclave_id); + if(it != g_dest_session_info_map.end()) + { + session_info = &it->second; + } + else + { + status = INVALID_SESSION; + break; + } + + if(session_info->status != IN_PROGRESS) + { + status = INVALID_SESSION; + break; + } + + memcpy(&sgx_dh_session, &session_info->in_progress.dh_session, sizeof(sgx_dh_session_t)); + + dh_msg3->msg3_body.additional_prop_length = 0; + //Process message 2 from source enclave and obtain message 3 + sgx_status_t se_ret = sgx_dh_responder_proc_msg2(dh_msg2, + dh_msg3, + &sgx_dh_session, + &dh_aek, + &initiator_identity); + if(SGX_SUCCESS != se_ret) + { + status = se_ret; + break; + } + + //Verify source enclave's trust + if(verify_peer_enclave_trust(&initiator_identity) != SUCCESS) + { + return INVALID_SESSION; + } + + //save the session ID, status and initialize the session nonce + session_info->session_id = session_id; + session_info->status = ACTIVE; + session_info->active.counter = 0; + memcpy(session_info->active.AEK, &dh_aek, sizeof(sgx_key_128bit_t)); + memset(&dh_aek,0, sizeof(sgx_key_128bit_t)); + g_session_count++; + }while(0); + + if(status != SUCCESS) + { + end_session(src_enclave_id); + } + + return status; +} + +//Request for the response size, send the request message to the destination enclave and receive the response message back +ATTESTATION_STATUS send_request_receive_response(sgx_enclave_id_t src_enclave_id, + sgx_enclave_id_t dest_enclave_id, + dh_session_t *session_info, + char *inp_buff, + size_t inp_buff_len, + size_t max_out_buff_size, + char **out_buff, + size_t* out_buff_len) +{ + const uint8_t* plaintext; + uint32_t plaintext_length; + sgx_status_t status; + uint32_t retstatus; + secure_message_t* req_message; + secure_message_t* resp_message; + uint8_t *decrypted_data; + uint32_t decrypted_data_length; + uint32_t plain_text_offset; + uint8_t l_tag[TAG_SIZE]; + size_t max_resp_message_length; + plaintext = (const uint8_t*)(" "); + plaintext_length = 0; + + if(!session_info || !inp_buff) + { + return INVALID_PARAMETER_ERROR; + } + //Check if the nonce for the session has not exceeded 2^32-2 if so end session and start a new session + if(session_info->active.counter == ((uint32_t) - 2)) + { + close_session(src_enclave_id, dest_enclave_id); + create_session(src_enclave_id, dest_enclave_id, session_info); + } + + //Allocate memory for the AES-GCM request message + req_message = (secure_message_t*)malloc(sizeof(secure_message_t)+ inp_buff_len); + if(!req_message) + { + return MALLOC_ERROR; + } + + memset(req_message,0,sizeof(secure_message_t)+ inp_buff_len); + const uint32_t data2encrypt_length = (uint32_t)inp_buff_len; + //Set the payload size to data to encrypt length + req_message->message_aes_gcm_data.payload_size = data2encrypt_length; + + //Use the session nonce as the payload IV + memcpy(req_message->message_aes_gcm_data.reserved,&session_info->active.counter,sizeof(session_info->active.counter)); + + //Set the session ID of the message to the current session id + req_message->session_id = session_info->session_id; + + //Prepare the request message with the encrypted payload + status = sgx_rijndael128GCM_encrypt(&session_info->active.AEK, (uint8_t*)inp_buff, data2encrypt_length, + reinterpret_cast(&(req_message->message_aes_gcm_data.payload)), + reinterpret_cast(&(req_message->message_aes_gcm_data.reserved)), + sizeof(req_message->message_aes_gcm_data.reserved), plaintext, plaintext_length, + &(req_message->message_aes_gcm_data.payload_tag)); + + if(SGX_SUCCESS != status) + { + SAFE_FREE(req_message); + return status; + } + + //Allocate memory for the response payload to be copied + *out_buff = (char*)malloc(max_out_buff_size); + if(!*out_buff) + { + SAFE_FREE(req_message); + return MALLOC_ERROR; + } + + memset(*out_buff, 0, max_out_buff_size); + + //Allocate memory for the response message + resp_message = (secure_message_t*)malloc(sizeof(secure_message_t)+ max_out_buff_size); + if(!resp_message) + { + SAFE_FREE(req_message); + return MALLOC_ERROR; + } + + memset(resp_message, 0, sizeof(secure_message_t)+ max_out_buff_size); + + //Ocall to send the request to the Destination Enclave and get the response message back + status = send_request_ocall(&retstatus, src_enclave_id, dest_enclave_id, req_message, + (sizeof(secure_message_t)+ inp_buff_len), max_out_buff_size, + resp_message, (sizeof(secure_message_t)+ max_out_buff_size)); + if (status == SGX_SUCCESS) + { + if ((ATTESTATION_STATUS)retstatus != SUCCESS) + { + SAFE_FREE(req_message); + SAFE_FREE(resp_message); + return ((ATTESTATION_STATUS)retstatus); + } + } + else + { + SAFE_FREE(req_message); + SAFE_FREE(resp_message); + return ATTESTATION_SE_ERROR; + } + + max_resp_message_length = sizeof(secure_message_t)+ max_out_buff_size; + + if(sizeof(resp_message) > max_resp_message_length) + { + SAFE_FREE(req_message); + SAFE_FREE(resp_message); + return INVALID_PARAMETER_ERROR; + } + + //Code to process the response message from the Destination Enclave + + decrypted_data_length = resp_message->message_aes_gcm_data.payload_size; + plain_text_offset = decrypted_data_length; + decrypted_data = (uint8_t*)malloc(decrypted_data_length); + if(!decrypted_data) + { + SAFE_FREE(req_message); + SAFE_FREE(resp_message); + return MALLOC_ERROR; + } + memset(&l_tag, 0, 16); + + memset(decrypted_data, 0, decrypted_data_length); + + //Decrypt the response message payload + status = sgx_rijndael128GCM_decrypt(&session_info->active.AEK, resp_message->message_aes_gcm_data.payload, + decrypted_data_length, decrypted_data, + reinterpret_cast(&(resp_message->message_aes_gcm_data.reserved)), + sizeof(resp_message->message_aes_gcm_data.reserved), &(resp_message->message_aes_gcm_data.payload[plain_text_offset]), plaintext_length, + &resp_message->message_aes_gcm_data.payload_tag); + + if(SGX_SUCCESS != status) + { + SAFE_FREE(req_message); + SAFE_FREE(decrypted_data); + SAFE_FREE(resp_message); + return status; + } + + // Verify if the nonce obtained in the response is equal to the session nonce + 1 (Prevents replay attacks) + if(*(resp_message->message_aes_gcm_data.reserved) != (session_info->active.counter + 1 )) + { + SAFE_FREE(req_message); + SAFE_FREE(resp_message); + SAFE_FREE(decrypted_data); + return INVALID_PARAMETER_ERROR; + } + + //Update the value of the session nonce in the source enclave + session_info->active.counter = session_info->active.counter + 1; + + memcpy(out_buff_len, &decrypted_data_length, sizeof(decrypted_data_length)); + memcpy(*out_buff, decrypted_data, decrypted_data_length); + + SAFE_FREE(decrypted_data); + SAFE_FREE(req_message); + SAFE_FREE(resp_message); + return SUCCESS; + + +} + +//Process the request from the Source enclave and send the response message back to the Source enclave +ATTESTATION_STATUS generate_response(sgx_enclave_id_t src_enclave_id, + secure_message_t* req_message, + size_t req_message_size, + size_t max_payload_size, + secure_message_t* resp_message, + size_t resp_message_size) +{ + const uint8_t* plaintext; + uint32_t plaintext_length; + uint8_t *decrypted_data; + uint32_t decrypted_data_length; + uint32_t plain_text_offset; + ms_in_msg_exchange_t * ms; + size_t resp_data_length; + size_t resp_message_calc_size; + char* resp_data; + uint8_t l_tag[TAG_SIZE]; + size_t header_size, expected_payload_size; + dh_session_t *session_info; + secure_message_t* temp_resp_message; + uint32_t ret; + sgx_status_t status; + + plaintext = (const uint8_t*)(" "); + plaintext_length = 0; + + if(!req_message || !resp_message) + { + return INVALID_PARAMETER_ERROR; + } + + //Get the session information from the map corresponding to the source enclave id + std::map::iterator it = g_dest_session_info_map.find(src_enclave_id); + if(it != g_dest_session_info_map.end()) + { + session_info = &it->second; + } + else + { + return INVALID_SESSION; + } + + if(session_info->status != ACTIVE) + { + return INVALID_SESSION; + } + + //Set the decrypted data length to the payload size obtained from the message + decrypted_data_length = req_message->message_aes_gcm_data.payload_size; + + header_size = sizeof(secure_message_t); + expected_payload_size = req_message_size - header_size; + + //Verify the size of the payload + if(expected_payload_size != decrypted_data_length) + return INVALID_PARAMETER_ERROR; + + memset(&l_tag, 0, 16); + plain_text_offset = decrypted_data_length; + decrypted_data = (uint8_t*)malloc(decrypted_data_length); + if(!decrypted_data) + { + return MALLOC_ERROR; + } + + memset(decrypted_data, 0, decrypted_data_length); + + //Decrypt the request message payload from source enclave + status = sgx_rijndael128GCM_decrypt(&session_info->active.AEK, req_message->message_aes_gcm_data.payload, + decrypted_data_length, decrypted_data, + reinterpret_cast(&(req_message->message_aes_gcm_data.reserved)), + sizeof(req_message->message_aes_gcm_data.reserved), &(req_message->message_aes_gcm_data.payload[plain_text_offset]), plaintext_length, + &req_message->message_aes_gcm_data.payload_tag); + + if(SGX_SUCCESS != status) + { + SAFE_FREE(decrypted_data); + return status; + } + + //Casting the decrypted data to the marshaling structure type to obtain type of request (generic message exchange/enclave to enclave call) + ms = (ms_in_msg_exchange_t *)decrypted_data; + + + // Verify if the nonce obtained in the request is equal to the session nonce + if((uint32_t)*(req_message->message_aes_gcm_data.reserved) != session_info->active.counter || *(req_message->message_aes_gcm_data.reserved) > ((2^32)-2)) + { + SAFE_FREE(decrypted_data); + return INVALID_PARAMETER_ERROR; + } + + if(ms->msg_type == MESSAGE_EXCHANGE) + { + //Call the generic secret response generator for message exchange + ret = message_exchange_response_generator((char*)decrypted_data, &resp_data, &resp_data_length); + if(ret !=0) + { + SAFE_FREE(decrypted_data); + SAFE_FREE(resp_data); + return INVALID_SESSION; + } + } + else if(ms->msg_type == ENCLAVE_TO_ENCLAVE_CALL) + { + //Call the destination enclave's dispatcher to call the appropriate function in the destination enclave + ret = enclave_to_enclave_call_dispatcher((char*)decrypted_data, decrypted_data_length, &resp_data, &resp_data_length); + if(ret !=0) + { + SAFE_FREE(decrypted_data); + SAFE_FREE(resp_data); + return INVALID_SESSION; + } + } + else + { + SAFE_FREE(decrypted_data); + return INVALID_REQUEST_TYPE_ERROR; + } + + + if(resp_data_length > max_payload_size) + { + SAFE_FREE(resp_data); + SAFE_FREE(decrypted_data); + return OUT_BUFFER_LENGTH_ERROR; + } + + resp_message_calc_size = sizeof(secure_message_t)+ resp_data_length; + + if(resp_message_calc_size > resp_message_size) + { + SAFE_FREE(resp_data); + SAFE_FREE(decrypted_data); + return OUT_BUFFER_LENGTH_ERROR; + } + + //Code to build the response back to the Source Enclave + temp_resp_message = (secure_message_t*)malloc(resp_message_calc_size); + if(!temp_resp_message) + { + SAFE_FREE(resp_data); + SAFE_FREE(decrypted_data); + return MALLOC_ERROR; + } + + memset(temp_resp_message,0,sizeof(secure_message_t)+ resp_data_length); + const uint32_t data2encrypt_length = (uint32_t)resp_data_length; + temp_resp_message->session_id = session_info->session_id; + temp_resp_message->message_aes_gcm_data.payload_size = data2encrypt_length; + + //Increment the Session Nonce (Replay Protection) + session_info->active.counter = session_info->active.counter + 1; + + //Set the response nonce as the session nonce + memcpy(&temp_resp_message->message_aes_gcm_data.reserved,&session_info->active.counter,sizeof(session_info->active.counter)); + + //Prepare the response message with the encrypted payload + status = sgx_rijndael128GCM_encrypt(&session_info->active.AEK, (uint8_t*)resp_data, data2encrypt_length, + reinterpret_cast(&(temp_resp_message->message_aes_gcm_data.payload)), + reinterpret_cast(&(temp_resp_message->message_aes_gcm_data.reserved)), + sizeof(temp_resp_message->message_aes_gcm_data.reserved), plaintext, plaintext_length, + &(temp_resp_message->message_aes_gcm_data.payload_tag)); + + if(SGX_SUCCESS != status) + { + SAFE_FREE(resp_data); + SAFE_FREE(decrypted_data); + SAFE_FREE(temp_resp_message); + return status; + } + + memset(resp_message, 0, sizeof(secure_message_t)+ resp_data_length); + memcpy(resp_message, temp_resp_message, sizeof(secure_message_t)+ resp_data_length); + + SAFE_FREE(decrypted_data); + SAFE_FREE(resp_data); + SAFE_FREE(temp_resp_message); + + return SUCCESS; +} + +//Close a current session +ATTESTATION_STATUS close_session(sgx_enclave_id_t src_enclave_id, + sgx_enclave_id_t dest_enclave_id) +{ + sgx_status_t status; + + uint32_t retstatus; + + //Ocall to ask the destination enclave to end the session + status = end_session_ocall(&retstatus, src_enclave_id, dest_enclave_id); + if (status == SGX_SUCCESS) + { + if ((ATTESTATION_STATUS)retstatus != SUCCESS) + return ((ATTESTATION_STATUS)retstatus); + } + else + { + return ATTESTATION_SE_ERROR; + } + return SUCCESS; +} + +//Respond to the request from the Source Enclave to close the session +ATTESTATION_STATUS end_session(sgx_enclave_id_t src_enclave_id) +{ + ATTESTATION_STATUS status = SUCCESS; + int i; + dh_session_t session_info; + uint32_t session_id; + + //Get the session information from the map corresponding to the source enclave id + std::map::iterator it = g_dest_session_info_map.find(src_enclave_id); + if(it != g_dest_session_info_map.end()) + { + session_info = it->second; + } + else + { + return INVALID_SESSION; + } + + session_id = session_info.session_id; + //Erase the session information for the current session + g_dest_session_info_map.erase(src_enclave_id); + + //Update the session id tracker + if (g_session_count > 0) + { + //check if session exists + for (i=1; i <= MAX_SESSION_COUNT; i++) + { + if(g_session_id_tracker[i-1] != NULL && g_session_id_tracker[i-1]->session_id == session_id) + { + memset(g_session_id_tracker[i-1], 0, sizeof(session_id_tracker_t)); + SAFE_FREE(g_session_id_tracker[i-1]); + g_session_count--; + break; + } + } + } + + return status; + +} + + +//Returns a new sessionID for the source destination session +ATTESTATION_STATUS generate_session_id(uint32_t *session_id) +{ + ATTESTATION_STATUS status = SUCCESS; + + if(!session_id) + { + return INVALID_PARAMETER_ERROR; + } + //if the session structure is untintialized, set that as the next session ID + for (int i = 0; i < MAX_SESSION_COUNT; i++) + { + if (g_session_id_tracker[i] == NULL) + { + *session_id = i; + return status; + } + } + + status = NO_AVAILABLE_SESSION_ERROR; + + return status; + +} diff --git a/sgx-jvm/linux-sgx/SampleCode/LocalAttestation/LocalAttestationCode/EnclaveMessageExchange.h b/sgx-jvm/linux-sgx/SampleCode/LocalAttestation/LocalAttestationCode/EnclaveMessageExchange.h new file mode 100644 index 0000000000..c16a24656e --- /dev/null +++ b/sgx-jvm/linux-sgx/SampleCode/LocalAttestation/LocalAttestationCode/EnclaveMessageExchange.h @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + + +#include "datatypes.h" +#include "sgx_eid.h" +#include "sgx_trts.h" +#include +#include "dh_session_protocol.h" + +#ifndef LOCALATTESTATION_H_ +#define LOCALATTESTATION_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +uint32_t SGXAPI create_session(sgx_enclave_id_t src_enclave_id, sgx_enclave_id_t dest_enclave_id, dh_session_t *p_session_info); +uint32_t SGXAPI send_request_receive_response(sgx_enclave_id_t src_enclave_id, sgx_enclave_id_t dest_enclave_id, dh_session_t *p_session_info, char *inp_buff, size_t inp_buff_len, size_t max_out_buff_size, char **out_buff, size_t* out_buff_len); +uint32_t SGXAPI close_session(sgx_enclave_id_t src_enclave_id, sgx_enclave_id_t dest_enclave_id); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/sgx-jvm/linux-sgx/SampleCode/LocalAttestation/LocalAttestationCode/LocalAttestationCode.edl b/sgx-jvm/linux-sgx/SampleCode/LocalAttestation/LocalAttestationCode/LocalAttestationCode.edl new file mode 100644 index 0000000000..8e401ee843 --- /dev/null +++ b/sgx-jvm/linux-sgx/SampleCode/LocalAttestation/LocalAttestationCode/LocalAttestationCode.edl @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +enclave { + include "sgx_eid.h" + include "datatypes.h" + include "../Include/dh_session_protocol.h" + trusted{ + public uint32_t session_request(sgx_enclave_id_t src_enclave_id, [out] sgx_dh_msg1_t *dh_msg1, [out] uint32_t *session_id); + public uint32_t exchange_report(sgx_enclave_id_t src_enclave_id, [in] sgx_dh_msg2_t *dh_msg2, [out] sgx_dh_msg3_t *dh_msg3, uint32_t session_id); + public uint32_t generate_response(sgx_enclave_id_t src_enclave_id, [in, size = req_message_size] secure_message_t* req_message, size_t req_message_size, size_t max_payload_size, [out, size=resp_message_size] secure_message_t* resp_message, size_t resp_message_size ); + public uint32_t end_session(sgx_enclave_id_t src_enclave_id); + }; + + untrusted{ + uint32_t session_request_ocall(sgx_enclave_id_t src_enclave_id, sgx_enclave_id_t dest_enclave_id, [out] sgx_dh_msg1_t *dh_msg1,[out] uint32_t *session_id); + uint32_t exchange_report_ocall(sgx_enclave_id_t src_enclave_id, sgx_enclave_id_t dest_enclave_id, [in] sgx_dh_msg2_t *dh_msg2, [out] sgx_dh_msg3_t *dh_msg3, uint32_t session_id); + uint32_t send_request_ocall(sgx_enclave_id_t src_enclave_id, sgx_enclave_id_t dest_enclave_id, [in, size = req_message_size] secure_message_t* req_message, size_t req_message_size, size_t max_payload_size, [out, size=resp_message_size] secure_message_t* resp_message, size_t resp_message_size); + uint32_t end_session_ocall(sgx_enclave_id_t src_enclave_id, sgx_enclave_id_t dest_enclave_id); + }; +}; diff --git a/sgx-jvm/linux-sgx/SampleCode/LocalAttestation/LocalAttestationCode/datatypes.h b/sgx-jvm/linux-sgx/SampleCode/LocalAttestation/LocalAttestationCode/datatypes.h new file mode 100644 index 0000000000..1c198aa141 --- /dev/null +++ b/sgx-jvm/linux-sgx/SampleCode/LocalAttestation/LocalAttestationCode/datatypes.h @@ -0,0 +1,105 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "sgx_report.h" +#include "sgx_eid.h" +#include "sgx_ecp_types.h" +#include "sgx_dh.h" +#include "sgx_tseal.h" + +#ifndef DATATYPES_H_ +#define DATATYPES_H_ + +#define DH_KEY_SIZE 20 +#define NONCE_SIZE 16 +#define MAC_SIZE 16 +#define MAC_KEY_SIZE 16 +#define PADDING_SIZE 16 + +#define TAG_SIZE 16 +#define IV_SIZE 12 + +#define DERIVE_MAC_KEY 0x0 +#define DERIVE_SESSION_KEY 0x1 +#define DERIVE_VK1_KEY 0x3 +#define DERIVE_VK2_KEY 0x4 + +#define CLOSED 0x0 +#define IN_PROGRESS 0x1 +#define ACTIVE 0x2 + +#define MESSAGE_EXCHANGE 0x0 +#define ENCLAVE_TO_ENCLAVE_CALL 0x1 + +#define INVALID_ARGUMENT -2 ///< Invalid function argument +#define LOGIC_ERROR -3 ///< Functional logic error +#define FILE_NOT_FOUND -4 ///< File not found + +#define SAFE_FREE(ptr) {if (NULL != (ptr)) {free(ptr); (ptr)=NULL;}} + +#define VMC_ATTRIBUTE_MASK 0xFFFFFFFFFFFFFFCB + +typedef uint8_t dh_nonce[NONCE_SIZE]; +typedef uint8_t cmac_128[MAC_SIZE]; + +#pragma pack(push, 1) + +//Format of the AES-GCM message being exchanged between the source and the destination enclaves +typedef struct _secure_message_t +{ + uint32_t session_id; //Session ID identifyting the session to which the message belongs + sgx_aes_gcm_data_t message_aes_gcm_data; +}secure_message_t; + +//Format of the input function parameter structure +typedef struct _ms_in_msg_exchange_t { + uint32_t msg_type; //Type of Call E2E or general message exchange + uint32_t target_fn_id; //Function Id to be called in Destination. Is valid only when msg_type=ENCLAVE_TO_ENCLAVE_CALL + uint32_t inparam_buff_len; //Length of the serialized input parameters + char inparam_buff[]; //Serialized input parameters +} ms_in_msg_exchange_t; + +//Format of the return value and output function parameter structure +typedef struct _ms_out_msg_exchange_t { + uint32_t retval_len; //Length of the return value + uint32_t ret_outparam_buff_len; //Length of the serialized return value and output parameters + char ret_outparam_buff[]; //Serialized return value and output parameters +} ms_out_msg_exchange_t; + +//Session Tracker to generate session ids +typedef struct _session_id_tracker_t +{ + uint32_t session_id; +}session_id_tracker_t; + +#pragma pack(pop) + +#endif diff --git a/sgx-jvm/linux-sgx/SampleCode/LocalAttestation/LocalAttestationCode/error_codes.h b/sgx-jvm/linux-sgx/SampleCode/LocalAttestation/LocalAttestationCode/error_codes.h new file mode 100644 index 0000000000..0bb2a25cf4 --- /dev/null +++ b/sgx-jvm/linux-sgx/SampleCode/LocalAttestation/LocalAttestationCode/error_codes.h @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef ERROR_CODES_H_ +#define ERROR_CODES_H_ + +typedef uint32_t ATTESTATION_STATUS; + +#define SUCCESS 0x00 +#define INVALID_PARAMETER 0xE1 +#define VALID_SESSION 0xE2 +#define INVALID_SESSION 0xE3 +#define ATTESTATION_ERROR 0xE4 +#define ATTESTATION_SE_ERROR 0xE5 +#define IPP_ERROR 0xE6 +#define NO_AVAILABLE_SESSION_ERROR 0xE7 +#define MALLOC_ERROR 0xE8 +#define ERROR_TAG_MISMATCH 0xE9 +#define OUT_BUFFER_LENGTH_ERROR 0xEA +#define INVALID_REQUEST_TYPE_ERROR 0xEB +#define INVALID_PARAMETER_ERROR 0xEC +#define ENCLAVE_TRUST_ERROR 0xED +#define ENCRYPT_DECRYPT_ERROR 0xEE +#define DUPLICATE_SESSION 0xEF +#endif diff --git a/sgx-jvm/linux-sgx/SampleCode/LocalAttestation/Makefile b/sgx-jvm/linux-sgx/SampleCode/LocalAttestation/Makefile new file mode 100644 index 0000000000..4fb31a0b3c --- /dev/null +++ b/sgx-jvm/linux-sgx/SampleCode/LocalAttestation/Makefile @@ -0,0 +1,328 @@ +# +# Copyright (C) 2011-2016 Intel Corporation. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# + +######## SGX SDK Settings ######## + +SGX_SDK ?= /opt/intel/sgxsdk +SGX_MODE ?= HW +SGX_ARCH ?= x64 +SGX_DEBUG ?= 1 + +ifeq ($(shell getconf LONG_BIT), 32) + SGX_ARCH := x86 +else ifeq ($(findstring -m32, $(CXXFLAGS)), -m32) + SGX_ARCH := x86 +endif + +ifeq ($(SGX_ARCH), x86) + SGX_COMMON_CFLAGS := -m32 + SGX_LIBRARY_PATH := $(SGX_SDK)/lib + SGX_ENCLAVE_SIGNER := $(SGX_SDK)/bin/x86/sgx_sign + SGX_EDGER8R := $(SGX_SDK)/bin/x86/sgx_edger8r +else + SGX_COMMON_CFLAGS := -m64 + SGX_LIBRARY_PATH := $(SGX_SDK)/lib64 + SGX_ENCLAVE_SIGNER := $(SGX_SDK)/bin/x64/sgx_sign + SGX_EDGER8R := $(SGX_SDK)/bin/x64/sgx_edger8r +endif + +ifeq ($(SGX_DEBUG), 1) +ifeq ($(SGX_PRERELEASE), 1) +$(error Cannot set SGX_DEBUG and SGX_PRERELEASE at the same time!!) +endif +endif + +ifeq ($(SGX_DEBUG), 1) + SGX_COMMON_CFLAGS += -O0 -g +else + SGX_COMMON_CFLAGS += -O2 +endif + +######## Library Settings ######## + +Trust_Lib_Name := libLocalAttestation_Trusted.a +TrustLib_Cpp_Files := $(wildcard LocalAttestationCode/*.cpp) +TrustLib_Cpp_Objects := $(TrustLib_Cpp_Files:.cpp=.o) +TrustLib_Include_Paths := -I$(SGX_SDK)/include -I$(SGX_SDK)/include/tlibc -I$(SGX_SDK)/include/stlport -I$(SGX_SDK)/include/epid -I./Include +TrustLib_Compile_Flags := $(SGX_COMMON_CFLAGS) -nostdinc -fvisibility=hidden -fpie -fstack-protector $(TrustLib_Include_Paths) +TrustLib_Compile_Cxx_Flags := -std=c++03 -nostdinc++ + +UnTrustLib_Name := libLocalAttestation_unTrusted.a +UnTrustLib_Cpp_Files := $(wildcard Untrusted_LocalAttestation/*.cpp) +UnTrustLib_Cpp_Objects := $(UnTrustLib_Cpp_Files:.cpp=.o) +UnTrustLib_Include_Paths := -I$(SGX_SDK)/include -I$(SGX_SDK)/include/ippcp -I./Include -I./LocalAttestationCode +UnTrustLib_Compile_Flags := $(SGX_COMMON_CFLAGS) -fPIC -Wno-attributes -std=c++11 $(UnTrustLib_Include_Paths) + +######## App Settings ######## + +ifneq ($(SGX_MODE), HW) + Urts_Library_Name := sgx_urts_sim +else + Urts_Library_Name := sgx_urts +endif + +App_Cpp_Files := $(wildcard App/*.cpp) +App_Include_Paths := -I$(SGX_SDK)/include -I$(SGX_SDK)/include/ippcp -I./Include -I./LocalAttestationCode + +App_Compile_Flags := $(SGX_COMMON_CFLAGS) -fPIC -Wno-attributes $(App_Include_Paths) +# Three configuration modes - Debug, prerelease, release +# Debug - Macro DEBUG enabled. +# Prerelease - Macro NDEBUG and EDEBUG enabled. +# Release - Macro NDEBUG enabled. +ifeq ($(SGX_DEBUG), 1) + App_Compile_Flags += -DDEBUG -UNDEBUG -UEDEBUG +else ifeq ($(SGX_PRERELEASE), 1) + App_Compile_Flags += -DNDEBUG -DEDEBUG -UDEBUG +else + App_Compile_Flags += -DNDEBUG -UEDEBUG -UDEBUG +endif + +App_Link_Flags := $(SGX_COMMON_CFLAGS) -L$(SGX_LIBRARY_PATH) -l$(Urts_Library_Name) -L. -lpthread -lLocalAttestation_unTrusted + +ifneq ($(SGX_MODE), HW) + App_Link_Flags += -lsgx_uae_service_sim +else + App_Link_Flags += -lsgx_uae_service +endif + +App_Cpp_Objects := $(App_Cpp_Files:.cpp=.o) +App_Name := app + +######## Enclave Settings ######## + +ifneq ($(SGX_MODE), HW) + Trts_Library_Name := sgx_trts_sim + Service_Library_Name := sgx_tservice_sim +else + Trts_Library_Name := sgx_trts + Service_Library_Name := sgx_tservice +endif +Crypto_Library_Name := sgx_tcrypto + +Enclave_Cpp_Files_1 := $(wildcard Enclave1/*.cpp) +Enclave_Cpp_Files_2 := $(wildcard Enclave2/*.cpp) +Enclave_Cpp_Files_3 := $(wildcard Enclave3/*.cpp) +Enclave_Include_Paths := -I$(SGX_SDK)/include -I$(SGX_SDK)/include/tlibc -I$(SGX_SDK)/include/stlport -I./LocalAttestationCode -I./Include + +Enclave_Compile_Flags := $(SGX_COMMON_CFLAGS) -nostdinc -fvisibility=hidden -fpie -fstack-protector $(Enclave_Include_Paths) + +# To generate a proper enclave, it is recommended to follow below guideline to link the trusted libraries: +# 1. Link sgx_trts with the `--whole-archive' and `--no-whole-archive' options, +# so that the whole content of trts is included in the enclave. +# 2. For other libraries, you just need to pull the required symbols. +# Use `--start-group' and `--end-group' to link these libraries. +# Do NOT move the libraries linked with `--start-group' and `--end-group' within `--whole-archive' and `--no-whole-archive' options. +# Otherwise, you may get some undesirable errors. +Enclave_Link_Flags := $(SGX_COMMON_CFLAGS) -Wl,--no-undefined -nostdlib -nodefaultlibs -nostartfiles -L$(SGX_LIBRARY_PATH) \ + -Wl,--whole-archive -l$(Trts_Library_Name) -Wl,--no-whole-archive \ + -Wl,--start-group -lsgx_tstdc -lsgx_tstdcxx -l$(Crypto_Library_Name) -L. -lLocalAttestation_Trusted -l$(Service_Library_Name) -Wl,--end-group \ + -Wl,-Bstatic -Wl,-Bsymbolic -Wl,--no-undefined \ + -Wl,-pie,-eenclave_entry -Wl,--export-dynamic \ + -Wl,--defsym,__ImageBase=0 + +Enclave_Cpp_Objects_1 := $(Enclave_Cpp_Files_1:.cpp=.o) +Enclave_Cpp_Objects_2 := $(Enclave_Cpp_Files_2:.cpp=.o) +Enclave_Cpp_Objects_3 := $(Enclave_Cpp_Files_3:.cpp=.o) + +Enclave_Name_1 := libenclave1.so +Enclave_Name_2 := libenclave2.so +Enclave_Name_3 := libenclave3.so + +ifeq ($(SGX_MODE), HW) +ifeq ($(SGX_DEBUG), 1) + Build_Mode = HW_DEBUG +else ifeq ($(SGX_PRERELEASE), 1) + Build_Mode = HW_PRERELEASE +else + Build_Mode = HW_RELEASE +endif +else +ifeq ($(SGX_DEBUG), 1) + Build_Mode = SIM_DEBUG +else ifeq ($(SGX_PRERELEASE), 1) + Build_Mode = SIM_PRERELEASE +else + Build_Mode = SIM_RELEASE +endif +endif + +ifeq ($(Build_Mode), HW_RELEASE) +all: $(Trust_Lib_Name) $(UnTrustLib_Name) Enclave1.so Enclave2.so Enclave3.so $(App_Name) + @echo "The project has been built in release hardware mode." + @echo "Please sign the enclaves (Enclave1.so, Enclave2.so, Enclave3.so) first with your signing keys before you run the $(App_Name) to launch and access the enclave." + @echo "To sign the enclaves use the following commands:" + @echo " $(SGX_ENCLAVE_SIGNER) sign -key -enclave Enclave1.so -out <$(Enclave_Name_1)> -config Enclave1/Enclave1.config.xml" + @echo " $(SGX_ENCLAVE_SIGNER) sign -key -enclave Enclave2.so -out <$(Enclave_Name_2)> -config Enclave2/Enclave2.config.xml" + @echo " $(SGX_ENCLAVE_SIGNER) sign -key -enclave Enclave3.so -out <$(Enclave_Name_3)> -config Enclave3/Enclave3.config.xml" + @echo "You can also sign the enclaves using an external signing tool." + @echo "To build the project in simulation mode set SGX_MODE=SIM. To build the project in prerelease mode set SGX_PRERELEASE=1 and SGX_MODE=HW." +else +all: $(Trust_Lib_Name) $(UnTrustLib_Name) $(Enclave_Name_1) $(Enclave_Name_2) $(Enclave_Name_3) $(App_Name) +ifeq ($(Build_Mode), HW_DEBUG) + @echo "The project has been built in debug hardware mode." +else ifeq ($(Build_Mode), SIM_DEBUG) + @echo "The project has been built in debug simulation mode." +else ifeq ($(Build_Mode), HW_PRERELEASE) + @echo "The project has been built in pre-release hardware mode." +else ifeq ($(Build_Mode), SIM_PRERELEASE) + @echo "The project has been built in pre-release simulation mode." +else + @echo "The project has been built in release simulation mode." +endif +endif + +######## Library Objects ######## + +LocalAttestationCode/LocalAttestationCode_t.c LocalAttestationCode/LocalAttestationCode_t.h : $(SGX_EDGER8R) LocalAttestationCode/LocalAttestationCode.edl + @cd LocalAttestationCode && $(SGX_EDGER8R) --trusted ../LocalAttestationCode/LocalAttestationCode.edl --search-path $(SGX_SDK)/include + @echo "GEN => $@" + +LocalAttestationCode/LocalAttestationCode_t.o: LocalAttestationCode/LocalAttestationCode_t.c + @$(CC) $(TrustLib_Compile_Flags) -c $< -o $@ + @echo "CC <= $<" + +LocalAttestationCode/%.o: LocalAttestationCode/%.cpp LocalAttestationCode/LocalAttestationCode_t.h + @$(CXX) $(TrustLib_Compile_Flags) $(TrustLib_Compile_Cxx_Flags) -c $< -o $@ + @echo "CC <= $<" + +$(Trust_Lib_Name): LocalAttestationCode/LocalAttestationCode_t.o $(TrustLib_Cpp_Objects) + @$(AR) rcs $@ $^ + @echo "GEN => $@" + +Untrusted_LocalAttestation/%.o: Untrusted_LocalAttestation/%.cpp + @$(CXX) $(UnTrustLib_Compile_Flags) -c $< -o $@ + @echo "CC <= $<" + +$(UnTrustLib_Name): $(UnTrustLib_Cpp_Objects) + @$(AR) rcs $@ $^ + @echo "GEN => $@" + +######## App Objects ######## +Enclave1/Enclave1_u.c Enclave1/Enclave1_u.h: $(SGX_EDGER8R) Enclave1/Enclave1.edl + @cd Enclave1 && $(SGX_EDGER8R) --use-prefix --untrusted ../Enclave1/Enclave1.edl --search-path $(SGX_SDK)/include + @echo "GEN => $@" + +App/Enclave1_u.o: Enclave1/Enclave1_u.c + @$(CC) $(App_Compile_Flags) -c $< -o $@ + @echo "CC <= $<" + +Enclave2/Enclave2_u.c Enclave2/Enclave2_u.h: $(SGX_EDGER8R) Enclave2/Enclave2.edl + @cd Enclave2 && $(SGX_EDGER8R) --use-prefix --untrusted ../Enclave2/Enclave2.edl --search-path $(SGX_SDK)/include + @echo "GEN => $@" + +App/Enclave2_u.o: Enclave2/Enclave2_u.c + @$(CC) $(App_Compile_Flags) -c $< -o $@ + @echo "CC <= $<" + +Enclave3/Enclave3_u.c Enclave3/Enclave3_u.h: $(SGX_EDGER8R) Enclave3/Enclave3.edl + @cd Enclave3 && $(SGX_EDGER8R) --use-prefix --untrusted ../Enclave3/Enclave3.edl --search-path $(SGX_SDK)/include + @echo "GEN => $@" + +App/Enclave3_u.o: Enclave3/Enclave3_u.c + @$(CC) $(App_Compile_Flags) -c $< -o $@ + @echo "CC <= $<" + +App/%.o: App/%.cpp Enclave1/Enclave1_u.h Enclave2/Enclave2_u.h Enclave3/Enclave3_u.h + @$(CXX) $(App_Compile_Flags) -c $< -o $@ + @echo "CXX <= $<" + +$(App_Name): App/Enclave1_u.o App/Enclave2_u.o App/Enclave3_u.o $(App_Cpp_Objects) $(UnTrustLib_Name) + @$(CXX) $^ -o $@ $(App_Link_Flags) + @echo "LINK => $@" + + +######## Enclave Objects ######## + +Enclave1/Enclave1_t.c Enclave1/Enclave1_t.h: $(SGX_EDGER8R) Enclave1/Enclave1.edl + @cd Enclave1 && $(SGX_EDGER8R) --use-prefix --trusted ../Enclave1/Enclave1.edl --search-path $(SGX_SDK)/include + @echo "GEN => $@" + +Enclave1/Enclave1_t.o: Enclave1/Enclave1_t.c + @$(CC) $(Enclave_Compile_Flags) -c $< -o $@ + @echo "CC <= $<" + +Enclave1/%.o: Enclave1/%.cpp Enclave1/Enclave1_t.h + @$(CXX) -std=c++03 -nostdinc++ $(Enclave_Compile_Flags) -c $< -o $@ + @echo "CXX <= $<" + +Enclave1.so: Enclave1/Enclave1_t.o $(Enclave_Cpp_Objects_1) $(Trust_Lib_Name) + @$(CXX) Enclave1/Enclave1_t.o $(Enclave_Cpp_Objects_1) -o $@ $(Enclave_Link_Flags) + @echo "LINK => $@" + +$(Enclave_Name_1): Enclave1.so + @$(SGX_ENCLAVE_SIGNER) sign -key Enclave1/Enclave1_private.pem -enclave Enclave1.so -out $@ -config Enclave1/Enclave1.config.xml + @echo "SIGN => $@" + +Enclave2/Enclave2_t.c: $(SGX_EDGER8R) Enclave2/Enclave2.edl + @cd Enclave2 && $(SGX_EDGER8R) --use-prefix --trusted ../Enclave2/Enclave2.edl --search-path $(SGX_SDK)/include + @echo "GEN => $@" + +Enclave2/Enclave2_t.o: Enclave2/Enclave2_t.c + @$(CC) $(Enclave_Compile_Flags) -c $< -o $@ + @echo "CC <= $<" + +Enclave2/%.o: Enclave2/%.cpp + @$(CXX) -std=c++03 -nostdinc++ $(Enclave_Compile_Flags) -c $< -o $@ + @echo "CXX <= $<" + +Enclave2.so: Enclave2/Enclave2_t.o $(Enclave_Cpp_Objects_2) $(Trust_Lib_Name) + @$(CXX) Enclave2/Enclave2_t.o $(Enclave_Cpp_Objects_2) -o $@ $(Enclave_Link_Flags) + @echo "LINK => $@" + +$(Enclave_Name_2): Enclave2.so + @$(SGX_ENCLAVE_SIGNER) sign -key Enclave2/Enclave2_private.pem -enclave Enclave2.so -out $@ -config Enclave2/Enclave2.config.xml + @echo "SIGN => $@" + +Enclave3/Enclave3_t.c: $(SGX_EDGER8R) Enclave3/Enclave3.edl + @cd Enclave3 && $(SGX_EDGER8R) --use-prefix --trusted ../Enclave3/Enclave3.edl --search-path $(SGX_SDK)/include + @echo "GEN => $@" + +Enclave3/Enclave3_t.o: Enclave3/Enclave3_t.c + @$(CC) $(Enclave_Compile_Flags) -c $< -o $@ + @echo "CC <= $<" + +Enclave3/%.o: Enclave3/%.cpp + @$(CXX) -std=c++03 -nostdinc++ $(Enclave_Compile_Flags) -c $< -o $@ + @echo "CXX <= $<" + +Enclave3.so: Enclave3/Enclave3_t.o $(Enclave_Cpp_Objects_3) $(Trust_Lib_Name) + @$(CXX) Enclave3/Enclave3_t.o $(Enclave_Cpp_Objects_3) -o $@ $(Enclave_Link_Flags) + @echo "LINK => $@" + +$(Enclave_Name_3): Enclave3.so + @$(SGX_ENCLAVE_SIGNER) sign -key Enclave3/Enclave3_private.pem -enclave Enclave3.so -out $@ -config Enclave3/Enclave3.config.xml + @echo "SIGN => $@" + +######## Clean ######## +.PHONY: clean + +clean: + @rm -rf $(App_Name) *.so *.a App/*.o Enclave1/*.o Enclave1/*_t.* Enclave1/*_u.* Enclave2/*.o Enclave2/*_t.* Enclave2/*_u.* Enclave3/*.o Enclave3/*_t.* Enclave3/*_u.* LocalAttestationCode/*.o Untrusted_LocalAttestation/*.o LocalAttestationCode/*_t.* diff --git a/sgx-jvm/linux-sgx/SampleCode/LocalAttestation/README.txt b/sgx-jvm/linux-sgx/SampleCode/LocalAttestation/README.txt new file mode 100644 index 0000000000..882143468d --- /dev/null +++ b/sgx-jvm/linux-sgx/SampleCode/LocalAttestation/README.txt @@ -0,0 +1,27 @@ +--------------------------- +Purpose of LocalAttestation +--------------------------- +The project demonstrates: +- How to establish a protected channel +- Secret message exchange using enclave to enclave function calls + +------------------------------------ +How to Build/Execute the Sample Code +------------------------------------ +1. Install Intel(R) SGX SDK for Linux* OS +2. Build the project with the prepared Makefile: + a. Hardware Mode, Debug build: + $ make + b. Hardware Mode, Pre-release build: + $ make SGX_PRERELEASE=1 SGX_DEBUG=0 + c. Hardware Mode, Release build: + $ make SGX_DEBUG=0 + d. Simulation Mode, Debug build: + $ make SGX_MODE=SIM + e. Simulation Mode, Pre-release build: + $ make SGX_MODE=SIM SGX_PRERELEASE=1 SGX_DEBUG=0 + f. Simulation Mode, Release build: + $ make SGX_MODE=SIM SGX_DEBUG=0 +3. Execute the binary directly: + $ ./app +4. Remember to "make clean" before switching build mode diff --git a/sgx-jvm/linux-sgx/SampleCode/LocalAttestation/Untrusted_LocalAttestation/UntrustedEnclaveMessageExchange.cpp b/sgx-jvm/linux-sgx/SampleCode/LocalAttestation/Untrusted_LocalAttestation/UntrustedEnclaveMessageExchange.cpp new file mode 100644 index 0000000000..805c14abad --- /dev/null +++ b/sgx-jvm/linux-sgx/SampleCode/LocalAttestation/Untrusted_LocalAttestation/UntrustedEnclaveMessageExchange.cpp @@ -0,0 +1,184 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + + +#include "sgx_eid.h" +#include "error_codes.h" +#include "datatypes.h" +#include "sgx_urts.h" +#include "UntrustedEnclaveMessageExchange.h" +#include "sgx_dh.h" +#include + +std::mapg_enclave_id_map; + +//Makes an sgx_ecall to the destination enclave to get session id and message1 +ATTESTATION_STATUS session_request_ocall(sgx_enclave_id_t src_enclave_id, sgx_enclave_id_t dest_enclave_id, sgx_dh_msg1_t* dh_msg1, uint32_t* session_id) +{ + uint32_t status = 0; + sgx_status_t ret = SGX_SUCCESS; + uint32_t temp_enclave_no; + + std::map::iterator it = g_enclave_id_map.find(dest_enclave_id); + if(it != g_enclave_id_map.end()) + { + temp_enclave_no = it->second; + } + else + { + return INVALID_SESSION; + } + + switch(temp_enclave_no) + { + case 1: + ret = Enclave1_session_request(dest_enclave_id, &status, src_enclave_id, dh_msg1, session_id); + break; + case 2: + ret = Enclave2_session_request(dest_enclave_id, &status, src_enclave_id, dh_msg1, session_id); + break; + case 3: + ret = Enclave3_session_request(dest_enclave_id, &status, src_enclave_id, dh_msg1, session_id); + break; + } + if (ret == SGX_SUCCESS) + return (ATTESTATION_STATUS)status; + else + return INVALID_SESSION; + +} +//Makes an sgx_ecall to the destination enclave sends message2 from the source enclave and gets message 3 from the destination enclave +ATTESTATION_STATUS exchange_report_ocall(sgx_enclave_id_t src_enclave_id, sgx_enclave_id_t dest_enclave_id, sgx_dh_msg2_t *dh_msg2, sgx_dh_msg3_t *dh_msg3, uint32_t session_id) +{ + uint32_t status = 0; + sgx_status_t ret = SGX_SUCCESS; + uint32_t temp_enclave_no; + + std::map::iterator it = g_enclave_id_map.find(dest_enclave_id); + if(it != g_enclave_id_map.end()) + { + temp_enclave_no = it->second; + } + else + { + return INVALID_SESSION; + } + + switch(temp_enclave_no) + { + case 1: + ret = Enclave1_exchange_report(dest_enclave_id, &status, src_enclave_id, dh_msg2, dh_msg3, session_id); + break; + case 2: + ret = Enclave2_exchange_report(dest_enclave_id, &status, src_enclave_id, dh_msg2, dh_msg3, session_id); + break; + case 3: + ret = Enclave3_exchange_report(dest_enclave_id, &status, src_enclave_id, dh_msg2, dh_msg3, session_id); + break; + } + if (ret == SGX_SUCCESS) + return (ATTESTATION_STATUS)status; + else + return INVALID_SESSION; + +} + +//Make an sgx_ecall to the destination enclave function that generates the actual response +ATTESTATION_STATUS send_request_ocall(sgx_enclave_id_t src_enclave_id, sgx_enclave_id_t dest_enclave_id,secure_message_t* req_message, size_t req_message_size, size_t max_payload_size, secure_message_t* resp_message, size_t resp_message_size) +{ + uint32_t status = 0; + sgx_status_t ret = SGX_SUCCESS; + uint32_t temp_enclave_no; + + std::map::iterator it = g_enclave_id_map.find(dest_enclave_id); + if(it != g_enclave_id_map.end()) + { + temp_enclave_no = it->second; + } + else + { + return INVALID_SESSION; + } + + switch(temp_enclave_no) + { + case 1: + ret = Enclave1_generate_response(dest_enclave_id, &status, src_enclave_id, req_message, req_message_size, max_payload_size, resp_message, resp_message_size); + break; + case 2: + ret = Enclave2_generate_response(dest_enclave_id, &status, src_enclave_id, req_message, req_message_size, max_payload_size, resp_message, resp_message_size); + break; + case 3: + ret = Enclave3_generate_response(dest_enclave_id, &status, src_enclave_id, req_message, req_message_size, max_payload_size, resp_message, resp_message_size); + break; + } + if (ret == SGX_SUCCESS) + return (ATTESTATION_STATUS)status; + else + return INVALID_SESSION; + +} + +//Make an sgx_ecall to the destination enclave to close the session +ATTESTATION_STATUS end_session_ocall(sgx_enclave_id_t src_enclave_id, sgx_enclave_id_t dest_enclave_id) +{ + uint32_t status = 0; + sgx_status_t ret = SGX_SUCCESS; + uint32_t temp_enclave_no; + + std::map::iterator it = g_enclave_id_map.find(dest_enclave_id); + if(it != g_enclave_id_map.end()) + { + temp_enclave_no = it->second; + } + else + { + return INVALID_SESSION; + } + + switch(temp_enclave_no) + { + case 1: + ret = Enclave1_end_session(dest_enclave_id, &status, src_enclave_id); + break; + case 2: + ret = Enclave2_end_session(dest_enclave_id, &status, src_enclave_id); + break; + case 3: + ret = Enclave3_end_session(dest_enclave_id, &status, src_enclave_id); + break; + } + if (ret == SGX_SUCCESS) + return (ATTESTATION_STATUS)status; + else + return INVALID_SESSION; + +} diff --git a/sgx-jvm/linux-sgx/SampleCode/LocalAttestation/Untrusted_LocalAttestation/UntrustedEnclaveMessageExchange.h b/sgx-jvm/linux-sgx/SampleCode/LocalAttestation/Untrusted_LocalAttestation/UntrustedEnclaveMessageExchange.h new file mode 100644 index 0000000000..684b33cb3b --- /dev/null +++ b/sgx-jvm/linux-sgx/SampleCode/LocalAttestation/Untrusted_LocalAttestation/UntrustedEnclaveMessageExchange.h @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + + +#include "sgx_eid.h" +#include "error_codes.h" +#include "datatypes.h" +#include "sgx_urts.h" +#include "dh_session_protocol.h" +#include "sgx_dh.h" +#include + + +#ifndef ULOCALATTESTATION_H_ +#define ULOCALATTESTATION_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +sgx_status_t Enclave1_session_request(sgx_enclave_id_t eid, uint32_t* retval, sgx_enclave_id_t src_enclave_id, sgx_dh_msg1_t* dh_msg1, uint32_t* session_id); +sgx_status_t Enclave1_exchange_report(sgx_enclave_id_t eid, uint32_t* retval, sgx_enclave_id_t src_enclave_id, sgx_dh_msg2_t* dh_msg2, sgx_dh_msg3_t* dh_msg3, uint32_t session_id); +sgx_status_t Enclave1_generate_response(sgx_enclave_id_t eid, uint32_t* retval, sgx_enclave_id_t src_enclave_id, secure_message_t* req_message, size_t req_message_size, size_t max_payload_size, secure_message_t* resp_message, size_t resp_message_size); +sgx_status_t Enclave1_end_session(sgx_enclave_id_t eid, uint32_t* retval, sgx_enclave_id_t src_enclave_id); + +sgx_status_t Enclave2_session_request(sgx_enclave_id_t eid, uint32_t* retval, sgx_enclave_id_t src_enclave_id, sgx_dh_msg1_t* dh_msg1, uint32_t* session_id); +sgx_status_t Enclave2_exchange_report(sgx_enclave_id_t eid, uint32_t* retval, sgx_enclave_id_t src_enclave_id, sgx_dh_msg2_t* dh_msg2, sgx_dh_msg3_t* dh_msg3, uint32_t session_id); +sgx_status_t Enclave2_generate_response(sgx_enclave_id_t eid, uint32_t* retval, sgx_enclave_id_t src_enclave_id, secure_message_t* req_message, size_t req_message_size, size_t max_payload_size, secure_message_t* resp_message, size_t resp_message_size); +sgx_status_t Enclave2_end_session(sgx_enclave_id_t eid, uint32_t* retval, sgx_enclave_id_t src_enclave_id); + +sgx_status_t Enclave3_session_request(sgx_enclave_id_t eid, uint32_t* retval, sgx_enclave_id_t src_enclave_id, sgx_dh_msg1_t* dh_msg1, uint32_t* session_id); +sgx_status_t Enclave3_exchange_report(sgx_enclave_id_t eid, uint32_t* retval, sgx_enclave_id_t src_enclave_id, sgx_dh_msg2_t* dh_msg2, sgx_dh_msg3_t* dh_msg3, uint32_t session_id); +sgx_status_t Enclave3_generate_response(sgx_enclave_id_t eid, uint32_t* retval, sgx_enclave_id_t src_enclave_id, secure_message_t* req_message, size_t req_message_size, size_t max_payload_size, secure_message_t* resp_message, size_t resp_message_size); +sgx_status_t Enclave3_end_session(sgx_enclave_id_t eid, uint32_t* retval, sgx_enclave_id_t src_enclave_id); + +uint32_t session_request_ocall(sgx_enclave_id_t src_enclave_id, sgx_enclave_id_t dest_enclave_id, sgx_dh_msg1_t* dh_msg1, uint32_t* session_id); +uint32_t exchange_report_ocall(sgx_enclave_id_t src_enclave_id, sgx_enclave_id_t dest_enclave_id, sgx_dh_msg2_t* dh_msg2, sgx_dh_msg3_t* dh_msg3, uint32_t session_id); +uint32_t send_request_ocall(sgx_enclave_id_t src_enclave_id, sgx_enclave_id_t dest_enclave_id, secure_message_t* req_message, size_t req_message_size, size_t max_payload_size, secure_message_t* resp_message, size_t resp_message_size); +uint32_t end_session_ocall(sgx_enclave_id_t src_enclave_id, sgx_enclave_id_t dest_enclave_id); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/sgx-jvm/linux-sgx/SampleCode/PowerTransition/.cproject b/sgx-jvm/linux-sgx/SampleCode/PowerTransition/.cproject new file mode 100644 index 0000000000..77c05bf4f1 --- /dev/null +++ b/sgx-jvm/linux-sgx/SampleCode/PowerTransition/.cproject @@ -0,0 +1,219 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sgx-jvm/linux-sgx/SampleCode/PowerTransition/.project b/sgx-jvm/linux-sgx/SampleCode/PowerTransition/.project new file mode 100644 index 0000000000..7f1ef0688c --- /dev/null +++ b/sgx-jvm/linux-sgx/SampleCode/PowerTransition/.project @@ -0,0 +1,28 @@ + + + PowerTransition + + + + + + org.eclipse.cdt.managedbuilder.core.genmakebuilder + clean,full,incremental, + + + + + org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder + full,incremental, + + + + + + org.eclipse.cdt.core.cnature + org.eclipse.cdt.managedbuilder.core.managedBuildNature + org.eclipse.cdt.managedbuilder.core.ScannerConfigNature + org.eclipse.cdt.core.ccnature + com.intel.sgx.sgxnature + + diff --git a/sgx-jvm/linux-sgx/SampleCode/PowerTransition/App/App.cpp b/sgx-jvm/linux-sgx/SampleCode/PowerTransition/App/App.cpp new file mode 100644 index 0000000000..6384116722 --- /dev/null +++ b/sgx-jvm/linux-sgx/SampleCode/PowerTransition/App/App.cpp @@ -0,0 +1,319 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + + + +// App.cpp : Define the entry point for the console application. +// + +#include +#include +#include +#include +#include + +#include "Enclave_u.h" +#include "sgx_urts.h" +#include "sgx_tseal.h" + +#include "rwlock.h" +#include "ErrorSupport.h" + +#define ENCLAVE_NAME "libenclave.signed.so" +#define TOKEN_NAME "Enclave.token" + +#define THREAD_NUM 3 + +// Global data +sgx_enclave_id_t global_eid = 0; +sgx_launch_token_t token = {0}; +rwlock_t lock_eid; +struct sealed_buf_t sealed_buf; + +using namespace std; + +// Ocall function +void print(const char *str) +{ + cout<()(std::this_thread::get_id()); + sgx_status_t ret = SGX_SUCCESS; + int retval = 0; + sgx_enclave_id_t current_eid = 0; + + // Enter the enclave to increase and seal the secret data for 100 times. + for(unsigned int i = 0; i< 50000; i++) + { + for( ; ; ) + { + // If power transition occurs, all the data inside the enclave will be lost when the system resumes. + // Therefore, if there are some secret data which need to be backed up for recover, + // users can choose to seal the secret data inside the enclave and back up the sealed data. + + // Enter the enclave to increase the secret data and back up the sealed data + rdlock(&lock_eid); + current_eid = global_eid; + rdunlock(&lock_eid); + ret = increase_and_seal_data(current_eid, &retval, thread_id, &sealed_buf); + + if(ret == SGX_ERROR_ENCLAVE_LOST) + { + // SGX_ERROR_ENCLAVE_LOST indicates the power transition occurs before the system resumes. + // Lock here is to make sure there is only one thread to load and initialize the enclave at the same time + wtlock(&lock_eid); + // The loading and initialization operations happen in current thread only if there is no other thread reloads and initializes the enclave before + if(current_eid == global_eid) + { + cout <<"power transition occured in increase_and_seal_data()." << endl; + // Use the backup sealed data to reload and initialize the enclave. + if((ret = load_and_initialize_enclave(¤t_eid, &sealed_buf)) != SGX_SUCCESS) + { + ret_error_support(ret); + wtunlock(&lock_eid); + return false; + } + else + { + // Update the global_eid after initializing the enclave successfully + global_eid = current_eid; + } + } + else + { + // The enclave has been reloaded by another thread. + // Update the current EID and do increase_and_seal_data() again. + current_eid = global_eid; + } + wtunlock(&lock_eid); + } + else + { + // No power transition occurs + break; + } + } + if(ret != SGX_SUCCESS) + { + ret_error_support(ret); + return false; + } + else if(retval != 0) + { + return false; + } + } + return true; +} + + +void thread_func() +{ + if(increase_and_seal_data_in_enclave() != true) + { + abort(); + } +} + +bool set_global_data() +{ + // Initialize the read/write lock. + init_rwlock(&lock_eid); + + // Get the saved launch token. + // If error occures, zero the token. + ifstream ifs(TOKEN_NAME, std::ios::binary | std::ios::in); + if(!ifs.good()) + { + memset(token, 0, sizeof(sgx_launch_token_t)); + } + else + { + ifs.read(reinterpret_cast(&token), sizeof(sgx_launch_token_t)); + if(ifs.fail()) + { + memset(&token, 0, sizeof(sgx_launch_token_t)); + } + } + + // Allocate memory to save the sealed data. + uint32_t sealed_len = sizeof(sgx_sealed_data_t) + sizeof(uint32_t); + for(int i = 0; i < BUF_NUM; i++) + { + sealed_buf.sealed_buf_ptr[i] = (uint8_t *)malloc(sealed_len); + if(sealed_buf.sealed_buf_ptr[i] == NULL) + { + cout << "Out of memory" << endl; + return false; + } + memset(sealed_buf.sealed_buf_ptr[i], 0, sealed_len); + } + sealed_buf.index = 0; // index indicates which buffer contains current sealed data and which contains the backup sealed data + + return true; +} + +void release_source() +{ + for(int i = 0; i < BUF_NUM; i++) + { + if(sealed_buf.sealed_buf_ptr[i] != NULL) + { + free(sealed_buf.sealed_buf_ptr[i]); + sealed_buf.sealed_buf_ptr[i] = NULL; + } + } + fini_rwlock(&lock_eid); + return; +} + +int main(int argc, char* argv[]) +{ + (void)argc, (void)argv; + + + // Initialize the global data + if(!set_global_data()) + { + release_source(); + cout << "Enter a character before exit ..." << endl; + getchar(); + return -1; + } + + // Load and initialize the signed enclave + // sealed_buf == NULL indicates it is the first time to initialize the enclave. + sgx_status_t ret = load_and_initialize_enclave(&global_eid , NULL); + if(ret != SGX_SUCCESS) + { + ret_error_support(ret); + release_source(); + cout << "Enter a character before exit ..." << endl; + getchar(); + return -1; + } + + cout << "****************************************************************" << endl; + cout << "Demonstrating Power transition needs your cooperation." << endl + << "Please take the following actions:" << endl + << " 1. Enter a character;" << endl + << " 2. Manually put the OS into a sleep or hibernate state;" << endl + << " 3. Resume the OS from that state;" << endl + << "Then you will see the application continues." << endl; + cout << "****************************************************************" << endl; + cout << "Now enter a character ..."; + getchar(); + + // Create multiple threads to calculate the sum + thread trd[THREAD_NUM]; + for (int i = 0; i< THREAD_NUM; i++) + { + trd[i] = thread(thread_func); + } + for (int i = 0; i < THREAD_NUM; i++) + { + trd[i].join(); + } + + // Release resources + release_source(); + + // Destroy the enclave + sgx_destroy_enclave(global_eid); + + cout << "Enter a character before exit ..." << endl; + getchar(); + return 0; +} + diff --git a/sgx-jvm/linux-sgx/SampleCode/PowerTransition/App/ErrorSupport.cpp b/sgx-jvm/linux-sgx/SampleCode/PowerTransition/App/ErrorSupport.cpp new file mode 100644 index 0000000000..9665fb6b31 --- /dev/null +++ b/sgx-jvm/linux-sgx/SampleCode/PowerTransition/App/ErrorSupport.cpp @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + + + +#include +#include "ErrorSupport.h" + + +typedef struct _sgx_errlist_t { + sgx_status_t err; + const char * msg; +} sgx_errlist_t; + +static sgx_errlist_t sgx_errlist[] = { + {SGX_ERROR_UNEXPECTED, "Unexpected error occurred."}, + {SGX_ERROR_INVALID_PARAMETER, "Invalid parameter."}, + {SGX_ERROR_OUT_OF_MEMORY, "Out of memory."}, + {SGX_ERROR_ENCLAVE_LOST, "Power transition occurred."}, + {SGX_ERROR_INVALID_ENCLAVE, "Invalid enclave image."}, + {SGX_ERROR_INVALID_ENCLAVE_ID, "Invalid enclave identification."}, + {SGX_ERROR_INVALID_SIGNATURE, "Invalid enclave signature."}, + {SGX_ERROR_OUT_OF_EPC, "Out of EPC memory."}, + {SGX_ERROR_NO_DEVICE, "Invalid SGX device."}, + {SGX_ERROR_MEMORY_MAP_CONFLICT, "Memory map conflicted."}, + {SGX_ERROR_INVALID_METADATA, "Invalid encalve metadata."}, + {SGX_ERROR_DEVICE_BUSY, "SGX device is busy."}, + {SGX_ERROR_INVALID_VERSION, "Enclave metadata version is invalid."}, + {SGX_ERROR_ENCLAVE_FILE_ACCESS, "Can't open enclave file."}, + + {SGX_ERROR_INVALID_FUNCTION, "Invalid function name."}, + {SGX_ERROR_OUT_OF_TCS, "Out of TCS."}, + {SGX_ERROR_ENCLAVE_CRASHED, "The enclave is crashed."}, + + {SGX_ERROR_MAC_MISMATCH, "Report varification error occurred."}, + {SGX_ERROR_INVALID_ATTRIBUTE, "The enclave is not authorized."}, + {SGX_ERROR_INVALID_CPUSVN, "Invalid CPUSVN."}, + {SGX_ERROR_INVALID_ISVSVN, "Invalid ISVSVN."}, + {SGX_ERROR_INVALID_KEYNAME, "The requested key name is invalid."}, + + {SGX_ERROR_SERVICE_UNAVAILABLE, "AESM service is not responsive."}, + {SGX_ERROR_SERVICE_TIMEOUT, "Request to AESM is time out."}, + {SGX_ERROR_SERVICE_INVALID_PRIVILEGE, "Error occurred while getting launch token."}, +}; + + +void ret_error_support(sgx_status_t ret) +{ + size_t idx = 0; + size_t ttl = sizeof sgx_errlist/sizeof sgx_errlist[0]; + + for (idx = 0; idx < ttl; idx++) { + if(ret == sgx_errlist[idx].err) { + std::cout << "Error: "<< sgx_errlist[idx].msg << std::endl; + break; + } + } + if (idx == ttl) + std::cout << "Error: Unexpected error occurred." < +void wtlock(prwlock_t lock) +{ + int ret = pthread_rwlock_wrlock(lock); + if(0 != ret) + abort(); +} + +void wtunlock(prwlock_t lock) +{ + int ret = pthread_rwlock_unlock(lock); + if(0 != ret) + abort(); +} + + +void rdlock(prwlock_t lock) +{ + int ret = pthread_rwlock_rdlock(lock); + if(0 != ret) + abort(); +} + +void rdunlock(prwlock_t lock) +{ + int ret = pthread_rwlock_unlock(lock); + if(0 != ret) + abort(); +} + +void init_rwlock(prwlock_t lock) +{ + //use the default attribute. + int ret = pthread_rwlock_init(lock, NULL); + if(0 != ret) + abort(); +} + +void fini_rwlock(prwlock_t lock) +{ + int ret = pthread_rwlock_destroy(lock); + if(0 != ret) + abort(); +} + + diff --git a/sgx-jvm/linux-sgx/SampleCode/PowerTransition/App/rwlock.h b/sgx-jvm/linux-sgx/SampleCode/PowerTransition/App/rwlock.h new file mode 100644 index 0000000000..19161f2845 --- /dev/null +++ b/sgx-jvm/linux-sgx/SampleCode/PowerTransition/App/rwlock.h @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + + + + +#ifndef _RWLOCK_H +#define _RWLOCK_H + +#include +typedef pthread_rwlock_t rwlock_t; +typedef pthread_rwlock_t* prwlock_t; + +#ifdef __cplusplus +extern "C" { +#endif + + void wtlock(prwlock_t lock); + void rdlock(prwlock_t lock); + void rdunlock(prwlock_t lock); + void wtunlock(prwlock_t lock); + void init_rwlock(prwlock_t lock); + void fini_rwlock(prwlock_t lock); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/sgx-jvm/linux-sgx/SampleCode/PowerTransition/Common/types.h b/sgx-jvm/linux-sgx/SampleCode/PowerTransition/Common/types.h new file mode 100644 index 0000000000..a4dc4eaa94 --- /dev/null +++ b/sgx-jvm/linux-sgx/SampleCode/PowerTransition/Common/types.h @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + + + +#ifndef _TYPES_H_ +#define _TYPES_H_ + +#define BUF_NUM 2 + +#define MOD2(x) ((x) % BUF_NUM) + +struct sealed_buf_t +{ + unsigned int index; + void * sealed_buf_ptr[BUF_NUM]; +}; + + +#endif diff --git a/sgx-jvm/linux-sgx/SampleCode/PowerTransition/Enclave/Enclave.config.xml b/sgx-jvm/linux-sgx/SampleCode/PowerTransition/Enclave/Enclave.config.xml new file mode 100644 index 0000000000..23f5748464 --- /dev/null +++ b/sgx-jvm/linux-sgx/SampleCode/PowerTransition/Enclave/Enclave.config.xml @@ -0,0 +1,11 @@ + + 0 + 0 + 0x40000 + 0x100000 + 3 + 1 + 0 + 0 + 0xFFFFFFFF + diff --git a/sgx-jvm/linux-sgx/SampleCode/PowerTransition/Enclave/Enclave.cpp b/sgx-jvm/linux-sgx/SampleCode/PowerTransition/Enclave/Enclave.cpp new file mode 100644 index 0000000000..3918abf4ab --- /dev/null +++ b/sgx-jvm/linux-sgx/SampleCode/PowerTransition/Enclave/Enclave.cpp @@ -0,0 +1,164 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + + + +#include "string.h" +#include "stdlib.h" +#include "stdio.h" +#include "sgx_trts.h" +#include "sgx_thread.h" +#include "sgx_tseal.h" + +#include "Enclave_t.h" + +uint32_t g_secret; +sgx_thread_mutex_t g_mutex = SGX_THREAD_MUTEX_INITIALIZER; + +static inline void free_allocated_memory(void *pointer) +{ + if(pointer != NULL) + { + free(pointer); + pointer = NULL; + } +} + + +int initialize_enclave(struct sealed_buf_t *sealed_buf) +{ + // sealed_buf == NULL indicates it is the first time to initialize the enclave + if(sealed_buf == NULL) + { + sgx_thread_mutex_lock(&g_mutex); + g_secret = 0; + sgx_thread_mutex_unlock(&g_mutex); + return 0; + } + + // It is not the first time to initialize the enclave + // Reinitialize the enclave to recover the secret data from the input backup sealed data. + + uint32_t len = sizeof(sgx_sealed_data_t) + sizeof(uint32_t); + //Check the sealed_buf length and check the outside pointers deeply + if(sealed_buf->sealed_buf_ptr[MOD2(sealed_buf->index)] == NULL || + sealed_buf->sealed_buf_ptr[MOD2(sealed_buf->index + 1)] == NULL || + !sgx_is_outside_enclave(sealed_buf->sealed_buf_ptr[MOD2(sealed_buf->index)], len) || + !sgx_is_outside_enclave(sealed_buf->sealed_buf_ptr[MOD2(sealed_buf->index + 1)], len)) + { + print("Incorrect input parameter(s).\n"); + return -1; + } + + // Retrieve the secret from current backup sealed data + uint32_t unsealed_data = 0; + uint32_t unsealed_data_length = sizeof(g_secret); + uint8_t *plain_text = NULL; + uint32_t plain_text_length = 0; + uint8_t *temp_sealed_buf = (uint8_t *)malloc(len); + if(temp_sealed_buf == NULL) + { + print("Out of memory.\n"); + return -1; + } + + sgx_thread_mutex_lock(&g_mutex); + memcpy(temp_sealed_buf, sealed_buf->sealed_buf_ptr[MOD2(sealed_buf->index)], len); + + // Unseal current sealed buf + sgx_status_t ret = sgx_unseal_data((sgx_sealed_data_t *)temp_sealed_buf, plain_text, &plain_text_length, (uint8_t *)&unsealed_data, &unsealed_data_length); + if(ret == SGX_SUCCESS) + { + g_secret = unsealed_data; + sgx_thread_mutex_unlock(&g_mutex); + free_allocated_memory(temp_sealed_buf); + return 0; + } + else + { + sgx_thread_mutex_unlock(&g_mutex); + print("Failed to reinitialize the enclave.\n"); + free_allocated_memory(temp_sealed_buf); + return -1; + } +} + +int increase_and_seal_data(size_t tid, struct sealed_buf_t* sealed_buf) +{ + uint32_t sealed_len = sizeof(sgx_sealed_data_t) + sizeof(g_secret); + // Check the sealed_buf length and check the outside pointers deeply + if(sealed_buf->sealed_buf_ptr[MOD2(sealed_buf->index)] == NULL || + sealed_buf->sealed_buf_ptr[MOD2(sealed_buf->index + 1)] == NULL || + !sgx_is_outside_enclave(sealed_buf->sealed_buf_ptr[MOD2(sealed_buf->index)], sealed_len) || + !sgx_is_outside_enclave(sealed_buf->sealed_buf_ptr[MOD2(sealed_buf->index + 1)], sealed_len)) + { + print("Incorrect input parameter(s).\n"); + return -1; + } + + char string_buf[BUFSIZ] = {'\0'}; + uint32_t temp_secret = 0; + uint8_t *plain_text = NULL; + uint32_t plain_text_length = 0; + uint8_t *temp_sealed_buf = (uint8_t *)malloc(sealed_len); + if(temp_sealed_buf == NULL) + { + print("Out of memory.\n"); + return -1; + } + memset(temp_sealed_buf, 0, sealed_len); + + sgx_thread_mutex_lock(&g_mutex); + + // Increase and seal the secret data + temp_secret = ++g_secret; + sgx_status_t ret = sgx_seal_data(plain_text_length, plain_text, sizeof(g_secret), (uint8_t *)&g_secret, sealed_len, (sgx_sealed_data_t *)temp_sealed_buf); + if(ret != SGX_SUCCESS) + { + sgx_thread_mutex_unlock(&g_mutex); + print("Failed to seal data\n"); + free_allocated_memory(temp_sealed_buf); + return -1; + } + // Backup the sealed data to outside buffer + memcpy(sealed_buf->sealed_buf_ptr[MOD2(sealed_buf->index + 1)], temp_sealed_buf, sealed_len); + sealed_buf->index++; + + sgx_thread_mutex_unlock(&g_mutex); + free_allocated_memory(temp_sealed_buf); + + // Ocall to print the unsealed secret data outside. + // In theory, the secret data(s) SHOULD NOT be transferred outside the enclave as clear text(s). + // So please DO NOT print any secret outside. Here printing the secret data to outside is only for demo. + snprintf(string_buf, BUFSIZ, "Thread %#x>: %u\n", (unsigned int)tid, (unsigned int)temp_secret); + print(string_buf); + return 0; +} diff --git a/sgx-jvm/linux-sgx/SampleCode/PowerTransition/Enclave/Enclave.edl b/sgx-jvm/linux-sgx/SampleCode/PowerTransition/Enclave/Enclave.edl new file mode 100644 index 0000000000..54aa25a740 --- /dev/null +++ b/sgx-jvm/linux-sgx/SampleCode/PowerTransition/Enclave/Enclave.edl @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + + +enclave { + + // Import the Ocalls for trusted mutex + from "sgx_tstdc.edl" import *; + include "types.h" + + trusted { + public int initialize_enclave([in]struct sealed_buf_t* sealed_buf); + public int increase_and_seal_data(size_t tid, [in, out]struct sealed_buf_t* sealed_buf); + }; + + untrusted { + void print([in, string] const char *string); + }; +}; diff --git a/sgx-jvm/linux-sgx/SampleCode/PowerTransition/Enclave/Enclave.lds b/sgx-jvm/linux-sgx/SampleCode/PowerTransition/Enclave/Enclave.lds new file mode 100644 index 0000000000..b1c6b6fd7e --- /dev/null +++ b/sgx-jvm/linux-sgx/SampleCode/PowerTransition/Enclave/Enclave.lds @@ -0,0 +1,9 @@ +libenclave.so +{ + global: + g_global_data_sim; + g_global_data; + enclave_entry; + local: + *; +}; diff --git a/sgx-jvm/linux-sgx/SampleCode/PowerTransition/Enclave/Enclave_private.pem b/sgx-jvm/linux-sgx/SampleCode/PowerTransition/Enclave/Enclave_private.pem new file mode 100644 index 0000000000..529d07be35 --- /dev/null +++ b/sgx-jvm/linux-sgx/SampleCode/PowerTransition/Enclave/Enclave_private.pem @@ -0,0 +1,39 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIG4gIBAAKCAYEAroOogvsj/fZDZY8XFdkl6dJmky0lRvnWMmpeH41Bla6U1qLZ +AmZuyIF+mQC/cgojIsrBMzBxb1kKqzATF4+XwPwgKz7fmiddmHyYz2WDJfAjIveJ +ZjdMjM4+EytGlkkJ52T8V8ds0/L2qKexJ+NBLxkeQLfV8n1mIk7zX7jguwbCG1Pr +nEMdJ3Sew20vnje+RsngAzdPChoJpVsWi/K7cettX/tbnre1DL02GXc5qJoQYk7b +3zkmhz31TgFrd9VVtmUGyFXAysuSAb3EN+5VnHGr0xKkeg8utErea2FNtNIgua8H +ONfm9Eiyaav1SVKzPHlyqLtcdxH3I8Wg7yqMsaprZ1n5A1v/levxnL8+It02KseD +5HqV4rf/cImSlCt3lpRg8U5E1pyFQ2IVEC/XTDMiI3c+AR+w2jSRB3Bwn9zJtFlW +KHG3m1xGI4ck+Lci1JvWWLXQagQSPtZTsubxTQNx1gsgZhgv1JHVZMdbVlAbbRMC +1nSuJNl7KPAS/VfzAgEDAoIBgHRXxaynbVP5gkO0ug6Qw/E27wzIw4SmjsxG6Wpe +K7kfDeRskKxESdsA/xCrKkwGwhcx1iIgS5+Qscd1Yg+1D9X9asd/P7waPmWoZd+Z +AhlKwhdPsO7PiF3e1AzHhGQwsUTt/Y/aSI1MpHBvy2/s1h9mFCslOUxTmWw0oj/Q +ldIEgWeNR72CE2+jFIJIyml6ftnb6qzPiga8Bm48ubKh0kvySOqnkmnPzgh+JBD6 +JnBmtZbfPT97bwTT+N6rnPqOOApvfHPf15kWI8yDbprG1l4OCUaIUH1AszxLd826 +5IPM+8gINLRDP1MA6azECPjTyHXhtnSIBZCyWSVkc05vYmNXYUNiXWMajcxW9M02 +wKzFELO8NCEAkaTPxwo4SCyIjUxiK1LbQ9h8PSy4c1+gGP4LAMR8xqP4QKg6zdu9 +osUGG/xRe/uufgTBFkcjqBHtK5L5VI0jeNIUAgW/6iNbYXjBMJ0GfauLs+g1VsOm +WfdgXzsb9DYdMa0OXXHypmV4GwKBwQDUwQj8RKJ6c8cT4vcWCoJvJF00+RFL+P3i +Gx2DLERxRrDa8AVGfqaCjsR+3vLgG8V/py+z+dxZYSqeB80Qeo6PDITcRKoeAYh9 +xlT3LJOS+k1cJcEmlbbO2IjLkTmzSwa80fWexKu8/Xv6vv15gpqYl1ngYoqJM3pd +vzmTIOi7MKSZ0WmEQavrZj8zK4endE3v0eAEeQ55j1GImbypSf7Idh7wOXtjZ7WD +Dg6yWDrri+AP/L3gClMj8wsAxMV4ZR8CgcEA0fzDHkFa6raVOxWnObmRoDhAtE0a +cjUj976NM5yyfdf2MrKy4/RhdTiPZ6b08/lBC/+xRfV3xKVGzacm6QjqjZrUpgHC +0LKiZaMtccCJjLtPwQd0jGQEnKfMFaPsnhOc5y8qVkCzVOSthY5qhz0XNotHHFmJ +gffVgB0iqrMTvSL7IA2yqqpOqNRlhaYhNl8TiFP3gIeMtVa9rZy31JPgT2uJ+kfo +gV7sdTPEjPWZd7OshGxWpT6QfVDj/T9T7L6tAoHBAI3WBf2DFvxNL2KXT2QHAZ9t +k3imC4f7U+wSE6zILaDZyzygA4RUbwG0gv8/TJVn2P/Eynf76DuWHGlaiLWnCbSz +Az2DHBQBBaku409zDQym3j1ugMRjzzSQWzJg0SIyBH3hTmnYcn3+Uqcp/lEBvGW6 +O+rsXFt3pukqJmIV8HzLGGaLm62BHUeZf3dyWm+i3p/hQAL7Xvu04QW70xuGqdr5 +afV7p5eaeQIJXyGQJ0eylV/90+qxjMKiB1XYg6WYvwKBwQCL/ddpgOdHJGN8uRom +e7Zq0Csi3hGheMKlKbN3vcxT5U7MdyHtTZZOJbTvxKNNUNYH/8uD+PqDGNneb29G +BfGzvI3EASyLIcGZF3OhKwZd0jUrWk2y7Vhob91jwp2+t73vdMbkKyI4mHOuXvGv +fg95si9oO7EBT+Oqvhccd2J+F1IVXncccYnF4u5ZGWt5lLewN/pVr7MjjykeaHqN +t+rfnQam2psA6fL4zS2zTmZPzR2tnY8Y1GBTi0Ko1OKd1HMCgcAb5cB/7/AQlhP9 +yQa04PLH9ygQkKKptZp7dy5WcWRx0K/hAHRoi2aw1wZqfm7VBNu2SLcs90kCCCxp +6C5sfJi6b8NpNbIPC+sc9wsFr7pGo9SFzQ78UlcWYK2Gu2FxlMjonhka5hvo4zvg +WxlpXKEkaFt3gLd92m/dMqBrHfafH7VwOJY2zT3WIpjwuk0ZzmRg5p0pG/svVQEH +NZmwRwlopysbR69B/n1nefJ84UO50fLh5s5Zr3gBRwbWNZyzhXk= +-----END RSA PRIVATE KEY----- diff --git a/sgx-jvm/linux-sgx/SampleCode/PowerTransition/Makefile b/sgx-jvm/linux-sgx/SampleCode/PowerTransition/Makefile new file mode 100644 index 0000000000..6bccdb7673 --- /dev/null +++ b/sgx-jvm/linux-sgx/SampleCode/PowerTransition/Makefile @@ -0,0 +1,239 @@ +# +# Copyright (C) 2011-2016 Intel Corporation. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# + +####### SGX SDK Settings ######## + +SGX_SDK ?= /opt/intel/sgxsdk +SGX_MODE ?= HW +SGX_ARCH ?= x64 +SGX_DEBUG ?= 1 + +ifeq ($(shell getconf LONG_BIT), 32) + SGX_ARCH := x86 +else ifeq ($(findstring -m32, $(CXXFLAGS)), -m32) + SGX_ARCH := x86 +endif + +ifeq ($(SGX_ARCH), x86) + SGX_COMMON_CFLAGS := -m32 + SGX_LIBRARY_PATH := $(SGX_SDK)/lib + SGX_ENCLAVE_SIGNER := $(SGX_SDK)/bin/x86/sgx_sign + SGX_EDGER8R := $(SGX_SDK)/bin/x86/sgx_edger8r +else + SGX_COMMON_CFLAGS := -m64 + SGX_LIBRARY_PATH := $(SGX_SDK)/lib64 + SGX_ENCLAVE_SIGNER := $(SGX_SDK)/bin/x64/sgx_sign + SGX_EDGER8R := $(SGX_SDK)/bin/x64/sgx_edger8r +endif + +ifeq ($(SGX_DEBUG), 1) +ifeq ($(SGX_PRERELEASE), 1) +$(error Cannot set SGX_DEBUG and SGX_PRERELEASE at the same time!!) +endif +endif + +ifeq ($(SGX_DEBUG), 1) + SGX_COMMON_CFLAGS += -O0 -g +else + SGX_COMMON_CFLAGS += -O2 +endif + +######## App Settings ######## + +ifneq ($(SGX_MODE), HW) + Urts_Library_Name := sgx_urts_sim +else + Urts_Library_Name := sgx_urts +endif + +App_Cpp_Files := $(wildcard App/*.cpp) +App_Include_Paths := -I$(SGX_SDK)/include -I./Common + +App_Compile_CFlags := -fPIC -Wno-attributes $(App_Include_Paths) +# Three configuration modes - Debug, prerelease, release +# Debug - Macro DEBUG enabled. +# Prerelease - Macro NDEBUG and EDEBUG enabled. +# Release - Macro NDEBUG enabled. +ifeq ($(SGX_DEBUG), 1) + App_Compile_CFlags += -DDEBUG -UNDEBUG -UEDEBUG +else ifeq ($(SGX_PRERELEASE), 1) + App_Compile_CFlags += -DNDEBUG -DEDEBUG -UDEBUG +else + App_Compile_CFlags += -DNDEBUG -UEDEBUG -UDEBUG +endif + +App_Compile_CXXFlags := -std=c++0x $(App_Compile_CFlags) +App_Link_Flags := -L$(SGX_LIBRARY_PATH) -l$(Urts_Library_Name) -lpthread + +ifneq ($(SGX_MODE), HW) + App_Link_Flags += -lsgx_uae_service_sim +else + App_Link_Flags += -lsgx_uae_service +endif + +Gen_Untrusted_Source := App/Enclave_u.c +Gen_Untrusted_Object := App/Enclave_u.o + +App_Objects := $(Gen_Untrusted_Object) $(App_Cpp_Files:.cpp=.o) + +App_Name := app + + +######## Enclave Settings ######## + +ifneq ($(SGX_MODE), HW) + Trts_Library_Name := sgx_trts_sim + Service_Library_Name := sgx_tservice_sim +else + Trts_Library_Name := sgx_trts + Service_Library_Name := sgx_tservice +endif +Crypto_Library_Name := sgx_tcrypto + +Enclave_Cpp_Files := $(wildcard Enclave/*.cpp) + +Enclave_Include_Paths := -I$(SGX_SDK)/include -I$(SGX_SDK)/include/tlibc -I$(SGX_SDK)/include/stlport -I./Common + +Enclave_Compile_CFlags := -nostdinc -ffreestanding -fvisibility=hidden -fpie \ + $(Enclave_Include_Paths) +Enclave_Compile_CXXFlags := -nostdinc++ -std=c++03 $(Enclave_Compile_CFlags) + +# To generate a proper enclave, it is recommended to follow below guideline to link the trusted libraries: +# 1. Link sgx_trts with the `--whole-archive' and `--no-whole-archive' options, +# so that the whole content of trts is included in the enclave. +# 2. For other libraries, you just need to pull the required symbols. +# Use `--start-group' and `--end-group' to link these libraries. +# Do NOT move the libraries linked with `--start-group' and `--end-group' within `--whole-archive' and `--no-whole-archive' options. +# Otherwise, you may get some undesirable errors. +Enclave_Link_Flags := -Wl,--no-undefined -nostdlib -nodefaultlibs -nostartfiles -L$(SGX_LIBRARY_PATH) \ + -Wl,--whole-archive -l$(Trts_Library_Name) -Wl,--no-whole-archive \ + -Wl,--start-group -lsgx_tstdc -lsgx_tstdcxx -l$(Crypto_Library_Name) -l$(Service_Library_Name) -Wl,--end-group \ + -Wl,--version-script=Enclave/Enclave.lds -Wl,-Bstatic -Wl,-Bsymbolic -Wl,--no-undefined \ + -Wl,-pie,-eenclave_entry -Wl,--export-dynamic -Wl,--defsym,__ImageBase=0 + +Enclave_Cpp_Objects := $(Enclave_Cpp_Files:.cpp=.o) +Gen_Trusted_Source := Enclave/Enclave_t.c +Gen_Trusted_Object := Enclave/Enclave_t.o + +Enclave_Objects := $(Gen_Trusted_Object) $(Enclave_Cpp_Files:.cpp=.o) + +Enclave_Name := libenclave.so +Signed_Enclave_Name := libenclave.signed.so +Enclave_Config_File := Enclave/Enclave.config.xml + +ifeq ($(SGX_MODE), HW) +ifeq ($(SGX_DEBUG), 1) + Build_Mode = HW_DEBUG +else ifeq ($(SGX_PRERELEASE), 1) + Build_Mode = HW_PRERELEASE +else + Build_Mode = HW_RELEASE +endif +else +ifeq ($(SGX_DEBUG), 1) + Build_Mode = SIM_DEBUG +else ifeq ($(SGX_PRERELEASE), 1) + Build_Mode = SIM_PRERELEASE +else + Build_Mode = SIM_RELEASE +endif +endif + +ifeq ($(Build_Mode), HW_RELEASE) +all: $(App_Name) $(Enclave_Name) + @echo "The project has been built in release hardware mode." + @echo "Please sign the $(Enclave_Name) first with your signing key before you run the $(App_Name) to launch and access the enclave." + @echo "To sign the enclave use the command:" + @echo " $(SGX_ENCLAVE_SIGNER) sign -key -enclave $(Enclave_Name) -out <$(Signed_Enclave_Name)> -config $(Enclave_Config_File)" + @echo "You can also sign the enclave using an external signing tool." + @echo "To build the project in simulation mode set SGX_MODE=SIM. To build the project in prerelease mode set SGX_PRERELEASE=1 and SGX_MODE=HW." +else +all: $(App_Name) $(Signed_Enclave_Name) +ifeq ($(Build_Mode), HW_DEBUG) + @echo "The project has been built in debug hardware mode." +else ifeq ($(Build_Mode), SIM_DEBUG) + @echo "The project has been built in debug simulation mode." +else ifeq ($(Build_Mode), HW_PRERELEASE) + @echo "The project has been built in pre-release hardware mode." +else ifeq ($(Build_Mode), SIM_PRERELEASE) + @echo "The project has been built in pre-release simulation mode." +else + @echo "The project has been built in release simulation mode." +endif +endif + +######## App Objects ######## + +$(Gen_Untrusted_Source): $(SGX_EDGER8R) Enclave/Enclave.edl + @cd App && $(SGX_EDGER8R) --untrusted ../Enclave/Enclave.edl --search-path $(SGX_SDK)/include + @echo "GEN => $@" + +$(Gen_Untrusted_Object): $(Gen_Untrusted_Source) + @$(CC) $(SGX_COMMON_CFLAGS) $(App_Compile_CFlags) -c $< -o $@ + @echo "CC <= $<" + +App/%.o: App/%.cpp + @$(CXX) $(SGX_COMMON_CFLAGS) $(App_Compile_CXXFlags) -c $< -o $@ + @echo "CXX <= $<" + +$(App_Name): $(App_Objects) + @$(CXX) $(SGX_COMMON_CFLAGS) $^ -o $@ $(App_Link_Flags) + @echo "LINK => $@" + + +######## Enclave Objects ######## + +$(Gen_Trusted_Source): $(SGX_EDGER8R) Enclave/Enclave.edl + @cd Enclave && $(SGX_EDGER8R) --trusted Enclave.edl --search-path $(SGX_SDK)/include + @echo "GEN => $@" +$(Gen_Trusted_Object): $(Gen_Trusted_Source) + @$(CC) $(SGX_COMMON_CFLAGS) $(Enclave_Compile_CFlags) -c $< -o $@ + @echo "CC <= $<" + +Enclave/%.o: Enclave/%.cpp + @$(CXX) $(SGX_COMMON_CFLAGS) $(Enclave_Compile_CXXFlags) -c $< -o $@ + @echo "CXX <= $<" + +$(Enclave_Name): $(Enclave_Objects) + @$(CXX) $(SGX_COMMON_CFLAGS) $(Enclave_Objects) -o $@ $(Enclave_Link_Flags) + @echo "LINK => $@" + +$(Signed_Enclave_Name): $(Enclave_Name) + @$(SGX_ENCLAVE_SIGNER) sign -key Enclave/Enclave_private.pem -enclave $(Enclave_Name) -out $@ -config $(Enclave_Config_File) + @echo "SIGN => $@" + + +######### clean up ######## +.PHONY: clean + + +clean: + @rm -f $(App_Name) $(App_Objects) $(Enclave_Name) $(Enclave_Objects) App/Enclave_u.* Enclave/Enclave_t.* $(Signed_Enclave_Name) diff --git a/sgx-jvm/linux-sgx/SampleCode/PowerTransition/README.txt b/sgx-jvm/linux-sgx/SampleCode/PowerTransition/README.txt new file mode 100644 index 0000000000..23c298b021 --- /dev/null +++ b/sgx-jvm/linux-sgx/SampleCode/PowerTransition/README.txt @@ -0,0 +1,26 @@ +-------------------------- +Purpose of PowerTransition +-------------------------- +The project demonstrates one method about power transition handling for Intel(R) +Software Guard Extensions projects development. + +------------------------------------ +How to Build/Execute the Sample Code +------------------------------------ +1. Install Intel(R) SGX SDK for Linux* OS +2. Build the project with the prepared Makefile: + a. Hardware Mode, Debug build: + $ make + b. Hardware Mode, Pre-release build: + $ make SGX_PRERELEASE=1 SGX_DEBUG=0 + c. Hardware Mode, Release build: + $ make SGX_DEBUG=0 + d. Simulation Mode, Debug build: + $ make SGX_MODE=SIM + e. Simulation Mode, Pre-release build: + $ make SGX_MODE=SIM SGX_PRERELEASE=1 SGX_DEBUG=0 + f. Simulation Mode, Release build: + $ make SGX_MODE=SIM SGX_DEBUG=0 +3. Execute the binary directly: + $ ./app +4. Remember to "make clean" before switching build mode diff --git a/sgx-jvm/linux-sgx/SampleCode/RemoteAttestation/.cproject b/sgx-jvm/linux-sgx/SampleCode/RemoteAttestation/.cproject new file mode 100644 index 0000000000..efe1117e34 --- /dev/null +++ b/sgx-jvm/linux-sgx/SampleCode/RemoteAttestation/.cproject @@ -0,0 +1,219 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sgx-jvm/linux-sgx/SampleCode/RemoteAttestation/.project b/sgx-jvm/linux-sgx/SampleCode/RemoteAttestation/.project new file mode 100644 index 0000000000..3cc71f6a6a --- /dev/null +++ b/sgx-jvm/linux-sgx/SampleCode/RemoteAttestation/.project @@ -0,0 +1,28 @@ + + + RemoteAttestation + + + + + + org.eclipse.cdt.managedbuilder.core.genmakebuilder + clean,full,incremental, + + + + + org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder + full,incremental, + + + + + + org.eclipse.cdt.core.cnature + org.eclipse.cdt.managedbuilder.core.managedBuildNature + org.eclipse.cdt.managedbuilder.core.ScannerConfigNature + org.eclipse.cdt.core.ccnature + com.intel.sgx.sgxnature + + diff --git a/sgx-jvm/linux-sgx/SampleCode/RemoteAttestation/Makefile b/sgx-jvm/linux-sgx/SampleCode/RemoteAttestation/Makefile new file mode 100644 index 0000000000..1f6e5af6f7 --- /dev/null +++ b/sgx-jvm/linux-sgx/SampleCode/RemoteAttestation/Makefile @@ -0,0 +1,263 @@ +# +# Copyright (C) 2011-2016 Intel Corporation. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# + +######## SGX SDK Settings ######## + +SGX_SDK ?= /opt/intel/sgxsdk +SGX_MODE ?= HW +SGX_ARCH ?= x64 +SGX_DEBUG ?= 1 + +ifeq ($(shell getconf LONG_BIT), 32) + SGX_ARCH := x86 +else ifeq ($(findstring -m32, $(CXXFLAGS)), -m32) + SGX_ARCH := x86 +endif + +ifeq ($(SGX_ARCH), x86) + SGX_COMMON_CFLAGS := -m32 + SGX_LIBRARY_PATH := $(SGX_SDK)/lib + SGX_ENCLAVE_SIGNER := $(SGX_SDK)/bin/x86/sgx_sign + SGX_EDGER8R := $(SGX_SDK)/bin/x86/sgx_edger8r +else + SGX_COMMON_CFLAGS := -m64 + SGX_LIBRARY_PATH := $(SGX_SDK)/lib64 + SGX_ENCLAVE_SIGNER := $(SGX_SDK)/bin/x64/sgx_sign + SGX_EDGER8R := $(SGX_SDK)/bin/x64/sgx_edger8r +endif + +ifeq ($(SGX_DEBUG), 1) +ifeq ($(SGX_PRERELEASE), 1) +$(error Cannot set SGX_DEBUG and SGX_PRERELEASE at the same time!!) +endif +endif + +ifeq ($(SGX_DEBUG), 1) + SGX_COMMON_CFLAGS += -O0 -g +else + SGX_COMMON_CFLAGS += -O2 +endif + +ifeq ($(SUPPLIED_KEY_DERIVATION), 1) + SGX_COMMON_CFLAGS += -DSUPPLIED_KEY_DERIVATION +endif +######## App Settings ######## + +ifneq ($(SGX_MODE), HW) + Urts_Library_Name := sgx_urts_sim +else + Urts_Library_Name := sgx_urts +endif + +App_Cpp_Files := isv_app/isv_app.cpp +App_Include_Paths := -Iservice_provider -I$(SGX_SDK)/include + +App_C_Flags := $(SGX_COMMON_CFLAGS) -fPIC -Wno-attributes $(App_Include_Paths) + +# Three configuration modes - Debug, prerelease, release +# Debug - Macro DEBUG enabled. +# Prerelease - Macro NDEBUG and EDEBUG enabled. +# Release - Macro NDEBUG enabled. +ifeq ($(SGX_DEBUG), 1) + App_C_Flags += -DDEBUG -UNDEBUG -UEDEBUG +else ifeq ($(SGX_PRERELEASE), 1) + App_C_Flags += -DNDEBUG -DEDEBUG -UDEBUG +else + App_C_Flags += -DNDEBUG -UEDEBUG -UDEBUG +endif + +App_Cpp_Flags := $(App_C_Flags) -std=c++11 +App_Link_Flags := $(SGX_COMMON_CFLAGS) -L$(SGX_LIBRARY_PATH) -l$(Urts_Library_Name) -L. -lsgx_ukey_exchange -lpthread -lservice_provider -Wl,-rpath=$(CURDIR)/sample_libcrypto -Wl,-rpath=$(CURDIR) + +ifneq ($(SGX_MODE), HW) + App_Link_Flags += -lsgx_uae_service_sim +else + App_Link_Flags += -lsgx_uae_service +endif + +App_Cpp_Objects := $(App_Cpp_Files:.cpp=.o) + +App_Name := app + +######## Service Provider Settings ######## + +ServiceProvider_Cpp_Files := service_provider/ecp.cpp service_provider/network_ra.cpp service_provider/service_provider.cpp service_provider/ias_ra.cpp +ServiceProvider_Include_Paths := -I$(SGX_SDK)/include -I$(SGX_SDK)/include/tlibc -I$(SGX_SDK)/include/stlport -Isample_libcrypto + +ServiceProvider_C_Flags := $(SGX_COMMON_CFLAGS) -fPIC -Wno-attributes -I$(SGX_SDK)/include -Isample_libcrypto +ServiceProvider_Cpp_Flags := $(ServiceProvider_C_Flags) -std=c++11 +ServiceProvider_Link_Flags := -shared $(SGX_COMMON_CFLAGS) -L$(SGX_LIBRARY_PATH) -lsample_libcrypto -Lsample_libcrypto + +ServiceProvider_Cpp_Objects := $(ServiceProvider_Cpp_Files:.cpp=.o) + +######## Enclave Settings ######## + +ifneq ($(SGX_MODE), HW) + Trts_Library_Name := sgx_trts_sim + Service_Library_Name := sgx_tservice_sim +else + Trts_Library_Name := sgx_trts + Service_Library_Name := sgx_tservice +endif +Crypto_Library_Name := sgx_tcrypto + +Enclave_Cpp_Files := isv_enclave/isv_enclave.cpp +Enclave_Include_Paths := -I$(SGX_SDK)/include -I$(SGX_SDK)/include/tlibc -I$(SGX_SDK)/include/stlport + +Enclave_C_Flags := $(SGX_COMMON_CFLAGS) -nostdinc -fvisibility=hidden -fpie -fstack-protector $(Enclave_Include_Paths) +Enclave_Cpp_Flags := $(Enclave_C_Flags) -std=c++03 -nostdinc++ + +# To generate a proper enclave, it is recommended to follow below guideline to link the trusted libraries: +# 1. Link sgx_trts with the `--whole-archive' and `--no-whole-archive' options, +# so that the whole content of trts is included in the enclave. +# 2. For other libraries, you just need to pull the required symbols. +# Use `--start-group' and `--end-group' to link these libraries. +# Do NOT move the libraries linked with `--start-group' and `--end-group' within `--whole-archive' and `--no-whole-archive' options. +# Otherwise, you may get some undesirable errors. +Enclave_Link_Flags := $(SGX_COMMON_CFLAGS) -Wl,--no-undefined -nostdlib -nodefaultlibs -nostartfiles -L$(SGX_LIBRARY_PATH) \ + -Wl,--whole-archive -l$(Trts_Library_Name) -Wl,--no-whole-archive \ + -Wl,--start-group -lsgx_tstdc -lsgx_tstdcxx -lsgx_tkey_exchange -l$(Crypto_Library_Name) -l$(Service_Library_Name) -Wl,--end-group \ + -Wl,-Bstatic -Wl,-Bsymbolic -Wl,--no-undefined \ + -Wl,-pie,-eenclave_entry -Wl,--export-dynamic \ + -Wl,--defsym,__ImageBase=0 \ + -Wl,--version-script=isv_enclave/isv_enclave.lds + +Enclave_Cpp_Objects := $(Enclave_Cpp_Files:.cpp=.o) + +Enclave_Name := isv_enclave.so +Signed_Enclave_Name := isv_enclave.signed.so +Enclave_Config_File := isv_enclave/isv_enclave.config.xml + +ifeq ($(SGX_MODE), HW) +ifeq ($(SGX_DEBUG), 1) + Build_Mode = HW_DEBUG +else ifeq ($(SGX_PRERELEASE), 1) + Build_Mode = HW_PRERELEASE +else + Build_Mode = HW_RELEASE +endif +else +ifeq ($(SGX_DEBUG), 1) + Build_Mode = SIM_DEBUG +else ifeq ($(SGX_PRERELEASE), 1) + Build_Mode = SIM_PRERELEASE +else + Build_Mode = SIM_RELEASE +endif +endif + + +.PHONY: all run + +ifeq ($(Build_Mode), HW_RELEASE) +all: libservice_provider.so $(App_Name) $(Enclave_Name) + @echo "The project has been built in release hardware mode." + @echo "Please sign the $(Enclave_Name) first with your signing key before you run the $(App_Name) to launch and access the enclave." + @echo "To sign the enclave use the command:" + @echo " $(SGX_ENCLAVE_SIGNER) sign -key -enclave $(Enclave_Name) -out <$(Signed_Enclave_Name)> -config $(Enclave_Config_File)" + @echo "You can also sign the enclave using an external signing tool." + @echo "To build the project in simulation mode set SGX_MODE=SIM. To build the project in prerelease mode set SGX_PRERELEASE=1 and SGX_MODE=HW." +else +all: libservice_provider.so $(App_Name) $(Signed_Enclave_Name) +ifeq ($(Build_Mode), HW_DEBUG) + @echo "The project has been built in debug hardware mode." +else ifeq ($(Build_Mode), SIM_DEBUG) + @echo "The project has been built in debug simulation mode." +else ifeq ($(Build_Mode), HW_PRERELEASE) + @echo "The project has been built in pre-release hardware mode." +else ifeq ($(Build_Mode), SIM_PRERELEASE) + @echo "The project has been built in pre-release simulation mode." +else + @echo "The project has been built in release simulation mode." +endif +endif + +run: all +ifneq ($(Build_Mode), HW_RELEASE) + @$(CURDIR)/$(App_Name) + @echo "RUN => $(App_Name) [$(SGX_MODE)|$(SGX_ARCH), OK]" +endif + +######## App Objects ######## + +isv_app/isv_enclave_u.c: $(SGX_EDGER8R) isv_enclave/isv_enclave.edl + @cd isv_app && $(SGX_EDGER8R) --untrusted ../isv_enclave/isv_enclave.edl --search-path ../isv_enclave --search-path $(SGX_SDK)/include + @echo "GEN => $@" + +isv_app/isv_enclave_u.o: isv_app/isv_enclave_u.c + @$(CC) $(App_C_Flags) -c $< -o $@ + @echo "CC <= $<" + +isv_app/%.o: isv_app/%.cpp + @$(CXX) $(App_Cpp_Flags) -c $< -o $@ + @echo "CXX <= $<" + +$(App_Name): isv_app/isv_enclave_u.o $(App_Cpp_Objects) + @$(CXX) $^ -o $@ $(App_Link_Flags) + @echo "LINK => $@" + +######## Service Provider Objects ######## + + +service_provider/%.o: service_provider/%.cpp + @$(CXX) $(ServiceProvider_Cpp_Flags) -c $< -o $@ + @echo "CXX <= $<" + +libservice_provider.so: $(ServiceProvider_Cpp_Objects) + @$(CXX) $^ -o $@ $(ServiceProvider_Link_Flags) + @echo "LINK => $@" + +######## Enclave Objects ######## + +isv_enclave/isv_enclave_t.c: $(SGX_EDGER8R) isv_enclave/isv_enclave.edl + @cd isv_enclave && $(SGX_EDGER8R) --trusted ../isv_enclave/isv_enclave.edl --search-path ../isv_enclave --search-path $(SGX_SDK)/include + @echo "GEN => $@" + +isv_enclave/isv_enclave_t.o: isv_enclave/isv_enclave_t.c + @$(CC) $(Enclave_C_Flags) -c $< -o $@ + @echo "CC <= $<" + +isv_enclave/%.o: isv_enclave/%.cpp + @$(CXX) $(Enclave_Cpp_Flags) -c $< -o $@ + @echo "CXX <= $<" + +$(Enclave_Name): isv_enclave/isv_enclave_t.o $(Enclave_Cpp_Objects) + @$(CXX) $^ -o $@ $(Enclave_Link_Flags) + @echo "LINK => $@" + +$(Signed_Enclave_Name): $(Enclave_Name) + @$(SGX_ENCLAVE_SIGNER) sign -key isv_enclave/isv_enclave_private.pem -enclave $(Enclave_Name) -out $@ -config $(Enclave_Config_File) + @echo "SIGN => $@" + +.PHONY: clean + +clean: + @rm -f $(App_Name) $(Enclave_Name) $(Signed_Enclave_Name) $(App_Cpp_Objects) isv_app/isv_enclave_u.* $(Enclave_Cpp_Objects) isv_enclave/isv_enclave_t.* libservice_provider.* $(ServiceProvider_Cpp_Objects) diff --git a/sgx-jvm/linux-sgx/SampleCode/RemoteAttestation/README.txt b/sgx-jvm/linux-sgx/SampleCode/RemoteAttestation/README.txt new file mode 100644 index 0000000000..2b78193368 --- /dev/null +++ b/sgx-jvm/linux-sgx/SampleCode/RemoteAttestation/README.txt @@ -0,0 +1,27 @@ +---------------------------- +Purpose of RemoteAttestation +---------------------------- +The project demonstrates: +- How an application enclave can attest to a remote party +- How an application enclave and the remote party can establish a secure session + +------------------------------------ +How to Build/Execute the Sample Code +------------------------------------ +1. Install Intel(R) SGX SDK for Linux* OS +2. Build the project with the prepared Makefile: + a. Hardware Mode, Debug build: + $ make + b. Hardware Mode, Pre-release build: + $ make SGX_PRERELEASE=1 SGX_DEBUG=0 + c. Hardware Mode, Release build: + $ make SGX_DEBUG=0 + d. Simulation Mode, Debug build: + $ make SGX_MODE=SIM + e. Simulation Mode, Pre-release build: + $ make SGX_MODE=SIM SGX_PRERELEASE=1 SGX_DEBUG=0 + f. Simulation Mode, Release build: + $ make SGX_MODE=SIM SGX_DEBUG=0 +3. Execute the binary directly: + $ ./app +4. Remember to "make clean" before switching build mode diff --git a/sgx-jvm/linux-sgx/SampleCode/RemoteAttestation/isv_app/isv_app.cpp b/sgx-jvm/linux-sgx/SampleCode/RemoteAttestation/isv_app/isv_app.cpp new file mode 100644 index 0000000000..0fb3590acb --- /dev/null +++ b/sgx-jvm/linux-sgx/SampleCode/RemoteAttestation/isv_app/isv_app.cpp @@ -0,0 +1,716 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +// This sample is confined to the communication between a SGX client platform +// and an ISV Application Server. + + + +#include +#include +#include +// Needed for definition of remote attestation messages. +#include "remote_attestation_result.h" + +#include "isv_enclave_u.h" + +// Needed to call untrusted key exchange library APIs, i.e. sgx_ra_proc_msg2. +#include "sgx_ukey_exchange.h" + +// Needed to get service provider's information, in your real project, you will +// need to talk to real server. +#include "network_ra.h" + +// Needed to create enclave and do ecall. +#include "sgx_urts.h" + +// Needed to query extended epid group id. +#include "sgx_uae_service.h" + +#include "service_provider.h" + +#ifndef SAFE_FREE +#define SAFE_FREE(ptr) {if (NULL != (ptr)) {free(ptr); (ptr) = NULL;}} +#endif + +// In addition to generating and sending messages, this application +// can use pre-generated messages to verify the generation of +// messages and the information flow. +#include "sample_messages.h" + + +#define ENCLAVE_PATH "isv_enclave.signed.so" + +uint8_t* msg1_samples[] = { msg1_sample1, msg1_sample2 }; +uint8_t* msg2_samples[] = { msg2_sample1, msg2_sample2 }; +uint8_t* msg3_samples[MSG3_BODY_SIZE] = { msg3_sample1, msg3_sample2 }; +uint8_t* attestation_msg_samples[] = + { attestation_msg_sample1, attestation_msg_sample2}; + +// Some utility functions to output some of the data structures passed between +// the ISV app and the remote attestation service provider. +void PRINT_BYTE_ARRAY( + FILE *file, void *mem, uint32_t len) +{ + if(!mem || !len) + { + fprintf(file, "\n( null )\n"); + return; + } + uint8_t *array = (uint8_t *)mem; + fprintf(file, "%u bytes:\n{\n", len); + uint32_t i = 0; + for(i = 0; i < len - 1; i++) + { + fprintf(file, "0x%x, ", array[i]); + if(i % 8 == 7) fprintf(file, "\n"); + } + fprintf(file, "0x%x ", array[i]); + fprintf(file, "\n}\n"); +} + + +void PRINT_ATTESTATION_SERVICE_RESPONSE( + FILE *file, + ra_samp_response_header_t *response) +{ + if(!response) + { + fprintf(file, "\t\n( null )\n"); + return; + } + + fprintf(file, "RESPONSE TYPE: 0x%x\n", response->type); + fprintf(file, "RESPONSE STATUS: 0x%x 0x%x\n", response->status[0], + response->status[1]); + fprintf(file, "RESPONSE BODY SIZE: %u\n", response->size); + + if(response->type == TYPE_RA_MSG2) + { + sgx_ra_msg2_t* p_msg2_body = (sgx_ra_msg2_t*)(response->body); + + fprintf(file, "MSG2 gb - "); + PRINT_BYTE_ARRAY(file, &(p_msg2_body->g_b), sizeof(p_msg2_body->g_b)); + + fprintf(file, "MSG2 spid - "); + PRINT_BYTE_ARRAY(file, &(p_msg2_body->spid), sizeof(p_msg2_body->spid)); + + fprintf(file, "MSG2 quote_type : %hx\n", p_msg2_body->quote_type); + + fprintf(file, "MSG2 kdf_id : %hx\n", p_msg2_body->kdf_id); + + fprintf(file, "MSG2 sign_gb_ga - "); + PRINT_BYTE_ARRAY(file, &(p_msg2_body->sign_gb_ga), + sizeof(p_msg2_body->sign_gb_ga)); + + fprintf(file, "MSG2 mac - "); + PRINT_BYTE_ARRAY(file, &(p_msg2_body->mac), sizeof(p_msg2_body->mac)); + + fprintf(file, "MSG2 sig_rl - "); + PRINT_BYTE_ARRAY(file, &(p_msg2_body->sig_rl), + p_msg2_body->sig_rl_size); + } + else if(response->type == TYPE_RA_ATT_RESULT) + { + sample_ra_att_result_msg_t *p_att_result = + (sample_ra_att_result_msg_t *)(response->body); + fprintf(file, "ATTESTATION RESULT MSG platform_info_blob - "); + PRINT_BYTE_ARRAY(file, &(p_att_result->platform_info_blob), + sizeof(p_att_result->platform_info_blob)); + + fprintf(file, "ATTESTATION RESULT MSG mac - "); + PRINT_BYTE_ARRAY(file, &(p_att_result->mac), sizeof(p_att_result->mac)); + + fprintf(file, "ATTESTATION RESULT MSG secret.payload_tag - %u bytes\n", + p_att_result->secret.payload_size); + + fprintf(file, "ATTESTATION RESULT MSG secret.payload - "); + PRINT_BYTE_ARRAY(file, p_att_result->secret.payload, + p_att_result->secret.payload_size); + } + else + { + fprintf(file, "\nERROR in printing out the response. " + "Response of type not supported %d\n", response->type); + } +} + +// This sample code doesn't have any recovery/retry mechanisms for the remote +// attestation. Since the enclave can be lost due S3 transitions, apps +// susceptible to S3 transitions should have logic to restart attestation in +// these scenarios. +#define _T(x) x +int main(int argc, char* argv[]) +{ + int ret = 0; + ra_samp_request_header_t *p_msg0_full = NULL; + ra_samp_response_header_t *p_msg0_resp_full = NULL; + ra_samp_request_header_t *p_msg1_full = NULL; + ra_samp_response_header_t *p_msg2_full = NULL; + sgx_ra_msg3_t *p_msg3 = NULL; + ra_samp_response_header_t* p_att_result_msg_full = NULL; + sgx_enclave_id_t enclave_id = 0; + int enclave_lost_retry_time = 1; + int busy_retry_time = 4; + sgx_ra_context_t context = INT_MAX; + sgx_status_t status = SGX_SUCCESS; + ra_samp_request_header_t* p_msg3_full = NULL; + + int32_t verify_index = -1; + int32_t verification_samples = sizeof(msg1_samples)/sizeof(msg1_samples[0]); + + FILE* OUTPUT = stdout; + +#define VERIFICATION_INDEX_IS_VALID() (verify_index > 0 && \ + verify_index <= verification_samples) +#define GET_VERIFICATION_ARRAY_INDEX() (verify_index-1) + + if(argc > 1) + { + + verify_index = atoi(argv[1]); + + if( VERIFICATION_INDEX_IS_VALID()) + { + fprintf(OUTPUT, "\nVerifying precomputed attestation messages " + "using precomputed values# %d\n", verify_index); + } + else + { + fprintf(OUTPUT, "\nValid invocations are:\n"); + fprintf(OUTPUT, "\n\tisv_app\n"); + fprintf(OUTPUT, "\n\tisv_app \n"); + fprintf(OUTPUT, "\nValid indices are [1 - %d]\n", + verification_samples); + fprintf(OUTPUT, "\nUsing a verification index uses precomputed " + "messages to assist debugging the remote attestation " + "service provider.\n"); + return -1; + } + } + + // Preparation for remote attestation by configuring extended epid group id. + { + uint32_t extended_epid_group_id = 0; + ret = sgx_get_extended_epid_group_id(&extended_epid_group_id); + if (SGX_SUCCESS != ret) + { + ret = -1; + fprintf(OUTPUT, "\nError, call sgx_get_extended_epid_group_id fail [%s].", + __FUNCTION__); + return ret; + } + fprintf(OUTPUT, "\nCall sgx_get_extended_epid_group_id success."); + + p_msg0_full = (ra_samp_request_header_t*) + malloc(sizeof(ra_samp_request_header_t) + +sizeof(uint32_t)); + if (NULL == p_msg0_full) + { + ret = -1; + goto CLEANUP; + } + p_msg0_full->type = TYPE_RA_MSG0; + p_msg0_full->size = sizeof(uint32_t); + + *(uint32_t*)((uint8_t*)p_msg0_full + sizeof(ra_samp_request_header_t)) = extended_epid_group_id; + { + + fprintf(OUTPUT, "\nMSG0 body generated -\n"); + + PRINT_BYTE_ARRAY(OUTPUT, p_msg0_full->body, p_msg0_full->size); + + } + // The ISV application sends msg0 to the SP. + // The ISV decides whether to support this extended epid group id. + fprintf(OUTPUT, "\nSending msg0 to remote attestation service provider.\n"); + + ret = ra_network_send_receive("http://SampleServiceProvider.intel.com/", + p_msg0_full, + &p_msg0_resp_full); + if (ret != 0) + { + fprintf(OUTPUT, "\nError, ra_network_send_receive for msg0 failed " + "[%s].", __FUNCTION__); + goto CLEANUP; + } + fprintf(OUTPUT, "\nSent MSG0 to remote attestation service.\n"); + } + // Remote attestation will be initiated the ISV server challenges the ISV + // app or if the ISV app detects it doesn't have the credentials + // (shared secret) from a previous attestation required for secure + // communication with the server. + { + // ISV application creates the ISV enclave. + int launch_token_update = 0; + sgx_launch_token_t launch_token = {0}; + memset(&launch_token, 0, sizeof(sgx_launch_token_t)); + do + { + ret = sgx_create_enclave(_T(ENCLAVE_PATH), + SGX_DEBUG_FLAG, + &launch_token, + &launch_token_update, + &enclave_id, NULL); + if(SGX_SUCCESS != ret) + { + ret = -1; + fprintf(OUTPUT, "\nError, call sgx_create_enclave fail [%s].", + __FUNCTION__); + goto CLEANUP; + } + fprintf(OUTPUT, "\nCall sgx_create_enclave success."); + + ret = enclave_init_ra(enclave_id, + &status, + false, + &context); + //Ideally, this check would be around the full attestation flow. + } while (SGX_ERROR_ENCLAVE_LOST == ret && enclave_lost_retry_time--); + + if(SGX_SUCCESS != ret || status) + { + ret = -1; + fprintf(OUTPUT, "\nError, call enclave_init_ra fail [%s].", + __FUNCTION__); + goto CLEANUP; + } + fprintf(OUTPUT, "\nCall enclave_init_ra success."); + + // isv application call uke sgx_ra_get_msg1 + p_msg1_full = (ra_samp_request_header_t*) + malloc(sizeof(ra_samp_request_header_t) + + sizeof(sgx_ra_msg1_t)); + if(NULL == p_msg1_full) + { + ret = -1; + goto CLEANUP; + } + p_msg1_full->type = TYPE_RA_MSG1; + p_msg1_full->size = sizeof(sgx_ra_msg1_t); + do + { + ret = sgx_ra_get_msg1(context, enclave_id, sgx_ra_get_ga, + (sgx_ra_msg1_t*)((uint8_t*)p_msg1_full + + sizeof(ra_samp_request_header_t))); + sleep(3); // Wait 3s between retries + } while (SGX_ERROR_BUSY == ret && busy_retry_time--); + if(SGX_SUCCESS != ret) + { + ret = -1; + fprintf(OUTPUT, "\nError, call sgx_ra_get_msg1 fail [%s].", + __FUNCTION__); + goto CLEANUP; + } + else + { + fprintf(OUTPUT, "\nCall sgx_ra_get_msg1 success.\n"); + + fprintf(OUTPUT, "\nMSG1 body generated -\n"); + + PRINT_BYTE_ARRAY(OUTPUT, p_msg1_full->body, p_msg1_full->size); + + } + + if(VERIFICATION_INDEX_IS_VALID()) + { + + memcpy_s(p_msg1_full->body, p_msg1_full->size, + msg1_samples[GET_VERIFICATION_ARRAY_INDEX()], + p_msg1_full->size); + + fprintf(OUTPUT, "\nInstead of using the recently generated MSG1, " + "we will use the following precomputed MSG1 -\n"); + + PRINT_BYTE_ARRAY(OUTPUT, p_msg1_full->body, p_msg1_full->size); + } + + + // The ISV application sends msg1 to the SP to get msg2, + // msg2 needs to be freed when no longer needed. + // The ISV decides whether to use linkable or unlinkable signatures. + fprintf(OUTPUT, "\nSending msg1 to remote attestation service provider." + "Expecting msg2 back.\n"); + + + ret = ra_network_send_receive("http://SampleServiceProvider.intel.com/", + p_msg1_full, + &p_msg2_full); + + if(ret != 0 || !p_msg2_full) + { + fprintf(OUTPUT, "\nError, ra_network_send_receive for msg1 failed " + "[%s].", __FUNCTION__); + if(VERIFICATION_INDEX_IS_VALID()) + { + fprintf(OUTPUT, "\nBecause we are in verification mode we will " + "ignore this error.\n"); + fprintf(OUTPUT, "\nInstead, we will pretend we received the " + "following MSG2 - \n"); + + SAFE_FREE(p_msg2_full); + ra_samp_response_header_t* precomputed_msg2 = + (ra_samp_response_header_t*)msg2_samples[ + GET_VERIFICATION_ARRAY_INDEX()]; + const size_t msg2_full_size = sizeof(ra_samp_response_header_t) + + precomputed_msg2->size; + p_msg2_full = + (ra_samp_response_header_t*)malloc(msg2_full_size); + if(NULL == p_msg2_full) + { + ret = -1; + goto CLEANUP; + } + memcpy_s(p_msg2_full, msg2_full_size, precomputed_msg2, + msg2_full_size); + + PRINT_BYTE_ARRAY(OUTPUT, p_msg2_full, + sizeof(ra_samp_response_header_t) + + p_msg2_full->size); + } + else + { + goto CLEANUP; + } + } + else + { + // Successfully sent msg1 and received a msg2 back. + // Time now to check msg2. + if(TYPE_RA_MSG2 != p_msg2_full->type) + { + + fprintf(OUTPUT, "\nError, didn't get MSG2 in response to MSG1. " + "[%s].", __FUNCTION__); + + if(VERIFICATION_INDEX_IS_VALID()) + { + fprintf(OUTPUT, "\nBecause we are in verification mode we " + "will ignore this error."); + } + else + { + goto CLEANUP; + } + } + + fprintf(OUTPUT, "\nSent MSG1 to remote attestation service " + "provider. Received the following MSG2:\n"); + PRINT_BYTE_ARRAY(OUTPUT, p_msg2_full, + sizeof(ra_samp_response_header_t) + + p_msg2_full->size); + + fprintf(OUTPUT, "\nA more descriptive representation of MSG2:\n"); + PRINT_ATTESTATION_SERVICE_RESPONSE(OUTPUT, p_msg2_full); + + if( VERIFICATION_INDEX_IS_VALID() ) + { + // The response should match the precomputed MSG2: + ra_samp_response_header_t* precomputed_msg2 = + (ra_samp_response_header_t *) + msg2_samples[GET_VERIFICATION_ARRAY_INDEX()]; + if(memcmp( precomputed_msg2, p_msg2_full, + sizeof(ra_samp_response_header_t) + p_msg2_full->size)) + { + fprintf(OUTPUT, "\nVerification ERROR. Our precomputed " + "value for MSG2 does NOT match.\n"); + fprintf(OUTPUT, "\nPrecomputed value for MSG2:\n"); + PRINT_BYTE_ARRAY(OUTPUT, precomputed_msg2, + sizeof(ra_samp_response_header_t) + + precomputed_msg2->size); + fprintf(OUTPUT, "\nA more descriptive representation " + "of precomputed value for MSG2:\n"); + PRINT_ATTESTATION_SERVICE_RESPONSE(OUTPUT, + precomputed_msg2); + } + else + { + fprintf(OUTPUT, "\nVerification COMPLETE. Remote " + "attestation service provider generated a " + "matching MSG2.\n"); + } + } + + } + + sgx_ra_msg2_t* p_msg2_body = (sgx_ra_msg2_t*)((uint8_t*)p_msg2_full + + sizeof(ra_samp_response_header_t)); + + + uint32_t msg3_size = 0; + if( VERIFICATION_INDEX_IS_VALID()) + { + // We cannot generate a valid MSG3 using the precomputed messages + // we have been using. We will use the precomputed msg3 instead. + msg3_size = MSG3_BODY_SIZE; + p_msg3 = (sgx_ra_msg3_t*)malloc(msg3_size); + if(NULL == p_msg3) + { + ret = -1; + goto CLEANUP; + } + memcpy_s(p_msg3, msg3_size, + msg3_samples[GET_VERIFICATION_ARRAY_INDEX()], msg3_size); + fprintf(OUTPUT, "\nBecause MSG1 was a precomputed value, the MSG3 " + "we use will also be. PRECOMPUTED MSG3 - \n"); + } + else + { + busy_retry_time = 2; + // The ISV app now calls uKE sgx_ra_proc_msg2, + // The ISV app is responsible for freeing the returned p_msg3!! + do + { + ret = sgx_ra_proc_msg2(context, + enclave_id, + sgx_ra_proc_msg2_trusted, + sgx_ra_get_msg3_trusted, + p_msg2_body, + p_msg2_full->size, + &p_msg3, + &msg3_size); + } while (SGX_ERROR_BUSY == ret && busy_retry_time--); + if(!p_msg3) + { + fprintf(OUTPUT, "\nError, call sgx_ra_proc_msg2 fail. " + "p_msg3 = 0x%p [%s].", p_msg3, __FUNCTION__); + ret = -1; + goto CLEANUP; + } + if(SGX_SUCCESS != (sgx_status_t)ret) + { + fprintf(OUTPUT, "\nError, call sgx_ra_proc_msg2 fail. " + "ret = 0x%08x [%s].", ret, __FUNCTION__); + ret = -1; + goto CLEANUP; + } + else + { + fprintf(OUTPUT, "\nCall sgx_ra_proc_msg2 success.\n"); + fprintf(OUTPUT, "\nMSG3 - \n"); + } + } + + PRINT_BYTE_ARRAY(OUTPUT, p_msg3, msg3_size); + + p_msg3_full = (ra_samp_request_header_t*)malloc( + sizeof(ra_samp_request_header_t) + msg3_size); + if(NULL == p_msg3_full) + { + ret = -1; + goto CLEANUP; + } + p_msg3_full->type = TYPE_RA_MSG3; + p_msg3_full->size = msg3_size; + if(memcpy_s(p_msg3_full->body, msg3_size, p_msg3, msg3_size)) + { + fprintf(OUTPUT,"\nError: INTERNAL ERROR - memcpy failed in [%s].", + __FUNCTION__); + ret = -1; + goto CLEANUP; + } + + // The ISV application sends msg3 to the SP to get the attestation + // result message, attestation result message needs to be freed when + // no longer needed. The ISV service provider decides whether to use + // linkable or unlinkable signatures. The format of the attestation + // result is up to the service provider. This format is used for + // demonstration. Note that the attestation result message makes use + // of both the MK for the MAC and the SK for the secret. These keys are + // established from the SIGMA secure channel binding. + ret = ra_network_send_receive("http://SampleServiceProvider.intel.com/", + p_msg3_full, + &p_att_result_msg_full); + if(ret || !p_att_result_msg_full) + { + ret = -1; + fprintf(OUTPUT, "\nError, sending msg3 failed [%s].", __FUNCTION__); + goto CLEANUP; + } + + + sample_ra_att_result_msg_t * p_att_result_msg_body = + (sample_ra_att_result_msg_t *)((uint8_t*)p_att_result_msg_full + + sizeof(ra_samp_response_header_t)); + if(TYPE_RA_ATT_RESULT != p_att_result_msg_full->type) + { + ret = -1; + fprintf(OUTPUT, "\nError. Sent MSG3 successfully, but the message " + "received was NOT of type att_msg_result. Type = " + "%d. [%s].", p_att_result_msg_full->type, + __FUNCTION__); + goto CLEANUP; + } + else + { + fprintf(OUTPUT, "\nSent MSG3 successfully. Received an attestation " + "result message back\n."); + if( VERIFICATION_INDEX_IS_VALID() ) + { + if(memcmp(p_att_result_msg_full->body, + attestation_msg_samples[GET_VERIFICATION_ARRAY_INDEX()], + p_att_result_msg_full->size) ) + { + fprintf(OUTPUT, "\nSent MSG3 successfully. Received an " + "attestation result message back that did " + "NOT match the expected value.\n"); + fprintf(OUTPUT, "\nEXPECTED ATTESTATION RESULT -"); + PRINT_BYTE_ARRAY(OUTPUT, + attestation_msg_samples[GET_VERIFICATION_ARRAY_INDEX()], + p_att_result_msg_full->size); + } + } + } + + fprintf(OUTPUT, "\nATTESTATION RESULT RECEIVED - "); + PRINT_BYTE_ARRAY(OUTPUT, p_att_result_msg_full->body, + p_att_result_msg_full->size); + + + if( VERIFICATION_INDEX_IS_VALID() ) + { + fprintf(OUTPUT, "\nBecause we used precomputed values for the " + "messages, the attestation result message will " + "not pass further verification tests, so we will " + "skip them.\n"); + goto CLEANUP; + } + + // Check the MAC using MK on the attestation result message. + // The format of the attestation result message is ISV specific. + // This is a simple form for demonstration. In a real product, + // the ISV may want to communicate more information. + ret = verify_att_result_mac(enclave_id, + &status, + context, + (uint8_t*)&p_att_result_msg_body->platform_info_blob, + sizeof(ias_platform_info_blob_t), + (uint8_t*)&p_att_result_msg_body->mac, + sizeof(sgx_mac_t)); + if((SGX_SUCCESS != ret) || + (SGX_SUCCESS != status)) + { + ret = -1; + fprintf(OUTPUT, "\nError: INTEGRITY FAILED - attestation result " + "message MK based cmac failed in [%s].", + __FUNCTION__); + goto CLEANUP; + } + + bool attestation_passed = true; + // Check the attestation result for pass or fail. + // Whether attestation passes or fails is a decision made by the ISV Server. + // When the ISV server decides to trust the enclave, then it will return success. + // When the ISV server decided to not trust the enclave, then it will return failure. + if(0 != p_att_result_msg_full->status[0] + || 0 != p_att_result_msg_full->status[1]) + { + fprintf(OUTPUT, "\nError, attestation result message MK based cmac " + "failed in [%s].", __FUNCTION__); + attestation_passed = false; + } + + // The attestation result message should contain a field for the Platform + // Info Blob (PIB). The PIB is returned by attestation server in the attestation report. + // It is not returned in all cases, but when it is, the ISV app + // should pass it to the blob analysis API called sgx_report_attestation_status() + // along with the trust decision from the ISV server. + // The ISV application will take action based on the update_info. + // returned in update_info by the API. + // This call is stubbed out for the sample. + // + // sgx_update_info_bit_t update_info; + // ret = sgx_report_attestation_status( + // &p_att_result_msg_body->platform_info_blob, + // attestation_passed ? 0 : 1, &update_info); + + // Get the shared secret sent by the server using SK (if attestation + // passed) + if(attestation_passed) + { + ret = put_secret_data(enclave_id, + &status, + context, + p_att_result_msg_body->secret.payload, + p_att_result_msg_body->secret.payload_size, + p_att_result_msg_body->secret.payload_tag); + if((SGX_SUCCESS != ret) || (SGX_SUCCESS != status)) + { + fprintf(OUTPUT, "\nError, attestation result message secret " + "using SK based AESGCM failed in [%s]. ret = " + "0x%0x. status = 0x%0x", __FUNCTION__, ret, + status); + goto CLEANUP; + } + } + fprintf(OUTPUT, "\nSecret successfully received from server."); + fprintf(OUTPUT, "\nRemote attestation success!"); + } + +CLEANUP: + // Clean-up + // Need to close the RA key state. + if(INT_MAX != context) + { + int ret_save = ret; + ret = enclave_ra_close(enclave_id, &status, context); + if(SGX_SUCCESS != ret || status) + { + ret = -1; + fprintf(OUTPUT, "\nError, call enclave_ra_close fail [%s].", + __FUNCTION__); + } + else + { + // enclave_ra_close was successful, let's restore the value that + // led us to this point in the code. + ret = ret_save; + } + fprintf(OUTPUT, "\nCall enclave_ra_close success."); + } + + sgx_destroy_enclave(enclave_id); + + + ra_free_network_response_buffer(p_msg0_resp_full); + ra_free_network_response_buffer(p_msg2_full); + ra_free_network_response_buffer(p_att_result_msg_full); + + // p_msg3 is malloc'd by the untrusted KE library. App needs to free. + SAFE_FREE(p_msg3); + SAFE_FREE(p_msg3_full); + SAFE_FREE(p_msg1_full); + SAFE_FREE(p_msg0_full); + printf("\nEnter a character before exit ...\n"); + getchar(); + return ret; +} + diff --git a/sgx-jvm/linux-sgx/SampleCode/RemoteAttestation/isv_app/sample_messages.h b/sgx-jvm/linux-sgx/SampleCode/RemoteAttestation/isv_app/sample_messages.h new file mode 100644 index 0000000000..92281777fa --- /dev/null +++ b/sgx-jvm/linux-sgx/SampleCode/RemoteAttestation/isv_app/sample_messages.h @@ -0,0 +1,537 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + + +//This file contains samples of messages sent between the sample ISV application +//and the sample service provider. It is intended to be used so that authors +//of other service providers can verify that the messages generated by their +//remote attestation service matches. + +#include + +uint8_t msg1_sample1[] = +{ + 0xe8, 0xcf, 0xf, 0x97, 0x8a, 0xf4, 0x24, 0x8a, + 0xf5, 0x5b, 0x56, 0xf0, 0xac, 0x7f, 0x78, 0x39, + 0x71, 0x10, 0xb8, 0xdc, 0x88, 0xd, 0x50, 0xf0, + 0x39, 0x85, 0x37, 0xfe, 0xad, 0x1f, 0xc7, 0x59, + 0xc7, 0x23, 0x81, 0xfd, 0x4a, 0x2, 0x48, 0xdf, + 0xd3, 0x74, 0xda, 0x45, 0x48, 0x62, 0xc8, 0xb6, + 0x73, 0x43, 0x26, 0x42, 0x8f, 0x1f, 0x89, 0x17, + 0xe7, 0xa9, 0x2a, 0xf5, 0x27, 0xb3, 0xcc, 0x4d, + 0x3, 0x1, 0x0, 0x0 +}; + +uint8_t msg1_sample2[] = +{ + 0xa8, 0x56, 0x72, 0xc1, 0x14, 0x41, 0xa, 0x2f, + 0xdc, 0xb0, 0xa8, 0xa1, 0x3a, 0x51, 0x40, 0xf9, + 0x12, 0x9f, 0x11, 0x86, 0xe9, 0x1a, 0xf1, 0x16, + 0xbc, 0xd4, 0x6, 0x2f, 0x47, 0x2c, 0xc3, 0x37, + 0x8e, 0x65, 0x7, 0x29, 0x85, 0xb0, 0x8, 0x61, + 0x6b, 0x6d, 0xc7, 0x22, 0x7d, 0x22, 0x61, 0x7f, + 0x40, 0x43, 0x40, 0x5a, 0x7a, 0xf4, 0x94, 0x0, + 0x60, 0x36, 0xf6, 0xa4, 0x22, 0x22, 0x41, 0x82, + 0x3, 0x1, 0x0, 0x0 +}; + +uint8_t msg2_sample1[] = +{ + 0x2, 0x0, 0x0, 0xa8, 0x0, 0x0, 0x0, 0x0, + 0x6a, 0x83, 0xdc, 0x84, 0xd4, 0x4c, 0x8a, 0xbb, + 0x5e, 0x42, 0xaf, 0xee, 0x8d, 0xe9, 0xf4, 0x57, + 0x71, 0xfd, 0x73, 0x66, 0xd7, 0xfa, 0xad, 0xfa, + 0xf2, 0x17, 0x14, 0xdd, 0x5a, 0xb9, 0x9e, 0x97, + 0x79, 0xa7, 0x38, 0x72, 0xf2, 0xb8, 0xd6, 0xbe, + 0x18, 0x91, 0x7f, 0xf7, 0xb5, 0xd3, 0xe5, 0x64, + 0x9b, 0x12, 0x18, 0xaf, 0x39, 0x29, 0x6c, 0x24, + 0x19, 0x38, 0x29, 0xb, 0xc6, 0xac, 0xc, 0x62, + 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x20, + 0x58, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x1, 0x0, 0x1, 0x0, 0x6a, 0x83, 0xdc, 0x84, + 0xd4, 0x4c, 0x8a, 0xbb, 0x5e, 0x42, 0xaf, 0xee, + 0x8d, 0xe9, 0xf4, 0x57, 0x71, 0xfd, 0x73, 0x66, + 0xd7, 0xfa, 0xad, 0xfa, 0xf2, 0x17, 0x14, 0xdd, + 0x5a, 0xb9, 0x9e, 0x97, 0x6, 0x10, 0x58, 0x61, + 0xa5, 0xbf, 0x7d, 0x2e, 0xab, 0xcc, 0x1a, 0x3e, + 0x4f, 0x44, 0x15, 0xe7, 0x91, 0xca, 0x64, 0x2b, + 0x42, 0xb7, 0x53, 0xd9, 0x71, 0x37, 0xf1, 0x9b, + 0x31, 0xb5, 0xa5, 0x6b, 0xf8, 0xfa, 0x64, 0xfe, + 0x7a, 0x9e, 0xdc, 0xf4, 0xf0, 0x59, 0xbd, 0x78, + 0x27, 0xc2, 0x55, 0xb9, 0x0, 0x0, 0x0, 0x0 +}; + +uint8_t msg2_sample2[] = +{ + 0x2, 0x0, 0x0, 0xa8, 0x0, 0x0, 0x0, 0x0, + 0x6a, 0x83, 0xdc, 0x84, 0xd4, 0x4c, 0x8a, 0xbb, + 0x5e, 0x42, 0xaf, 0xee, 0x8d, 0xe9, 0xf4, 0x57, + 0x71, 0xfd, 0x73, 0x66, 0xd7, 0xfa, 0xad, 0xfa, + 0xf2, 0x17, 0x14, 0xdd, 0x5a, 0xb9, 0x9e, 0x97, + 0x79, 0xa7, 0x38, 0x72, 0xf2, 0xb8, 0xd6, 0xbe, + 0x18, 0x91, 0x7f, 0xf7, 0xb5, 0xd3, 0xe5, 0x64, + 0x9b, 0x12, 0x18, 0xaf, 0x39, 0x29, 0x6c, 0x24, + 0x19, 0x38, 0x29, 0xb, 0xc6, 0xac, 0xc, 0x62, + 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x20, + 0x58, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x1, 0x0, 0x1, 0x0, 0x6a, 0x83, 0xdc, 0x84, + 0xd4, 0x4c, 0x8a, 0xbb, 0x5e, 0x42, 0xaf, 0xee, + 0x8d, 0xe9, 0xf4, 0x57, 0x71, 0xfd, 0x73, 0x66, + 0xd7, 0xfa, 0xad, 0xfa, 0xf2, 0x17, 0x14, 0xdd, + 0x5a, 0xb9, 0x9e, 0x97, 0x75, 0x39, 0x23, 0x1b, + 0xc2, 0x5a, 0xd4, 0xfa, 0x41, 0xe9, 0xd4, 0x42, + 0x72, 0x8a, 0x75, 0x4b, 0x48, 0x5a, 0xfb, 0xc0, + 0x90, 0x42, 0xef, 0x9c, 0xed, 0xcb, 0xc1, 0x45, + 0x2d, 0xfe, 0x86, 0xbc, 0xee, 0x3, 0xa8, 0x97, + 0x68, 0xf0, 0xb4, 0xf, 0xa, 0x5b, 0x5f, 0xc1, + 0xe4, 0xf9, 0xa9, 0xa6, 0x0, 0x0, 0x0, 0x0 +}; + +#define MSG3_BODY_SIZE 1452 + +uint8_t msg3_sample1[MSG3_BODY_SIZE] = +{ + 0x57, 0x19, 0x8, 0xa1, 0x3b, 0xd0, 0x37, 0xa8, + 0x4a, 0x32, 0xf1, 0x31, 0xc1, 0x14, 0xff, 0xdf, + 0xe8, 0xcf, 0xf, 0x97, 0x8a, 0xf4, 0x24, 0x8a, + 0xf5, 0x5b, 0x56, 0xf0, 0xac, 0x7f, 0x78, 0x39, + 0x71, 0x10, 0xb8, 0xdc, 0x88, 0xd, 0x50, 0xf0, + 0x39, 0x85, 0x37, 0xfe, 0xad, 0x1f, 0xc7, 0x59, + 0xc7, 0x23, 0x81, 0xfd, 0x4a, 0x2, 0x48, 0xdf, + 0xd3, 0x74, 0xda, 0x45, 0x48, 0x62, 0xc8, 0xb6, + 0x73, 0x43, 0x26, 0x42, 0x8f, 0x1f, 0x89, 0x17, + 0xe7, 0xa9, 0x2a, 0xf5, 0x27, 0xb3, 0xcc, 0x4d, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x2, 0x0, 0x1, 0x0, 0x3, 0x1, 0x0, 0x0, + 0x1, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x20, + 0x58, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x2, 0x2, 0xff, 0xff, 0xff, 0x1, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0xe2, 0x55, 0x5d, 0xc6, 0xe6, 0x69, 0x53, 0xc0, + 0x8d, 0x52, 0x5b, 0xc0, 0x2a, 0x2c, 0x5c, 0x2f, + 0xc, 0x8c, 0xfe, 0x5b, 0x1, 0xae, 0x89, 0xff, + 0x2, 0x2f, 0x97, 0xea, 0x9b, 0x45, 0xb6, 0x2e, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x60, 0x27, 0x7a, 0xd2, 0xfd, 0xfc, 0x57, 0xe9, + 0x80, 0xe8, 0x76, 0xe7, 0xf8, 0x78, 0xac, 0x19, + 0x9, 0x88, 0xe, 0xa5, 0x38, 0x7, 0x95, 0xa7, + 0xe8, 0xea, 0x98, 0xb1, 0x57, 0x84, 0x1f, 0x85, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x2a, 0xe, 0x9, 0x4c, 0xe2, 0xd9, 0x44, 0x73, + 0x36, 0x42, 0xfa, 0xe0, 0x44, 0x5b, 0x7b, 0x1f, + 0xc2, 0x85, 0x16, 0xca, 0xf1, 0xc5, 0xcd, 0xd2, + 0xf, 0xe4, 0xdf, 0xf, 0x31, 0xca, 0x36, 0x28, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0xa8, 0x2, 0x0, 0x0, 0x68, 0xe3, 0x1d, 0x2, + 0xd1, 0x6, 0x2a, 0x16, 0xab, 0x1c, 0xfd, 0x43, + 0x5c, 0x1f, 0x34, 0x5, 0x15, 0xc4, 0x84, 0xdd, + 0xee, 0x73, 0x79, 0xe7, 0x2e, 0xc8, 0x95, 0x77, + 0x6b, 0xca, 0xff, 0xb9, 0xf4, 0xf8, 0x5a, 0x42, + 0x9d, 0x32, 0x73, 0x62, 0xab, 0x49, 0x8, 0xa4, + 0xc3, 0x5c, 0x5a, 0x66, 0x38, 0x76, 0xcd, 0x58, + 0x5b, 0x85, 0xbf, 0xf0, 0x52, 0x12, 0xd2, 0xc8, + 0xd, 0xf8, 0x6d, 0x91, 0xb8, 0xcf, 0x3f, 0x1d, + 0xe0, 0x1d, 0x63, 0xb2, 0x58, 0xa7, 0xbc, 0x8, + 0x97, 0xbb, 0xcc, 0x19, 0x31, 0xdb, 0x47, 0xf3, + 0x8e, 0x54, 0x7d, 0x36, 0x6e, 0x6, 0xd3, 0x20, + 0xca, 0x5e, 0x8a, 0x5, 0x30, 0x50, 0x56, 0xe9, + 0x91, 0x9, 0x35, 0x13, 0x69, 0xd, 0x24, 0x71, + 0x55, 0xca, 0xe8, 0xef, 0x4d, 0x1c, 0xe6, 0x1f, + 0x51, 0xeb, 0x12, 0x32, 0x97, 0xa2, 0xbb, 0x1e, + 0xf2, 0x26, 0xc5, 0xe9, 0x3f, 0xda, 0x79, 0xc3, + 0x89, 0x28, 0x9, 0x6c, 0x59, 0x9e, 0x2d, 0x60, + 0x5f, 0x35, 0x33, 0x76, 0xfe, 0xf5, 0xba, 0x73, + 0xc5, 0xb6, 0x44, 0x9d, 0xb9, 0x3a, 0x90, 0x8, + 0x5e, 0xba, 0x33, 0x3d, 0xe5, 0xff, 0xc0, 0x5b, + 0xbb, 0x7b, 0xbc, 0x39, 0x52, 0x6f, 0x54, 0x8b, + 0xb5, 0x44, 0xf7, 0x75, 0xc5, 0x28, 0xa7, 0x51, + 0xd, 0x69, 0x2b, 0x3a, 0xfd, 0xc0, 0x7c, 0x6f, + 0xf, 0xcf, 0x76, 0x32, 0xea, 0x38, 0xd2, 0x8d, + 0xbe, 0x9c, 0xef, 0x3b, 0x56, 0xdc, 0x8e, 0x29, + 0x40, 0x87, 0x4, 0xe6, 0x15, 0xa1, 0x12, 0x9f, + 0x21, 0x12, 0xe8, 0xd8, 0x5, 0x26, 0x22, 0x23, + 0x12, 0x57, 0xd1, 0xb6, 0x3, 0x59, 0xfa, 0xa6, + 0xfe, 0x24, 0xe1, 0x84, 0xfb, 0x63, 0xf3, 0x3d, + 0xf1, 0xe2, 0x70, 0x2c, 0x94, 0xf1, 0xa4, 0xdc, + 0x70, 0x31, 0xda, 0x9e, 0xb9, 0xf7, 0xc6, 0xba, + 0xd3, 0x4e, 0x5c, 0x63, 0xf1, 0x78, 0xcc, 0x38, + 0xc2, 0x1a, 0xd6, 0x2, 0x34, 0x23, 0x1a, 0x4b, + 0x1, 0x4e, 0xf4, 0xe6, 0xe, 0x6b, 0xfa, 0x27, + 0x8d, 0xe3, 0x67, 0x5d, 0xec, 0x79, 0x13, 0x66, + 0x46, 0xbb, 0xd0, 0x8e, 0xc8, 0x21, 0x6f, 0x37, + 0x5c, 0x5e, 0x5d, 0xed, 0x8e, 0x2d, 0x8d, 0x94, + 0x68, 0x1, 0x0, 0x0, 0x84, 0xd5, 0x35, 0x93, + 0x3a, 0xb1, 0x19, 0x8e, 0xb6, 0xb0, 0x5f, 0x4f, + 0x66, 0x8a, 0xb3, 0xe0, 0x12, 0xbb, 0x7, 0xe0, + 0xa3, 0x6b, 0x54, 0xd5, 0xf6, 0xc8, 0x2, 0xdd, + 0x33, 0x78, 0x3c, 0x4f, 0xdc, 0xa3, 0x3e, 0x5c, + 0x99, 0xb8, 0x2f, 0x3f, 0xdf, 0xf0, 0xf0, 0x63, + 0x24, 0x6f, 0xc2, 0x17, 0xeb, 0x45, 0xd5, 0x79, + 0xaa, 0xb5, 0x46, 0x4b, 0x77, 0x6d, 0x3d, 0xbf, + 0xe8, 0xca, 0xaf, 0x4d, 0xb5, 0x5d, 0xee, 0x9e, + 0xf5, 0x73, 0x8d, 0x1, 0xff, 0x84, 0x1e, 0xc9, + 0x78, 0x2e, 0xde, 0x3, 0x97, 0x36, 0x1c, 0x47, + 0xc, 0x46, 0x5, 0xfc, 0x8b, 0xf5, 0xd5, 0x13, + 0xa3, 0x8, 0xd4, 0x29, 0x83, 0xfb, 0x4b, 0x3e, + 0xf1, 0x3d, 0xe8, 0x54, 0x28, 0x2f, 0x3d, 0x9c, + 0x8b, 0x91, 0xcc, 0xf0, 0x45, 0x40, 0x3, 0xb, + 0xaa, 0x41, 0x38, 0x2f, 0xad, 0xc3, 0x1d, 0x61, + 0x15, 0x20, 0x9, 0xea, 0xfd, 0xdb, 0xf9, 0x17, + 0x84, 0x19, 0xae, 0xf3, 0x4b, 0x4d, 0x8e, 0xa2, + 0x3e, 0x9c, 0xb3, 0x70, 0x4d, 0x38, 0x1, 0x5, + 0xb7, 0xc, 0xb2, 0xf6, 0x84, 0xbe, 0xbc, 0xd5, + 0xd1, 0x8a, 0x22, 0xfc, 0x82, 0xb4, 0x3b, 0x96, + 0x8f, 0xc0, 0x49, 0xaa, 0xf0, 0x52, 0x25, 0xda, + 0x39, 0xc2, 0x4c, 0xbc, 0xe2, 0x47, 0xe3, 0xc, + 0x59, 0xad, 0x40, 0x42, 0x17, 0x30, 0x4d, 0x1c, + 0x34, 0xd3, 0xdb, 0xa7, 0xc5, 0x9c, 0xef, 0x83, + 0xd, 0xb8, 0x9a, 0xa9, 0x29, 0x1b, 0x11, 0x32, + 0x74, 0x53, 0x17, 0x34, 0xd6, 0xa2, 0x14, 0x6, + 0x8b, 0xae, 0x8c, 0xb4, 0xcb, 0x20, 0xec, 0xb3, + 0x2f, 0xe, 0xf3, 0x8f, 0xc3, 0x84, 0xe3, 0xb8, + 0x46, 0x51, 0xea, 0xa6, 0x1c, 0x27, 0x31, 0x1e, + 0x69, 0xb, 0xc7, 0x47, 0xad, 0x7d, 0xde, 0x3f, + 0x13, 0x2b, 0x5e, 0x2a, 0x24, 0x37, 0x85, 0xa4, + 0x8d, 0x45, 0x39, 0xeb, 0x95, 0x47, 0xb8, 0x57, + 0x5d, 0x88, 0xeb, 0x56, 0xb0, 0xa8, 0x58, 0xd, + 0x9e, 0x1b, 0x80, 0x3a, 0x74, 0x86, 0x3a, 0x58, + 0xfc, 0xa6, 0xa, 0xc5, 0x66, 0x5f, 0xc7, 0xa9, + 0xd5, 0xc, 0x37, 0xd1, 0x23, 0xff, 0xfd, 0x1d, + 0x38, 0x1c, 0x98, 0xd1, 0xa9, 0x24, 0x3b, 0x23, + 0xa2, 0x1a, 0xee, 0x8, 0x31, 0x4f, 0xd5, 0xaa, + 0x1d, 0x67, 0xe7, 0x77, 0x5c, 0x46, 0xcc, 0xb, + 0x18, 0xf6, 0xdd, 0x86, 0xf4, 0xcc, 0xb4, 0xd5, + 0xcd, 0xe6, 0xae, 0xb3, 0xf0, 0x24, 0x15, 0x71, + 0xb3, 0x65, 0xff, 0xfa, 0xe5, 0x1a, 0x6d, 0xc3, + 0x6f, 0x43, 0x73, 0xe0, 0xe8, 0xa9, 0x6f, 0x68, + 0xf8, 0x4, 0xf2, 0x73, 0x1, 0x36, 0xeb, 0x83, + 0xa5, 0xf2, 0x6e, 0x4e, 0x36, 0xa5, 0x63, 0xab, + 0x7d, 0xa1, 0xd2, 0x24, 0x17, 0xb7, 0x3b, 0x96, + 0x4b, 0xbe, 0x4c, 0xcb +}; + + +uint8_t msg3_sample2[MSG3_BODY_SIZE] = +{ + 0x4f, 0x85, 0xd3, 0x93, 0xc, 0x44, 0x9c, 0xdd, + 0x3e, 0x81, 0xbd, 0xb6, 0xa2, 0x44, 0x16, 0x5f, + 0xa8, 0x56, 0x72, 0xc1, 0x14, 0x41, 0xa, 0x2f, + 0xdc, 0xb0, 0xa8, 0xa1, 0x3a, 0x51, 0x40, 0xf9, + 0x12, 0x9f, 0x11, 0x86, 0xe9, 0x1a, 0xf1, 0x16, + 0xbc, 0xd4, 0x6, 0x2f, 0x47, 0x2c, 0xc3, 0x37, + 0x8e, 0x65, 0x7, 0x29, 0x85, 0xb0, 0x8, 0x61, + 0x6b, 0x6d, 0xc7, 0x22, 0x7d, 0x22, 0x61, 0x7f, + 0x40, 0x43, 0x40, 0x5a, 0x7a, 0xf4, 0x94, 0x0, + 0x60, 0x36, 0xf6, 0xa4, 0x22, 0x22, 0x41, 0x82, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x2, 0x0, 0x1, 0x0, 0x3, 0x1, 0x0, 0x0, + 0x1, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x20, + 0x58, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x2, 0x2, 0xff, 0xff, 0xff, 0x1, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0xe2, 0x55, 0x5d, 0xc6, 0xe6, 0x69, 0x53, 0xc0, + 0x8d, 0x52, 0x5b, 0xc0, 0x2a, 0x2c, 0x5c, 0x2f, + 0xc, 0x8c, 0xfe, 0x5b, 0x1, 0xae, 0x89, 0xff, + 0x2, 0x2f, 0x97, 0xea, 0x9b, 0x45, 0xb6, 0x2e, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x60, 0x27, 0x7a, 0xd2, 0xfd, 0xfc, 0x57, 0xe9, + 0x80, 0xe8, 0x76, 0xe7, 0xf8, 0x78, 0xac, 0x19, + 0x9, 0x88, 0xe, 0xa5, 0x38, 0x7, 0x95, 0xa7, + 0xe8, 0xea, 0x98, 0xb1, 0x57, 0x84, 0x1f, 0x85, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0xdd, 0xda, 0x3e, 0x6b, 0x72, 0xa2, 0xd7, 0x31, + 0x31, 0x32, 0xbd, 0xf3, 0xf4, 0xc0, 0xe3, 0xaa, + 0x16, 0x19, 0x72, 0x47, 0x92, 0xe7, 0x8f, 0xf8, + 0x40, 0x2b, 0xa7, 0xc0, 0xb9, 0x77, 0xb1, 0x1c, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0xa8, 0x2, 0x0, 0x0, 0x2e, 0x23, 0x7d, 0xe8, + 0x5d, 0xcd, 0x6d, 0x88, 0x6f, 0xad, 0xd3, 0x4c, + 0x7e, 0xed, 0xff, 0xa2, 0xea, 0x1c, 0xd5, 0xc8, + 0x54, 0xbb, 0x93, 0xc8, 0x1b, 0xbe, 0xbe, 0x51, + 0x6b, 0x8d, 0xb7, 0x90, 0x7f, 0x87, 0x9f, 0x9b, + 0x66, 0x4f, 0xeb, 0xf4, 0x34, 0xbb, 0x90, 0x5d, + 0xc5, 0x20, 0x7b, 0xd2, 0x5a, 0x92, 0x42, 0x80, + 0x2f, 0x3f, 0xc2, 0x64, 0x7e, 0x77, 0xa, 0x49, + 0xdb, 0xde, 0x77, 0x88, 0xd7, 0xce, 0xdb, 0x2e, + 0x44, 0x50, 0x26, 0xd8, 0x7a, 0xe, 0x1c, 0x7f, + 0x63, 0x36, 0x62, 0xa8, 0xa7, 0x2e, 0x60, 0x56, + 0xf4, 0xbc, 0xb5, 0xca, 0xc3, 0x81, 0x9e, 0x84, + 0xb8, 0xc, 0xef, 0x7a, 0x18, 0x4a, 0x5b, 0x3, + 0x0, 0xe3, 0x8c, 0x3f, 0x2e, 0xf9, 0x9a, 0xf7, + 0x72, 0xe1, 0xa0, 0x5e, 0x6a, 0x4c, 0x68, 0xea, + 0x67, 0xfc, 0xe8, 0x21, 0x27, 0x90, 0xae, 0xbf, + 0x51, 0xa4, 0xc9, 0xae, 0x3d, 0x3b, 0x5c, 0x53, + 0x7e, 0x25, 0xa4, 0x6f, 0x78, 0x99, 0x35, 0x2e, + 0x48, 0x50, 0xf9, 0xf0, 0x63, 0x90, 0x19, 0x6a, + 0xc, 0x3d, 0x48, 0x2a, 0x5f, 0x6f, 0xb, 0xd7, + 0x26, 0x64, 0xb5, 0xe0, 0x60, 0x36, 0x69, 0x40, + 0x9c, 0x21, 0x29, 0xe0, 0xca, 0xae, 0xd1, 0x7a, + 0x4, 0xb8, 0x8d, 0x96, 0x74, 0xa3, 0x7, 0xa4, + 0x41, 0x9e, 0xf7, 0x9, 0xbe, 0x8f, 0xe8, 0x65, + 0xd9, 0x26, 0x16, 0xa1, 0xef, 0x1b, 0xf4, 0xb7, + 0xd5, 0xfe, 0xd6, 0x7d, 0xa6, 0x6c, 0x50, 0x8c, + 0x90, 0x34, 0x1f, 0x17, 0x8c, 0x14, 0x38, 0x6d, + 0xd7, 0x83, 0x1a, 0x1e, 0xcf, 0xf5, 0xb, 0xdb, + 0x26, 0x8f, 0x23, 0xf9, 0x4f, 0x41, 0x73, 0xac, + 0x9d, 0xfa, 0x77, 0x3, 0x6a, 0x32, 0xbb, 0x37, + 0x93, 0x47, 0x38, 0x93, 0x39, 0xd2, 0x51, 0x46, + 0xaf, 0xfd, 0x71, 0xda, 0x89, 0xc7, 0x44, 0xb0, + 0xf3, 0x95, 0x74, 0x3b, 0xbc, 0x7d, 0x86, 0xc1, + 0x6e, 0x49, 0xd8, 0x52, 0xc, 0xc1, 0x88, 0x72, + 0x5, 0x5c, 0x92, 0x12, 0x22, 0x95, 0xc5, 0x12, + 0xf5, 0xfa, 0x11, 0x8d, 0x50, 0x42, 0x33, 0x4, + 0x41, 0x17, 0x90, 0xc8, 0xb3, 0x1d, 0x2e, 0xe5, + 0x13, 0xf5, 0xd6, 0xb1, 0xc5, 0xd4, 0x6d, 0xe1, + 0x68, 0x1, 0x0, 0x0, 0xc4, 0x15, 0xbf, 0x91, + 0xf1, 0xad, 0xb1, 0x9f, 0x9b, 0x6b, 0x8d, 0xa2, + 0xdf, 0x7d, 0x6, 0xf8, 0xba, 0x73, 0xb7, 0xb, + 0x72, 0xcc, 0x34, 0x4d, 0x52, 0x3b, 0x76, 0xfd, + 0x8e, 0x3a, 0x67, 0xcc, 0x36, 0xb, 0xa9, 0xc2, + 0x90, 0x37, 0x77, 0x75, 0x90, 0xb8, 0x97, 0x44, + 0xed, 0xb4, 0x61, 0xe8, 0x11, 0xe9, 0x2, 0x50, + 0xde, 0x98, 0x99, 0x3e, 0xf6, 0x5c, 0x71, 0x92, + 0x49, 0xcb, 0x0, 0x72, 0xe0, 0x55, 0xa9, 0x6e, + 0xc7, 0x2, 0xf4, 0x2b, 0x3c, 0xe3, 0x42, 0x7e, + 0x8b, 0xf, 0x26, 0xd9, 0x42, 0x21, 0xd5, 0x74, + 0xe3, 0x35, 0xb3, 0xb8, 0xfe, 0x25, 0x1d, 0x47, + 0x5b, 0x35, 0x8d, 0xfd, 0x18, 0x77, 0x29, 0xd9, + 0x69, 0x2b, 0x67, 0x54, 0x8c, 0xf5, 0xd7, 0x84, + 0x36, 0xf3, 0x96, 0xca, 0xb9, 0x42, 0xad, 0xd6, + 0xba, 0x8d, 0x2f, 0xfc, 0x21, 0xfe, 0xa7, 0xea, + 0x59, 0x94, 0xfe, 0x95, 0x1f, 0x1e, 0xb9, 0xca, + 0x5e, 0x4d, 0xf1, 0x2, 0x68, 0x91, 0xf7, 0xa1, + 0xea, 0x11, 0x90, 0x95, 0x1c, 0xf7, 0x85, 0xd4, + 0x70, 0xf9, 0x49, 0xae, 0x5e, 0xa5, 0x62, 0x3d, + 0x35, 0xc5, 0xdf, 0xc1, 0x7f, 0xc7, 0x39, 0x5a, + 0x3b, 0x89, 0x8c, 0x80, 0x71, 0xe7, 0xbc, 0xbf, + 0x4e, 0x72, 0x6d, 0xd7, 0xe0, 0xa2, 0xb0, 0x7d, + 0xca, 0x89, 0x22, 0x6, 0xb2, 0xb4, 0x3c, 0xa2, + 0xed, 0x51, 0xf, 0xa2, 0xf7, 0xc9, 0x89, 0xf0, + 0x27, 0x2f, 0xf6, 0x41, 0x4e, 0xa, 0x2b, 0x67, + 0x49, 0x44, 0x8e, 0x40, 0xc6, 0xb8, 0xad, 0xb8, + 0x40, 0xb, 0xba, 0x73, 0x2e, 0x1d, 0x4, 0xc9, + 0x28, 0x62, 0x6b, 0x3d, 0xe6, 0x5f, 0x1c, 0xdd, + 0xae, 0x27, 0x6d, 0x3c, 0x2d, 0xf6, 0x42, 0x3b, + 0x91, 0x1, 0x37, 0x47, 0x76, 0x5, 0xbc, 0x7, + 0x8c, 0x6, 0x81, 0x77, 0x70, 0x9d, 0x8a, 0x75, + 0x34, 0x1, 0x68, 0x1a, 0x38, 0x13, 0x11, 0x74, + 0xf2, 0x70, 0x4f, 0x9b, 0x86, 0x15, 0xc6, 0xbc, + 0x6b, 0x1a, 0x56, 0x3f, 0x4f, 0xfa, 0xd4, 0x17, + 0x97, 0xbb, 0x4b, 0x91, 0x3b, 0x54, 0xf7, 0x8e, + 0x53, 0xf5, 0x2, 0x21, 0x3b, 0x66, 0xf9, 0xe5, + 0x79, 0xff, 0xeb, 0x5c, 0x66, 0x1b, 0x34, 0xf4, + 0x41, 0xd1, 0x9a, 0xdb, 0x1f, 0x3e, 0xe3, 0x8a, + 0x90, 0x98, 0x9e, 0x73, 0xb9, 0xa8, 0x20, 0xfe, + 0xe7, 0xe3, 0x9f, 0x83, 0xd3, 0x95, 0x5f, 0xa, + 0x40, 0x53, 0x6a, 0xd3, 0x72, 0x32, 0xde, 0xf1, + 0xf, 0x98, 0x2b, 0x7d, 0x6e, 0x76, 0xbd, 0x31, + 0x84, 0x99, 0x1c, 0xdc, 0xac, 0x78, 0x44, 0xbf, + 0x29, 0xdd, 0x2e, 0xe3, 0x39, 0x9d, 0x38, 0x83, + 0xa, 0x3e, 0x83, 0xb6, 0x74, 0x44, 0x4d, 0x78, + 0x55, 0xb2, 0xe0, 0x74, 0x25, 0x61, 0x67, 0xc0, + 0xe8, 0x1e, 0x5e, 0xd8 +}; + +uint8_t attestation_msg_sample1[] = +{ + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x97, 0x9e, 0xb9, 0x5a, 0xdd, 0x14, 0x17, + 0xf2, 0xfa, 0xad, 0xfa, 0xd7, 0x66, 0x73, 0xfd, + 0x71, 0x57, 0xf4, 0xe9, 0x8d, 0xee, 0xaf, 0x42, + 0x5e, 0xbb, 0x8a, 0x4c, 0xd4, 0x84, 0xdc, 0x83, + 0x6a, 0x8, 0x70, 0xd, 0xf2, 0x42, 0x8b, 0x2b, + 0xee, 0x42, 0xb0, 0x85, 0xe5, 0xbf, 0x99, 0xc5, + 0x22, 0xf8, 0x37, 0xf7, 0xee, 0xb6, 0x2c, 0xd5, + 0x8c, 0x37, 0xa2, 0xd2, 0x51, 0xed, 0x45, 0xf9, + 0x65, 0xf2, 0x25, 0x8a, 0xf9, 0x9, 0x2d, 0xdb, + 0xdc, 0x4a, 0x73, 0xbd, 0x15, 0x49, 0x2, 0x10, + 0xd, 0x8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x54, 0x1c, 0xdd, 0x52, 0x93, 0xd8, 0xd4, + 0x28, 0x9d, 0x24, 0x7d, 0x4b, 0xe5, 0xcc, 0xe8, + 0xc0 +}; + +uint8_t attestation_msg_sample2[] = +{ + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x97, 0x9e, 0xb9, 0x5a, 0xdd, 0x14, 0x17, + 0xf2, 0xfa, 0xad, 0xfa, 0xd7, 0x66, 0x73, 0xfd, + 0x71, 0x57, 0xf4, 0xe9, 0x8d, 0xee, 0xaf, 0x42, + 0x5e, 0xbb, 0x8a, 0x4c, 0xd4, 0x84, 0xdc, 0x83, + 0x6a, 0x8, 0x70, 0xd, 0xf2, 0x42, 0x8b, 0x2b, + 0xee, 0x42, 0xb0, 0x85, 0xe5, 0xbf, 0x99, 0xc5, + 0x22, 0xf8, 0x37, 0xf7, 0xee, 0xb6, 0x2c, 0xd5, + 0x8c, 0x37, 0xa2, 0xd2, 0x51, 0xed, 0x45, 0xf9, + 0x65, 0x82, 0x12, 0xa8, 0x53, 0x84, 0x65, 0x62, + 0x33, 0xc0, 0x6, 0x86, 0x9f, 0x82, 0xbb, 0x6d, + 0xd6, 0x8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0xb1, 0x60, 0x31, 0x45, 0xd1, 0xa9, 0x23, + 0x7b, 0x85, 0x3f, 0x8, 0x3f, 0x48, 0x6d, 0x2d, + 0xad +}; diff --git a/sgx-jvm/linux-sgx/SampleCode/RemoteAttestation/isv_enclave/isv_enclave.config.xml b/sgx-jvm/linux-sgx/SampleCode/RemoteAttestation/isv_enclave/isv_enclave.config.xml new file mode 100644 index 0000000000..0b95a3edb1 --- /dev/null +++ b/sgx-jvm/linux-sgx/SampleCode/RemoteAttestation/isv_enclave/isv_enclave.config.xml @@ -0,0 +1,11 @@ + + 0 + 0 + 0x40000 + 0x100000 + 1 + 1 + 0 + 0 + 0xFFFFFFFF + \ No newline at end of file diff --git a/sgx-jvm/linux-sgx/SampleCode/RemoteAttestation/isv_enclave/isv_enclave.cpp b/sgx-jvm/linux-sgx/SampleCode/RemoteAttestation/isv_enclave/isv_enclave.cpp new file mode 100644 index 0000000000..980de0c8db --- /dev/null +++ b/sgx-jvm/linux-sgx/SampleCode/RemoteAttestation/isv_enclave/isv_enclave.cpp @@ -0,0 +1,397 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + + +#include +#include "isv_enclave_t.h" +#include "sgx_tkey_exchange.h" +#include "sgx_tcrypto.h" +#include "string.h" + +// This is the public EC key of the SP. The corresponding private EC key is +// used by the SP to sign data used in the remote attestation SIGMA protocol +// to sign channel binding data in MSG2. A successful verification of the +// signature confirms the identity of the SP to the ISV app in remote +// attestation secure channel binding. The public EC key should be hardcoded in +// the enclave or delivered in a trustworthy manner. The use of a spoofed public +// EC key in the remote attestation with secure channel binding session may lead +// to a security compromise. Every different SP the enlcave communicates to +// must have a unique SP public key. Delivery of the SP public key is +// determined by the ISV. The TKE SIGMA protocl expects an Elliptical Curve key +// based on NIST P-256 +static const sgx_ec256_public_t g_sp_pub_key = { + { + 0x72, 0x12, 0x8a, 0x7a, 0x17, 0x52, 0x6e, 0xbf, + 0x85, 0xd0, 0x3a, 0x62, 0x37, 0x30, 0xae, 0xad, + 0x3e, 0x3d, 0xaa, 0xee, 0x9c, 0x60, 0x73, 0x1d, + 0xb0, 0x5b, 0xe8, 0x62, 0x1c, 0x4b, 0xeb, 0x38 + }, + { + 0xd4, 0x81, 0x40, 0xd9, 0x50, 0xe2, 0x57, 0x7b, + 0x26, 0xee, 0xb7, 0x41, 0xe7, 0xc6, 0x14, 0xe2, + 0x24, 0xb7, 0xbd, 0xc9, 0x03, 0xf2, 0x9a, 0x28, + 0xa8, 0x3c, 0xc8, 0x10, 0x11, 0x14, 0x5e, 0x06 + } + +}; + +// Used to store the secret passed by the SP in the sample code. The +// size is forced to be 8 bytes. Expected value is +// 0x01,0x02,0x03,0x04,0x0x5,0x0x6,0x0x7 +uint8_t g_secret[8] = {0}; + + +#ifdef SUPPLIED_KEY_DERIVATION + +#pragma message ("Supplied key derivation function is used.") + +typedef struct _hash_buffer_t +{ + uint8_t counter[4]; + sgx_ec256_dh_shared_t shared_secret; + uint8_t algorithm_id[4]; +} hash_buffer_t; + +const char ID_U[] = "SGXRAENCLAVE"; +const char ID_V[] = "SGXRASERVER"; + +// Derive two keys from shared key and key id. +bool derive_key( + const sgx_ec256_dh_shared_t *p_shared_key, + uint8_t key_id, + sgx_ec_key_128bit_t *first_derived_key, + sgx_ec_key_128bit_t *second_derived_key) +{ + sgx_status_t sgx_ret = SGX_SUCCESS; + hash_buffer_t hash_buffer; + sgx_sha_state_handle_t sha_context; + sgx_sha256_hash_t key_material; + + memset(&hash_buffer, 0, sizeof(hash_buffer_t)); + /* counter in big endian */ + hash_buffer.counter[3] = key_id; + + /*convert from little endian to big endian */ + for (size_t i = 0; i < sizeof(sgx_ec256_dh_shared_t); i++) + { + hash_buffer.shared_secret.s[i] = p_shared_key->s[sizeof(p_shared_key->s)-1 - i]; + } + + sgx_ret = sgx_sha256_init(&sha_context); + if (sgx_ret != SGX_SUCCESS) + { + return false; + } + sgx_ret = sgx_sha256_update((uint8_t*)&hash_buffer, sizeof(hash_buffer_t), sha_context); + if (sgx_ret != SGX_SUCCESS) + { + sgx_sha256_close(sha_context); + return false; + } + sgx_ret = sgx_sha256_update((uint8_t*)&ID_U, sizeof(ID_U), sha_context); + if (sgx_ret != SGX_SUCCESS) + { + sgx_sha256_close(sha_context); + return false; + } + sgx_ret = sgx_sha256_update((uint8_t*)&ID_V, sizeof(ID_V), sha_context); + if (sgx_ret != SGX_SUCCESS) + { + sgx_sha256_close(sha_context); + return false; + } + sgx_ret = sgx_sha256_get_hash(sha_context, &key_material); + if (sgx_ret != SGX_SUCCESS) + { + sgx_sha256_close(sha_context); + return false; + } + sgx_ret = sgx_sha256_close(sha_context); + + assert(sizeof(sgx_ec_key_128bit_t)* 2 == sizeof(sgx_sha256_hash_t)); + memcpy(first_derived_key, &key_material, sizeof(sgx_ec_key_128bit_t)); + memcpy(second_derived_key, (uint8_t*)&key_material + sizeof(sgx_ec_key_128bit_t), sizeof(sgx_ec_key_128bit_t)); + + // memset here can be optimized away by compiler, so please use memset_s on + // windows for production code and similar functions on other OSes. + memset(&key_material, 0, sizeof(sgx_sha256_hash_t)); + + return true; +} + +//isv defined key derivation function id +#define ISV_KDF_ID 2 + +typedef enum _derive_key_type_t +{ + DERIVE_KEY_SMK_SK = 0, + DERIVE_KEY_MK_VK, +} derive_key_type_t; + +sgx_status_t key_derivation(const sgx_ec256_dh_shared_t* shared_key, + uint16_t kdf_id, + sgx_ec_key_128bit_t* smk_key, + sgx_ec_key_128bit_t* sk_key, + sgx_ec_key_128bit_t* mk_key, + sgx_ec_key_128bit_t* vk_key) +{ + bool derive_ret = false; + + if (NULL == shared_key) + { + return SGX_ERROR_INVALID_PARAMETER; + } + + if (ISV_KDF_ID != kdf_id) + { + //fprintf(stderr, "\nError, key derivation id mismatch in [%s].", __FUNCTION__); + return SGX_ERROR_KDF_MISMATCH; + } + + derive_ret = derive_key(shared_key, DERIVE_KEY_SMK_SK, + smk_key, sk_key); + if (derive_ret != true) + { + //fprintf(stderr, "\nError, derive key fail in [%s].", __FUNCTION__); + return SGX_ERROR_UNEXPECTED; + } + + derive_ret = derive_key(shared_key, DERIVE_KEY_MK_VK, + mk_key, vk_key); + if (derive_ret != true) + { + //fprintf(stderr, "\nError, derive key fail in [%s].", __FUNCTION__); + return SGX_ERROR_UNEXPECTED; + } + return SGX_SUCCESS; +} +#else +#pragma message ("Default key derivation function is used.") +#endif + +// This ecall is a wrapper of sgx_ra_init to create the trusted +// KE exchange key context needed for the remote attestation +// SIGMA API's. Input pointers aren't checked since the trusted stubs +// copy them into EPC memory. +// +// @param b_pse Indicates whether the ISV app is using the +// platform services. +// @param p_context Pointer to the location where the returned +// key context is to be copied. +// +// @return Any error return from the create PSE session if b_pse +// is true. +// @return Any error returned from the trusted key exchange API +// for creating a key context. + +sgx_status_t enclave_init_ra( + int b_pse, + sgx_ra_context_t *p_context) +{ + // isv enclave call to trusted key exchange library. + sgx_status_t ret; + if(b_pse) + { + int busy_retry_times = 2; + do{ + ret = sgx_create_pse_session(); + }while (ret == SGX_ERROR_BUSY && busy_retry_times--); + if (ret != SGX_SUCCESS) + return ret; + } +#ifdef SUPPLIED_KEY_DERIVATION + ret = sgx_ra_init_ex(&g_sp_pub_key, b_pse, key_derivation, p_context); +#else + ret = sgx_ra_init(&g_sp_pub_key, b_pse, p_context); +#endif + if(b_pse) + { + sgx_close_pse_session(); + return ret; + } + return ret; +} + + +// Closes the tKE key context used during the SIGMA key +// exchange. +// +// @param context The trusted KE library key context. +// +// @return Return value from the key context close API + +sgx_status_t SGXAPI enclave_ra_close( + sgx_ra_context_t context) +{ + sgx_status_t ret; + ret = sgx_ra_close(context); + return ret; +} + + +// Verify the mac sent in att_result_msg from the SP using the +// MK key. Input pointers aren't checked since the trusted stubs +// copy them into EPC memory. +// +// +// @param context The trusted KE library key context. +// @param p_message Pointer to the message used to produce MAC +// @param message_size Size in bytes of the message. +// @param p_mac Pointer to the MAC to compare to. +// @param mac_size Size in bytes of the MAC +// +// @return SGX_ERROR_INVALID_PARAMETER - MAC size is incorrect. +// @return Any error produced by tKE API to get SK key. +// @return Any error produced by the AESCMAC function. +// @return SGX_ERROR_MAC_MISMATCH - MAC compare fails. + +sgx_status_t verify_att_result_mac(sgx_ra_context_t context, + uint8_t* p_message, + size_t message_size, + uint8_t* p_mac, + size_t mac_size) +{ + sgx_status_t ret; + sgx_ec_key_128bit_t mk_key; + + if(mac_size != sizeof(sgx_mac_t)) + { + ret = SGX_ERROR_INVALID_PARAMETER; + return ret; + } + if(message_size > UINT32_MAX) + { + ret = SGX_ERROR_INVALID_PARAMETER; + return ret; + } + + do { + uint8_t mac[SGX_CMAC_MAC_SIZE] = {0}; + + ret = sgx_ra_get_keys(context, SGX_RA_KEY_MK, &mk_key); + if(SGX_SUCCESS != ret) + { + break; + } + ret = sgx_rijndael128_cmac_msg(&mk_key, + p_message, + (uint32_t)message_size, + &mac); + if(SGX_SUCCESS != ret) + { + break; + } + if(0 == consttime_memequal(p_mac, mac, sizeof(mac))) + { + ret = SGX_ERROR_MAC_MISMATCH; + break; + } + + } + while(0); + + return ret; +} + + +// Generate a secret information for the SP encrypted with SK. +// Input pointers aren't checked since the trusted stubs copy +// them into EPC memory. +// +// @param context The trusted KE library key context. +// @param p_secret Message containing the secret. +// @param secret_size Size in bytes of the secret message. +// @param p_gcm_mac The pointer the the AESGCM MAC for the +// message. +// +// @return SGX_ERROR_INVALID_PARAMETER - secret size if +// incorrect. +// @return Any error produced by tKE API to get SK key. +// @return Any error produced by the AESGCM function. +// @return SGX_ERROR_UNEXPECTED - the secret doesn't match the +// expected value. + +sgx_status_t put_secret_data( + sgx_ra_context_t context, + uint8_t *p_secret, + uint32_t secret_size, + uint8_t *p_gcm_mac) +{ + sgx_status_t ret = SGX_SUCCESS; + sgx_ec_key_128bit_t sk_key; + + do { + if(secret_size != 8) + { + ret = SGX_ERROR_INVALID_PARAMETER; + break; + } + + ret = sgx_ra_get_keys(context, SGX_RA_KEY_SK, &sk_key); + if(SGX_SUCCESS != ret) + { + break; + } + + uint8_t aes_gcm_iv[12] = {0}; + ret = sgx_rijndael128GCM_decrypt(&sk_key, + p_secret, + secret_size, + &g_secret[0], + &aes_gcm_iv[0], + 12, + NULL, + 0, + (const sgx_aes_gcm_128bit_tag_t *) + (p_gcm_mac)); + + uint32_t i; + bool secret_match = true; + for(i=0;i +#include +#include "ecp.h" + +#include "sample_libcrypto.h" + + +#define MAC_KEY_SIZE 16 + +errno_t memcpy_s( + void *dest, + size_t numberOfElements, + const void *src, + size_t count) +{ + if(numberOfElementss[sizeof(p_shared_key->s) - 1 - i]; + } + + sample_ret = sample_sha256_init(&sha_context); + if (sample_ret != SAMPLE_SUCCESS) + { + return false; + } + sample_ret = sample_sha256_update((uint8_t*)&hash_buffer, sizeof(hash_buffer_t), sha_context); + if (sample_ret != SAMPLE_SUCCESS) + { + sample_sha256_close(sha_context); + return false; + } + sample_ret = sample_sha256_update((uint8_t*)ID_U, sizeof(ID_U), sha_context); + if (sample_ret != SAMPLE_SUCCESS) + { + sample_sha256_close(sha_context); + return false; + } + sample_ret = sample_sha256_update((uint8_t*)ID_V, sizeof(ID_V), sha_context); + if (sample_ret != SAMPLE_SUCCESS) + { + sample_sha256_close(sha_context); + return false; + } + sample_ret = sample_sha256_get_hash(sha_context, &key_material); + if (sample_ret != SAMPLE_SUCCESS) + { + sample_sha256_close(sha_context); + return false; + } + sample_ret = sample_sha256_close(sha_context); + + static_assert(sizeof(sample_ec_key_128bit_t)* 2 == sizeof(sample_sha256_hash_t), "structure size mismatch."); + memcpy(first_derived_key, &key_material, sizeof(sample_ec_key_128bit_t)); + memcpy(second_derived_key, (uint8_t*)&key_material + sizeof(sample_ec_key_128bit_t), sizeof(sample_ec_key_128bit_t)); + + // memset here can be optimized away by compiler, so please use memset_s on + // windows for production code and similar functions on other OSes. + memset(&key_material, 0, sizeof(sample_sha256_hash_t)); + + return true; +} + +#else + +#pragma message ("Default key derivation function is used.") + +#define EC_DERIVATION_BUFFER_SIZE(label_length) ((label_length) +4) + +const char str_SMK[] = "SMK"; +const char str_SK[] = "SK"; +const char str_MK[] = "MK"; +const char str_VK[] = "VK"; + +// Derive key from shared key and key id. +// key id should be sample_derive_key_type_t. +bool derive_key( + const sample_ec_dh_shared_t *p_shared_key, + uint8_t key_id, + sample_ec_key_128bit_t* derived_key) +{ + sample_status_t sample_ret = SAMPLE_SUCCESS; + uint8_t cmac_key[MAC_KEY_SIZE]; + sample_ec_key_128bit_t key_derive_key; + + memset(&cmac_key, 0, MAC_KEY_SIZE); + + sample_ret = sample_rijndael128_cmac_msg( + (sample_cmac_128bit_key_t *)&cmac_key, + (uint8_t*)p_shared_key, + sizeof(sample_ec_dh_shared_t), + (sample_cmac_128bit_tag_t *)&key_derive_key); + if (sample_ret != SAMPLE_SUCCESS) + { + // memset here can be optimized away by compiler, so please use memset_s on + // windows for production code and similar functions on other OSes. + memset(&key_derive_key, 0, sizeof(key_derive_key)); + return false; + } + + const char *label = NULL; + uint32_t label_length = 0; + switch (key_id) + { + case SAMPLE_DERIVE_KEY_SMK: + label = str_SMK; + label_length = sizeof(str_SMK) -1; + break; + case SAMPLE_DERIVE_KEY_SK: + label = str_SK; + label_length = sizeof(str_SK) -1; + break; + case SAMPLE_DERIVE_KEY_MK: + label = str_MK; + label_length = sizeof(str_MK) -1; + break; + case SAMPLE_DERIVE_KEY_VK: + label = str_VK; + label_length = sizeof(str_VK) -1; + break; + default: + // memset here can be optimized away by compiler, so please use memset_s on + // windows for production code and similar functions on other OSes. + memset(&key_derive_key, 0, sizeof(key_derive_key)); + return false; + break; + } + /* derivation_buffer = counter(0x01) || label || 0x00 || output_key_len(0x0080) */ + uint32_t derivation_buffer_length = EC_DERIVATION_BUFFER_SIZE(label_length); + uint8_t *p_derivation_buffer = (uint8_t *)malloc(derivation_buffer_length); + if (p_derivation_buffer == NULL) + { + // memset here can be optimized away by compiler, so please use memset_s on + // windows for production code and similar functions on other OSes. + memset(&key_derive_key, 0, sizeof(key_derive_key)); + return false; + } + memset(p_derivation_buffer, 0, derivation_buffer_length); + + /*counter = 0x01 */ + p_derivation_buffer[0] = 0x01; + /*label*/ + memcpy(&p_derivation_buffer[1], label, label_length); + /*output_key_len=0x0080*/ + uint16_t *key_len = (uint16_t *)(&(p_derivation_buffer[derivation_buffer_length - 2])); + *key_len = 0x0080; + + + sample_ret = sample_rijndael128_cmac_msg( + (sample_cmac_128bit_key_t *)&key_derive_key, + p_derivation_buffer, + derivation_buffer_length, + (sample_cmac_128bit_tag_t *)derived_key); + free(p_derivation_buffer); + // memset here can be optimized away by compiler, so please use memset_s on + // windows for production code and similar functions on other OSes. + memset(&key_derive_key, 0, sizeof(key_derive_key)); + if (sample_ret != SAMPLE_SUCCESS) + { + return false; + } + return true; +} +#endif \ No newline at end of file diff --git a/sgx-jvm/linux-sgx/SampleCode/RemoteAttestation/service_provider/ecp.h b/sgx-jvm/linux-sgx/SampleCode/RemoteAttestation/service_provider/ecp.h new file mode 100644 index 0000000000..0a562b05f0 --- /dev/null +++ b/sgx-jvm/linux-sgx/SampleCode/RemoteAttestation/service_provider/ecp.h @@ -0,0 +1,114 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef _ECP_H +#define _ECP_H + +#include +#include + +#include "remote_attestation_result.h" + +#ifndef SAMPLE_FEBITSIZE + #define SAMPLE_FEBITSIZE 256 +#endif + +#define SAMPLE_ECP_KEY_SIZE (SAMPLE_FEBITSIZE/8) + +typedef struct sample_ec_priv_t +{ + uint8_t r[SAMPLE_ECP_KEY_SIZE]; +} sample_ec_priv_t; + +typedef struct sample_ec_dh_shared_t +{ + uint8_t s[SAMPLE_ECP_KEY_SIZE]; +}sample_ec_dh_shared_t; + +typedef uint8_t sample_ec_key_128bit_t[16]; + +#define SAMPLE_EC_MAC_SIZE 16 + +#ifdef __cplusplus +extern "C" { +#endif + + +#ifndef _ERRNO_T_DEFINED +#define _ERRNO_T_DEFINED +typedef int errno_t; +#endif +errno_t memcpy_s(void *dest, size_t numberOfElements, const void *src, + size_t count); + + +#ifdef SUPPLIED_KEY_DERIVATION + +typedef enum _sample_derive_key_type_t +{ + SAMPLE_DERIVE_KEY_SMK_SK = 0, + SAMPLE_DERIVE_KEY_MK_VK, +} sample_derive_key_type_t; + +bool derive_key( + const sample_ec_dh_shared_t *p_shared_key, + uint8_t key_id, + sample_ec_key_128bit_t *first_derived_key, + sample_ec_key_128bit_t *second_derived_key); + +#else + +typedef enum _sample_derive_key_type_t +{ + SAMPLE_DERIVE_KEY_SMK = 0, + SAMPLE_DERIVE_KEY_SK, + SAMPLE_DERIVE_KEY_MK, + SAMPLE_DERIVE_KEY_VK, +} sample_derive_key_type_t; + +bool derive_key( + const sample_ec_dh_shared_t *p_shared_key, + uint8_t key_id, + sample_ec_key_128bit_t *derived_key); + +#endif + +bool verify_cmac128( + sample_ec_key_128bit_t mac_key, + const uint8_t *p_data_buf, + uint32_t buf_size, + const uint8_t *p_mac_buf); +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/sgx-jvm/linux-sgx/SampleCode/RemoteAttestation/service_provider/ias_ra.cpp b/sgx-jvm/linux-sgx/SampleCode/RemoteAttestation/service_provider/ias_ra.cpp new file mode 100644 index 0000000000..ec6f52f769 --- /dev/null +++ b/sgx-jvm/linux-sgx/SampleCode/RemoteAttestation/service_provider/ias_ra.cpp @@ -0,0 +1,254 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + + + +#include "service_provider.h" +#include "sample_libcrypto.h" +#include "ecp.h" +#include +#include +#include +#include +#include +#include "ias_ra.h" + +//This whole file is used as simulation of the interfaces to be +// delivered an attestation server. + + +#define UNUSED(expr) do { (void)(expr); } while (0) + +#if !defined(SWAP_ENDIAN_DW) + #define SWAP_ENDIAN_DW(dw) ((((dw) & 0x000000ff) << 24) \ + | (((dw) & 0x0000ff00) << 8) \ + | (((dw) & 0x00ff0000) >> 8) \ + | (((dw) & 0xff000000) >> 24)) +#endif +#if !defined(SWAP_ENDIAN_32B) + #define SWAP_ENDIAN_32B(ptr) \ +{\ + unsigned int temp = 0; \ + temp = SWAP_ENDIAN_DW(((unsigned int*)(ptr))[0]); \ + ((unsigned int*)(ptr))[0] = SWAP_ENDIAN_DW(((unsigned int*)(ptr))[7]); \ + ((unsigned int*)(ptr))[7] = temp; \ + temp = SWAP_ENDIAN_DW(((unsigned int*)(ptr))[1]); \ + ((unsigned int*)(ptr))[1] = SWAP_ENDIAN_DW(((unsigned int*)(ptr))[6]); \ + ((unsigned int*)(ptr))[6] = temp; \ + temp = SWAP_ENDIAN_DW(((unsigned int*)(ptr))[2]); \ + ((unsigned int*)(ptr))[2] = SWAP_ENDIAN_DW(((unsigned int*)(ptr))[5]); \ + ((unsigned int*)(ptr))[5] = temp; \ + temp = SWAP_ENDIAN_DW(((unsigned int*)(ptr))[3]); \ + ((unsigned int*)(ptr))[3] = SWAP_ENDIAN_DW(((unsigned int*)(ptr))[4]); \ + ((unsigned int*)(ptr))[4] = temp; \ +} +#endif + +// This is the ECDSA NIST P-256 private key used to sign platform_info_blob. +// This private +// key and the public key in SDK untrusted KElibrary should be a temporary key +// pair. For production parts an attestation server will sign the platform_info_blob with the +// production private key and the SDK untrusted KE library will have the public +// key for verifcation. + +static const sample_ec256_private_t g_rk_priv_key = +{{ + 0x63,0x2c,0xd4,0x02,0x7a,0xdc,0x56,0xa5, + 0x59,0x6c,0x44,0x3e,0x43,0xca,0x4e,0x0b, + 0x58,0xcd,0x78,0xcb,0x3c,0x7e,0xd5,0xb9, + 0xf2,0x91,0x5b,0x39,0x0d,0xb3,0xb5,0xfb +}}; + +static sample_spid_t g_sim_spid = {"Service X"}; + + +// Simulates the attestation server function for verifying the quote produce by +// the ISV enclave. It doesn't decrypt or verify the quote in +// the simulation. Just produces the attestaion verification +// report with the platform info blob. +// +// @param p_isv_quote Pointer to the quote generated by the ISV +// enclave. +// @param pse_manifest Pointer to the PSE manifest if used. +// @param p_attestation_verification_report Pointer the outputed +// verification report. +// +// @return int + +int ias_verify_attestation_evidence( + sample_quote_t *p_isv_quote, + uint8_t* pse_manifest, + ias_att_report_t* p_attestation_verification_report) +{ + int ret = 0; + sample_ecc_state_handle_t ecc_state = NULL; + + //unused parameters + UNUSED(pse_manifest); + + if((NULL == p_isv_quote) || + (NULL == p_attestation_verification_report)) + { + return -1; + } + //Decrypt the Quote signature and verify. + + p_attestation_verification_report->id = 0x12345678; + p_attestation_verification_report->status = IAS_QUOTE_OK; + p_attestation_verification_report->revocation_reason = + IAS_REVOC_REASON_NONE; + p_attestation_verification_report->info_blob.sample_epid_group_status = + 0 << IAS_EPID_GROUP_STATUS_REVOKED_BIT_POS + | 0 << IAS_EPID_GROUP_STATUS_REKEY_AVAILABLE_BIT_POS; + p_attestation_verification_report->info_blob.sample_tcb_evaluation_status = + 0 << IAS_TCB_EVAL_STATUS_CPUSVN_OUT_OF_DATE_BIT_POS + | 0 << IAS_TCB_EVAL_STATUS_ISVSVN_OUT_OF_DATE_BIT_POS; + p_attestation_verification_report->info_blob.pse_evaluation_status = + 0 << IAS_PSE_EVAL_STATUS_ISVSVN_OUT_OF_DATE_BIT_POS + | 0 << IAS_PSE_EVAL_STATUS_EPID_GROUP_REVOKED_BIT_POS + | 0 << IAS_PSE_EVAL_STATUS_PSDASVN_OUT_OF_DATE_BIT_POS + | 0 << IAS_PSE_EVAL_STATUS_SIGRL_OUT_OF_DATE_BIT_POS + | 0 << IAS_PSE_EVAL_STATUS_PRIVRL_OUT_OF_DATE_BIT_POS; + memset(p_attestation_verification_report-> + info_blob.latest_equivalent_tcb_psvn, 0, PSVN_SIZE); + memset(p_attestation_verification_report->info_blob.latest_pse_isvsvn, + 0, ISVSVN_SIZE); + memset(p_attestation_verification_report->info_blob.latest_psda_svn, + 0, PSDA_SVN_SIZE); + memset(p_attestation_verification_report->info_blob.performance_rekey_gid, + 0, GID_SIZE); + + // @TODO: Product signing algorithm still TBD. May be RSA2048 signing. + // Generate the Service providers ECCDH key pair. + do { + ret = sample_ecc256_open_context(&ecc_state); + if (SAMPLE_SUCCESS != ret) { + fprintf(stderr, "\nError, cannot get ECC cotext in [%s].", + __FUNCTION__); + ret = -1; + break; + } + // Sign + ret = sample_ecdsa_sign( + (uint8_t *)&p_attestation_verification_report-> + info_blob.sample_epid_group_status, + sizeof(ias_platform_info_blob_t) - sizeof(sample_ec_sign256_t), + (sample_ec256_private_t *)&g_rk_priv_key, + (sample_ec256_signature_t *)&p_attestation_verification_report-> + info_blob.signature, + ecc_state); + if (SAMPLE_SUCCESS != ret) { + fprintf(stderr, "\nError, sign ga_gb fail in [%s].", __FUNCTION__); + ret = SP_INTERNAL_ERROR; + break; + } + SWAP_ENDIAN_32B(p_attestation_verification_report-> + info_blob.signature.x); + SWAP_ENDIAN_32B(p_attestation_verification_report-> + info_blob.signature.y); + + }while (0); + if (ecc_state) { + sample_ecc256_close_context(ecc_state); + } + p_attestation_verification_report->pse_status = IAS_PSE_OK; + + // For now, don't simulate the policy reports. + p_attestation_verification_report->policy_report_size = 0; + return(ret); +} + + +// Simulates retrieving the SIGRL for upon the SP request. +// +// @param gid Group ID for the EPID key. +// @param p_sig_rl_size Pointer to the output value of the full +// SIGRL size in bytes. (including the +// signature). +// @param p_sig_rl Pointer to the output of the SIGRL. +// +// @return int + +int ias_get_sigrl( + const sample_epid_group_id_t gid, + uint32_t *p_sig_rl_size, + uint8_t **p_sig_rl) +{ + int ret = 0; + + UNUSED(gid); + + do { + + if (NULL == p_sig_rl || NULL == p_sig_rl_size) { + ret = -1; + break; + } + *p_sig_rl_size = 0; + *p_sig_rl = NULL; + // we should try to get sig_rl from an attestation server + break; + }while (0); + + return(ret); +} + + +// Used to simulate the enrollment function of an attestation server. It only +// gives back the SPID right now. In production, the enrollment +// occurs out of context from an attestation attempt and only +// occurs once. +// +// +// @param sp_credentials +// @param p_spid +// @param p_authentication_token +// +// @return int + +int ias_enroll( + int sp_credentials, + sample_spid_t *p_spid, + int *p_authentication_token) +{ + UNUSED(sp_credentials); + UNUSED(p_authentication_token); + + if (NULL != p_spid) { + memcpy_s(p_spid, sizeof(sample_spid_t), &g_sim_spid, + sizeof(sample_spid_t)); + } else { + return(1); + } + return(0); +} + + diff --git a/sgx-jvm/linux-sgx/SampleCode/RemoteAttestation/service_provider/ias_ra.h b/sgx-jvm/linux-sgx/SampleCode/RemoteAttestation/service_provider/ias_ra.h new file mode 100644 index 0000000000..a984d0f06e --- /dev/null +++ b/sgx-jvm/linux-sgx/SampleCode/RemoteAttestation/service_provider/ias_ra.h @@ -0,0 +1,209 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + + + +#ifndef _IAS_RA_H +#define _IAS_RA_H + +#include "ecp.h" + +typedef enum { + IAS_QUOTE_OK, + IAS_QUOTE_SIGNATURE_INVALID, + IAS_QUOTE_GROUP_REVOKED, + IAS_QUOTE_SIGNATURE_REVOKED, + IAS_QUOTE_KEY_REVOKED, + IAS_QUOTE_SIGRL_VERSION_MISMATCH, + IAS_QUOTE_GROUP_OUT_OF_DATE, +} ias_quote_status_t; + +// These status should align with the definition in IAS API spec(rev 0.6) +typedef enum { + IAS_PSE_OK, + IAS_PSE_DESC_TYPE_NOT_SUPPORTED, + IAS_PSE_ISVSVN_OUT_OF_DATE, + IAS_PSE_MISCSELECT_INVALID, + IAS_PSE_ATTRIBUTES_INVALID, + IAS_PSE_MRSIGNER_INVALID, + IAS_PS_HW_GID_REVOKED, + IAS_PS_HW_PRIVKEY_RLVER_MISMATCH, + IAS_PS_HW_SIG_RLVER_MISMATCH, + IAS_PS_HW_CA_ID_INVALID, + IAS_PS_HW_SEC_INFO_INVALID, + IAS_PS_HW_PSDA_SVN_OUT_OF_DATE, +} ias_pse_status_t; + +// Revocation Reasons from RFC5280 +typedef enum { + IAS_REVOC_REASON_NONE, + IAS_REVOC_REASON_KEY_COMPROMISE, + IAS_REVOC_REASON_CA_COMPROMISED, + IAS_REVOC_REASON_SUPERCEDED, + IAS_REVOC_REASON_CESSATION_OF_OPERATION, + IAS_REVOC_REASON_CERTIFICATE_HOLD, + IAS_REVOC_REASON_PRIVILEGE_WITHDRAWN, + IAS_REVOC_REASON_AA_COMPROMISE, +} ias_revoc_reason_t; + +// These status should align with the definition in IAS API spec(rev 0.6) +#define IAS_EPID_GROUP_STATUS_REVOKED_BIT_POS 0x00 +#define IAS_EPID_GROUP_STATUS_REKEY_AVAILABLE_BIT_POS 0x01 + +#define IAS_TCB_EVAL_STATUS_CPUSVN_OUT_OF_DATE_BIT_POS 0x00 +#define IAS_TCB_EVAL_STATUS_ISVSVN_OUT_OF_DATE_BIT_POS 0x01 + +#define IAS_PSE_EVAL_STATUS_ISVSVN_OUT_OF_DATE_BIT_POS 0x00 +#define IAS_PSE_EVAL_STATUS_EPID_GROUP_REVOKED_BIT_POS 0x01 +#define IAS_PSE_EVAL_STATUS_PSDASVN_OUT_OF_DATE_BIT_POS 0x02 +#define IAS_PSE_EVAL_STATUS_SIGRL_OUT_OF_DATE_BIT_POS 0x03 +#define IAS_PSE_EVAL_STATUS_PRIVRL_OUT_OF_DATE_BIT_POS 0x04 + +// These status should align with the definition in IAS API spec(rev 0.6) +#define ISVSVN_SIZE 2 +#define PSDA_SVN_SIZE 4 +#define GID_SIZE 4 +#define PSVN_SIZE 18 + +#define SAMPLE_HASH_SIZE 32 // SHA256 +#define SAMPLE_MAC_SIZE 16 // Message Authentication Code + // - 16 bytes + +#define SAMPLE_REPORT_DATA_SIZE 64 + +typedef uint8_t sample_measurement_t[SAMPLE_HASH_SIZE]; +typedef uint8_t sample_mac_t[SAMPLE_MAC_SIZE]; +typedef uint8_t sample_report_data_t[SAMPLE_REPORT_DATA_SIZE]; +typedef uint16_t sample_prod_id_t; + +#define SAMPLE_CPUSVN_SIZE 16 + +typedef uint8_t sample_cpu_svn_t[SAMPLE_CPUSVN_SIZE]; +typedef uint16_t sample_isv_svn_t; + +typedef struct sample_attributes_t +{ + uint64_t flags; + uint64_t xfrm; +} sample_attributes_t; + +typedef struct sample_report_body_t { + sample_cpu_svn_t cpu_svn; // ( 0) Security Version of the CPU + uint8_t reserved1[32]; // ( 16) + sample_attributes_t attributes; // ( 48) Any special Capabilities + // the Enclave possess + sample_measurement_t mr_enclave; // ( 64) The value of the enclave's + // ENCLAVE measurement + uint8_t reserved2[32]; // ( 96) + sample_measurement_t mr_signer; // (128) The value of the enclave's + // SIGNER measurement + uint8_t reserved3[32]; // (160) + sample_measurement_t mr_reserved1; // (192) + sample_measurement_t mr_reserved2; // (224) + sample_prod_id_t isv_prod_id; // (256) Product ID of the Enclave + sample_isv_svn_t isv_svn; // (258) Security Version of the + // Enclave + uint8_t reserved4[60]; // (260) + sample_report_data_t report_data; // (320) Data provided by the user +} sample_report_body_t; + +#pragma pack(push, 1) + + +// This is a context data structure used in SP side +// @TODO: Modify at production to use the values specified by the Production +// IAS API +typedef struct _ias_att_report_t +{ + uint32_t id; + ias_quote_status_t status; + uint32_t revocation_reason; + ias_platform_info_blob_t info_blob; + ias_pse_status_t pse_status; + uint32_t policy_report_size; + + uint8_t policy_report[];// IAS_Q: Why does it specify a + // list of reports? + + +} ias_att_report_t; + +typedef uint8_t sample_epid_group_id_t[4]; + +typedef struct sample_spid_t +{ + uint8_t id[16]; +} sample_spid_t; + +typedef struct sample_basename_t +{ + uint8_t name[32]; +} sample_basename_t; + + +typedef struct sample_quote_nonce_t +{ + uint8_t rand[16]; +} sample_quote_nonce_t; + +#define SAMPLE_QUOTE_UNLINKABLE_SIGNATURE 0 +#define SAMPLE_QUOTE_LINKABLE_SIGNATURE 1 + +typedef struct sample_quote_t { + uint16_t version; // 0 + uint16_t sign_type; // 2 + sample_epid_group_id_t epid_group_id; // 4 + sample_isv_svn_t qe_svn; // 8 + uint8_t reserved[6]; // 10 + sample_basename_t basename; // 16 + sample_report_body_t report_body; // 48 + uint32_t signature_len; // 432 + uint8_t signature[]; // 436 +} sample_quote_t; + +#pragma pack(pop) + +#ifdef __cplusplus +extern "C" { +#endif + +int ias_enroll(int sp_credentials, sample_spid_t* spid, + int* authentication_token); +int ias_get_sigrl(const sample_epid_group_id_t gid, uint32_t* p_sig_rl_size, + uint8_t** p_sig_rl); +int ias_verify_attestation_evidence(sample_quote_t* p_isv_quote, + uint8_t* pse_manifest, + ias_att_report_t* attestation_verification_report); +#ifdef __cplusplus +} +#endif + +#endif diff --git a/sgx-jvm/linux-sgx/SampleCode/RemoteAttestation/service_provider/network_ra.cpp b/sgx-jvm/linux-sgx/SampleCode/RemoteAttestation/service_provider/network_ra.cpp new file mode 100644 index 0000000000..f8ab863720 --- /dev/null +++ b/sgx-jvm/linux-sgx/SampleCode/RemoteAttestation/service_provider/network_ra.cpp @@ -0,0 +1,134 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + + + +#include +#include +#include +#include "network_ra.h" +#include "service_provider.h" + + +// Used to send requests to the service provider sample. It +// simulates network communication between the ISV app and the +// ISV service provider. This would be modified in a real +// product to use the proper IP communication. +// +// @param server_url String name of the server URL +// @param p_req Pointer to the message to be sent. +// @param p_resp Pointer to a pointer of the response message. + +// @return int + +int ra_network_send_receive(const char *server_url, + const ra_samp_request_header_t *p_req, + ra_samp_response_header_t **p_resp) +{ + int ret = 0; + ra_samp_response_header_t* p_resp_msg; + + if((NULL == server_url) || + (NULL == p_req) || + (NULL == p_resp)) + { + return -1; + } + + switch(p_req->type) + { + + case TYPE_RA_MSG0: + ret = sp_ra_proc_msg0_req((const sample_ra_msg0_t*)((uint8_t*)p_req + + sizeof(ra_samp_request_header_t)), + p_req->size); + if (0 != ret) + { + fprintf(stderr, "\nError, call sp_ra_proc_msg1_req fail [%s].", + __FUNCTION__); + } + break; + + case TYPE_RA_MSG1: + ret = sp_ra_proc_msg1_req((const sample_ra_msg1_t*)((uint8_t*)p_req + + sizeof(ra_samp_request_header_t)), + p_req->size, + &p_resp_msg); + if(0 != ret) + { + fprintf(stderr, "\nError, call sp_ra_proc_msg1_req fail [%s].", + __FUNCTION__); + } + else + { + *p_resp = p_resp_msg; + } + break; + + case TYPE_RA_MSG3: + ret =sp_ra_proc_msg3_req((const sample_ra_msg3_t*)((uint8_t*)p_req + + sizeof(ra_samp_request_header_t)), + p_req->size, + &p_resp_msg); + if(0 != ret) + { + fprintf(stderr, "\nError, call sp_ra_proc_msg3_req fail [%s].", + __FUNCTION__); + } + else + { + *p_resp = p_resp_msg; + } + break; + + default: + ret = -1; + fprintf(stderr, "\nError, unknown ra message type. Type = %d [%s].", + p_req->type, __FUNCTION__); + break; + } + + return ret; +} + +// Used to free the response messages. In the sample code, the +// response messages are allocated by the SP code. +// +// +// @param resp Pointer to the response buffer to be freed. + +void ra_free_network_response_buffer(ra_samp_response_header_t *resp) +{ + if(resp!=NULL) + { + free(resp); + } +} diff --git a/sgx-jvm/linux-sgx/SampleCode/RemoteAttestation/service_provider/network_ra.h b/sgx-jvm/linux-sgx/SampleCode/RemoteAttestation/service_provider/network_ra.h new file mode 100644 index 0000000000..9091bfb67c --- /dev/null +++ b/sgx-jvm/linux-sgx/SampleCode/RemoteAttestation/service_provider/network_ra.h @@ -0,0 +1,95 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + + + +#ifndef _NETWORK_RA_H +#define _NETWORK_RA_H + + +/* Enum for all possible message types between the ISV app and + * the ISV SP. Requests and responses in the remote attestation + * sample. + */ +typedef enum _ra_msg_type_t +{ + TYPE_RA_MSG0, + TYPE_RA_MSG1, + TYPE_RA_MSG2, + TYPE_RA_MSG3, + TYPE_RA_ATT_RESULT, +}ra_msg_type_t; + +/* Enum for all possible message types between the SP and IAS. + * Network communication is not simulated in the remote + * attestation sample. Currently these aren't used. + */ +typedef enum _ias_msg_type_t +{ + TYPE_IAS_ENROLL, + TYPE_IAS_GET_SIGRL, + TYPE_IAS_SIGRL, + TYPE_IAS_ATT_EVIDENCE, + TYPE_IAS_ATT_RESULT, +}ias_msg_type_t; + +#pragma pack(1) +typedef struct _ra_samp_request_header_t{ + uint8_t type; /* set to one of ra_msg_type_t*/ + uint32_t size; /*size of request body*/ + uint8_t align[3]; + uint8_t body[]; +}ra_samp_request_header_t; + +typedef struct _ra_samp_response_header_t{ + uint8_t type; /* set to one of ra_msg_type_t*/ + uint8_t status[2]; + uint32_t size; /*size of the response body*/ + uint8_t align[1]; + uint8_t body[]; +}ra_samp_response_header_t; + +#pragma pack() + +#ifdef __cplusplus +extern "C" { +#endif + +int ra_network_send_receive(const char *server_url, + const ra_samp_request_header_t *req, + ra_samp_response_header_t **p_resp); +void ra_free_network_response_buffer(ra_samp_response_header_t *resp); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/sgx-jvm/linux-sgx/SampleCode/RemoteAttestation/service_provider/remote_attestation_result.h b/sgx-jvm/linux-sgx/SampleCode/RemoteAttestation/service_provider/remote_attestation_result.h new file mode 100644 index 0000000000..86d1532b6d --- /dev/null +++ b/sgx-jvm/linux-sgx/SampleCode/RemoteAttestation/service_provider/remote_attestation_result.h @@ -0,0 +1,105 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef _REMOTE_ATTESTATION_RESULT_H_ +#define _REMOTE_ATTESTATION_RESULT_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define SAMPLE_MAC_SIZE 16 /* Message Authentication Code*/ + /* - 16 bytes*/ +typedef uint8_t sample_mac_t[SAMPLE_MAC_SIZE]; + +#ifndef SAMPLE_FEBITSIZE + #define SAMPLE_FEBITSIZE 256 +#endif + +#define SAMPLE_NISTP256_KEY_SIZE (SAMPLE_FEBITSIZE/ 8 /sizeof(uint32_t)) + +typedef struct sample_ec_sign256_t +{ + uint32_t x[SAMPLE_NISTP256_KEY_SIZE]; + uint32_t y[SAMPLE_NISTP256_KEY_SIZE]; +} sample_ec_sign256_t; + +#pragma pack(push,1) + +#define SAMPLE_SP_TAG_SIZE 16 + +typedef struct sp_aes_gcm_data_t { + uint32_t payload_size; /* 0: Size of the payload which is*/ + /* encrypted*/ + uint8_t reserved[12]; /* 4: Reserved bits*/ + uint8_t payload_tag[SAMPLE_SP_TAG_SIZE]; + /* 16: AES-GMAC of the plain text,*/ + /* payload, and the sizes*/ + uint8_t payload[]; /* 32: Ciphertext of the payload*/ + /* followed by the plain text*/ +} sp_aes_gcm_data_t; + + +#define ISVSVN_SIZE 2 +#define PSDA_SVN_SIZE 4 +#define GID_SIZE 4 +#define PSVN_SIZE 18 + +/* @TODO: Modify at production to use the values specified by an Production*/ +/* attestation server API*/ +typedef struct ias_platform_info_blob_t +{ + uint8_t sample_epid_group_status; + uint16_t sample_tcb_evaluation_status; + uint16_t pse_evaluation_status; + uint8_t latest_equivalent_tcb_psvn[PSVN_SIZE]; + uint8_t latest_pse_isvsvn[ISVSVN_SIZE]; + uint8_t latest_psda_svn[PSDA_SVN_SIZE]; + uint8_t performance_rekey_gid[GID_SIZE]; + sample_ec_sign256_t signature; +} ias_platform_info_blob_t; + + +typedef struct sample_ra_att_result_msg_t { + ias_platform_info_blob_t platform_info_blob; + sample_mac_t mac; /* mac_smk(attestation_status)*/ + sp_aes_gcm_data_t secret; +} sample_ra_att_result_msg_t; + +#pragma pack(pop) + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/sgx-jvm/linux-sgx/SampleCode/RemoteAttestation/service_provider/service_provider.cpp b/sgx-jvm/linux-sgx/SampleCode/RemoteAttestation/service_provider/service_provider.cpp new file mode 100644 index 0000000000..1db44c0a96 --- /dev/null +++ b/sgx-jvm/linux-sgx/SampleCode/RemoteAttestation/service_provider/service_provider.cpp @@ -0,0 +1,738 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + + + +#include "service_provider.h" + +#include "sample_libcrypto.h" + +#include "ecp.h" + +#include +#include +#include +#include +#include +#include "ias_ra.h" + +#ifndef SAFE_FREE +#define SAFE_FREE(ptr) {if (NULL != (ptr)) {free(ptr); (ptr) = NULL;}} +#endif + +// This is supported extended epid group of SP. SP can support more than one +// extended epid group with different extended epid group id and credentials. +static const sample_extended_epid_group g_extended_epid_groups[] = { + { + 0, + ias_enroll, + ias_get_sigrl, + ias_verify_attestation_evidence + } +}; + +// This is the private EC key of SP, the corresponding public EC key is +// hard coded in isv_enclave. It is based on NIST P-256 curve. +static const sample_ec256_private_t g_sp_priv_key = { + { + 0x90, 0xe7, 0x6c, 0xbb, 0x2d, 0x52, 0xa1, 0xce, + 0x3b, 0x66, 0xde, 0x11, 0x43, 0x9c, 0x87, 0xec, + 0x1f, 0x86, 0x6a, 0x3b, 0x65, 0xb6, 0xae, 0xea, + 0xad, 0x57, 0x34, 0x53, 0xd1, 0x03, 0x8c, 0x01 + } +}; + +// This is the public EC key of SP, this key is hard coded in isv_enclave. +// It is based on NIST P-256 curve. Not used in the SP code. +static const sample_ec_pub_t g_sp_pub_key = { + { + 0x72, 0x12, 0x8a, 0x7a, 0x17, 0x52, 0x6e, 0xbf, + 0x85, 0xd0, 0x3a, 0x62, 0x37, 0x30, 0xae, 0xad, + 0x3e, 0x3d, 0xaa, 0xee, 0x9c, 0x60, 0x73, 0x1d, + 0xb0, 0x5b, 0xe8, 0x62, 0x1c, 0x4b, 0xeb, 0x38 + }, + { + 0xd4, 0x81, 0x40, 0xd9, 0x50, 0xe2, 0x57, 0x7b, + 0x26, 0xee, 0xb7, 0x41, 0xe7, 0xc6, 0x14, 0xe2, + 0x24, 0xb7, 0xbd, 0xc9, 0x03, 0xf2, 0x9a, 0x28, + 0xa8, 0x3c, 0xc8, 0x10, 0x11, 0x14, 0x5e, 0x06 + } +}; + +// This is a context data structure used on SP side +typedef struct _sp_db_item_t +{ + sample_ec_pub_t g_a; + sample_ec_pub_t g_b; + sample_ec_key_128bit_t vk_key;// Shared secret key for the REPORT_DATA + sample_ec_key_128bit_t mk_key;// Shared secret key for generating MAC's + sample_ec_key_128bit_t sk_key;// Shared secret key for encryption + sample_ec_key_128bit_t smk_key;// Used only for SIGMA protocol + sample_ec_priv_t b; + sample_ps_sec_prop_desc_t ps_sec_prop; +}sp_db_item_t; +static sp_db_item_t g_sp_db; + +static const sample_extended_epid_group* g_sp_extended_epid_group_id= NULL; +static bool g_is_sp_registered = false; +static int g_sp_credentials = 0; +static int g_authentication_token = 0; + +uint8_t g_secret[8] = {0,1,2,3,4,5,6,7}; + +sample_spid_t g_spid; + + +// Verify message 0 then configure extended epid group. +int sp_ra_proc_msg0_req(const sample_ra_msg0_t *p_msg0, + uint32_t msg0_size) +{ + int ret = -1; + + if (!p_msg0 || + (msg0_size != sizeof(sample_ra_msg0_t))) + { + return -1; + } + uint32_t extended_epid_group_id = p_msg0->extended_epid_group_id; + + // Check to see if we have registered with the attestation server yet? + if (!g_is_sp_registered || + (g_sp_extended_epid_group_id != NULL && g_sp_extended_epid_group_id->extended_epid_group_id != extended_epid_group_id)) + { + // Check to see if the extended_epid_group_id is supported? + ret = SP_UNSUPPORTED_EXTENDED_EPID_GROUP; + for (size_t i = 0; i < sizeof(g_extended_epid_groups) / sizeof(sample_extended_epid_group); i++) + { + if (g_extended_epid_groups[i].extended_epid_group_id == extended_epid_group_id) + { + g_sp_extended_epid_group_id = &(g_extended_epid_groups[i]); + // In the product, the SP will establish a mutually + // authenticated SSL channel. During the enrollment process, the ISV + // registers it exchanges TLS certs with attestation server and obtains an SPID and + // Report Key from the attestation server. + // For a product attestation server, enrollment is an offline process. See the 'on-boarding' + // documentation to get the information required. The enrollment process is + // simulated by a call in this sample. + ret = g_sp_extended_epid_group_id->enroll(g_sp_credentials, &g_spid, + &g_authentication_token); + if (0 != ret) + { + ret = SP_IAS_FAILED; + break; + } + + g_is_sp_registered = true; + ret = SP_OK; + break; + } + } + } + else + { + ret = SP_OK; + } + + return ret; +} + +// Verify message 1 then generate and return message 2 to isv. +int sp_ra_proc_msg1_req(const sample_ra_msg1_t *p_msg1, + uint32_t msg1_size, + ra_samp_response_header_t **pp_msg2) +{ + int ret = 0; + ra_samp_response_header_t* p_msg2_full = NULL; + sample_ra_msg2_t *p_msg2 = NULL; + sample_ecc_state_handle_t ecc_state = NULL; + sample_status_t sample_ret = SAMPLE_SUCCESS; + bool derive_ret = false; + + if(!p_msg1 || + !pp_msg2 || + (msg1_size != sizeof(sample_ra_msg1_t))) + { + return -1; + } + + // Check to see if we have registered? + if (!g_is_sp_registered) + { + return SP_UNSUPPORTED_EXTENDED_EPID_GROUP; + } + + do + { + // Get the sig_rl from attestation server using GID. + // GID is Base-16 encoded of EPID GID in little-endian format. + // In the product, the SP and attesation server uses an established channel for + // communication. + uint8_t* sig_rl; + uint32_t sig_rl_size = 0; + + // The product interface uses a REST based message to get the SigRL. + + ret = g_sp_extended_epid_group_id->get_sigrl(p_msg1->gid, &sig_rl_size, &sig_rl); + if(0 != ret) + { + fprintf(stderr, "\nError, ias_get_sigrl [%s].", __FUNCTION__); + ret = SP_IAS_FAILED; + break; + } + + // Need to save the client's public ECCDH key to local storage + if (memcpy_s(&g_sp_db.g_a, sizeof(g_sp_db.g_a), &p_msg1->g_a, + sizeof(p_msg1->g_a))) + { + fprintf(stderr, "\nError, cannot do memcpy in [%s].", __FUNCTION__); + ret = SP_INTERNAL_ERROR; + break; + } + + // Generate the Service providers ECCDH key pair. + sample_ret = sample_ecc256_open_context(&ecc_state); + if(SAMPLE_SUCCESS != sample_ret) + { + fprintf(stderr, "\nError, cannot get ECC context in [%s].", + __FUNCTION__); + ret = -1; + break; + } + sample_ec256_public_t pub_key = {{0},{0}}; + sample_ec256_private_t priv_key = {{0}}; + sample_ret = sample_ecc256_create_key_pair(&priv_key, &pub_key, + ecc_state); + if(SAMPLE_SUCCESS != sample_ret) + { + fprintf(stderr, "\nError, cannot generate key pair in [%s].", + __FUNCTION__); + ret = SP_INTERNAL_ERROR; + break; + } + + // Need to save the SP ECCDH key pair to local storage. + if(memcpy_s(&g_sp_db.b, sizeof(g_sp_db.b), &priv_key,sizeof(priv_key)) + || memcpy_s(&g_sp_db.g_b, sizeof(g_sp_db.g_b), + &pub_key,sizeof(pub_key))) + { + fprintf(stderr, "\nError, cannot do memcpy in [%s].", __FUNCTION__); + ret = SP_INTERNAL_ERROR; + break; + } + + // Generate the client/SP shared secret + sample_ec_dh_shared_t dh_key = {{0}}; + sample_ret = sample_ecc256_compute_shared_dhkey(&priv_key, + (sample_ec256_public_t *)&p_msg1->g_a, + (sample_ec256_dh_shared_t *)&dh_key, + ecc_state); + if(SAMPLE_SUCCESS != sample_ret) + { + fprintf(stderr, "\nError, compute share key fail in [%s].", + __FUNCTION__); + ret = SP_INTERNAL_ERROR; + break; + } + +#ifdef SUPPLIED_KEY_DERIVATION + + // smk is only needed for msg2 generation. + derive_ret = derive_key(&dh_key, SAMPLE_DERIVE_KEY_SMK_SK, + &g_sp_db.smk_key, &g_sp_db.sk_key); + if(derive_ret != true) + { + fprintf(stderr, "\nError, derive key fail in [%s].", __FUNCTION__); + ret = SP_INTERNAL_ERROR; + break; + } + + // The rest of the keys are the shared secrets for future communication. + derive_ret = derive_key(&dh_key, SAMPLE_DERIVE_KEY_MK_VK, + &g_sp_db.mk_key, &g_sp_db.vk_key); + if(derive_ret != true) + { + fprintf(stderr, "\nError, derive key fail in [%s].", __FUNCTION__); + ret = SP_INTERNAL_ERROR; + break; + } +#else + // smk is only needed for msg2 generation. + derive_ret = derive_key(&dh_key, SAMPLE_DERIVE_KEY_SMK, + &g_sp_db.smk_key); + if(derive_ret != true) + { + fprintf(stderr, "\nError, derive key fail in [%s].", __FUNCTION__); + ret = SP_INTERNAL_ERROR; + break; + } + + // The rest of the keys are the shared secrets for future communication. + derive_ret = derive_key(&dh_key, SAMPLE_DERIVE_KEY_MK, + &g_sp_db.mk_key); + if(derive_ret != true) + { + fprintf(stderr, "\nError, derive key fail in [%s].", __FUNCTION__); + ret = SP_INTERNAL_ERROR; + break; + } + + derive_ret = derive_key(&dh_key, SAMPLE_DERIVE_KEY_SK, + &g_sp_db.sk_key); + if(derive_ret != true) + { + fprintf(stderr, "\nError, derive key fail in [%s].", __FUNCTION__); + ret = SP_INTERNAL_ERROR; + break; + } + + derive_ret = derive_key(&dh_key, SAMPLE_DERIVE_KEY_VK, + &g_sp_db.vk_key); + if(derive_ret != true) + { + fprintf(stderr, "\nError, derive key fail in [%s].", __FUNCTION__); + ret = SP_INTERNAL_ERROR; + break; + } +#endif + + uint32_t msg2_size = sizeof(sample_ra_msg2_t) + sig_rl_size; + p_msg2_full = (ra_samp_response_header_t*)malloc(msg2_size + + sizeof(ra_samp_response_header_t)); + if(!p_msg2_full) + { + fprintf(stderr, "\nError, out of memory in [%s].", __FUNCTION__); + ret = SP_INTERNAL_ERROR; + break; + } + memset(p_msg2_full, 0, msg2_size + sizeof(ra_samp_response_header_t)); + p_msg2_full->type = TYPE_RA_MSG2; + p_msg2_full->size = msg2_size; + // The simulated message2 always passes. This would need to be set + // accordingly in a real service provider implementation. + p_msg2_full->status[0] = 0; + p_msg2_full->status[1] = 0; + p_msg2 = (sample_ra_msg2_t *)p_msg2_full->body; + + // Assemble MSG2 + if(memcpy_s(&p_msg2->g_b, sizeof(p_msg2->g_b), &g_sp_db.g_b, + sizeof(g_sp_db.g_b)) || + memcpy_s(&p_msg2->spid, sizeof(sample_spid_t), + &g_spid, sizeof(g_spid))) + { + fprintf(stderr,"\nError, memcpy failed in [%s].", __FUNCTION__); + ret = SP_INTERNAL_ERROR; + break; + } + + // The service provider is responsible for selecting the proper EPID + // signature type and to understand the implications of the choice! + p_msg2->quote_type = SAMPLE_QUOTE_LINKABLE_SIGNATURE; + +#ifdef SUPPLIED_KEY_DERIVATION +//isv defined key derivation function id +#define ISV_KDF_ID 2 + p_msg2->kdf_id = ISV_KDF_ID; +#else + p_msg2->kdf_id = SAMPLE_AES_CMAC_KDF_ID; +#endif + // Create gb_ga + sample_ec_pub_t gb_ga[2]; + if(memcpy_s(&gb_ga[0], sizeof(gb_ga[0]), &g_sp_db.g_b, + sizeof(g_sp_db.g_b)) + || memcpy_s(&gb_ga[1], sizeof(gb_ga[1]), &g_sp_db.g_a, + sizeof(g_sp_db.g_a))) + { + fprintf(stderr,"\nError, memcpy failed in [%s].", __FUNCTION__); + ret = SP_INTERNAL_ERROR; + break; + } + + // Sign gb_ga + sample_ret = sample_ecdsa_sign((uint8_t *)&gb_ga, sizeof(gb_ga), + (sample_ec256_private_t *)&g_sp_priv_key, + (sample_ec256_signature_t *)&p_msg2->sign_gb_ga, + ecc_state); + if(SAMPLE_SUCCESS != sample_ret) + { + fprintf(stderr, "\nError, sign ga_gb fail in [%s].", __FUNCTION__); + ret = SP_INTERNAL_ERROR; + break; + } + + // Generate the CMACsmk for gb||SPID||TYPE||KDF_ID||Sigsp(gb,ga) + uint8_t mac[SAMPLE_EC_MAC_SIZE] = {0}; + uint32_t cmac_size = offsetof(sample_ra_msg2_t, mac); + sample_ret = sample_rijndael128_cmac_msg(&g_sp_db.smk_key, + (uint8_t *)&p_msg2->g_b, cmac_size, &mac); + if(SAMPLE_SUCCESS != sample_ret) + { + fprintf(stderr, "\nError, cmac fail in [%s].", __FUNCTION__); + ret = SP_INTERNAL_ERROR; + break; + } + if(memcpy_s(&p_msg2->mac, sizeof(p_msg2->mac), mac, sizeof(mac))) + { + fprintf(stderr,"\nError, memcpy failed in [%s].", __FUNCTION__); + ret = SP_INTERNAL_ERROR; + break; + } + + if(memcpy_s(&p_msg2->sig_rl[0], sig_rl_size, sig_rl, sig_rl_size)) + { + fprintf(stderr,"\nError, memcpy failed in [%s].", __FUNCTION__); + ret = SP_INTERNAL_ERROR; + break; + } + p_msg2->sig_rl_size = sig_rl_size; + + }while(0); + + if(ret) + { + *pp_msg2 = NULL; + SAFE_FREE(p_msg2_full); + } + else + { + // Freed by the network simulator in ra_free_network_response_buffer + *pp_msg2 = p_msg2_full; + } + + if(ecc_state) + { + sample_ecc256_close_context(ecc_state); + } + + return ret; +} + +// Process remote attestation message 3 +int sp_ra_proc_msg3_req(const sample_ra_msg3_t *p_msg3, + uint32_t msg3_size, + ra_samp_response_header_t **pp_att_result_msg) +{ + int ret = 0; + sample_status_t sample_ret = SAMPLE_SUCCESS; + const uint8_t *p_msg3_cmaced = NULL; + sample_quote_t *p_quote = NULL; + sample_sha_state_handle_t sha_handle = NULL; + sample_report_data_t report_data = {0}; + sample_ra_att_result_msg_t *p_att_result_msg = NULL; + ra_samp_response_header_t* p_att_result_msg_full = NULL; + uint32_t i; + + if((!p_msg3) || + (msg3_size < sizeof(sample_ra_msg3_t)) || + (!pp_att_result_msg)) + { + return SP_INTERNAL_ERROR; + } + + // Check to see if we have registered? + if (!g_is_sp_registered) + { + return SP_UNSUPPORTED_EXTENDED_EPID_GROUP; + } + do + { + // Compare g_a in message 3 with local g_a. + ret = memcmp(&g_sp_db.g_a, &p_msg3->g_a, sizeof(sample_ec_pub_t)); + if(ret) + { + fprintf(stderr, "\nError, g_a is not same [%s].", __FUNCTION__); + ret = SP_PROTOCOL_ERROR; + break; + } + //Make sure that msg3_size is bigger than sample_mac_t. + uint32_t mac_size = msg3_size - sizeof(sample_mac_t); + p_msg3_cmaced = reinterpret_cast(p_msg3); + p_msg3_cmaced += sizeof(sample_mac_t); + + // Verify the message mac using SMK + sample_cmac_128bit_tag_t mac = {0}; + sample_ret = sample_rijndael128_cmac_msg(&g_sp_db.smk_key, + p_msg3_cmaced, + mac_size, + &mac); + if(SAMPLE_SUCCESS != sample_ret) + { + fprintf(stderr, "\nError, cmac fail in [%s].", __FUNCTION__); + ret = SP_INTERNAL_ERROR; + break; + } + // In real implementation, should use a time safe version of memcmp here, + // in order to avoid side channel attack. + ret = memcmp(&p_msg3->mac, mac, sizeof(mac)); + if(ret) + { + fprintf(stderr, "\nError, verify cmac fail [%s].", __FUNCTION__); + ret = SP_INTEGRITY_FAILED; + break; + } + + if(memcpy_s(&g_sp_db.ps_sec_prop, sizeof(g_sp_db.ps_sec_prop), + &p_msg3->ps_sec_prop, sizeof(p_msg3->ps_sec_prop))) + { + fprintf(stderr,"\nError, memcpy failed in [%s].", __FUNCTION__); + ret = SP_INTERNAL_ERROR; + break; + } + + p_quote = (sample_quote_t *)p_msg3->quote; + + // Check the quote version if needed. Only check the Quote.version field if the enclave + // identity fields have changed or the size of the quote has changed. The version may + // change without affecting the legacy fields or size of the quote structure. + //if(p_quote->version < ACCEPTED_QUOTE_VERSION) + //{ + // fprintf(stderr,"\nError, quote version is too old.", __FUNCTION__); + // ret = SP_QUOTE_VERSION_ERROR; + // break; + //} + + // Verify the report_data in the Quote matches the expected value. + // The first 32 bytes of report_data are SHA256 HASH of {ga|gb|vk}. + // The second 32 bytes of report_data are set to zero. + sample_ret = sample_sha256_init(&sha_handle); + if(sample_ret != SAMPLE_SUCCESS) + { + fprintf(stderr,"\nError, init hash failed in [%s].", __FUNCTION__); + ret = SP_INTERNAL_ERROR; + break; + } + sample_ret = sample_sha256_update((uint8_t *)&(g_sp_db.g_a), + sizeof(g_sp_db.g_a), sha_handle); + if(sample_ret != SAMPLE_SUCCESS) + { + fprintf(stderr,"\nError, udpate hash failed in [%s].", + __FUNCTION__); + ret = SP_INTERNAL_ERROR; + break; + } + sample_ret = sample_sha256_update((uint8_t *)&(g_sp_db.g_b), + sizeof(g_sp_db.g_b), sha_handle); + if(sample_ret != SAMPLE_SUCCESS) + { + fprintf(stderr,"\nError, udpate hash failed in [%s].", + __FUNCTION__); + ret = SP_INTERNAL_ERROR; + break; + } + sample_ret = sample_sha256_update((uint8_t *)&(g_sp_db.vk_key), + sizeof(g_sp_db.vk_key), sha_handle); + if(sample_ret != SAMPLE_SUCCESS) + { + fprintf(stderr,"\nError, udpate hash failed in [%s].", + __FUNCTION__); + ret = SP_INTERNAL_ERROR; + break; + } + sample_ret = sample_sha256_get_hash(sha_handle, + (sample_sha256_hash_t *)&report_data); + if(sample_ret != SAMPLE_SUCCESS) + { + fprintf(stderr,"\nError, Get hash failed in [%s].", __FUNCTION__); + ret = SP_INTERNAL_ERROR; + break; + } + ret = memcmp((uint8_t *)&report_data, + (uint8_t *)&(p_quote->report_body.report_data), + sizeof(report_data)); + if(ret) + { + fprintf(stderr, "\nError, verify hash fail [%s].", __FUNCTION__); + ret = SP_INTEGRITY_FAILED; + break; + } + + // Verify Enclave policy (an attestation server may provide an API for this if we + // registered an Enclave policy) + + // Verify quote with attestation server. + // In the product, an attestation server could use a REST message and JSON formatting to request + // attestation Quote verification. The sample only simulates this interface. + ias_att_report_t attestation_report = {0}; + ret = g_sp_extended_epid_group_id->verify_attestation_evidence(p_quote, NULL, + &attestation_report); + if(0 != ret) + { + ret = SP_IAS_FAILED; + break; + } + FILE* OUTPUT = stdout; + fprintf(OUTPUT, "\n\n\tAtestation Report:"); + fprintf(OUTPUT, "\n\tid: 0x%0x.", attestation_report.id); + fprintf(OUTPUT, "\n\tstatus: %d.", attestation_report.status); + fprintf(OUTPUT, "\n\trevocation_reason: %u.", + attestation_report.revocation_reason); + // attestation_report.info_blob; + fprintf(OUTPUT, "\n\tpse_status: %d.", attestation_report.pse_status); + // Note: This sample always assumes the PIB is sent by attestation server. In the product + // implementation, the attestation server could only send the PIB for certain attestation + // report statuses. A product SP implementation needs to handle cases + // where the PIB is zero length. + + // Respond the client with the results of the attestation. + uint32_t att_result_msg_size = sizeof(sample_ra_att_result_msg_t); + p_att_result_msg_full = + (ra_samp_response_header_t*)malloc(att_result_msg_size + + sizeof(ra_samp_response_header_t) + sizeof(g_secret)); + if(!p_att_result_msg_full) + { + fprintf(stderr, "\nError, out of memory in [%s].", __FUNCTION__); + ret = SP_INTERNAL_ERROR; + break; + } + memset(p_att_result_msg_full, 0, att_result_msg_size + + sizeof(ra_samp_response_header_t) + sizeof(g_secret)); + p_att_result_msg_full->type = TYPE_RA_ATT_RESULT; + p_att_result_msg_full->size = att_result_msg_size; + if(IAS_QUOTE_OK != attestation_report.status) + { + p_att_result_msg_full->status[0] = 0xFF; + } + if(IAS_PSE_OK != attestation_report.pse_status) + { + p_att_result_msg_full->status[1] = 0xFF; + } + + p_att_result_msg = + (sample_ra_att_result_msg_t *)p_att_result_msg_full->body; + + // In a product implementation of attestation server, the HTTP response header itself could have + // an RK based signature that the service provider needs to check here. + + // The platform_info_blob signature will be verified by the client + // when sent. No need to have the Service Provider to check it. The SP + // should pass it down to the application for further analysis. + + fprintf(OUTPUT, "\n\n\tEnclave Report:"); + fprintf(OUTPUT, "\n\tSignature Type: 0x%x", p_quote->sign_type); + fprintf(OUTPUT, "\n\tSignature Basename: "); + for(i=0; ibasename.name) && p_quote->basename.name[i]; + i++) + { + fprintf(OUTPUT, "%c", p_quote->basename.name[i]); + } +#ifdef __x86_64__ + fprintf(OUTPUT, "\n\tattributes.flags: 0x%0lx", + p_quote->report_body.attributes.flags); + fprintf(OUTPUT, "\n\tattributes.xfrm: 0x%0lx", + p_quote->report_body.attributes.xfrm); +#else + fprintf(OUTPUT, "\n\tattributes.flags: 0x%0llx", + p_quote->report_body.attributes.flags); + fprintf(OUTPUT, "\n\tattributes.xfrm: 0x%0llx", + p_quote->report_body.attributes.xfrm); +#endif + fprintf(OUTPUT, "\n\tmr_enclave: "); + for(i=0;ireport_body.mr_enclave[i]); + + //fprintf(stderr, "%02x",p_quote->report_body.mr_enclave.m[i]); + + } + fprintf(OUTPUT, "\n\tmr_signer: "); + for(i=0;ireport_body.mr_signer[i]); + + //fprintf(stderr, "%02x",p_quote->report_body.mr_signer.m[i]); + + } + fprintf(OUTPUT, "\n\tisv_prod_id: 0x%0x", + p_quote->report_body.isv_prod_id); + fprintf(OUTPUT, "\n\tisv_svn: 0x%0x",p_quote->report_body.isv_svn); + fprintf(OUTPUT, "\n"); + + // A product service provider needs to verify that its enclave properties + // match what is expected. The SP needs to check these values before + // trusting the enclave. For the sample, we always pass the policy check. + // Attestation server only verifies the quote structure and signature. It does not + // check the identity of the enclave. + bool isv_policy_passed = true; + + // Assemble Attestation Result Message + // Note, this is a structure copy. We don't copy the policy reports + // right now. + p_att_result_msg->platform_info_blob = attestation_report.info_blob; + + // Generate mac based on the mk key. + mac_size = sizeof(ias_platform_info_blob_t); + sample_ret = sample_rijndael128_cmac_msg(&g_sp_db.mk_key, + (const uint8_t*)&p_att_result_msg->platform_info_blob, + mac_size, + &p_att_result_msg->mac); + if(SAMPLE_SUCCESS != sample_ret) + { + fprintf(stderr, "\nError, cmac fail in [%s].", __FUNCTION__); + ret = SP_INTERNAL_ERROR; + break; + } + + // Generate shared secret and encrypt it with SK, if attestation passed. + uint8_t aes_gcm_iv[SAMPLE_SP_IV_SIZE] = {0}; + p_att_result_msg->secret.payload_size = 8; + if((IAS_QUOTE_OK == attestation_report.status) && + (IAS_PSE_OK == attestation_report.pse_status) && + (isv_policy_passed == true)) + { + ret = sample_rijndael128GCM_encrypt(&g_sp_db.sk_key, + &g_secret[0], + p_att_result_msg->secret.payload_size, + p_att_result_msg->secret.payload, + &aes_gcm_iv[0], + SAMPLE_SP_IV_SIZE, + NULL, + 0, + &p_att_result_msg->secret.payload_tag); + } + }while(0); + + if(ret) + { + *pp_att_result_msg = NULL; + SAFE_FREE(p_att_result_msg_full); + } + else + { + // Freed by the network simulator in ra_free_network_response_buffer + *pp_att_result_msg = p_att_result_msg_full; + } + return ret; +} + + + + diff --git a/sgx-jvm/linux-sgx/SampleCode/RemoteAttestation/service_provider/service_provider.h b/sgx-jvm/linux-sgx/SampleCode/RemoteAttestation/service_provider/service_provider.h new file mode 100644 index 0000000000..83a7522e07 --- /dev/null +++ b/sgx-jvm/linux-sgx/SampleCode/RemoteAttestation/service_provider/service_provider.h @@ -0,0 +1,161 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + + + +#ifndef _SERVICE_PROVIDER_H +#define _SERVICE_PROVIDER_H + +#include "remote_attestation_result.h" +#include "ias_ra.h" +#include "network_ra.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + SP_OK, + SP_UNSUPPORTED_EXTENDED_EPID_GROUP, + SP_INTEGRITY_FAILED, + SP_QUOTE_VERIFICATION_FAILED, + SP_IAS_FAILED, + SP_INTERNAL_ERROR, + SP_PROTOCOL_ERROR, + SP_QUOTE_VERSION_ERROR, +} sp_ra_msg_status_t; + +#pragma pack(push,1) + +#define SAMPLE_SP_TAG_SIZE 16 +#define SAMPLE_SP_IV_SIZE 12 + +typedef struct sample_ec_pub_t +{ + uint8_t gx[SAMPLE_ECP_KEY_SIZE]; + uint8_t gy[SAMPLE_ECP_KEY_SIZE]; +} sample_ec_pub_t; + +/*fixed length to align with internal structure*/ +typedef struct sample_ps_sec_prop_desc_t +{ + uint8_t sample_ps_sec_prop_desc[256]; +} sample_ps_sec_prop_desc_t; + +#pragma pack(pop) + +typedef uint32_t sample_ra_context_t; + +typedef uint8_t sample_key_128bit_t[16]; + +typedef sample_key_128bit_t sample_ra_key_128_t; + +typedef struct sample_ra_msg0_t +{ + uint32_t extended_epid_group_id; +} sample_ra_msg0_t; + + +typedef struct sample_ra_msg1_t +{ + sample_ec_pub_t g_a; /* the Endian-ness of Ga is + Little-Endian*/ + sample_epid_group_id_t gid; /* the Endian-ness of GID is + Little-Endian*/ +} sample_ra_msg1_t; + +/*Key Derivation Function ID : 0x0001 AES-CMAC Entropy Extraction and Key Expansion*/ +const uint16_t SAMPLE_AES_CMAC_KDF_ID = 0x0001; + +typedef struct sample_ra_msg2_t +{ + sample_ec_pub_t g_b; /* the Endian-ness of Gb is + Little-Endian*/ + sample_spid_t spid; /* In little endian*/ + uint16_t quote_type; /* unlinkable Quote(0) or linkable Quote(0) in little endian*/ + uint16_t kdf_id; /* key derivation function id in little endian. + 0x0001 for AES-CMAC Entropy Extraction and Key Derivation */ + sample_ec_sign256_t sign_gb_ga; /* In little endian*/ + sample_mac_t mac; /* mac_smk(g_b||spid||quote_type|| + sign_gb_ga)*/ + uint32_t sig_rl_size; + uint8_t sig_rl[]; +} sample_ra_msg2_t; + +typedef struct sample_ra_msg3_t +{ + sample_mac_t mac; /* mac_smk(g_a||ps_sec_prop||quote)*/ + sample_ec_pub_t g_a; /* the Endian-ness of Ga is*/ + /* Little-Endian*/ + sample_ps_sec_prop_desc_t ps_sec_prop; + uint8_t quote[]; +} sample_ra_msg3_t; + +int sp_ra_proc_msg0_req(const sample_ra_msg0_t *p_msg0, + uint32_t msg0_size); + +int sp_ra_proc_msg1_req(const sample_ra_msg1_t *p_msg1, + uint32_t msg1_size, + ra_samp_response_header_t **pp_msg2); + +int sp_ra_proc_msg3_req(const sample_ra_msg3_t *p_msg3, + uint32_t msg3_size, + ra_samp_response_header_t **pp_att_result_msg); + +int sp_ra_free_msg2( + sample_ra_msg2_t *p_msg2); + + + +typedef int (*sample_enroll)(int sp_credentials, sample_spid_t* spid, + int* authentication_token); + +typedef int(*sample_get_sigrl)(const sample_epid_group_id_t gid, uint32_t* p_sig_rl_size, + uint8_t** p_sig_rl); + +typedef int(*sample_verify_attestation_evidence)(sample_quote_t* p_isv_quote, + uint8_t* pse_manifest, + ias_att_report_t* attestation_verification_report); + + +typedef struct sample_extended_epid_group +{ + uint32_t extended_epid_group_id; + sample_enroll enroll; + sample_get_sigrl get_sigrl; + sample_verify_attestation_evidence verify_attestation_evidence; +} sample_extended_epid_group; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/sgx-jvm/linux-sgx/SampleCode/SampleEnclave/.cproject b/sgx-jvm/linux-sgx/SampleCode/SampleEnclave/.cproject new file mode 100644 index 0000000000..e685836b4d --- /dev/null +++ b/sgx-jvm/linux-sgx/SampleCode/SampleEnclave/.cproject @@ -0,0 +1,219 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sgx-jvm/linux-sgx/SampleCode/SampleEnclave/.project b/sgx-jvm/linux-sgx/SampleCode/SampleEnclave/.project new file mode 100644 index 0000000000..102c105873 --- /dev/null +++ b/sgx-jvm/linux-sgx/SampleCode/SampleEnclave/.project @@ -0,0 +1,28 @@ + + + SampleEnclave + + + + + + org.eclipse.cdt.managedbuilder.core.genmakebuilder + clean,full,incremental, + + + + + org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder + full,incremental, + + + + + + org.eclipse.cdt.core.cnature + org.eclipse.cdt.managedbuilder.core.managedBuildNature + org.eclipse.cdt.managedbuilder.core.ScannerConfigNature + org.eclipse.cdt.core.ccnature + com.intel.sgx.sgxnature + + diff --git a/sgx-jvm/linux-sgx/SampleCode/SampleEnclave/App/App.cpp b/sgx-jvm/linux-sgx/SampleCode/SampleEnclave/App/App.cpp new file mode 100644 index 0000000000..0538d2d8f3 --- /dev/null +++ b/sgx-jvm/linux-sgx/SampleCode/SampleEnclave/App/App.cpp @@ -0,0 +1,265 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + + +#include +#include +#include + +# include +# include +# define MAX_PATH FILENAME_MAX + +#include "sgx_urts.h" +#include "App.h" +#include "Enclave_u.h" + +/* Global EID shared by multiple threads */ +sgx_enclave_id_t global_eid = 0; + +typedef struct _sgx_errlist_t { + sgx_status_t err; + const char *msg; + const char *sug; /* Suggestion */ +} sgx_errlist_t; + +/* Error code returned by sgx_create_enclave */ +static sgx_errlist_t sgx_errlist[] = { + { + SGX_ERROR_UNEXPECTED, + "Unexpected error occurred.", + NULL + }, + { + SGX_ERROR_INVALID_PARAMETER, + "Invalid parameter.", + NULL + }, + { + SGX_ERROR_OUT_OF_MEMORY, + "Out of memory.", + NULL + }, + { + SGX_ERROR_ENCLAVE_LOST, + "Power transition occurred.", + "Please refer to the sample \"PowerTransition\" for details." + }, + { + SGX_ERROR_INVALID_ENCLAVE, + "Invalid enclave image.", + NULL + }, + { + SGX_ERROR_INVALID_ENCLAVE_ID, + "Invalid enclave identification.", + NULL + }, + { + SGX_ERROR_INVALID_SIGNATURE, + "Invalid enclave signature.", + NULL + }, + { + SGX_ERROR_OUT_OF_EPC, + "Out of EPC memory.", + NULL + }, + { + SGX_ERROR_NO_DEVICE, + "Invalid SGX device.", + "Please make sure SGX module is enabled in the BIOS, and install SGX driver afterwards." + }, + { + SGX_ERROR_MEMORY_MAP_CONFLICT, + "Memory map conflicted.", + NULL + }, + { + SGX_ERROR_INVALID_METADATA, + "Invalid enclave metadata.", + NULL + }, + { + SGX_ERROR_DEVICE_BUSY, + "SGX device was busy.", + NULL + }, + { + SGX_ERROR_INVALID_VERSION, + "Enclave version was invalid.", + NULL + }, + { + SGX_ERROR_INVALID_ATTRIBUTE, + "Enclave was not authorized.", + NULL + }, + { + SGX_ERROR_ENCLAVE_FILE_ACCESS, + "Can't open enclave file.", + NULL + }, +}; + +/* Check error conditions for loading enclave */ +void print_error_message(sgx_status_t ret) +{ + size_t idx = 0; + size_t ttl = sizeof sgx_errlist/sizeof sgx_errlist[0]; + + for (idx = 0; idx < ttl; idx++) { + if(ret == sgx_errlist[idx].err) { + if(NULL != sgx_errlist[idx].sug) + printf("Info: %s\n", sgx_errlist[idx].sug); + printf("Error: %s\n", sgx_errlist[idx].msg); + break; + } + } + + if (idx == ttl) + printf("Error: Unexpected error occurred.\n"); +} + +/* Initialize the enclave: + * Step 1: try to retrieve the launch token saved by last transaction + * Step 2: call sgx_create_enclave to initialize an enclave instance + * Step 3: save the launch token if it is updated + */ +int initialize_enclave(void) +{ + char token_path[MAX_PATH] = {'\0'}; + sgx_launch_token_t token = {0}; + sgx_status_t ret = SGX_ERROR_UNEXPECTED; + int updated = 0; + + /* Step 1: try to retrieve the launch token saved by last transaction + * if there is no token, then create a new one. + */ + /* try to get the token saved in $HOME */ + const char *home_dir = getpwuid(getuid())->pw_dir; + + if (home_dir != NULL && + (strlen(home_dir)+strlen("/")+sizeof(TOKEN_FILENAME)+1) <= MAX_PATH) { + /* compose the token path */ + strncpy(token_path, home_dir, strlen(home_dir)); + strncat(token_path, "/", strlen("/")); + strncat(token_path, TOKEN_FILENAME, sizeof(TOKEN_FILENAME)+1); + } else { + /* if token path is too long or $HOME is NULL */ + strncpy(token_path, TOKEN_FILENAME, sizeof(TOKEN_FILENAME)); + } + + FILE *fp = fopen(token_path, "rb"); + if (fp == NULL && (fp = fopen(token_path, "wb")) == NULL) { + printf("Warning: Failed to create/open the launch token file \"%s\".\n", token_path); + } + + if (fp != NULL) { + /* read the token from saved file */ + size_t read_num = fread(token, 1, sizeof(sgx_launch_token_t), fp); + if (read_num != 0 && read_num != sizeof(sgx_launch_token_t)) { + /* if token is invalid, clear the buffer */ + memset(&token, 0x0, sizeof(sgx_launch_token_t)); + printf("Warning: Invalid launch token read from \"%s\".\n", token_path); + } + } + /* Step 2: call sgx_create_enclave to initialize an enclave instance */ + /* Debug Support: set 2nd parameter to 1 */ + ret = sgx_create_enclave(ENCLAVE_FILENAME, SGX_DEBUG_FLAG, &token, &updated, &global_eid, NULL); + if (ret != SGX_SUCCESS) { + print_error_message(ret); + if (fp != NULL) fclose(fp); + return -1; + } + + /* Step 3: save the launch token if it is updated */ + if (updated == FALSE || fp == NULL) { + /* if the token is not updated, or file handler is invalid, do not perform saving */ + if (fp != NULL) fclose(fp); + return 0; + } + + /* reopen the file with write capablity */ + fp = freopen(token_path, "wb", fp); + if (fp == NULL) return 0; + size_t write_num = fwrite(token, 1, sizeof(sgx_launch_token_t), fp); + if (write_num != sizeof(sgx_launch_token_t)) + printf("Warning: Failed to save launch token to \"%s\".\n", token_path); + fclose(fp); + return 0; +} + +/* OCall functions */ +void ocall_print_string(const char *str) +{ + /* Proxy/Bridge will check the length and null-terminate + * the input string to prevent buffer overflow. + */ + printf("%s", str); +} + + +/* Application entry */ +int SGX_CDECL main(int argc, char *argv[]) +{ + (void)(argc); + (void)(argv); + + + /* Initialize the enclave */ + if(initialize_enclave() < 0){ + printf("Enter a character before exit ...\n"); + getchar(); + return -1; + } + + /* Utilize edger8r attributes */ + edger8r_array_attributes(); + edger8r_pointer_attributes(); + edger8r_type_attributes(); + edger8r_function_attributes(); + + /* Utilize trusted libraries */ + ecall_libc_functions(); + ecall_libcxx_functions(); + ecall_thread_functions(); + + /* Destroy the enclave */ + sgx_destroy_enclave(global_eid); + + printf("Info: SampleEnclave successfully returned.\n"); + + printf("Enter a character before exit ...\n"); + getchar(); + return 0; +} + diff --git a/sgx-jvm/linux-sgx/SampleCode/SampleEnclave/App/App.h b/sgx-jvm/linux-sgx/SampleCode/SampleEnclave/App/App.h new file mode 100644 index 0000000000..bc86ff850f --- /dev/null +++ b/sgx-jvm/linux-sgx/SampleCode/SampleEnclave/App/App.h @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + + +#ifndef _APP_H_ +#define _APP_H_ + +#include +#include +#include +#include + +#include "sgx_error.h" /* sgx_status_t */ +#include "sgx_eid.h" /* sgx_enclave_id_t */ + +#ifndef TRUE +# define TRUE 1 +#endif + +#ifndef FALSE +# define FALSE 0 +#endif + +# define TOKEN_FILENAME "enclave.token" +# define ENCLAVE_FILENAME "enclave.signed.so" + +extern sgx_enclave_id_t global_eid; /* global enclave id */ + +#if defined(__cplusplus) +extern "C" { +#endif + +void edger8r_array_attributes(void); +void edger8r_type_attributes(void); +void edger8r_pointer_attributes(void); +void edger8r_function_attributes(void); + +void ecall_libc_functions(void); +void ecall_libcxx_functions(void); +void ecall_thread_functions(void); + +#if defined(__cplusplus) +} +#endif + +#endif /* !_APP_H_ */ diff --git a/sgx-jvm/linux-sgx/SampleCode/SampleEnclave/App/Edger8rSyntax/Arrays.cpp b/sgx-jvm/linux-sgx/SampleCode/SampleEnclave/App/Edger8rSyntax/Arrays.cpp new file mode 100644 index 0000000000..01552eeffb --- /dev/null +++ b/sgx-jvm/linux-sgx/SampleCode/SampleEnclave/App/Edger8rSyntax/Arrays.cpp @@ -0,0 +1,92 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + + +#include "../App.h" +#include "Enclave_u.h" + +/* edger8r_array_attributes: + * Invokes ECALLs declared with array attributes. + */ +void edger8r_array_attributes(void) +{ + sgx_status_t ret = SGX_ERROR_UNEXPECTED; + + /* user_check */ + int arr1[4] = {0, 1, 2, 3}; + ret = ecall_array_user_check(global_eid, arr1); + if (ret != SGX_SUCCESS) + abort(); + + /* make sure arr1 is changed */ + for (int i = 0; i < 4; i++) + assert(arr1[i] == (3 - i)); + + /* in */ + int arr2[4] = {0, 1, 2, 3}; + ret = ecall_array_in(global_eid, arr2); + if (ret != SGX_SUCCESS) + abort(); + + /* arr2 is not changed */ + for (int i = 0; i < 4; i++) + assert(arr2[i] == i); + + /* out */ + int arr3[4] = {0, 1, 2, 3}; + ret = ecall_array_out(global_eid, arr3); + if (ret != SGX_SUCCESS) + abort(); + + /* arr3 is changed */ + for (int i = 0; i < 4; i++) + assert(arr3[i] == (3 - i)); + + /* in, out */ + int arr4[4] = {0, 1, 2, 3}; + ret = ecall_array_in_out(global_eid, arr4); + if (ret != SGX_SUCCESS) + abort(); + + /* arr4 is changed */ + for (int i = 0; i < 4; i++) + assert(arr4[i] == (3 - i)); + + /* isary */ + array_t arr5 = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + ret = ecall_array_isary(global_eid, arr5); + if (ret != SGX_SUCCESS) + abort(); + + /* arr5 is changed */ + for (int i = 0; i < 10; i++) + assert(arr5[i] == (9 - i)); +} diff --git a/sgx-jvm/linux-sgx/SampleCode/SampleEnclave/App/Edger8rSyntax/Functions.cpp b/sgx-jvm/linux-sgx/SampleCode/SampleEnclave/App/Edger8rSyntax/Functions.cpp new file mode 100644 index 0000000000..acc2ad2737 --- /dev/null +++ b/sgx-jvm/linux-sgx/SampleCode/SampleEnclave/App/Edger8rSyntax/Functions.cpp @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + + +#include "../App.h" +#include "Enclave_u.h" + +/* No need to implement memccpy here! */ + +/* edger8r_function_attributes: + * Invokes ECALL declared with calling convention attributes. + * Invokes ECALL declared with [public]. + */ +void edger8r_function_attributes(void) +{ + sgx_status_t ret = SGX_ERROR_UNEXPECTED; + + ret = ecall_function_calling_convs(global_eid); + if (ret != SGX_SUCCESS) + abort(); + + ret = ecall_function_public(global_eid); + if (ret != SGX_SUCCESS) + abort(); + + /* user shall not invoke private function here */ + int runned = 0; + ret = ecall_function_private(global_eid, &runned); + if (ret != SGX_ERROR_ECALL_NOT_ALLOWED || runned != 0) + abort(); +} + +/* ocall_function_allow: + * The OCALL invokes the [allow]ed ECALL 'edger8r_private'. + */ +void ocall_function_allow(void) +{ + int runned = 0; + sgx_status_t ret = SGX_ERROR_UNEXPECTED; + + ret = ecall_function_private(global_eid, &runned); + if (ret != SGX_SUCCESS || runned != 1) + abort(); +} diff --git a/sgx-jvm/linux-sgx/SampleCode/SampleEnclave/App/Edger8rSyntax/Pointers.cpp b/sgx-jvm/linux-sgx/SampleCode/SampleEnclave/App/Edger8rSyntax/Pointers.cpp new file mode 100644 index 0000000000..2187a40dde --- /dev/null +++ b/sgx-jvm/linux-sgx/SampleCode/SampleEnclave/App/Edger8rSyntax/Pointers.cpp @@ -0,0 +1,149 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + + +#include "../App.h" +#include "Enclave_u.h" + +/* edger8r_pointer_attributes: + * Invokes the ECALLs declared with pointer attributes. + */ +void edger8r_pointer_attributes(void) +{ + int val = 0; + sgx_status_t ret = SGX_ERROR_UNEXPECTED; + + char c[128] = {0}; + size_t len = 0; + memset(c, 0xe, 128); + ret = ecall_pointer_user_check(global_eid, &len, &c, 128); + if (ret != SGX_SUCCESS) + abort(); + assert(strcmp(c, "SGX_SUCCESS") == 0); + + + val = 0; + ret = ecall_pointer_in(global_eid, &val); + if (ret != SGX_SUCCESS) + abort(); + assert(val == 0); + + val = 0; + ret = ecall_pointer_out(global_eid, &val); + if (ret != SGX_SUCCESS) + abort(); + assert(val == 1234); + + val = 0; + ret = ecall_pointer_in_out(global_eid, &val); + if (ret != SGX_SUCCESS) + abort(); + assert(val == 1234); + + ret = ocall_pointer_attr(global_eid); + if (ret != SGX_SUCCESS) + abort(); + + char str1[] = "1234567890"; + ret = ecall_pointer_string(global_eid, str1); + if (ret != SGX_SUCCESS) + abort(); + assert(memcmp(str1, "0987654321", strlen(str1)) == 0); + + const char str2[] = "1234567890"; + ret = ecall_pointer_string_const(global_eid, str2); + if (ret != SGX_SUCCESS) + abort(); + assert(memcmp(str2, "1234567890", strlen(str2)) == 0); + + char str3[] = "1234567890"; + ret = ecall_pointer_size(global_eid, (void*)str3, strlen(str3)); + if (ret != SGX_SUCCESS) + abort(); + assert(memcmp(str3, "0987654321", strlen(str3)) == 0); + + char str4[] = "1234567890"; + ret = ecall_pointer_isptr_readonly(global_eid, (buffer_t)str4, strlen(str4)); + if (ret != SGX_SUCCESS) + abort(); + assert(memcmp(str4, "1234567890", strlen(str4)) == 0); + + int arr[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + ret = ecall_pointer_count(global_eid, arr, 10); + if (ret != SGX_SUCCESS) + abort(); + + for (int i = 0; i < 10; i++) + assert(arr[i] == (9 - i)); + + memset(arr, 0x0, sizeof(arr)); + ret = ecall_pointer_sizefunc(global_eid, (char *)arr); + if (ret != SGX_SUCCESS) + abort(); + + for (int i = 0; i < 10; i++) + assert(arr[i] == i); + + return; +} + +/* ocall_pointer_user_check: + * The OCALL declared with [user_check]. + */ +void ocall_pointer_user_check(int* val) +{ + (void)val; + assert(val != NULL); +} + +/* ocall_pointer_in: + * The OCALL declared with [in]. + */ +void ocall_pointer_in(int* val) +{ + *val = 1234; +} + +/* ocall_pointer_out: + * The OCALL declared with [out]. + */ +void ocall_pointer_out(int* val) +{ + *val = 1234; +} + +/* ocall_pointer_in_out: + * The OCALL declared with [in, out]. + */ +void ocall_pointer_in_out(int* val) +{ + *val = 1234; +} diff --git a/sgx-jvm/linux-sgx/SampleCode/SampleEnclave/App/Edger8rSyntax/Types.cpp b/sgx-jvm/linux-sgx/SampleCode/SampleEnclave/App/Edger8rSyntax/Types.cpp new file mode 100644 index 0000000000..19702263dd --- /dev/null +++ b/sgx-jvm/linux-sgx/SampleCode/SampleEnclave/App/Edger8rSyntax/Types.cpp @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + + +#include "../App.h" +#include "Enclave_u.h" + +/* edger8r_type_attributes: + * Invokes ECALLs declared with basic types. + */ +void edger8r_type_attributes(void) +{ + sgx_status_t ret = SGX_ERROR_UNEXPECTED; + + ret = ecall_type_char(global_eid, (char)0x12); + if (ret != SGX_SUCCESS) + abort(); + + ret = ecall_type_int(global_eid, (int)1234); + if (ret != SGX_SUCCESS) + abort(); + + ret = ecall_type_float(global_eid, (float)1234.0); + if (ret != SGX_SUCCESS) + abort(); + + ret = ecall_type_double(global_eid, (double)1234.5678); + if (ret != SGX_SUCCESS) + abort(); + + ret = ecall_type_size_t(global_eid, (size_t)12345678); + if (ret != SGX_SUCCESS) + abort(); + + ret = ecall_type_wchar_t(global_eid, (wchar_t)0x1234); + if (ret != SGX_SUCCESS) + abort(); + + struct struct_foo_t g = {1234, 5678}; + ret = ecall_type_struct(global_eid, g); + if (ret != SGX_SUCCESS) + abort(); + + union union_foo_t val = {0}; + ret = ecall_type_enum_union(global_eid, ENUM_FOO_0, &val); + if (ret != SGX_SUCCESS) + abort(); + assert(val.union_foo_0 == 2); +} diff --git a/sgx-jvm/linux-sgx/SampleCode/SampleEnclave/App/TrustedLibrary/Libc.cpp b/sgx-jvm/linux-sgx/SampleCode/SampleEnclave/App/TrustedLibrary/Libc.cpp new file mode 100644 index 0000000000..29f0074669 --- /dev/null +++ b/sgx-jvm/linux-sgx/SampleCode/SampleEnclave/App/TrustedLibrary/Libc.cpp @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + + +#include "../App.h" +#include "Enclave_u.h" + +/* ecall_libc_functions: + * Invokes standard C functions. + */ +void ecall_libc_functions(void) +{ + sgx_status_t ret = SGX_ERROR_UNEXPECTED; + + ret = ecall_malloc_free(global_eid); + if (ret != SGX_SUCCESS) + abort(); + + int cpuid[4] = {0x1, 0x0, 0x0, 0x0}; + ret = ecall_sgx_cpuid(global_eid, cpuid, 0x0); + if (ret != SGX_SUCCESS) + abort(); +} diff --git a/sgx-jvm/linux-sgx/SampleCode/SampleEnclave/App/TrustedLibrary/Libcxx.cpp b/sgx-jvm/linux-sgx/SampleCode/SampleEnclave/App/TrustedLibrary/Libcxx.cpp new file mode 100644 index 0000000000..f6d567b98f --- /dev/null +++ b/sgx-jvm/linux-sgx/SampleCode/SampleEnclave/App/TrustedLibrary/Libcxx.cpp @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include + +#include "../App.h" +#include "Enclave_u.h" + +/* ecall_libcxx_functions: + * Invokes standard C++ functions. + */ +void ecall_libcxx_functions(void) +{ + sgx_status_t ret = SGX_ERROR_UNEXPECTED; + + ret = ecall_exception(global_eid); + if (ret != SGX_SUCCESS) + abort(); + + ret = ecall_map(global_eid); + if (ret != SGX_SUCCESS) + abort(); +} diff --git a/sgx-jvm/linux-sgx/SampleCode/SampleEnclave/App/TrustedLibrary/Thread.cpp b/sgx-jvm/linux-sgx/SampleCode/SampleEnclave/App/TrustedLibrary/Thread.cpp new file mode 100644 index 0000000000..ca28fe5ed8 --- /dev/null +++ b/sgx-jvm/linux-sgx/SampleCode/SampleEnclave/App/TrustedLibrary/Thread.cpp @@ -0,0 +1,98 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + + +#include +#include +using namespace std; + +#include "../App.h" +#include "Enclave_u.h" + +static size_t counter = 0; + +void increase_counter(void) +{ + size_t cnr = 0; + sgx_status_t ret = SGX_ERROR_UNEXPECTED; + ret = ecall_increase_counter(global_eid, &cnr); + if (cnr != 0) counter = cnr; + if (ret != SGX_SUCCESS) + abort(); +} + +void data_producer(void) +{ + sgx_status_t ret = SGX_ERROR_UNEXPECTED; + ret = ecall_producer(global_eid); + if (ret != SGX_SUCCESS) + abort(); +} + +void data_consumer(void) +{ + sgx_status_t ret = SGX_ERROR_UNEXPECTED; + ret = ecall_consumer(global_eid); + if (ret != SGX_SUCCESS) + abort(); +} + +/* ecall_thread_functions: + * Invokes thread functions including mutex, condition variable, etc. + */ +void ecall_thread_functions(void) +{ + thread adder1(increase_counter); + thread adder2(increase_counter); + thread adder3(increase_counter); + thread adder4(increase_counter); + + adder1.join(); + adder2.join(); + adder3.join(); + adder4.join(); + + assert(counter == 4*LOOPS_PER_THREAD); + + printf("Info: executing thread synchronization, please wait... \n"); + /* condition variable */ + thread consumer1(data_consumer); + thread producer0(data_producer); + thread consumer2(data_consumer); + thread consumer3(data_consumer); + thread consumer4(data_consumer); + + consumer1.join(); + consumer2.join(); + consumer3.join(); + consumer4.join(); + producer0.join(); +} diff --git a/sgx-jvm/linux-sgx/SampleCode/SampleEnclave/Enclave/Edger8rSyntax/Arrays.cpp b/sgx-jvm/linux-sgx/SampleCode/SampleEnclave/Enclave/Edger8rSyntax/Arrays.cpp new file mode 100644 index 0000000000..cd0718b5c0 --- /dev/null +++ b/sgx-jvm/linux-sgx/SampleCode/SampleEnclave/Enclave/Edger8rSyntax/Arrays.cpp @@ -0,0 +1,102 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +/* Test Array Attributes */ + +#include "sgx_trts.h" +#include "../Enclave.h" +#include "Enclave_t.h" + +/* ecall_array_user_check: + * [user_check] parameter does not perfrom copy operations. + */ +void ecall_array_user_check(int arr[4]) +{ + if (sgx_is_outside_enclave(arr, 4 * sizeof(int)) != 1) + abort(); + + for (int i = 0; i < 4; i++) { + assert(arr[i] == i); + arr[i] = 3 - i; + } +} + +/* ecall_array_in: + * arr[] is copied to trusted domain, but modified + * results will not be reflected to the untrusted side. + */ +void ecall_array_in(int arr[4]) +{ + for (int i = 0; i < 4; i++) { + assert(arr[i] == i); + arr[i] = (3 - i); + } +} + +/* ecall_array_out: + * arr[] is allocated inside the enclave, and it will be copied + * to the untrusted side + */ +void ecall_array_out(int arr[4]) +{ + for (int i = 0; i < 4; i++) { + /* arr is not copied from App */ + assert(arr[i] == 0); + arr[i] = (3 - i); + } +} + +/* ecall_array_in_out: + * arr[] will be allocated inside the enclave, content of arr[] will be copied either. + * After ECALL returns, the results will be copied to the outside. + */ +void ecall_array_in_out(int arr[4]) +{ + for (int i = 0; i < 4; i++) { + assert(arr[i] == i); + arr[i] = (3 - i); + } +} + +/* ecall_array_isary: + * [isary] tells Edger8r that user defined 'array_t' is an array type. + */ +void ecall_array_isary(array_t arr) +{ + if (sgx_is_outside_enclave(arr, sizeof(array_t)) != 1) + abort(); + + int n = sizeof(array_t)/sizeof(arr[0]); + for (int i = 0; i < n; i++) { + assert(arr[i] == i); + arr[i] = (n - 1 - i); + } +} diff --git a/sgx-jvm/linux-sgx/SampleCode/SampleEnclave/Enclave/Edger8rSyntax/Arrays.edl b/sgx-jvm/linux-sgx/SampleCode/SampleEnclave/Enclave/Edger8rSyntax/Arrays.edl new file mode 100644 index 0000000000..4d481fa197 --- /dev/null +++ b/sgx-jvm/linux-sgx/SampleCode/SampleEnclave/Enclave/Edger8rSyntax/Arrays.edl @@ -0,0 +1,98 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + + +/* Arrays.edl - Samples for array attributes. */ + +enclave { + + /* + * Only for fixed-size array (size is explicitly specified). + */ + + trusted { + + /* + * []: can be used to declare an array. + * [user_check]: + * pointer of the array won't be valified, and the buffer pointed by 'arr' + * is not copied into the enclave either. But enclave can modify the memory outside. + */ + + public void ecall_array_user_check([user_check] int arr[4]); + + /* + * [in]: + * buffer for the array will be allocated inside the enclave, + * content of the array will be copied into the new allocated memory inside. + * Any changes performed inside the enclave will not affect the array outside. + */ + + public void ecall_array_in([in] int arr[4]); + + /* + * [out]: + * buffer for the array will be allocated inside the enclave, + * but the content of the array won't be copied. After ECALL returns, + * the buffer inside the enclave will copied into outside array. + */ + + public void ecall_array_out([out] int arr[4]); + + /* + * [in, out]: + * buffer for the array will be allocated inside the enclave, + * the content of the array will be copied either. After ECALL returns, + * the buffer inside the enclave will by copied into outside array again. + */ + + public void ecall_array_in_out([in, out] int arr[4]); + + /* + * [isary]: + * tells Edger8r the user defined 'array_t' is an array type, 'arr' will be + * treated as a pointer, no memory copied either due to [user_check]. + * For OCALLs, 'arr' shall point to the memory outside the enclave. + */ + + public void ecall_array_isary([user_check, isary] array_t arr); + + }; + + untrusted { + + /* + * [user_check|in|out|in,out|isary] can also be used in OCALLs, refer to the "User Guide" for details. + */ + + }; + +}; diff --git a/sgx-jvm/linux-sgx/SampleCode/SampleEnclave/Enclave/Edger8rSyntax/Functions.cpp b/sgx-jvm/linux-sgx/SampleCode/SampleEnclave/Enclave/Edger8rSyntax/Functions.cpp new file mode 100644 index 0000000000..e29739a21e --- /dev/null +++ b/sgx-jvm/linux-sgx/SampleCode/SampleEnclave/Enclave/Edger8rSyntax/Functions.cpp @@ -0,0 +1,84 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + + +/* Test Calling Conventions */ + +#include +#include + +#include "../Enclave.h" +#include "Enclave_t.h" + +/* ecall_function_calling_convs: + * memccpy is defined in system C library. + */ +void ecall_function_calling_convs(void) +{ + sgx_status_t ret = SGX_ERROR_UNEXPECTED; + + char s1[] = "1234567890"; + char s2[] = "0987654321"; + + char buf[BUFSIZ] = {'\0'}; + memcpy(buf, s1, strlen(s1)); + + ret = memccpy(NULL, s1, s2, '\0', strlen(s1)); + + if (ret != SGX_SUCCESS) + abort(); + assert(memcmp(s1, s2, strlen(s1)) == 0); + + return; +} + +/* ecall_function_public: + * The public ECALL that invokes the OCALL 'ocall_function_allow'. + */ +void ecall_function_public(void) +{ + sgx_status_t ret = SGX_ERROR_UNEXPECTED; + + ret = ocall_function_allow(); + if (ret != SGX_SUCCESS) + abort(); + + return; +} + +/* ecall_function_private: + * The private ECALL that only can be invoked in the OCALL 'ocall_function_allow'. + */ +int ecall_function_private(void) +{ + return 1; +} + diff --git a/sgx-jvm/linux-sgx/SampleCode/SampleEnclave/Enclave/Edger8rSyntax/Functions.edl b/sgx-jvm/linux-sgx/SampleCode/SampleEnclave/Enclave/Edger8rSyntax/Functions.edl new file mode 100644 index 0000000000..ad9e1d995f --- /dev/null +++ b/sgx-jvm/linux-sgx/SampleCode/SampleEnclave/Enclave/Edger8rSyntax/Functions.edl @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + + +/* Functions.edl - Samples for function attributes. */ + +enclave { + + /* + * Following keywords/attributes are supported for untrusted functions: + * cdecl, stdcall, fastcall, dllimport (only for Windows). + * [public] is only supported for the trusted functions. + * Trusted function will be treated as [private] w/o the [public]. + */ + + trusted { + + public void ecall_function_calling_convs(void); + + /* + * [public]: + * public ECALL can be called directly in App. + */ + + public void ecall_function_public(void); + + /* + * [private]: + * private ECALL cannot be called directly in App. + */ + + int ecall_function_private(void); + + }; + + untrusted { + + /* + * [cdecl]: + * tells edger8r the calling convention of the OCALLs is 'cdecl'. + * [dllimport]: + * indicats the OCALL is provided in DLLs. + * + * Note: memccpy() is provided by MS system DLL, we don't need to implement it in App side. + */ + + [cdecl, dllimport] void *memccpy([in, out, size=len] void *dest, [in, size=len] const void *src, int val, size_t len); + + /* + * [allow]: + * OCALL 'ocall_function_allow' can invoke ECALL 'ecall_function_private' in App side. + * + * Note: No ECALL can be called in OCALL w/o [allow]. + */ + + void ocall_function_allow(void) allow(ecall_function_private); + + }; + +}; diff --git a/sgx-jvm/linux-sgx/SampleCode/SampleEnclave/Enclave/Edger8rSyntax/Pointers.cpp b/sgx-jvm/linux-sgx/SampleCode/SampleEnclave/Enclave/Edger8rSyntax/Pointers.cpp new file mode 100644 index 0000000000..6e027e9cd3 --- /dev/null +++ b/sgx-jvm/linux-sgx/SampleCode/SampleEnclave/Enclave/Edger8rSyntax/Pointers.cpp @@ -0,0 +1,217 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + + +/* Test Pointer Auttributes */ + +#include +#include + +#include "sgx_trts.h" +#include "../Enclave.h" +#include "Enclave_t.h" + +/* checksum_internal: + * get simple checksum of input buffer and length + */ +int32_t checksum_internal(char *buf, size_t count) +{ + register int32_t sum = 0; + int16_t *ptr = (int16_t *)buf; + + /* Main summing loop */ + while(count > 1) { + sum = sum + *ptr++; + count = count - 2; + } + + /* Add left-over byte, if any */ + if (count > 0) + sum = sum + *((char *)ptr); + + return ~sum; +} + +/* ecall_pointer_user_check, ecall_pointer_in, ecall_pointer_out, ecall_pointer_in_out: + * The root ECALLs to test [in], [out], [user_check] attributes. + */ +size_t ecall_pointer_user_check(void *val, size_t sz) +{ + /* check if the buffer is allocated outside */ + if (sgx_is_outside_enclave(val, sz) != 1) + abort(); + + char tmp[100] = {0}; + size_t len = sz>100?100:sz; + + /* copy the memory into the enclave to make sure 'val' + * is not being changed in checksum_internal() */ + memcpy(tmp, val, len); + + int32_t sum = checksum_internal((char *)tmp, len); + printf("Checksum(0x%p, %zu) = 0x%x\n", + val, len, (unsigned int)sum); + + /* modify outside memory directly */ + memcpy(val, "SGX_SUCCESS", len>12?12:len); + + return len; +} + +/* ecall_pointer_in: + * the buffer of val is copied to the enclave. + */ + +void ecall_pointer_in(int *val) +{ + if (sgx_is_within_enclave(val, sizeof(int)) != 1) + abort(); + *val = 1234; +} + +/* ecall_pointer_out: + * the buffer of val is copied to the untrusted side. + */ +void ecall_pointer_out(int *val) +{ + if (sgx_is_within_enclave(val, sizeof(int)) != 1) + abort(); + assert(*val == 0); + *val = 1234; +} + +/* ecall_pointer_in_out: + * the buffer of val is double-copied. + */ +void ecall_pointer_in_out(int *val) +{ + if (sgx_is_within_enclave(val, sizeof(int)) != 1) + abort(); + *val = 1234; +} + +/* ocall_pointer_attr: + * The root ECALL that test OCALL [in], [out], [user_check]. + */ +void ocall_pointer_attr(void) +{ + sgx_status_t ret = SGX_ERROR_UNEXPECTED; + + int val = 0; + ret = ocall_pointer_user_check(&val); + if (ret != SGX_SUCCESS) + abort(); + + val = 0; + ret = ocall_pointer_in(&val); + if (ret != SGX_SUCCESS) + abort(); + assert(val == 0); + + val = 0; + ret = ocall_pointer_out(&val); + if (ret != SGX_SUCCESS) + abort(); + assert(val == 1234); + + val = 0; + ret = ocall_pointer_in_out(&val); + if (ret != SGX_SUCCESS) + abort(); + assert(val == 1234); + + return; +} + +/* ecall_pointer_string: + * [string] defines a string. + */ +void ecall_pointer_string(char *str) +{ + strncpy(str, "0987654321", strlen(str)); +} + +/* ecall_pointer_string_const: + * const [string] defines a string that cannot be modified. + */ +void ecall_pointer_string_const(const char *str) +{ + char* temp = new char[strlen(str)]; + strncpy(temp, str, strlen(str)); + delete []temp; +} + +/* ecall_pointer_size: + * 'len' needs to be specified to tell Edger8r the length of 'str'. + */ +void ecall_pointer_size(void *ptr, size_t len) +{ + strncpy((char*)ptr, "0987654321", len); +} + +/* ecall_pointer_count: + * 'cnt' needs to be specified to tell Edger8r the number of elements in 'arr'. + */ +void ecall_pointer_count(int *arr, int cnt) +{ + for (int i = (cnt - 1); i >= 0; i--) + arr[i] = (cnt - 1 - i); +} + +/* ecall_pointer_isptr_readonly: + * 'buf' is user defined type, shall be tagged with [isptr]. + * if it's not writable, [readonly] shall be specified. + */ +void ecall_pointer_isptr_readonly(buffer_t buf, size_t len) +{ + strncpy((char*)buf, "0987654321", len); +} + +/* get_buffer_len: + * get the length of input buffer 'buf'. + */ +size_t get_buffer_len(const char* buf) +{ + (void)buf; + return 10*sizeof(int); +} + +/* ecall_pointer_sizefunc: + * call get_buffer_len to determin the length of 'buf'. + */ +void ecall_pointer_sizefunc(char *buf) +{ + int *tmp = (int*)buf; + for (int i = 0; i < 10; i++) { + assert(tmp[i] == 0); + tmp[i] = i; + } +} diff --git a/sgx-jvm/linux-sgx/SampleCode/SampleEnclave/Enclave/Edger8rSyntax/Pointers.edl b/sgx-jvm/linux-sgx/SampleCode/SampleEnclave/Enclave/Edger8rSyntax/Pointers.edl new file mode 100644 index 0000000000..cbbc960f38 --- /dev/null +++ b/sgx-jvm/linux-sgx/SampleCode/SampleEnclave/Enclave/Edger8rSyntax/Pointers.edl @@ -0,0 +1,190 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + + +/* Pointers.edl - Samples for pointer attributes. */ + +enclave { + + /* + * Following keywords/attributes are supported for pointers in Edger8r: + * in, out, user_check, + * string, wstring, + * const, size, count, sizefunc, isptr, readonly + */ + + trusted { + + /* + * [user_check]: + * the pointer won't be validated, and the buffer pointed by + * 'val' is not copied into the enclave either. But Enclave + * can modify the memory pointed by 'val'. + */ + + public size_t ecall_pointer_user_check([user_check] void *val, size_t sz); + + /* + * [in]: + * buffer with the same size will be allocated inside the enclave, + * content pointed by 'val' will be copied into the new allocated + * memory inside. Any changes performed inside the enclave will not + * affect the buffer outside. + */ + + public void ecall_pointer_in([in] int *val); + + /* + * [out]: + * buffer with the same size will be allocated inside the enclave, + * but the content pointed by 'val' won't be copied. But after return, + * the buffer inside the enclave will copied into outside 'val'. + */ + + public void ecall_pointer_out([out] int *val); + + /* + * [in, out]: + * buffer with the same size will be allocated inside the enclave, + * the content pointed by 'val' will be copied either. After return, + * the buffer inside the enclave will by copied into outside 'val' again. + */ + + public void ecall_pointer_in_out([in, out] int *val); + + /* + * [string]: + * the attribute tells Edger8r 'str' is NULL terminated string, so strlen + * will be used to count the length of buffer pointed by 'str'. + */ + + public void ecall_pointer_string([in, out, string] char *str); + + /* + * [const]: + * the attribute tells Edger8r the buffer pointed by 'str' cannot be modified, + * so users cannot decorate 'str' with [out] attribute anymore. + */ + + public void ecall_pointer_string_const([in, string] const char *str); + + /* + * [size]: + * the attribute tells Edger8r the length of buffer in byte pointed by 'ptr' + * (shall be copied or not). + * Note: Users shall not specify [size] on [string] parameters. + */ + + public void ecall_pointer_size([in, out, size=len] void *ptr, size_t len); + + /* + * [count]: + * the attribute tells Edger8r the number of integers to be copied from 'arr'. + */ + + public void ecall_pointer_count([in, out, count=cnt] int *arr, int cnt); + + /* + * [isptr]: + * tells Edger8r the user defined type is a pointer; + * [readonly]: + * forbids the buffer allocated inside the enclave to be copied back to App + * (cannot use with [out]). + */ + + public void ecall_pointer_isptr_readonly([in, isptr, readonly, size=len] buffer_t buf, size_t len); + + /* + * [sizefunc]: + * call a function to decide the size/length of the parameter; + * Note: + * User need to define and implement `get_buf_len' as: + * size_t get_buf_len(const char* buf); + */ + + public void ecall_pointer_sizefunc([sizefunc = get_buffer_len, in, out] char *buf); + + }; + + /* + * Users can define multiple trusted/untrusted blocks, + * edger8r will merged them into one trusted/untrusted block. + */ + trusted { + /* + * Test pointer attributes in OCALLs + */ + + public void ocall_pointer_attr(void); + + }; + + untrusted { + + /* + * [user_check]: + * the pointer won't be valified, and the buffer pointed by 'val' is not + * copied to outside buffer either. Besides 'App' cannot modify the memory + * pointer by 'val'. + */ + + void ocall_pointer_user_check([user_check] int *val); + + /* + * [in]: + * buffer with the same size will be allocated in 'App' side, the content + * pointed by 'val' will be copied into the new allocated memory outside. + * Any changes performed by 'App' will not affect the buffer pointed by 'val'. + */ + + void ocall_pointer_in([in] int *val); + + /* + * [out]: + * buffer with the same size will be allocated in 'App' side, the content + * pointed by 'val' won't be copied. But after return, the buffer outside + * will be copied into the enclave. + */ + + void ocall_pointer_out([out] int *val); + + /* + * [in, out]: + * buffer with the same size will be allocated in 'App' side, the content + * pointed by 'val' will be copied either. After return, the buffer outside + * will copied into the enclave. + */ + + void ocall_pointer_in_out([in, out] int *val); + + }; + +}; diff --git a/sgx-jvm/linux-sgx/SampleCode/SampleEnclave/Enclave/Edger8rSyntax/Types.cpp b/sgx-jvm/linux-sgx/SampleCode/SampleEnclave/Enclave/Edger8rSyntax/Types.cpp new file mode 100644 index 0000000000..aba016a6d8 --- /dev/null +++ b/sgx-jvm/linux-sgx/SampleCode/SampleEnclave/Enclave/Edger8rSyntax/Types.cpp @@ -0,0 +1,155 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + + +/* Test Basic Types */ + +#include "sgx_trts.h" +#include "../Enclave.h" +#include "Enclave_t.h" +#include +#include + +/* used to eliminate `unused variable' warning */ +#define UNUSED(val) (void)(val) + +#define ULP 2 + +/* used to compare double variables in order to avoid compile warnings */ +bool almost_equal(double x, double y) +{ + /* the machine epsilon has to be scaled to the magnitude of the larger value + and multiplied by the desired precision in ULPs (units in the last place) */ + return std::abs(x-y) <= std::numeric_limits::epsilon() * std::abs(x+y) * ULP; +} + +/* used to compare double variables in order to avoid compile warnings */ +bool almost_equal(float x, float y) +{ + /* the machine epsilon has to be scaled to the magnitude of the larger value + and multiplied by the desired precision in ULPs (units in the last place) */ + return std::abs(x-y) <= std::numeric_limits::epsilon() * std::abs(x+y) * ULP; +} + +/* ecall_type_char: + * [char] value passed by App. + */ +void ecall_type_char(char val) +{ + assert(val == 0x12); +#ifndef DEBUG + UNUSED(val); +#endif +} + +/* ecall_type_int: + * [int] value passed by App. + */ +void ecall_type_int(int val) +{ + assert(val == 1234); +#ifndef DEBUG + UNUSED(val); +#endif +} + +/* ecall_type_float: + * [float] value passed by App. + */ +void ecall_type_float(float val) +{ + assert(almost_equal(val, (float)1234.0)); +#ifndef DEBUG + UNUSED(val); +#endif +} + +/* ecall_type_double: + * [double] value passed by App. + */ +void ecall_type_double(double val) +{ + assert(almost_equal(val, (double)1234.5678)); +#ifndef DEBUG + UNUSED(val); +#endif +} + +/* ecall_type_size_t: + * [size_t] value passed by App. + */ +void ecall_type_size_t(size_t val) +{ + assert(val == (size_t)12345678); +#ifndef DEBUG + UNUSED(val); +#endif +} + +/* ecall_type_wchar_t: + * [wchar_t] value passed by App. + */ +void ecall_type_wchar_t(wchar_t val) +{ + assert(val == (wchar_t)0x1234); +#ifndef DEBUG + UNUSED(val); +#endif +} + +/* ecall_type_struct: + * struct_foo_t is defined in EDL and can be used in ECALL. + */ +void ecall_type_struct(struct struct_foo_t val) +{ + assert(val.struct_foo_0 == 1234); + assert(val.struct_foo_1 == 5678); +#ifndef DEBUG + UNUSED(val); +#endif +} + +/* + * ecall_type_enum_union: + * enum_foo_t/union_foo_t is defined in EDL + * and can be used in ECALL. + */ +void ecall_type_enum_union(enum enum_foo_t val1, union union_foo_t *val2) +{ + if (sgx_is_outside_enclave(val2, sizeof(union union_foo_t)) != 1) + abort(); + val2->union_foo_0 = 1; + val2->union_foo_1 = 2; /* overwrite union_foo_0 */ + assert(val1 == ENUM_FOO_0); +#ifndef DEBUG + UNUSED(val1); +#endif +} diff --git a/sgx-jvm/linux-sgx/SampleCode/SampleEnclave/Enclave/Edger8rSyntax/Types.edl b/sgx-jvm/linux-sgx/SampleCode/SampleEnclave/Enclave/Edger8rSyntax/Types.edl new file mode 100644 index 0000000000..a23aed85ca --- /dev/null +++ b/sgx-jvm/linux-sgx/SampleCode/SampleEnclave/Enclave/Edger8rSyntax/Types.edl @@ -0,0 +1,87 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +/* Types.edl - Samples for basic types. */ + +enclave { + + /* + * Following types can be supported in Edger8r: + * char, short, int, float, double, void, + * int8_t, int16_t, int32_t, int64_t, + * size_t, wchar_t, + * uint8_t, uint16_t, uint32_t, uint64_t, + * unsigned, struct, enum, union. + */ + + /* + * We will demo few types in ECALL functions, data + * types in OCALL functions can be handled either. + */ + + /* structure definition */ + struct struct_foo_t { + /* Basic types can be used in structure. */ + uint32_t struct_foo_0; + uint64_t struct_foo_1; + }; + + /* enum definition */ + enum enum_foo_t { + ENUM_FOO_0 = 0, + ENUM_FOO_1 = 1 + }; + + /* union definition */ + union union_foo_t { + uint32_t union_foo_0; + uint32_t union_foo_1; + uint64_t union_foo_3; + }; + + trusted { + + public void ecall_type_char(char val); + public void ecall_type_int(int val); + + public void ecall_type_float(float val); + public void ecall_type_double(double val); + + public void ecall_type_size_t(size_t val); + public void ecall_type_wchar_t(wchar_t val); + + public void ecall_type_struct(struct struct_foo_t val); + public void ecall_type_enum_union(enum enum_foo_t val1, [user_check] union union_foo_t *val2); + + /* for using user defined types, please refer to Pointers.edl, Arrays.edl. */ + }; + +}; diff --git a/sgx-jvm/linux-sgx/SampleCode/SampleEnclave/Enclave/Enclave.config.xml b/sgx-jvm/linux-sgx/SampleCode/SampleEnclave/Enclave/Enclave.config.xml new file mode 100644 index 0000000000..c9533851cf --- /dev/null +++ b/sgx-jvm/linux-sgx/SampleCode/SampleEnclave/Enclave/Enclave.config.xml @@ -0,0 +1,11 @@ + + 0 + 0 + 0x40000 + 0x100000 + 10 + 1 + 0 + 0 + 0xFFFFFFFF + diff --git a/sgx-jvm/linux-sgx/SampleCode/SampleEnclave/Enclave/Enclave.cpp b/sgx-jvm/linux-sgx/SampleCode/SampleEnclave/Enclave/Enclave.cpp new file mode 100644 index 0000000000..94a3108c46 --- /dev/null +++ b/sgx-jvm/linux-sgx/SampleCode/SampleEnclave/Enclave/Enclave.cpp @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + + +#include +#include /* vsnprintf */ + +#include "Enclave.h" +#include "Enclave_t.h" /* print_string */ + +/* + * printf: + * Invokes OCALL to display the enclave buffer to the terminal. + */ +void printf(const char *fmt, ...) +{ + char buf[BUFSIZ] = {'\0'}; + va_list ap; + va_start(ap, fmt); + vsnprintf(buf, BUFSIZ, fmt, ap); + va_end(ap); + ocall_print_string(buf); +} diff --git a/sgx-jvm/linux-sgx/SampleCode/SampleEnclave/Enclave/Enclave.edl b/sgx-jvm/linux-sgx/SampleCode/SampleEnclave/Enclave/Enclave.edl new file mode 100644 index 0000000000..9e31bd2ce8 --- /dev/null +++ b/sgx-jvm/linux-sgx/SampleCode/SampleEnclave/Enclave/Enclave.edl @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +/* Enclave.edl - Top EDL file. */ + +enclave { + + include "user_types.h" /* buffer_t */ + + /* Import ECALL/OCALL from sub-directory EDLs. + * [from]: specifies the location of EDL file. + * [import]: specifies the functions to import, + * [*]: implies to import all functions. + */ + + from "Edger8rSyntax/Types.edl" import *; + from "Edger8rSyntax/Pointers.edl" import *; + from "Edger8rSyntax/Arrays.edl" import *; + from "Edger8rSyntax/Functions.edl" import *; + + from "TrustedLibrary/Libc.edl" import *; + from "TrustedLibrary/Libcxx.edl" import ecall_exception, ecall_map; + from "TrustedLibrary/Thread.edl" import *; + + /* + * ocall_print_string - invokes OCALL to display string buffer inside the enclave. + * [in]: copy the string buffer to App outside. + * [string]: specifies 'str' is a NULL terminated buffer. + */ + untrusted { + void ocall_print_string([in, string] const char *str); + }; + +}; diff --git a/sgx-jvm/linux-sgx/SampleCode/SampleEnclave/Enclave/Enclave.h b/sgx-jvm/linux-sgx/SampleCode/SampleEnclave/Enclave/Enclave.h new file mode 100644 index 0000000000..6e4c09ee2c --- /dev/null +++ b/sgx-jvm/linux-sgx/SampleCode/SampleEnclave/Enclave/Enclave.h @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + + +#ifndef _ENCLAVE_H_ +#define _ENCLAVE_H_ + +#include +#include + +#if defined(__cplusplus) +extern "C" { +#endif + +void printf(const char *fmt, ...); + +#if defined(__cplusplus) +} +#endif + +#endif /* !_ENCLAVE_H_ */ diff --git a/sgx-jvm/linux-sgx/SampleCode/SampleEnclave/Enclave/Enclave.lds b/sgx-jvm/linux-sgx/SampleCode/SampleEnclave/Enclave/Enclave.lds new file mode 100644 index 0000000000..e3d9d0ee0d --- /dev/null +++ b/sgx-jvm/linux-sgx/SampleCode/SampleEnclave/Enclave/Enclave.lds @@ -0,0 +1,9 @@ +enclave.so +{ + global: + g_global_data_sim; + g_global_data; + enclave_entry; + local: + *; +}; diff --git a/sgx-jvm/linux-sgx/SampleCode/SampleEnclave/Enclave/Enclave_private.pem b/sgx-jvm/linux-sgx/SampleCode/SampleEnclave/Enclave/Enclave_private.pem new file mode 100644 index 0000000000..529d07be35 --- /dev/null +++ b/sgx-jvm/linux-sgx/SampleCode/SampleEnclave/Enclave/Enclave_private.pem @@ -0,0 +1,39 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIG4gIBAAKCAYEAroOogvsj/fZDZY8XFdkl6dJmky0lRvnWMmpeH41Bla6U1qLZ +AmZuyIF+mQC/cgojIsrBMzBxb1kKqzATF4+XwPwgKz7fmiddmHyYz2WDJfAjIveJ +ZjdMjM4+EytGlkkJ52T8V8ds0/L2qKexJ+NBLxkeQLfV8n1mIk7zX7jguwbCG1Pr +nEMdJ3Sew20vnje+RsngAzdPChoJpVsWi/K7cettX/tbnre1DL02GXc5qJoQYk7b +3zkmhz31TgFrd9VVtmUGyFXAysuSAb3EN+5VnHGr0xKkeg8utErea2FNtNIgua8H +ONfm9Eiyaav1SVKzPHlyqLtcdxH3I8Wg7yqMsaprZ1n5A1v/levxnL8+It02KseD +5HqV4rf/cImSlCt3lpRg8U5E1pyFQ2IVEC/XTDMiI3c+AR+w2jSRB3Bwn9zJtFlW +KHG3m1xGI4ck+Lci1JvWWLXQagQSPtZTsubxTQNx1gsgZhgv1JHVZMdbVlAbbRMC +1nSuJNl7KPAS/VfzAgEDAoIBgHRXxaynbVP5gkO0ug6Qw/E27wzIw4SmjsxG6Wpe +K7kfDeRskKxESdsA/xCrKkwGwhcx1iIgS5+Qscd1Yg+1D9X9asd/P7waPmWoZd+Z +AhlKwhdPsO7PiF3e1AzHhGQwsUTt/Y/aSI1MpHBvy2/s1h9mFCslOUxTmWw0oj/Q +ldIEgWeNR72CE2+jFIJIyml6ftnb6qzPiga8Bm48ubKh0kvySOqnkmnPzgh+JBD6 +JnBmtZbfPT97bwTT+N6rnPqOOApvfHPf15kWI8yDbprG1l4OCUaIUH1AszxLd826 +5IPM+8gINLRDP1MA6azECPjTyHXhtnSIBZCyWSVkc05vYmNXYUNiXWMajcxW9M02 +wKzFELO8NCEAkaTPxwo4SCyIjUxiK1LbQ9h8PSy4c1+gGP4LAMR8xqP4QKg6zdu9 +osUGG/xRe/uufgTBFkcjqBHtK5L5VI0jeNIUAgW/6iNbYXjBMJ0GfauLs+g1VsOm +WfdgXzsb9DYdMa0OXXHypmV4GwKBwQDUwQj8RKJ6c8cT4vcWCoJvJF00+RFL+P3i +Gx2DLERxRrDa8AVGfqaCjsR+3vLgG8V/py+z+dxZYSqeB80Qeo6PDITcRKoeAYh9 +xlT3LJOS+k1cJcEmlbbO2IjLkTmzSwa80fWexKu8/Xv6vv15gpqYl1ngYoqJM3pd +vzmTIOi7MKSZ0WmEQavrZj8zK4endE3v0eAEeQ55j1GImbypSf7Idh7wOXtjZ7WD +Dg6yWDrri+AP/L3gClMj8wsAxMV4ZR8CgcEA0fzDHkFa6raVOxWnObmRoDhAtE0a +cjUj976NM5yyfdf2MrKy4/RhdTiPZ6b08/lBC/+xRfV3xKVGzacm6QjqjZrUpgHC +0LKiZaMtccCJjLtPwQd0jGQEnKfMFaPsnhOc5y8qVkCzVOSthY5qhz0XNotHHFmJ +gffVgB0iqrMTvSL7IA2yqqpOqNRlhaYhNl8TiFP3gIeMtVa9rZy31JPgT2uJ+kfo +gV7sdTPEjPWZd7OshGxWpT6QfVDj/T9T7L6tAoHBAI3WBf2DFvxNL2KXT2QHAZ9t +k3imC4f7U+wSE6zILaDZyzygA4RUbwG0gv8/TJVn2P/Eynf76DuWHGlaiLWnCbSz +Az2DHBQBBaku409zDQym3j1ugMRjzzSQWzJg0SIyBH3hTmnYcn3+Uqcp/lEBvGW6 +O+rsXFt3pukqJmIV8HzLGGaLm62BHUeZf3dyWm+i3p/hQAL7Xvu04QW70xuGqdr5 +afV7p5eaeQIJXyGQJ0eylV/90+qxjMKiB1XYg6WYvwKBwQCL/ddpgOdHJGN8uRom +e7Zq0Csi3hGheMKlKbN3vcxT5U7MdyHtTZZOJbTvxKNNUNYH/8uD+PqDGNneb29G +BfGzvI3EASyLIcGZF3OhKwZd0jUrWk2y7Vhob91jwp2+t73vdMbkKyI4mHOuXvGv +fg95si9oO7EBT+Oqvhccd2J+F1IVXncccYnF4u5ZGWt5lLewN/pVr7MjjykeaHqN +t+rfnQam2psA6fL4zS2zTmZPzR2tnY8Y1GBTi0Ko1OKd1HMCgcAb5cB/7/AQlhP9 +yQa04PLH9ygQkKKptZp7dy5WcWRx0K/hAHRoi2aw1wZqfm7VBNu2SLcs90kCCCxp +6C5sfJi6b8NpNbIPC+sc9wsFr7pGo9SFzQ78UlcWYK2Gu2FxlMjonhka5hvo4zvg +WxlpXKEkaFt3gLd92m/dMqBrHfafH7VwOJY2zT3WIpjwuk0ZzmRg5p0pG/svVQEH +NZmwRwlopysbR69B/n1nefJ84UO50fLh5s5Zr3gBRwbWNZyzhXk= +-----END RSA PRIVATE KEY----- diff --git a/sgx-jvm/linux-sgx/SampleCode/SampleEnclave/Enclave/TrustedLibrary/Libc.cpp b/sgx-jvm/linux-sgx/SampleCode/SampleEnclave/Enclave/TrustedLibrary/Libc.cpp new file mode 100644 index 0000000000..b0e566ced1 --- /dev/null +++ b/sgx-jvm/linux-sgx/SampleCode/SampleEnclave/Enclave/TrustedLibrary/Libc.cpp @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + + +#include +#include + +#include "sgx_trts.h" +#include "../Enclave.h" +#include "Enclave_t.h" + +/* ecall_malloc_free: + * Uses malloc/free to allocate/free trusted memory. + */ +void ecall_malloc_free(void) +{ + void *ptr = malloc(100); + assert(ptr != NULL); + memset(ptr, 0x0, 100); + free(ptr); +} + +/* ecall_sgx_cpuid: + * Uses sgx_cpuid to get CPU features and types. + */ +void ecall_sgx_cpuid(int cpuinfo[4], int leaf) +{ + sgx_status_t ret = sgx_cpuid(cpuinfo, leaf); + if (ret != SGX_SUCCESS) + abort(); +} diff --git a/sgx-jvm/linux-sgx/SampleCode/SampleEnclave/Enclave/TrustedLibrary/Libc.edl b/sgx-jvm/linux-sgx/SampleCode/SampleEnclave/Enclave/TrustedLibrary/Libc.edl new file mode 100644 index 0000000000..9efe3219d4 --- /dev/null +++ b/sgx-jvm/linux-sgx/SampleCode/SampleEnclave/Enclave/TrustedLibrary/Libc.edl @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + + +/* Libc.edl - EDL sample for trusted C library. */ + +enclave { + + from "sgx_tstdc.edl" import sgx_oc_cpuidex; + + /* + * A subset of the C99 standard is supported as well as SGX customized functions: + * sgx_cpuid, etc. + */ + + trusted { + /* + * Utilize malloc/free in enclave. + */ + public void ecall_malloc_free(void); + + /* + * Utilize SGX version __cpuid() in enclave. + */ + public void ecall_sgx_cpuid([in, out] int cpuinfo[4], int leaf); + }; +}; diff --git a/sgx-jvm/linux-sgx/SampleCode/SampleEnclave/Enclave/TrustedLibrary/Libcxx.cpp b/sgx-jvm/linux-sgx/SampleCode/SampleEnclave/Enclave/TrustedLibrary/Libcxx.cpp new file mode 100644 index 0000000000..6f76646466 --- /dev/null +++ b/sgx-jvm/linux-sgx/SampleCode/SampleEnclave/Enclave/TrustedLibrary/Libcxx.cpp @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + + +#include +#include + +#include "../Enclave.h" +#include "Enclave_t.h" + +/* + * ecall_exception: + * throw/catch C++ exception inside the enclave. + */ + +void ecall_exception(void) +{ + std::string foo = "foo"; + try { + throw std::runtime_error(foo); + } + catch (std::runtime_error const& e) { + assert( foo == e.what() ); + std::runtime_error clone(""); + clone = e; + assert(foo == clone.what() ); + } + catch (...) { + assert( false ); + } +} + +#include +#include + +using namespace std; + +/* + * ecall_map: + * Utilize STL in the enclave. + */ +void ecall_map(void) +{ + typedef map > map_t; + typedef map_t::value_type map_value; + map_t m; + + m.insert(map_value('a', 1)); + m.insert(map_value('b', 2)); + m.insert(map_value('c', 3)); + m.insert(map_value('d', 4)); + + assert(m['a'] == 1); + assert(m['b'] == 2); + assert(m['c'] == 3); + assert(m['d'] == 4); + + assert(m.find('e') == m.end()); + + return; +} diff --git a/sgx-jvm/linux-sgx/SampleCode/SampleEnclave/Enclave/TrustedLibrary/Libcxx.edl b/sgx-jvm/linux-sgx/SampleCode/SampleEnclave/Enclave/TrustedLibrary/Libcxx.edl new file mode 100644 index 0000000000..49a8b8d9d9 --- /dev/null +++ b/sgx-jvm/linux-sgx/SampleCode/SampleEnclave/Enclave/TrustedLibrary/Libcxx.edl @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + + +/* Libcxx.edl - EDL sample for trusted C++ library. */ + +enclave { + + /* + * A subset of the C++03 standard is supported. + */ + + trusted { + /* + * Throw/catch exception inside the enclave. + */ + public void ecall_exception(void); + + /* + * Utilize inside the enclave. + */ + public void ecall_map(void); + }; +}; diff --git a/sgx-jvm/linux-sgx/SampleCode/SampleEnclave/Enclave/TrustedLibrary/Thread.cpp b/sgx-jvm/linux-sgx/SampleCode/SampleEnclave/Enclave/TrustedLibrary/Thread.cpp new file mode 100644 index 0000000000..d360d716a6 --- /dev/null +++ b/sgx-jvm/linux-sgx/SampleCode/SampleEnclave/Enclave/TrustedLibrary/Thread.cpp @@ -0,0 +1,104 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + + +#include "../Enclave.h" +#include "Enclave_t.h" + +#include + +static size_t global_counter = 0; +static sgx_thread_mutex_t global_mutex = SGX_THREAD_MUTEX_INITIALIZER; + +#define BUFFER_SIZE 50 + +typedef struct { + int buf[BUFFER_SIZE]; + int occupied; + int nextin; + int nextout; + sgx_thread_mutex_t mutex; + sgx_thread_cond_t more; + sgx_thread_cond_t less; +} cond_buffer_t; + +static cond_buffer_t buffer = {{0, 0, 0, 0, 0, 0}, 0, 0, 0, + SGX_THREAD_MUTEX_INITIALIZER, SGX_THREAD_COND_INITIALIZER, SGX_THREAD_COND_INITIALIZER}; + +/* + * ecall_increase_counter: + * Utilize thread APIs inside the enclave. + */ +size_t ecall_increase_counter(void) +{ + size_t ret = 0; + for (int i = 0; i < LOOPS_PER_THREAD; i++) { + sgx_thread_mutex_lock(&global_mutex); + /* mutually exclusive adding */ + size_t tmp = global_counter; + global_counter = ++tmp; + if (4*LOOPS_PER_THREAD == global_counter) + ret = global_counter; + sgx_thread_mutex_unlock(&global_mutex); + } + return ret; +} + +void ecall_producer(void) +{ + for (int i = 0; i < 4*LOOPS_PER_THREAD; i++) { + cond_buffer_t *b = &buffer; + sgx_thread_mutex_lock(&b->mutex); + while (b->occupied >= BUFFER_SIZE) + sgx_thread_cond_wait(&b->less, &b->mutex); + b->buf[b->nextin] = b->nextin; + b->nextin++; + b->nextin %= BUFFER_SIZE; + b->occupied++; + sgx_thread_cond_signal(&b->more); + sgx_thread_mutex_unlock(&b->mutex); + } +} + +void ecall_consumer(void) +{ + for (int i = 0; i < LOOPS_PER_THREAD; i++) { + cond_buffer_t *b = &buffer; + sgx_thread_mutex_lock(&b->mutex); + while(b->occupied <= 0) + sgx_thread_cond_wait(&b->more, &b->mutex); + b->buf[b->nextout++] = 0; + b->nextout %= BUFFER_SIZE; + b->occupied--; + sgx_thread_cond_signal(&b->less); + sgx_thread_mutex_unlock(&b->mutex); + } +} diff --git a/sgx-jvm/linux-sgx/SampleCode/SampleEnclave/Enclave/TrustedLibrary/Thread.edl b/sgx-jvm/linux-sgx/SampleCode/SampleEnclave/Enclave/TrustedLibrary/Thread.edl new file mode 100644 index 0000000000..77ce461de4 --- /dev/null +++ b/sgx-jvm/linux-sgx/SampleCode/SampleEnclave/Enclave/TrustedLibrary/Thread.edl @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +/* Thread.edl - EDL sample for trusted thread library. */ + +enclave { + + from "sgx_tstdc.edl" import sgx_thread_wait_untrusted_event_ocall, sgx_thread_set_untrusted_event_ocall, sgx_thread_setwait_untrusted_events_ocall, sgx_thread_set_multiple_untrusted_events_ocall; + + trusted { + /* + * Use SGX mutex. + */ + public size_t ecall_increase_counter(); + + /* + * Use SGX condition variables. + */ + public void ecall_producer(); + public void ecall_consumer(); + + }; +}; diff --git a/sgx-jvm/linux-sgx/SampleCode/SampleEnclave/Include/user_types.h b/sgx-jvm/linux-sgx/SampleCode/SampleEnclave/Include/user_types.h new file mode 100644 index 0000000000..00a9bed83f --- /dev/null +++ b/sgx-jvm/linux-sgx/SampleCode/SampleEnclave/Include/user_types.h @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + + +/* User defined types */ + + +#define LOOPS_PER_THREAD 500 + +typedef void *buffer_t; +typedef int array_t[10]; + diff --git a/sgx-jvm/linux-sgx/SampleCode/SampleEnclave/Makefile b/sgx-jvm/linux-sgx/SampleCode/SampleEnclave/Makefile new file mode 100644 index 0000000000..aaa22052e6 --- /dev/null +++ b/sgx-jvm/linux-sgx/SampleCode/SampleEnclave/Makefile @@ -0,0 +1,239 @@ +# +# Copyright (C) 2011-2016 Intel Corporation. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# + +######## SGX SDK Settings ######## + +SGX_SDK ?= /opt/intel/sgxsdk +SGX_MODE ?= HW +SGX_ARCH ?= x64 +SGX_DEBUG ?= 1 + +ifeq ($(shell getconf LONG_BIT), 32) + SGX_ARCH := x86 +else ifeq ($(findstring -m32, $(CXXFLAGS)), -m32) + SGX_ARCH := x86 +endif + +ifeq ($(SGX_ARCH), x86) + SGX_COMMON_CFLAGS := -m32 + SGX_LIBRARY_PATH := $(SGX_SDK)/lib + SGX_ENCLAVE_SIGNER := $(SGX_SDK)/bin/x86/sgx_sign + SGX_EDGER8R := $(SGX_SDK)/bin/x86/sgx_edger8r +else + SGX_COMMON_CFLAGS := -m64 + SGX_LIBRARY_PATH := $(SGX_SDK)/lib64 + SGX_ENCLAVE_SIGNER := $(SGX_SDK)/bin/x64/sgx_sign + SGX_EDGER8R := $(SGX_SDK)/bin/x64/sgx_edger8r +endif + +ifeq ($(SGX_DEBUG), 1) +ifeq ($(SGX_PRERELEASE), 1) +$(error Cannot set SGX_DEBUG and SGX_PRERELEASE at the same time!!) +endif +endif + +ifeq ($(SGX_DEBUG), 1) + SGX_COMMON_CFLAGS += -O0 -g +else + SGX_COMMON_CFLAGS += -O2 +endif + +######## App Settings ######## + +ifneq ($(SGX_MODE), HW) + Urts_Library_Name := sgx_urts_sim +else + Urts_Library_Name := sgx_urts +endif + +App_Cpp_Files := App/App.cpp $(wildcard App/Edger8rSyntax/*.cpp) $(wildcard App/TrustedLibrary/*.cpp) +App_Include_Paths := -IInclude -IApp -I$(SGX_SDK)/include + +App_C_Flags := $(SGX_COMMON_CFLAGS) -fPIC -Wno-attributes $(App_Include_Paths) + +# Three configuration modes - Debug, prerelease, release +# Debug - Macro DEBUG enabled. +# Prerelease - Macro NDEBUG and EDEBUG enabled. +# Release - Macro NDEBUG enabled. +ifeq ($(SGX_DEBUG), 1) + App_C_Flags += -DDEBUG -UNDEBUG -UEDEBUG +else ifeq ($(SGX_PRERELEASE), 1) + App_C_Flags += -DNDEBUG -DEDEBUG -UDEBUG +else + App_C_Flags += -DNDEBUG -UEDEBUG -UDEBUG +endif + +App_Cpp_Flags := $(App_C_Flags) -std=c++11 +App_Link_Flags := $(SGX_COMMON_CFLAGS) -L$(SGX_LIBRARY_PATH) -l$(Urts_Library_Name) -lpthread + +ifneq ($(SGX_MODE), HW) + App_Link_Flags += -lsgx_uae_service_sim +else + App_Link_Flags += -lsgx_uae_service +endif + +App_Cpp_Objects := $(App_Cpp_Files:.cpp=.o) + +App_Name := app + +######## Enclave Settings ######## + +ifneq ($(SGX_MODE), HW) + Trts_Library_Name := sgx_trts_sim + Service_Library_Name := sgx_tservice_sim +else + Trts_Library_Name := sgx_trts + Service_Library_Name := sgx_tservice +endif +Crypto_Library_Name := sgx_tcrypto + +Enclave_Cpp_Files := Enclave/Enclave.cpp $(wildcard Enclave/Edger8rSyntax/*.cpp) $(wildcard Enclave/TrustedLibrary/*.cpp) +Enclave_Include_Paths := -IInclude -IEnclave -I$(SGX_SDK)/include -I$(SGX_SDK)/include/tlibc -I$(SGX_SDK)/include/stlport + +Enclave_C_Flags := $(SGX_COMMON_CFLAGS) -nostdinc -fvisibility=hidden -fpie -fstack-protector $(Enclave_Include_Paths) +Enclave_Cpp_Flags := $(Enclave_C_Flags) -std=c++03 -nostdinc++ + +# To generate a proper enclave, it is recommended to follow below guideline to link the trusted libraries: +# 1. Link sgx_trts with the `--whole-archive' and `--no-whole-archive' options, +# so that the whole content of trts is included in the enclave. +# 2. For other libraries, you just need to pull the required symbols. +# Use `--start-group' and `--end-group' to link these libraries. +# Do NOT move the libraries linked with `--start-group' and `--end-group' within `--whole-archive' and `--no-whole-archive' options. +# Otherwise, you may get some undesirable errors. +Enclave_Link_Flags := $(SGX_COMMON_CFLAGS) -Wl,--no-undefined -nostdlib -nodefaultlibs -nostartfiles -L$(SGX_LIBRARY_PATH) \ + -Wl,--whole-archive -l$(Trts_Library_Name) -Wl,--no-whole-archive \ + -Wl,--start-group -lsgx_tstdc -lsgx_tstdcxx -l$(Crypto_Library_Name) -l$(Service_Library_Name) -Wl,--end-group \ + -Wl,-Bstatic -Wl,-Bsymbolic -Wl,--no-undefined \ + -Wl,-pie,-eenclave_entry -Wl,--export-dynamic \ + -Wl,--defsym,__ImageBase=0 \ + -Wl,--version-script=Enclave/Enclave.lds + +Enclave_Cpp_Objects := $(Enclave_Cpp_Files:.cpp=.o) + +Enclave_Name := enclave.so +Signed_Enclave_Name := enclave.signed.so +Enclave_Config_File := Enclave/Enclave.config.xml + +ifeq ($(SGX_MODE), HW) +ifeq ($(SGX_DEBUG), 1) + Build_Mode = HW_DEBUG +else ifeq ($(SGX_PRERELEASE), 1) + Build_Mode = HW_PRERELEASE +else + Build_Mode = HW_RELEASE +endif +else +ifeq ($(SGX_DEBUG), 1) + Build_Mode = SIM_DEBUG +else ifeq ($(SGX_PRERELEASE), 1) + Build_Mode = SIM_PRERELEASE +else + Build_Mode = SIM_RELEASE +endif +endif + + +.PHONY: all run + +ifeq ($(Build_Mode), HW_RELEASE) +all: $(App_Name) $(Enclave_Name) + @echo "The project has been built in release hardware mode." + @echo "Please sign the $(Enclave_Name) first with your signing key before you run the $(App_Name) to launch and access the enclave." + @echo "To sign the enclave use the command:" + @echo " $(SGX_ENCLAVE_SIGNER) sign -key -enclave $(Enclave_Name) -out <$(Signed_Enclave_Name)> -config $(Enclave_Config_File)" + @echo "You can also sign the enclave using an external signing tool." + @echo "To build the project in simulation mode set SGX_MODE=SIM. To build the project in prerelease mode set SGX_PRERELEASE=1 and SGX_MODE=HW." +else +all: $(App_Name) $(Signed_Enclave_Name) +ifeq ($(Build_Mode), HW_DEBUG) + @echo "The project has been built in debug hardware mode." +else ifeq ($(Build_Mode), SIM_DEBUG) + @echo "The project has been built in debug simulation mode." +else ifeq ($(Build_Mode), HW_PRERELEASE) + @echo "The project has been built in pre-release hardware mode." +else ifeq ($(Build_Mode), SIM_PRERELEASE) + @echo "The project has been built in pre-release simulation mode." +else + @echo "The project has been built in release simulation mode." +endif +endif + +run: all +ifneq ($(Build_Mode), HW_RELEASE) + @$(CURDIR)/$(App_Name) + @echo "RUN => $(App_Name) [$(SGX_MODE)|$(SGX_ARCH), OK]" +endif + +######## App Objects ######## + +App/Enclave_u.c: $(SGX_EDGER8R) Enclave/Enclave.edl + @cd App && $(SGX_EDGER8R) --untrusted ../Enclave/Enclave.edl --search-path ../Enclave --search-path $(SGX_SDK)/include + @echo "GEN => $@" + +App/Enclave_u.o: App/Enclave_u.c + @$(CC) $(App_C_Flags) -c $< -o $@ + @echo "CC <= $<" + +App/%.o: App/%.cpp + @$(CXX) $(App_Cpp_Flags) -c $< -o $@ + @echo "CXX <= $<" + +$(App_Name): App/Enclave_u.o $(App_Cpp_Objects) + @$(CXX) $^ -o $@ $(App_Link_Flags) + @echo "LINK => $@" + + +######## Enclave Objects ######## + +Enclave/Enclave_t.c: $(SGX_EDGER8R) Enclave/Enclave.edl + @cd Enclave && $(SGX_EDGER8R) --trusted ../Enclave/Enclave.edl --search-path ../Enclave --search-path $(SGX_SDK)/include + @echo "GEN => $@" + +Enclave/Enclave_t.o: Enclave/Enclave_t.c + @$(CC) $(Enclave_C_Flags) -c $< -o $@ + @echo "CC <= $<" + +Enclave/%.o: Enclave/%.cpp + @$(CXX) $(Enclave_Cpp_Flags) -c $< -o $@ + @echo "CXX <= $<" + +$(Enclave_Name): Enclave/Enclave_t.o $(Enclave_Cpp_Objects) + @$(CXX) $^ -o $@ $(Enclave_Link_Flags) + @echo "LINK => $@" + +$(Signed_Enclave_Name): $(Enclave_Name) + @$(SGX_ENCLAVE_SIGNER) sign -key Enclave/Enclave_private.pem -enclave $(Enclave_Name) -out $@ -config $(Enclave_Config_File) + @echo "SIGN => $@" + +.PHONY: clean + +clean: + @rm -f $(App_Name) $(Enclave_Name) $(Signed_Enclave_Name) $(App_Cpp_Objects) App/Enclave_u.* $(Enclave_Cpp_Objects) Enclave/Enclave_t.* diff --git a/sgx-jvm/linux-sgx/SampleCode/SampleEnclave/README.txt b/sgx-jvm/linux-sgx/SampleCode/SampleEnclave/README.txt new file mode 100644 index 0000000000..3ecd3c3ac3 --- /dev/null +++ b/sgx-jvm/linux-sgx/SampleCode/SampleEnclave/README.txt @@ -0,0 +1,30 @@ +------------------------ +Purpose of SampleEnclave +------------------------ +The project demonstrates several fundamental usages of Intel(R) Software Guard +Extensions (SGX) SDK: +- Initializing and destroying an enclave +- Creating ECALLs or OCALLs +- Calling trusted libraries inside the enclave + +------------------------------------ +How to Build/Execute the Sample Code +------------------------------------ +1. Install Intel(R) SGX SDK for Linux* OS +2. Build the project with the prepared Makefile: + a. Hardware Mode, Debug build: + $ make + b. Hardware Mode, Pre-release build: + $ make SGX_PRERELEASE=1 SGX_DEBUG=0 + c. Hardware Mode, Release build: + $ make SGX_DEBUG=0 + d. Simulation Mode, Debug build: + $ make SGX_MODE=SIM + e. Simulation Mode, Pre-release build: + $ make SGX_MODE=SIM SGX_PRERELEASE=1 SGX_DEBUG=0 + f. Simulation Mode, Release build: + $ make SGX_MODE=SIM SGX_DEBUG=0 +3. Execute the binary directly: + $ ./app +4. Remember to "make clean" before switching build mode + diff --git a/sgx-jvm/linux-sgx/build-scripts/enclave.lds b/sgx-jvm/linux-sgx/build-scripts/enclave.lds new file mode 100644 index 0000000000..975b185f3c --- /dev/null +++ b/sgx-jvm/linux-sgx/build-scripts/enclave.lds @@ -0,0 +1,9 @@ +{ +global: + enclave_entry; + g_global_data_sim; + g_peak_heap_used; + g_global_data; +local: + *; +}; diff --git a/sgx-jvm/linux-sgx/buildenv.mk b/sgx-jvm/linux-sgx/buildenv.mk new file mode 100644 index 0000000000..560e000ce0 --- /dev/null +++ b/sgx-jvm/linux-sgx/buildenv.mk @@ -0,0 +1,183 @@ +# +# Copyright (C) 2011-2016 Intel Corporation. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# + +# ----------------------------------------------------------------------------- +# Function : parent-dir +# Arguments: 1: path +# Returns : Parent dir or path of $1, with final separator removed. +# ----------------------------------------------------------------------------- +parent-dir = $(patsubst %/,%,$(dir $(1:%/=%))) + +# ----------------------------------------------------------------------------- +# Macro : my-dir +# Returns : the directory of the current Makefile +# Usage : $(my-dir) +# ----------------------------------------------------------------------------- +my-dir = $(realpath $(call parent-dir,$(lastword $(MAKEFILE_LIST)))) + + +ROOT_DIR := $(call my-dir) +COMMON_DIR := $(ROOT_DIR)/common +LINUX_EXTERNAL_DIR := $(ROOT_DIR)/external +LINUX_PSW_DIR := $(ROOT_DIR)/psw +LINUX_SDK_DIR := $(ROOT_DIR)/sdk +LINUX_UNITTESTS := $(ROOT_DIR)/unittests + + +CP := /bin/cp -f +MKDIR := mkdir -p +STRIP := strip +OBJCOPY := objcopy + +# clean the content of 'INCLUDE' - this variable will be set by vcvars32.bat +# thus it will cause build error when this variable is used by our Makefile, +# when compiling the code under Cygwin tainted by MSVC environment settings. +INCLUDE := + +# this will return the path to the file that included the buildenv.mk file +CUR_DIR := $(realpath $(call parent-dir,$(lastword $(wordlist 2,$(words $(MAKEFILE_LIST)),x $(MAKEFILE_LIST))))) + +# turn on stack protector for SDK +COMMON_FLAGS += -fstack-protector + +ifdef DEBUG + COMMON_FLAGS += -ggdb -DDEBUG -UNDEBUG + COMMON_FLAGS += -DSE_DEBUG_LEVEL=SE_TRACE_DEBUG +else + COMMON_FLAGS += -O2 -UDEBUG -DNDEBUG +endif + +ifdef SE_SIM + COMMON_FLAGS += -DSE_SIM +endif + +# turn on compiler warnings as much as possible +COMMON_FLAGS += -Wall -Wextra -Winit-self -Wpointer-arith -Wreturn-type \ + -Waddress -Wsequence-point -Wformat-security \ + -Wmissing-include-dirs -Wfloat-equal -Wundef -Wshadow \ + -Wcast-align -Wconversion -Wredundant-decls + +# additional warnings flags for C +CFLAGS += -Wjump-misses-init -Wstrict-prototypes -Wunsuffixed-float-constants + +# additional warnings flags for C++ +CXXFLAGS += -Wnon-virtual-dtor + +# for static_assert() +CXXFLAGS += -std=c++0x + +# Disable cxx11 abi +CXXFLAGS += -D_GLIBCXX_USE_CXX11_ABI=0 + +.DEFAULT_GOAL := all +# this turns off the RCS / SCCS implicit rules of GNU Make +% : RCS/%,v +% : RCS/% +% : %,v +% : s.% +% : SCCS/s.% + +# If a rule fails, delete $@. +.DELETE_ON_ERROR: + +HOST_FILE_PROGRAM := file + +UNAME := $(shell uname -m) +ifneq (,$(findstring 86,$(UNAME))) + HOST_ARCH := x86 + ifneq (,$(shell $(HOST_FILE_PROGRAM) -L $(SHELL) | grep 'x86[_-]64')) + HOST_ARCH := x86_64 + endif +else + $(info Unknown host CPU arhitecture $(UNAME)) + $(error Aborting) +endif + +BUILD_DIR := $(ROOT_DIR)/build/linux + +ifeq "$(findstring __INTEL_COMPILER, $(shell $(CC) -E -dM -xc /dev/null))" "__INTEL_COMPILER" + ifeq ($(shell test -f /usr/bin/dpkg; echo $$?), 0) + ADDED_INC := -I /usr/include/$(shell dpkg-architecture -qDEB_BUILD_MULTIARCH) + endif +endif + +ARCH := $(HOST_ARCH) +ifeq "$(findstring -m32, $(CXXFLAGS))" "-m32" + ARCH := x86 +endif + +ifeq ($(ARCH), x86) +COMMON_FLAGS += -DITT_ARCH_IA32 +else +COMMON_FLAGS += -DITT_ARCH_IA64 +endif + +CFLAGS += $(COMMON_FLAGS) +CXXFLAGS += $(COMMON_FLAGS) + +# Compiler and linker options for an Enclave +# +# We are using '--export-dynamic' so that `g_global_data_sim' etc. +# will be exported to dynamic symbol table. +# +# When `pie' is enabled, the linker (both BFD and Gold) under Ubuntu 14.04 +# will hide all symbols from dynamic symbol table even if they are marked +# as `global' in the LD version script. +ENCLAVE_CFLAGS = -ffreestanding -nostdinc -fvisibility=hidden -fpie +ENCLAVE_CXXFLAGS = $(ENCLAVE_CFLAGS) -nostdinc++ +ENCLAVE_LDFLAGS = -Wl,-Bstatic -Wl,-Bsymbolic -Wl,--no-undefined \ + -Wl,-pie,-eenclave_entry -Wl,--export-dynamic \ + -Wl,--defsym,__ImageBase=0 + + +# Choose to use the optimized libraries (IPP/String/Math) by default. +# Users could also use the non-optimized source code version by +# explicitly specifying 'USE_OPT_LIBS=0' +USE_OPT_LIBS ?= 1 + +ifeq ($(ARCH), x86_64) +IPP_SUBDIR = intel64 +else +IPP_SUBDIR = ia32 +endif + +ifneq ($(USE_OPT_LIBS), 0) + SGX_IPP_DIR := $(ROOT_DIR)/external/ippcp_internal + SGX_IPP_INC := $(SGX_IPP_DIR)/inc + IPP_LIBS_DIR := $(SGX_IPP_DIR)/lib/linux/$(IPP_SUBDIR) + LD_IPP := -lippcp -lippcore +else + SGX_IPP_DIR := $(ROOT_DIR)/external/crypto_px + SGX_IPP_INC := $(SGX_IPP_DIR)/include + IPP_LIBS_DIR := $(SGX_IPP_DIR) + LD_IPP := -lcrypto_px +endif + diff --git a/sgx-jvm/linux-sgx/common/inc/internal/ae_ipp.h b/sgx-jvm/linux-sgx/common/inc/internal/ae_ipp.h new file mode 100644 index 0000000000..3fad09cdff --- /dev/null +++ b/sgx-jvm/linux-sgx/common/inc/internal/ae_ipp.h @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + + +#ifndef _AE_IPP_H +#define _AE_IPP_H + +#include "ippcore.h" +#include "ippcp.h" + +#endif diff --git a/sgx-jvm/linux-sgx/common/inc/internal/arch.h b/sgx-jvm/linux-sgx/common/inc/internal/arch.h new file mode 100644 index 0000000000..624276e920 --- /dev/null +++ b/sgx-jvm/linux-sgx/common/inc/internal/arch.h @@ -0,0 +1,298 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef _SE_ARCH_H_ +#define _SE_ARCH_H_ + +#include "inst.h" +#include "se_types.h" +#include "sgx_attributes.h" +#include "sgx_key.h" +#include "sgx_report.h" +#include "sgx_tcrypto.h" + +#define SE_PAGE_SIZE 0x1000 +#define TCS_SIZE SE_PAGE_SIZE + +#pragma pack(push, 1) + +#if !defined(__cplusplus) || defined(__INTEL_COMPILER) || (defined(SE_GNU) && !defined(__GXX_EXPERIMENTAL_CXX0X__)) +#define _ASSERT_CONCAT(a, b) a##b +#define ASSERT_CONCAT(a, b) _ASSERT_CONCAT(a, b) +#define se_static_assert(e) typedef char ASSERT_CONCAT(assert_line, __LINE__)[(e)?1:-1] +#else +#define se_static_assert(e) static_assert(e,#e) +#endif + +se_static_assert(sizeof(sgx_key_request_t) == 512); +se_static_assert(sizeof(sgx_target_info_t) == 512); + +/*SECS data structure*/ +typedef struct _secs_t +{ + uint64_t size; /* ( 0) Size of the enclave in bytes */ + PADDED_POINTER(void, base); /* ( 8) Base address of enclave */ + uint32_t ssa_frame_size; /* ( 16) size of 1 SSA frame in pages */ + sgx_misc_select_t misc_select; /* ( 20) Which fields defined in SSA.MISC */ +#define SECS_RESERVED1_LENGTH 24 + uint8_t reserved1[SECS_RESERVED1_LENGTH]; /* ( 24) reserved */ + sgx_attributes_t attributes; /* ( 48) ATTRIBUTES Flags Field */ + sgx_measurement_t mr_enclave; /* ( 64) Integrity Reg 0 - Enclave measurement */ +#define SECS_RESERVED2_LENGTH 32 + uint8_t reserved2[SECS_RESERVED2_LENGTH]; /* ( 96) reserved */ + sgx_measurement_t mr_signer; /* (128) Integrity Reg 1 - Enclave signing key */ +#define SECS_RESERVED3_LENGTH 96 + uint8_t reserved3[SECS_RESERVED3_LENGTH]; /* (160) reserved */ + sgx_prod_id_t isv_prod_id; /* (256) product ID of enclave */ + sgx_isv_svn_t isv_svn; /* (258) Security Version of the Enclave */ +#define SECS_RESERVED4_LENGTH 3836 + uint8_t reserved4[SECS_RESERVED4_LENGTH];/* (260) reserved */ +} secs_t; + +/* +TCS +flags definitions +*/ +#define DBGOPTIN 1 /* used by debugger */ + +typedef struct _tcs_t +{ + uint64_t reserved0; /* (0) */ + uint64_t flags; /* (8)bit 0: DBGOPTION */ + uint64_t ossa; /* (16)State Save Area */ + uint32_t cssa; /* (24)Current SSA slot */ + uint32_t nssa; /* (28)Number of SSA slots */ + uint64_t oentry; /* (32)Offset in enclave to which control is transferred on EENTER if enclave INACTIVE state */ + uint64_t reserved1; /* (40) */ + uint64_t ofs_base; /* (48)When added to the base address of the enclave, produces the base address FS segment inside the enclave */ + uint64_t ogs_base; /* (56)When added to the base address of the enclave, produces the base address GS segment inside the enclave */ + uint32_t ofs_limit; /* (64)Size to become the new FS limit in 32-bit mode */ + uint32_t ogs_limit; /* (68)Size to become the new GS limit in 32-bit mode */ +#define TCS_RESERVED_LENGTH 4024 + uint8_t reserved[TCS_RESERVED_LENGTH]; /* (72) */ +}tcs_t; + +se_static_assert(sizeof(tcs_t) == SE_PAGE_SIZE); + +/**************************************************************************** + * Definitions for SSA + ****************************************************************************/ +typedef struct _exit_info_t +{ + uint32_t vector:8; /* Exception number of exceptions reported inside enclave */ + uint32_t exit_type:3; /* 3: Hardware exceptions, 6: Software exceptions */ + uint32_t reserved:20; + uint32_t valid:1; /* 0: unsupported exceptions, 1: Supported exceptions */ +} exit_info_t; + +#define SE_VECTOR_DE 0 +#define SE_VECTOR_DB 1 +#define SE_VECTOR_BP 3 +#define SE_VECTOR_BR 5 +#define SE_VECTOR_UD 6 +#define SE_VECTOR_MF 16 +#define SE_VECTOR_AC 17 +#define SE_VECTOR_XM 19 + +typedef struct _ssa_gpr_t +{ + REGISTER( ax); /* (0) */ + REGISTER( cx); /* (8) */ + REGISTER( dx); /* (16) */ + REGISTER( bx); /* (24) */ + REGISTER( sp); /* (32) */ + REGISTER( bp); /* (40) */ + REGISTER( si); /* (48) */ + REGISTER( di); /* (56) */ + uint64_t r8; /* (64) */ + uint64_t r9; /* (72) */ + uint64_t r10; /* (80) */ + uint64_t r11; /* (88) */ + uint64_t r12; /* (96) */ + uint64_t r13; /* (104) */ + uint64_t r14; /* (112) */ + uint64_t r15; /* (120) */ + REGISTER(flags); /* (128) */ + REGISTER( ip); /* (136) */ + REGISTER( sp_u); /* (144) untrusted stack pointer. saved by EENTER */ + REGISTER( bp_u); /* (152) untrusted frame pointer. saved by EENTER */ + exit_info_t exit_info; /* (160) contain information for exits */ + uint32_t reserved; /* (164) padding to multiple of 8 bytes */ + uint64_t fs; /* (168) FS register */ + uint64_t gs; /* (176) GS register */ +} ssa_gpr_t; + +typedef uint64_t si_flags_t; + +#define SI_FLAG_NONE 0x0 +#define SI_FLAG_R 0x1 /* Read Access */ +#define SI_FLAG_W 0x2 /* Write Access */ +#define SI_FLAG_X 0x4 /* Execute Access */ +#define SI_FLAG_PT_LOW_BIT 0x8 /* PT low bit */ +#define SI_FLAG_PT_MASK (0xFF< +#include + +namespace { + template + void delete_ptrs_from_container(T& vec) + { + typename T::iterator iter = vec.begin(); + typename T::iterator end = vec.end(); + typename T::iterator this_iter; + + while (iter != end) + { + this_iter = iter; + ++iter; + delete *this_iter; + } + } + + /* Each pair is well-formed (p.first <= p.second) */ + template + bool is_overlap(const std::pair& p1, + const std::pair& p2) + { + assert(p1.first <= p1.second); + assert(p2.first <= p2.second); + + return ((p1.first <= p2.second) && (p2.first <= p1.second)); + } +} + +#endif diff --git a/sgx-jvm/linux-sgx/common/inc/internal/cpuid.h b/sgx-jvm/linux-sgx/common/inc/internal/cpuid.h new file mode 100644 index 0000000000..b3ee8f5db9 --- /dev/null +++ b/sgx-jvm/linux-sgx/common/inc/internal/cpuid.h @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef _CPUID_H_ +#define _CPUID_H_ + +#include "linux/cpuid_gnu.h" + + +#endif /* _CPUID_H_ */ diff --git a/sgx-jvm/linux-sgx/common/inc/internal/dh.h b/sgx-jvm/linux-sgx/common/inc/internal/dh.h new file mode 100644 index 0000000000..76c347f588 --- /dev/null +++ b/sgx-jvm/linux-sgx/common/inc/internal/dh.h @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + + +#ifndef _DH_H +#define _DH_H + +#include "utility.h" + +/*return true if encrypt message successfully */ +bool encrypt_msg(pse_message_t* pse_msg, uint8_t* data, sgx_key_128bit_t* authenticated_encryption_key); + +/*return true if decrypt message successfully */ +bool decrypt_msg(pse_message_t* pse_msg, uint8_t* data, sgx_key_128bit_t* authenticated_encryption_key); +#endif diff --git a/sgx-jvm/linux-sgx/common/inc/internal/driver_api.h b/sgx-jvm/linux-sgx/common/inc/internal/driver_api.h new file mode 100644 index 0000000000..c0e20232e7 --- /dev/null +++ b/sgx-jvm/linux-sgx/common/inc/internal/driver_api.h @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef _DRIVER_API_H_ +#define _DRIVER_API_H_ + +#include "arch.h" +#include "sgx_eid.h" + +/* +@enclave_id identify the unique enclave; +@start_addr is the linear address that driver allocate for app; +*/ +int create_enclave(secs_t *secs, sgx_enclave_id_t *enclave_id, void **start_addr); +/* +*@attr can be REMOVABLE +*/ +int add_enclave_page(sgx_enclave_id_t enclave_id, void *source, size_t offset, const sec_info_t &secinfo, uint32_t attr); +int init_enclave(sgx_enclave_id_t enclave_id, enclave_css_t *enclave_css, token_t *launch); +int destroy_enclave(sgx_enclave_id_t enclave_id); + +#endif diff --git a/sgx-jvm/linux-sgx/common/inc/internal/ecp_interface.h b/sgx-jvm/linux-sgx/common/inc/internal/ecp_interface.h new file mode 100644 index 0000000000..d3b7515cd5 --- /dev/null +++ b/sgx-jvm/linux-sgx/common/inc/internal/ecp_interface.h @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + + +#ifndef _ECP_INTERFACE_H +#define _ECP_INTERFACE_H + +#include "sgx_ecp_types.h" +#include "sgx_tcrypto.h" + +//Key Derivation Function ID : 0x0001 AES-CMAC Entropy Extraction and Key Expansion +const uint16_t AES_CMAC_KDF_ID = 0x0001; + +sgx_status_t derive_key( + const sgx_ec256_dh_shared_t* shared_key, + const char* label, + uint32_t label_length, + sgx_ec_key_128bit_t* derived_key); + +#ifndef INTERNAL_SGX_ERROR_CODE_CONVERTOR +#define INTERNAL_SGX_ERROR_CODE_CONVERTOR(x) if(x != SGX_ERROR_OUT_OF_MEMORY){x = SGX_ERROR_UNEXPECTED;} +#endif + +#endif + diff --git a/sgx-jvm/linux-sgx/common/inc/internal/elf_util.h b/sgx-jvm/linux-sgx/common/inc/internal/elf_util.h new file mode 100644 index 0000000000..408c42f642 --- /dev/null +++ b/sgx-jvm/linux-sgx/common/inc/internal/elf_util.h @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#ifndef _ELF_UTIL_H_ +#define _ELF_UTIL_H_ + +#include "elfheader/elf_common.h" +#include "elfheader/elfstructs.h" + +#ifndef __ELF_NATIVE_CLASS +# if defined(_M_X64) || defined(__x86_64) || defined(__amd64) +# include /* for UINT_MAX */ +# define __ELF_NATIVE_CLASS 64 +# else +# define __ELF_NATIVE_CLASS 32 +# endif +#endif + +#if __ELF_NATIVE_CLASS == 64 +# define Rel Rela + +# define RTS_DT_REL DT_RELA +# define RTS_DT_RELSZ DT_RELASZ +# define RTS_DT_RELENT DT_RELAENT +# else +# define RTS_DT_REL DT_REL +# define RTS_DT_RELSZ DT_RELSZ +# define RTS_DT_RELENT DT_RELENT +#endif + +/* We use this macro to refer to ELF types independent of the native wordsize. + `ElfW(TYPE)' is used in place of `Elf32_TYPE' or `Elf64_TYPE'. */ +#define ElfW(type) _ElfW (Elf, __ELF_NATIVE_CLASS, type) + +/* We use this macro to refer to ELF macro constants. For example, + `ELFW(R_SYM)' is used in place of `ELF32_R_SYM' or `ELF64_R_SYM'. */ +#define ELFW(type) _ElfW (ELF, __ELF_NATIVE_CLASS, type) + +#define _ElfW(e,w,t) _ElfW_1 (e, w, _##t) +#define _ElfW_1(e,w,t) e##w##t + +/* GNU header uses `JUMP_SLOT' while `JMP_SLOT' in FreeBSD. */ +#define R_X86_64_JUMP_SLOT R_X86_64_JMP_SLOT + +#endif diff --git a/sgx-jvm/linux-sgx/common/inc/internal/elfheader/README.txt b/sgx-jvm/linux-sgx/common/inc/internal/elfheader/README.txt new file mode 100644 index 0000000000..654a5ecadd --- /dev/null +++ b/sgx-jvm/linux-sgx/common/inc/internal/elfheader/README.txt @@ -0,0 +1,59 @@ +Note, the files `elf_common.h' and `elfstructs.h' are from FreeBSD. + git://github.com/freebsd/freebsd.git + +But with slight modifications shown below: + +diff --git a/sys/sys/elf_common.h b/sys/sys/elf_common.h +index 8f02ef1..7601abb 100644 +--- a/sys/sys/elf_common.h ++++ b/sys/sys/elf_common.h +@@ -30,6 +30,9 @@ + #ifndef _SYS_ELF_COMMON_H_ + #define _SYS_ELF_COMMON_H_ 1 + ++typedef uint32_t u_int32_t; ++typedef uint32_t Elf_Symndx; ++ + /* + * ELF definitions that are independent of architecture or word size. + */ +@@ -117,9 +120,6 @@ typedef struct { + #define ELFOSABI_ARM 97 /* ARM */ + #define ELFOSABI_STANDALONE 255 /* Standalone (embedded) application */ + +-#define ELFOSABI_SYSV ELFOSABI_NONE /* symbol used in old spec */ +-#define ELFOSABI_MONTEREY ELFOSABI_AIX /* Monterey */ +- + /* e_ident */ + #define IS_ELF(ehdr) ((ehdr).e_ident[EI_MAG0] == ELFMAG0 && \ + (ehdr).e_ident[EI_MAG1] == ELFMAG1 && \ +@@ -242,7 +242,6 @@ typedef struct { + #define EM_486 6 /* Intel i486. */ + #define EM_MIPS_RS4_BE 10 /* MIPS R4000 Big-Endian */ + #define EM_ALPHA_STD 41 /* Digital Alpha (standard value). */ +-#define EM_ALPHA 0x9026 /* Alpha (written in the absence of an ABI) */ + + /* Special section indexes. */ + #define SHN_UNDEF 0 /* Undefined, missing, irrelevant. */ +@@ -441,6 +440,8 @@ typedef struct { + #define DT_MOVETAB 0x6ffffefe /* move table */ + #define DT_SYMINFO 0x6ffffeff /* syminfo table */ + #define DT_ADDRRNGHI 0x6ffffeff ++#define DT_ADDRTAGIDX(tag) (DT_ADDRRNGHI - (tag)) /* Reverse order! */ ++#define DT_ADDRNUM 11 + + #define DT_VERSYM 0x6ffffff0 /* Address of versym section. */ + #define DT_RELACOUNT 0x6ffffff9 /* number of RELATIVE relocations */ +@@ -505,12 +506,9 @@ typedef struct { + #define STT_FILE 4 /* Source file. */ + #define STT_COMMON 5 /* Uninitialized common block. */ + #define STT_TLS 6 /* TLS object. */ +-#define STT_NUM 7 + #define STT_LOOS 10 /* Reserved range for operating system */ + #define STT_GNU_IFUNC 10 + #define STT_HIOS 12 /* specific semantics. */ +-#define STT_LOPROC 13 /* reserved range for processor */ +-#define STT_HIPROC 15 /* specific semantics. */ + + /* Symbol visibility - ELFNN_ST_VISIBILITY - st_other */ + #define STV_DEFAULT 0x0 /* Default visibility (see binding). */ diff --git a/sgx-jvm/linux-sgx/common/inc/internal/elfheader/elf_common.h b/sgx-jvm/linux-sgx/common/inc/internal/elfheader/elf_common.h new file mode 100644 index 0000000000..7601abb189 --- /dev/null +++ b/sgx-jvm/linux-sgx/common/inc/internal/elfheader/elf_common.h @@ -0,0 +1,975 @@ +/*- + * Copyright (c) 2000, 2001, 2008, 2011, David E. O'Brien + * Copyright (c) 1998 John D. Polstra. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _SYS_ELF_COMMON_H_ +#define _SYS_ELF_COMMON_H_ 1 + +typedef uint32_t u_int32_t; +typedef uint32_t Elf_Symndx; + +/* + * ELF definitions that are independent of architecture or word size. + */ + +/* + * Note header. The ".note" section contains an array of notes. Each + * begins with this header, aligned to a word boundary. Immediately + * following the note header is n_namesz bytes of name, padded to the + * next word boundary. Then comes n_descsz bytes of descriptor, again + * padded to a word boundary. The values of n_namesz and n_descsz do + * not include the padding. + */ + +typedef struct { + u_int32_t n_namesz; /* Length of name. */ + u_int32_t n_descsz; /* Length of descriptor. */ + u_int32_t n_type; /* Type of this note. */ +} Elf_Note; + +/* + * The header for GNU-style hash sections. + */ + +typedef struct { + u_int32_t gh_nbuckets; /* Number of hash buckets. */ + u_int32_t gh_symndx; /* First visible symbol in .dynsym. */ + u_int32_t gh_maskwords; /* #maskwords used in bloom filter. */ + u_int32_t gh_shift2; /* Bloom filter shift count. */ +} Elf_GNU_Hash_Header; + +/* Indexes into the e_ident array. Keep synced with + http://www.sco.com/developers/gabi/latest/ch4.eheader.html */ +#define EI_MAG0 0 /* Magic number, byte 0. */ +#define EI_MAG1 1 /* Magic number, byte 1. */ +#define EI_MAG2 2 /* Magic number, byte 2. */ +#define EI_MAG3 3 /* Magic number, byte 3. */ +#define EI_CLASS 4 /* Class of machine. */ +#define EI_DATA 5 /* Data format. */ +#define EI_VERSION 6 /* ELF format version. */ +#define EI_OSABI 7 /* Operating system / ABI identification */ +#define EI_ABIVERSION 8 /* ABI version */ +#define OLD_EI_BRAND 8 /* Start of architecture identification. */ +#define EI_PAD 9 /* Start of padding (per SVR4 ABI). */ +#define EI_NIDENT 16 /* Size of e_ident array. */ + +/* Values for the magic number bytes. */ +#define ELFMAG0 0x7f +#define ELFMAG1 'E' +#define ELFMAG2 'L' +#define ELFMAG3 'F' +#define ELFMAG "\177ELF" /* magic string */ +#define SELFMAG 4 /* magic string size */ + +/* Values for e_ident[EI_VERSION] and e_version. */ +#define EV_NONE 0 +#define EV_CURRENT 1 + +/* Values for e_ident[EI_CLASS]. */ +#define ELFCLASSNONE 0 /* Unknown class. */ +#define ELFCLASS32 1 /* 32-bit architecture. */ +#define ELFCLASS64 2 /* 64-bit architecture. */ + +/* Values for e_ident[EI_DATA]. */ +#define ELFDATANONE 0 /* Unknown data format. */ +#define ELFDATA2LSB 1 /* 2's complement little-endian. */ +#define ELFDATA2MSB 2 /* 2's complement big-endian. */ + +/* Values for e_ident[EI_OSABI]. */ +#define ELFOSABI_NONE 0 /* UNIX System V ABI */ +#define ELFOSABI_HPUX 1 /* HP-UX operating system */ +#define ELFOSABI_NETBSD 2 /* NetBSD */ +#define ELFOSABI_LINUX 3 /* GNU/Linux */ +#define ELFOSABI_HURD 4 /* GNU/Hurd */ +#define ELFOSABI_86OPEN 5 /* 86Open common IA32 ABI */ +#define ELFOSABI_SOLARIS 6 /* Solaris */ +#define ELFOSABI_AIX 7 /* AIX */ +#define ELFOSABI_IRIX 8 /* IRIX */ +#define ELFOSABI_FREEBSD 9 /* FreeBSD */ +#define ELFOSABI_TRU64 10 /* TRU64 UNIX */ +#define ELFOSABI_MODESTO 11 /* Novell Modesto */ +#define ELFOSABI_OPENBSD 12 /* OpenBSD */ +#define ELFOSABI_OPENVMS 13 /* Open VMS */ +#define ELFOSABI_NSK 14 /* HP Non-Stop Kernel */ +#define ELFOSABI_AROS 15 /* Amiga Research OS */ +#define ELFOSABI_ARM 97 /* ARM */ +#define ELFOSABI_STANDALONE 255 /* Standalone (embedded) application */ + +/* e_ident */ +#define IS_ELF(ehdr) ((ehdr).e_ident[EI_MAG0] == ELFMAG0 && \ + (ehdr).e_ident[EI_MAG1] == ELFMAG1 && \ + (ehdr).e_ident[EI_MAG2] == ELFMAG2 && \ + (ehdr).e_ident[EI_MAG3] == ELFMAG3) + +/* Values for e_type. */ +#define ET_NONE 0 /* Unknown type. */ +#define ET_REL 1 /* Relocatable. */ +#define ET_EXEC 2 /* Executable. */ +#define ET_DYN 3 /* Shared object. */ +#define ET_CORE 4 /* Core file. */ +#define ET_LOOS 0xfe00 /* First operating system specific. */ +#define ET_HIOS 0xfeff /* Last operating system-specific. */ +#define ET_LOPROC 0xff00 /* First processor-specific. */ +#define ET_HIPROC 0xffff /* Last processor-specific. */ + +/* Values for e_machine. */ +#define EM_NONE 0 /* Unknown machine. */ +#define EM_M32 1 /* AT&T WE32100. */ +#define EM_SPARC 2 /* Sun SPARC. */ +#define EM_386 3 /* Intel i386. */ +#define EM_68K 4 /* Motorola 68000. */ +#define EM_88K 5 /* Motorola 88000. */ +#define EM_860 7 /* Intel i860. */ +#define EM_MIPS 8 /* MIPS R3000 Big-Endian only. */ +#define EM_S370 9 /* IBM System/370. */ +#define EM_MIPS_RS3_LE 10 /* MIPS R3000 Little-Endian. */ +#define EM_PARISC 15 /* HP PA-RISC. */ +#define EM_VPP500 17 /* Fujitsu VPP500. */ +#define EM_SPARC32PLUS 18 /* SPARC v8plus. */ +#define EM_960 19 /* Intel 80960. */ +#define EM_PPC 20 /* PowerPC 32-bit. */ +#define EM_PPC64 21 /* PowerPC 64-bit. */ +#define EM_S390 22 /* IBM System/390. */ +#define EM_V800 36 /* NEC V800. */ +#define EM_FR20 37 /* Fujitsu FR20. */ +#define EM_RH32 38 /* TRW RH-32. */ +#define EM_RCE 39 /* Motorola RCE. */ +#define EM_ARM 40 /* ARM. */ +#define EM_SH 42 /* Hitachi SH. */ +#define EM_SPARCV9 43 /* SPARC v9 64-bit. */ +#define EM_TRICORE 44 /* Siemens TriCore embedded processor. */ +#define EM_ARC 45 /* Argonaut RISC Core. */ +#define EM_H8_300 46 /* Hitachi H8/300. */ +#define EM_H8_300H 47 /* Hitachi H8/300H. */ +#define EM_H8S 48 /* Hitachi H8S. */ +#define EM_H8_500 49 /* Hitachi H8/500. */ +#define EM_IA_64 50 /* Intel IA-64 Processor. */ +#define EM_MIPS_X 51 /* Stanford MIPS-X. */ +#define EM_COLDFIRE 52 /* Motorola ColdFire. */ +#define EM_68HC12 53 /* Motorola M68HC12. */ +#define EM_MMA 54 /* Fujitsu MMA. */ +#define EM_PCP 55 /* Siemens PCP. */ +#define EM_NCPU 56 /* Sony nCPU. */ +#define EM_NDR1 57 /* Denso NDR1 microprocessor. */ +#define EM_STARCORE 58 /* Motorola Star*Core processor. */ +#define EM_ME16 59 /* Toyota ME16 processor. */ +#define EM_ST100 60 /* STMicroelectronics ST100 processor. */ +#define EM_TINYJ 61 /* Advanced Logic Corp. TinyJ processor. */ +#define EM_X86_64 62 /* Advanced Micro Devices x86-64 */ +#define EM_AMD64 EM_X86_64 /* Advanced Micro Devices x86-64 (compat) */ +#define EM_PDSP 63 /* Sony DSP Processor. */ +#define EM_FX66 66 /* Siemens FX66 microcontroller. */ +#define EM_ST9PLUS 67 /* STMicroelectronics ST9+ 8/16 + microcontroller. */ +#define EM_ST7 68 /* STmicroelectronics ST7 8-bit + microcontroller. */ +#define EM_68HC16 69 /* Motorola MC68HC16 microcontroller. */ +#define EM_68HC11 70 /* Motorola MC68HC11 microcontroller. */ +#define EM_68HC08 71 /* Motorola MC68HC08 microcontroller. */ +#define EM_68HC05 72 /* Motorola MC68HC05 microcontroller. */ +#define EM_SVX 73 /* Silicon Graphics SVx. */ +#define EM_ST19 74 /* STMicroelectronics ST19 8-bit mc. */ +#define EM_VAX 75 /* Digital VAX. */ +#define EM_CRIS 76 /* Axis Communications 32-bit embedded + processor. */ +#define EM_JAVELIN 77 /* Infineon Technologies 32-bit embedded + processor. */ +#define EM_FIREPATH 78 /* Element 14 64-bit DSP Processor. */ +#define EM_ZSP 79 /* LSI Logic 16-bit DSP Processor. */ +#define EM_MMIX 80 /* Donald Knuth's educational 64-bit proc. */ +#define EM_HUANY 81 /* Harvard University machine-independent + object files. */ +#define EM_PRISM 82 /* SiTera Prism. */ +#define EM_AVR 83 /* Atmel AVR 8-bit microcontroller. */ +#define EM_FR30 84 /* Fujitsu FR30. */ +#define EM_D10V 85 /* Mitsubishi D10V. */ +#define EM_D30V 86 /* Mitsubishi D30V. */ +#define EM_V850 87 /* NEC v850. */ +#define EM_M32R 88 /* Mitsubishi M32R. */ +#define EM_MN10300 89 /* Matsushita MN10300. */ +#define EM_MN10200 90 /* Matsushita MN10200. */ +#define EM_PJ 91 /* picoJava. */ +#define EM_OPENRISC 92 /* OpenRISC 32-bit embedded processor. */ +#define EM_ARC_A5 93 /* ARC Cores Tangent-A5. */ +#define EM_XTENSA 94 /* Tensilica Xtensa Architecture. */ +#define EM_VIDEOCORE 95 /* Alphamosaic VideoCore processor. */ +#define EM_TMM_GPP 96 /* Thompson Multimedia General Purpose + Processor. */ +#define EM_NS32K 97 /* National Semiconductor 32000 series. */ +#define EM_TPC 98 /* Tenor Network TPC processor. */ +#define EM_SNP1K 99 /* Trebia SNP 1000 processor. */ +#define EM_ST200 100 /* STMicroelectronics ST200 microcontroller. */ +#define EM_IP2K 101 /* Ubicom IP2xxx microcontroller family. */ +#define EM_MAX 102 /* MAX Processor. */ +#define EM_CR 103 /* National Semiconductor CompactRISC + microprocessor. */ +#define EM_F2MC16 104 /* Fujitsu F2MC16. */ +#define EM_MSP430 105 /* Texas Instruments embedded microcontroller + msp430. */ +#define EM_BLACKFIN 106 /* Analog Devices Blackfin (DSP) processor. */ +#define EM_SE_C33 107 /* S1C33 Family of Seiko Epson processors. */ +#define EM_SEP 108 /* Sharp embedded microprocessor. */ +#define EM_ARCA 109 /* Arca RISC Microprocessor. */ +#define EM_UNICORE 110 /* Microprocessor series from PKU-Unity Ltd. + and MPRC of Peking University */ + +/* Non-standard or deprecated. */ +#define EM_486 6 /* Intel i486. */ +#define EM_MIPS_RS4_BE 10 /* MIPS R4000 Big-Endian */ +#define EM_ALPHA_STD 41 /* Digital Alpha (standard value). */ + +/* Special section indexes. */ +#define SHN_UNDEF 0 /* Undefined, missing, irrelevant. */ +#define SHN_LORESERVE 0xff00 /* First of reserved range. */ +#define SHN_LOPROC 0xff00 /* First processor-specific. */ +#define SHN_HIPROC 0xff1f /* Last processor-specific. */ +#define SHN_LOOS 0xff20 /* First operating system-specific. */ +#define SHN_HIOS 0xff3f /* Last operating system-specific. */ +#define SHN_ABS 0xfff1 /* Absolute values. */ +#define SHN_COMMON 0xfff2 /* Common data. */ +#define SHN_XINDEX 0xffff /* Escape -- index stored elsewhere. */ +#define SHN_HIRESERVE 0xffff /* Last of reserved range. */ + +/* sh_type */ +#define SHT_NULL 0 /* inactive */ +#define SHT_PROGBITS 1 /* program defined information */ +#define SHT_SYMTAB 2 /* symbol table section */ +#define SHT_STRTAB 3 /* string table section */ +#define SHT_RELA 4 /* relocation section with addends */ +#define SHT_HASH 5 /* symbol hash table section */ +#define SHT_DYNAMIC 6 /* dynamic section */ +#define SHT_NOTE 7 /* note section */ +#define SHT_NOBITS 8 /* no space section */ +#define SHT_REL 9 /* relocation section - no addends */ +#define SHT_SHLIB 10 /* reserved - purpose unknown */ +#define SHT_DYNSYM 11 /* dynamic symbol table section */ +#define SHT_INIT_ARRAY 14 /* Initialization function pointers. */ +#define SHT_FINI_ARRAY 15 /* Termination function pointers. */ +#define SHT_PREINIT_ARRAY 16 /* Pre-initialization function ptrs. */ +#define SHT_GROUP 17 /* Section group. */ +#define SHT_SYMTAB_SHNDX 18 /* Section indexes (see SHN_XINDEX). */ +#define SHT_LOOS 0x60000000 /* First of OS specific semantics */ +#define SHT_LOSUNW 0x6ffffff4 +#define SHT_SUNW_dof 0x6ffffff4 +#define SHT_SUNW_cap 0x6ffffff5 +#define SHT_SUNW_SIGNATURE 0x6ffffff6 +#define SHT_GNU_HASH 0x6ffffff6 +#define SHT_SUNW_ANNOTATE 0x6ffffff7 +#define SHT_SUNW_DEBUGSTR 0x6ffffff8 +#define SHT_SUNW_DEBUG 0x6ffffff9 +#define SHT_SUNW_move 0x6ffffffa +#define SHT_SUNW_COMDAT 0x6ffffffb +#define SHT_SUNW_syminfo 0x6ffffffc +#define SHT_SUNW_verdef 0x6ffffffd +#define SHT_GNU_verdef 0x6ffffffd /* Symbol versions provided */ +#define SHT_SUNW_verneed 0x6ffffffe +#define SHT_GNU_verneed 0x6ffffffe /* Symbol versions required */ +#define SHT_SUNW_versym 0x6fffffff +#define SHT_GNU_versym 0x6fffffff /* Symbol version table */ +#define SHT_HISUNW 0x6fffffff +#define SHT_HIOS 0x6fffffff /* Last of OS specific semantics */ +#define SHT_LOPROC 0x70000000 /* reserved range for processor */ +#define SHT_AMD64_UNWIND 0x70000001 /* unwind information */ +#define SHT_MIPS_REGINFO 0x70000006 +#define SHT_MIPS_OPTIONS 0x7000000d +#define SHT_MIPS_DWARF 0x7000001e /* MIPS gcc uses MIPS_DWARF */ +#define SHT_HIPROC 0x7fffffff /* specific section header types */ +#define SHT_LOUSER 0x80000000 /* reserved range for application */ +#define SHT_HIUSER 0xffffffff /* specific indexes */ + +/* Flags for sh_flags. */ +#define SHF_WRITE 0x1 /* Section contains writable data. */ +#define SHF_ALLOC 0x2 /* Section occupies memory. */ +#define SHF_EXECINSTR 0x4 /* Section contains instructions. */ +#define SHF_MERGE 0x10 /* Section may be merged. */ +#define SHF_STRINGS 0x20 /* Section contains strings. */ +#define SHF_INFO_LINK 0x40 /* sh_info holds section index. */ +#define SHF_LINK_ORDER 0x80 /* Special ordering requirements. */ +#define SHF_OS_NONCONFORMING 0x100 /* OS-specific processing required. */ +#define SHF_GROUP 0x200 /* Member of section group. */ +#define SHF_TLS 0x400 /* Section contains TLS data. */ +#define SHF_MASKOS 0x0ff00000 /* OS-specific semantics. */ +#define SHF_MASKPROC 0xf0000000 /* Processor-specific semantics. */ + +/* Values for p_type. */ +#define PT_NULL 0 /* Unused entry. */ +#define PT_LOAD 1 /* Loadable segment. */ +#define PT_DYNAMIC 2 /* Dynamic linking information segment. */ +#define PT_INTERP 3 /* Pathname of interpreter. */ +#define PT_NOTE 4 /* Auxiliary information. */ +#define PT_SHLIB 5 /* Reserved (not used). */ +#define PT_PHDR 6 /* Location of program header itself. */ +#define PT_TLS 7 /* Thread local storage segment */ +#define PT_LOOS 0x60000000 /* First OS-specific. */ +#define PT_SUNW_UNWIND 0x6464e550 /* amd64 UNWIND program header */ +#define PT_GNU_EH_FRAME 0x6474e550 +#define PT_GNU_STACK 0x6474e551 +#define PT_GNU_RELRO 0x6474e552 +#define PT_LOSUNW 0x6ffffffa +#define PT_SUNWBSS 0x6ffffffa /* Sun Specific segment */ +#define PT_SUNWSTACK 0x6ffffffb /* describes the stack segment */ +#define PT_SUNWDTRACE 0x6ffffffc /* private */ +#define PT_SUNWCAP 0x6ffffffd /* hard/soft capabilities segment */ +#define PT_HISUNW 0x6fffffff +#define PT_HIOS 0x6fffffff /* Last OS-specific. */ +#define PT_LOPROC 0x70000000 /* First processor-specific type. */ +#define PT_HIPROC 0x7fffffff /* Last processor-specific type. */ + +/* Values for p_flags. */ +#define PF_X 0x1 /* Executable. */ +#define PF_W 0x2 /* Writable. */ +#define PF_R 0x4 /* Readable. */ +#define PF_MASKOS 0x0ff00000 /* Operating system-specific. */ +#define PF_MASKPROC 0xf0000000 /* Processor-specific. */ + +/* Extended program header index. */ +#define PN_XNUM 0xffff + +/* Values for d_tag. */ +#define DT_NULL 0 /* Terminating entry. */ +#define DT_NEEDED 1 /* String table offset of a needed shared + library. */ +#define DT_PLTRELSZ 2 /* Total size in bytes of PLT relocations. */ +#define DT_PLTGOT 3 /* Processor-dependent address. */ +#define DT_HASH 4 /* Address of symbol hash table. */ +#define DT_STRTAB 5 /* Address of string table. */ +#define DT_SYMTAB 6 /* Address of symbol table. */ +#define DT_RELA 7 /* Address of ElfNN_Rela relocations. */ +#define DT_RELASZ 8 /* Total size of ElfNN_Rela relocations. */ +#define DT_RELAENT 9 /* Size of each ElfNN_Rela relocation entry. */ +#define DT_STRSZ 10 /* Size of string table. */ +#define DT_SYMENT 11 /* Size of each symbol table entry. */ +#define DT_INIT 12 /* Address of initialization function. */ +#define DT_FINI 13 /* Address of finalization function. */ +#define DT_SONAME 14 /* String table offset of shared object + name. */ +#define DT_RPATH 15 /* String table offset of library path. [sup] */ +#define DT_SYMBOLIC 16 /* Indicates "symbolic" linking. [sup] */ +#define DT_REL 17 /* Address of ElfNN_Rel relocations. */ +#define DT_RELSZ 18 /* Total size of ElfNN_Rel relocations. */ +#define DT_RELENT 19 /* Size of each ElfNN_Rel relocation. */ +#define DT_PLTREL 20 /* Type of relocation used for PLT. */ +#define DT_DEBUG 21 /* Reserved (not used). */ +#define DT_TEXTREL 22 /* Indicates there may be relocations in + non-writable segments. [sup] */ +#define DT_JMPREL 23 /* Address of PLT relocations. */ +#define DT_BIND_NOW 24 /* [sup] */ +#define DT_INIT_ARRAY 25 /* Address of the array of pointers to + initialization functions */ +#define DT_FINI_ARRAY 26 /* Address of the array of pointers to + termination functions */ +#define DT_INIT_ARRAYSZ 27 /* Size in bytes of the array of + initialization functions. */ +#define DT_FINI_ARRAYSZ 28 /* Size in bytes of the array of + termination functions. */ +#define DT_RUNPATH 29 /* String table offset of a null-terminated + library search path string. */ +#define DT_FLAGS 30 /* Object specific flag values. */ +#define DT_ENCODING 32 /* Values greater than or equal to DT_ENCODING + and less than DT_LOOS follow the rules for + the interpretation of the d_un union + as follows: even == 'd_ptr', odd == 'd_val' + or none */ +#define DT_PREINIT_ARRAY 32 /* Address of the array of pointers to + pre-initialization functions. */ +#define DT_PREINIT_ARRAYSZ 33 /* Size in bytes of the array of + pre-initialization functions. */ +#define DT_MAXPOSTAGS 34 /* number of positive tags */ +#define DT_LOOS 0x6000000d /* First OS-specific */ +#define DT_SUNW_AUXILIARY 0x6000000d /* symbol auxiliary name */ +#define DT_SUNW_RTLDINF 0x6000000e /* ld.so.1 info (private) */ +#define DT_SUNW_FILTER 0x6000000f /* symbol filter name */ +#define DT_SUNW_CAP 0x60000010 /* hardware/software */ +#define DT_HIOS 0x6ffff000 /* Last OS-specific */ + +/* + * DT_* entries which fall between DT_VALRNGHI & DT_VALRNGLO use the + * Dyn.d_un.d_val field of the Elf*_Dyn structure. + */ +#define DT_VALRNGLO 0x6ffffd00 +#define DT_CHECKSUM 0x6ffffdf8 /* elf checksum */ +#define DT_PLTPADSZ 0x6ffffdf9 /* pltpadding size */ +#define DT_MOVEENT 0x6ffffdfa /* move table entry size */ +#define DT_MOVESZ 0x6ffffdfb /* move table size */ +#define DT_FEATURE_1 0x6ffffdfc /* feature holder */ +#define DT_POSFLAG_1 0x6ffffdfd /* flags for DT_* entries, effecting */ + /* the following DT_* entry. */ + /* See DF_P1_* definitions */ +#define DT_SYMINSZ 0x6ffffdfe /* syminfo table size (in bytes) */ +#define DT_SYMINENT 0x6ffffdff /* syminfo entry size (in bytes) */ +#define DT_VALRNGHI 0x6ffffdff + +/* + * DT_* entries which fall between DT_ADDRRNGHI & DT_ADDRRNGLO use the + * Dyn.d_un.d_ptr field of the Elf*_Dyn structure. + * + * If any adjustment is made to the ELF object after it has been + * built, these entries will need to be adjusted. + */ +#define DT_ADDRRNGLO 0x6ffffe00 +#define DT_GNU_HASH 0x6ffffef5 /* GNU-style hash table */ +#define DT_CONFIG 0x6ffffefa /* configuration information */ +#define DT_DEPAUDIT 0x6ffffefb /* dependency auditing */ +#define DT_AUDIT 0x6ffffefc /* object auditing */ +#define DT_PLTPAD 0x6ffffefd /* pltpadding (sparcv9) */ +#define DT_MOVETAB 0x6ffffefe /* move table */ +#define DT_SYMINFO 0x6ffffeff /* syminfo table */ +#define DT_ADDRRNGHI 0x6ffffeff +#define DT_ADDRTAGIDX(tag) (DT_ADDRRNGHI - (tag)) /* Reverse order! */ +#define DT_ADDRNUM 11 + +#define DT_VERSYM 0x6ffffff0 /* Address of versym section. */ +#define DT_RELACOUNT 0x6ffffff9 /* number of RELATIVE relocations */ +#define DT_RELCOUNT 0x6ffffffa /* number of RELATIVE relocations */ +#define DT_FLAGS_1 0x6ffffffb /* state flags - see DF_1_* defs */ +#define DT_VERDEF 0x6ffffffc /* Address of verdef section. */ +#define DT_VERDEFNUM 0x6ffffffd /* Number of elems in verdef section */ +#define DT_VERNEED 0x6ffffffe /* Address of verneed section. */ +#define DT_VERNEEDNUM 0x6fffffff /* Number of elems in verneed section */ + +#define DT_LOPROC 0x70000000 /* First processor-specific type. */ +#define DT_DEPRECATED_SPARC_REGISTER 0x7000001 +#define DT_AUXILIARY 0x7ffffffd /* shared library auxiliary name */ +#define DT_USED 0x7ffffffe /* ignored - same as needed */ +#define DT_FILTER 0x7fffffff /* shared library filter name */ +#define DT_HIPROC 0x7fffffff /* Last processor-specific type. */ + +/* Values for DT_FLAGS */ +#define DF_ORIGIN 0x0001 /* Indicates that the object being loaded may + make reference to the $ORIGIN substitution + string */ +#define DF_SYMBOLIC 0x0002 /* Indicates "symbolic" linking. */ +#define DF_TEXTREL 0x0004 /* Indicates there may be relocations in + non-writable segments. */ +#define DF_BIND_NOW 0x0008 /* Indicates that the dynamic linker should + process all relocations for the object + containing this entry before transferring + control to the program. */ +#define DF_STATIC_TLS 0x0010 /* Indicates that the shared object or + executable contains code using a static + thread-local storage scheme. */ + +/* Values for DT_FLAGS_1 */ +#define DF_1_BIND_NOW 0x00000001 /* Same as DF_BIND_NOW */ +#define DF_1_GLOBAL 0x00000002 /* Set the RTLD_GLOBAL for object */ +#define DF_1_NODELETE 0x00000008 /* Set the RTLD_NODELETE for object */ +#define DF_1_LOADFLTR 0x00000010 /* Immediate loading of filtees */ +#define DF_1_NOOPEN 0x00000040 /* Do not allow loading on dlopen() */ +#define DF_1_ORIGIN 0x00000080 /* Process $ORIGIN */ +#define DF_1_NODEFLIB 0x00000800 /* Do not search default paths */ + +/* Values for n_type. Used in core files. */ +#define NT_PRSTATUS 1 /* Process status. */ +#define NT_FPREGSET 2 /* Floating point registers. */ +#define NT_PRPSINFO 3 /* Process state info. */ +#define NT_THRMISC 7 /* Thread miscellaneous info. */ + +/* Symbol Binding - ELFNN_ST_BIND - st_info */ +#define STB_LOCAL 0 /* Local symbol */ +#define STB_GLOBAL 1 /* Global symbol */ +#define STB_WEAK 2 /* like global - lower precedence */ +#define STB_LOOS 10 /* Reserved range for operating system */ +#define STB_HIOS 12 /* specific semantics. */ +#define STB_LOPROC 13 /* reserved range for processor */ +#define STB_HIPROC 15 /* specific semantics. */ + +/* Symbol type - ELFNN_ST_TYPE - st_info */ +#define STT_NOTYPE 0 /* Unspecified type. */ +#define STT_OBJECT 1 /* Data object. */ +#define STT_FUNC 2 /* Function. */ +#define STT_SECTION 3 /* Section. */ +#define STT_FILE 4 /* Source file. */ +#define STT_COMMON 5 /* Uninitialized common block. */ +#define STT_TLS 6 /* TLS object. */ +#define STT_LOOS 10 /* Reserved range for operating system */ +#define STT_GNU_IFUNC 10 +#define STT_HIOS 12 /* specific semantics. */ + +/* Symbol visibility - ELFNN_ST_VISIBILITY - st_other */ +#define STV_DEFAULT 0x0 /* Default visibility (see binding). */ +#define STV_INTERNAL 0x1 /* Special meaning in relocatable objects. */ +#define STV_HIDDEN 0x2 /* Not visible. */ +#define STV_PROTECTED 0x3 /* Visible but not preemptible. */ +#define STV_EXPORTED 0x4 +#define STV_SINGLETON 0x5 +#define STV_ELIMINATE 0x6 + +/* Special symbol table indexes. */ +#define STN_UNDEF 0 /* Undefined symbol index. */ + +/* Symbol versioning flags. */ +#define VER_DEF_CURRENT 1 +#define VER_DEF_IDX(x) VER_NDX(x) + +#define VER_FLG_BASE 0x01 +#define VER_FLG_WEAK 0x02 + +#define VER_NEED_CURRENT 1 +#define VER_NEED_WEAK (1u << 15) +#define VER_NEED_HIDDEN VER_NDX_HIDDEN +#define VER_NEED_IDX(x) VER_NDX(x) + +#define VER_NDX_LOCAL 0 +#define VER_NDX_GLOBAL 1 +#define VER_NDX_GIVEN 2 + +#define VER_NDX_HIDDEN (1u << 15) +#define VER_NDX(x) ((x) & ~(1u << 15)) + +#define CA_SUNW_NULL 0 +#define CA_SUNW_HW_1 1 /* first hardware capabilities entry */ +#define CA_SUNW_SF_1 2 /* first software capabilities entry */ + +/* + * Syminfo flag values + */ +#define SYMINFO_FLG_DIRECT 0x0001 /* symbol ref has direct association */ + /* to object containing defn. */ +#define SYMINFO_FLG_PASSTHRU 0x0002 /* ignored - see SYMINFO_FLG_FILTER */ +#define SYMINFO_FLG_COPY 0x0004 /* symbol is a copy-reloc */ +#define SYMINFO_FLG_LAZYLOAD 0x0008 /* object containing defn should be */ + /* lazily-loaded */ +#define SYMINFO_FLG_DIRECTBIND 0x0010 /* ref should be bound directly to */ + /* object containing defn. */ +#define SYMINFO_FLG_NOEXTDIRECT 0x0020 /* don't let an external reference */ + /* directly bind to this symbol */ +#define SYMINFO_FLG_FILTER 0x0002 /* symbol ref is associated to a */ +#define SYMINFO_FLG_AUXILIARY 0x0040 /* standard or auxiliary filter */ + +/* + * Syminfo.si_boundto values. + */ +#define SYMINFO_BT_SELF 0xffff /* symbol bound to self */ +#define SYMINFO_BT_PARENT 0xfffe /* symbol bound to parent */ +#define SYMINFO_BT_NONE 0xfffd /* no special symbol binding */ +#define SYMINFO_BT_EXTERN 0xfffc /* symbol defined as external */ +#define SYMINFO_BT_LOWRESERVE 0xff00 /* beginning of reserved entries */ + +/* + * Syminfo version values. + */ +#define SYMINFO_NONE 0 /* Syminfo version */ +#define SYMINFO_CURRENT 1 +#define SYMINFO_NUM 2 + +/* + * Relocation types. + * + * All machine architectures are defined here to allow tools on one to + * handle others. + */ + +#define R_386_NONE 0 /* No relocation. */ +#define R_386_32 1 /* Add symbol value. */ +#define R_386_PC32 2 /* Add PC-relative symbol value. */ +#define R_386_GOT32 3 /* Add PC-relative GOT offset. */ +#define R_386_PLT32 4 /* Add PC-relative PLT offset. */ +#define R_386_COPY 5 /* Copy data from shared object. */ +#define R_386_GLOB_DAT 6 /* Set GOT entry to data address. */ +#define R_386_JMP_SLOT 7 /* Set GOT entry to code address. */ +#define R_386_RELATIVE 8 /* Add load address of shared object. */ +#define R_386_GOTOFF 9 /* Add GOT-relative symbol address. */ +#define R_386_GOTPC 10 /* Add PC-relative GOT table address. */ +#define R_386_TLS_TPOFF 14 /* Negative offset in static TLS block */ +#define R_386_TLS_IE 15 /* Absolute address of GOT for -ve static TLS */ +#define R_386_TLS_GOTIE 16 /* GOT entry for negative static TLS block */ +#define R_386_TLS_LE 17 /* Negative offset relative to static TLS */ +#define R_386_TLS_GD 18 /* 32 bit offset to GOT (index,off) pair */ +#define R_386_TLS_LDM 19 /* 32 bit offset to GOT (index,zero) pair */ +#define R_386_TLS_GD_32 24 /* 32 bit offset to GOT (index,off) pair */ +#define R_386_TLS_GD_PUSH 25 /* pushl instruction for Sun ABI GD sequence */ +#define R_386_TLS_GD_CALL 26 /* call instruction for Sun ABI GD sequence */ +#define R_386_TLS_GD_POP 27 /* popl instruction for Sun ABI GD sequence */ +#define R_386_TLS_LDM_32 28 /* 32 bit offset to GOT (index,zero) pair */ +#define R_386_TLS_LDM_PUSH 29 /* pushl instruction for Sun ABI LD sequence */ +#define R_386_TLS_LDM_CALL 30 /* call instruction for Sun ABI LD sequence */ +#define R_386_TLS_LDM_POP 31 /* popl instruction for Sun ABI LD sequence */ +#define R_386_TLS_LDO_32 32 /* 32 bit offset from start of TLS block */ +#define R_386_TLS_IE_32 33 /* 32 bit offset to GOT static TLS offset entry */ +#define R_386_TLS_LE_32 34 /* 32 bit offset within static TLS block */ +#define R_386_TLS_DTPMOD32 35 /* GOT entry containing TLS index */ +#define R_386_TLS_DTPOFF32 36 /* GOT entry containing TLS offset */ +#define R_386_TLS_TPOFF32 37 /* GOT entry of -ve static TLS offset */ +#define R_386_IRELATIVE 42 /* PLT entry resolved indirectly at runtime */ + +#define R_ARM_NONE 0 /* No relocation. */ +#define R_ARM_PC24 1 +#define R_ARM_ABS32 2 +#define R_ARM_REL32 3 +#define R_ARM_PC13 4 +#define R_ARM_ABS16 5 +#define R_ARM_ABS12 6 +#define R_ARM_THM_ABS5 7 +#define R_ARM_ABS8 8 +#define R_ARM_SBREL32 9 +#define R_ARM_THM_PC22 10 +#define R_ARM_THM_PC8 11 +#define R_ARM_AMP_VCALL9 12 +#define R_ARM_SWI24 13 +#define R_ARM_THM_SWI8 14 +#define R_ARM_XPC25 15 +#define R_ARM_THM_XPC22 16 +/* TLS relocations */ +#define R_ARM_TLS_DTPMOD32 17 /* ID of module containing symbol */ +#define R_ARM_TLS_DTPOFF32 18 /* Offset in TLS block */ +#define R_ARM_TLS_TPOFF32 19 /* Offset in static TLS block */ +#define R_ARM_COPY 20 /* Copy data from shared object. */ +#define R_ARM_GLOB_DAT 21 /* Set GOT entry to data address. */ +#define R_ARM_JUMP_SLOT 22 /* Set GOT entry to code address. */ +#define R_ARM_RELATIVE 23 /* Add load address of shared object. */ +#define R_ARM_GOTOFF 24 /* Add GOT-relative symbol address. */ +#define R_ARM_GOTPC 25 /* Add PC-relative GOT table address. */ +#define R_ARM_GOT32 26 /* Add PC-relative GOT offset. */ +#define R_ARM_PLT32 27 /* Add PC-relative PLT offset. */ +#define R_ARM_GNU_VTENTRY 100 +#define R_ARM_GNU_VTINHERIT 101 +#define R_ARM_RSBREL32 250 +#define R_ARM_THM_RPC22 251 +#define R_ARM_RREL32 252 +#define R_ARM_RABS32 253 +#define R_ARM_RPC24 254 +#define R_ARM_RBASE 255 + +/* Name Value Field Calculation */ +#define R_IA_64_NONE 0 /* None */ +#define R_IA_64_IMM14 0x21 /* immediate14 S + A */ +#define R_IA_64_IMM22 0x22 /* immediate22 S + A */ +#define R_IA_64_IMM64 0x23 /* immediate64 S + A */ +#define R_IA_64_DIR32MSB 0x24 /* word32 MSB S + A */ +#define R_IA_64_DIR32LSB 0x25 /* word32 LSB S + A */ +#define R_IA_64_DIR64MSB 0x26 /* word64 MSB S + A */ +#define R_IA_64_DIR64LSB 0x27 /* word64 LSB S + A */ +#define R_IA_64_GPREL22 0x2a /* immediate22 @gprel(S + A) */ +#define R_IA_64_GPREL64I 0x2b /* immediate64 @gprel(S + A) */ +#define R_IA_64_GPREL32MSB 0x2c /* word32 MSB @gprel(S + A) */ +#define R_IA_64_GPREL32LSB 0x2d /* word32 LSB @gprel(S + A) */ +#define R_IA_64_GPREL64MSB 0x2e /* word64 MSB @gprel(S + A) */ +#define R_IA_64_GPREL64LSB 0x2f /* word64 LSB @gprel(S + A) */ +#define R_IA_64_LTOFF22 0x32 /* immediate22 @ltoff(S + A) */ +#define R_IA_64_LTOFF64I 0x33 /* immediate64 @ltoff(S + A) */ +#define R_IA_64_PLTOFF22 0x3a /* immediate22 @pltoff(S + A) */ +#define R_IA_64_PLTOFF64I 0x3b /* immediate64 @pltoff(S + A) */ +#define R_IA_64_PLTOFF64MSB 0x3e /* word64 MSB @pltoff(S + A) */ +#define R_IA_64_PLTOFF64LSB 0x3f /* word64 LSB @pltoff(S + A) */ +#define R_IA_64_FPTR64I 0x43 /* immediate64 @fptr(S + A) */ +#define R_IA_64_FPTR32MSB 0x44 /* word32 MSB @fptr(S + A) */ +#define R_IA_64_FPTR32LSB 0x45 /* word32 LSB @fptr(S + A) */ +#define R_IA_64_FPTR64MSB 0x46 /* word64 MSB @fptr(S + A) */ +#define R_IA_64_FPTR64LSB 0x47 /* word64 LSB @fptr(S + A) */ +#define R_IA_64_PCREL60B 0x48 /* immediate60 form1 S + A - P */ +#define R_IA_64_PCREL21B 0x49 /* immediate21 form1 S + A - P */ +#define R_IA_64_PCREL21M 0x4a /* immediate21 form2 S + A - P */ +#define R_IA_64_PCREL21F 0x4b /* immediate21 form3 S + A - P */ +#define R_IA_64_PCREL32MSB 0x4c /* word32 MSB S + A - P */ +#define R_IA_64_PCREL32LSB 0x4d /* word32 LSB S + A - P */ +#define R_IA_64_PCREL64MSB 0x4e /* word64 MSB S + A - P */ +#define R_IA_64_PCREL64LSB 0x4f /* word64 LSB S + A - P */ +#define R_IA_64_LTOFF_FPTR22 0x52 /* immediate22 @ltoff(@fptr(S + A)) */ +#define R_IA_64_LTOFF_FPTR64I 0x53 /* immediate64 @ltoff(@fptr(S + A)) */ +#define R_IA_64_LTOFF_FPTR32MSB 0x54 /* word32 MSB @ltoff(@fptr(S + A)) */ +#define R_IA_64_LTOFF_FPTR32LSB 0x55 /* word32 LSB @ltoff(@fptr(S + A)) */ +#define R_IA_64_LTOFF_FPTR64MSB 0x56 /* word64 MSB @ltoff(@fptr(S + A)) */ +#define R_IA_64_LTOFF_FPTR64LSB 0x57 /* word64 LSB @ltoff(@fptr(S + A)) */ +#define R_IA_64_SEGREL32MSB 0x5c /* word32 MSB @segrel(S + A) */ +#define R_IA_64_SEGREL32LSB 0x5d /* word32 LSB @segrel(S + A) */ +#define R_IA_64_SEGREL64MSB 0x5e /* word64 MSB @segrel(S + A) */ +#define R_IA_64_SEGREL64LSB 0x5f /* word64 LSB @segrel(S + A) */ +#define R_IA_64_SECREL32MSB 0x64 /* word32 MSB @secrel(S + A) */ +#define R_IA_64_SECREL32LSB 0x65 /* word32 LSB @secrel(S + A) */ +#define R_IA_64_SECREL64MSB 0x66 /* word64 MSB @secrel(S + A) */ +#define R_IA_64_SECREL64LSB 0x67 /* word64 LSB @secrel(S + A) */ +#define R_IA_64_REL32MSB 0x6c /* word32 MSB BD + A */ +#define R_IA_64_REL32LSB 0x6d /* word32 LSB BD + A */ +#define R_IA_64_REL64MSB 0x6e /* word64 MSB BD + A */ +#define R_IA_64_REL64LSB 0x6f /* word64 LSB BD + A */ +#define R_IA_64_LTV32MSB 0x74 /* word32 MSB S + A */ +#define R_IA_64_LTV32LSB 0x75 /* word32 LSB S + A */ +#define R_IA_64_LTV64MSB 0x76 /* word64 MSB S + A */ +#define R_IA_64_LTV64LSB 0x77 /* word64 LSB S + A */ +#define R_IA_64_PCREL21BI 0x79 /* immediate21 form1 S + A - P */ +#define R_IA_64_PCREL22 0x7a /* immediate22 S + A - P */ +#define R_IA_64_PCREL64I 0x7b /* immediate64 S + A - P */ +#define R_IA_64_IPLTMSB 0x80 /* function descriptor MSB special */ +#define R_IA_64_IPLTLSB 0x81 /* function descriptor LSB speciaal */ +#define R_IA_64_SUB 0x85 /* immediate64 A - S */ +#define R_IA_64_LTOFF22X 0x86 /* immediate22 special */ +#define R_IA_64_LDXMOV 0x87 /* immediate22 special */ +#define R_IA_64_TPREL14 0x91 /* imm14 @tprel(S + A) */ +#define R_IA_64_TPREL22 0x92 /* imm22 @tprel(S + A) */ +#define R_IA_64_TPREL64I 0x93 /* imm64 @tprel(S + A) */ +#define R_IA_64_TPREL64MSB 0x96 /* word64 MSB @tprel(S + A) */ +#define R_IA_64_TPREL64LSB 0x97 /* word64 LSB @tprel(S + A) */ +#define R_IA_64_LTOFF_TPREL22 0x9a /* imm22 @ltoff(@tprel(S+A)) */ +#define R_IA_64_DTPMOD64MSB 0xa6 /* word64 MSB @dtpmod(S + A) */ +#define R_IA_64_DTPMOD64LSB 0xa7 /* word64 LSB @dtpmod(S + A) */ +#define R_IA_64_LTOFF_DTPMOD22 0xaa /* imm22 @ltoff(@dtpmod(S+A)) */ +#define R_IA_64_DTPREL14 0xb1 /* imm14 @dtprel(S + A) */ +#define R_IA_64_DTPREL22 0xb2 /* imm22 @dtprel(S + A) */ +#define R_IA_64_DTPREL64I 0xb3 /* imm64 @dtprel(S + A) */ +#define R_IA_64_DTPREL32MSB 0xb4 /* word32 MSB @dtprel(S + A) */ +#define R_IA_64_DTPREL32LSB 0xb5 /* word32 LSB @dtprel(S + A) */ +#define R_IA_64_DTPREL64MSB 0xb6 /* word64 MSB @dtprel(S + A) */ +#define R_IA_64_DTPREL64LSB 0xb7 /* word64 LSB @dtprel(S + A) */ +#define R_IA_64_LTOFF_DTPREL22 0xba /* imm22 @ltoff(@dtprel(S+A)) */ + +#define R_MIPS_NONE 0 /* No reloc */ +#define R_MIPS_16 1 /* Direct 16 bit */ +#define R_MIPS_32 2 /* Direct 32 bit */ +#define R_MIPS_REL32 3 /* PC relative 32 bit */ +#define R_MIPS_26 4 /* Direct 26 bit shifted */ +#define R_MIPS_HI16 5 /* High 16 bit */ +#define R_MIPS_LO16 6 /* Low 16 bit */ +#define R_MIPS_GPREL16 7 /* GP relative 16 bit */ +#define R_MIPS_LITERAL 8 /* 16 bit literal entry */ +#define R_MIPS_GOT16 9 /* 16 bit GOT entry */ +#define R_MIPS_PC16 10 /* PC relative 16 bit */ +#define R_MIPS_CALL16 11 /* 16 bit GOT entry for function */ +#define R_MIPS_GPREL32 12 /* GP relative 32 bit */ +#define R_MIPS_GOTHI16 21 /* GOT HI 16 bit */ +#define R_MIPS_GOTLO16 22 /* GOT LO 16 bit */ +#define R_MIPS_CALLHI16 30 /* upper 16 bit GOT entry for function */ +#define R_MIPS_CALLLO16 31 /* lower 16 bit GOT entry for function */ + +#define R_PPC_NONE 0 /* No relocation. */ +#define R_PPC_ADDR32 1 +#define R_PPC_ADDR24 2 +#define R_PPC_ADDR16 3 +#define R_PPC_ADDR16_LO 4 +#define R_PPC_ADDR16_HI 5 +#define R_PPC_ADDR16_HA 6 +#define R_PPC_ADDR14 7 +#define R_PPC_ADDR14_BRTAKEN 8 +#define R_PPC_ADDR14_BRNTAKEN 9 +#define R_PPC_REL24 10 +#define R_PPC_REL14 11 +#define R_PPC_REL14_BRTAKEN 12 +#define R_PPC_REL14_BRNTAKEN 13 +#define R_PPC_GOT16 14 +#define R_PPC_GOT16_LO 15 +#define R_PPC_GOT16_HI 16 +#define R_PPC_GOT16_HA 17 +#define R_PPC_PLTREL24 18 +#define R_PPC_COPY 19 +#define R_PPC_GLOB_DAT 20 +#define R_PPC_JMP_SLOT 21 +#define R_PPC_RELATIVE 22 +#define R_PPC_LOCAL24PC 23 +#define R_PPC_UADDR32 24 +#define R_PPC_UADDR16 25 +#define R_PPC_REL32 26 +#define R_PPC_PLT32 27 +#define R_PPC_PLTREL32 28 +#define R_PPC_PLT16_LO 29 +#define R_PPC_PLT16_HI 30 +#define R_PPC_PLT16_HA 31 +#define R_PPC_SDAREL16 32 +#define R_PPC_SECTOFF 33 +#define R_PPC_SECTOFF_LO 34 +#define R_PPC_SECTOFF_HI 35 +#define R_PPC_SECTOFF_HA 36 + +/* + * 64-bit relocations + */ +#define R_PPC64_ADDR64 38 +#define R_PPC64_ADDR16_HIGHER 39 +#define R_PPC64_ADDR16_HIGHERA 40 +#define R_PPC64_ADDR16_HIGHEST 41 +#define R_PPC64_ADDR16_HIGHESTA 42 +#define R_PPC64_UADDR64 43 +#define R_PPC64_REL64 44 +#define R_PPC64_PLT64 45 +#define R_PPC64_PLTREL64 46 +#define R_PPC64_TOC16 47 +#define R_PPC64_TOC16_LO 48 +#define R_PPC64_TOC16_HI 49 +#define R_PPC64_TOC16_HA 50 +#define R_PPC64_TOC 51 +#define R_PPC64_DTPMOD64 68 +#define R_PPC64_TPREL64 73 +#define R_PPC64_DTPREL64 78 + +/* + * TLS relocations + */ +#define R_PPC_TLS 67 +#define R_PPC_DTPMOD32 68 +#define R_PPC_TPREL16 69 +#define R_PPC_TPREL16_LO 70 +#define R_PPC_TPREL16_HI 71 +#define R_PPC_TPREL16_HA 72 +#define R_PPC_TPREL32 73 +#define R_PPC_DTPREL16 74 +#define R_PPC_DTPREL16_LO 75 +#define R_PPC_DTPREL16_HI 76 +#define R_PPC_DTPREL16_HA 77 +#define R_PPC_DTPREL32 78 +#define R_PPC_GOT_TLSGD16 79 +#define R_PPC_GOT_TLSGD16_LO 80 +#define R_PPC_GOT_TLSGD16_HI 81 +#define R_PPC_GOT_TLSGD16_HA 82 +#define R_PPC_GOT_TLSLD16 83 +#define R_PPC_GOT_TLSLD16_LO 84 +#define R_PPC_GOT_TLSLD16_HI 85 +#define R_PPC_GOT_TLSLD16_HA 86 +#define R_PPC_GOT_TPREL16 87 +#define R_PPC_GOT_TPREL16_LO 88 +#define R_PPC_GOT_TPREL16_HI 89 +#define R_PPC_GOT_TPREL16_HA 90 + +/* + * The remaining relocs are from the Embedded ELF ABI, and are not in the + * SVR4 ELF ABI. + */ + +#define R_PPC_EMB_NADDR32 101 +#define R_PPC_EMB_NADDR16 102 +#define R_PPC_EMB_NADDR16_LO 103 +#define R_PPC_EMB_NADDR16_HI 104 +#define R_PPC_EMB_NADDR16_HA 105 +#define R_PPC_EMB_SDAI16 106 +#define R_PPC_EMB_SDA2I16 107 +#define R_PPC_EMB_SDA2REL 108 +#define R_PPC_EMB_SDA21 109 +#define R_PPC_EMB_MRKREF 110 +#define R_PPC_EMB_RELSEC16 111 +#define R_PPC_EMB_RELST_LO 112 +#define R_PPC_EMB_RELST_HI 113 +#define R_PPC_EMB_RELST_HA 114 +#define R_PPC_EMB_BIT_FLD 115 +#define R_PPC_EMB_RELSDA 116 + +#define R_SPARC_NONE 0 +#define R_SPARC_8 1 +#define R_SPARC_16 2 +#define R_SPARC_32 3 +#define R_SPARC_DISP8 4 +#define R_SPARC_DISP16 5 +#define R_SPARC_DISP32 6 +#define R_SPARC_WDISP30 7 +#define R_SPARC_WDISP22 8 +#define R_SPARC_HI22 9 +#define R_SPARC_22 10 +#define R_SPARC_13 11 +#define R_SPARC_LO10 12 +#define R_SPARC_GOT10 13 +#define R_SPARC_GOT13 14 +#define R_SPARC_GOT22 15 +#define R_SPARC_PC10 16 +#define R_SPARC_PC22 17 +#define R_SPARC_WPLT30 18 +#define R_SPARC_COPY 19 +#define R_SPARC_GLOB_DAT 20 +#define R_SPARC_JMP_SLOT 21 +#define R_SPARC_RELATIVE 22 +#define R_SPARC_UA32 23 +#define R_SPARC_PLT32 24 +#define R_SPARC_HIPLT22 25 +#define R_SPARC_LOPLT10 26 +#define R_SPARC_PCPLT32 27 +#define R_SPARC_PCPLT22 28 +#define R_SPARC_PCPLT10 29 +#define R_SPARC_10 30 +#define R_SPARC_11 31 +#define R_SPARC_64 32 +#define R_SPARC_OLO10 33 +#define R_SPARC_HH22 34 +#define R_SPARC_HM10 35 +#define R_SPARC_LM22 36 +#define R_SPARC_PC_HH22 37 +#define R_SPARC_PC_HM10 38 +#define R_SPARC_PC_LM22 39 +#define R_SPARC_WDISP16 40 +#define R_SPARC_WDISP19 41 +#define R_SPARC_GLOB_JMP 42 +#define R_SPARC_7 43 +#define R_SPARC_5 44 +#define R_SPARC_6 45 +#define R_SPARC_DISP64 46 +#define R_SPARC_PLT64 47 +#define R_SPARC_HIX22 48 +#define R_SPARC_LOX10 49 +#define R_SPARC_H44 50 +#define R_SPARC_M44 51 +#define R_SPARC_L44 52 +#define R_SPARC_REGISTER 53 +#define R_SPARC_UA64 54 +#define R_SPARC_UA16 55 +#define R_SPARC_TLS_GD_HI22 56 +#define R_SPARC_TLS_GD_LO10 57 +#define R_SPARC_TLS_GD_ADD 58 +#define R_SPARC_TLS_GD_CALL 59 +#define R_SPARC_TLS_LDM_HI22 60 +#define R_SPARC_TLS_LDM_LO10 61 +#define R_SPARC_TLS_LDM_ADD 62 +#define R_SPARC_TLS_LDM_CALL 63 +#define R_SPARC_TLS_LDO_HIX22 64 +#define R_SPARC_TLS_LDO_LOX10 65 +#define R_SPARC_TLS_LDO_ADD 66 +#define R_SPARC_TLS_IE_HI22 67 +#define R_SPARC_TLS_IE_LO10 68 +#define R_SPARC_TLS_IE_LD 69 +#define R_SPARC_TLS_IE_LDX 70 +#define R_SPARC_TLS_IE_ADD 71 +#define R_SPARC_TLS_LE_HIX22 72 +#define R_SPARC_TLS_LE_LOX10 73 +#define R_SPARC_TLS_DTPMOD32 74 +#define R_SPARC_TLS_DTPMOD64 75 +#define R_SPARC_TLS_DTPOFF32 76 +#define R_SPARC_TLS_DTPOFF64 77 +#define R_SPARC_TLS_TPOFF32 78 +#define R_SPARC_TLS_TPOFF64 79 + +#define R_X86_64_NONE 0 /* No relocation. */ +#define R_X86_64_64 1 /* Add 64 bit symbol value. */ +#define R_X86_64_PC32 2 /* PC-relative 32 bit signed sym value. */ +#define R_X86_64_GOT32 3 /* PC-relative 32 bit GOT offset. */ +#define R_X86_64_PLT32 4 /* PC-relative 32 bit PLT offset. */ +#define R_X86_64_COPY 5 /* Copy data from shared object. */ +#define R_X86_64_GLOB_DAT 6 /* Set GOT entry to data address. */ +#define R_X86_64_JMP_SLOT 7 /* Set GOT entry to code address. */ +#define R_X86_64_RELATIVE 8 /* Add load address of shared object. */ +#define R_X86_64_GOTPCREL 9 /* Add 32 bit signed pcrel offset to GOT. */ +#define R_X86_64_32 10 /* Add 32 bit zero extended symbol value */ +#define R_X86_64_32S 11 /* Add 32 bit sign extended symbol value */ +#define R_X86_64_16 12 /* Add 16 bit zero extended symbol value */ +#define R_X86_64_PC16 13 /* Add 16 bit signed extended pc relative symbol value */ +#define R_X86_64_8 14 /* Add 8 bit zero extended symbol value */ +#define R_X86_64_PC8 15 /* Add 8 bit signed extended pc relative symbol value */ +#define R_X86_64_DTPMOD64 16 /* ID of module containing symbol */ +#define R_X86_64_DTPOFF64 17 /* Offset in TLS block */ +#define R_X86_64_TPOFF64 18 /* Offset in static TLS block */ +#define R_X86_64_TLSGD 19 /* PC relative offset to GD GOT entry */ +#define R_X86_64_TLSLD 20 /* PC relative offset to LD GOT entry */ +#define R_X86_64_DTPOFF32 21 /* Offset in TLS block */ +#define R_X86_64_GOTTPOFF 22 /* PC relative offset to IE GOT entry */ +#define R_X86_64_TPOFF32 23 /* Offset in static TLS block */ +#define R_X86_64_IRELATIVE 37 + + +#endif /* !_SYS_ELF_COMMON_H_ */ diff --git a/sgx-jvm/linux-sgx/common/inc/internal/elfheader/elfstructs.h b/sgx-jvm/linux-sgx/common/inc/internal/elfheader/elfstructs.h new file mode 100644 index 0000000000..77362f3b9e --- /dev/null +++ b/sgx-jvm/linux-sgx/common/inc/internal/elfheader/elfstructs.h @@ -0,0 +1,527 @@ +#ifndef __XEN_PUBLIC_ELFSTRUCTS_H__ +#define __XEN_PUBLIC_ELFSTRUCTS_H__ 1 +/* + * Copyright (c) 1995, 1996 Erik Theisen. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +typedef uint8_t Elf_Byte; + +typedef uint32_t Elf32_Addr; /* Unsigned program address */ +typedef uint32_t Elf32_Off; /* Unsigned file offset */ +typedef int32_t Elf32_Sword; /* Signed large integer */ +typedef uint32_t Elf32_Word; /* Unsigned large integer */ +typedef uint16_t Elf32_Half; /* Unsigned medium integer */ + +typedef uint64_t Elf64_Addr; +typedef uint64_t Elf64_Off; +typedef int32_t Elf64_Shalf; + +typedef int32_t Elf64_Sword; +typedef uint32_t Elf64_Word; + +typedef int64_t Elf64_Sxword; +typedef uint64_t Elf64_Xword; + +typedef uint32_t Elf64_Half; +typedef uint16_t Elf64_Quarter; + +/* + * e_ident[] identification indexes + * See http://www.caldera.com/developers/gabi/2000-07-17/ch4.eheader.html + */ +#define EI_MAG0 0 /* file ID */ +#define EI_MAG1 1 /* file ID */ +#define EI_MAG2 2 /* file ID */ +#define EI_MAG3 3 /* file ID */ +#define EI_CLASS 4 /* file class */ +#define EI_DATA 5 /* data encoding */ +#define EI_VERSION 6 /* ELF header version */ +#define EI_OSABI 7 /* OS/ABI ID */ +#define EI_ABIVERSION 8 /* ABI version */ +#define EI_PAD 9 /* start of pad bytes */ +#define EI_NIDENT 16 /* Size of e_ident[] */ + +/* e_ident[] magic number */ +#define ELFMAG0 0x7f /* e_ident[EI_MAG0] */ +#define ELFMAG1 'E' /* e_ident[EI_MAG1] */ +#define ELFMAG2 'L' /* e_ident[EI_MAG2] */ +#define ELFMAG3 'F' /* e_ident[EI_MAG3] */ +#define ELFMAG "\177ELF" /* magic */ +#define SELFMAG 4 /* size of magic */ + +/* e_ident[] file class */ +#define ELFCLASSNONE 0 /* invalid */ +#define ELFCLASS32 1 /* 32-bit objs */ +#define ELFCLASS64 2 /* 64-bit objs */ +#define ELFCLASSNUM 3 /* number of classes */ + +/* e_ident[] data encoding */ +#define ELFDATANONE 0 /* invalid */ +#define ELFDATA2LSB 1 /* Little-Endian */ +#define ELFDATA2MSB 2 /* Big-Endian */ +#define ELFDATANUM 3 /* number of data encode defines */ + +/* e_ident[] Operating System/ABI */ +#define ELFOSABI_SYSV 0 /* UNIX System V ABI */ +#define ELFOSABI_HPUX 1 /* HP-UX operating system */ +#define ELFOSABI_NETBSD 2 /* NetBSD */ +#define ELFOSABI_LINUX 3 /* GNU/Linux */ +#define ELFOSABI_HURD 4 /* GNU/Hurd */ +#define ELFOSABI_86OPEN 5 /* 86Open common IA32 ABI */ +#define ELFOSABI_SOLARIS 6 /* Solaris */ +#define ELFOSABI_MONTEREY 7 /* Monterey */ +#define ELFOSABI_IRIX 8 /* IRIX */ +#define ELFOSABI_FREEBSD 9 /* FreeBSD */ +#define ELFOSABI_TRU64 10 /* TRU64 UNIX */ +#define ELFOSABI_MODESTO 11 /* Novell Modesto */ +#define ELFOSABI_OPENBSD 12 /* OpenBSD */ +#define ELFOSABI_ARM 97 /* ARM */ +#define ELFOSABI_STANDALONE 255 /* Standalone (embedded) application */ + +/* e_ident */ +#define IS_ELF(ehdr) ((ehdr).e_ident[EI_MAG0] == ELFMAG0 && \ + (ehdr).e_ident[EI_MAG1] == ELFMAG1 && \ + (ehdr).e_ident[EI_MAG2] == ELFMAG2 && \ + (ehdr).e_ident[EI_MAG3] == ELFMAG3) + +/* ELF Header */ +typedef struct elfhdr { + unsigned char e_ident[EI_NIDENT]; /* ELF Identification */ + Elf32_Half e_type; /* object file type */ + Elf32_Half e_machine; /* machine */ + Elf32_Word e_version; /* object file version */ + Elf32_Addr e_entry; /* virtual entry point */ + Elf32_Off e_phoff; /* program header table offset */ + Elf32_Off e_shoff; /* section header table offset */ + Elf32_Word e_flags; /* processor-specific flags */ + Elf32_Half e_ehsize; /* ELF header size */ + Elf32_Half e_phentsize; /* program header entry size */ + Elf32_Half e_phnum; /* number of program header entries */ + Elf32_Half e_shentsize; /* section header entry size */ + Elf32_Half e_shnum; /* number of section header entries */ + Elf32_Half e_shstrndx; /* section header table's "section + header string table" entry offset */ +} Elf32_Ehdr; + +typedef struct { + unsigned char e_ident[EI_NIDENT]; /* Id bytes */ + Elf64_Quarter e_type; /* file type */ + Elf64_Quarter e_machine; /* machine type */ + Elf64_Half e_version; /* version number */ + Elf64_Addr e_entry; /* entry point */ + Elf64_Off e_phoff; /* Program hdr offset */ + Elf64_Off e_shoff; /* Section hdr offset */ + Elf64_Half e_flags; /* Processor flags */ + Elf64_Quarter e_ehsize; /* sizeof ehdr */ + Elf64_Quarter e_phentsize; /* Program header entry size */ + Elf64_Quarter e_phnum; /* Number of program headers */ + Elf64_Quarter e_shentsize; /* Section header entry size */ + Elf64_Quarter e_shnum; /* Number of section headers */ + Elf64_Quarter e_shstrndx; /* String table index */ +} Elf64_Ehdr; + +/* e_type */ +#define ET_NONE 0 /* No file type */ +#define ET_REL 1 /* relocatable file */ +#define ET_EXEC 2 /* executable file */ +#define ET_DYN 3 /* shared object file */ +#define ET_CORE 4 /* core file */ +#define ET_NUM 5 /* number of types */ +#define ET_LOPROC 0xff00 /* reserved range for processor */ +#define ET_HIPROC 0xffff /* specific e_type */ + +/* e_machine */ +#define EM_NONE 0 /* No Machine */ +#define EM_M32 1 /* AT&T WE 32100 */ +#define EM_SPARC 2 /* SPARC */ +#define EM_386 3 /* Intel 80386 */ +#define EM_68K 4 /* Motorola 68000 */ +#define EM_88K 5 /* Motorola 88000 */ +#define EM_486 6 /* Intel 80486 - unused? */ +#define EM_860 7 /* Intel 80860 */ +#define EM_MIPS 8 /* MIPS R3000 Big-Endian only */ +/* + * Don't know if EM_MIPS_RS4_BE, + * EM_SPARC64, EM_PARISC, + * or EM_PPC are ABI compliant + */ +#define EM_MIPS_RS4_BE 10 /* MIPS R4000 Big-Endian */ +#define EM_SPARC64 11 /* SPARC v9 64-bit unoffical */ +#define EM_PARISC 15 /* HPPA */ +#define EM_SPARC32PLUS 18 /* Enhanced instruction set SPARC */ +#define EM_PPC 20 /* PowerPC */ +#define EM_PPC64 21 /* PowerPC 64-bit */ +#define EM_ARM 40 /* Advanced RISC Machines ARM */ +#define EM_ALPHA 41 /* DEC ALPHA */ +#define EM_SPARCV9 43 /* SPARC version 9 */ +#define EM_ALPHA_EXP 0x9026 /* DEC ALPHA */ +#define EM_IA_64 50 /* Intel Merced */ +#define EM_X86_64 62 /* AMD x86-64 architecture */ +#define EM_VAX 75 /* DEC VAX */ + +/* Version */ +#define EV_NONE 0 /* Invalid */ +#define EV_CURRENT 1 /* Current */ +#define EV_NUM 2 /* number of versions */ + +/* Section Header */ +typedef struct { + Elf32_Word sh_name; /* name - index into section header + string table section */ + Elf32_Word sh_type; /* type */ + Elf32_Word sh_flags; /* flags */ + Elf32_Addr sh_addr; /* address */ + Elf32_Off sh_offset; /* file offset */ + Elf32_Word sh_size; /* section size */ + Elf32_Word sh_link; /* section header table index link */ + Elf32_Word sh_info; /* extra information */ + Elf32_Word sh_addralign; /* address alignment */ + Elf32_Word sh_entsize; /* section entry size */ +} Elf32_Shdr; + +typedef struct { + Elf64_Half sh_name; /* section name */ + Elf64_Half sh_type; /* section type */ + Elf64_Xword sh_flags; /* section flags */ + Elf64_Addr sh_addr; /* virtual address */ + Elf64_Off sh_offset; /* file offset */ + Elf64_Xword sh_size; /* section size */ + Elf64_Half sh_link; /* link to another */ + Elf64_Half sh_info; /* misc info */ + Elf64_Xword sh_addralign; /* memory alignment */ + Elf64_Xword sh_entsize; /* table entry size */ +} Elf64_Shdr; + +/* Special Section Indexes */ +#define SHN_UNDEF 0 /* undefined */ +#define SHN_LORESERVE 0xff00 /* lower bounds of reserved indexes */ +#define SHN_LOPROC 0xff00 /* reserved range for processor */ +#define SHN_HIPROC 0xff1f /* specific section indexes */ +#define SHN_ABS 0xfff1 /* absolute value */ +#define SHN_COMMON 0xfff2 /* common symbol */ +#define SHN_HIRESERVE 0xffff /* upper bounds of reserved indexes */ + +/* sh_type */ +#define SHT_NULL 0 /* inactive */ +#define SHT_PROGBITS 1 /* program defined information */ +#define SHT_SYMTAB 2 /* symbol table section */ +#define SHT_STRTAB 3 /* string table section */ +#define SHT_RELA 4 /* relocation section with addends*/ +#define SHT_HASH 5 /* symbol hash table section */ +#define SHT_DYNAMIC 6 /* dynamic section */ +#define SHT_NOTE 7 /* note section */ +#define SHT_NOBITS 8 /* no space section */ +#define SHT_REL 9 /* relation section without addends */ +#define SHT_SHLIB 10 /* reserved - purpose unknown */ +#define SHT_DYNSYM 11 /* dynamic symbol table section */ +#define SHT_NUM 12 /* number of section types */ +#define SHT_LOPROC 0x70000000 /* reserved range for processor */ +#define SHT_HIPROC 0x7fffffff /* specific section header types */ +#define SHT_LOUSER 0x80000000 /* reserved range for application */ +#define SHT_HIUSER 0xffffffff /* specific indexes */ + +/* Section names */ +#define ELF_BSS ".bss" /* uninitialized data */ +#define ELF_DATA ".data" /* initialized data */ +#define ELF_DEBUG ".debug" /* debug */ +#define ELF_DYNAMIC ".dynamic" /* dynamic linking information */ +#define ELF_DYNSTR ".dynstr" /* dynamic string table */ +#define ELF_DYNSYM ".dynsym" /* dynamic symbol table */ +#define ELF_FINI ".fini" /* termination code */ +#define ELF_GOT ".got" /* global offset table */ +#define ELF_HASH ".hash" /* symbol hash table */ +#define ELF_INIT ".init" /* initialization code */ +#define ELF_REL_DATA ".rel.data" /* relocation data */ +#define ELF_REL_FINI ".rel.fini" /* relocation termination code */ +#define ELF_REL_INIT ".rel.init" /* relocation initialization code */ +#define ELF_REL_DYN ".rel.dyn" /* relocaltion dynamic link info */ +#define ELF_REL_RODATA ".rel.rodata" /* relocation read-only data */ +#define ELF_REL_TEXT ".rel.text" /* relocation code */ +#define ELF_RODATA ".rodata" /* read-only data */ +#define ELF_SHSTRTAB ".shstrtab" /* section header string table */ +#define ELF_STRTAB ".strtab" /* string table */ +#define ELF_SYMTAB ".symtab" /* symbol table */ +#define ELF_TEXT ".text" /* code */ + + +/* Section Attribute Flags - sh_flags */ +#define SHF_WRITE 0x1 /* Writable */ +#define SHF_ALLOC 0x2 /* occupies memory */ +#define SHF_EXECINSTR 0x4 /* executable */ +#define SHF_MASKPROC 0xf0000000 /* reserved bits for processor */ + /* specific section attributes */ + +/* Symbol Table Entry */ +typedef struct elf32_sym { + Elf32_Word st_name; /* name - index into string table */ + Elf32_Addr st_value; /* symbol value */ + Elf32_Word st_size; /* symbol size */ + unsigned char st_info; /* type and binding */ + unsigned char st_other; /* 0 - no defined meaning */ + Elf32_Half st_shndx; /* section header index */ +} Elf32_Sym; + +typedef struct { + Elf64_Half st_name; /* Symbol name index in str table */ + Elf_Byte st_info; /* type / binding attrs */ + Elf_Byte st_other; /* unused */ + Elf64_Quarter st_shndx; /* section index of symbol */ + Elf64_Xword st_value; /* value of symbol */ + Elf64_Xword st_size; /* size of symbol */ +} Elf64_Sym; + +/* Symbol table index */ +#define STN_UNDEF 0 /* undefined */ + +/* Extract symbol info - st_info */ +#define ELF32_ST_BIND(x) ((x) >> 4) +#define ELF32_ST_TYPE(x) (((unsigned int) x) & 0xf) +#define ELF32_ST_INFO(b,t) (((b) << 4) + ((t) & 0xf)) + +#define ELF64_ST_BIND(x) ((x) >> 4) +#define ELF64_ST_TYPE(x) (((unsigned int) x) & 0xf) +#define ELF64_ST_INFO(b,t) (((b) << 4) + ((t) & 0xf)) + +/* Symbol Binding - ELF32_ST_BIND - st_info */ +#define STB_LOCAL 0 /* Local symbol */ +#define STB_GLOBAL 1 /* Global symbol */ +#define STB_WEAK 2 /* like global - lower precedence */ +#define STB_NUM 3 /* number of symbol bindings */ +#define STB_LOPROC 13 /* reserved range for processor */ +#define STB_HIPROC 15 /* specific symbol bindings */ + +/* Symbol type - ELF32_ST_TYPE - st_info */ +#define STT_NOTYPE 0 /* not specified */ +#define STT_OBJECT 1 /* data object */ +#define STT_FUNC 2 /* function */ +#define STT_SECTION 3 /* section */ +#define STT_FILE 4 /* file */ +#define STT_NUM 5 /* number of symbol types */ +#define STT_LOPROC 13 /* reserved range for processor */ +#define STT_HIPROC 15 /* specific symbol types */ + +/* Relocation entry with implicit addend */ +typedef struct { + Elf32_Addr r_offset; /* offset of relocation */ + Elf32_Word r_info; /* symbol table index and type */ +} Elf32_Rel; + +/* Relocation entry with explicit addend */ +typedef struct { + Elf32_Addr r_offset; /* offset of relocation */ + Elf32_Word r_info; /* symbol table index and type */ + Elf32_Sword r_addend; +} Elf32_Rela; + +/* Extract relocation info - r_info */ +#define ELF32_R_SYM(i) ((i) >> 8) +#define ELF32_R_TYPE(i) ((unsigned char) (i)) +#define ELF32_R_INFO(s,t) (((s) << 8) + (unsigned char)(t)) + +typedef struct { + Elf64_Xword r_offset; /* where to do it */ + Elf64_Xword r_info; /* index & type of relocation */ +} Elf64_Rel; + +typedef struct { + Elf64_Xword r_offset; /* where to do it */ + Elf64_Xword r_info; /* index & type of relocation */ + Elf64_Sxword r_addend; /* adjustment value */ +} Elf64_Rela; + +#define ELF64_R_SYM(info) ((info) >> 32) +#define ELF64_R_TYPE(info) ((info) & 0xFFFFFFFF) +#define ELF64_R_INFO(s,t) (((s) << 32) + (u_int32_t)(t)) + +/* Program Header */ +typedef struct { + Elf32_Word p_type; /* segment type */ + Elf32_Off p_offset; /* segment offset */ + Elf32_Addr p_vaddr; /* virtual address of segment */ + Elf32_Addr p_paddr; /* physical address - ignored? */ + Elf32_Word p_filesz; /* number of bytes in file for seg. */ + Elf32_Word p_memsz; /* number of bytes in mem. for seg. */ + Elf32_Word p_flags; /* flags */ + Elf32_Word p_align; /* memory alignment */ +} Elf32_Phdr; + +typedef struct { + Elf64_Half p_type; /* entry type */ + Elf64_Half p_flags; /* flags */ + Elf64_Off p_offset; /* offset */ + Elf64_Addr p_vaddr; /* virtual address */ + Elf64_Addr p_paddr; /* physical address */ + Elf64_Xword p_filesz; /* file size */ + Elf64_Xword p_memsz; /* memory size */ + Elf64_Xword p_align; /* memory & file alignment */ +} Elf64_Phdr; + +/* Segment types - p_type */ +#define PT_NULL 0 /* unused */ +#define PT_LOAD 1 /* loadable segment */ +#define PT_DYNAMIC 2 /* dynamic linking section */ +#define PT_INTERP 3 /* the RTLD */ +#define PT_NOTE 4 /* auxiliary information */ +#define PT_SHLIB 5 /* reserved - purpose undefined */ +#define PT_PHDR 6 /* program header */ +#define PT_NUM 7 /* Number of segment types */ +#define PT_LOPROC 0x70000000 /* reserved range for processor */ +#define PT_HIPROC 0x7fffffff /* specific segment types */ + +/* Segment flags - p_flags */ +#define PF_X 0x1 /* Executable */ +#define PF_W 0x2 /* Writable */ +#define PF_R 0x4 /* Readable */ +#define PF_MASKPROC 0xf0000000 /* reserved bits for processor */ + /* specific segment flags */ + +/* Dynamic structure */ +typedef struct { + Elf32_Sword d_tag; /* controls meaning of d_val */ + union { + Elf32_Word d_val; /* Multiple meanings - see d_tag */ + Elf32_Addr d_ptr; /* program virtual address */ + } d_un; +} Elf32_Dyn; + +typedef struct { + Elf64_Xword d_tag; /* controls meaning of d_val */ + union { + Elf64_Addr d_ptr; + Elf64_Xword d_val; + } d_un; +} Elf64_Dyn; + +/* Dynamic Array Tags - d_tag */ +#define DT_NULL 0 /* marks end of _DYNAMIC array */ +#define DT_NEEDED 1 /* string table offset of needed lib */ +#define DT_PLTRELSZ 2 /* size of relocation entries in PLT */ +#define DT_PLTGOT 3 /* address PLT/GOT */ +#define DT_HASH 4 /* address of symbol hash table */ +#define DT_STRTAB 5 /* address of string table */ +#define DT_SYMTAB 6 /* address of symbol table */ +#define DT_RELA 7 /* address of relocation table */ +#define DT_RELASZ 8 /* size of relocation table */ +#define DT_RELAENT 9 /* size of relocation entry */ +#define DT_STRSZ 10 /* size of string table */ +#define DT_SYMENT 11 /* size of symbol table entry */ +#define DT_INIT 12 /* address of initialization func. */ +#define DT_FINI 13 /* address of termination function */ +#define DT_SONAME 14 /* string table offset of shared obj */ +#define DT_RPATH 15 /* string table offset of library + search path */ +#define DT_SYMBOLIC 16 /* start sym search in shared obj. */ +#define DT_REL 17 /* address of rel. tbl. w addends */ +#define DT_RELSZ 18 /* size of DT_REL relocation table */ +#define DT_RELENT 19 /* size of DT_REL relocation entry */ +#define DT_PLTREL 20 /* PLT referenced relocation entry */ +#define DT_DEBUG 21 /* bugger */ +#define DT_TEXTREL 22 /* Allow rel. mod. to unwritable seg */ +#define DT_JMPREL 23 /* add. of PLT's relocation entries */ +#define DT_BIND_NOW 24 /* Bind now regardless of env setting */ +#define DT_NUM 25 /* Number used. */ +#define DT_LOPROC 0x70000000 /* reserved range for processor */ +#define DT_HIPROC 0x7fffffff /* specific dynamic array tags */ + +/* Standard ELF hashing function */ +unsigned int elf_hash(const unsigned char *name); + +/* + * Note Definitions + */ +typedef struct { + Elf32_Word namesz; + Elf32_Word descsz; + Elf32_Word type; +} Elf32_Note; + +typedef struct { + Elf64_Half namesz; + Elf64_Half descsz; + Elf64_Half type; +} Elf64_Note; + + +#if defined(ELFSIZE) +#define CONCAT(x,y) __CONCAT(x,y) +#define ELFNAME(x) CONCAT(elf,CONCAT(ELFSIZE,CONCAT(_,x))) +#define ELFNAME2(x,y) CONCAT(x,CONCAT(_elf,CONCAT(ELFSIZE,CONCAT(_,y)))) +#define ELFNAMEEND(x) CONCAT(x,CONCAT(_elf,ELFSIZE)) +#define ELFDEFNNAME(x) CONCAT(ELF,CONCAT(ELFSIZE,CONCAT(_,x))) +#endif + +#if defined(ELFSIZE) && (ELFSIZE == 32) +#define Elf_Ehdr Elf32_Ehdr +#define Elf_Phdr Elf32_Phdr +#define Elf_Shdr Elf32_Shdr +#define Elf_Sym Elf32_Sym +#define Elf_Rel Elf32_Rel +#define Elf_RelA Elf32_Rela +#define Elf_Dyn Elf32_Dyn +#define Elf_Word Elf32_Word +#define Elf_Sword Elf32_Sword +#define Elf_Addr Elf32_Addr +#define Elf_Off Elf32_Off +#define Elf_Nhdr Elf32_Nhdr +#define Elf_Note Elf32_Note + +#define ELF_R_SYM ELF32_R_SYM +#define ELF_R_TYPE ELF32_R_TYPE +#define ELF_R_INFO ELF32_R_INFO +#define ELFCLASS ELFCLASS32 + +#define ELF_ST_BIND ELF32_ST_BIND +#define ELF_ST_TYPE ELF32_ST_TYPE +#define ELF_ST_INFO ELF32_ST_INFO + +#define AuxInfo Aux32Info +#elif defined(ELFSIZE) && (ELFSIZE == 64) +#define Elf_Ehdr Elf64_Ehdr +#define Elf_Phdr Elf64_Phdr +#define Elf_Shdr Elf64_Shdr +#define Elf_Sym Elf64_Sym +#define Elf_Rel Elf64_Rel +#define Elf_RelA Elf64_Rela +#define Elf_Dyn Elf64_Dyn +#define Elf_Word Elf64_Word +#define Elf_Sword Elf64_Sword +#define Elf_Addr Elf64_Addr +#define Elf_Off Elf64_Off +#define Elf_Nhdr Elf64_Nhdr +#define Elf_Note Elf64_Note + +#define ELF_R_SYM ELF64_R_SYM +#define ELF_R_TYPE ELF64_R_TYPE +#define ELF_R_INFO ELF64_R_INFO +#define ELFCLASS ELFCLASS64 + +#define ELF_ST_BIND ELF64_ST_BIND +#define ELF_ST_TYPE ELF64_ST_TYPE +#define ELF_ST_INFO ELF64_ST_INFO + +#define AuxInfo Aux64Info +#endif + +#endif /* __XEN_PUBLIC_ELFSTRUCTS_H__ */ diff --git a/sgx-jvm/linux-sgx/common/inc/internal/enclave_creator.h b/sgx-jvm/linux-sgx/common/inc/internal/enclave_creator.h new file mode 100644 index 0000000000..c7f25088de --- /dev/null +++ b/sgx-jvm/linux-sgx/common/inc/internal/enclave_creator.h @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +/** + * File: enclave_creator.h + * Description: this header file defines the interface used by Enclave loader to create the Enclave + * + * The hardware, simulation and signing mode shall inherit from this class and + * implement all the virtual functions + */ + +#ifndef _ENCLAVE_CREATOR_H +#define _ENCLAVE_CREATOR_H + +#include "arch.h" +#include "sgx_eid.h" +#include "metadata.h" +#include "sgx_error.h" +#include "util.h" +#include "launch_checker.h" +#include "uncopyable.h" +#include +#include "file.h" + +// this is the interface to both hardware, simulation and signing mode +class EnclaveCreator : private Uncopyable +{ +public: + /* + @quote the EPC reserved; + @enclave_id identify the unique enclave; + @start_addr is the linear address allocated for Enclave; + */ + virtual int create_enclave(secs_t *secs, sgx_enclave_id_t *enclave_id, void **start_addr, bool ae = false) = 0; + /* + *@attr can be REMOVABLE + */ + virtual int add_enclave_page(sgx_enclave_id_t enclave_id, void *source, uint64_t offset, const sec_info_t &sinfo, uint32_t attr) = 0; + virtual int init_enclave(sgx_enclave_id_t enclave_id, enclave_css_t *enclave_css, SGXLaunchToken *lc, le_prd_css_file_t *prd_css_file = NULL) = 0; + virtual int destroy_enclave(sgx_enclave_id_t enclave_id, uint64_t enclave_size = 0) = 0; + virtual int initialize(sgx_enclave_id_t enclave_id) = 0; + virtual bool use_se_hw() const = 0; + + virtual int get_misc_attr(sgx_misc_attribute_t *sgx_misc_attr, metadata_t *metadata, SGXLaunchToken * const lc, uint32_t flag) = 0; + virtual bool get_plat_cap(sgx_misc_attribute_t *se_attr) = 0; +#ifdef SE_1P5_VERTICAL + virtual uint32_t handle_page_fault(uint64_t pf_address) { UNUSED(pf_address); return (uint32_t)SGX_ERROR_UNEXPECTED; } +#endif + // destructor + virtual ~EnclaveCreator() {}; +}; + +EnclaveCreator* get_enclave_creator(void); + +extern EnclaveCreator* g_enclave_creator; + +#endif diff --git a/sgx-jvm/linux-sgx/common/inc/internal/global_data.h b/sgx-jvm/linux-sgx/common/inc/internal/global_data.h new file mode 100644 index 0000000000..be1e97eec8 --- /dev/null +++ b/sgx-jvm/linux-sgx/common/inc/internal/global_data.h @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + + +/** + * File: global_data.h + * Description: + * The file defines the structure global_data_t. + */ + +#ifndef _TRTS_GLOBAL_DATA_H_ +#define _TRTS_GLOBAL_DATA_H_ + +#include "se_types.h" +#include "thread_data.h" + +typedef struct _global_data_t +{ + sys_word_t enclave_size; + sys_word_t heap_offset; + sys_word_t heap_size; + uint32_t thread_policy; + uint32_t reserved; + thread_data_t td_template; +} global_data_t; + +#define ENCLAVE_INIT_NOT_STARTED 0 +#define ENCLAVE_INIT_IN_PROGRESS 1 +#define ENCLAVE_INIT_DONE 2 +#define ENCLAVE_CRASHED 3 + +#ifdef __cplusplus +extern "C" { +#endif +extern SE_DECLSPEC_EXPORT global_data_t const volatile g_global_data; +extern uint32_t g_enclave_state; +extern uint8_t __ImageBase; + +#ifdef __cplusplus +} +#endif +#endif diff --git a/sgx-jvm/linux-sgx/common/inc/internal/global_init.h b/sgx-jvm/linux-sgx/common/inc/internal/global_init.h new file mode 100644 index 0000000000..d7a36530cb --- /dev/null +++ b/sgx-jvm/linux-sgx/common/inc/internal/global_init.h @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef GLOBAL_INIT_H +#define GLOBAL_INIT_H + +#include + + +#ifdef __cplusplus +extern "C" { +#endif + +void init_global_object(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/sgx-jvm/linux-sgx/common/inc/internal/inst.h b/sgx-jvm/linux-sgx/common/inc/internal/inst.h new file mode 100644 index 0000000000..cd09c5a939 --- /dev/null +++ b/sgx-jvm/linux-sgx/common/inc/internal/inst.h @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef _SE_ARCH_H_ +# error "never include inst.h directly; use arch.h instead." +#endif + + +#ifndef _SE_INST_H_ +#define _SE_INST_H_ + +#define ENCLU 0xd7010f + +typedef enum { + SE_EREPORT = 0x0, + SE_EGETKEY, + SE_EENTER, + SE_ERESUME, + SE_EEXIT, + SE_LAST_RING3, + + SE_ECREATE = 0x0, + SE_EADD, + SE_EINIT, + SE_EREMOVE, + SE_EDBGRD, + SE_EDBGWR, + SE_EEXTEND, + SE_LAST_RING0 +} se_opcode_t; + +#endif diff --git a/sgx-jvm/linux-sgx/common/inc/internal/ipp_wrapper.h b/sgx-jvm/linux-sgx/common/inc/internal/ipp_wrapper.h new file mode 100644 index 0000000000..242a041c3b --- /dev/null +++ b/sgx-jvm/linux-sgx/common/inc/internal/ipp_wrapper.h @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef _IPP_WRAPPER_H +#define _IPP_WRAPPER_H + +#include "ippcp.h" + +#ifndef SAFE_FREE_MM +#define SAFE_FREE_MM(ptr) {\ + if(ptr != NULL) \ + { \ + free(ptr); \ + ptr = NULL; \ + }} +#endif + +#ifndef ERROR_BREAK +#define ERROR_BREAK(x) if(x != ippStsNoErr){break;} +#endif +#ifndef NULL_BREAK +#define NULL_BREAK(x) if(!x){break;} +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +IppStatus newBN(const Ipp32u *data, int size_in_bytes, IppsBigNumState **p_new_BN); + +IppStatus create_rsa_priv1_key(int n_byte_size, int d_byte_size, const Ipp32u *n, const Ipp32u *d, IppsRSAPrivateKeyState **new_pri_key1); + +IppStatus create_rsa_priv2_key(int p_byte_size, const Ipp32u *p, const Ipp32u *q, + const Ipp32u *dmp1, const Ipp32u *dmq1, const Ipp32u *iqmp, + IppsRSAPrivateKeyState **new_pri_key2); + +IppStatus create_rsa_pub_key(int n_byte_size, int e_byte_size, const Ipp32u *n, const Ipp32u *e, IppsRSAPublicKeyState **new_pub_key); + +IppStatus create_validate_rsa_key_pair(int n_byte_size, int e_byte_size, const Ipp32u *n, const Ipp32u *d, const Ipp32u *e, const Ipp32u *p, const Ipp32u *q, + const Ipp32u *dmp1, const Ipp32u *dmq1, const Ipp32u *iqmp, + IppsRSAPrivateKeyState **new_pri_key, IppsRSAPublicKeyState **new_pub_key, int *validate_result); + +IppStatus get_pub_key(const IppsRSAPublicKeyState *pub_key, int *e_byte_size, Ipp32u *e, int *n_byte_size, Ipp32u *n); + +void secure_free_BN(IppsBigNumState *pBN, int size_in_bytes); + +void secure_free_rsa_pri1_key(int n_byte_size, int d_byte_size, IppsRSAPrivateKeyState *pri_key1); + +void secure_free_rsa_pri2_key(int p_byte_size, IppsRSAPrivateKeyState *pri_key2); + +void secure_free_rsa_pub_key(int n_byte_size, int e_byte_size, IppsRSAPublicKeyState *pub_key); + + + +#ifdef __cplusplus +} +#endif + +#endif + + diff --git a/sgx-jvm/linux-sgx/common/inc/internal/linux/cpuid_gnu.h b/sgx-jvm/linux-sgx/common/inc/internal/linux/cpuid_gnu.h new file mode 100644 index 0000000000..5fd907162f --- /dev/null +++ b/sgx-jvm/linux-sgx/common/inc/internal/linux/cpuid_gnu.h @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef _CPUID_GNU_H_ +#define _CPUID_GNU_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/* This is a PIC-compliant version of CPUID */ +static inline void cpuid(int *eax, int *ebx, int *ecx, int *edx) +{ +#if defined(__x86_64__) + asm("cpuid" + : "=a" (*eax), + "=b" (*ebx), + "=c" (*ecx), + "=d" (*edx) + : "0" (*eax), "2" (*ecx)); + +#else + /*on 32bit, ebx can NOT be used as PIC code*/ + asm volatile ("xchgl %%ebx, %1; cpuid; xchgl %%ebx, %1" + : "=a" (*eax), "=r" (*ebx), "=c" (*ecx), "=d" (*edx) + : "0" (*eax), "2" (*ecx)); +#endif +} + +static inline void __cpuid(int a[4], int b) +{ + a[0] = b; + a[2] = 0; + cpuid(&a[0], &a[1], &a[2], &a[3]); +} + +static inline void __cpuidex(int a[4], int b, int c) +{ + a[0] = b; + a[2] = c; + cpuid(&a[0], &a[1], &a[2], &a[3]); +} + +#ifdef __cplusplus +} +#endif + +#endif /*_CPUID_GNU_H_*/ diff --git a/sgx-jvm/linux-sgx/common/inc/internal/linux/linux-regs.h b/sgx-jvm/linux-sgx/common/inc/internal/linux/linux-regs.h new file mode 100644 index 0000000000..1ebed38720 --- /dev/null +++ b/sgx-jvm/linux-sgx/common/inc/internal/linux/linux-regs.h @@ -0,0 +1,272 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +/* + * This header wraps the register names for x86/x64. + */ + +#ifndef LINUX_REGS_H__ +#define LINUX_REGS_H__ + +#if defined(__i386) || defined(__i386__) +# define LINUX32 1 +# define SE_WORDSIZE 4 + +/* Generic argument picker for `naked' functions */ +# define naked_arg0 4(%esp) +# define naked_arg1 8(%esp) +# define naked_arg2 12(%esp) +# define naked_arg3 16(%esp) + +# define xax eax +# define xbx ebx +# define xcx ecx +# define xdx edx + +# define xsi esi +# define xdi edi +# define xbp ebp +# define xsp esp +#elif defined(__x86_64) || defined(__x86_64__) +# define LINUX64 1 +# define SE_WORDSIZE 8 + +/* For x86_64, the first six parameters are passed by + * rdi, rsi, rdx, rcx, r8, r9. + */ +# define naked_arg0 %rdi +# define naked_arg1 %rsi +# define naked_arg2 %rdx +# define naked_arg3 %rcx + +# define xax rax +# define xbx rbx +# define xcx rcx +# define xdx rdx + +# define xsi rsi +# define xdi rdi +# define xbp rbp +# define xsp rsp +#else +# error unknown platform! +#endif + +/* SE instructions - needs to be sync-up with inst70.h */ +#define SE_EREPORT 0 +#define SE_EGETKEY 1 +#define SE_EENTER 2 +#define SE_EEXIT 4 + +#define SE_ECREATE 0 +#define SE_EADD 1 +#define SE_EINIT 2 +#define SE_EREMOVE 3 + +/* + * Macros for GNU assembly + */ +.macro ENCLU +#ifdef SE_SIM + cmp $SE_EEXIT, %xax + jne 1f + + /* if leaf is EEXIT, xbp and xsp need to be passed by xdx and xcx */ + mov %xbp, %xdx + mov %xsp, %xcx +1: + push %xdi + push %xsi + push %xdx + push %xcx + push %xbx + push %xax + +# ifdef LINUX64 + pop %rdi + pop %rsi + pop %rdx + pop %rcx + pop %r8 + pop %r9 +# endif + +.type _SE3,@function +.protected _SE3 + call _SE3 + +# ifdef LINUX32 + add $(SE_WORDSIZE * 6), %esp +# endif + +#else /* SE_SIM */ +.byte 0x0f, 0x01, 0xd7 /* 0xf3 */ +#endif /* !SE_SIM */ +.endm + +/* declare a function with default visibility */ +.macro DECLARE_GLOBAL_FUNC name + .globl \name + .type \name, @function +\name: +.endm + +/* declare a function with visibility='hidden' */ +.macro DECLARE_LOCAL_FUNC name + .globl \name + .hidden \name + .type \name, @function +\name: +.endm + +.macro NAKED_PROLOG + push %xbp + mov %xsp, %xbp + sub $(7 * SE_WORDSIZE), %xsp +.endm + +.macro NAKED_EPILOG + mov %xbp, %xsp + pop %xbp +.endm + +/* `paramN' (N = 1,2,3,4) should be registers. */ +.macro SET_PARAMS param1:req, param2, param3, param4 +#if defined(LINUX32) + +.ifnb \param4 + mov \param4, 3*SE_WORDSIZE(%esp) +.endif + +.ifnb \param3 + mov \param3, 2*SE_WORDSIZE(%esp) +.endif + +.ifnb \param2 + mov \param2, 1*SE_WORDSIZE(%esp) +.endif + + mov \param1, 0*SE_WORDSIZE(%esp) + +#else /* LINUX32 */ + +.ifnb \param4 +.ifnc \param4, %rcx + mov \param4, %rcx +.endif +.endif + +.ifnb \param3 +.ifnc \param3, %rdx + mov \param3, %rdx +.endif +.endif + +.ifnb \param2 +.ifnc \param2, %rsi + mov \param2, %rsi +.endif +.endif + +.ifnc \param1, %rdi + mov \param1, %rdi +.endif + +#endif /* LINUX64 */ +.endm + +/*******************************************************************/ + +.macro SE_PROLOG + .cfi_startproc + +#ifdef LINUX32 + pushl %ebp + movl %esp, %ebp +#endif + + push %xbx + push %xcx + push %xdx + +#if defined LINUX64 + movq %rdi, %rbx + movq %rsi, %rcx + /* rdx remains the same, rdi/rsi is not used by _SE0 + */ +#elif defined LINUX32 + movl 2*SE_WORDSIZE(%ebp), %ebx + movl 3*SE_WORDSIZE(%ebp), %ecx + movl 4*SE_WORDSIZE(%ebp), %edx +#endif + +.endm + +/*******************************************************************/ + +.macro SE_EPILOG + pop %xdx + pop %xcx + pop %xbx + +#ifdef LINUX32 + movl %ebp, %esp + popl %ebp +#endif + + ret + .cfi_endproc +.endm + +/*******************************************************************/ + +/* load the address of `symbol' to the register `reg' in PIC way. */ +.macro lea_pic symbol, reg +#ifdef LINUX64 + lea \symbol(%rip), \reg +#else +/* The real code on x86 would look like this (get `bar' from `foo'): + * + * 00000198 : + * 198: c3 ret + * + * 00000199 : + * 199: e8 00 00 00 00 call 19e + * 19e: 58 pop %eax + * 19f: 8d 40 fa lea -0x6(%eax),%eax + */ + call . + 0x5 /* No label here to avoid interfering w/ calling code */ + pop \reg + lea (\symbol - . + 1)(\reg), \reg +#endif +.endm + +#endif /* LINUX_REGS_H__ */ diff --git a/sgx-jvm/linux-sgx/common/inc/internal/linux/xsave_gnu.h b/sgx-jvm/linux-sgx/common/inc/internal/linux/xsave_gnu.h new file mode 100644 index 0000000000..5466ba5de6 --- /dev/null +++ b/sgx-jvm/linux-sgx/common/inc/internal/linux/xsave_gnu.h @@ -0,0 +1,92 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef _XSAVE_GNU_H_ +#define _XSAVE_GNU_H_ + +#include "se_types.h" + +#ifdef __x86_64__ +# define ASM_FXSAVE "rex64/fxsave" +# define ASM_FXRSTR "rex64/fxrstor" +# define ASM_XSAVE ".byte 0x48,0x0f,0xae,0x21" +# define ASM_XRSTR ".byte 0x48,0x0f,0xae,0x2f" +#else +# define ASM_FXSAVE "fxsave" +# define ASM_FXRSTR "fxrstor" +# define ASM_XSAVE ".byte 0x0f,0xae,0x21" +# define ASM_XRSTR ".byte 0x0f,0xae,0x2f" +#endif + +static inline void do_fwait(void) +{ + asm volatile("fwait"); +} + +static inline void do_fxsave(void *buffer) +{ + asm volatile(ASM_FXSAVE" (%0)" : : "r"(buffer) : "memory"); +} + +static inline void do_fxrstor(const void *buffer) +{ + asm volatile(ASM_FXRSTR" (%0)" : : "r"(buffer)); +} + +static inline void do_xsave(void *buffer) +{ + asm volatile(ASM_XSAVE + : + : "D" (buffer), "a" (-1), "d" (-1) + : "memory"); +} + +static inline void _do_xrstor(const void *buffer, uint64_t mask) +{ + uint32_t lmask = (uint32_t)mask; + uint32_t hmask = (uint32_t)(mask >> 32); + + asm volatile(ASM_XRSTR + : + : "D" (buffer), "a" (lmask), "d" (hmask)); +} + +static inline void do_xrstor(const void *buffer) +{ + _do_xrstor(buffer, 0xffffffffffffffffULL); +} + +static inline void do_vzeroupper() +{ + asm volatile("vzeroupper"); +} + +#endif diff --git a/sgx-jvm/linux-sgx/common/inc/internal/metadata.h b/sgx-jvm/linux-sgx/common/inc/internal/metadata.h new file mode 100644 index 0000000000..031af632e2 --- /dev/null +++ b/sgx-jvm/linux-sgx/common/inc/internal/metadata.h @@ -0,0 +1,150 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef _METADATA_H_ +#define _METADATA_H_ +#include "arch.h" +#include "se_macro.h" + +#pragma pack(1) + + /* version of metadata */ +#define MAJOR_VERSION 1 /* MAJOR_VERSION should not larger than 0ffffffff */ +#define MINOR_VERSION 3 /* MINOR_VERSION should not larger than 0ffffffff */ + +#define META_DATA_MAKE_VERSION(major, minor) (((uint64_t)major)<<32 | minor) + +#define METADATA_MAGIC 0x86A80294635D0E4CULL +#define METADATA_SIZE 0x1000 +/* TCS Policy bit masks */ +#define TCS_POLICY_BIND 0x00000000 /* If set, the TCS is bound to the application thread */ +#define TCS_POLICY_UNBIND 0x00000001 + +#define MAX_SAVE_BUF_SIZE 2632 + +#define TCS_NUM_MIN 1 +#define SSA_NUM_MIN 2 +#define SSA_FRAME_SIZE_MIN 1 +#define SSA_FRAME_SIZE_MAX 2 +#define STACK_SIZE_MIN 0x1000 +#define HEAP_SIZE_MIN 0 +#define DEFAULT_MISC_SELECT 0 +#define DEFAULT_MISC_MASK 0xFFFFFFFF + +typedef struct _data_directory_t +{ + uint32_t offset; + uint32_t size; +} data_directory_t; + +typedef enum +{ + DIR_PATCH, + DIR_LAYOUT, + DIR_NUM, +} dir_index_t; + +#define GROUP_FLAG (1<<12) +#define GROUP_ID(x) (GROUP_FLAG | x) +#define IS_GROUP_ID(x) !!((x) & GROUP_FLAG) +#define LAYOUT_ID_HEAP 1 +#define LAYOUT_ID_TCS 2 +#define LAYOUT_ID_TD 3 +#define LAYOUT_ID_SSA 4 +#define LAYOUT_ID_STACK 5 +#define LAYOUT_ID_THREAD_GROUP GROUP_ID(6) +#define LAYOUT_ID_GUARD 7 + +/* +** layout table example +** entry0 - entry1 - entry2 - group3 (entry_count=2, load_times=3) ... +** the load sequence should be: +** entry0 - entry1 - entry2 - entry1 - entry2 - entry1 - entry2 - entry1 - entry2 ... +** -------------- -------------- -------------- +** group3 1st time group3 2nd time group3 3rd time +*/ +typedef struct _layout_entry_t +{ + uint16_t id; /* unique ID to identify the purpose for this entry */ + uint16_t attributes; /* EADD/EEXTEND/EREMOVE... */ + uint32_t page_count; /* map size in page. Biggest chunk = 2^32 pages = 2^44 bytes. */ + uint64_t rva; /* map offset, relative to encalve base */ + uint32_t content_size; /* if content_offset = 0, content_size is the initial data to fill the whole page. */ + uint32_t content_offset; /* offset to the initial content, relative to metadata */ + si_flags_t si_flags; /* security info, R/W/X, SECS/TCS/REG/VA */ +} layout_entry_t; + +typedef struct _layout_group_t +{ + uint16_t id; /* unique ID to identify the purpose for this entry */ + uint16_t entry_count; /* reversely count entry_count entries for the group loading. */ + uint32_t load_times; /* the repeated times of loading */ + uint64_t load_step; /* the group size. the entry load rva should be adjusted with the load_step */ + /* rva = entry.rva + group.load_step * load_times */ + uint32_t reserved[4]; +} layout_group_t; + +typedef union _layout_t +{ + layout_entry_t entry; + layout_group_t group; +} layout_t; + +typedef struct _patch_entry_t +{ + uint64_t dst; /* relative to enclave file base */ + uint32_t src; /* relative to metadata base */ + uint32_t size; /* patched size */ + uint32_t reserved[4]; +} patch_entry_t; + +typedef struct _metadata_t +{ + uint64_t magic_num; /* The magic number identifying the file as a signed enclave image */ + uint64_t version; /* The metadata version */ + uint32_t size; /* The size of this structure */ + uint32_t tcs_policy; /* TCS management policy */ + uint32_t ssa_frame_size; /* The size of SSA frame in page */ + uint32_t max_save_buffer_size; /* Max buffer size is 2632 */ + uint32_t desired_misc_select; + uint32_t reserved; + uint64_t enclave_size; /* enclave virtual size */ + sgx_attributes_t attributes; /* XFeatureMask to be set in SECS. */ + enclave_css_t enclave_css; /* The enclave signature */ + data_directory_t dirs[DIR_NUM]; + uint8_t data[2208]; +}metadata_t; + +se_static_assert(sizeof(metadata_t) == METADATA_SIZE); + +#pragma pack() + +#endif diff --git a/sgx-jvm/linux-sgx/common/inc/internal/oal/uae_oal_api.h b/sgx-jvm/linux-sgx/common/inc/internal/oal/uae_oal_api.h new file mode 100644 index 0000000000..42c917dddb --- /dev/null +++ b/sgx-jvm/linux-sgx/common/inc/internal/oal/uae_oal_api.h @@ -0,0 +1,146 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#ifndef _UAE_OAL_H +#define _UAE_OAL_H + +#include "sgx_quote.h" +#include "sgx_error.h" +#include "sgx_urts.h" +#include +#include + +typedef enum{ + UAE_OAL_SUCCESS = 0, + UAE_OAL_ERROR_UNEXPECTED , + UAE_OAL_ERROR_AESM_UNAVAILABLE , + UAE_OAL_ERROR_TIMEOUT , +} uae_oal_status_t; + +/*OAL methods from here forward */ + +extern "C" +{ + +uae_oal_status_t SGXAPI oal_get_launch_token( + const enclave_css_t* signature, + const sgx_attributes_t* attribute, + sgx_launch_token_t* launch_token, + uint32_t timeout_usec, + aesm_error_t *result); + + +uae_oal_status_t SGXAPI oal_init_quote( + sgx_target_info_t *p_target_info, + sgx_epid_group_id_t *p_gid, + uint32_t timeout_usec, + aesm_error_t *result); + + +uae_oal_status_t SGXAPI oal_get_quote( + const sgx_report_t *p_report, + sgx_quote_sign_type_t quote_type, + const sgx_spid_t *p_spid, + const sgx_quote_nonce_t *p_nonce, + const uint8_t *p_sig_rl, + uint32_t sig_rl_size, + sgx_report_t *p_qe_report, + sgx_quote_t *p_quote, + uint32_t quote_size, + uint32_t timeout_usec, + aesm_error_t *result); + +uae_oal_status_t SGXAPI oal_get_ps_cap( + uint64_t* p_ps_cap, + uint32_t timeout_usec, + aesm_error_t *result); + +uae_oal_status_t SGXAPI oal_report_attestation_status( + const sgx_platform_info_t* p_platform_info, + int attestation_status, + sgx_update_info_bit_t* p_update_info, + uint32_t timeout_usec, + aesm_error_t *result); + +uae_oal_status_t oal_create_session( + uint32_t *session_id, + uint8_t *se_dh_msg1, + uint32_t dh_msg1_size, + uint32_t timeout_usec, + aesm_error_t *result); + +uae_oal_status_t oal_exchange_report( + uint32_t session_id, + const uint8_t *se_dh_msg2, + uint32_t dh_msg2_size, + uint8_t *se_dh_msg3, + uint32_t dh_msg3_size, + uint32_t timeout_usec, + aesm_error_t *result); + +uae_oal_status_t oal_close_session( + uint32_t session_id, + uint32_t timeout_usec, + aesm_error_t *result); + +uae_oal_status_t oal_invoke_service( + const uint8_t *pse_message_req, + uint32_t pse_message_req_size, + uint8_t *pse_message_resp, + uint32_t pse_message_resp_size, + uint32_t timeout_usec, + aesm_error_t *response); + +uae_oal_status_t oal_get_whitelist_size( + uint32_t* p_whitelist_size, + uint32_t timeout_usec, + aesm_error_t* result); + +uae_oal_status_t oal_get_whitelist( + uint8_t* p_whitelist, + uint32_t whitelist_size, + uint32_t timeout_usec, + aesm_error_t *result); + +uae_oal_status_t oal_get_extended_epid_group_id( + uint32_t* extended_group_id, + uint32_t timeout_usec, + aesm_error_t *result); + +uae_oal_status_t oal_switch_extended_epid_group( + uint32_t x_group_id, + uint32_t timeout_usec, + aesm_error_t *result); + +sgx_status_t oal_map_status(uae_oal_status_t status); +sgx_status_t oal_map_result(aesm_error_t result); + +} /* end of extern "C" */ +#endif diff --git a/sgx-jvm/linux-sgx/common/inc/internal/routine.h b/sgx-jvm/linux-sgx/common/inc/internal/routine.h new file mode 100644 index 0000000000..c753b2e2bf --- /dev/null +++ b/sgx-jvm/linux-sgx/common/inc/internal/routine.h @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + + +#ifndef _ROUTINE_H_ +#define _ROUTINE_H_ +#include "sgx_eid.h" +#include "sgx_error.h" +#include "sgx_defs.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct _ocall_table_t +{ + uint32_t count; + void *ocall[]; +} sgx_ocall_table_t; + +sgx_status_t SGXAPI sgx_ecall(const sgx_enclave_id_t enclave_id, const int proc, const void *ocall_table, void *ms); + +#ifdef __cplusplus +} +#endif + +#endif \ No newline at end of file diff --git a/sgx-jvm/linux-sgx/common/inc/internal/rts.h b/sgx-jvm/linux-sgx/common/inc/internal/rts.h new file mode 100644 index 0000000000..61a7711501 --- /dev/null +++ b/sgx-jvm/linux-sgx/common/inc/internal/rts.h @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef _RTS_H_ +#define _RTS_H_ + +#include "se_types.h" +#include "rts_cmd.h" + +typedef struct _ocall_context_t +{ + uintptr_t shadow0; + uintptr_t shadow1; + uintptr_t shadow2; + uintptr_t shadow3; + uintptr_t ocall_flag; + uintptr_t ocall_index; + uintptr_t pre_last_sp; + uintptr_t r15; + uintptr_t r14; + uintptr_t r13; + uintptr_t r12; + uintptr_t xbp; + uintptr_t xdi; + uintptr_t xsi; + uintptr_t xbx; + uintptr_t reserved[3]; + uintptr_t ocall_depth; + uintptr_t ocall_ret; +} ocall_context_t; + +typedef enum +{ + SDK_VERSION_1_5, + SDK_VERSION_2_0 +} sdk_version_t; + +typedef struct _cpu_feature_sdk_version +{ + uint64_t cpu_features; + sdk_version_t version; +}cpu_sdk_info_t; + +#define OCALL_FLAG 0x4F434944 + +#endif diff --git a/sgx-jvm/linux-sgx/common/inc/internal/rts_cmd.h b/sgx-jvm/linux-sgx/common/inc/internal/rts_cmd.h new file mode 100644 index 0000000000..671c2c90d1 --- /dev/null +++ b/sgx-jvm/linux-sgx/common/inc/internal/rts_cmd.h @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +/* ECALL command */ +#define ECMD_ECALL 0 +#define ECMD_INIT_ENCLAVE -1 +#define ECMD_ORET -2 +#define ECMD_EXCEPT -3 + +/* OCALL command */ +#define OCMD_ERET -1 + diff --git a/sgx-jvm/linux-sgx/common/inc/internal/se_atomic.h b/sgx-jvm/linux-sgx/common/inc/internal/se_atomic.h new file mode 100644 index 0000000000..f4de235e8d --- /dev/null +++ b/sgx-jvm/linux-sgx/common/inc/internal/se_atomic.h @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef _SE_ATOMIC_H_ +#define _SE_ATOMIC_H_ + + +inline uint32_t se_atomic_inc(volatile uint32_t *mem) +{ + int ret; + + __asm__ __volatile__ ("lock; xaddl %0, %1" + : "=r" (ret), "=m" (*mem) + : "0" (1), "m" (*mem) + ); + + return ret + 1; +} + +inline uint32_t se_atomic_dec(uint32_t volatile *mem) +{ + int ret; + + __asm__ __volatile__ ("lock; xaddl %0, %1" + : "=r" (ret), "=m" (*mem) + : "0" (-1), "m" (*mem) + ); + + return ret - 1; +} + +#endif diff --git a/sgx-jvm/linux-sgx/common/inc/internal/se_cdefs.h b/sgx-jvm/linux-sgx/common/inc/internal/se_cdefs.h new file mode 100644 index 0000000000..12be808120 --- /dev/null +++ b/sgx-jvm/linux-sgx/common/inc/internal/se_cdefs.h @@ -0,0 +1,103 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + + +#ifndef _SE_CDEFS_H_ +#define _SE_CDEFS_H_ + + +#define SGX_WEAK __attribute__((weak)) + +# if (__GNUC__ >= 3) +# define likely(x) __builtin_expect ((x), 1) +# define unlikely(x) __builtin_expect ((x), 0) +# else +# define likely(x) (x) +# define unlikely(x) (x) +# endif + +#ifndef SE_DECLSPEC_EXPORT +#define SE_DECLSPEC_EXPORT __attribute__((visibility("default"))) +#endif + +#ifndef SE_DECLSPEC_IMPORT +#define SE_DECLSPEC_IMPORT +#endif + +#ifndef SE_DECLSPEC_ALIGN +#define SE_DECLSPEC_ALIGN(x) __attribute__((aligned(x))) +#endif + +#ifndef SE_DECLSPEC_THREAD +#define SE_DECLSPEC_THREAD /*__thread*/ +#endif + +/* disable __try, __except on linux */ +#ifndef __try +#define __try try +#endif + +#ifndef __except +#define __except(x) catch(...) +#endif + + +#ifndef SE_DRIVER + +# define SE_GNU +# if defined(__x86_64__) +# define SE_64 +# define SE_GNU64 +# else +# define SE_32 +# define SE_GNU32 +# endif + +#endif + + #define INITIALIZER(f) \ + static void f(void) __attribute__((constructor)); + +#ifdef __cplusplus +#define MY_EXTERN extern "C" +#else +#define MY_EXTERN extern +#endif + +#define SGX_ACCESS_VERSION(libname, num) \ + MY_EXTERN const char *sgx_##libname##_version; \ + const char * __attribute__((destructor)) libname##_access_version_dummy##num() \ + { \ + return sgx_##libname##_version; \ + } + + +#endif diff --git a/sgx-jvm/linux-sgx/common/inc/internal/se_cpu_feature.h b/sgx-jvm/linux-sgx/common/inc/internal/se_cpu_feature.h new file mode 100644 index 0000000000..8b3edbfa66 --- /dev/null +++ b/sgx-jvm/linux-sgx/common/inc/internal/se_cpu_feature.h @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + + +#ifndef _SE_CPU_FEATURE_H_ +#define _SE_CPU_FEATURE_H_ + +#include +#include "se_cpu_feature_defs.h" + + +#ifdef __cplusplus +extern "C" uint64_t g_cpu_feature_indicator; +#else +extern uint64_t g_cpu_feature_indicator; +#endif + +#define TEST_CPU_HAS_RDRAND (g_cpu_feature_indicator & CPU_FEATURE_RDRND) + + +#endif diff --git a/sgx-jvm/linux-sgx/common/inc/internal/se_cpu_feature_defs.h b/sgx-jvm/linux-sgx/common/inc/internal/se_cpu_feature_defs.h new file mode 100644 index 0000000000..20983b96d7 --- /dev/null +++ b/sgx-jvm/linux-sgx/common/inc/internal/se_cpu_feature_defs.h @@ -0,0 +1,294 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef _SE_CPU_FEATURE_DEFS_H_ +#define _SE_CPU_FEATURE_DEFS_H_ + +/* + * Different extended model + model values for Silverthorn. + */ +#define CPU_ATOM1 0x1c +#define CPU_ATOM2 0x26 +#define CPU_ATOM3 0x27 + +/* + * The processor family is an 8-bit value obtained by adding the + * Extended Family field of the processor signature returned by + * CPUID Function 1 with the Family field. + * F = (CPUID(1).EAX[27:20] >> 20) + (CPUID(1).EAX[11:8] >> 8) + */ +#define CPU_FAMILY(x) (((((x) >> 20) & 0xffU) | (((x) >> 8) & 0xfU)) & 0xffU) + +/* The processor model is an 8-bit value obtained by shifting left 4 + * the Extended Model field of the processor signature returned by + * CPUID Function 1 then adding the Model field. + * M = (CPUID(1).EAX[19:16] >> 12) + (CPUID(1).EAX[7:4] >> 4) + */ +#define CPU_MODEL(x) ((((x) >> 12) & 0xf0U) | (((x) >> 4) & 0xfU)) +#define CPU_STEPPING(x) (((x) >> 0) & 0xf) + +#define CPU_HAS_MMX(x) (((x) & (1 << 23)) != 0) +#define CPU_HAS_FXSAVE(x) (((x) & (1 << 24)) != 0) +#define CPU_HAS_SSE(x) (((x) & (1 << 25)) != 0) +#define CPU_HAS_SSE2(x) (((x) & (1 << 26)) != 0) +#define CPU_HAS_PNI(x) (((x) & (1 << 0)) != 0) +#define CPU_HAS_MNI(x) (((x) & (1 << 9)) != 0) +#define CPU_HAS_SNI(x) (((x) & (1 << 19)) != 0) +#define CPU_HAS_MOVBE(x) (((x) & (1 << 22)) != 0) +#define CPU_HAS_SSE4_2(x) (((x) & (1 << 20)) != 0) +#define CPU_HAS_POPCNT(x) (((x) & (1 << 23)) != 0) +#define CPU_HAS_PCLMULQDQ(x) (((x) & (1 << 1)) != 0) +#define CPU_HAS_AES(x) (((x) & (1 << 25)) != 0) +#define CPU_HAS_XSAVE(x) (((x) & (1 << 27)) != 0) +#define CPU_HAS_AVX(x) (((x) & (1 << 28)) != 0) +#define XFEATURE_ENABLED_AVX(x) \ + (((x) & 0x06) == 0x06) +#define CPU_HAS_F16C(x) (((x) & (1 << 29)) != 0) +#define CPU_HAS_RDRAND(x) (((x) & (1 << 30)) != 0) +#define CPU_HAS_IVB(x) (CPU_HAS_F16C(x) && CPU_HAS_RDRAND(x)) +#define CPU_HAS_IVB_NORDRAND(x) (CPU_HAS_F16C(x)) +#define CPU_HAS_AVX2(x) (((x) & (1 << 5)) != 0) +#define CPU_HAS_HLE(x) (((x) & (1 << 4)) != 0) +#define CPU_HAS_RTM(x) (((x) & (1 << 11)) != 0) +#define CPU_HAS_ADCOX(x) (((x) & (1 << 19)) != 0) +#define CPU_HAS_RDSEED(x) (((x) & (1 << 18)) != 0) +#define CPU_HAS_BMI(x) (((x) & (1 << 3)) != 0 && \ + ((x) & (1 << 8)) != 0) +#define CPU_HAS_LZCNT(x) (((x) & (1 << 5)) != 0) +#define CPU_HAS_PREFETCHW(x) (((x) & (1 << 8)) != 0) +#define CPU_HAS_FMA(x) (((x) & (1 << 12)) != 0) +#define CPU_HAS_HSW(cpuid7_ebx, ecpuid1_ecx, cpuid1_ecx) \ + (CPU_HAS_AVX2(cpuid7_ebx) && CPU_HAS_BMI(cpuid7_ebx) && \ + CPU_HAS_LZCNT(ecpuid1_ecx) && CPU_HAS_FMA(cpuid1_ecx) && \ + CPU_HAS_HLE(cpuid7_ebx) && CPU_HAS_RTM(cpuid7_ebx)) + +#define CPU_HAS_FPU(x) (((x) & (1 << 0)) != 0) +#define CPU_HAS_CMOV(x) (((x) & (1 << 15)) != 0) + +#define CPU_HAS_SSE3(x) (((x) & (1 << 0)) != 0) +#define CPU_HAS_SSSE3(x) (((x) & (1 << 9)) != 0) + +#define CPU_HAS_SSE4_1(x) (((x) & (1 << 19)) != 0) + +#define CPU_HAS_LRBNI(x) (((x) & (1 << 1)) != 0) +#define CPU_HAS_LRB2(x) (((x) & (1 << 4)) != 0) + + +#define CPU_GENU_VAL ('G' << 0 | 'e' << 8 | 'n' << 16 | 'u' << 24) +#define CPU_INEI_VAL ('i' << 0 | 'n' << 8 | 'e' << 16 | 'I' << 24) +#define CPU_NTEL_VAL ('n' << 0 | 't' << 8 | 'e' << 16 | 'l' << 24) + +/* + * These values must be in sync with dev/proton/globals/glob_cpu_info.c + * c_legacy_cpu_set_xxx constants. + */ +#define CPU_GENERIC 0x1 +#define CPU_PENTIUM 0x2 +#define CPU_PENTIUM_PRO 0x4 +#define CPU_PENTIUM_MMX 0x8 +#define CPU_PENTIUM_II 0x10 +#define CPU_PENTIUM_II_FXSV 0x20 +#define CPU_PENTIUM_III 0x40 +#define CPU_PENTIUM_III_SSE 0x80 +#define CPU_PENTIUM_4 0x100 +#define CPU_PENTIUM_4_SSE2 0x200 +#define CPU_BNI 0x400 +#define CPU_PENTIUM_4_PNI 0x800 +#define CPU_MNI 0x1000 +#define CPU_SNI 0x2000 +#define CPU_BNL 0x4000 +#define CPU_NHM 0x8000 +#define CPU_WSM 0x10000 +#define CPU_SNB 0x20000 +#define CPU_IVB 0x40000 +#define CPU_HSW 0x400000 + +#define CPU_PENTIUM_FAMILY 5 +#define CPU_PPRO_FAMILY 6 +#define CPU_WMT_FAMILY 15 + +/* + * The processor is a generic IA32 CPU + */ +#define CPU_FEATURE_GENERIC_IA32 0x00000001ULL + +/* + * Floating point unit is on-chip. + */ +#define CPU_FEATURE_FPU 0x00000002ULL + +/* + * Conditional mov instructions are supported. + */ +#define CPU_FEATURE_CMOV 0x00000004ULL + +/* + * The processor supports the MMX technology instruction set extensions + * to Intel Architecture. + */ +#define CPU_FEATURE_MMX 0x00000008ULL + +/* + * The FXSAVE and FXRSTOR instructions are supported for fast + * save and restore of the floating point context. + */ +#define CPU_FEATURE_FXSAVE 0x00000010ULL + +/* + * Indicates the processor supports the Streaming SIMD Extensions Instructions. + */ +#define CPU_FEATURE_SSE 0x00000020ULL + +/* + * Indicates the processor supports the Streaming SIMD + * Extensions 2 Instructions. + */ +#define CPU_FEATURE_SSE2 0x00000040ULL + +/* + * Indicates the processor supports the Streaming SIMD + * Extensions 3 Instructions. (PNI) + */ +#define CPU_FEATURE_SSE3 0x00000080ULL + +/* + * The processor supports the Supplemental Streaming SIMD Extensions 3 + * instructions. (MNI) + */ +#define CPU_FEATURE_SSSE3 0x00000100ULL + +/* + * The processor supports the Streaming SIMD Extensions 4.1 instructions.(SNI) + */ +#define CPU_FEATURE_SSE4_1 0x00000200ULL + +/* + * The processor supports the Streaming SIMD Extensions 4.1 instructions. + * (NNI + STTNI) + */ +#define CPU_FEATURE_SSE4_2 0x00000400ULL + + +/* + * The processor supports POPCNT instruction. + */ +#define CPU_FEATURE_POPCNT 0x00000800ULL + +/* + * The processor supports MOVBE instruction. + */ +#define CPU_FEATURE_MOVBE 0x00001000ULL + +/* + * The processor supports PCLMULQDQ instruction. + */ +#define CPU_FEATURE_PCLMULQDQ 0x00002000ULL + +/* + * The processor supports instruction extension for encryption. + */ +#define CPU_FEATURE_AES 0x00004000ULL + +/* + * The processor supports 16-bit floating-point conversions instructions. + */ +#define CPU_FEATURE_F16C 0x00008000ULL + +/* + * The processor supports AVX instruction extension. + */ +#define CPU_FEATURE_AVX 0x00010000ULL + +/* + * The processor supports RDRND (read random value) instruction. + */ +#define CPU_FEATURE_RDRND 0x00020000ULL + +/* + * The processor supports FMA instructions. + */ +#define CPU_FEATURE_FMA 0x00040000ULL + +/* + * The processor supports two groups of advanced bit manipulation extensions. - Haswell introduced, AVX2 related + */ +#define CPU_FEATURE_BMI 0x00080000ULL + +/* + * The processor supports LZCNT instruction (counts the number of leading zero + * bits). - Haswell introduced + */ +#define CPU_FEATURE_LZCNT 0x00100000ULL + +/* + * The processor supports HLE extension (hardware lock elision). - Haswell introduced + */ +#define CPU_FEATURE_HLE 0x00200000ULL + +/* + * The processor supports RTM extension (restricted transactional memory) - Haswell AVX2 related. + */ +#define CPU_FEATURE_RTM 0x00400000ULL + +/* + * The processor supports AVX2 instruction extension. + */ +#define CPU_FEATURE_AVX2 0x00800000ULL + +/* + * The processor supports AVX512 instruction extension. + */ +#define CPU_FEATURE_AVX512 0x01000000ULL + +/* + * The processor supports the PREFETCHW instruction. + */ +#define CPU_FEATURE_PREFETCHW 0x02000000ULL + +/* + * The processor supports RDSEED instruction. + */ +#define CPU_FEATURE_RDSEED 0x04000000ULL + +/* + * The processor supports ADCX and ADOX instructions. + */ +#define CPU_FEATURE_ADCOX 0x08000000ULL + +/* + * The processor is a full inorder (Silverthorne) processor + */ +#define CPU_FEATURE_FULL_INORDER 0x10000000ULL + +/* Reserved feature bits which includes the unset bit CPU_FEATURE_AVX512 */ +#define RESERVED_CPU_FEATURE_BIT ((~(0x20000000ULL - 1)) | 0x01000000ULL) + +#endif diff --git a/sgx-jvm/linux-sgx/common/inc/internal/se_debugger_lib.h b/sgx-jvm/linux-sgx/common/inc/internal/se_debugger_lib.h new file mode 100644 index 0000000000..97e4e36546 --- /dev/null +++ b/sgx-jvm/linux-sgx/common/inc/internal/se_debugger_lib.h @@ -0,0 +1,115 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef _SEDEBUGGERLIB_H_ +#define _SEDEBUGGERLIB_H_ + +#include "arch.h" +#include "se_types.h" +#include "se_macro.h" +#include + +#define URTS_EXCEPTION_PRECREATEENCLAVE 0xa1a01ec0 +#define URTS_EXCEPTION_POSTINITENCLAVE 0xa1a01ec1 +#define URTS_EXCEPTION_PREREMOVEENCLAVE 0xa1a01ec3 +#define URTS_EXCEPTION_PREEENTER 0xa1a01ec7 + +#define FIRST_CHANCE_EXCEPTION 1 +#define SECOND_CHANCE_EXCEPTION 0 + +#define DBWIN_BUFFER 0xa1a01ec5 +#define CXX_EXCEPTION 0xe06d7363 + +#define SE_UNICODE 1 +#define SE_ANSI 0 +#define DEBUGGER_ENABLED 1 + +#define DEBUG_INFO_STRUCT_VERSION 0x83d0ce23 + +const size_t BUF_SIZE = sizeof(void*); + +typedef struct _debug_tcs_info_t +{ + struct _debug_tcs_info_t* next_tcs_info; + void* TCS_address; + uintptr_t ocall_frame; /* ocall_frame_t** */ + unsigned long thread_id; +}debug_tcs_info_t; + + +#define DEBUG_INFO_MAX_PARAMETERS 10 +typedef struct _debug_info_t +{ + uintptr_t param_array[DEBUG_INFO_MAX_PARAMETERS]; +}debug_info_t; + +//enclave_type bit map +#define ET_SIM_SHIFT 0 /*bits[0]=0 hw, bits[0]=1 sim*/ +#define ET_DEBUG_SHIFT 1 /*bits[1]=0 product enclave, bits[1]=1 debug enclave*/ +#define ET_SIM (1 << ET_SIM_SHIFT) +#define ET_DEBUG (1 << ET_DEBUG_SHIFT) + +typedef struct _debug_enclave_info_t +{ + PADDED_POINTER(struct _debug_enclave_info_t, next_enclave_info); + PADDED_POINTER(void, start_addr); + PADDED_POINTER(debug_tcs_info_t, tcs_list); + uint32_t enclave_type; + uint32_t file_name_size; + PADDED_POINTER(void, lpFileName); + PADDED_POINTER(void, g_peak_heap_used_addr); + PADDED_POINTER(void, dyn_sec); + sgx_misc_select_t misc_select; + /* The following members are optional or unused */ + uint32_t struct_version; + uint32_t unicode; +}debug_enclave_info_t; +typedef struct _ocall_frame_t +{ + uintptr_t pre_last_frame; + uintptr_t index; + uintptr_t xbp; + uintptr_t ret; +}ocall_frame_t; + +static inline void destory_debug_info(debug_enclave_info_t *debug_info) +{ + if(debug_info->lpFileName) + { + free(debug_info->lpFileName); + debug_info->lpFileName = NULL; + } + + /*tcs_list is just a pointer, the instance is maintained in CTrustThread, so don't free it.*/ + debug_info->tcs_list = NULL; +} +#endif /*_SEDEBUGGERLIB_H_*/ + diff --git a/sgx-jvm/linux-sgx/common/inc/internal/se_enclave_type.h b/sgx-jvm/linux-sgx/common/inc/internal/se_enclave_type.h new file mode 100644 index 0000000000..bd450e3918 --- /dev/null +++ b/sgx-jvm/linux-sgx/common/inc/internal/se_enclave_type.h @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef _SE_ENCLAVE_TYPE_H_ +#define _SE_ENCLAVE_TYPE_H_ + +typedef enum +{ + enclave_type_general = 0, + enclave_type_architecture, +} enclave_type_t; + +#endif diff --git a/sgx-jvm/linux-sgx/common/inc/internal/se_error_internal.h b/sgx-jvm/linux-sgx/common/inc/internal/se_error_internal.h new file mode 100644 index 0000000000..b98aed81d7 --- /dev/null +++ b/sgx-jvm/linux-sgx/common/inc/internal/se_error_internal.h @@ -0,0 +1,90 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef _SE_ERROR_INTERNAL_H_ +#define _SE_ERROR_INTERNAL_H_ + +#include "sgx_error.h" + +/* +bit[31:30] - main module id + 00 - external error + 11---internal error +bit[29:16] - reserved +bit[15:12] - sub-module id +bit[11:0] - specific error +*/ + +#define MAIN_MOD_SHIFT 30 +#define SUB_MOD_SHIFT 12 + +#define INTERNAL_ERROR 3 +#define EXTERNAL_ERROR 0 + +#define SE_INTERNAL_ERROR(x) (0xC0000000|(x)) + +typedef enum _se_status_internal_t +{ + SE_ERROR_SUCCESS = 0, /*same value as SGX_SUCCESS*/ + /*error code for driver return to uRTS*/ + SE_ERROR_DRIVER_UNEXPECTED = SE_INTERNAL_ERROR(0X2001), + SE_ERROR_DRIVER_INVALID_ID = SE_INTERNAL_ERROR(0X2002), + SE_ERROR_DRIVER_INVALID_PARAMETER = SE_INTERNAL_ERROR(0X2003), + SE_ERROR_DRIVER_INVALID_REQUEST = SE_INTERNAL_ERROR(0X2004), + SE_ERROR_DRIVER_OUTOF_MEMORY_R0 = SE_INTERNAL_ERROR(0X2005), + SE_ERROR_DRIVER_OUTOF_MEMORY_R3 = SE_INTERNAL_ERROR(0X2006), + SE_ERROR_DRIVER_OUTOF_EPC = SE_INTERNAL_ERROR(0X2007), + SE_ERROR_DRIVER_HW_CAPABILITY = SE_INTERNAL_ERROR(0X2008), + SE_ERROR_DRIVER_MEMORY_MAP_CONFLICT = SE_INTERNAL_ERROR(0X2009), + SE_ERROR_DRIVER_POWER = SE_INTERNAL_ERROR(0X200a), + SE_ERROR_DRIVER_INVALID_PRIVILEGE = SE_INTERNAL_ERROR(0X200b), + SE_ERROR_DRIVER_INVALID_ISVSVNLE = SE_INTERNAL_ERROR(0X200c), + + SE_ERROR_DRIVER_INVALID_SIG_STRUCT = SE_INTERNAL_ERROR(0X2100), + SE_ERROR_DRIVER_INVALID_ATTRIBUTE = SE_INTERNAL_ERROR(0X2101), + SE_ERROR_DRIVER_INVALID_MEASUREMENT = SE_INTERNAL_ERROR(0X2102), + SE_ERROR_DRIVER_INVALID_SIGNATURE = SE_INTERNAL_ERROR(0X2103), + SE_ERROR_DRIVER_INVALID_LAUNCH_TOKEN= SE_INTERNAL_ERROR(0X2104), + SE_ERROR_DRIVER_INVALID_CPUSVN = SE_INTERNAL_ERROR(0X2105), + SE_ERROR_DRIVER_UNMASKED_EVENT = SE_INTERNAL_ERROR(0X2106), + + SE_ERROR_INVALID_LAUNCH_TOKEN = SE_INTERNAL_ERROR(0x2200), /* the license is invalid*/ + SE_ERROR_INVALID_MEASUREMENT = SE_INTERNAL_ERROR(0x2201), /* The measurement of the enclave is invalid. May caused by signature or launch token*/ + SE_ERROR_READ_LOCK_FAIL = SE_INTERNAL_ERROR(0x2202), + SE_ERROR_INVALID_ISVSVNLE = SE_INTERNAL_ERROR(0X2203), + + /*error code for untrusted event of SE mutex*/ + SE_ERROR_MUTEX_GET_EVENT = SE_INTERNAL_ERROR(0x3001), + SE_ERROR_MUTEX_WAIT_EVENT = SE_INTERNAL_ERROR(0x3002), + SE_ERROR_MUTEX_WAKE_EVENT = SE_INTERNAL_ERROR(0x3003), +} se_status_internal_t; + +#endif diff --git a/sgx-jvm/linux-sgx/common/inc/internal/se_event.h b/sgx-jvm/linux-sgx/common/inc/internal/se_event.h new file mode 100644 index 0000000000..3672fd3246 --- /dev/null +++ b/sgx-jvm/linux-sgx/common/inc/internal/se_event.h @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef _SE_EVENT_H_ +#define _SE_EVENT_H_ + +# include +# include +# include +typedef void * se_handle_t; + +#include "sgx_defs.h" + +#define SE_MUTEX_SUCCESS 0x0 +#define SE_MUTEX_INVALID 0x1 +#define SE_MUTEX_ERROR_WAKE 0x2 +#define SE_MUTEX_ERROR_WAIT 0x3 + +#ifdef __cplusplus +extern "C" { +#endif + +se_handle_t SGXAPI se_event_init(void); +void SGXAPI se_event_destroy(se_handle_t); + +int SGXAPI se_event_wait(se_handle_t); +int SGXAPI se_event_wake(se_handle_t); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/sgx-jvm/linux-sgx/common/inc/internal/se_lock.hpp b/sgx-jvm/linux-sgx/common/inc/internal/se_lock.hpp new file mode 100644 index 0000000000..68aedf2cf5 --- /dev/null +++ b/sgx-jvm/linux-sgx/common/inc/internal/se_lock.hpp @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +/* This file implement lock guard */ + +#ifndef SE_LOCK_HPP +#define SE_LOCK_HPP + +#include "util.h" +#include "se_thread.h" +#include "uncopyable.h" + +class Mutex: private Uncopyable +{ +public: + Mutex(){se_mutex_init(&m_mutex);} + ~Mutex(){se_mutex_destroy(&m_mutex);} + void lock(){se_mutex_lock(&m_mutex);} + void unlock(){se_mutex_unlock(&m_mutex);} +private: + se_mutex_t m_mutex; +}; + +class LockGuard: private Uncopyable +{ +public: + LockGuard(Mutex* mutex):m_mutex(mutex){m_mutex->lock();} + ~LockGuard(){m_mutex->unlock();} +private: + Mutex* m_mutex; +}; + +#endif diff --git a/sgx-jvm/linux-sgx/common/inc/internal/se_macro.h b/sgx-jvm/linux-sgx/common/inc/internal/se_macro.h new file mode 100644 index 0000000000..4b465ac71b --- /dev/null +++ b/sgx-jvm/linux-sgx/common/inc/internal/se_macro.h @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + + + #ifndef SE_MACRO_H_ + #define SE_MACRO_H_ + +#ifndef SGX_HYPERV_ECO +#define SGX_HYPERV_ECO +#endif + + #endif \ No newline at end of file diff --git a/sgx-jvm/linux-sgx/common/inc/internal/se_map.h b/sgx-jvm/linux-sgx/common/inc/internal/se_map.h new file mode 100644 index 0000000000..2b1889a838 --- /dev/null +++ b/sgx-jvm/linux-sgx/common/inc/internal/se_map.h @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef _SE_MAP_H_ +#define _SE_MAP_H_ + +#include +#include +#include +#include + +#include "se_types.h" + +#include +#include +#include +#include +typedef int se_file_handle_t; + +typedef struct { + uint8_t* base_addr; /* pointer to the mapped area */ + size_t length; /* the length of the mapping */ +} map_handle_t; + +#ifdef __cplusplus +extern "C" { +#endif + +/* Map a file to memory and get its size. */ +map_handle_t* map_file(se_file_handle_t fd, uint32_t *size); + +/* Unmap a mapped file. */ +void unmap_file(map_handle_t* mh); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/sgx-jvm/linux-sgx/common/inc/internal/se_memcpy.h b/sgx-jvm/linux-sgx/common/inc/internal/se_memcpy.h new file mode 100644 index 0000000000..f7cd259993 --- /dev/null +++ b/sgx-jvm/linux-sgx/common/inc/internal/se_memcpy.h @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef _SE_MEMCPY_H_ +#define _SE_MEMCPY_H_ + +#include + + +/* memcpy_s always return 0 under Linux */ + +#ifndef _ERRNO_T_DEFINED +#define _ERRNO_T_DEFINED +typedef int errno_t; +#endif + +static inline errno_t memcpy_s(void *dest, size_t numberOfElements, const void *src, size_t count) +{ + if(numberOfElements +#include +#include +#include + +#ifndef MEM_COMMIT +#define MEM_COMMIT 0x1000 +#endif + +#ifndef MEM_RESERVE +#define MEM_RESERVE 0x2000 +#endif + +#ifdef MEM_RELEASE +#warning "MEM_RELEASE define conflict" +#else +#define MEM_RELEASE 0x8000 +#endif + +#ifdef MEM_DECOMMIT +#warning "MEM_DECOMMIT define conflict" +#else +#define MEM_DECOMMIT 0x4000 +#endif + +#include "se_types.h" +#include "arch.h" +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* +Reserves or commits a region of pages in the virtual address space of the calling process. +Memory allocated by this function is automatically initialized to zero, unless MEM_RESET is specified. +@address: the starting address of the region to allocate. +@size: size of region in bytes. +@type: Only MEM_COMMIT accepted. + MEM_COMMIT - Allocates memory charges for the specified reserved memory pages. + Actual physical pages are not allocated until the virtual addresses are actually accessed. + The function initializes the memory to zero. +@return value: If the function succeeds, the return value is the base address of the allocated region of pages. + If the function fails, the return value is NULL. +*/ +void* se_virtual_alloc(void* address, size_t size, uint32_t type); +/* +Releases, decommits, or releases and decommits a region of pages within the virtual address space of the calling process. +@address:A pointer to the base address of the region of pages to be freed. If the dwFreeType parameter is MEM_RELEASE, + this parameter must be the base address returned by the se_virtual_alloc function when the region of pages is reserved. +@size: The size of the region of memory to be freed, in bytes. +@type: Only MEM_RELEASE accepted + MEM_RELEASE - releases the specified region of pages. After this operation, the pages are in the free state. +@return value:If the function succeeds, the return value is nonzero.If the function fails, the return value is zero. +*/ +int se_virtual_free(void* address, size_t size, uint32_t type); +/* +Locks the specified region of the process's virtual address space into physical memory, ensuring that subsequent access to the region will not incur a page fault. +@address: A pointer to the base address of the region of pages to be locked. + The region of affected pages includes all pages that contain one or more bytes in the range from the address parameter to (address+size). +@size: The size of the region to be locked, in bytes. +@return value: If the function succeeds, the return value is nonzero. If the function fails, the return value is zero. +*/ +int se_virtual_lock(void* address, size_t size); +/* +Changes the protection on a region of committed pages in the virtual address space of the calling process. +@address: A pointer an address that describes the starting page of the region of pages whose access protection attributes are to be changed. +@size: The size of the region whose access protection attributes are to be changed, in bytes. +@prot: The memory protection option. The option can be SI_FLAG_R, SI_FLAG_W, SI_FLAG_X. +@return value: If the function succeeds, the return value is nonzero.If the function fails, the return value is zero. +*/ + +#define SGX_PROT_NONE PROT_NONE + +int se_virtual_protect(void* address, size_t size, uint32_t prot); + + +#include +#include +#include +#include +typedef pid_t se_proc_t; + +/* +@return value: on success, return TRUE else return FALSE +*/ +se_proc_t get_self_proc(void); +/* +** If the function succeeds, the return value is nonzero. +** If the function fails, the return value is zero. +*/ +int put_self_proc(se_proc_t proc); +int se_read_process_mem(se_proc_t proc, void* base_addr, void* buffer, size_t size, size_t* read_nr); +int se_write_process_mem(se_proc_t proc, void* base_addr, void* buffer, size_t size, size_t* write_ndr); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/sgx-jvm/linux-sgx/common/inc/internal/se_page_attr.h b/sgx-jvm/linux-sgx/common/inc/internal/se_page_attr.h new file mode 100644 index 0000000000..9bafac8af5 --- /dev/null +++ b/sgx-jvm/linux-sgx/common/inc/internal/se_page_attr.h @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef _SE_PAGE_ATTR_H_ +#define _SE_PAGE_ATTR_H_ + +typedef enum +{ + DoEADD = 0, + DoEEXTEND, +} ATTRIBUTE_BITS_t; + +typedef enum +{ + ADD_PAGE_ONLY = 1< + +typedef pthread_rwlock_t se_rwlock_t; +typedef pthread_rwlock_t* se_prwlock_t; + +#ifdef __cplusplus +extern "C" { +#endif + +void se_wtlock(se_prwlock_t); +void se_wtunlock(se_prwlock_t); +int se_try_rdlock(se_prwlock_t); +void se_rdlock(se_prwlock_t lock); +void se_rdunlock(se_prwlock_t); +void se_init_rwlock(se_prwlock_t lock); +void se_fini_rwlock(se_prwlock_t lock); + +#ifdef __cplusplus +} +#endif + +#endif /* _RWLOCK_H_ */ diff --git a/sgx-jvm/linux-sgx/common/inc/internal/se_stdio.h b/sgx-jvm/linux-sgx/common/inc/internal/se_stdio.h new file mode 100644 index 0000000000..9f5dc3adab --- /dev/null +++ b/sgx-jvm/linux-sgx/common/inc/internal/se_stdio.h @@ -0,0 +1,155 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + + + +#ifndef SE_STDIO_H +#define SE_STDIO_H + +#include +#include +#include "se_memcpy.h" +#include +#include +#include +#include +#include + +#ifndef MAX_PATH +#define MAX_PATH 260 +#endif + +static inline int se_delete_file(const char *path_name) +{ + return unlink(path_name); +} + +#define se_delete_tfile se_delete_file + +static inline int sprintf_s(char *dst_buf, size_t size_in_bytes, const char *format, ...) +{ + va_list argptr; + int cnt; + va_start(argptr, format); + cnt = vsnprintf(dst_buf, size_in_bytes, format, argptr); + va_end(argptr); + return cnt; +} + +static inline int _snprintf_s(char *dst_buf, size_t size_in_bytes, size_t max_count, const char *format, ...) +{ + (void) size_in_bytes; + va_list argptr; + int cnt; + va_start(argptr, format); + cnt = vsnprintf(dst_buf, max_count, format, argptr); + va_end(argptr); + return cnt; +} + +static inline errno_t fopen_s(FILE **f, const char *filename, const char *mode) +{ + errno_t err = 0; + *f = fopen(filename, mode); + if(*f==NULL){ + err = -1; + } + return err; +} + +static inline int se_copy_file(const char *dst_name, const char *src_name) +{ + int dest = -1; + int source = -1; + ssize_t nr_read; + struct stat stat_buf; + +#ifndef BUF_SIZE +#define BUF_SIZE 4096 +#endif + char buf[BUF_SIZE]; + + /* open the input file */ + source = open(src_name, O_RDONLY); + if(source < 0) + goto error; + + /* get size and permissions of the prebuild DB file */ + if (fstat(source, &stat_buf) != 0) + goto error; + + dest = open(dst_name, O_WRONLY|O_CREAT|O_TRUNC, stat_buf.st_mode); + if(dest < 0) + goto error; + + while ((nr_read = read(source, buf, BUF_SIZE)) > 0) + { + if (write(dest, buf, nr_read) != nr_read) + goto error; + } +#undef BUF_SIZE + + close(dest); + close(source); + return 0; + +error: + if(dest>=0)close(dest); + if(source>=0)close(source); + return -1; +} + +#ifdef __cplusplus +template +int sprintf_s(char (&dst)[_Size], const char *format, ...) +{ + va_list argptr; + int cnt; + va_start(argptr, format); + cnt = vsprintf(dst, format, argptr); + va_end(argptr); + return cnt; +} + +template +int _snprintf_s(char (&dst)[_Size], size_t max_count, const char *format, ...) +{ + va_list argptr; + int cnt; + va_start(argptr, format); + cnt = vsnprintf(dst, max_count, format, argptr); + va_end(argptr); + return cnt; +} + +#endif + +#endif diff --git a/sgx-jvm/linux-sgx/common/inc/internal/se_string.h b/sgx-jvm/linux-sgx/common/inc/internal/se_string.h new file mode 100644 index 0000000000..e5185617df --- /dev/null +++ b/sgx-jvm/linux-sgx/common/inc/internal/se_string.h @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef _SE_STRING_H_ +#define _SE_STRING_H_ + +#include "se_memcpy.h" +#include + + +#ifndef _ERRNO_T_DEFINED +#define _ERRNO_T_DEFINED +typedef int errno_t; +#endif + +static inline errno_t strcat_s(char *dst, size_t max_size, const char *src) +{ + if(strlen(dst)+strlen(src)+1>max_size)return -1; + strcat(dst, src); + return 0; +} + +static inline errno_t strcpy_s(char *dst, size_t max_size, const char *src) +{ + if(strnlen(src, max_size)+1>max_size)return -1; + strcpy(dst, src); + return 0; +} + +#define _strnicmp strncasecmp +static inline errno_t strncat_s(char *dst, size_t max_size, const char *src, size_t max_count) +{ + size_t len = strnlen(src,max_count); + len+=strnlen(dst, max_size)+1; + if(len>max_size)return -1; + strncat(dst, src, max_count); + return 0; +} + +#define _strdup strdup +#define strnlen_s strnlen + + + +#endif diff --git a/sgx-jvm/linux-sgx/common/inc/internal/se_thread.h b/sgx-jvm/linux-sgx/common/inc/internal/se_thread.h new file mode 100644 index 0000000000..d6432b80b1 --- /dev/null +++ b/sgx-jvm/linux-sgx/common/inc/internal/se_thread.h @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + + + +#ifndef _SE_THREAD_H_ +#define _SE_THREAD_H_ + + +#ifndef _GNU_SOURCE +#define _GNU_SOURCE /* for PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP */ +#endif +#include +#include +#include +#include +typedef pthread_mutex_t se_mutex_t; +typedef pid_t se_thread_id_t; +typedef pthread_key_t se_tls_index_t; + +#ifdef __cplusplus +extern "C" { +#endif +/* +@mutex: A pointer to the critical section object. +@return value: If the function succeeds, the return value is nonzero.If the function fails, the return value is zero. +*/ +void se_mutex_init(se_mutex_t* mutex); +int se_mutex_lock(se_mutex_t* mutex); +int se_mutex_unlock(se_mutex_t* mutex); +int se_mutex_destroy(se_mutex_t* mutex); + +unsigned int se_get_threadid(void); + +/* tls functions */ +int se_tls_alloc(se_tls_index_t *tls_index); +int se_tls_free(se_tls_index_t tls_index); +void * se_tls_get_value(se_tls_index_t tls_index); +int se_tls_set_value(se_tls_index_t tls_index, void *tls_value); + +/* se_thread_handle_t se_create_thread(size_t stack_size, thread_start_routine_t start_routine, void *param, se_thread_t* thread); */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/sgx-jvm/linux-sgx/common/inc/internal/se_time.h b/sgx-jvm/linux-sgx/common/inc/internal/se_time.h new file mode 100644 index 0000000000..d1492021ea --- /dev/null +++ b/sgx-jvm/linux-sgx/common/inc/internal/se_time.h @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef _SE_TIME_H_ +#define _SE_TIME_H_ + +#include "se_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* +*@milli_seconds: the time range for sleep. It is milliseconds. +*/ +void se_sleep(uint32_t milli_seconds); +uint64_t se_get_tick_count_freq(void); +uint64_t se_get_tick_count(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/sgx-jvm/linux-sgx/common/inc/internal/se_trace.h b/sgx-jvm/linux-sgx/common/inc/internal/se_trace.h new file mode 100644 index 0000000000..68967939d7 --- /dev/null +++ b/sgx-jvm/linux-sgx/common/inc/internal/se_trace.h @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +/* + *This file wrapper some trace output. +*/ + +#ifndef _SE_DEBUG_H_ +#define _SE_DEBUG_H_ + +#include +#include + +typedef enum +{ + SE_TRACE_ERROR, + SE_TRACE_WARNING, + SE_TRACE_NOTICE, + SE_TRACE_DEBUG +} se_trace_t; + +#ifndef SE_DEBUG_LEVEL +/* Each module need define their own SE_DEBUG_LEVEL */ +#define SE_DEBUG_LEVEL SE_TRACE_ERROR +#endif + +#ifdef __cplusplus +extern "C" { +#endif +int se_trace_internal(int debug_level, const char *fmt, ...); + +#ifdef __cplusplus +} +#endif + +/* For libraries, we usually define DISABLE_TRACE to disable any trace. */ +/* For apps, we usually enable trace. */ +#ifdef DISABLE_TRACE +#define SE_TRACE(...) +#define se_trace(...) +#else /* DISABLE_TRACE */ +#define se_trace(debug_level, fmt, ...) \ + do { \ + if(debug_level <= SE_DEBUG_LEVEL) \ + se_trace_internal(debug_level, fmt, ##__VA_ARGS__); \ + }while(0) + +/* For compatibility, SE_TRACE/se_trace is used in old code. */ +/* New code should use SE_TRACE_DEBUG, SE_TRACE_NOTICE, SE_TRACE_WARNING, SE_TRACE_ERROR */ +#define SE_TRACE(debug_level, fmt, ...) \ + se_trace(debug_level, "[%s %s:%d] " fmt, __FUNCTION__, __FILE__, __LINE__, ##__VA_ARGS__) +#endif/* DISABLE_TRACE */ + +/* SE_TRACE_DEBUG and SE_TRACE_NOTICE print the debug information plus message. */ +#define SE_TRACE_DEBUG(fmt, ...) se_trace(SE_TRACE_DEBUG, "[%s %s:%d] " fmt, __FUNCTION__, __FILE__, __LINE__, ##__VA_ARGS__) +#define SE_TRACE_NOTICE(fmt, ...) se_trace(SE_TRACE_NOTICE, "[%s %s:%d] " fmt, __FUNCTION__, __FILE__, __LINE__, ##__VA_ARGS__) +/* SE_TRACE_WARNING and SE_TRACE_ERROR only print message. */ +#define SE_TRACE_WARNING(fmt, ...) se_trace(SE_TRACE_WARNING, fmt, ##__VA_ARGS__) +#define SE_TRACE_ERROR(fmt, ...) se_trace(SE_TRACE_ERROR, fmt, ##__VA_ARGS__) + +#endif diff --git a/sgx-jvm/linux-sgx/common/inc/internal/se_types.h b/sgx-jvm/linux-sgx/common/inc/internal/se_types.h new file mode 100644 index 0000000000..c3b29e047a --- /dev/null +++ b/sgx-jvm/linux-sgx/common/inc/internal/se_types.h @@ -0,0 +1,93 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +/* + * This file is to define some types that is platform independent. +*/ + +#ifndef _SE_TYPE_H_ +#define _SE_TYPE_H_ +#include "se_cdefs.h" + +#ifdef SE_DRIVER + +typedef INT8 int8_t; +typedef UINT8 uint8_t; +typedef INT16 int16_t; +typedef UINT16 uint16_t; +typedef INT32 int32_t; +typedef UINT32 uint32_t; +typedef INT64 int64_t; +typedef UINT64 uint64_t; + +#else + +#include +#include + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +#endif + +#if defined(SE_64) + +#define PADDED_POINTER(t, p) t* p +#define PADDED_DWORD(d) uint64_t d +#define PADDED_LONG(l) int64_t l +#define REG(name) r##name +#ifdef SE_SIM_EXCEPTION +#define REG_ALIAS(name) R##name +#endif +#define REGISTER(name) uint64_t REG(name) + +#else /* !defined(SE_64) */ + +#define PADDED_POINTER(t, p) t* p; void* ___##p##_pad_to64_bit +#define PADDED_DWORD(d) uint32_t d; uint32_t ___##d##_pad_to64_bit +#define PADDED_LONG(l) int32_t l; int32_t ___##l##_pad_to64_bit + +#define REG(name) e##name + +#ifdef SE_SIM_EXCEPTION +#define REG_ALIAS(name) E##name +#endif + +#define REGISTER(name) uint32_t REG(name); uint32_t ___##e##name##_pad_to64_bit + +#endif /* !defined(SE_64) */ + +#endif diff --git a/sgx-jvm/linux-sgx/common/inc/internal/se_vendor.h b/sgx-jvm/linux-sgx/common/inc/internal/se_vendor.h new file mode 100644 index 0000000000..ce2f1674bc --- /dev/null +++ b/sgx-jvm/linux-sgx/common/inc/internal/se_vendor.h @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef _SE_VENDOR_H_ +#define _SE_VENDOR_H_ + +#define INTEL_VENDOR_ID 0x8086 +#define AE_PRODUCT_ID 0x1 + +#endif diff --git a/sgx-jvm/linux-sgx/common/inc/internal/se_version.h b/sgx-jvm/linux-sgx/common/inc/internal/se_version.h new file mode 100644 index 0000000000..84814cfc28 --- /dev/null +++ b/sgx-jvm/linux-sgx/common/inc/internal/se_version.h @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#define STRFILEVER "1.7.100.36470" + diff --git a/sgx-jvm/linux-sgx/common/inc/internal/se_wrapper.h b/sgx-jvm/linux-sgx/common/inc/internal/se_wrapper.h new file mode 100644 index 0000000000..0edf25d8be --- /dev/null +++ b/sgx-jvm/linux-sgx/common/inc/internal/se_wrapper.h @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +/* + *This file wrapper all the head file that is platform dependent. +*/ +#ifndef _SE_WRAPPER_H_ +#define _SE_WRAPPER_H_ + +#include "se_cdefs.h" +#include "se_types.h" +#include "se_thread.h" +#include "se_trace.h" +#include "se_time.h" +#include "se_event.h" +#include "se_rwlock.h" +#include "se_atomic.h" +#include "se_memcpy.h" +#include "se_string.h" +#include "se_stdio.h" + +#endif diff --git a/sgx-jvm/linux-sgx/common/inc/internal/sgx_memset_s.h b/sgx-jvm/linux-sgx/common/inc/internal/sgx_memset_s.h new file mode 100644 index 0000000000..64956b384a --- /dev/null +++ b/sgx-jvm/linux-sgx/common/inc/internal/sgx_memset_s.h @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef _SE_MEMSET_S_H +#define _SE_MEMSET_S_H +#include +#ifdef __cplusplus +extern "C" +#endif +int memset_s(void *s, size_t smax, int c, size_t n); + +#endif diff --git a/sgx-jvm/linux-sgx/common/inc/internal/sgx_profile.h b/sgx-jvm/linux-sgx/common/inc/internal/sgx_profile.h new file mode 100644 index 0000000000..3c83d1a396 --- /dev/null +++ b/sgx-jvm/linux-sgx/common/inc/internal/sgx_profile.h @@ -0,0 +1,104 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + + +/* +Some notes for using the profiling macros + +1. Define _PROFILE_ before including "sgx_profile.h" will enable the profiling, + also need to include sgx_profile.cpp in the compiling process +2. When use it in multi-threaded application, please don't trigger profiling in multiple threads at the same time. + The implementation is not thread-safe now, to avoid additional latency introduced by locks +3. PROFILE_OUTPUT macro should only be used once before application exits +4. PROFILE_START and PROFILE_END should be paired, otherwise PROFILE_OUTPUT will abort the program when detects the mismatch + +A simple example to use PROFILE macro + +#define _PROFILE_ +#include "sgx_profile.h" + +... +PROFILE_INIT(); +... + +PROFILE_START("func1"); +func1(); +PROFILE_END("func1"); + +... + +PROFILE_START("func2"); +func2(); +PROFILE_END("func2"); + +... + +PROFILE_OUTPUT("C:\\work\\output.csv"); +... +*/ + + +#ifndef _SGX_PROFILE_H_ +#define _SGX_PROFILE_H_ + + +#if defined(_PROFILE_) +#define PRO_START 0 +#define PRO_END 1 + +#if defined(__cplusplus) +extern "C" +{ +#endif + +void profile_init(); +void profile_start(const char* str); /* 'str' must be global string. Do not use string in stack. */ +void profile_end(const char * str); +void profile_output(const char* filename); + +#if defined(__cplusplus) +} +#endif + +#define PROFILE_INIT() profile_init() +#define PROFILE_START(x) profile_start(x) +#define PROFILE_END(x) profile_end(x) +#define PROFILE_OUTPUT(x) profile_output(x) + +#else +#define PROFILE_INIT() +#define PROFILE_START(x) +#define PROFILE_END(x) +#define PROFILE_OUTPUT(x) +#endif + + +#endif diff --git a/sgx-jvm/linux-sgx/common/inc/internal/sgx_read_rand.h b/sgx-jvm/linux-sgx/common/inc/internal/sgx_read_rand.h new file mode 100644 index 0000000000..05d79861f3 --- /dev/null +++ b/sgx-jvm/linux-sgx/common/inc/internal/sgx_read_rand.h @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef __SGX_READ_RAND_H__ +#define __SGX_READ_RAND_H__ +#include "sgx.h" +#include "sgx_defs.h" +#ifdef __cplusplus +extern "C" +#endif +sgx_status_t SGXAPI sgx_read_rand(unsigned char *buf, size_t size); +#endif diff --git a/sgx-jvm/linux-sgx/common/inc/internal/sgx_sha256_128.h b/sgx-jvm/linux-sgx/common/inc/internal/sgx_sha256_128.h new file mode 100644 index 0000000000..52602d0ec2 --- /dev/null +++ b/sgx-jvm/linux-sgx/common/inc/internal/sgx_sha256_128.h @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + + +#ifndef _SHA256_128_H +#define _SHA256_128_H + +#include "stdlib.h" +#include "sgx_utils.h" +#include "sgx_tcrypto.h" +#include "math.h" +#include "string.h" + +#define SGX_SHA256_128_HASH_SIZE 16 +typedef uint8_t sgx_sha256_128_hash_t[SGX_SHA256_128_HASH_SIZE]; + +sgx_status_t SGXAPI sgx_sha256_128_msg(const uint8_t *p_src, uint32_t src_len, sgx_sha256_128_hash_t *p_hash); + +#endif diff --git a/sgx-jvm/linux-sgx/common/inc/internal/sgx_tcrypto_internal.h b/sgx-jvm/linux-sgx/common/inc/internal/sgx_tcrypto_internal.h new file mode 100644 index 0000000000..666b36125a --- /dev/null +++ b/sgx-jvm/linux-sgx/common/inc/internal/sgx_tcrypto_internal.h @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef _SGX_TCRYPTO_INTERNAL_H_ +#define _SGX_TCRYPTO_INTERNAL_H_ + +#include "sgx_tcrypto.h" + +typedef struct _sgx_ec256_dh_shared512_t +{ + uint8_t x[SGX_ECP256_KEY_SIZE]; + uint8_t y[SGX_ECP256_KEY_SIZE]; +} sgx_ec256_dh_shared512_t; + +#ifdef __cplusplus +extern "C" { +#endif + + /* Computes 512-bit DH shared key based on private B key (local) and remote public Ga Key + * Parameters: + * Return: sgx_status_t - SGX_SUCCESS or failure as defined in sgx_error.h + * Inputs: sgx_ecc_state_handle_t ecc_handle - Handle to the ECC crypto system + * sgx_ec256_private_t *p_private_b - Pointer to the local private key + * sgx_ec256_public_t *p_public_ga - Pointer to the remote public key + * Output: sgx_ec256_dh_shared512_t *p_shared_key - Pointer to the 512-bit shared DH key + */ + sgx_status_t SGXAPI sgx_ecc256_compute_shared_dhkey512(sgx_ec256_private_t *p_private_b, + sgx_ec256_public_t *p_public_ga, + sgx_ec256_dh_shared512_t *p_shared_key, + sgx_ecc_state_handle_t ecc_handle); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/sgx-jvm/linux-sgx/common/inc/internal/tae_service_internal.h b/sgx-jvm/linux-sgx/common/inc/internal/tae_service_internal.h new file mode 100644 index 0000000000..948402c2bd --- /dev/null +++ b/sgx-jvm/linux-sgx/common/inc/internal/tae_service_internal.h @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef _TAE_SERVICE_INTERNAL_H_ +#define _TAE_SERVICE_INTERNAL_H_ + +#include +#include "sgx.h" +#include "arch.h" +#include "sgx_tae_service.h" +#include "pse_types.h" + +#pragma pack(push, 1) + +typedef struct _se_ps_sec_prop_desc_internal +{ + uint32_t desc_type; /* Type of this descriptor. Must be 0 */ + sgx_prod_id_t pse_prod_id; /* REPORT(PSE).ProdID */ + sgx_isv_svn_t pse_isvsvn; /* REPORT(PSE).ISVSVN */ + uint32_t pse_miscselect; /* REPORT(PSE).MISC_SELECT */ + uint32_t reserved1; /* For DESC_TYPE=0, MBZ */ + sgx_attributes_t pse_attributes; /* REPORT(PSE).ATTRIBUTES */ + sgx_measurement_t pse_mr_signer; /* REPORT(PSE).MRSIGNER */ + uint32_t reserved2[16]; + /*the following will be provided by PSE from CSE_SEC_PROP */ + cse_sec_prop_t cse_sec_prop; +} se_ps_sec_prop_desc_internal_t; + +se_static_assert(sizeof(se_ps_sec_prop_desc_internal_t) == sizeof(sgx_ps_sec_prop_desc_t)); + +#pragma pack(pop) + +#endif diff --git a/sgx-jvm/linux-sgx/common/inc/internal/thread_data.h b/sgx-jvm/linux-sgx/common/inc/internal/thread_data.h new file mode 100644 index 0000000000..da2bfe7abc --- /dev/null +++ b/sgx-jvm/linux-sgx/common/inc/internal/thread_data.h @@ -0,0 +1,125 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef _THREAD_DATA_H_ +#define _THREAD_DATA_H_ + +#include "se_types.h" +#include "se_cdefs.h" + +#ifdef TD_SUPPORT_MULTI_PLATFORM +/* To enable the SignTool to sign both 32/64-bit Enclave for ELF, + * we need to make the struct `thread_data_t' have a consistent + * definition for 32/64-bit compiler. + * + * We achieve it by forcing the compiler to check pre-defined macros + * `RTS_SYSTEM_WORDSIZE' + * + * |--------------------------+-------| + * | RTS_SYSTEM_WORDSIZE = 32 | ELF32 | + * |--------------------------+-------| + * | RTS_SYSTEM_WORDSIZE = 64 | ELF64 | + * + */ +# ifndef RTS_SYSTEM_WORDSIZE +# error RTS_SYSTEM_WORDSIZE should be pre-defined. +# endif + +/* Avoid to use `uintptr_t' in the struct `thread_data_t' and its members. */ +# if RTS_SYSTEM_WORDSIZE == 32 +typedef uint32_t sys_word_t; +# elif RTS_SYSTEM_WORDSIZE == 64 +typedef uint64_t sys_word_t; +# else +# error Invalid value for 'RTS_SYSTEM_WORDSIZE'. +# endif + +#else + +/* For uRTS, there is no need to define the macro 'TD_SUPPORT_MULTI_PLATFORM' */ +typedef size_t sys_word_t; + +/* SE_32 and SE_64 are defined in "se_cdefs.h" */ +# ifdef SE_32 +# define RTS_SYSTEM_WORDSIZE 32 +# elif defined(SE_64) +# define RTS_SYSTEM_WORDSIZE 64 +# else +# error Unknown system word size. +# endif + +#endif /* ! TD_SUPPORT_MULTI_PLATFORM */ + +/* The data structure currently is naturally aligned regardless of the value of + * RTS_SYSTEM_WORDSIZE. + * + * However, we need to take care when modifying the data structure in future. + */ + +typedef struct _thread_data_t +{ + sys_word_t self_addr; + sys_word_t last_sp; /* set by urts, relative to TCS */ + sys_word_t stack_base_addr; /* set by urts, relative to TCS */ + sys_word_t stack_limit_addr; /* set by urts, relative to TCS */ + sys_word_t first_ssa_gpr; /* set by urts, relative to TCS */ + sys_word_t stack_guard; /* GCC expects start_guard at 0x14 on x86 and 0x28 on x64 */ + + sys_word_t reserved; + sys_word_t ssa_frame_size; /* set by urts, in pages (se_ptrace.c needs to know its offset). */ + sys_word_t last_error; /* init to be 0. Used by trts. */ + +#ifdef TD_SUPPORT_MULTI_PLATFORM + sys_word_t m_next; /* next TD used by trusted thread library (of type "struct _thread_data *") */ +#else + struct _thread_data_t *m_next; +#endif + sys_word_t tls_addr; /* points to TLS pages */ + sys_word_t tls_array; /* points to TD.tls_addr relative to TCS */ +#ifdef TD_SUPPORT_MULTI_PLATFORM + sys_word_t exception_flag; /* mark how many exceptions are being handled */ +#else + intptr_t exception_flag; +#endif + sys_word_t cxx_thread_info[6]; +} thread_data_t; + +#ifdef __cplusplus +extern "C" { +#endif + +thread_data_t *get_thread_data(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/sgx-jvm/linux-sgx/common/inc/internal/trts_inst.h b/sgx-jvm/linux-sgx/common/inc/internal/trts_inst.h new file mode 100644 index 0000000000..09ed8ae9f5 --- /dev/null +++ b/sgx-jvm/linux-sgx/common/inc/internal/trts_inst.h @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef _TRTS_INST_H_ +#define _TRTS_INST_H_ + +#include "sgx.h" + +/* Attention: + * if the following alignment requirement changes, go to selib to + * review the memory allocation of sgx_create_report and sgx_get_key. + */ +#define TARGET_INFO_ALIGN_SIZE 512 +#define REPORT_DATA_ALIGN_SIZE 128 +#define REPORT_ALIGN_SIZE 512 +#define KEY_REQUEST_ALIGN_SIZE 512 +#define KEY_ALIGN_SIZE 16 + +#define BIT_ERROR(x) (1 << (x)) + +typedef enum _egetkey_status_t +{ + EGETKEY_SUCCESS = 0, + EGETKEY_INVALID_ATTRIBUTE = BIT_ERROR(1), + EGETKEY_INVALID_CPUSVN = BIT_ERROR(5), + EGETKEY_INVALID_ISVSVN = BIT_ERROR(6), + EGETKEY_INVALID_KEYNAME = BIT_ERROR(8), +} egetkey_status_t; + +#ifdef __cplusplus +extern "C" { +#endif + +void do_ereport(const sgx_target_info_t *target_info, const sgx_report_data_t *report_data, sgx_report_t *report); +int do_egetkey(const sgx_key_request_t *key_request, sgx_key_128bit_t *key); +uint32_t do_rdrand(uint32_t *rand); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/sgx-jvm/linux-sgx/common/inc/internal/uae_service_internal.h b/sgx-jvm/linux-sgx/common/inc/internal/uae_service_internal.h new file mode 100644 index 0000000000..75428cadef --- /dev/null +++ b/sgx-jvm/linux-sgx/common/inc/internal/uae_service_internal.h @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef _UAE_SERVICE_INTERNAL_H_ +#define _UAE_SERVICE_INTERNAL_H_ + +#include +#include "arch.h" +#include "sgx_urts.h" + +#ifdef __cplusplus +extern "C" { +#endif +/** + * Function to get launch token of a enclave + * + * @param signature[in] Signature of enclave to be launched. + * @param attribute[in] Attribute of enclave to be launched. + * @param launch_token[out] Vontains launch token. + * @return if a launch token is generated,return SGX_SCCUESS, otherwise return general error code SGX_ERROR_SERVICE_UNAVAILABLE + * SGX_ERROR_SERVICE_TIMEOUT, or SGX_ERROR_SERVICE_INVALID_PRIVILEGE, SGX_ERROR_INVALID_PARAMETER + * to indicate special error condition. + */ +sgx_status_t SGXAPI get_launch_token(const enclave_css_t* signature, const sgx_attributes_t* attribute, sgx_launch_token_t* launch_token); + +/* Return SGX_SUCCESS on success */ +sgx_status_t create_session_ocall(uint32_t* sid, uint8_t* dh_msg1, uint32_t dh_msg1_size, uint32_t timeout); + +/* Return SGX_SUCCESS on success */ +sgx_status_t exchange_report_ocall(uint32_t sid, const uint8_t* dh_msg2, uint32_t dh_msg2_size, uint8_t* dh_msg3, uint32_t dh_msg3_size, uint32_t timeout); + +/* Return SGX_SUCCESS on success */ +sgx_status_t close_session_ocall(uint32_t sid, uint32_t timeout); + +/* Return SGX_SUCCESS on success */ +sgx_status_t invoke_service_ocall( + const uint8_t* pse_message_req, uint32_t pse_message_req_size, + uint8_t* pse_message_resp, uint32_t pse_message_resp_size, + uint32_t timeout + ); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/sgx-jvm/linux-sgx/common/inc/internal/uncopyable.h b/sgx-jvm/linux-sgx/common/inc/internal/uncopyable.h new file mode 100644 index 0000000000..b271953f79 --- /dev/null +++ b/sgx-jvm/linux-sgx/common/inc/internal/uncopyable.h @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef _UNCOPYABLE_H_ +#define _UNCOPYABLE_H_ + +/* Similiar to boost::noncopyable */ +class Uncopyable { +protected: + Uncopyable() {} + ~Uncopyable() {} + +private: + /* Disable copying */ + Uncopyable(const Uncopyable&); + Uncopyable& operator=(const Uncopyable&); +}; + +#endif diff --git a/sgx-jvm/linux-sgx/common/inc/internal/util.h b/sgx-jvm/linux-sgx/common/inc/internal/util.h new file mode 100644 index 0000000000..ce066ec32a --- /dev/null +++ b/sgx-jvm/linux-sgx/common/inc/internal/util.h @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef _UTIL_H_ +#define _UTIL_H_ + +#include "arch.h" +#include + +#ifdef __cplusplus +#define GET_PTR(t, p, offset) reinterpret_cast( reinterpret_cast(p) + static_cast(offset) ) +#define PTR_DIFF(p1, p2) ((reinterpret_cast(p1) - reinterpret_cast(p2))) +#else +#define GET_PTR(t, p, offset) (t*)( (size_t)(p) + (size_t)(offset) ) +#define PTR_DIFF(p1, p2) ((size_t)(p1) - (size_t)(p2)) +#endif + +#define DIFF(p1, p2) (assert((size_t)(p1) >= (size_t)(p2)), ((size_t)(p1) - (size_t)(p2))) +#define DIFF64(p1, p2) (assert((uint64_t)(p1) >= (uint64_t)(p2)), ((uint64_t)(p1) - (uint64_t)(p2))) + +#define SE_PAGE_SHIFT 12 +#define SE_BULK_PAGE_FRAME_SHIFT 4 +#define SE_BULK_PAGE_FRAME_SIZE (1 << SE_BULK_PAGE_FRAME_SHIFT) +#define SE_BULK_PAGE_FRAME_MASK (SE_BULK_PAGE_FRAME_SIZE-1) +#define SE_BULK_PAGE_SHIFT (SE_PAGE_SHIFT + SE_BULK_PAGE_FRAME_SHIFT) +#define SE_BULK_PAGE_SIZE (1 << SE_BULK_PAGE_SHIFT) +#define SE_GUARD_PAGE_SHIFT SE_PAGE_SHIFT +#define SE_GUARD_PAGE_SIZE SE_PAGE_SIZE + +#define ROUND_TO(x, align) (((x) + ((align)-1)) & ~((align)-1)) +#define ROUND_TO_PAGE(x) ROUND_TO(x, SE_PAGE_SIZE) +#define TRIM_TO_PAGE(x) ((x) & ~(SE_PAGE_SIZE-1)) +#define PAGE_OFFSET(x) ((x) & (SE_PAGE_SIZE -1)) +#ifdef __cplusplus +#define PAGE_ALIGN(t, x) reinterpret_cast((reinterpret_cast(x)+(SE_PAGE_SIZE-1)) & (~(SE_PAGE_SIZE-1))) +#else +#define PAGE_ALIGN(t, x) (t*)( ((size_t)(x)+(SE_PAGE_SIZE-1)) & (~(SE_PAGE_SIZE-1)) ) +#endif + +#define IS_PAGE_ALIGNED(x) (!((size_t)(x)&(SE_PAGE_SIZE-1))) + +#define MIN(x, y) (((x)>(y))?(y):(x)) +#define MAX(x, y) (((x)>(y))?(x):(y)) +#define ARRAY_LENGTH(x) (sizeof(x)/sizeof(x[0])) + +/* used to eliminate `unused variable' warning */ +#define UNUSED(val) (void)(val) + +#include +#define container_of(ptr, type, member) (type *)( (char *)(ptr) - offsetof(type,member) ) + +#endif diff --git a/sgx-jvm/linux-sgx/common/inc/internal/xsave.h b/sgx-jvm/linux-sgx/common/inc/internal/xsave.h new file mode 100644 index 0000000000..431d453542 --- /dev/null +++ b/sgx-jvm/linux-sgx/common/inc/internal/xsave.h @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef _XSAVE_H_ +#define _XSAVE_H_ + +#include "se_types.h" + + +#define XSAVE_ALIGN_SIZE 64 +#define FXSAVE_ALIGN_SIZE 16 +#define FXSAVE_SIZE 528 +/* 512 + 16, the alignment is handled in internal functions */ + +#define CLEAN_XFEATURE_REGS save_and_clean_xfeature_regs(NULL); + +#ifdef __cplusplus +extern "C" { +#endif + +#include "linux/xsave_gnu.h" + +/* implemented in urts_xsave.cpp/trts_xsave.cpp */ +void save_and_clean_xfeature_regs(uint8_t *buffer); +void restore_xfeature_regs(const uint8_t *buffer); + +/* trts_xsave.cpp */ +uint64_t get_xfeature_state(); + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/sgx-jvm/linux-sgx/common/inc/sgx.h b/sgx-jvm/linux-sgx/common/inc/sgx.h new file mode 100644 index 0000000000..7695c65d04 --- /dev/null +++ b/sgx-jvm/linux-sgx/common/inc/sgx.h @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef _SGX_H_ +#define _SGX_H_ + +#include "sgx_error.h" +#include "sgx_attributes.h" +#include "sgx_key.h" +#include "sgx_report.h" + +#endif diff --git a/sgx-jvm/linux-sgx/common/inc/sgx_attributes.h b/sgx-jvm/linux-sgx/common/inc/sgx_attributes.h new file mode 100644 index 0000000000..665ce88547 --- /dev/null +++ b/sgx-jvm/linux-sgx/common/inc/sgx_attributes.h @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef _SGX_ATTRIBUTES_H_ +#define _SGX_ATTRIBUTES_H_ + +#include + +/* Enclave Flags Bit Masks */ +#define SGX_FLAGS_INITTED 0x0000000000000001ULL /* If set, then the enclave is initialized */ +#define SGX_FLAGS_DEBUG 0x0000000000000002ULL /* If set, then the enclave is debug */ +#define SGX_FLAGS_MODE64BIT 0x0000000000000004ULL /* If set, then the enclave is 64 bit */ +#define SGX_FLAGS_PROVISION_KEY 0x0000000000000010ULL /* If set, then the enclave has access to provision key */ +#define SGX_FLAGS_EINITOKEN_KEY 0x0000000000000020ULL /* If set, then the enclave has access to EINITOKEN key */ +#define SGX_FLAGS_RESERVED (~(SGX_FLAGS_INITTED | SGX_FLAGS_DEBUG | SGX_FLAGS_MODE64BIT | SGX_FLAGS_PROVISION_KEY | SGX_FLAGS_EINITOKEN_KEY)) + +/* XSAVE Feature Request Mask */ +#define SGX_XFRM_LEGACY 0x0000000000000003ULL /* Legacy XFRM */ +#define SGX_XFRM_AVX 0x0000000000000006ULL /* AVX */ +#define SGX_XFRM_AVX512 0x00000000000000E6ULL /* AVX-512 - not supported */ +#define SGX_XFRM_MPX 0x0000000000000018ULL /* MPX - not supported */ + +#define SGX_XFRM_RESERVED (~(SGX_XFRM_LEGACY | SGX_XFRM_AVX)) + +typedef struct _attributes_t +{ + uint64_t flags; + uint64_t xfrm; +} sgx_attributes_t; + +/* define MISCSELECT - all bits are currently reserved */ +typedef uint32_t sgx_misc_select_t; + +typedef struct _sgx_misc_attribute_t { + sgx_attributes_t secs_attr; + sgx_misc_select_t misc_select; +} sgx_misc_attribute_t; + +#endif/* _SGX_ATTRIBUTES_H_ */ diff --git a/sgx-jvm/linux-sgx/common/inc/sgx_cpuid.h b/sgx-jvm/linux-sgx/common/inc/sgx_cpuid.h new file mode 100644 index 0000000000..2d4221280b --- /dev/null +++ b/sgx-jvm/linux-sgx/common/inc/sgx_cpuid.h @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + + + +/** + * File: sgx_cpuid.h + * Description: + * Enquire CPU capabilities via OCALLs. + */ + +#ifndef _SGX_CPUID_H_ +#define _SGX_CPUID_H_ + +#include "sgx_defs.h" +#include "sgx_error.h" + +#ifdef __cplusplus +extern "C" { +#endif + +sgx_status_t SGXAPI sgx_cpuid(int cpuinfo[4], int leaf); +sgx_status_t SGXAPI sgx_cpuidex(int cpuinfo[4], int leaf, int subleaf); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/sgx-jvm/linux-sgx/common/inc/sgx_defs.h b/sgx-jvm/linux-sgx/common/inc/sgx_defs.h new file mode 100644 index 0000000000..4b0a658283 --- /dev/null +++ b/sgx-jvm/linux-sgx/common/inc/sgx_defs.h @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef _SGX_DEFS_H_ +#define _SGX_DEFS_H_ + +/* The following macros are for GCC only */ + +# define SGXAPI + +# ifdef linux +# undef linux +# endif +# define SGX_CXX_NATIVE_HEADER(header) + +# define SGX_CDECL +# define SGX_STDCALL +# define SGX_FASTCALL + +# define SGX_DLLIMPORT +# define SGX_UBRIDGE(attr, fname, args...) attr fname args + + +#define SGX_NOCONVENTION /* Empty. No calling convention specified. */ + +#endif /* !_SGX_DEFS_H_ */ diff --git a/sgx-jvm/linux-sgx/common/inc/sgx_dh.h b/sgx-jvm/linux-sgx/common/inc/sgx_dh.h new file mode 100644 index 0000000000..9860271a0b --- /dev/null +++ b/sgx-jvm/linux-sgx/common/inc/sgx_dh.h @@ -0,0 +1,161 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + + + +#ifndef _SGX_DH_H_ +#define _SGX_DH_H_ + +#include "sgx.h" +#include "sgx_defs.h" +#include "sgx_ecp_types.h" + +#pragma pack(push, 1) + +#define SGX_DH_MAC_SIZE 16 + +#define SGX_DH_SESSION_DATA_SIZE 200 + +typedef struct _sgx_dh_msg1_t +{ + sgx_ec256_public_t g_a; /* the Endian-ness of Ga is Little-Endian */ + sgx_target_info_t target; +} sgx_dh_msg1_t; + +typedef struct _sgx_dh_msg2_t +{ + sgx_ec256_public_t g_b; /* the Endian-ness of Gb is Little-Endian */ + sgx_report_t report; + uint8_t cmac[SGX_DH_MAC_SIZE]; +} sgx_dh_msg2_t; + +typedef struct _sgx_dh_msg3_body_t +{ + sgx_report_t report; + uint32_t additional_prop_length; + uint8_t additional_prop[0]; +} sgx_dh_msg3_body_t; + + +typedef struct _sgx_dh_msg3_t +{ + uint8_t cmac[SGX_DH_MAC_SIZE]; + sgx_dh_msg3_body_t msg3_body; +} sgx_dh_msg3_t; + +typedef struct _sgx_dh_session_enclave_identity_t +{ + sgx_cpu_svn_t cpu_svn; + sgx_misc_select_t misc_select; + uint8_t reserved_1[28]; + sgx_attributes_t attributes; + sgx_measurement_t mr_enclave; + uint8_t reserved_2[32]; + sgx_measurement_t mr_signer; + uint8_t reserved_3[96]; + sgx_prod_id_t isv_prod_id; + sgx_isv_svn_t isv_svn; +} sgx_dh_session_enclave_identity_t; + +typedef enum _sgx_dh_session_role_t +{ + SGX_DH_SESSION_INITIATOR, + SGX_DH_SESSION_RESPONDER +} sgx_dh_session_role_t; + +typedef struct _sgx_dh_session_t +{ + uint8_t sgx_dh_session[SGX_DH_SESSION_DATA_SIZE]; +} sgx_dh_session_t; +#pragma pack(pop) +#ifdef __cplusplus +extern "C" { +#endif + +/* The order of calling SGX DH Library APIs is restricted as below */ +/* As session initiator : Step.1 sgx_dh_init_session --> Step.2 sgx_dh_initiator_proc_msg1 --> Step.3 sgx_dh_initiator_proc_msg3 */ +/* As session responder : Step.1 sgx_dh_init_session --> Step.2 sgx_dh_responder_gen_msg1 --> Step.3 sgx_dh_responder_proc_msg2*/ +/* Any out of order calling will cause session establishment failure. */ + +/*Function name: sgx_dh_init_session +** parameter description +**@ [input] role: caller's role in dh session establishment +**@ [output] session: point to dh session structure that is used during establishment, the buffer must be in enclave address space +*/ +sgx_status_t SGXAPI sgx_dh_init_session(sgx_dh_session_role_t role, + sgx_dh_session_t* session); +/*Function name: sgx_dh_responder_gen_msg1 +** parameter description +**@ [output] msg1: point to dh message 1 buffer, and the buffer must be in enclave address space +**@ [input/output] dh_session: point to dh session structure that is used during establishment, and the buffer must be in enclave address space +*/ +sgx_status_t SGXAPI sgx_dh_responder_gen_msg1(sgx_dh_msg1_t* msg1, + sgx_dh_session_t* dh_session); +/*Function name: sgx_dh_initiator_proc_msg1 +** parameter description +**@ [input] msg1: point to dh message 1 buffer generated by session responder, and the buffer must be in enclave address space +**@ [output] msg2: point to dh message 2 buffer, and the buffer must be in enclave address space +**@ [input/output] dh_session: point to dh session structure that is used during establishment, and the buffer must be in enclave address space +*/ +sgx_status_t SGXAPI sgx_dh_initiator_proc_msg1(const sgx_dh_msg1_t* msg1, + sgx_dh_msg2_t* msg2, + sgx_dh_session_t* dh_session); +/*Function name: sgx_dh_responder_proc_msg2 +** parameter description +**@ [input] msg2: point to dh message 2 buffer generated by session initiator, and the buffer must be in enclave address space +**@ [output] msg3: point to dh message 3 buffer generated by session responder in this function, and the buffer must be in enclave address space +**@ [input/output] dh_session: point to dh session structure that is used during establishment, and the buffer must be in enclave address space +**@ [output] aek: AEK derived from shared key. the buffer must be in enclave address space. +**@ [output] initiator_identity: identity information of initiator including isv svn, isv product id, sgx attributes, mr signer, and mr enclave. the buffer must be in enclave address space. +*/ +sgx_status_t SGXAPI sgx_dh_responder_proc_msg2(const sgx_dh_msg2_t* msg2, + sgx_dh_msg3_t* msg3, + sgx_dh_session_t* dh_session, + sgx_key_128bit_t* aek, + sgx_dh_session_enclave_identity_t* initiator_identity); +/*Function name: sgx_dh_initiator_proc_msg3 +** parameter description +**@ [input] msg3: point to dh message 3 buffer generated by session responder, and the buffer must be in enclave address space +**@ [input/output] dh_session: point to dh session structure that is used during establishment, and the buffer must be in enclave address space +**@ [output] aek: AEK derived from shared key. the buffer must be in enclave address space. +**@ [output] responder_identity: identity information of responder including isv svn, isv product id, sgx attributes, mr signer, and mr enclave. the buffer must be in enclave address space. +*/ +sgx_status_t SGXAPI sgx_dh_initiator_proc_msg3(const sgx_dh_msg3_t* msg3, + sgx_dh_session_t* dh_session, + sgx_key_128bit_t* aek, + sgx_dh_session_enclave_identity_t* responder_identity); + +#ifdef __cplusplus +} +#endif + + +#endif diff --git a/sgx-jvm/linux-sgx/common/inc/sgx_ecp_types.h b/sgx-jvm/linux-sgx/common/inc/sgx_ecp_types.h new file mode 100644 index 0000000000..ef935d103b --- /dev/null +++ b/sgx-jvm/linux-sgx/common/inc/sgx_ecp_types.h @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + + + +#ifndef _SGX_ECP_TYPES_H_ +#define _SGX_ECP_TYPES_H_ + +#include + +#pragma pack(push, 1) + +#include "sgx_tcrypto.h" + +#ifndef SGX_FEBITSIZE +#define SGX_FEBITSIZE 256 +#endif + +typedef struct _ecc_param_t +{ + uint32_t eccP[SGX_NISTP_ECP256_KEY_SIZE]; /* EC prime field */ + uint32_t eccA[SGX_NISTP_ECP256_KEY_SIZE]; /* EC curve coefficient A */ + uint32_t eccB[SGX_NISTP_ECP256_KEY_SIZE]; /* EC curve coefficient B */ + uint32_t eccG[2][SGX_NISTP_ECP256_KEY_SIZE]; /* ECC base point */ + uint32_t eccR[SGX_NISTP_ECP256_KEY_SIZE]; /* ECC base point order */ +} sgx_ecc_param_t; + +typedef uint8_t sgx_ec_key_128bit_t[SGX_CMAC_KEY_SIZE]; + +#pragma pack(pop) + +#endif diff --git a/sgx-jvm/linux-sgx/common/inc/sgx_edger8r.h b/sgx-jvm/linux-sgx/common/inc/sgx_edger8r.h new file mode 100644 index 0000000000..f3da7873df --- /dev/null +++ b/sgx-jvm/linux-sgx/common/inc/sgx_edger8r.h @@ -0,0 +1,107 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + + + +/* + * Here contains functions intended to be used by `sgx_edger8r' only. + * + * ------------------------------------- + * Be warned: use them at your own risk. + * ------------------------------------- + * + */ + +#ifndef _SGX_EDGER8R_H_ +#define _SGX_EDGER8R_H_ + +#include "sgx_defs.h" +#include "sgx_error.h" +#include "sgx_eid.h" +#include /* for size_t */ + +/* The `sgx_edger8r' tool will generate C interfaces. */ +#ifdef __cplusplus +# define SGX_EXTERNC extern "C" +#else +# define SGX_EXTERNC +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* sgx_ocalloc() + * Parameters: + * size - bytes to allocate on the outside stack + * Return Value: + * the pointer to the allocated space on the outside stack + * NULL - fail to allocate +*/ +void* SGXAPI sgx_ocalloc(size_t size); + +/* sgx_ocfree() + * Parameters: + * N/A + * Return Value: + * N/A +*/ +void SGXAPI sgx_ocfree(void); + +/* sgx_ecall() + * Parameters: + * eid - the enclave id + * index - the index of the trusted function + * ocall_table - the address of the OCALL table + * ms - the pointer to the marshaling struct + * Return Value: + * SGX_SUCCESS on success +*/ +sgx_status_t SGXAPI sgx_ecall(const sgx_enclave_id_t eid, + const int index, + const void* ocall_table, + void* ms); + +/* sgx_ocall() + * Parameters: + * index - the index of the untrusted function + * ms - the pointer to the marshaling struct + * Return Value: + * SGX_SUCCESS on success +*/ +sgx_status_t SGXAPI sgx_ocall(const unsigned int index, + void* ms); + +#ifdef __cplusplus +} +#endif + +#endif /* !_SGX_EDGER8R_H_ */ diff --git a/sgx-jvm/linux-sgx/common/inc/sgx_eid.h b/sgx-jvm/linux-sgx/common/inc/sgx_eid.h new file mode 100644 index 0000000000..ea2dfc6e28 --- /dev/null +++ b/sgx-jvm/linux-sgx/common/inc/sgx_eid.h @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef _SGX_EID_H_ +#define _SGX_EID_H_ + +#include + +typedef uint64_t sgx_enclave_id_t; + +#endif diff --git a/sgx-jvm/linux-sgx/common/inc/sgx_error.h b/sgx-jvm/linux-sgx/common/inc/sgx_error.h new file mode 100644 index 0000000000..d093fd8a1e --- /dev/null +++ b/sgx-jvm/linux-sgx/common/inc/sgx_error.h @@ -0,0 +1,92 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef _SGX_ERROR_H_ +#define _SGX_ERROR_H_ + +#define SGX_MK_ERROR(x) (0x00000000|(x)) + +typedef enum _status_t +{ + SGX_SUCCESS = SGX_MK_ERROR(0x0000), + + SGX_ERROR_UNEXPECTED = SGX_MK_ERROR(0x0001), /* Unexpected error */ + SGX_ERROR_INVALID_PARAMETER = SGX_MK_ERROR(0x0002), /* The parameter is incorrect */ + SGX_ERROR_OUT_OF_MEMORY = SGX_MK_ERROR(0x0003), /* Not enough memory is available to complete this operation */ + SGX_ERROR_ENCLAVE_LOST = SGX_MK_ERROR(0x0004), /* Enclave lost after power transition or used in child process created by linux:fork() */ + SGX_ERROR_INVALID_STATE = SGX_MK_ERROR(0x0005), /* SGX API is invoked in incorrect order or state */ + + SGX_ERROR_INVALID_FUNCTION = SGX_MK_ERROR(0x1001), /* The ecall/ocall index is invalid */ + SGX_ERROR_OUT_OF_TCS = SGX_MK_ERROR(0x1003), /* The enclave is out of TCS */ + SGX_ERROR_ENCLAVE_CRASHED = SGX_MK_ERROR(0x1006), /* The enclave is crashed */ + SGX_ERROR_ECALL_NOT_ALLOWED = SGX_MK_ERROR(0x1007), /* The ECALL is not allowed at this time, e.g. ecall is blocked by the dynamic entry table, or nested ecall is not allowed during initialization */ + SGX_ERROR_OCALL_NOT_ALLOWED = SGX_MK_ERROR(0x1008), /* The OCALL is not allowed at this time, e.g. ocall is not allowed during exception handling */ + SGX_ERROR_STACK_OVERRUN = SGX_MK_ERROR(0x1009), /* The enclave is running out of stack */ + + SGX_ERROR_UNDEFINED_SYMBOL = SGX_MK_ERROR(0x2000), /* The enclave image has undefined symbol. */ + SGX_ERROR_INVALID_ENCLAVE = SGX_MK_ERROR(0x2001), /* The enclave image is not correct. */ + SGX_ERROR_INVALID_ENCLAVE_ID = SGX_MK_ERROR(0x2002), /* The enclave id is invalid */ + SGX_ERROR_INVALID_SIGNATURE = SGX_MK_ERROR(0x2003), /* The signature is invalid */ + SGX_ERROR_NDEBUG_ENCLAVE = SGX_MK_ERROR(0x2004), /* The enclave is signed as product enclave, and can not be created as debuggable enclave. */ + SGX_ERROR_OUT_OF_EPC = SGX_MK_ERROR(0x2005), /* Not enough EPC is available to load the enclave */ + SGX_ERROR_NO_DEVICE = SGX_MK_ERROR(0x2006), /* Can't open SGX device */ + SGX_ERROR_MEMORY_MAP_CONFLICT= SGX_MK_ERROR(0x2007), /* Page mapping failed in driver */ + SGX_ERROR_INVALID_METADATA = SGX_MK_ERROR(0x2009), /* The metadata is incorrect. */ + SGX_ERROR_DEVICE_BUSY = SGX_MK_ERROR(0x200c), /* Device is busy, mostly EINIT failed. */ + SGX_ERROR_INVALID_VERSION = SGX_MK_ERROR(0x200d), /* Metadata version is inconsistent between uRTS and sgx_sign or uRTS is incompatible with current platform. */ + SGX_ERROR_MODE_INCOMPATIBLE = SGX_MK_ERROR(0x200e), /* The target enclave 32/64 bit mode or sim/hw mode is incompatible with the mode of current uRTS. */ + SGX_ERROR_ENCLAVE_FILE_ACCESS = SGX_MK_ERROR(0x200f), /* Can't open enclave file. */ + SGX_ERROR_INVALID_MISC = SGX_MK_ERROR(0x2010), /* The MiscSelct/MiscMask settings are not correct.*/ + + SGX_ERROR_MAC_MISMATCH = SGX_MK_ERROR(0x3001), /* Indicates verification error for reports, sealed datas, etc */ + SGX_ERROR_INVALID_ATTRIBUTE = SGX_MK_ERROR(0x3002), /* The enclave is not authorized */ + SGX_ERROR_INVALID_CPUSVN = SGX_MK_ERROR(0x3003), /* The cpu svn is beyond platform's cpu svn value */ + SGX_ERROR_INVALID_ISVSVN = SGX_MK_ERROR(0x3004), /* The isv svn is greater than the enclave's isv svn */ + SGX_ERROR_INVALID_KEYNAME = SGX_MK_ERROR(0x3005), /* The key name is an unsupported value */ + + SGX_ERROR_SERVICE_UNAVAILABLE = SGX_MK_ERROR(0x4001), /* Indicates aesm didn't response or the requested service is not supported */ + SGX_ERROR_SERVICE_TIMEOUT = SGX_MK_ERROR(0x4002), /* The request to aesm time out */ + SGX_ERROR_AE_INVALID_EPIDBLOB = SGX_MK_ERROR(0x4003), /* Indicates epid blob verification error */ + SGX_ERROR_SERVICE_INVALID_PRIVILEGE = SGX_MK_ERROR(0x4004), /* Enclave has no privilege to get launch token */ + SGX_ERROR_EPID_MEMBER_REVOKED = SGX_MK_ERROR(0x4005), /* The EPID group membership is revoked. */ + SGX_ERROR_UPDATE_NEEDED = SGX_MK_ERROR(0x4006), /* SGX needs to be updated */ + SGX_ERROR_NETWORK_FAILURE = SGX_MK_ERROR(0x4007), /* Network connecting or proxy setting issue is encountered */ + SGX_ERROR_AE_SESSION_INVALID = SGX_MK_ERROR(0x4008), /* Session is invalid or ended by server */ + SGX_ERROR_BUSY = SGX_MK_ERROR(0x400a), /* The requested service is temporarily not availabe */ + SGX_ERROR_MC_NOT_FOUND = SGX_MK_ERROR(0x400c), /* The Monotonic Counter doesn't exist or has been invalided */ + SGX_ERROR_MC_NO_ACCESS_RIGHT = SGX_MK_ERROR(0x400d), /* Caller doesn't have the access right to specified VMC */ + SGX_ERROR_MC_USED_UP = SGX_MK_ERROR(0x400e), /* Monotonic counters are used out */ + SGX_ERROR_MC_OVER_QUOTA = SGX_MK_ERROR(0x400f), /* Monotonic counters exceeds quota limitation */ + SGX_ERROR_KDF_MISMATCH = SGX_MK_ERROR(0x4011), /* Key derivation function doesn't match during key exchange */ + +} sgx_status_t; + +#endif diff --git a/sgx-jvm/linux-sgx/common/inc/sgx_intrin.h b/sgx-jvm/linux-sgx/common/inc/sgx_intrin.h new file mode 100644 index 0000000000..237a1cd6f1 --- /dev/null +++ b/sgx-jvm/linux-sgx/common/inc/sgx_intrin.h @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + + + +#ifndef _SGX_INTRIN_H_ +#define _SGX_INTRIN_H_ + +#if defined(__STDC__) || defined(__cplusplus) +# define __STRING(x) #x +#else +# define __STRING(x) "x" +#endif + +#define _DEPR_MESSAGE(func) __STRING(func)" is deprecated in enclave." + +/* Deprecated GCC Built-ins */ + +# include + +/*#pragma GCC diagnostic error "-Wdeprecated-declarations" */ +#define _SGX_DEPRECATED(__ret_type, __func_name, ...) \ + __attribute__((deprecated(_DEPR_MESSAGE(__func_name)))) \ + __ret_type __func_name(__VA_ARGS__) + +_SGX_DEPRECATED(void, _writefsbase_u32, unsigned int); +_SGX_DEPRECATED(void, _writefsbase_u64, unsigned long long); +_SGX_DEPRECATED(void, _writegsbase_u32, unsigned int); +_SGX_DEPRECATED(void, _writegsbase_u64, unsigned long long); + +_SGX_DEPRECATED(unsigned long long, __rdpmc, int); +_SGX_DEPRECATED(unsigned long long, __rdtsc, void); +_SGX_DEPRECATED(unsigned long long, __rdtscp, unsigned int *); + + +#endif /* _SGX_INTRIN_H_ */ diff --git a/sgx-jvm/linux-sgx/common/inc/sgx_key.h b/sgx-jvm/linux-sgx/common/inc/sgx_key.h new file mode 100644 index 0000000000..b607747843 --- /dev/null +++ b/sgx-jvm/linux-sgx/common/inc/sgx_key.h @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + + + + +/* + * This file is to define Enclave's keys +*/ + +#ifndef _SGX_KEY_H_ +#define _SGX_KEY_H_ + +#include +#include "sgx_attributes.h" + +/* Key Name */ +#define SGX_KEYSELECT_EINITOKEN 0x0000 +#define SGX_KEYSELECT_PROVISION 0x0001 +#define SGX_KEYSELECT_PROVISION_SEAL 0x0002 +#define SGX_KEYSELECT_REPORT 0x0003 +#define SGX_KEYSELECT_SEAL 0x0004 + +/* Key Policy */ +#define SGX_KEYPOLICY_MRENCLAVE 0x0001 /* Derive key using the enclave's ENCLAVE measurement register */ +#define SGX_KEYPOLICY_MRSIGNER 0x0002 /* Derive key using the enclave's SINGER measurement register */ + +#define SGX_KEYID_SIZE 32 +#define SGX_CPUSVN_SIZE 16 + +typedef uint8_t sgx_key_128bit_t[16]; +typedef uint16_t sgx_isv_svn_t; + +typedef struct _sgx_cpu_svn_t +{ + uint8_t svn[SGX_CPUSVN_SIZE]; +} sgx_cpu_svn_t; + +typedef struct _sgx_key_id_t +{ + uint8_t id[SGX_KEYID_SIZE]; +} sgx_key_id_t; + +#define SGX_KEY_REQUEST_RESERVED2_BYTES 436 + +typedef struct _key_request_t +{ + uint16_t key_name; /* Identifies the key required */ + uint16_t key_policy; /* Identifies which inputs should be used in the key derivation */ + sgx_isv_svn_t isv_svn; /* Security Version of the Enclave */ + uint16_t reserved1; /* Must be 0 */ + sgx_cpu_svn_t cpu_svn; /* Security Version of the CPU */ + sgx_attributes_t attribute_mask; /* Mask which ATTRIBUTES Seal keys should be bound to */ + sgx_key_id_t key_id; /* Value for key wear-out protection */ + sgx_misc_select_t misc_mask; /* Mask what MISCSELECT Seal keys bound to */ + uint8_t reserved2[SGX_KEY_REQUEST_RESERVED2_BYTES]; /* Struct size is 512 bytes */ +} sgx_key_request_t; + + +#endif diff --git a/sgx-jvm/linux-sgx/common/inc/sgx_key_exchange.h b/sgx-jvm/linux-sgx/common/inc/sgx_key_exchange.h new file mode 100644 index 0000000000..570945f013 --- /dev/null +++ b/sgx-jvm/linux-sgx/common/inc/sgx_key_exchange.h @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef _SGX_KEY_EXCHANGE_H_ +#define _SGX_KEY_EXCHANGE_H_ + +#include +#include "sgx_quote.h" +#include "sgx_ecp_types.h" +#include "sgx_tae_service.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef uint32_t sgx_ra_context_t; + +typedef sgx_key_128bit_t sgx_ra_key_128_t; + +typedef enum _ra_key_type_t +{ + SGX_RA_KEY_SK = 1, + SGX_RA_KEY_MK, + SGX_RA_KEY_VK, +} sgx_ra_key_type_t; + +typedef struct _ra_msg1_t +{ + sgx_ec256_public_t g_a; /* the Endian-ness of Ga is Little-Endian */ + sgx_epid_group_id_t gid; /* the Endian-ness of GID is Little-Endian */ +} sgx_ra_msg1_t; + + +typedef struct _ra_msg2_t +{ + sgx_ec256_public_t g_b; /* the Endian-ness of Gb is Little-Endian */ + sgx_spid_t spid; + uint16_t quote_type; /* unlinkable Quote(0) or linkable Quote(1) in little endian*/ + uint16_t kdf_id; /* key derivation function id in little endian. */ + sgx_ec256_signature_t sign_gb_ga; /* In little endian */ + sgx_mac_t mac; /* mac_smk(g_b||spid||quote_type||kdf_id||sign_gb_ga) */ + uint32_t sig_rl_size; + uint8_t sig_rl[]; +} sgx_ra_msg2_t; + +typedef struct _ra_msg3_t +{ + sgx_mac_t mac; /* mac_smk(g_a||ps_sec_prop||quote) */ + sgx_ec256_public_t g_a; /* the Endian-ness of Ga is Little-Endian */ + sgx_ps_sec_prop_desc_t ps_sec_prop; + uint8_t quote[]; +} sgx_ra_msg3_t; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/sgx-jvm/linux-sgx/common/inc/sgx_quote.h b/sgx-jvm/linux-sgx/common/inc/sgx_quote.h new file mode 100644 index 0000000000..aec125e893 --- /dev/null +++ b/sgx-jvm/linux-sgx/common/inc/sgx_quote.h @@ -0,0 +1,110 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + + + + /** + * File: sgx_quote.h + * Description: Definition for quote structure. + * + * Quote structure and all relative structure will be defined in this file. + */ + +#ifndef _SGX_QUOTE_H_ +#define _SGX_QUOTE_H_ + +#include "sgx_report.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#pragma pack(push, 1) +typedef uint8_t sgx_epid_group_id_t[4]; + +typedef struct _spid_t +{ + uint8_t id[16]; +} sgx_spid_t; + +typedef struct _basename_t +{ + uint8_t name[32]; +} sgx_basename_t; + + +typedef struct _quote_nonce +{ + uint8_t rand[16]; +} sgx_quote_nonce_t; + +typedef enum +{ + SGX_UNLINKABLE_SIGNATURE, + SGX_LINKABLE_SIGNATURE +} sgx_quote_sign_type_t; + +typedef struct _quote_t +{ + uint16_t version; /* 0 */ + uint16_t sign_type; /* 2 */ + sgx_epid_group_id_t epid_group_id; /* 4 */ + sgx_isv_svn_t qe_svn; /* 8 */ + sgx_isv_svn_t pce_svn; /* 10 */ + uint32_t xeid; /* 12 */ + sgx_basename_t basename; /* 16 */ + sgx_report_body_t report_body; /* 48 */ + uint32_t signature_len; /* 432 */ + uint8_t signature[]; /* 436 */ +} sgx_quote_t; + +#define SGX_PLATFORM_INFO_SIZE 101 +typedef struct _platform_info +{ + uint8_t platform_info[SGX_PLATFORM_INFO_SIZE]; +} sgx_platform_info_t; + +typedef struct _update_info_bit +{ + int ucodeUpdate; + int csmeFwUpdate; + int pswUpdate; +} sgx_update_info_bit_t; + +#pragma pack(pop) + + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/sgx-jvm/linux-sgx/common/inc/sgx_report.h b/sgx-jvm/linux-sgx/common/inc/sgx_report.h new file mode 100644 index 0000000000..8d26087397 --- /dev/null +++ b/sgx-jvm/linux-sgx/common/inc/sgx_report.h @@ -0,0 +1,98 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + + + +/* + * This file is to define Enclave's Report +*/ + +#ifndef _SGX_REPORT_H_ +#define _SGX_REPORT_H_ + +#include "sgx_attributes.h" +#include "sgx_key.h" + +#define SGX_HASH_SIZE 32 /* SHA256 */ +#define SGX_MAC_SIZE 16 /* Message Authentication Code - 16 bytes */ + +#define SGX_REPORT_DATA_SIZE 64 + +typedef struct _sgx_measurement_t +{ + uint8_t m[SGX_HASH_SIZE]; +} sgx_measurement_t; + +typedef uint8_t sgx_mac_t[SGX_MAC_SIZE]; + +typedef struct _sgx_report_data_t +{ + uint8_t d[SGX_REPORT_DATA_SIZE]; +} sgx_report_data_t; + +typedef uint16_t sgx_prod_id_t; + +#define SGX_TARGET_INFO_RESERVED1_BYTES 4 +#define SGX_TARGET_INFO_RESERVED2_BYTES 456 + +typedef struct _targe_info_t +{ + sgx_measurement_t mr_enclave; /* ( 0) The MRENCLAVE of the target enclave */ + sgx_attributes_t attributes; /* ( 32) The ATTRIBUTES field of the target enclave */ + uint8_t reserved1[SGX_TARGET_INFO_RESERVED1_BYTES]; /* ( 48) Reserved */ + sgx_misc_select_t misc_select; /* ( 52) The MISCSELECT of the target enclave */ + uint8_t reserved2[SGX_TARGET_INFO_RESERVED2_BYTES]; /* ( 56) Struct size is 512 bytes */ +} sgx_target_info_t; + +typedef struct _report_body_t +{ + sgx_cpu_svn_t cpu_svn; /* ( 0) Security Version of the CPU */ + sgx_misc_select_t misc_select; /* ( 16) Which fields defined in SSA.MISC */ + uint8_t reserved1[28]; /* ( 20) */ + sgx_attributes_t attributes; /* ( 48) Any special Capabilities the Enclave possess */ + sgx_measurement_t mr_enclave; /* ( 64) The value of the enclave's ENCLAVE measurement */ + uint8_t reserved2[32]; /* ( 96) */ + sgx_measurement_t mr_signer; /* (128) The value of the enclave's SIGNER measurement */ + uint8_t reserved3[96]; /* (160) */ + sgx_prod_id_t isv_prod_id; /* (256) Product ID of the Enclave */ + sgx_isv_svn_t isv_svn; /* (258) Security Version of the Enclave */ + uint8_t reserved4[60]; /* (260) */ + sgx_report_data_t report_data; /* (320) Data provided by the user */ +} sgx_report_body_t; + +typedef struct _report_t /* 432 bytes */ +{ + sgx_report_body_t body; + sgx_key_id_t key_id; /* (384) KeyID used for diversifying the key tree */ + sgx_mac_t mac; /* (416) The Message Authentication Code over this structure. */ +} sgx_report_t; + +#endif diff --git a/sgx-jvm/linux-sgx/common/inc/sgx_spinlock.h b/sgx-jvm/linux-sgx/common/inc/sgx_spinlock.h new file mode 100644 index 0000000000..77d8084856 --- /dev/null +++ b/sgx-jvm/linux-sgx/common/inc/sgx_spinlock.h @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + + + + + +#ifndef _SGX_SPINLOCK_H_ +#define _SGX_SPINLOCK_H_ + +#include "sgx_defs.h" +#include + +typedef volatile uint32_t sgx_spinlock_t; + +#define SGX_SPINLOCK_INITIALIZER 0 + +#if defined(__cplusplus) +extern "C" { +#endif + +uint32_t SGXAPI sgx_spin_lock(sgx_spinlock_t *lock); +uint32_t SGXAPI sgx_spin_unlock(sgx_spinlock_t *lock); + +#if defined(__cplusplus) +} +#endif + +#endif /* !_SGX_SPINLOCK_H_ */ diff --git a/sgx-jvm/linux-sgx/common/inc/sgx_tae_service.edl b/sgx-jvm/linux-sgx/common/inc/sgx_tae_service.edl new file mode 100644 index 0000000000..9b19a8026b --- /dev/null +++ b/sgx-jvm/linux-sgx/common/inc/sgx_tae_service.edl @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +enclave{ + from "sgx_tstdc.edl" import *; + untrusted { + sgx_status_t create_session_ocall([out] uint32_t* sid, + [size = dh_msg1_size, out] uint8_t* dh_msg1, + uint32_t dh_msg1_size, + uint32_t timeout); + + sgx_status_t exchange_report_ocall(uint32_t sid, + [size = dh_msg2_size, in] uint8_t* dh_msg2, uint32_t dh_msg2_size, + [size = dh_msg3_size, out] uint8_t* dh_msg3, uint32_t dh_msg3_size, + uint32_t timeout); + + sgx_status_t close_session_ocall(uint32_t sid, uint32_t timeout); + + sgx_status_t invoke_service_ocall([size = pse_message_req_size, in] uint8_t* pse_message_req, + uint32_t pse_message_req_size, + [size = pse_message_resp_size, out] uint8_t* pse_message_resp, uint32_t pse_message_resp_size, + uint32_t timeout); + }; +}; diff --git a/sgx-jvm/linux-sgx/common/inc/sgx_tae_service.h b/sgx-jvm/linux-sgx/common/inc/sgx_tae_service.h new file mode 100644 index 0000000000..687f230607 --- /dev/null +++ b/sgx-jvm/linux-sgx/common/inc/sgx_tae_service.h @@ -0,0 +1,124 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef _SGX_TAE_SERVICE_H_ +#define _SGX_TAE_SERVICE_H_ + +/** +* File: +* sgx_tae_service.h +*Description: +* header for trusted AE support library. +* ADD from path/sgx_tae_service.edl import *; to your edl file +* to use sgx_tae_service.lib +*/ + +#include "sgx.h" +#include "sgx_defs.h" + + +#ifdef __cplusplus +extern "C" { +#endif + +#pragma pack(push, 1) + +typedef uint64_t sgx_time_t; + +typedef uint8_t sgx_time_source_nonce_t[32]; + +#define SGX_MC_UUID_COUNTER_ID_SIZE 3 +#define SGX_MC_UUID_NONCE_SIZE 13 +typedef struct _mc_uuid { + uint8_t counter_id[SGX_MC_UUID_COUNTER_ID_SIZE]; + uint8_t nonce[SGX_MC_UUID_NONCE_SIZE]; +} sgx_mc_uuid_t; + +/* fixed length to align with internal structure */ +typedef struct _ps_sec_prop_desc +{ + uint8_t sgx_ps_sec_prop_desc[256]; +} sgx_ps_sec_prop_desc_t; + +#pragma pack(pop) + +/* create a session, call it before using Platform Service */ +sgx_status_t SGXAPI sgx_create_pse_session(void); + +/* close a created session, call it after finishing using Platform Service */ +sgx_status_t SGXAPI sgx_close_pse_session(void); + +/* get a data structure describing the Security Property of the Platform Service */ +sgx_status_t SGXAPI sgx_get_ps_sec_prop(sgx_ps_sec_prop_desc_t* security_property); + +/* provides the trusted platform current time */ +sgx_status_t SGXAPI sgx_get_trusted_time( + sgx_time_t* current_time, + sgx_time_source_nonce_t* time_source_nonce + ); + +/* monotonic counter policy */ +#define SGX_MC_POLICY_SIGNER 0x1 +#define SGX_MC_POLICY_ENCLAVE 0x2 +/* create a monotonic counter using given policy(SIGNER 0x1 or ENCLAVE 0x2) and attribute_mask */ +sgx_status_t SGXAPI sgx_create_monotonic_counter_ex( + uint16_t owner_policy, + const sgx_attributes_t* owner_attribute_mask, + sgx_mc_uuid_t* counter_uuid, + uint32_t* counter_value + ); + +/* create a monotonic counter using default policy SIGNER and default attribute_mask */ +sgx_status_t SGXAPI sgx_create_monotonic_counter( + sgx_mc_uuid_t* counter_uuid, + uint32_t* counter_value + ); + +/* destroy a specified monotonic counter */ +sgx_status_t SGXAPI sgx_destroy_monotonic_counter(const sgx_mc_uuid_t* counter_uuid); + +/* increment a specified monotonic counter by 1 */ +sgx_status_t SGXAPI sgx_increment_monotonic_counter( + const sgx_mc_uuid_t* counter_uuid, + uint32_t* counter_value + ); + +/* read a specified monotonic counter */ +sgx_status_t SGXAPI sgx_read_monotonic_counter( + const sgx_mc_uuid_t* counter_uuid, + uint32_t* counter_value + ); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/sgx-jvm/linux-sgx/common/inc/sgx_tcrypto.h b/sgx-jvm/linux-sgx/common/inc/sgx_tcrypto.h new file mode 100644 index 0000000000..8ecf0b32d0 --- /dev/null +++ b/sgx-jvm/linux-sgx/common/inc/sgx_tcrypto.h @@ -0,0 +1,588 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + + + +/** +* File: sgx_tcrypto.h +* Description: +* Interface for generic crypto library APIs required in SDK implementation. +*/ + +#ifndef _SGX_TCRYPTO_H_ +#define _SGX_TCRYPTO_H_ + +#include "sgx.h" +#include "sgx_defs.h" + +#define SGX_SHA256_HASH_SIZE 32 +#define SGX_ECP256_KEY_SIZE 32 +#define SGX_NISTP_ECP256_KEY_SIZE (SGX_ECP256_KEY_SIZE/sizeof(uint32_t)) +#define SGX_AESGCM_IV_SIZE 12 +#define SGX_AESGCM_KEY_SIZE 16 +#define SGX_AESGCM_MAC_SIZE 16 +#define SGX_CMAC_KEY_SIZE 16 +#define SGX_CMAC_MAC_SIZE 16 +#define SGX_AESCTR_KEY_SIZE 16 + +typedef struct _sgx_ec256_dh_shared_t +{ + uint8_t s[SGX_ECP256_KEY_SIZE]; +} sgx_ec256_dh_shared_t; + +typedef struct _sgx_ec256_private_t +{ + uint8_t r[SGX_ECP256_KEY_SIZE]; +} sgx_ec256_private_t; + +typedef struct _sgx_ec256_public_t +{ + uint8_t gx[SGX_ECP256_KEY_SIZE]; + uint8_t gy[SGX_ECP256_KEY_SIZE]; +} sgx_ec256_public_t; + +typedef struct _sgx_ec256_signature_t +{ + uint32_t x[SGX_NISTP_ECP256_KEY_SIZE]; + uint32_t y[SGX_NISTP_ECP256_KEY_SIZE]; +} sgx_ec256_signature_t; + +typedef void* sgx_sha_state_handle_t; +typedef void* sgx_cmac_state_handle_t; +typedef void* sgx_ecc_state_handle_t; + +typedef uint8_t sgx_sha256_hash_t[SGX_SHA256_HASH_SIZE]; + +typedef uint8_t sgx_aes_gcm_128bit_key_t[SGX_AESGCM_KEY_SIZE]; +typedef uint8_t sgx_aes_gcm_128bit_tag_t[SGX_AESGCM_MAC_SIZE]; +typedef uint8_t sgx_cmac_128bit_key_t[SGX_CMAC_KEY_SIZE]; +typedef uint8_t sgx_cmac_128bit_tag_t[SGX_CMAC_MAC_SIZE]; +typedef uint8_t sgx_aes_ctr_128bit_key_t[SGX_AESCTR_KEY_SIZE]; + +typedef enum { + SGX_EC_VALID, /* validation pass successfully */ + + SGX_EC_COMPOSITE_BASE, /* field based on composite */ + SGX_EC_COMPLICATED_BASE, /* number of non-zero terms in the polynomial (> PRIME_ARR_MAX) */ + SGX_EC_IS_ZERO_DISCRIMINANT,/* zero discriminant */ + SGX_EC_COMPOSITE_ORDER, /* composite order of base point */ + SGX_EC_INVALID_ORDER, /* invalid base point order */ + SGX_EC_IS_WEAK_MOV, /* weak Meneze-Okamoto-Vanstone reduction attack */ + SGX_EC_IS_WEAK_SSA, /* weak Semaev-Smart,Satoh-Araki reduction attack */ + SGX_EC_IS_SUPER_SINGULAR, /* supersingular curve */ + + SGX_EC_INVALID_PRIVATE_KEY, /* !(0 < Private < order) */ + SGX_EC_INVALID_PUBLIC_KEY, /* (order*PublicKey != Infinity) */ + SGX_EC_INVALID_KEY_PAIR, /* (Private*BasePoint != PublicKey) */ + + SGX_EC_POINT_OUT_OF_GROUP, /* out of group (order*P != Infinity) */ + SGX_EC_POINT_IS_AT_INFINITY,/* point (P=(Px,Py)) at Infinity */ + SGX_EC_POINT_IS_NOT_VALID, /* point (P=(Px,Py)) out-of EC */ + + SGX_EC_POINT_IS_EQUAL, /* compared points are equal */ + SGX_EC_POINT_IS_NOT_EQUAL, /* compared points are different */ + + SGX_EC_INVALID_SIGNATURE /* invalid signature */ +} sgx_generic_ecresult_t; + + +#ifdef __cplusplus +extern "C" { +#endif + + /** SHA Hashing functions - NOTE: ONLY 256-bit is supported. + * + * NOTE: Use sgx_sha256_msg if the src pointer contains the complete msg to perform hash (Option 1) + * Else use the Init, Update, Update, ..., Final procedure (Option 2) + * Option 1: If the complete dataset is available for hashing, sgx_sha256_msg + * is a single API call for generating the 256bit hash for the given dataset. + * Return: If source pointer or hash pointer are NULL, SGX_ERROR_INVALID_PARAMETER is returned. + * If hash function fails then SGX_ERROR_UNEXPECTED is returned. + * Option 2: If the hash is to be performed over multiple data sets, then use: + * A. sgx_sha256_init - to create the context - context memory is allocated by this function. + * Return: If out of enclave memory, SGX_ERROR_OUT_OF_MEMORY is returned. + * If context creation fails then SGX_ERROR_UNEXPECTED is returned. + * B. sgx_sha256_update - updates hash based on input source data + * This function should be called for each chunk of data to be + * included in the hash including the 1st and final chunks. + * Return: If source pointer or context pointer are NULL, SGX_ERROR_INVALID_PARAMETER is returned. + * If hash function fails then SGX_ERROR_UNEXPECTED is returned. + * C. sgx_sha256_get_hash - function obtains the hash value + * Return: If hash pointer or context pointer are NULL, SGX_ERROR_INVALID_PARAMETER is returned. + * If the function fails then SGX_ERROR_UNEXPECTED is returned. + * D. sgx_sha256_close - SHOULD BE CALLED to FREE context memory + * Upon completing the process of computing a hash over a set of data + * or sets of data, this function is used to free the context. + * Return: If context pointer is NULL, SGX_ERROR_INVALID_PARAMETER is returned. + * + * Parameters: + * Return: sgx_status_t - SGX_SUCCESS or failure as defined in sgx_error.h + * Inputs: uint8_t *p_src - Pointer to the input stream to be hashed + * uint32_t src_len - Length of the input stream to be hashed + * Output: sgx_sha256_hash_t *p_hash - Resultant hash from operation + */ + sgx_status_t SGXAPI sgx_sha256_msg(const uint8_t *p_src, uint32_t src_len, sgx_sha256_hash_t *p_hash); + + /** Allocates and initializes sha256 state + * + * Parameters: + * Return: sgx_status_t - SGX_SUCCESS or failure as defined in sgx_error.h + * Output: sgx_sha_state_handle_t *p_sha_handle - Pointer to the handle of the SHA256 state + */ + sgx_status_t SGXAPI sgx_sha256_init(sgx_sha_state_handle_t* p_sha_handle); + + /** Updates sha256 has calculation based on the input message + * + * Parameters: + * Return: sgx_status_t - SGX_SUCCESS or failure as defined in sgx_error.h + * Input: sgx_sha_state_handle_t sha_handle - Handle to the SHA256 state + * uint8_t *p_src - Pointer to the input stream to be hashed + * uint32_t src_len - Length of the input stream to be hashed + */ + sgx_status_t SGXAPI sgx_sha256_update(const uint8_t *p_src, uint32_t src_len, sgx_sha_state_handle_t sha_handle); + + /** Returns Hash calculation + * + * Parameters: + * Return: sgx_status_t - SGX_SUCCESS or failure as defined in sgx_error.h + * Input: sgx_sha_state_handle_t sha_handle - Handle to the SHA256 state + * Output: sgx_sha256_hash_t *p_hash - Resultant hash from operation + */ + sgx_status_t SGXAPI sgx_sha256_get_hash(sgx_sha_state_handle_t sha_handle, sgx_sha256_hash_t *p_hash); + + /** Cleans up SHA state + * + * Parameters: + * Return: sgx_status_t - SGX_SUCCESS or failure as defined in sgx_error.h + * Input: sgx_sha_state_handle_t sha_handle - Handle to the SHA256 state + */ + sgx_status_t SGXAPI sgx_sha256_close(sgx_sha_state_handle_t sha_handle); + + /**Rijndael AES-GCM - Only 128-bit key AES-GCM Encryption/Decryption is supported + * + * The Galois/Counter Mode (GCM) is a mode of operation of the AES algorithm. + * GCM [NIST SP 800-38D] uses a variation of the Counter mode of operation for encryption. + * GCM assures authenticity of the confidential data (of up to about 64 GB per invocation) + * using a universal hash function defined over a binary finite field (the Galois field). + * + * GCM can also provide authentication assurance for additional data + * (of practically unlimited length per invocation) that is not encrypted. + * GCM provides stronger authentication assurance than a (non-cryptographic) checksum or + * error detecting code. In particular, GCM can detect both accidental modifications of + * the data and intentional, unauthorized modifications. + * + * sgx_rijndael128GCM_encrypt: + * Return: If key, source, destination, MAC, or IV pointer is NULL, SGX_ERROR_INVALID_PARAMETER is returned. + * If AAD size is > 0 and the AAD pointer is NULL, SGX_ERROR_INVALID_PARAMETER is returned. + * If the Source Length is < 1, SGX_ERROR_INVALID_PARAMETER is returned. + * IV Length must = 12 (bytes) or SGX_ERROR_INVALID_PARAMETER is returned. + * If out of enclave memory then SGX_ERROR_OUT_OF_MEMORY is returned. + * If the encryption process fails then SGX_ERROR_UNEXPECTED is returned. + * + * sgx_rijndael128GCM_decrypt: + * Return: If key, source, destination, MAC, or IV pointer is NULL, SGX_ERROR_INVALID_PARAMETER is returned. + * If AAD size is > 0 and the AAD pointer is NULL, SGX_ERROR_INVALID_PARAMETER is returned. + * If the Source Length is < 1, SGX_ERROR_INVALID_PARAMETER is returned. + * IV Length must = 12 (bytes) or SGX_ERROR_INVALID_PARAMETER is returned. + * If the decryption process fails then SGX_ERROR_UNEXPECTED is returned. + * If the input MAC does not match the calculated MAC, SGX_ERROR_MAC_MISMATCH is returned. + * + * Parameters: + * Return: sgx_status_t - SGX_SUCCESS or failure as defined in sgx_error.h + * Inputs: sgx_aes_gcm_128bit_key_t *p_key - Pointer to the key used in encryption/decryption operation + * Size MUST BE 128-bits + * uint8_t *p_src - Pointer to the input stream to be encrypted/decrypted + * uint32_t src_len - Length of the input stream to be encrypted/decrypted + * uint8_t *p_iv - Pointer to the initialization vector + * uint32_t iv_len - Length of the initialization vector - MUST BE 12 (bytes) + * NIST AES-GCM recommended IV size = 96 bits + * uint8_t *p_aad - Pointer to the input stream of additional authentication data + * uint32_t aad_len - Length of the additional authentication data stream + * sgx_aes_gcm_128bit_tag_t *p_in_mac - Pointer to the expected MAC in decryption process + * Output: uint8_t *p_dst - Pointer to the cipher text for encryption or clear text for decryption. Size of buffer should be >= src_len. + * sgx_aes_gcm_128bit_tag_t *p_out_mac - Pointer to the MAC generated from encryption process + * NOTE: Wrapper is responsible for confirming decryption tag matches encryption tag + */ + sgx_status_t SGXAPI sgx_rijndael128GCM_encrypt(const sgx_aes_gcm_128bit_key_t *p_key, + const uint8_t *p_src, + uint32_t src_len, + uint8_t *p_dst, + const uint8_t *p_iv, + uint32_t iv_len, + const uint8_t *p_aad, + uint32_t aad_len, + sgx_aes_gcm_128bit_tag_t *p_out_mac); + sgx_status_t SGXAPI sgx_rijndael128GCM_decrypt(const sgx_aes_gcm_128bit_key_t *p_key, + const uint8_t *p_src, + uint32_t src_len, + uint8_t *p_dst, + const uint8_t *p_iv, + uint32_t iv_len, + const uint8_t *p_aad, + uint32_t aad_len, + const sgx_aes_gcm_128bit_tag_t *p_in_mac); + + /** Message Authentication Rijndael 128 CMAC - Only 128-bit key size is supported. + * NOTE: Use sgx_rijndael128_cmac_msg if the src ptr contains the complete msg to perform hash (Option 1) + * Else use the Init, Update, Update, ..., Final, Close procedure (Option 2) + * Option 1: If the complete dataset is available for hashing, sgx_rijndael128_cmac_msg + * is a single API call for generating the 128-bit hash for the given dataset. + * Return: If source, key, or MAC pointer is NULL, SGX_ERROR_INVALID_PARAMETER is returned. + * If out of enclave memory, SGX_ERROR_OUT_OF_MEMORY is returned. + * If hash function fails then SGX_ERROR_UNEXPECTED is returned. + * Option 2: If the hash is to be performed over multiple data sets, then use: + * A. sgx_cmac128_init - to create the context - context memory is allocated by this function. + * Return: If key pointer is NULL, SGX_ERROR_INVALID_PARAMETER is returned. + * If out of enclave memory, SGX_ERROR_OUT_OF_MEMORY is returned. + * If context creation fails then SGX_ERROR_UNEXPECTED is returned. + * B. sgx_cmac128_update - updates hash based on input source data + * This function should be called for each chunk of data to be + * included in the hash including the 1st and final chunks. + * Return: If source pointer or context pointer are NULL, SGX_ERROR_INVALID_PARAMETER is returned. + * If hash function fails then SGX_ERROR_UNEXPECTED is returned. + * C. sgx_cmac128_final - function obtains the hash value + * Upon completing the process of computing a hash over a set of data or sets of data, + * this function populates the hash value. + * Return: If hash pointer or context pointer are NULL, SGX_ERROR_INVALID_PARAMETER is returned. + * If the function fails then SGX_ERROR_UNEXPECTED is returned. + * D. sgx_cmac128_close - SHOULD BE CALLED to clean up the CMAC state + * Upon populating the hash value over a set of data or sets of data, + * this function is used to free the CMAC state. + * Return: If CMAC state pointer is NULL, SGX_ERROR_INVALID_PARAMETER is returned. + * + * Parameters: + * Return: sgx_status_t - SGX_SUCCESS or failure as defined in sgx_error.h + * Inputs: sgx_cmac_128bit_key_t *p_key - Pointer to the key used in encryption/decryption operation + * uint8_t *p_src - Pointer to the input stream to be MAC’d + * uint32_t src_len - Length of the input stream to be MAC’d + * Output: sgx_cmac_gcm_128bit_tag_t *p_mac - Pointer to the resultant MAC + */ + sgx_status_t SGXAPI sgx_rijndael128_cmac_msg(const sgx_cmac_128bit_key_t *p_key, + const uint8_t *p_src, + uint32_t src_len, + sgx_cmac_128bit_tag_t *p_mac); + /** Allocates and initializes CMAC state. + * + * Parameters: + * Return: sgx_status_t - SGX_SUCCESS or failure as defined in sgx_error.h + * Inputs: sgx_cmac_128bit_key_t *p_key - Pointer to the key used in encryption/decryption operation + * Output: sgx_cmac_state_handle_t *p_cmac_handle - Pointer to the handle of the CMAC state + */ + sgx_status_t SGXAPI sgx_cmac128_init(const sgx_cmac_128bit_key_t *p_key, sgx_cmac_state_handle_t* p_cmac_handle); + + /** Updates CMAC has calculation based on the input message. + * + * Parameters: + * Return: sgx_status_t - SGX_SUCCESS or failure as defined in sgx_error.h + * Input: sgx_cmac_state_handle_t cmac_handle - Handle to the CMAC state + * uint8_t *p_src - Pointer to the input stream to be hashed + * uint32_t src_len - Length of the input stream to be hashed + */ + sgx_status_t SGXAPI sgx_cmac128_update(const uint8_t *p_src, uint32_t src_len, sgx_cmac_state_handle_t cmac_handle); + + /** Returns Hash calculation and clean up CMAC state. + * + * Parameters: + * Return: sgx_status_t - SGX_SUCCESS or failure as defined in sgx_error.h + * Input: sgx_cmac_state_handle_t cmac_handle - Handle to the CMAC state + * Output: sgx_cmac_128bit_tag_t *p_hash - Resultant hash from operation + */ + sgx_status_t SGXAPI sgx_cmac128_final(sgx_cmac_state_handle_t cmac_handle, sgx_cmac_128bit_tag_t *p_hash); + + /** Clean up the CMAC state + * + * Parameters: + * Return: sgx_status_t - SGX_SUCCESS or failure as defined in sgx_error.h + * Input: sgx_cmac_state_handle_t cmac_handle - Handle to the CMAC state + */ + sgx_status_t SGXAPI sgx_cmac128_close(sgx_cmac_state_handle_t cmac_handle); + + + /** AES-CTR 128-bit - Only 128-bit key size is supported. + * + * These functions encrypt/decrypt the input data stream of a variable length according + * to the CTR mode as specified in [NIST SP 800-38A]. The counter can be thought of as + * an IV which increments on successive encryption or decrytion calls. For a given + * dataset or data stream the incremented counter block should be used on successive + * calls of the encryption/decryption process for that given stream. However for + * new or different datasets/streams, the same counter should not be reused, instead + * intialize the counter for the new data set. + * + * sgx_aes_ctr_encrypt + * Return: If source, key, counter, or destination pointer is NULL, + * SGX_ERROR_INVALID_PARAMETER is returned. + * If out of enclave memory, SGX_ERROR_OUT_OF_MEMORY is returned. + * If the encryption process fails then SGX_ERROR_UNEXPECTED is returned. + * sgx_aes_ctr_decrypt + * Return: If source, key, counter, or destination pointer is NULL, + * SGX_ERROR_INVALID_PARAMETER is returned. + * If out of enclave memory, SGX_ERROR_OUT_OF_MEMORY is returned. + * If the decryption process fails then SGX_ERROR_UNEXPECTED is returned. + * + * Parameters: + * Return: + * sgx_status_t - SGX_SUCCESS or failure as defined + * in sgx_error.h + * Inputs: + * sgx_aes_128bit_key_t *p_key - Pointer to the key used in + * encryption/decryption operation + * uint8_t *p_src - Pointer to the input stream to be + * encrypted/decrypted + * uint32_t src_len - Length of the input stream to be + * encrypted/decrypted + * uint8_t *p_ctr - Pointer to the counter block + * uint32_t ctr_inc_bits - Number of bits in counter to be + * incremented + * Output: + * uint8_t *p_dst - Pointer to the cipher text. + * Size of buffer should be >= src_len. + */ + sgx_status_t SGXAPI sgx_aes_ctr_encrypt( + const sgx_aes_ctr_128bit_key_t *p_key, + const uint8_t *p_src, + const uint32_t src_len, + uint8_t *p_ctr, + const uint32_t ctr_inc_bits, + uint8_t *p_dst); + sgx_status_t SGXAPI sgx_aes_ctr_decrypt( + const sgx_aes_ctr_128bit_key_t *p_key, + const uint8_t *p_src, + const uint32_t src_len, + uint8_t *p_ctr, + const uint32_t ctr_inc_bits, + uint8_t *p_dst); + + + /** + * Elliptic Curve Cryptography based on GF(p), 256 bit. + * + * Elliptic curve cryptosystems (ECCs) implement a different way of creating public keys. + * Because elliptic curve calculation is based on the addition of the rational points in + * the (x,y) plane and it is difficult to solve a discrete logarithm from these points, + * a higher level of security is achieved through the cryptographic schemes that use the + * elliptic curves. The cryptographic systems that encrypt messages by using the properties + * of elliptic curves are hard to attack due to the extreme complexity of deciphering the + * private key. + * + * Use of elliptic curves allows for shorter public key length and encourage cryptographers + * to create cryptosystems with the same or higher encryption strength as the RSA or DSA + * cryptosystems. Because of the relatively short key length, ECCs do encryption and decryption + * faster on the hardware that requires less computation processing volumes. For example, with + * a key length of 150-350 bits, ECCs provide the same encryption strength as the cryptosystems + * who have to use 600 -1400 bits. + * + * ECCP stands for Elliptic Curve Cryptography Prime and these functions include operations + * over a prime finite field GF(p). + * + */ + /** Allocates and initializes ecc context. + * The function initializes the context of the elliptic curve cryptosystem over the + * prime finite field GF(p). This function allocates and initializes the ecc context. + * Return: If out of enclave memory, SGX_ERROR_OUT_OF_MEMORY is returned. + * If context creation fails then SGX_ERROR_UNEXPECTED is returned. + * Parameters: + * Return: sgx_status_t - SGX_SUCCESS or failure as defined in sgx_error.h + * Output: sgx_ecc_state_handle_t *p_ecc_handle - Pointer to the handle of the ECC crypto system + */ + sgx_status_t SGXAPI sgx_ecc256_open_context(sgx_ecc_state_handle_t* p_ecc_handle); + + /** Cleans up ecc context. + * Return: If context pointer is NULL, SGX_ERROR_INVALID_PARAMETER is returned. + * Parameters: + * Return: sgx_status_t - SGX_SUCCESS or failure as defined in sgx_error.h + * Output: sgx_ecc_state_handle_t ecc_handle - Handle to the ECC crypto system + */ + sgx_status_t SGXAPI sgx_ecc256_close_context(sgx_ecc_state_handle_t ecc_handle); + + /** Populates private/public key pair. + * NOTE: Caller code allocates memory for Private & Public key pointers to be populated + * + * The function generates a private key p_private and computes a public key p_public of the + * elliptic cryptosystem over a finite field GF(p). + * + * The private key p_private is a number that lies in the range of [1, n-1] where n is + * the order of the elliptic curve base point. + * + * The public key p_public is an elliptic curve point such that p_public = p_private ?G, + * where G is the base point of the elliptic curve. + * + * The context of the point p_public as an elliptic curve point must be created by using + * the function sgx_ecc256_open_context. + * + * Return: If context, public key, or private key pointer is NULL, + * SGX_ERROR_INVALID_PARAMETER is returned. + * If the key creation process fails then SGX_ERROR_UNEXPECTED is returned. + * Parameters: + * Return: sgx_status_t - SGX_SUCCESS or failure as defined in sgx_error.h + * Inputs: sgx_ecc_state_handle_t ecc_handle - Handle to the ECC crypto system + * Outputs: sgx_ec256_private_t *p_private - Pointer to the private key - LITTLE ENDIAN + * sgx_ec256_public_t *p_public - Pointer to the public key - LITTLE ENDIAN + */ + sgx_status_t SGXAPI sgx_ecc256_create_key_pair(sgx_ec256_private_t *p_private, + sgx_ec256_public_t *p_public, + sgx_ecc_state_handle_t ecc_handle); + + /** Checks whether the input point is a valid point on the given elliptic curve. + * Parameters: + * Return: sgx_status_t - SGX_SUCCESS or failure as defined sgx_error.h + * Inputs: sgx_ecc_state_handle_t ecc_handle - Handle to ECC crypto system + * sgx_ec256_public_t *p_point - Pointer to perform validity check on - LITTLE ENDIAN + * Output: int *p_valid - Return 0 if the point is an invalid point on ECC curve + */ + sgx_status_t SGXAPI sgx_ecc256_check_point(const sgx_ec256_public_t *p_point, + const sgx_ecc_state_handle_t ecc_handle, + int *p_valid); + + /** Computes DH shared key based on own (local) private key and remote public Ga Key. + * NOTE: Caller code allocates memory for Shared key pointer to be populated + * + * The function computes a secret number bnShare, which is a secret key shared between + * two participants of the cryptosystem. + * + * In cryptography, metasyntactic names such as Alice as Bob are normally used as examples + * and in discussions and stand for participant A and participant B. + * + * Both participants (Alice and Bob) use the cryptosystem for receiving a common secret point + * on the elliptic curve called a secret key. To receive a secret key, participants apply the + * Diffie-Hellman key-agreement scheme involving public key exchange. The value of the secret + * key entirely depends on participants. + * + * According to the scheme, Alice and Bob perform the following operations: + * 1. Alice calculates her own public key pubKeyA by using her private key + * privKeyA: pubKeyA = privKeyA ?G, where G is the base point of the elliptic curve. + * 2. Alice passes the public key to Bob. + * 3. Bob calculates his own public key pubKeyB by using his private key + * privKeyB: pubKeyB = privKeyB ?G, where G is a base point of the elliptic curve. + * 4. Bob passes the public key to Alice. + * 5. Alice gets Bob's public key and calculates the secret point shareA. When calculating, + * she uses her own private key and Bob's public key and applies the following formula: + * shareA = privKeyA ?pubKeyB = privKeyA ?privKeyB ?G. + * 6. Bob gets Alice's public key and calculates the secret point shareB. When calculating, + * he uses his own private key and Alice's public key and applies the following formula: + * shareB = privKeyB ?pubKeyA = privKeyB ?privKeyA ?G. + * + * Because the following equation is true privKeyA ?privKeyB ?G = privKeyB ?privKeyA ?G, + * the result of both calculations is the same, that is, the equation shareA = shareB is true. + * The secret point serves as a secret key. + * + * Shared secret bnShare is an x-coordinate of the secret point on the elliptic curve. The elliptic + * curve domain parameters must be hitherto defined by the function: sgx_ecc256_open_context. + * + * Return: If context, public key, private key, or shared key pointer is NULL, + * SGX_ERROR_INVALID_PARAMETER is returned. + * If the remote public key is not a valid point on the elliptic curve, + * SGX_ERROR_INVALID_PARAMETER is returned. + * If the key creation process fails then SGX_ERROR_UNEXPECTED is returned. + * + * Parameters: + * Return: sgx_status_t - SGX_SUCCESS or failure as defined in sgx_error.h + * Inputs: sgx_ecc_state_handle_t ecc_handle - Handle to the ECC crypto system + * sgx_ec256_private_t *p_private_b - Pointer to the local private key - LITTLE ENDIAN + * sgx_ec256_public_t *p_public_ga - Pointer to the remote public key - LITTLE ENDIAN + * Output: sgx_ec256_dh_shared_t *p_shared_key - Pointer to the shared DH key - LITTLE ENDIAN + */ + sgx_status_t SGXAPI sgx_ecc256_compute_shared_dhkey(sgx_ec256_private_t *p_private_b, + sgx_ec256_public_t *p_public_ga, + sgx_ec256_dh_shared_t *p_shared_key, + sgx_ecc_state_handle_t ecc_handle); + + /** Computes signature for data based on private key. + * + * A message digest is a fixed size number derived from the original message with + * an applied hash function over the binary code of the message. (SHA256 in this case) + * The signer's private key and the message digest are used to create a signature. + * + * A digital signature over a message consists of a pair of large numbers, 256-bits each, + * which the given function computes. + * + * The scheme used for computing a digital signature is of the ECDSA scheme, + * an elliptic curve of the DSA scheme. + * + * The keys can be generated and set up by the function: sgx_ecc256_create_key_pair. + * + * The elliptic curve domain parameters must be created by function: + * sgx_ecc256_open_context + * + * Return: If context, private key, signature or data pointer is NULL, + * SGX_ERROR_INVALID_PARAMETER is returned. + * If the signature creation process fails then SGX_ERROR_UNEXPECTED is returned. + * + * Parameters: + * Return: sgx_status_t - SGX_SUCCESS or failure as defined in sgx_error.h + * Inputs: sgx_ecc_state_handle_t ecc_handle - Handle to the ECC crypto system + * sgx_ec256_private_t *p_private - Pointer to the private key - LITTLE ENDIAN + * uint8_t *p_data - Pointer to the data to be signed + * uint32_t data_size - Size of the data to be signed + * Output: ec256_signature_t *p_signature - Pointer to the signature - LITTLE ENDIAN + */ + sgx_status_t SGXAPI sgx_ecdsa_sign(const uint8_t *p_data, + uint32_t data_size, + sgx_ec256_private_t *p_private, + sgx_ec256_signature_t *p_signature, + sgx_ecc_state_handle_t ecc_handle); + + /** Verifies the signature for the given data based on the public key. + * + * A digital signature over a message consists of a pair of large numbers, 256-bits each, + * which could be created by function: sgx_ecdsa_sign. The scheme used for computing a + * digital signature is of the ECDSA scheme, an elliptic curve of the DSA scheme. + * + * The typical result of the digital signature verification is one of the two values: + * SGX_Generic_ECValid - Digital signature is valid + * SGX_Generic_ECInvalidSignature - Digital signature is not valid + * + * The elliptic curve domain parameters must be created by function: + * sgx_ecc256_open_context + * + * Return: If context, public key, signature, result or data pointer is NULL, + * SGX_ERROR_INVALID_PARAMETER is returned. + * If the verification process fails then SGX_ERROR_UNEXPECTED is returned. + * Parameters: + * Return: sgx_status_t - SGX_SUCCESS or failure as defined in sgx_error.h + * Inputs: sgx_ecc_state_handle_t ecc_handle - Handle to the ECC crypto system + * sgx_ec256_public_t *p_public - Pointer to the public key + * uint8_t *p_data - Pointer to the data to be signed + * uint32_t data_size - Size of the data to be signed + * sgx_ec256_signature_t *p_signature - Pointer to the signature + * Output: uint8_t *p_result - Pointer to the result of verification check + */ + sgx_status_t SGXAPI sgx_ecdsa_verify(const uint8_t *p_data, + uint32_t data_size, + const sgx_ec256_public_t *p_public, + sgx_ec256_signature_t *p_signature, + uint8_t *p_result, + sgx_ecc_state_handle_t ecc_handle); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/sgx-jvm/linux-sgx/common/inc/sgx_thread.h b/sgx-jvm/linux-sgx/common/inc/sgx_thread.h new file mode 100644 index 0000000000..ee0274c9e3 --- /dev/null +++ b/sgx-jvm/linux-sgx/common/inc/sgx_thread.h @@ -0,0 +1,114 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef _SGX_THREAD_H_ +#define _SGX_THREAD_H_ + +#include +#include +#include "sgx_defs.h" + +typedef uintptr_t sgx_thread_t; + +typedef struct sgx_thread_queue +{ + sgx_thread_t m_first; /* first element */ + sgx_thread_t m_last; /* last element */ +} sgx_thread_queue_t; + +/* Mutex */ +typedef struct sgx_thread_mutex +{ + size_t m_refcount; + uint32_t m_control; + volatile uint32_t m_lock; /* use sgx_spinlock_t */ + sgx_thread_t m_owner; + sgx_thread_queue_t m_queue; +} sgx_thread_mutex_t; + +#define SGX_THREAD_T_NULL ((sgx_thread_t)(NULL)) + +#define SGX_THREAD_MUTEX_NONRECURSIVE 0x01 +#define SGX_THREAD_MUTEX_RECURSIVE 0x02 +#define SGX_THREAD_NONRECURSIVE_MUTEX_INITIALIZER \ + {0, SGX_THREAD_MUTEX_NONRECURSIVE, 0, SGX_THREAD_T_NULL, {SGX_THREAD_T_NULL, SGX_THREAD_T_NULL}} +#define SGX_THREAD_RECURSIVE_MUTEX_INITIALIZER \ + {0, SGX_THREAD_MUTEX_RECURSIVE, 0, SGX_THREAD_T_NULL, {SGX_THREAD_T_NULL, SGX_THREAD_T_NULL}} +#define SGX_THREAD_MUTEX_INITIALIZER \ + SGX_THREAD_NONRECURSIVE_MUTEX_INITIALIZER + +typedef struct sgx_thread_mutex_attr +{ + unsigned char m_dummy; /* for C syntax check */ +} sgx_thread_mutexattr_t; + +/* Condition Variable */ +typedef struct sgx_thread_cond +{ + volatile uint32_t m_lock; /* use sgx_spinlock_t */ + sgx_thread_queue_t m_queue; +} sgx_thread_cond_t; + +#define SGX_THREAD_COND_INITIALIZER {0, {SGX_THREAD_T_NULL, SGX_THREAD_T_NULL}} + +typedef struct sgx_thread_cond_attr +{ + unsigned char m_dummy; /* for C syntax check */ +} sgx_thread_condattr_t; + +#ifdef __cplusplus +extern "C" { +#endif + +/* Mutex */ +int SGXAPI sgx_thread_mutex_init(sgx_thread_mutex_t *mutex, const sgx_thread_mutexattr_t *unused); +int SGXAPI sgx_thread_mutex_destroy(sgx_thread_mutex_t *mutex); + +int SGXAPI sgx_thread_mutex_lock(sgx_thread_mutex_t *mutex); +int SGXAPI sgx_thread_mutex_trylock(sgx_thread_mutex_t *mutex); +int SGXAPI sgx_thread_mutex_unlock(sgx_thread_mutex_t *mutex); + +/* Condition Variable */ +int SGXAPI sgx_thread_cond_init(sgx_thread_cond_t *cond, const sgx_thread_condattr_t *unused); +int SGXAPI sgx_thread_cond_destroy(sgx_thread_cond_t *cond); + +int SGXAPI sgx_thread_cond_wait(sgx_thread_cond_t *cond, sgx_thread_mutex_t *mutex); +int SGXAPI sgx_thread_cond_signal(sgx_thread_cond_t *cond); +int SGXAPI sgx_thread_cond_broadcast(sgx_thread_cond_t *cond); + +sgx_thread_t SGXAPI sgx_thread_self(void); +int sgx_thread_equal(sgx_thread_t a, sgx_thread_t b); + +#ifdef __cplusplus +} +#endif + +#endif /* _SGX_THREAD_H_ */ diff --git a/sgx-jvm/linux-sgx/common/inc/sgx_tkey_exchange.edl b/sgx-jvm/linux-sgx/common/inc/sgx_tkey_exchange.edl new file mode 100644 index 0000000000..179418d0ce --- /dev/null +++ b/sgx-jvm/linux-sgx/common/inc/sgx_tkey_exchange.edl @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +enclave { + from "sgx_tae_service.edl" import *; + trusted { + public sgx_status_t sgx_ra_get_ga(sgx_ra_context_t context, + [out] sgx_ec256_public_t *g_a); + + public sgx_status_t sgx_ra_proc_msg2_trusted(sgx_ra_context_t context, + [in]const sgx_ra_msg2_t *p_msg2, /*copy msg2 except quote into enclave */ + [in] const sgx_target_info_t *p_qe_target, + [out] sgx_report_t *p_report, + [out] sgx_quote_nonce_t *p_nonce); + + public sgx_status_t sgx_ra_get_msg3_trusted(sgx_ra_context_t context, + uint32_t quote_size, + [in]sgx_report_t* qe_report, + [user_check]sgx_ra_msg3_t *p_msg3, + uint32_t msg3_size); + }; +}; diff --git a/sgx-jvm/linux-sgx/common/inc/sgx_tkey_exchange.h b/sgx-jvm/linux-sgx/common/inc/sgx_tkey_exchange.h new file mode 100644 index 0000000000..eb8e27f6e3 --- /dev/null +++ b/sgx-jvm/linux-sgx/common/inc/sgx_tkey_exchange.h @@ -0,0 +1,183 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef _SGX_TKEY_EXCHANGE_H_ +#define _SGX_TKEY_EXCHANGE_H_ + +#include "sgx.h" +#include "sgx_defs.h" +#include "sgx_key_exchange.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * The sgx_ra_init function creates a context for the remote attestation and + * key exchange process. + * + * @param p_pub_key The EC public key of the service provider based on the NIST + * P-256 elliptic curve. + * @param b_pse If true, platform service information is needed in message + * 3. The caller should make sure a PSE session has been + * established using sgx_create_pse_session before attempting + * to establish a remote attestation and key exchange session + * involving platform service information. + * @param p_context The output context for the subsequent remote attestation + * and key exchange process, to be used in sgx_ra_get_msg1 and + * sgx_ra_proc_msg2. + * @return sgx_status_t SGX_SUCCESS Indicates success. + * SGX_ERROR_INVALID_PARAMETER Indicates an error that + * the input parameters are + * invalid. + * SGX_ERROR_OUT_OF_MEMORY There is not enough + * memory available to + * complete this operation. + * SGX_ERROR_AE_SESSION_INVALID Session is invalid or + * ended by server. + * SGX_ERROR_UNEXPECTED Indicates an unexpected + * error occurs. + */ +sgx_status_t SGXAPI sgx_ra_init( + const sgx_ec256_public_t *p_pub_key, + int b_pse, + sgx_ra_context_t *p_context); + +/* + * The sgx_ra_derive_secret_keys_t function should takes the Diffie-Hellman + * shared secret as input to allow the ISV enclave to generate their own derived + * shared keys (SMK, SK, MK and VK). + * + * @param p_shared_key The the Diffie-Hellman shared secret. + * @param kdf_id, Key Derivation Function ID + * @param p_smk_key The output SMK. + * @param p_sk_key The output SK. + * @param p_mk_key The output MK. + * @param p_vk_key The output VK. + * @return sgx_status_t SGX_SUCCESS Indicates success. + * SGX_ERROR_INVALID_PARAMETER Indicates an error that + * the input parameters are + * invalid. + * SGX_ERROR_KDF_MISMATCH Indicates key derivation + * function doesn't match. + * SGX_ERROR_OUT_OF_MEMORY There is not enough + * memory available to + * complete this operation. + * SGX_ERROR_UNEXPECTED Indicates an unexpected + * error occurs. + */ + +typedef sgx_status_t(*sgx_ra_derive_secret_keys_t)( + const sgx_ec256_dh_shared_t* p_shared_key, + uint16_t kdf_id, + sgx_ec_key_128bit_t* p_smk_key, + sgx_ec_key_128bit_t* p_sk_key, + sgx_ec_key_128bit_t* p_mk_key, + sgx_ec_key_128bit_t* p_vk_key); + +/* + * The sgx_ra_init_ex function creates a context for the remote attestation and + * key exchange process asociated with a key derive function. + * + * @param p_pub_key The EC public key of the service provider based on the NIST + * P-256 elliptic curve. + * @param b_pse If true, platform service information is needed in message + * 3. The caller should make sure a PSE session has been + * established using sgx_create_pse_session before attempting + * to establish a remote attestation and key exchange session + * involving platform service information. + * @param derive_key_cb A pointer to a call back routine matching the + * function prototype of sgx_ra_derive_secret_keys_t. This + * function takes the Diffie-Hellman shared secret as input + * to allow the ISV enclave to generate their own derived + * shared keys (SMK, SK, MK and VK). + * @param p_context The output context for the subsequent remote attestation + * and key exchange process, to be used in sgx_ra_get_msg1 and + * sgx_ra_get_msg2. + * @return sgx_status_t SGX_SUCCESS Indicates success. + * SGX_ERROR_INVALID_PARAMETER Indicates an error that + * the input parameters are + * invalid. + * SGX_ERROR_OUT_OF_MEMORY There is not enough + * memory available to + * complete this operation. + * SGX_ERROR_AE_SESSION_INVALID Session is invalid or + * ended by server. + * SGX_ERROR_UNEXPECTED Indicates an unexpected + * error occurs. + */ + +sgx_status_t SGXAPI sgx_ra_init_ex( + const sgx_ec256_public_t *p_pub_key, + int b_pse, + sgx_ra_derive_secret_keys_t derive_key_cb, + sgx_ra_context_t *p_context); +/* + * The sgx_ra_get_keys function is used to get the negotiated keys of a remote + * attestation and key exchange session. This function should only be called + * after the service provider accepts the remote attestation and key exchange + * protocol message 3 produced by sgx_ra_proc_msg2. + * + * @param context Context returned by sgx_ra_init. + * @param type The specifier of keys, can be SGX_RA_KEY_MK, SGX_RA_KEY_SK + * and SGX_RA_VK. + * @param p_key The key returned. + * @return sgx_status_t SGX_SUCCESS Indicates success. + * SGX_ERROR_INVALID_PARAMETER Indicates an error that + * the input parameters are + * invalid. + * SGX_ERROR_INVALID_STATE Indicates this function + * is called out of order. + */ +sgx_status_t SGXAPI sgx_ra_get_keys( + sgx_ra_context_t context, + sgx_ra_key_type_t type, + sgx_ra_key_128_t *p_key); + +/* + * Call the sgx_ra_close function to release the remote attestation and key + * exchange context after the process is done and the context isn't needed + * anymore. + * + * @param context Context returned by sgx_ra_init. + * @return sgx_status_t SGX_SUCCESS Indicates success. + * SGX_ERROR_INVALID_PARAMETER Indicates an error that + * the input parameters are + * invalid. + */ +sgx_status_t SGXAPI sgx_ra_close( + sgx_ra_context_t context); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/sgx-jvm/linux-sgx/common/inc/sgx_trts.h b/sgx-jvm/linux-sgx/common/inc/sgx_trts.h new file mode 100644 index 0000000000..1a669f78d2 --- /dev/null +++ b/sgx-jvm/linux-sgx/common/inc/sgx_trts.h @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef _SGX_TRTS_H_ +#define _SGX_TRTS_H_ + +#include "sgx_error.h" +#include "stddef.h" +#include "sgx_defs.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* sgx_is_within_enclave() + * Parameters: + * addr - the start address of the buffer + * size - the size of the buffer + * Return Value: + * 1 - the buffer is strictly within the enclave + * 0 - the whole buffer or part of the buffer is not within the enclave, + * or the buffer is wrap around +*/ +int SGXAPI sgx_is_within_enclave(const void *addr, size_t size); + +/* sgx_is_outside_enclave() + * Parameters: + * addr - the start address of the buffer + * size - the size of the buffer + * Return Value: + * 1 - the buffer is strictly outside the enclave + * 0 - the whole buffer or part of the buffer is not outside the enclave, + * or the buffer is wrap around +*/ +int SGXAPI sgx_is_outside_enclave(const void *addr, size_t size); + + +/* sgx_read_rand() + * Parameters: + * rand - the buffer to receive the random number + * length_in_bytes - the number of bytes to read the random number + * Return Value: + * SGX_SUCCESS - success + * SGX_ERROR_INVALID_PARAMETER - the parameter is invalid + * SGX_ERROR_UNEXPECTED - HW failure of RDRAND instruction +*/ +sgx_status_t SGXAPI sgx_read_rand(unsigned char *rand, size_t length_in_bytes); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/sgx-jvm/linux-sgx/common/inc/sgx_trts_exception.h b/sgx-jvm/linux-sgx/common/inc/sgx_trts_exception.h new file mode 100644 index 0000000000..41280aff4d --- /dev/null +++ b/sgx-jvm/linux-sgx/common/inc/sgx_trts_exception.h @@ -0,0 +1,148 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + + + +/** + * File: sgx_trts_exception.h + * Description: + * Header file for custom exception handling support. + */ + +#ifndef _SGX_TRTS_EXCEPTION_H_ +#define _SGX_TRTS_EXCEPTION_H_ + +#include +#include +#include "sgx_defs.h" + +#define EXCEPTION_CONTINUE_SEARCH 0 +#define EXCEPTION_CONTINUE_EXECUTION -1 + +typedef enum _sgx_exception_vector_t +{ + SGX_EXCEPTION_VECTOR_DE = 0, /* DIV and DIV instructions */ + SGX_EXCEPTION_VECTOR_DB = 1, /* For Intel use only */ + SGX_EXCEPTION_VECTOR_BP = 3, /* INT 3 instruction */ + SGX_EXCEPTION_VECTOR_BR = 5, /* BOUND instruction */ + SGX_EXCEPTION_VECTOR_UD = 6, /* UD2 instruction or reserved opcode */ + SGX_EXCEPTION_VECTOR_MF = 16, /* x87 FPU floating-point or WAIT/FWAIT instruction */ + SGX_EXCEPTION_VECTOR_AC = 17, /* Any data reference in memory */ + SGX_EXCEPTION_VECTOR_XM = 19, /* SSE/SSE2/SSE3 floating-point instruction */ +} sgx_exception_vector_t; + +typedef enum _sgx_exception_type_t +{ + SGX_EXCEPTION_HARDWARE = 3, + SGX_EXCEPTION_SOFTWARE = 6, +} sgx_exception_type_t; + +#if defined (_M_X64) || defined (__x86_64__) +typedef struct _cpu_context_t +{ + uint64_t rax; + uint64_t rcx; + uint64_t rdx; + uint64_t rbx; + uint64_t rsp; + uint64_t rbp; + uint64_t rsi; + uint64_t rdi; + uint64_t r8; + uint64_t r9; + uint64_t r10; + uint64_t r11; + uint64_t r12; + uint64_t r13; + uint64_t r14; + uint64_t r15; + uint64_t rflags; + uint64_t rip; +} sgx_cpu_context_t; +#else +typedef struct _cpu_context_t +{ + uint32_t eax; + uint32_t ecx; + uint32_t edx; + uint32_t ebx; + uint32_t esp; + uint32_t ebp; + uint32_t esi; + uint32_t edi; + uint32_t eflags; + uint32_t eip; +} sgx_cpu_context_t; +#endif + +typedef struct _exception_info_t +{ + sgx_cpu_context_t cpu_context; + sgx_exception_vector_t exception_vector; + sgx_exception_type_t exception_type; +} sgx_exception_info_t; + +typedef int (*sgx_exception_handler_t)(sgx_exception_info_t *info); + +#ifdef __cplusplus +extern "C" { +#endif + +/* sgx_register_exception_handler() + * register a custom exception handler + * Parameter + * is_first_handler - the order in which the handler should be called. + * If the parameter is nonzero, the handler is the first handler to be called. + * If the parameter is zero, the handler is the last handler to be called. + * exception_handler - a pointer to the handler to be called. + * Return Value + * handler - success + * NULL - fail +*/ +void * SGXAPI sgx_register_exception_handler(int is_first_handler, sgx_exception_handler_t exception_handler); + +/* sgx_unregister_exception_handler() + * unregister a custom exception handler. + * Parameter + * handler - a handler to the custom excepetion handler previously + * registered using the sgx_register_exception_handler function. + * Return Value + * none zero - success + * 0 - fail +*/ +int SGXAPI sgx_unregister_exception_handler(void *handler); + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/sgx-jvm/linux-sgx/common/inc/sgx_tseal.h b/sgx-jvm/linux-sgx/common/inc/sgx_tseal.h new file mode 100644 index 0000000000..fa93227800 --- /dev/null +++ b/sgx-jvm/linux-sgx/common/inc/sgx_tseal.h @@ -0,0 +1,257 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + + + +#ifndef _SGX_TSEAL_H_ +#define _SGX_TSEAL_H_ + +#include +#include +#include "sgx_key.h" +#include "sgx_error.h" +#include "sgx_defs.h" +#include "sgx_attributes.h" +#include "sgx_tcrypto.h" + +#define SGX_SEAL_TAG_SIZE SGX_AESGCM_MAC_SIZE +#define SGX_SEAL_IV_SIZE 12 + +typedef struct _aes_gcm_data_t +{ + uint32_t payload_size; /* 0: Size of the payload which includes both the encrypted data and the optional additional MAC text */ + uint8_t reserved[12]; /* 4: Reserved bits */ + uint8_t payload_tag[SGX_SEAL_TAG_SIZE]; /* 16: AES-GMAC of the plain text, payload, and the sizes */ + uint8_t payload[]; /* 32: The payload data which includes the encrypted data followed by the optional additional MAC text */ +} sgx_aes_gcm_data_t; + +typedef struct _sealed_data_t +{ + sgx_key_request_t key_request; /* 00: The key request used to obtain the sealing key */ + uint32_t plain_text_offset; /* 64: Offset within aes_data.playload to the start of the optional additional MAC text */ + uint8_t reserved[12]; /* 68: Reserved bits */ + sgx_aes_gcm_data_t aes_data; /* 80: Data structure holding the AES/GCM related data */ +} sgx_sealed_data_t; + +#ifdef __cplusplus +extern "C" { +#endif + /* sgx_calc_sealed_data_size + * Purpose: This function is used to determine how much memory to allocate for sgx_sealed_data_t structure. + * + * Paramters: + * add_mac_txt_size - [IN] Length of the optional additional data stream in bytes + * txt_encrypt_size - [IN] Length of the data stream to be encrypted in bytes + * + * Return Value: + * uint32_t - The minimum number of bytes that need to be allocated for the sgx_sealed_data_t structure + * If the function fails, the return value is UINT32_MAX + */ + uint32_t sgx_calc_sealed_data_size(const uint32_t add_mac_txt_size, const uint32_t txt_encrypt_size); + + /* sgx_get_add_mac_txt_len + * Purpose: This function is used to determine how much memory to allocate for the additional_MAC_text buffer + * + * Parameter: + * p_sealed_data - [IN] Pointer to the sgx_sealed_data_t structure which was populated by the sgx_seal_data function + * + * Return Value: + * uint32_t - The number of bytes in the optional additional MAC buffer + */ + uint32_t sgx_get_add_mac_txt_len(const sgx_sealed_data_t* p_sealed_data); + + /* sgx_get_encrypt_txt_len + * + * Parameter: + * p_sealed_data - [IN] Pointer to the sgx_sealed_data_t structure which was populated by the sgx_seal_data function + * + * Return Value: + * uint32_t - The number of bytes in the encrypted data buffer + * If the function fails, the return value is UINT32_MAX + */ + uint32_t sgx_get_encrypt_txt_len(const sgx_sealed_data_t* p_sealed_data); + + + /* sgx_seal_data + * Purpose: This algorithm is used to AES-GCM encrypt the input data. Specifically, + * two input data sets can be provided, one is the text to encrypt (p_text2encrypt) + * the second being optional additional text that should not be encrypted but will + * be part of the GCM MAC calculation. + * The sgx_sealed_data_t structure should be allocated prior to the API call and + * should include buffer storage for the MAC text and encrypted text. + * The sgx_sealed_data_t structure contains the data required to unseal the data on + * the same system it was sealed. + * + * Parameters: + * additional_MACtext_length - [IN] length of the plaintext data stream in bytes + * The additional data is optional and thus the length + * can be zero if no data is provided + * p_additional_MACtext - [IN] pointer to the plaintext data stream to be GCM protected + * The additional data is optional. You may pass a NULL pointer + * but additional_MACtext_length must be zero in that case + * text2encrypt_length - [IN] length of the data stream to encrypt in bytes + * p_text2encrypt - [IN] pointer to data stream to encrypt + * sealed_data_size - [IN] Size of the sealed data buffer passed in + * p_sealed_data - [OUT] pointer to the sealed data structure containing protected data + * + * Return Value: + * sgx_status_t - SGX Error code + */ + sgx_status_t SGXAPI sgx_seal_data(const uint32_t additional_MACtext_length, + const uint8_t *p_additional_MACtext, + const uint32_t text2encrypt_length, + const uint8_t *p_text2encrypt, + const uint32_t sealed_data_size, + sgx_sealed_data_t *p_sealed_data); + + /* sgx_seal_data_ex + * Purpose: Expert version of sgx_seal_data which is used if the key_policy/attribute_mask/misc_mask + * need to be modified from the default values. + * + * Parameters: + * key_policy - [IN] Specifies the measurement to use in key derivation + * attribute_mask - [IN] Identifies which platform/enclave attributes to use in key derivation + * misc_mask - [IN] The mask for MISC_SELECT + * additional_MACtext_length - [IN] length of the plaintext data stream in bytes + * The additional data is optional and thus the length + * can be zero if no data is provided + * p_additional_MACtext - [IN] pointer to the plaintext data stream to be GCM protected + * The additional data is optional. You may pass a NULL pointer + * but additional_MACtext_length must be zero in that case + * text2encrypt_length - [IN] length of the data stream to encrypt in bytes + * p_text2encrypt - [IN] pointer to data stream to encrypt + * sealed_data_size - [IN] Size of the sealed data buffer passed in + * p_sealed_data - [OUT] pointer to the sealed data structure containing protected data + * + * Return Value: + * sgx_status_t - SGX Error code + */ + sgx_status_t SGXAPI sgx_seal_data_ex(const uint16_t key_policy, + const sgx_attributes_t attribute_mask, + const sgx_misc_select_t misc_mask, + const uint32_t additional_MACtext_length, + const uint8_t *p_additional_MACtext, + const uint32_t text2encrypt_length, + const uint8_t *p_text2encrypt, + const uint32_t sealed_data_size, + sgx_sealed_data_t *p_sealed_data); + + /* sgx_unseal_data + * Purpose: Unseal the sealed data structure passed in and populate the MAC text and decrypted text + * buffers with the appropriate data from the sealed data structure. + * + * Parameters: + * p_sealed_data - [IN] pointer to the sealed data structure containing protected data + * p_additional_MACtext - [OUT] pointer to the plaintext data stream which was GCM protected + * The additiona data is optional. You may pass a NULL pointer but + * p_additional_MACtext_length must be zero in that case + * p_additional_MACtext_length - [IN/OUT] pointer to length of the plaintext data stream in bytes + * If there is not additional data, this parameter should be zero. + * p_decrypted_text - [OUT] pointer to decrypted data stream + * p_decrypted_text_length - [IN/OUT] pointer to length of the decrypted data stream to encrypt in bytes + * + * Return Value: + * sgx_status_t - SGX Error code + */ + sgx_status_t SGXAPI sgx_unseal_data(const sgx_sealed_data_t *p_sealed_data, + uint8_t *p_additional_MACtext, + uint32_t *p_additional_MACtext_length, + uint8_t *p_decrypted_text, + uint32_t *p_decrypted_text_length); + + /* sgx_mac_aadata + * Purpose: Use AES-GCM algorithm to generate a sealed data structure with integrity protection. + * Specifically, the input data set is ONLY the plaintext data stream, or + * additional authenticated data(AAD), no encrypt data. + * The sgx_sealed_data_t structure should be allocated prior to the API call and + * should include buffer storage for the plaintext data. + * The sgx_sealed_data_t structure contains the data required to unseal the data on + * the same system it was sealed. + * + * Parameters: + * additional_MACtext_length - [IN] length of the plaintext data stream in bytes + * p_additional_MACtext - [IN] pointer to the plaintext data stream to be GCM protected + * sealed_data_size - [IN] Size of the sealed data buffer passed in + * p_sealed_data - [OUT] pointer to the sealed data structure containing protected data + * + * Return Value: + * sgx_status_t - SGX Error code + */ + sgx_status_t sgx_mac_aadata(const uint32_t additional_MACtext_length, + const uint8_t *p_additional_MACtext, + const uint32_t sealed_data_size, + sgx_sealed_data_t *p_sealed_data); + + /* sgx_mac_aadata_ex + * Purpose: Expert version of sgx_mac_aadata which is used if the key_policy/attribute_mask/misc_mask + * need to be modified from the default values. + * + * Parameters: + * key_policy - [IN] Specifies the measurement to use in key derivation + * attribute_mask - [IN] Identifies which platform/enclave attributes to use in key derivation + * misc_mask - [IN] The mask for MISC_SELECT + * additional_MACtext_length - [IN] length of the plaintext data stream in bytes + * p_additional_MACtext - [IN] pointer to the plaintext data stream to be GCM protected + * sealed_data_size - [IN] Size of the sealed data buffer passed in + * p_sealed_data - [OUT] pointer to the sealed data structure containing protected data + * + * Return Value: + * sgx_status_t - SGX Error code + */ + sgx_status_t sgx_mac_aadata_ex(const uint16_t key_policy, + const sgx_attributes_t attribute_mask, + const sgx_misc_select_t misc_mask, + const uint32_t additional_MACtext_length, + const uint8_t *p_additional_MACtext, + const uint32_t sealed_data_size, + sgx_sealed_data_t *p_sealed_data); + + /* sgx_unmac_aadata + * Purpose: Unseal the sealed data structure passed in and populate the plaintext data stream + * with the appropriate data from the sealed data structure. + * + * Parameters: + * p_sealed_data - [IN] pointer to the sealed data structure containing protected data + * p_additional_MACtext - [OUT] pointer to the plaintext data stream which was GCM protected + * p_additional_MACtext_length - [IN/OUT] pointer to length of the plaintext data stream in bytes + * + * Return Value: + * sgx_status_t - SGX Error code + */ + sgx_status_t sgx_unmac_aadata(const sgx_sealed_data_t *p_sealed_data, + uint8_t *p_additional_MACtext, + uint32_t *p_additional_MACtext_length); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/sgx-jvm/linux-sgx/common/inc/sgx_tstdc.edl b/sgx-jvm/linux-sgx/common/inc/sgx_tstdc.edl new file mode 100644 index 0000000000..e92e2218c3 --- /dev/null +++ b/sgx-jvm/linux-sgx/common/inc/sgx_tstdc.edl @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +enclave { + untrusted { + [cdecl] void sgx_oc_cpuidex([in, out] int cpuinfo[4], int leaf, int subleaf); + + /* Go outside and wait on my untrusted event */ + [cdecl] int sgx_thread_wait_untrusted_event_ocall([user_check] const void *self); + + /* Wake a thread waiting on its untrusted event */ + [cdecl] int sgx_thread_set_untrusted_event_ocall([user_check] const void *waiter); + + /* Wake a thread waiting on its untrusted event, and wait on my untrusted event */ + [cdecl] int sgx_thread_setwait_untrusted_events_ocall([user_check] const void *waiter, [user_check] const void *self); + + /* Wake multiple threads waiting on their untrusted events */ + [cdecl] int sgx_thread_set_multiple_untrusted_events_ocall([in, count = total] const void **waiters, size_t total); + }; +}; diff --git a/sgx-jvm/linux-sgx/common/inc/sgx_uae_service.h b/sgx-jvm/linux-sgx/common/inc/sgx_uae_service.h new file mode 100644 index 0000000000..ff668b131b --- /dev/null +++ b/sgx-jvm/linux-sgx/common/inc/sgx_uae_service.h @@ -0,0 +1,171 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef _SGX_UAE_SERVICE_H_ +#define _SGX_UAE_SERVICE_H_ + +#include + +#include "sgx_quote.h" +#include "sgx_error.h" +#include "sgx_urts.h" + +#define PS_CAP_TRUSTED_TIME 0x1 +#define PS_CAP_MONOTONIC_COUNTER 0x2 + +/** + * Platform service capabilities + * ps_cap0 + * Bit 0 : Trusted Time + * Bit 1 : Monotonic Counter + * Bit 2-31 : Reserved + * ps_cap1 + * Bit 0-31 : Reserved + */ +typedef struct _sgx_ps_cap_t +{ + uint32_t ps_cap0; + uint32_t ps_cap1; +} sgx_ps_cap_t; + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Function used to initialize the process of quoting. + * + * @param p_target_info[out] Target info of quoting enclave. + * @param p_gid[out] ID of platform's current EPID group. + * @return If outputs are generated, return SGX_SCCUESS, otherwise return general error code + * or SGX_ERROR_AE_INVALID_EPIDBLOB to indicate special error condition. + */ +sgx_status_t SGXAPI sgx_init_quote( + sgx_target_info_t *p_target_info, + sgx_epid_group_id_t *p_gid); + + +/* + * Function used to get quote size. + * + * @param p_sig_rl[in] OPTIONAL Signature Revocation List. + * @param p_quote_size[out] Quote size, in bytes. + * @return If quote size is calculated,return SGX_SCCUESS, otherwise return + * SGX_ERROR_INVALID_PARAMETER to indicate special error condition. + */ +sgx_status_t SGXAPI sgx_get_quote_size( + const uint8_t *p_sig_rl, + uint32_t* p_quote_size); + +/* + * Function used to get quote. + * + * @param p_report[in] Report of enclave for which quote is being calculated. + * @param quote_type[in] Linkable or unlinkable quote. + * @param p_spid[in] Pointer of SPID. + * @param p_nonce[in] OPTIONAL nonce. + * @param p_sig_rl[in] OPTIONAL list of signature made fore EPID. + * @param sig_rl_size[in] The size of p_sig_rl, in bytes. + * @param p_qe_report[out] OPTIONAL The QE report. + * @param p_quote[out] The quote buffer, can not be NULL. + * @param quote_size[in] Quote buffer size, in bytes. + * @return If quote is generated,return SGX_SCCUESS, + * error code or SGX_ERROR_AE_INVALID_EPIDBLOB, + * SGX_ERROR_INVALID_PARAMETER to indicate special error condition. + * SGX_ERROR_EPID_MEMBER_REVOKED to indicate the EPID group membership has been revoked. + */ +sgx_status_t SGXAPI sgx_get_quote( + const sgx_report_t *p_report, + sgx_quote_sign_type_t quote_type, + const sgx_spid_t *p_spid, + const sgx_quote_nonce_t *p_nonce, + const uint8_t *p_sig_rl, + uint32_t sig_rl_size, + sgx_report_t *p_qe_report, + sgx_quote_t *p_quote, + uint32_t quote_size); + +/** + * Get the platform service capabilities + * + * @param sgx_ps_cap Platform capabilities reported by AESM. + * @return if OK, return SGX_SUCCESS + */ +sgx_status_t SGXAPI sgx_get_ps_cap(sgx_ps_cap_t* p_sgx_ps_cap); + +/** + * Get the white list's size + * + * @param p_whitelist_size Save the size of the white list. + * @return if OK, return SGX_SUCCESS + */ +sgx_status_t SGXAPI sgx_get_whitelist_size(uint32_t* p_whitelist_size); + +/** + * Get the white list value + * + * @param p_whitelist Save the white list value + * @param whitelist_size The size of the white list and the read data size is whitelist_size + * @return if OK, return SGX_SUCCESS + */ +sgx_status_t SGXAPI sgx_get_whitelist(uint8_t* p_whitelist, uint32_t whitelist_size); + +/** + * Get the extended epid group id + * + * @param p_extended_epid_group_id Save the extended epid group id. + * @return if OK, return SGX_SUCCESS + */ +sgx_status_t SGXAPI sgx_get_extended_epid_group_id(uint32_t* p_extended_epid_group_id); + +#define SGX_IS_TRUSTED_TIME_AVAILABLE(cap) ((((uint32_t)PS_CAP_TRUSTED_TIME)&((cap).ps_cap0))!=0) +#define SGX_IS_MONOTONIC_COUNTER_AVAILABLE(cap) ((((uint32_t)PS_CAP_MONOTONIC_COUNTER)&((cap).ps_cap0))!=0) + +/* + * Function used to report the status of the attestation. + * + * @param p_platform_info[in] platform information received from Intel Attestation Server. + * @param attestation_status[in] Value representing status during attestation. 0 if attestation succeeds. + * @param p_update_info[out] update information of the SGX platform. + * @return If OK, return SGX_SUCCESS. If update is needed, return SGX_ERROR_UPDATE_NEEDED and update_info contains update information. + */ + +sgx_status_t SGXAPI sgx_report_attestation_status( + const sgx_platform_info_t* p_platform_info, + int attestation_status, + sgx_update_info_bit_t* p_update_info); + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/sgx-jvm/linux-sgx/common/inc/sgx_ukey_exchange.h b/sgx-jvm/linux-sgx/common/inc/sgx_ukey_exchange.h new file mode 100644 index 0000000000..0f1e79f506 --- /dev/null +++ b/sgx-jvm/linux-sgx/common/inc/sgx_ukey_exchange.h @@ -0,0 +1,199 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef _SGX_UKEY_EXCHANGE_H_ +#define _SGX_UKEY_EXCHANGE_H_ + +#include "sgx_eid.h" +#include "sgx_defs.h" +#include "sgx_key_exchange.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +typedef sgx_status_t (* sgx_ecall_get_ga_trusted_t)( + sgx_enclave_id_t eid, + sgx_status_t* retval, + sgx_ra_context_t context, + sgx_ec256_public_t *g_a); + +typedef sgx_status_t (* sgx_ecall_proc_msg2_trusted_t)( + sgx_enclave_id_t eid, + sgx_status_t* retval, + sgx_ra_context_t context, + const sgx_ra_msg2_t *p_msg2, + const sgx_target_info_t *p_qe_target, + sgx_report_t *p_report, + sgx_quote_nonce_t* nonce); + +typedef sgx_status_t (* sgx_ecall_get_msg3_trusted_t)( + sgx_enclave_id_t eid, + sgx_status_t* retval, + sgx_ra_context_t context, + uint32_t quote_size, + sgx_report_t* qe_report, + sgx_ra_msg3_t *p_msg3, + uint32_t msg3_size); + +/* + * sgx_ra_get_msg1 is used to get the remote attestation and key exchange + * protocol message 1 to send to a service provider. The application enclave + * should use sgx_ra_init function to create the remote attestation and key + * exchange process context and return to the untrusted code, before the + * untrusted code can invoke this function. + * + * @param context Context returned by the sgx_ra_init function inside the + * application enclave. + * @param eid ID of the application enclave which is going to be + * attested. + * @param p_get_ga Function pointer of the ECALL proxy sgx_ra_get_ga + * generated by sgx_edger8r. The application enclave should + * link with sgx_tkey_exchange library and import + * sgx_tkey_exchange.edl in the enclave's EDL file to + * expose the ECALL proxy for sgx_ra_get_ga. + * @param p_msg1 Message 1 used by the remote attestation and key + * exchange protocol. + * @return sgx_status_t SGX_SUCCESS Indicates success. + * SGX_ERROR_INVALID_PARAMETER Invalid input parameters + * detected. + * SGX_ERROR_AE_INVALID_EPIDBLOB The EPID blob is + * corrupted. + * SGX_ERROR_INVALID_STATE SGX API is invoked in + * incorrect order or + * state. + * SGX_ERROR_EPID_MEMBER_REVOKED The EPID group + * membership revoked. + * SGX_ERROR_BUSY The requested service is + * temporarily not + * available. + * SGX_ERROR_UPDATE_NEEDED SGX needs to be updated. + * SGX_ERROR_SERVICE_UNAVAILABLE The AE service did not + * respond. + * SGX_ERROR_SERVICE_TIMEOUT A request to the AE + * service timed out. + * SGX_ERROR_NETWORK_FAILURE Network connecting or + * proxy setting issue was + * encountered. + * SGX_ERROR_OUT_OF_MEMORY There is not enough + * memory available to + * complete this operation. + * SGX_ERROR_UNEXPECTED Indicates an unexpected + * error occurs. + * And other possible return code from sgx_ecall. + */ +sgx_status_t SGXAPI sgx_ra_get_msg1( + sgx_ra_context_t context, + sgx_enclave_id_t eid, + sgx_ecall_get_ga_trusted_t p_get_ga, + sgx_ra_msg1_t *p_msg1); + +/* + * sgx_ra_get_msg2 is used to process the remote attestation and key exchange + * protocol message 2 from the service provider and generate message 3 to send + * to the service provider. If the service provider accepts message 3, + * negotiated session keys between the application enclave and the service + * provider are ready for use. The application enclave can use sgx_ra_get_keys + * function to retrieve the negotiated keys and use sgx_ra_close function to + * release the context of the remote attestation and key exchange process. + * + * @param context Context returned by the sgx_ra_init function inside the + * application enclave. + * @param eid ID of the application enclave which is going to be + * attested. + * @param p_proc_msg2 Function pointer of the ECALL proxy sgx_ra_proc_msg2_trusted + * generated by sgx_edger8r. The application enclave should + * link with sgx_tkey_exchange library and import the + * sgx_tkey_exchange.edl in the application enclave's EDL + * file to expose the ECALL proxy for sgx_ra_get_msg2. + * @param p_get_msg3 Function pointer of the ECALL proxy sgx_ra_get_msg3_trusted + * generated by sgx_edger8r. The application enclave should + * link with sgx_tkey_exchange library and import the + * sgx_tkey_exchange.edl in the application enclave's EDL + * file to expose the ECALL proxy for sgx_ra_get_msg3. + * @param p_msg2 sgx_ra_msg2_t message 2 from the service provider + * received by application. + * @param msg2_size The length of msg2 (in bytes). + * @param pp_msg3 sgx_ra_msg3_t message 3 to be sent to the service + * provider. The message buffer is allocated by the + * sgx_ukey_exchange library. The caller should free the + * buffer after use. + * @param p_msg3_size The length of msg3 (in bytes). + * @return sgx_status_t SGX_SUCCESS Indicates success. + * SGX_ERROR_INVALID_PARAMETER Invalid input parameters + * detected. + * SGX_ERROR_AE_INVALID_EPIDBLOB The EPID blob is + * corrupted. + * SGX_ERROR_INVALID_STATE SGX API is invoked in + * incorrect order or + * state. + * SGX_ERROR_EPID_MEMBER_REVOKED The EPID group + * membership revoked. + * SGX_ERROR_INVALID_SIGNATURE The signature is invalid. + * SGX_ERROR_MAC_MISMATCH Indicates verification + * error for reports, sealed + * data, etc. + * SGX_ERROR_KDF_MISMATCH Indicates key derivation + * function doesn't match. + * SGX_ERROR_BUSY The requested service is + * temporarily not + * available. + * SGX_ERROR_UPDATE_NEEDED SGX needs to be updated. + * SGX_ERROR_SERVICE_UNAVAILABLE The AE service did not + * respond. + * SGX_ERROR_SERVICE_TIMEOUT A request to the AE + * service timed out. + * SGX_ERROR_NETWORK_FAILURE Network connecting or + * proxy setting issue was + * encountered. + * SGX_ERROR_OUT_OF_MEMORY There is not enough + * memory available to + * complete this operation. + * SGX_ERROR_UNEXPECTED Indicates an unexpected + * error occurs. + * And other possible return code from sgx_ecall. + */ +sgx_status_t SGXAPI sgx_ra_proc_msg2( + sgx_ra_context_t context, + sgx_enclave_id_t eid, + sgx_ecall_proc_msg2_trusted_t p_proc_msg2, + sgx_ecall_get_msg3_trusted_t p_get_msg3, + const sgx_ra_msg2_t *p_msg2, + uint32_t msg2_size, + sgx_ra_msg3_t **pp_msg3, + uint32_t *p_msg3_size); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/sgx-jvm/linux-sgx/common/inc/sgx_urts.h b/sgx-jvm/linux-sgx/common/inc/sgx_urts.h new file mode 100644 index 0000000000..c1bfa65183 --- /dev/null +++ b/sgx-jvm/linux-sgx/common/inc/sgx_urts.h @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + + + +#ifndef _SGX_URTS_H_ +#define _SGX_URTS_H_ + +#include "sgx_attributes.h" +#include "sgx_error.h" +#include "sgx_eid.h" +#include "sgx_defs.h" +#include "sgx_key.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef uint8_t sgx_launch_token_t[1024]; + +/* Convenient macro to be passed to sgx_create_enclave(). */ +#if !defined(NDEBUG) || defined(EDEBUG) +#define SGX_DEBUG_FLAG ((int)1) +#else +#define SGX_DEBUG_FLAG ((int)0) +#endif + +sgx_status_t SGXAPI sgx_create_enclave(const char *file_name, const int debug, sgx_launch_token_t *launch_token, int *launch_token_updated, sgx_enclave_id_t *enclave_id, sgx_misc_attribute_t *misc_attr); + +sgx_status_t SGXAPI sgx_destroy_enclave(const sgx_enclave_id_t enclave_id); + +#ifdef __cplusplus +} +#endif + + +#endif diff --git a/sgx-jvm/linux-sgx/common/inc/sgx_utils.h b/sgx-jvm/linux-sgx/common/inc/sgx_utils.h new file mode 100644 index 0000000000..0d8420b753 --- /dev/null +++ b/sgx-jvm/linux-sgx/common/inc/sgx_utils.h @@ -0,0 +1,90 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + + + +/** + * File: sgx_utils.h + * Description: + * Trusted library for SGX instructions + */ + +#ifndef _SGX_UTILS_H_ +#define _SGX_UTILS_H_ + +#include "sgx.h" +#include "sgx_defs.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/*sgx_create_report + * Purpose: Create a cryptographic report of the enclave using the input information if any. + * + * Parameters: + * target_info - [IN] pointer to the information of the target enclave. + * report_data - [IN] pointer to a set of data used for communication between the enclaves. + * report - [OUT] pointer to the cryptographic report of the enclave + * + * Return value: + * sgx_status_t - SGX_SUCCESS or failure as defined in sgx_error.h. +*/ +sgx_status_t SGXAPI sgx_create_report(const sgx_target_info_t *target_info, const sgx_report_data_t *report_data, sgx_report_t *report); + +/* sgx_verify_report + * Purpose: Software verification for the input report + * + * Paramters: + * report - [IN] ponter to the cryptographic report to be verified. + * + * Return value: + * sgx_status_t - SGX_SUCCESS or failure as defined in sgx_error.h. +*/ +sgx_status_t SGXAPI sgx_verify_report(const sgx_report_t *report); + +/*sgx_get_key + * Purpose: Generate a 128-bit secret key with the input information. + * + * Parameters: + * key_request - [IN] pointer to the sgx_key_request_t object used for selecting the appropriate key. + * key - [OUT] Pointer to the buffer that receives the cryptographic key output. + * + * Return value: + * sgx_status_t - SGX_SUCCESS or failure as defined in sgx_error.h. +*/ +sgx_status_t SGXAPI sgx_get_key(const sgx_key_request_t *key_request, sgx_key_128bit_t *key); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/sgx-jvm/linux-sgx/common/inc/stdc++/exception b/sgx-jvm/linux-sgx/common/inc/stdc++/exception new file mode 100644 index 0000000000..0389bfd199 --- /dev/null +++ b/sgx-jvm/linux-sgx/common/inc/stdc++/exception @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef _EXCEPTION_ +#define _EXCEPTION_ + +#include +#include SGX_CXX_NATIVE_HEADER(exception) + +#endif /* _EXCEPTION_ */ diff --git a/sgx-jvm/linux-sgx/common/inc/stdc++/linux/exception b/sgx-jvm/linux-sgx/common/inc/stdc++/linux/exception new file mode 100644 index 0000000000..afcb0feac1 --- /dev/null +++ b/sgx-jvm/linux-sgx/common/inc/stdc++/linux/exception @@ -0,0 +1,77 @@ +/* + * Copyright 2010-2011 PathScale, Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS + * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _LINUX_EXCEPTION_ +#define _LINUX_EXCEPTION_ + + +namespace std +{ + class exception + { + public: + exception() throw(); + exception(const exception&) throw(); + exception& operator=(const exception&) throw(); + virtual ~exception(); + virtual const char* what() const throw(); + }; + + /** + * Bad allocation exception. Thrown by ::operator new() if it fails. + */ + class bad_alloc: public exception + { + public: + bad_alloc() throw(); + bad_alloc(const bad_alloc&) throw(); + bad_alloc& operator=(const bad_alloc&) throw(); + ~bad_alloc(); + virtual const char* what() const throw(); + }; + + class bad_exception : public exception + { + public: + bad_exception() throw(); + virtual ~bad_exception() throw(); + virtual const char* what() const throw(); + }; + + bool uncaught_exception() throw(); + + typedef void (*unexpected_handler)(); + unexpected_handler set_unexpected(unexpected_handler) throw(); + void unexpected(); + + typedef void (*terminate_handler)(); + terminate_handler set_terminate(terminate_handler) throw(); + void terminate(); + +} // namespace std + + +#endif /* _LINUX_EXCEPTION_ */ diff --git a/sgx-jvm/linux-sgx/common/inc/stdc++/linux/typeinfo b/sgx-jvm/linux-sgx/common/inc/stdc++/linux/typeinfo new file mode 100644 index 0000000000..a32df180f6 --- /dev/null +++ b/sgx-jvm/linux-sgx/common/inc/stdc++/linux/typeinfo @@ -0,0 +1,138 @@ +/* + * Copyright 2010-2011 PathScale, Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS + * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _LINUX_TYPEINFO_ +#define _LINUX_TYPEINFO_ + +#include +#include "exception" + +namespace __cxxabiv1 +{ + struct __class_type_info; +} +namespace std +{ + /** + * Standard type info class. The layout of this class is specified by the + * ABI. The layout of the vtable is not, but is intended to be + * compatible with the GNU ABI. + * + * Unlike the GNU version, the vtable layout is considered semi-private. + */ + class type_info + { + public: + /** + * Virtual destructor. This class must have one virtual function to + * ensure that it has a vtable. + */ + virtual ~type_info(); + bool operator==(const type_info &) const; + bool operator!=(const type_info &) const; + bool before(const type_info &) const; + const char* name() const; + type_info(); + private: + type_info(const type_info& rhs); + type_info& operator= (const type_info& rhs); + const char *__type_name; + /* + * The following functions are in this order to match the + * vtable layout of libsupc++. This allows libcxxrt to be used + * with libraries that depend on this. + * + * These functions are in the public headers for libstdc++, so + * we have to assume that someone will probably call them and + * expect them to work. Their names must also match the names used in + * libsupc++, so that code linking against this library can subclass + * type_info and correctly fill in the values in the vtables. + */ + public: + /** + * Returns true if this is some pointer type, false otherwise. + */ + virtual bool __is_pointer_p() const { return false; } + /** + * Returns true if this is some function type, false otherwise. + */ + virtual bool __is_function_p() const { return false; } + /** + * Catch function. Allows external libraries to implement + * their own basic types. This is used, for example, in the + * GNUstep Objective-C runtime to allow Objective-C types to be + * caught in G++ catch blocks. + * + * The outer parameter indicates the number of outer pointers + * in the high bits. The low bit indicates whether the + * pointers are const qualified. + */ + virtual bool __do_catch(const type_info *thrown_type, + void **thrown_object, + unsigned outer) const; + /** + * Performs an upcast. This is used in exception handling to + * cast from subclasses to superclasses. If the upcast is + * possible, it returns true and adjusts the pointer. If the + * upcast is not possible, it returns false and does not adjust + * the pointer. + */ + virtual bool __do_upcast( + const __cxxabiv1::__class_type_info *target, + void **thrown_object) const + { + (void)target, (void)thrown_object; + return false; + } + }; + + /** + * Bad cast exception. Thrown by the __cxa_bad_cast() helper function. + */ + class bad_cast: public exception { + public: + bad_cast() throw(); + bad_cast(const bad_cast&) throw(); + bad_cast& operator=(const bad_cast&) throw(); + virtual ~bad_cast(); + virtual const char* what() const throw(); + }; + + /** + * Bad typeidexception. Thrown by the __cxa_bad_typeid() helper function. + */ + class bad_typeid: public exception + { + public: + bad_typeid() throw(); + bad_typeid(const bad_typeid &__rhs) throw(); + virtual ~bad_typeid(); + bad_typeid& operator=(const bad_typeid &__rhs) throw(); + virtual const char* what() const throw(); + }; +} + +#endif /* _LINUX_TYPEINFO_ */ diff --git a/sgx-jvm/linux-sgx/common/inc/stdc++/new b/sgx-jvm/linux-sgx/common/inc/stdc++/new new file mode 100644 index 0000000000..fbf11fb67d --- /dev/null +++ b/sgx-jvm/linux-sgx/common/inc/stdc++/new @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef _NEW_ +#define _NEW_ + +#include +#include +#include + + +namespace std +{ + typedef void (*new_handler)(); // The type of the function called when allocation fails. + + struct nothrow_t {}; // placement new tag type to suppress exceptions + const nothrow_t nothrow = {}; // constant for placement new tag + + /* + * The function to call when allocation fails. By default, there is no + * handler and a bad allocation exception is thrown if an allocation fails. + */ + new_handler set_new_handler(new_handler handler) throw(); +}; + +void* SGXAPI operator new (size_t) throw (std::bad_alloc); +void* SGXAPI operator new[] (size_t) throw (std::bad_alloc); + +void* SGXAPI operator new (size_t, const std::nothrow_t&) throw(); +void* SGXAPI operator new (size_t, void*) throw(); +void* SGXAPI operator new[] (size_t, const std::nothrow_t&) throw(); +void* SGXAPI operator new[] (size_t, void*) throw(); + +void SGXAPI operator delete (void*) throw (); +void SGXAPI operator delete (void*, const std::nothrow_t&) throw(); +void SGXAPI operator delete (void*, void*) throw(); +void SGXAPI operator delete[] (void*) throw (); +void SGXAPI operator delete[] (void*, const std::nothrow_t&) throw(); +void SGXAPI operator delete[] (void*, void*) throw(); + +#endif /* _NEW_ */ diff --git a/sgx-jvm/linux-sgx/common/inc/stdc++/typeinfo b/sgx-jvm/linux-sgx/common/inc/stdc++/typeinfo new file mode 100644 index 0000000000..fa9c05e737 --- /dev/null +++ b/sgx-jvm/linux-sgx/common/inc/stdc++/typeinfo @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef _TYPEINFO_ +#define _TYPEINFO_ + +#include +#include SGX_CXX_NATIVE_HEADER(typeinfo) + +#endif /* _TYPEINFO_ */ diff --git a/sgx-jvm/linux-sgx/common/inc/tlibc/assert.h b/sgx-jvm/linux-sgx/common/inc/tlibc/assert.h new file mode 100644 index 0000000000..82489e80c0 --- /dev/null +++ b/sgx-jvm/linux-sgx/common/inc/tlibc/assert.h @@ -0,0 +1,63 @@ +/* $OpenBSD: assert.h,v 1.12 2006/01/31 10:53:51 hshoexer Exp $ */ +/* $NetBSD: assert.h,v 1.6 1994/10/26 00:55:44 cgd Exp $ */ + +/*- + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * (c) UNIX System Laboratories, Inc. + * All or some portions of this file are derived from material licensed + * to the University of California by American Telephone and Telegraph + * Co. or Unix System Laboratories, Inc. and are reproduced herein with + * the permission of UNIX System Laboratories, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)assert.h 8.2 (Berkeley) 1/21/94 + */ + +/* + * Unlike other ANSI header files, may usefully be included + * multiple times, with and without NDEBUG defined. + */ + +#include + +#undef assert + +#ifdef NDEBUG +# define assert(e) ((void)0) +#else +# define assert(e) ((e) ? (void)0 : __assert(__FILE__, __LINE__, __func__, #e)) +#endif + +#ifndef _ASSERT_H_DECLS +#define _ASSERT_H_DECLS +__BEGIN_DECLS + +void _TLIBC_CDECL_ __assert(const char *, int, const char *, const char *); + +__END_DECLS +#endif /* Not _ASSERT_H_DECLS */ + diff --git a/sgx-jvm/linux-sgx/common/inc/tlibc/complex.h b/sgx-jvm/linux-sgx/common/inc/tlibc/complex.h new file mode 100644 index 0000000000..7d92d63e87 --- /dev/null +++ b/sgx-jvm/linux-sgx/common/inc/tlibc/complex.h @@ -0,0 +1,134 @@ +/* $OpenBSD: complex.h,v 1.3 2010/07/24 22:17:03 guenther Exp $ */ +/* + * Copyright (c) 2008 Martynas Venckus + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _COMPLEX_H_ +#define _COMPLEX_H_ + +#include + +/* + * C99 + */ +#ifdef __GNUC__ +#if __STDC_VERSION__ < 199901 +#define _Complex __complex__ +#endif +#define _Complex_I 1.0fi +#elif defined(lint) +#define _Complex_I 1.0fi +#endif + +#define complex _Complex + +/* XXX switch to _Imaginary_I */ +#undef I +#define I _Complex_I + +__BEGIN_DECLS +/* + * Double versions of C99 functions + */ +double complex cacos(double complex); +double complex casin(double complex); +double complex catan(double complex); +double complex ccos(double complex); +double complex csin(double complex); +double complex ctan(double complex); +double complex cacosh(double complex); +double complex casinh(double complex); +double complex catanh(double complex); +double complex ccosh(double complex); +double complex csinh(double complex); +double complex ctanh(double complex); +double complex cexp(double complex); +double complex clog(double complex); +double cabs(double complex); +double complex cpow(double complex, double complex); +double complex csqrt(double complex); +double carg(double complex); +double cimag(double complex); +double complex conj(double complex); +double complex cproj(double complex); +double creal(double complex); +/* + * C99 reserved + */ +double complex clog10(double complex); + +/* + * Float versions of C99 functions + */ +float complex cacosf(float complex); +float complex casinf(float complex); +float complex catanf(float complex); +float complex ccosf(float complex); +float complex csinf(float complex); +float complex ctanf(float complex); +float complex cacoshf(float complex); +float complex casinhf(float complex); +float complex catanhf(float complex); +float complex ccoshf(float complex); +float complex csinhf(float complex); +float complex ctanhf(float complex); +float complex cexpf(float complex); +float complex clogf(float complex); +float cabsf(float complex); +float complex cpowf(float complex, float complex); +float complex csqrtf(float complex); +float cargf(float complex); +float cimagf(float complex); +float complex conjf(float complex); +float complex cprojf(float complex); +float crealf(float complex); +/* + * C99 reserved + */ +float complex clog10f(float complex); + +/* + * Long double versions of C99 functions + */ +long double complex cacosl(long double complex); +long double complex casinl(long double complex); +long double complex catanl(long double complex); +long double complex ccosl(long double complex); +long double complex csinl(long double complex); +long double complex ctanl(long double complex); +long double complex cacoshl(long double complex); +long double complex casinhl(long double complex); +long double complex catanhl(long double complex); +long double complex ccoshl(long double complex); +long double complex csinhl(long double complex); +long double complex ctanhl(long double complex); +long double complex cexpl(long double complex); +long double complex clogl(long double complex); +long double cabsl(long double complex); +long double complex cpowl(long double complex, long double complex); +long double complex csqrtl(long double complex); +long double cargl(long double complex); +long double cimagl(long double complex); +long double complex conjl(long double complex); +long double complex cprojl(long double complex); +long double creall(long double complex); +/* + * C99 reserved + */ +long double complex clog10l(long double complex); + +__END_DECLS + +#endif /* !_COMPLEX_H_ */ diff --git a/sgx-jvm/linux-sgx/common/inc/tlibc/ctype.h b/sgx-jvm/linux-sgx/common/inc/tlibc/ctype.h new file mode 100644 index 0000000000..1408447059 --- /dev/null +++ b/sgx-jvm/linux-sgx/common/inc/tlibc/ctype.h @@ -0,0 +1,64 @@ +/* $OpenBSD: ctype.h,v 1.22 2010/10/01 20:10:24 guenther Exp $ */ +/* $NetBSD: ctype.h,v 1.14 1994/10/26 00:55:47 cgd Exp $ */ + +/* + * Copyright (c) 1989 The Regents of the University of California. + * All rights reserved. + * (c) UNIX System Laboratories, Inc. + * All or some portions of this file are derived from material licensed + * to the University of California by American Telephone and Telegraph + * Co. or Unix System Laboratories, Inc. and are reproduced herein with + * the permission of UNIX System Laboratories, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)ctype.h 5.3 (Berkeley) 4/3/91 + */ + +#ifndef _CTYPE_H_ +#define _CTYPE_H_ + +#include + +__BEGIN_DECLS + +int _TLIBC_CDECL_ isalnum(int); +int _TLIBC_CDECL_ isalpha(int); +int _TLIBC_CDECL_ iscntrl(int); +int _TLIBC_CDECL_ isdigit(int); +int _TLIBC_CDECL_ isgraph(int); +int _TLIBC_CDECL_ islower(int); +int _TLIBC_CDECL_ isprint(int); +int _TLIBC_CDECL_ ispunct(int); +int _TLIBC_CDECL_ isspace(int); +int _TLIBC_CDECL_ isupper(int); +int _TLIBC_CDECL_ isxdigit(int); +int _TLIBC_CDECL_ tolower(int); +int _TLIBC_CDECL_ toupper(int); +int _TLIBC_CDECL_ isblank(int); + +__END_DECLS + +#endif /* _CTYPE_H_ */ diff --git a/sgx-jvm/linux-sgx/common/inc/tlibc/endian.h b/sgx-jvm/linux-sgx/common/inc/tlibc/endian.h new file mode 100644 index 0000000000..fcd74c9a14 --- /dev/null +++ b/sgx-jvm/linux-sgx/common/inc/tlibc/endian.h @@ -0,0 +1,33 @@ +/* $OpenBSD: endian.h,v 1.18 2006/03/27 07:09:24 otto Exp $ */ + +/*- + * Copyright (c) 1997 Niklas Hallqvist. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _ENDIAN_H_ +#define _ENDIAN_H_ + +#include + +#endif /* _ENDIAN_H_ */ + diff --git a/sgx-jvm/linux-sgx/common/inc/tlibc/errno.h b/sgx-jvm/linux-sgx/common/inc/tlibc/errno.h new file mode 100644 index 0000000000..0924d5ac4b --- /dev/null +++ b/sgx-jvm/linux-sgx/common/inc/tlibc/errno.h @@ -0,0 +1,187 @@ +/* $OpenBSD: errno.h,v 1.1 2005/12/28 16:33:56 millert Exp $ */ + +/* + * Copyright (c) 1982, 1986, 1989, 1993 + * The Regents of the University of California. All rights reserved. + * (c) UNIX System Laboratories, Inc. + * All or some portions of this file are derived from material licensed + * to the University of California by American Telephone and Telegraph + * Co. or Unix System Laboratories, Inc. and are reproduced herein with + * the permission of UNIX System Laboratories, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)errno.h 8.5 (Berkeley) 1/21/94 + */ + +#ifndef _ERRNO_H_ +#define _ERRNO_H_ + +#include + +#define EPERM 1 +#define ENOENT 2 +#define ESRCH 3 +#define EINTR 4 +#define EIO 5 +#define ENXIO 6 +#define E2BIG 7 +#define ENOEXEC 8 +#define EBADF 9 +#define ECHILD 10 +#define EAGAIN 11 +#define ENOMEM 12 +#define EACCES 13 +#define EFAULT 14 +#define ENOTBLK 15 +#define EBUSY 16 +#define EEXIST 17 +#define EXDEV 18 +#define ENODEV 19 +#define ENOTDIR 20 +#define EISDIR 21 +#define EINVAL 22 +#define ENFILE 23 +#define EMFILE 24 +#define ENOTTY 25 +#define ETXTBSY 26 +#define EFBIG 27 +#define ENOSPC 28 +#define ESPIPE 29 +#define EROFS 30 +#define EMLINK 31 +#define EPIPE 32 +#define EDOM 33 +#define ERANGE 34 +#define EDEADLK 35 +#define ENAMETOOLONG 36 +#define ENOLCK 37 +#define ENOSYS 38 +#define ENOTEMPTY 39 +#define ELOOP 40 +#define EWOULDBLOCK EAGAIN +#define ENOMSG 42 +#define EIDRM 43 +#define ECHRNG 44 +#define EL2NSYNC 45 +#define EL3HLT 46 +#define EL3RST 47 +#define ELNRNG 48 +#define EUNATCH 49 +#define ENOCSI 50 +#define EL2HLT 51 +#define EBADE 52 +#define EBADR 53 +#define EXFULL 54 +#define ENOANO 55 +#define EBADRQC 56 +#define EBADSLT 57 +#define EDEADLOCK EDEADLK +#define EBFONT 59 +#define ENOSTR 60 +#define ENODATA 61 +#define ETIME 62 +#define ENOSR 63 +#define ENONET 64 +#define ENOPKG 65 +#define EREMOTE 66 +#define ENOLINK 67 +#define EADV 68 +#define ESRMNT 69 +#define ECOMM 70 +#define EPROTO 71 +#define EMULTIHOP 72 +#define EDOTDOT 73 +#define EBADMSG 74 +#define EOVERFLOW 75 +#define ENOTUNIQ 76 +#define EBADFD 77 +#define EREMCHG 78 +#define ELIBACC 79 +#define ELIBBAD 80 +#define ELIBSCN 81 +#define ELIBMAX 82 +#define ELIBEXEC 83 +#define EILSEQ 84 +#define ERESTART 85 +#define ESTRPIPE 86 +#define EUSERS 87 +#define ENOTSOCK 88 +#define EDESTADDRREQ 89 +#define EMSGSIZE 90 +#define EPROTOTYPE 91 +#define ENOPROTOOPT 92 +#define EPROTONOSUPPORT 93 +#define ESOCKTNOSUPPORT 94 +#define EOPNOTSUPP 95 +#define EPFNOSUPPORT 96 +#define EAFNOSUPPORT 97 +#define EADDRINUSE 98 +#define EADDRNOTAVAIL 99 +#define ENETDOWN 100 +#define ENETUNREACH 101 +#define ENETRESET 102 +#define ECONNABORTED 103 +#define ECONNRESET 104 +#define ENOBUFS 105 +#define EISCONN 106 +#define ENOTCONN 107 +#define ESHUTDOWN 108 +#define ETOOMANYREFS 109 +#define ETIMEDOUT 110 +#define ECONNREFUSED 111 +#define EHOSTDOWN 112 +#define EHOSTUNREACH 113 +#define EALREADY 114 +#define EINPROGRESS 115 +#define ESTALE 116 +#define EUCLEAN 117 +#define ENOTNAM 118 +#define ENAVAIL 119 +#define EISNAM 120 +#define EREMOTEIO 121 +#define EDQUOT 122 +#define ENOMEDIUM 123 +#define EMEDIUMTYPE 124 +#define ECANCELED 125 +#define ENOKEY 126 +#define EKEYEXPIRED 127 +#define EKEYREVOKED 128 +#define EKEYREJECTED 129 +#define EOWNERDEAD 130 +#define ENOTRECOVERABLE 131 +#define ERFKILL 132 +#define EHWPOISON 133 +#define ENOTSUP EOPNOTSUPP + +__BEGIN_DECLS + +#ifndef errno +int * _TLIBC_CDECL_ __errno(void); +#define errno (*__errno()) +#endif /* errno */ +__END_DECLS + +#endif /* _ERRNO_H_ */ diff --git a/sgx-jvm/linux-sgx/common/inc/tlibc/float.h b/sgx-jvm/linux-sgx/common/inc/tlibc/float.h new file mode 100644 index 0000000000..99ae58de83 --- /dev/null +++ b/sgx-jvm/linux-sgx/common/inc/tlibc/float.h @@ -0,0 +1,84 @@ +/* $OpenBSD: float.h,v 1.3 2008/07/21 20:50:54 martynas Exp $ */ +/* $NetBSD: float.h,v 1.8 1995/06/20 20:45:37 jtc Exp $ */ + +/* + * Copyright (c) 1989 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)float.h 7.1 (Berkeley) 5/8/90 + */ + +#ifndef _FLOAT_H_ +#define _FLOAT_H_ + +#include + +#define FLT_RADIX 2 /* b */ + +// The rounding direction can be specified by fesetround() in +#define FLT_ROUNDS 1 /* addition rounding: near */ +#define DECIMAL_DIG 21 /* max precision in decimal digits */ + +// NOTE: FLT_EVAL_METHOD is -1 under FREEBSD x86. +#ifdef __i386__ +#define FLT_EVAL_METHOD 2 /* long double */ +#else +#define FLT_EVAL_METHOD 0 /* no promotions */ +#endif + +#define DBL_MANT_DIG 53 +#define DBL_EPSILON 2.2204460492503131E-16 +#define DBL_DIG 15 +#define DBL_MIN_EXP (-1021) +#define DBL_MIN 2.2250738585072014E-308 +#define DBL_MIN_10_EXP (-307) +#define DBL_MAX_EXP 1024 +#define DBL_MAX_10_EXP 308 + +#define FLT_MANT_DIG 24 /* p */ +#define FLT_DIG 6 /* floor((p-1)*log10(b))+(b == 10) */ +#define FLT_MIN_EXP (-125) /* emin */ +#define FLT_MIN_10_EXP (-37) /* ceil(log10(b**(emin-1))) */ +#define FLT_MAX_EXP 128 /* emax */ +#define FLT_MAX_10_EXP 38 /* floor(log10((1-b**(-p))*b**emax)) */ + +#define DBL_MAX 1.7976931348623157E+308 +#define FLT_EPSILON 1.19209290E-07F /* b**(1-p) */ +#define FLT_MIN 1.17549435E-38F /* b**(emin-1) */ +#define FLT_MAX 3.40282347E+38F /* (1-b**(-p))*b**emax */ + +#define LDBL_MANT_DIG 64 +#define LDBL_EPSILON 1.08420217248550443401e-19L +#define LDBL_DIG 18 +#define LDBL_MIN_EXP (-16381) +#define LDBL_MIN 3.36210314311209350626e-4932L +#define LDBL_MIN_10_EXP (-4931) +#define LDBL_MAX_EXP 16384 +#define LDBL_MAX 1.18973149535723176502e+4932L +#define LDBL_MAX_10_EXP 4932 + +#endif /* _FLOAT_H_ */ diff --git a/sgx-jvm/linux-sgx/common/inc/tlibc/inttypes.h b/sgx-jvm/linux-sgx/common/inc/tlibc/inttypes.h new file mode 100644 index 0000000000..c4fbcafc32 --- /dev/null +++ b/sgx-jvm/linux-sgx/common/inc/tlibc/inttypes.h @@ -0,0 +1,330 @@ +/* $OpenBSD: inttypes.h,v 1.10 2009/01/13 18:13:51 kettenis Exp $ */ + +/* + * Copyright (c) 1997, 2005 Todd C. Miller + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _INTTYPES_H_ +#define _INTTYPES_H_ + +#include + +/* + * 7.8.1 Macros for format specifiers + * + * Each of the following object-like macros expands to a string + * literal containing a conversion specifier, possibly modified by + * a prefix such as hh, h, l, or ll, suitable for use within the + * format argument of a formatted input/output function when + * converting the corresponding integer type. These macro names + * have the general form of PRI (character string literals for the + * fprintf family) or SCN (character string literals for the fscanf + * family), followed by the conversion specifier, followed by a + * name corresponding to a similar typedef name. For example, + * PRIdFAST32 can be used in a format string to print the value of + * an integer of type int_fast32_t. + */ + +/* fprintf macros for signed integers */ +#define PRId8 "d" /* int8_t */ +#define PRId16 "d" /* int16_t */ +#define PRId32 "d" /* int32_t */ +#ifdef __x86_64__ +#define PRId64 "ld" /* int64_t */ +#else +#define PRId64 "lld" /* int64_t */ +#endif + +#define PRIdLEAST8 "d" /* int_least8_t */ +#define PRIdLEAST16 "d" /* int_least16_t */ +#define PRIdLEAST32 "d" /* int_least32_t */ +#ifdef __x86_64__ +#define PRIdLEAST64 "ld" /* int_least64_t */ +#else +#define PRIdLEAST64 "lld" /* int_least64_t */ +#endif + +#define PRIdFAST8 "d" /* int_fast8_t */ +#ifdef __x86_64__ +#define PRIdFAST16 "ld" /* int_fast16_t */ +#define PRIdFAST32 "ld" /* int_fast32_t */ +#define PRIdFAST64 "ld" /* int_fast64_t */ +#else +#define PRIdFAST16 "d" /* int_fast16_t */ +#define PRIdFAST32 "d" /* int_fast32_t */ +#define PRIdFAST64 "lld" /* int_fast64_t */ +#endif + +#ifdef __x86_64__ +#define PRIdMAX "ld" /* intmax_t */ +#else +#if defined(__i386__) +#define PRIdMAX "lld" /* intmax_t */ +#else +#define PRIdMAX "jd" /* intmax_t */ +#endif +#endif + +#ifdef __i386__ +#define PRIdPTR "d" /* intptr_t */ +#else +#define PRIdPTR "ld" /* intptr_t */ +#endif + +#define PRIi8 "i" /* int8_t */ +#define PRIi16 "i" /* int16_t */ +#define PRIi32 "i" /* int32_t */ +#ifdef __x86_64__ +#define PRIi64 "li" /* int64_t */ +#else +#define PRIi64 "lli" /* int64_t */ +#endif + +#define PRIiLEAST8 "i" /* int_least8_t */ +#define PRIiLEAST16 "i" /* int_least16_t */ +#define PRIiLEAST32 "i" /* int_least32_t */ +#ifdef __x86_64__ +#define PRIiLEAST64 "li" /* int_least64_t */ +#else +#define PRIiLEAST64 "lli" /* int_least64_t */ +#endif + +#define PRIiFAST8 "i" /* int_fast8_t */ +#ifdef __x86_64__ +#define PRIiFAST16 "li" /* int_fast16_t */ +#define PRIiFAST32 "li" /* int_fast32_t */ +#define PRIiFAST64 "li" /* int_fast64_t */ +#else +#define PRIiFAST16 "i" /* int_fast16_t */ +#define PRIiFAST32 "i" /* int_fast32_t */ +#define PRIiFAST64 "lli" /* int_fast64_t */ +#endif + +#ifdef __x86_64__ +#define PRIiMAX "li" /* intmax_t */ +#else +#if defined(__i386__) +#define PRIiMAX "lli" /* intmax_t */ +#else +#define PRIiMAX "ji" /* intmax_t */ +#endif +#endif + +#ifdef __i386__ +#define PRIiPTR "i" /* intptr_t */ +#else +#define PRIiPTR "li" /* intptr_t */ +#endif + +/* fprintf macros for unsigned integers */ +#define PRIo8 "o" /* int8_t */ +#define PRIo16 "o" /* int16_t */ +#define PRIo32 "o" /* int32_t */ +#ifdef __x86_64__ +#define PRIo64 "lo" /* int64_t */ +#else +#define PRIo64 "llo" /* int64_t */ +#endif + +#define PRIoLEAST8 "o" /* int_least8_t */ +#define PRIoLEAST16 "o" /* int_least16_t */ +#define PRIoLEAST32 "o" /* int_least32_t */ +#ifdef __x86_64__ +#define PRIoLEAST64 "lo" /* int_least64_t */ +#else +#define PRIoLEAST64 "llo" /* int_least64_t */ +#endif + +#define PRIoFAST8 "o" /* int_fast8_t */ +#ifdef __x86_64__ +#define PRIoFAST16 "lo" /* int_fast16_t */ +#define PRIoFAST32 "lo" /* int_fast32_t */ +#define PRIoFAST64 "lo" /* int_fast64_t */ +#else +#define PRIoFAST16 "o" /* int_fast16_t */ +#define PRIoFAST32 "o" /* int_fast32_t */ +#define PRIoFAST64 "llo" /* int_fast64_t */ +#endif + +#ifdef __x86_64__ +#define PRIoMAX "lo" /* intmax_t */ +#else +#if defined(__i386__) +#define PRIoMAX "llo" /* intmax_t */ +#else +#define PRIoMAX "jo" /* intmax_t */ +#endif +#endif + +#ifdef __i386__ +#define PRIoPTR "o" /* intptr_t */ +#else +#define PRIoPTR "lo" /* intptr_t */ +#endif + +#define PRIu8 "u" /* uint8_t */ +#define PRIu16 "u" /* uint16_t */ +#define PRIu32 "u" /* uint32_t */ + +#ifdef __x86_64__ +#define PRIu64 "lu" /* uint64_t */ +#else +#define PRIu64 "llu" /* uint64_t */ +#endif + +#define PRIuLEAST8 "u" /* uint_least8_t */ +#define PRIuLEAST16 "u" /* uint_least16_t */ +#define PRIuLEAST32 "u" /* uint_least32_t */ + +#ifdef __x86_64__ +#define PRIuLEAST64 "lu" /* uint_least64_t */ +#else +#define PRIuLEAST64 "llu" /* uint_least64_t */ +#endif + +#define PRIuFAST8 "u" /* uint_fast8_t */ + +#ifdef __x86_64__ +#define PRIuFAST16 "lu" /* uint_fast16_t */ +#define PRIuFAST32 "lu" /* uint_fast32_t */ +#define PRIuFAST64 "lu" /* uint_fast64_t */ +#else +#define PRIuFAST16 "u" /* uint_fast16_t */ +#define PRIuFAST32 "u" /* uint_fast32_t */ +#define PRIuFAST64 "llu" /* uint_fast64_t */ +#endif + +#ifdef __x86_64__ +#define PRIuMAX "lu" /* uintmax_t */ +#else +#if defined(__i386__) +#define PRIuMAX "llu" /* uintmax_t */ +#else +#define PRIuMAX "ju" /* uintmax_t */ +#endif +#endif + +#ifdef __i386__ +#define PRIuPTR "u" /* uintptr_t */ +#else +#define PRIuPTR "lu" /* uintptr_t */ +#endif + +#define PRIx8 "x" /* uint8_t */ +#define PRIx16 "x" /* uint16_t */ +#define PRIx32 "x" /* uint32_t */ +#ifdef __x86_64__ +#define PRIx64 "lx" /* uint64_t */ +#else +#define PRIx64 "llx" /* uint64_t */ +#endif + +#define PRIxLEAST8 "x" /* uint_least8_t */ +#define PRIxLEAST16 "x" /* uint_least16_t */ +#define PRIxLEAST32 "x" /* uint_least32_t */ +#ifdef __x86_64__ +#define PRIxLEAST64 "lx" /* uint_least64_t */ +#else +#define PRIxLEAST64 "llx" /* uint_least64_t */ +#endif + +#define PRIxFAST8 "x" /* uint_fast8_t */ +#ifdef __x86_64__ +#define PRIxFAST16 "lx" /* uint_fast16_t */ +#define PRIxFAST32 "lx" /* uint_fast32_t */ +#define PRIxFAST64 "lx" /* uint_fast64_t */ +#else +#define PRIxFAST16 "x" /* uint_fast16_t */ +#define PRIxFAST32 "x" /* uint_fast32_t */ +#define PRIxFAST64 "llx" /* uint_fast64_t */ +#endif + +#ifdef __x86_64__ +#define PRIxMAX "lx" /* uintmax_t */ +#else +#if defined(__i386__) +#define PRIxMAX "llx" /* uintmax_t */ +#else +#define PRIxMAX "jx" /* uintmax_t */ +#endif +#endif + +#ifdef __i386__ +#define PRIxPTR "x" /* uintptr_t */ +#else +#define PRIxPTR "lx" /* uintptr_t */ +#endif + +#define PRIX8 "X" /* uint8_t */ +#define PRIX16 "X" /* uint16_t */ +#define PRIX32 "X" /* uint32_t */ + +#ifdef __x86_64__ +#define PRIX64 "lX" /* uint64_t */ +#else +#define PRIX64 "llX" /* uint64_t */ +#endif + +#define PRIXLEAST8 "X" /* uint_least8_t */ +#define PRIXLEAST16 "X" /* uint_least16_t */ +#define PRIXLEAST32 "X" /* uint_least32_t */ +#ifdef __x86_64__ +#define PRIXLEAST64 "lX" /* uint_least64_t */ +#else +#define PRIXLEAST64 "llX" /* uint_least64_t */ +#endif + +#define PRIXFAST8 "X" /* uint_fast8_t */ +#ifdef __x86_64__ +#define PRIXFAST16 "lX" /* uint_fast16_t */ +#define PRIXFAST32 "lX" /* uint_fast32_t */ +#define PRIXFAST64 "lX" /* uint_fast64_t */ +#else +#define PRIXFAST16 "X" /* uint_fast16_t */ +#define PRIXFAST32 "X" /* uint_fast32_t */ +#define PRIXFAST64 "llX" /* uint_fast64_t */ +#endif + +#ifdef __x86_64__ +#define PRIXMAX "lX" /* uintmax_t */ +#else +#if defined(__i386__) +#define PRIXMAX "llX" /* uintmax_t */ +#else +#define PRIXMAX "jX" /* uintmax_t */ +#endif +#endif + +#ifdef __i386__ +#define PRIXPTR "X" /* uintptr_t */ +#else +#define PRIXPTR "lX" /* uintptr_t */ +#endif + +typedef struct { + intmax_t quot; /* quotient */ + intmax_t rem; /* remainder */ +} imaxdiv_t; + +__BEGIN_DECLS + +intmax_t _TLIBC_CDECL_ imaxabs(intmax_t); +imaxdiv_t _TLIBC_CDECL_ imaxdiv(intmax_t, intmax_t); +intmax_t _TLIBC_CDECL_ strtoimax(const char *, char **, int); +uintmax_t _TLIBC_CDECL_ strtoumax(const char *, char **, int); + +__END_DECLS + +#endif /* _INTTYPES_H_ */ diff --git a/sgx-jvm/linux-sgx/common/inc/tlibc/iso646.h b/sgx-jvm/linux-sgx/common/inc/tlibc/iso646.h new file mode 100644 index 0000000000..d711cace6d --- /dev/null +++ b/sgx-jvm/linux-sgx/common/inc/tlibc/iso646.h @@ -0,0 +1,26 @@ +/* $OpenBSD: iso646.h,v 1.3 2001/10/11 00:05:21 espie Exp $ */ +/* $NetBSD: iso646.h,v 1.1 1995/02/17 09:08:10 jtc Exp $ */ + +/* + * Written by J.T. Conklin 02/16/95. + * Public domain. + */ + +#ifndef _ISO646_H_ +#define _ISO646_H_ + +#ifndef __cplusplus +#define and && +#define and_eq &= +#define bitand & +#define bitor | +#define compl ~ +#define not ! +#define not_eq != +#define or || +#define or_eq |= +#define xor ^ +#define xor_eq ^= +#endif + +#endif /* !_ISO646_H_ */ diff --git a/sgx-jvm/linux-sgx/common/inc/tlibc/limits.h b/sgx-jvm/linux-sgx/common/inc/tlibc/limits.h new file mode 100644 index 0000000000..fab59c9b8e --- /dev/null +++ b/sgx-jvm/linux-sgx/common/inc/tlibc/limits.h @@ -0,0 +1,41 @@ +/* $OpenBSD: limits.h,v 1.15 2008/02/10 09:59:54 kettenis Exp $ */ +/* $NetBSD: limits.h,v 1.7 1994/10/26 00:56:00 cgd Exp $ */ + +/* + * Copyright (c) 1988 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)limits.h 5.9 (Berkeley) 4/3/91 + */ + + +#ifndef _LIMITS_H_ +#define _LIMITS_H_ + +#include + +#endif /* !_LIMITS_H_ */ diff --git a/sgx-jvm/linux-sgx/common/inc/tlibc/math.h b/sgx-jvm/linux-sgx/common/inc/tlibc/math.h new file mode 100644 index 0000000000..104ac7f156 --- /dev/null +++ b/sgx-jvm/linux-sgx/common/inc/tlibc/math.h @@ -0,0 +1,430 @@ +/* $OpenBSD: math.h,v 1.27 2010/12/14 11:16:15 martynas Exp $ */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +/* + * from: @(#)fdlibm.h 5.1 93/09/24 + */ + +#ifndef _MATH_H_ +#define _MATH_H_ + +#include +#include +#include + +#include + +typedef __float_t float_t; +typedef __double_t double_t; + +#define FP_NAN 0x00 +#define FP_INFINITE 0x01 +#define FP_ZERO 0x02 +#define FP_SUBNORMAL 0x03 +#define FP_NORMAL 0x04 + +#define FP_ILOGB0 (-INT_MAX - 1) +#define FP_ILOGBNAN (-INT_MAX - 1) + +#define fpclassify(x) \ + ((sizeof (x) == sizeof (float)) ? \ + __fpclassifyf(x) \ + : (sizeof (x) == sizeof (double)) ? \ + __fpclassify(x) \ + : __fpclassifyl(x)) +#define isfinite(x) \ + ((sizeof (x) == sizeof (float)) ? \ + __isfinitef(x) \ + : (sizeof (x) == sizeof (double)) ? \ + __isfinite(x) \ + : __isfinitel(x)) +#define isnormal(x) \ + ((sizeof (x) == sizeof (float)) ? \ + __isnormalf(x) \ + : (sizeof (x) == sizeof (double)) ? \ + __isnormal(x) \ + : __isnormall(x)) +#define signbit(x) \ + ((sizeof (x) == sizeof (float)) ? \ + __signbitf(x) \ + : (sizeof (x) == sizeof (double)) ? \ + __signbit(x) \ + : __signbitl(x)) +#define isinf(x) \ + ((sizeof (x) == sizeof (float)) ? \ + __isinff(x) \ + : (sizeof (x) == sizeof (double)) ? \ + __isinf(x) \ + : __isinfl(x)) +#define isnan(x) \ + ((sizeof (x) == sizeof (float)) ? \ + __isnanf(x) \ + : (sizeof (x) == sizeof (double)) ? \ + __isnan(x) \ + : __isnanl(x)) + +#define isgreater(x, y) (!isunordered((x), (y)) && (x) > (y)) +#define isgreaterequal(x, y) (!isunordered((x), (y)) && (x) >= (y)) +#define isless(x, y) (!isunordered((x), (y)) && (x) < (y)) +#define islessequal(x, y) (!isunordered((x), (y)) && (x) <= (y)) +#define islessgreater(x, y) (!isunordered((x), (y)) && ((x) > (y) || (y) > (x))) +#define isunordered(x, y) (isnan(x) || isnan(y)) + +__BEGIN_DECLS + +extern char __infinity[]; +#define HUGE_VAL (*(double *)(void *)__infinity) +#define HUGE_VALF ((float)HUGE_VAL) +#define HUGE_VALL ((long double)HUGE_VAL) +#define INFINITY HUGE_VALF +extern char __nan[]; +#define NAN (*(float *)(void *)__nan) + +/* + * ANSI/POSIX + */ +double _TLIBC_CDECL_ acos(double); +double _TLIBC_CDECL_ asin(double); +double _TLIBC_CDECL_ atan(double); +double _TLIBC_CDECL_ atan2(double, double); +double _TLIBC_CDECL_ cos(double); +double _TLIBC_CDECL_ sin(double); +double _TLIBC_CDECL_ tan(double); + +double _TLIBC_CDECL_ cosh(double); +double _TLIBC_CDECL_ sinh(double); +double _TLIBC_CDECL_ tanh(double); + +double _TLIBC_CDECL_ exp(double); +double _TLIBC_CDECL_ frexp(double, int *); +double _TLIBC_CDECL_ ldexp(double, int); +double _TLIBC_CDECL_ log(double); +double _TLIBC_CDECL_ log10(double); +double _TLIBC_CDECL_ modf(double, double *); + +double _TLIBC_CDECL_ pow(double, double); +double _TLIBC_CDECL_ sqrt(double); + +double _TLIBC_CDECL_ ceil(double); +double _TLIBC_CDECL_ fabs(double); +double _TLIBC_CDECL_ floor(double); +double _TLIBC_CDECL_ fmod(double, double); + +/* + * C99 + */ +double _TLIBC_CDECL_ acosh(double); +double _TLIBC_CDECL_ asinh(double); +double _TLIBC_CDECL_ atanh(double); + +double _TLIBC_CDECL_ exp2(double); +double _TLIBC_CDECL_ expm1(double); +int _TLIBC_CDECL_ ilogb(double); +double _TLIBC_CDECL_ log1p(double); +double _TLIBC_CDECL_ log2(double); +double _TLIBC_CDECL_ logb(double); +double _TLIBC_CDECL_ scalbn(double, int); +double _TLIBC_CDECL_ scalbln(double, long int); + +double _TLIBC_CDECL_ cbrt(double); +double _TLIBC_CDECL_ hypot(double, double); + +double _TLIBC_CDECL_ erf(double); +double _TLIBC_CDECL_ erfc(double); +double _TLIBC_CDECL_ lgamma(double); +double _TLIBC_CDECL_ tgamma(double); + +double _TLIBC_CDECL_ nearbyint(double); +double _TLIBC_CDECL_ rint(double); +long int _TLIBC_CDECL_ lrint(double); +long long int _TLIBC_CDECL_ llrint(double); +double _TLIBC_CDECL_ round(double); +long int _TLIBC_CDECL_ lround(double); +long long int _TLIBC_CDECL_ llround(double); +double _TLIBC_CDECL_ trunc(double); + +double _TLIBC_CDECL_ remainder(double, double); +double _TLIBC_CDECL_ remquo(double, double, int *); + +double _TLIBC_CDECL_ copysign(double, double); +double _TLIBC_CDECL_ nan(const char *); +double _TLIBC_CDECL_ nextafter(double, double); + +double _TLIBC_CDECL_ fdim(double, double); +double _TLIBC_CDECL_ fmax(double, double); +double _TLIBC_CDECL_ fmin(double, double); + +double _TLIBC_CDECL_ fma(double, double, double); + +/* + * Float versions of C99 functions + */ + +float _TLIBC_CDECL_ acosf(float); +float _TLIBC_CDECL_ asinf(float); +float _TLIBC_CDECL_ atanf(float); +float _TLIBC_CDECL_ atan2f(float, float); +float _TLIBC_CDECL_ cosf(float); +float _TLIBC_CDECL_ sinf(float); +float _TLIBC_CDECL_ tanf(float); + +float _TLIBC_CDECL_ acoshf(float); +float _TLIBC_CDECL_ asinhf(float); +float _TLIBC_CDECL_ atanhf(float); +float _TLIBC_CDECL_ coshf(float); +float _TLIBC_CDECL_ sinhf(float); +float _TLIBC_CDECL_ tanhf(float); + +float _TLIBC_CDECL_ expf(float); +float _TLIBC_CDECL_ exp2f(float); +float _TLIBC_CDECL_ expm1f(float); +float _TLIBC_CDECL_ frexpf(float, int *); +int _TLIBC_CDECL_ ilogbf(float); +float _TLIBC_CDECL_ ldexpf(float, int); +float _TLIBC_CDECL_ logf(float); +float _TLIBC_CDECL_ log10f(float); +float _TLIBC_CDECL_ log1pf(float); +float _TLIBC_CDECL_ log2f(float); +float _TLIBC_CDECL_ logbf(float); +float _TLIBC_CDECL_ modff(float, float *); +float _TLIBC_CDECL_ scalbnf(float, int); +float _TLIBC_CDECL_ scalblnf(float, long int); + +float _TLIBC_CDECL_ cbrtf(float); +float _TLIBC_CDECL_ fabsf(float); +float _TLIBC_CDECL_ hypotf(float, float); +float _TLIBC_CDECL_ powf(float, float); +float _TLIBC_CDECL_ sqrtf(float); + +float _TLIBC_CDECL_ erff(float); +float _TLIBC_CDECL_ erfcf(float); +float _TLIBC_CDECL_ lgammaf(float); +float _TLIBC_CDECL_ tgammaf(float); + +float _TLIBC_CDECL_ ceilf(float); +float _TLIBC_CDECL_ floorf(float); +float _TLIBC_CDECL_ nearbyintf(float); + +float _TLIBC_CDECL_ rintf(float); +long int _TLIBC_CDECL_ lrintf(float); +long long int _TLIBC_CDECL_ llrintf(float); +float _TLIBC_CDECL_ roundf(float); +long int _TLIBC_CDECL_ lroundf(float); +long long int _TLIBC_CDECL_ llroundf(float); +float _TLIBC_CDECL_ truncf(float); + +float _TLIBC_CDECL_ fmodf(float, float); +float _TLIBC_CDECL_ remainderf(float, float); +float _TLIBC_CDECL_ remquof(float, float, int *); + +float _TLIBC_CDECL_ copysignf(float, float); +float _TLIBC_CDECL_ nanf(const char *); +float _TLIBC_CDECL_ nextafterf(float, float); + +float _TLIBC_CDECL_ fdimf(float, float); +float _TLIBC_CDECL_ fmaxf(float, float); +float _TLIBC_CDECL_ fminf(float, float); + +float _TLIBC_CDECL_ fmaf(float, float, float); + +/* + * Long double versions of C99 functions + */ + +/* Macros defining long double functions to be their double counterparts + * (long double is synonymous with double in this implementation). + */ + +long double _TLIBC_CDECL_ acosl(long double); +long double _TLIBC_CDECL_ asinl(long double); +long double _TLIBC_CDECL_ atanl(long double); +long double _TLIBC_CDECL_ atan2l(long double, long double); +long double _TLIBC_CDECL_ cosl(long double); +long double _TLIBC_CDECL_ sinl(long double); +long double _TLIBC_CDECL_ tanl(long double); + +long double _TLIBC_CDECL_ acoshl(long double); +long double _TLIBC_CDECL_ asinhl(long double); +long double _TLIBC_CDECL_ atanhl(long double); +long double _TLIBC_CDECL_ coshl(long double); +long double _TLIBC_CDECL_ sinhl(long double); +long double _TLIBC_CDECL_ tanhl(long double); + +long double _TLIBC_CDECL_ expl(long double); +long double _TLIBC_CDECL_ exp2l(long double); +long double _TLIBC_CDECL_ expm1l(long double); +long double _TLIBC_CDECL_ frexpl(long double, int *); +int _TLIBC_CDECL_ ilogbl(long double); +long double _TLIBC_CDECL_ ldexpl(long double, int); +long double _TLIBC_CDECL_ logl(long double); +long double _TLIBC_CDECL_ log10l(long double); +long double _TLIBC_CDECL_ log1pl(long double); +long double _TLIBC_CDECL_ log2l(long double); +long double _TLIBC_CDECL_ logbl(long double); +long double _TLIBC_CDECL_ modfl(long double, long double *); +long double _TLIBC_CDECL_ scalbnl(long double, int); +long double _TLIBC_CDECL_ scalblnl(long double, long int); + +long double _TLIBC_CDECL_ cbrtl(long double); +long double _TLIBC_CDECL_ fabsl(long double); +long double _TLIBC_CDECL_ hypotl(long double, long double); +long double _TLIBC_CDECL_ powl(long double, long double); +long double _TLIBC_CDECL_ sqrtl(long double); + +long double _TLIBC_CDECL_ erfl(long double); +long double _TLIBC_CDECL_ erfcl(long double); +long double _TLIBC_CDECL_ lgammal(long double); +long double _TLIBC_CDECL_ tgammal(long double); + +long double _TLIBC_CDECL_ ceill(long double); +long double _TLIBC_CDECL_ floorl(long double); +long double _TLIBC_CDECL_ nearbyintl(long double); +long double _TLIBC_CDECL_ rintl(long double); +long int _TLIBC_CDECL_ lrintl(long double); +long long int _TLIBC_CDECL_ llrintl(long double); +long double _TLIBC_CDECL_ roundl(long double); +long int _TLIBC_CDECL_ lroundl(long double); +long long int _TLIBC_CDECL_ llroundl(long double); +long double _TLIBC_CDECL_ truncl(long double); + +long double _TLIBC_CDECL_ fmodl(long double, long double); +long double _TLIBC_CDECL_ remainderl(long double, long double); +long double _TLIBC_CDECL_ remquol(long double, long double, int *); + +long double _TLIBC_CDECL_ copysignl(long double, long double); +long double _TLIBC_CDECL_ nanl(const char *); +long double _TLIBC_CDECL_ nextafterl(long double, long double); + +long double _TLIBC_CDECL_ fdiml(long double, long double); +long double _TLIBC_CDECL_ fmaxl(long double, long double); +long double _TLIBC_CDECL_ fminl(long double, long double); +long double _TLIBC_CDECL_ fmal(long double, long double, long double); + +/* nexttoward(): +* The implementation in Intel math library is incompatible with MSVC. +* Because sizeof(long double) is 8bytes with MSVC, +* but the expected long double size is 10bytes. +* And by default, MSVC doesn't provide nexttoward(). +* So we only provide Linux version here. +*/ +double _TLIBC_CDECL_ nexttoward(double, long double); +float _TLIBC_CDECL_ nexttowardf(float, long double); + +long double _TLIBC_CDECL_ nexttowardl(long double, long double); + +/* + * Library implementation + */ +int _TLIBC_CDECL_ __fpclassify(double); +int _TLIBC_CDECL_ __fpclassifyf(float); +int _TLIBC_CDECL_ __isfinite(double); +int _TLIBC_CDECL_ __isfinitef(float); +int _TLIBC_CDECL_ __isinf(double); +int _TLIBC_CDECL_ __isinff(float); +int _TLIBC_CDECL_ __isnan(double); +int _TLIBC_CDECL_ __isnanf(float); +int _TLIBC_CDECL_ __isnormal(double); +int _TLIBC_CDECL_ __isnormalf(float); +int _TLIBC_CDECL_ __signbit(double); +int _TLIBC_CDECL_ __signbitf(float); + +int _TLIBC_CDECL_ __fpclassifyl(long double); +int _TLIBC_CDECL_ __isfinitel(long double); +int _TLIBC_CDECL_ __isinfl(long double); +int _TLIBC_CDECL_ __isnanl(long double); +int _TLIBC_CDECL_ __isnormall(long double); +int _TLIBC_CDECL_ __signbitl(long double); + +/* + * Non-C99 functions. + */ +double _TLIBC_CDECL_ drem(double, double); +double _TLIBC_CDECL_ exp10(double); +double _TLIBC_CDECL_ gamma(double); +double _TLIBC_CDECL_ gamma_r(double, int *); +double _TLIBC_CDECL_ j0(double); +double _TLIBC_CDECL_ j1(double); +double _TLIBC_CDECL_ jn(int, double); +double _TLIBC_CDECL_ lgamma_r(double, int *); +double _TLIBC_CDECL_ pow10(double); +double _TLIBC_CDECL_ scalb(double, double); +/* C99 Macro signbit.*/ +double _TLIBC_CDECL_ significand(double); +void _TLIBC_CDECL_ sincos(double, double *, double *); +double _TLIBC_CDECL_ y0(double); +double _TLIBC_CDECL_ y1(double); +double _TLIBC_CDECL_ yn(int, double); +/* C99 Macro isinf.*/ +/* C99 Macro isnan.*/ +int _TLIBC_CDECL_ finite(double); + +float _TLIBC_CDECL_ dremf(float, float); +float _TLIBC_CDECL_ exp10f(float); +float _TLIBC_CDECL_ gammaf(float); +float _TLIBC_CDECL_ gammaf_r(float, int *); +float _TLIBC_CDECL_ j0f(float); +float _TLIBC_CDECL_ j1f(float); +float _TLIBC_CDECL_ jnf(int, float); +float _TLIBC_CDECL_ lgammaf_r(float, int *); +float _TLIBC_CDECL_ pow10f(float); +float _TLIBC_CDECL_ scalbf(float, float); +int _TLIBC_CDECL_ signbitf(float); +float _TLIBC_CDECL_ significandf(float); +void _TLIBC_CDECL_ sincosf(float, float *, float *); +float _TLIBC_CDECL_ y0f(float); +float _TLIBC_CDECL_ y1f(float); +float _TLIBC_CDECL_ ynf(int, float); +int _TLIBC_CDECL_ finitef(float); +int _TLIBC_CDECL_ isinff(float); +int _TLIBC_CDECL_ isnanf(float); + +long double _TLIBC_CDECL_ dreml(long double, long double); +long double _TLIBC_CDECL_ exp10l(long double); +long double _TLIBC_CDECL_ gammal(long double); +long double _TLIBC_CDECL_ gammal_r(long double, int *); +long double _TLIBC_CDECL_ j0l(long double); +long double _TLIBC_CDECL_ j1l(long double); +long double _TLIBC_CDECL_ jnl(int, long double); +long double _TLIBC_CDECL_ lgammal_r(long double, int *); +long double _TLIBC_CDECL_ pow10l(long double); +long double _TLIBC_CDECL_ scalbl(long double, long double); +int _TLIBC_CDECL_ signbitl(long double); +long double _TLIBC_CDECL_ significandl(long double); +void _TLIBC_CDECL_ sincosl(long double, long double *, long double *); +long double _TLIBC_CDECL_ y1l(long double); +long double _TLIBC_CDECL_ y0l(long double); +long double _TLIBC_CDECL_ ynl(int, long double); +int _TLIBC_CDECL_ finitel(long double); +int _TLIBC_CDECL_ isinfl(long double); +int _TLIBC_CDECL_ isnanl(long double); + +/* + * TODO: From Intel Decimal Floating-Point Math Library + * signbitd32/signbitd64/signbitd128, finited32/finited64/finited128 + * isinfd32/isinfd64/isinfd128, isnand32/isnand64/isnand128 + */ +#if defined(__cplusplus) +/* Clang does not support decimal floating point types. + * + * c.f.: + * http://clang.llvm.org/docs/UsersManual.html#gcc-extensions-not-implemented-yet + */ +#if !defined(__clang__) +typedef float _Decimal32 __attribute__((mode(SD))); +typedef float _Decimal64 __attribute__((mode(DD))); +typedef float _Decimal128 __attribute__((mode(TD))); +#endif +#endif + +__END_DECLS + +#endif /* !_MATH_H_ */ diff --git a/sgx-jvm/linux-sgx/common/inc/tlibc/setjmp.h b/sgx-jvm/linux-sgx/common/inc/tlibc/setjmp.h new file mode 100644 index 0000000000..ac5627f7ea --- /dev/null +++ b/sgx-jvm/linux-sgx/common/inc/tlibc/setjmp.h @@ -0,0 +1,64 @@ +/* $NetBSD: setjmp.h,v 1.26 2011/11/05 09:27:06 joerg Exp $ */ + +/*- + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * (c) UNIX System Laboratories, Inc. + * All or some portions of this file are derived from material licensed + * to the University of California by American Telephone and Telegraph + * Co. or Unix System Laboratories, Inc. and are reproduced herein with + * the permission of UNIX System Laboratories, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)setjmp.h 8.2 (Berkeley) 1/21/94 + */ + +#ifndef _SETJMP_H_ +#define _SETJMP_H_ + +#ifndef _JB_ATTRIBUTES +#define _JB_ATTRIBUTES /**/ +#else +#endif +#ifndef _BSD_JBSLOT_T_ +#define _BSD_JBSLOT_T_ long +#endif + +#define _JBLEN 8 + +typedef _BSD_JBSLOT_T_ jmp_buf[_JBLEN] _JB_ATTRIBUTES; + +#include +#define __returns_twice __attribute__((__returns_twice__)) +#define __dead + +__BEGIN_DECLS +int _setjmp(jmp_buf) __returns_twice; +void _longjmp(jmp_buf, int) __dead; +__END_DECLS + +#endif /* !_SETJMP_H_ */ + diff --git a/sgx-jvm/linux-sgx/common/inc/tlibc/stdarg.h b/sgx-jvm/linux-sgx/common/inc/tlibc/stdarg.h new file mode 100644 index 0000000000..ed73e246a6 --- /dev/null +++ b/sgx-jvm/linux-sgx/common/inc/tlibc/stdarg.h @@ -0,0 +1,48 @@ +/* $OpenBSD: stdarg.h,v 1.14 2010/12/30 05:01:36 tedu Exp $ */ +/* $NetBSD: stdarg.h,v 1.12 1995/12/25 23:15:31 mycroft Exp $ */ + +/*- + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)stdarg.h 8.1 (Berkeley) 6/10/93 + */ + +#ifndef _STDARG_H_ +#define _STDARG_H_ + +#include +#include + +typedef __va_list va_list; + +#define va_start(ap, last) __builtin_va_start((ap), last) +#define va_end __builtin_va_end +#define va_arg __builtin_va_arg +#define va_copy(dst, src) __builtin_va_copy((dst),(src)) + +#endif /* !_STDARG_H_ */ diff --git a/sgx-jvm/linux-sgx/common/inc/tlibc/stdbool.h b/sgx-jvm/linux-sgx/common/inc/tlibc/stdbool.h new file mode 100644 index 0000000000..bd1837ec46 --- /dev/null +++ b/sgx-jvm/linux-sgx/common/inc/tlibc/stdbool.h @@ -0,0 +1,44 @@ +/* $OpenBSD: stdbool.h,v 1.5 2010/07/24 22:17:03 guenther Exp $ */ + +/* + * Written by Marc Espie, September 25, 1999 + * Public domain. + */ + +#ifndef _STDBOOL_H_ +#define _STDBOOL_H_ + +#ifndef __cplusplus + +#ifndef __GNUC__ +/* Support for _C99: type _Bool is already built-in. */ +/* `_Bool' type must promote to `int' or `unsigned int'. */ +typedef enum { + false = 0, + true = 1 +} _Bool; + +/* And those constants must also be available as macros. */ +# define false false +# define true true +#else /* __GNUC__ */ +# define false 0 +# define true 1 +#endif + +/* User visible type `bool' is provided as a macro which may be redefined */ +#define bool _Bool + +#else /* __cplusplus */ + +# define _Bool bool +# define bool bool +# define false false +# define true true + +#endif + +/* Inform that everything is fine */ +#define __bool_true_false_are_defined 1 + +#endif /* _STDBOOL_H_ */ diff --git a/sgx-jvm/linux-sgx/common/inc/tlibc/stddef.h b/sgx-jvm/linux-sgx/common/inc/tlibc/stddef.h new file mode 100644 index 0000000000..84509c5025 --- /dev/null +++ b/sgx-jvm/linux-sgx/common/inc/tlibc/stddef.h @@ -0,0 +1,70 @@ +/* $OpenBSD: stddef.h,v 1.10 2009/09/22 21:40:02 jsg Exp $ */ +/* $NetBSD: stddef.h,v 1.4 1994/10/26 00:56:26 cgd Exp $ */ + +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)stddef.h 5.5 (Berkeley) 4/3/91 + */ + +#ifndef _STDDEF_H_ +#define _STDDEF_H_ + +#include +#include + +#ifndef _PTRDIFF_T_DEFINED_ +#define _PTRDIFF_T_DEFINED_ +typedef __ptrdiff_t ptrdiff_t; +#endif + +#ifndef _SIZE_T_DEFINED_ +#define _SIZE_T_DEFINED_ +typedef __size_t size_t; +#endif + +#if !defined(_WCHAR_T_DEFINED_) && !defined(__cplusplus) +#define _WCHAR_T_DEFINED_ +#ifndef __WCHAR_TYPE__ +#define __WCHAR_TYPE__ int +#endif +typedef __WCHAR_TYPE__ wchar_t; +#endif + +#ifndef NULL +#ifdef __cplusplus +#define NULL 0 +#else +#define NULL ((void *)0) +#endif +#endif + +#define offsetof(type, member) ((size_t)(&((type *)0)->member)) + +#endif /* _STDDEF_H_ */ + diff --git a/sgx-jvm/linux-sgx/common/inc/tlibc/stdint.h b/sgx-jvm/linux-sgx/common/inc/tlibc/stdint.h new file mode 100644 index 0000000000..d283ae9214 --- /dev/null +++ b/sgx-jvm/linux-sgx/common/inc/tlibc/stdint.h @@ -0,0 +1,24 @@ +/* $OpenBSD: stdint.h,v 1.4 2006/12/10 22:17:55 deraadt Exp $ */ + +/* + * Copyright (c) 1997, 2005 Todd C. Miller + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _STDINT_H_ +#define _STDINT_H_ + +#include + +#endif /* _STDINT_H_ */ diff --git a/sgx-jvm/linux-sgx/common/inc/tlibc/stdio.h b/sgx-jvm/linux-sgx/common/inc/tlibc/stdio.h new file mode 100644 index 0000000000..0175a3ace3 --- /dev/null +++ b/sgx-jvm/linux-sgx/common/inc/tlibc/stdio.h @@ -0,0 +1,95 @@ +/* $OpenBSD: stdio.h,v 1.38 2009/11/09 00:18:27 kurt Exp $ */ +/* $NetBSD: stdio.h,v 1.18 1996/04/25 18:29:21 jtc Exp $ */ + +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)stdio.h 5.17 (Berkeley) 6/3/91 + */ + +#ifndef _STDIO_H_ +#define _STDIO_H_ + +#include +#include + +#include + +#ifndef _SIZE_T_DEFINED_ +typedef __size_t size_t; +#define _SIZE_T_DEFINED_ +#endif + +#ifndef NULL +# ifdef __cplusplus +# define NULL 0 +# else +# define NULL ((void *)0) +# endif +#endif + +# define BUFSIZ 8192 + +#define EOF (-1) + +__BEGIN_DECLS + +int _TLIBC_CDECL_ snprintf(char *, size_t, const char *, ...) _GCC_PRINTF_FORMAT_(3, 4); +int _TLIBC_CDECL_ vsnprintf(char *, size_t, const char *, __va_list) _GCC_PRINTF_FORMAT_(3, 0); + +/* + * Deprecated definitions. + */ +#if 0 /* No FILE */ +_TLIBC_DEPRECATED_FUNCTION_(int _TLIBC_CDECL_, fprintf, FILE *, const char *, ...); +_TLIBC_DEPRECATED_FUNCTION_(int _TLIBC_CDECL_, putc, int, FILE *); +_TLIBC_DEPRECATED_FUNCTION_(int _TLIBC_CDECL_, fputc, int, FILE *); +_TLIBC_DEPRECATED_FUNCTION_(int _TLIBC_CDECL_, fputs, const char *, FILE *); +_TLIBC_DEPRECATED_FUNCTION_(int _TLIBC_CDECL_, fscanf, FILE *, const char *, ...); +_TLIBC_DEPRECATED_FUNCTION_(size_t _TLIBC_CDECL_, fwrite, const void *, size_t, size_t, FILE *); +_TLIBC_DEPRECATED_FUNCTION_(int _TLIBC_CDECL_, printf, const char *, ...); +_TLIBC_DEPRECATED_FUNCTION_(int _TLIBC_CDECL_, putchar, int); +_TLIBC_DEPRECATED_FUNCTION_(int _TLIBC_CDECL_, puts, const char *); +_TLIBC_DEPRECATED_FUNCTION_(int _TLIBC_CDECL_, scanf, const char *, ...); +_TLIBC_DEPRECATED_FUNCTION_(int _TLIBC_CDECL_, sprintf, char *, const char *, ...); +_TLIBC_DEPRECATED_FUNCTION_(int _TLIBC_CDECL_, sscanf, const char *, const char *, ...); +_TLIBC_DEPRECATED_FUNCTION_(int _TLIBC_CDECL_, vfprintf, FILE *, const char *, __va_list); +_TLIBC_DEPRECATED_FUNCTION_(int _TLIBC_CDECL_, vfscanf, FILE *, const char *, __va_list); +_TLIBC_DEPRECATED_FUNCTION_(int _TLIBC_CDECL_, vprintf, const char *, __va_list); +_TLIBC_DEPRECATED_FUNCTION_(int _TLIBC_CDECL_, vscanf, const char *, __va_list); +_TLIBC_DEPRECATED_FUNCTION_(int _TLIBC_CDECL_, vsprintf, char *, const char *, __va_list); +_TLIBC_DEPRECATED_FUNCTION_(int _TLIBC_CDECL_, vsscanf, const char *, const char *, __va_list); +#endif + +__END_DECLS + + +#endif /* !_STDIO_H_ */ diff --git a/sgx-jvm/linux-sgx/common/inc/tlibc/stdlib.h b/sgx-jvm/linux-sgx/common/inc/tlibc/stdlib.h new file mode 100644 index 0000000000..936042ec26 --- /dev/null +++ b/sgx-jvm/linux-sgx/common/inc/tlibc/stdlib.h @@ -0,0 +1,164 @@ +/* $OpenBSD: stdlib.h,v 1.47 2010/05/18 22:24:55 tedu Exp $ */ +/* $NetBSD: stdlib.h,v 1.25 1995/12/27 21:19:08 jtc Exp $ */ + +/*- +* Copyright (c) 1990 The Regents of the University of California. +* All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* 1. Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* 2. Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* 3. Neither the name of the University nor the names of its contributors +* may be used to endorse or promote products derived from this software +* without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +* SUCH DAMAGE. +* +* @(#)stdlib.h 5.13 (Berkeley) 6/4/91 +*/ + +#ifndef _STDLIB_H_ +#define _STDLIB_H_ + +#include +#include + +#ifndef _SIZE_T_DEFINED_ +#define _SIZE_T_DEFINED_ +typedef __size_t size_t; +#endif + +#ifdef _TLIBC_WIN_ +#if !defined(_WCHAR_T_DEFINED) && !defined (_NATIVE_WCHAR_T_DEFINED) +#define _WCHAR_T_DEFINED +typedef unsigned short wchar_t; +#endif +#else +#if !defined(_WCHAR_T_DEFINED_) && !defined(__cplusplus) +#define _WCHAR_T_DEFINED_ +#ifndef __WCHAR_TYPE__ +#define __WCHAR_TYPE__ int +#endif +typedef __WCHAR_TYPE__ wchar_t; +#endif +#endif + +#ifndef _DIV_T_DEFINED +typedef struct { + int quot; /* quotient */ + int rem; /* remainder */ +} div_t; + +typedef struct { + long quot; /* quotient */ + long rem; /* remainder */ +} ldiv_t; + +typedef struct { + long long quot; /* quotient */ + long long rem; /* remainder */ +} lldiv_t; +#define _DIV_T_DEFINED +#endif + +#ifndef NULL +#ifdef __cplusplus +#define NULL 0 +#else +#define NULL ((void *)0) +#endif +#endif + +#define EXIT_FAILURE 1 +#define EXIT_SUCCESS 0 + +#define RAND_MAX 0x7fffffff +#define MB_CUR_MAX 1 + +__BEGIN_DECLS + +_TLIBC_NORETURN_ void _TLIBC_CDECL_ abort(void); +int _TLIBC_CDECL_ abs(int); +double _TLIBC_CDECL_ atof(const char *); +int _TLIBC_CDECL_ atoi(const char *); +long _TLIBC_CDECL_ atol(const char *); +void * _TLIBC_CDECL_ bsearch(const void *, const void *, size_t, size_t, int (*)(const void *, const void *)); +div_t _TLIBC_CDECL_ div(int, int); +void * _TLIBC_CDECL_ calloc(size_t, size_t); +void _TLIBC_CDECL_ free(void *); +void * _TLIBC_CDECL_ malloc(size_t); +void * _TLIBC_CDECL_ memalign(size_t, size_t); +void * _TLIBC_CDECL_ realloc(void *, size_t); +void * _TLIBC_CDECL_ __tlibc_calloc(size_t, size_t); +void _TLIBC_CDECL_ __tlibc_free(void *); +void * _TLIBC_CDECL_ __tlibc_malloc(size_t); +void * _TLIBC_CDECL_ __tlibc_memalign(size_t, size_t); +void * _TLIBC_CDECL_ __tlibc_realloc(void *, size_t); +long _TLIBC_CDECL_ labs(long); +ldiv_t _TLIBC_CDECL_ ldiv(long, long); +void _TLIBC_CDECL_ qsort(void *, size_t, size_t, int (*)(const void *, const void *)); +double _TLIBC_CDECL_ strtod(const char *, char **); +long _TLIBC_CDECL_ strtol(const char *, char **, int); +float _TLIBC_CDECL_ strtof(const char *, char **); + +long long + _TLIBC_CDECL_ atoll(const char *); +long long + _TLIBC_CDECL_ llabs(long long); +lldiv_t + _TLIBC_CDECL_ lldiv(long long, long long); +long long + _TLIBC_CDECL_ strtoll(const char *, char **, int); +unsigned long + _TLIBC_CDECL_ strtoul(const char *, char **, int); +long double + _TLIBC_CDECL_ strtold(const char *, char **); +unsigned long long + _TLIBC_CDECL_ strtoull(const char *, char **, int); + +int _TLIBC_CDECL_ mblen(const char *, size_t); +size_t _TLIBC_CDECL_ mbstowcs(wchar_t *, const char *, size_t); +int _TLIBC_CDECL_ wctomb(char *, wchar_t); +int _TLIBC_CDECL_ mbtowc(wchar_t *, const char *, size_t); +size_t _TLIBC_CDECL_ wcstombs(char *, const wchar_t *, size_t); + + +/* + * Deprecated C99. + */ +_TLIBC_DEPRECATED_FUNCTION_(int _TLIBC_CDECL_, atexit, void (_TLIBC_CDECL_ *)(void)); +_TLIBC_DEPRECATED_FUNCTION_(int _TLIBC_CDECL_, rand, void); +_TLIBC_DEPRECATED_FUNCTION_(void _TLIBC_CDECL_, srand, unsigned); +_TLIBC_DEPRECATED_FUNCTION_(void _TLIBC_CDECL_, exit, int); +_TLIBC_DEPRECATED_FUNCTION_(void _TLIBC_CDECL_, _Exit, int); +_TLIBC_DEPRECATED_FUNCTION_(char * _TLIBC_CDECL_, getenv, const char *); +_TLIBC_DEPRECATED_FUNCTION_(int _TLIBC_CDECL_, system, const char *); + +/* + * Non-C99 Functions. + */ +void * _TLIBC_CDECL_ alloca(size_t); + +/* + * Deprecated Non-C99. + */ +//_TLIBC_DEPRECATED_FUNCTION_(void _TLIBC_CDECL_, _exit, int); + +__END_DECLS + +#endif /* !_STDLIB_H_ */ diff --git a/sgx-jvm/linux-sgx/common/inc/tlibc/string.h b/sgx-jvm/linux-sgx/common/inc/tlibc/string.h new file mode 100644 index 0000000000..c8e458f477 --- /dev/null +++ b/sgx-jvm/linux-sgx/common/inc/tlibc/string.h @@ -0,0 +1,125 @@ +/* $OpenBSD: string.h,v 1.20 2010/09/24 13:33:00 matthew Exp $ */ +/* $NetBSD: string.h,v 1.6 1994/10/26 00:56:30 cgd Exp $ */ + +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)string.h 5.10 (Berkeley) 3/9/91 + */ + +#ifndef _STRING_H_ +#define _STRING_H_ + +#include +#include + +#ifndef _SIZE_T_DEFINED_ +typedef __size_t size_t; +#define _SIZE_T_DEFINED_ +#endif + +#ifndef _ERRNO_T_DEFINED +#define _ERRNO_T_DEFINED +typedef int errno_t; +#endif + +#ifndef NULL +#ifdef __cplusplus +#define NULL 0 +#else +#define NULL ((void *)0) +#endif +#endif + +__BEGIN_DECLS + +void * _TLIBC_CDECL_ memchr(const void *, int, size_t); +int _TLIBC_CDECL_ memcmp(const void *, const void *, size_t); +void * _TLIBC_CDECL_ memcpy(void *, const void *, size_t); +void * _TLIBC_CDECL_ memmove(void *, const void *, size_t); +void * _TLIBC_CDECL_ memset(void *, int, size_t); +char * _TLIBC_CDECL_ strchr(const char *, int); +int _TLIBC_CDECL_ strcmp(const char *, const char *); +int _TLIBC_CDECL_ strcoll(const char *, const char *); +size_t _TLIBC_CDECL_ strcspn(const char *, const char *); +char * _TLIBC_CDECL_ strerror(int); +size_t _TLIBC_CDECL_ strlen(const char *); +char * _TLIBC_CDECL_ strncat(char *, const char *, size_t); +int _TLIBC_CDECL_ strncmp(const char *, const char *, size_t); +char * _TLIBC_CDECL_ strncpy(char *, const char *, size_t); +char * _TLIBC_CDECL_ strpbrk(const char *, const char *); +char * _TLIBC_CDECL_ strrchr(const char *, int); +size_t _TLIBC_CDECL_ strspn(const char *, const char *); +char * _TLIBC_CDECL_ strstr(const char *, const char *); +char * _TLIBC_CDECL_ strtok(char *, const char *); +size_t _TLIBC_CDECL_ strxfrm(char *, const char *, size_t); +size_t _TLIBC_CDECL_ strlcpy(char *, const char *, size_t); +errno_t _TLIBC_CDECL_ memset_s(void *s, size_t smax, int c, size_t n); + +/* + * Deprecated C99. + */ +_TLIBC_DEPRECATED_FUNCTION_(char * _TLIBC_CDECL_, strcat, char *, const char *); +_TLIBC_DEPRECATED_FUNCTION_(char * _TLIBC_CDECL_, strcpy, char *, const char *); + +/* + * Common used non-C99 functions. + */ +char * _TLIBC_CDECL_ strndup(const char *, size_t); +size_t _TLIBC_CDECL_ strnlen(const char *, size_t); +int _TLIBC_CDECL_ consttime_memequal(const void *b1, const void *b2, size_t len); + +/* + * Non-C99 + */ +int _TLIBC_CDECL_ bcmp(const void *, const void *, size_t); +void _TLIBC_CDECL_ bcopy(const void *, void *, size_t); +void _TLIBC_CDECL_ bzero(void *, size_t); +char * _TLIBC_CDECL_ index(const char *, int); +void * _TLIBC_CDECL_ mempcpy(void *, const void *, size_t); +char * _TLIBC_CDECL_ rindex(const char *, int); +char * _TLIBC_CDECL_ stpncpy(char *dest, const char *src, size_t n); +int _TLIBC_CDECL_ strcasecmp(const char *, const char *); +int _TLIBC_CDECL_ strncasecmp(const char *, const char *, size_t); + +int _TLIBC_CDECL_ ffs(int); +int _TLIBC_CDECL_ ffsl(long int); +int _TLIBC_CDECL_ ffsll(long long int); + +char * _TLIBC_CDECL_ strtok_r(char *, const char *, char **); +int _TLIBC_CDECL_ strerror_r(int, char *, size_t); + +/* + * Deprecated Non-C99. + */ +_TLIBC_DEPRECATED_FUNCTION_(char * _TLIBC_CDECL_, strdup, const char *); +_TLIBC_DEPRECATED_FUNCTION_(char * _TLIBC_CDECL_, stpcpy, char *dest, const char *src); + +__END_DECLS + +#endif /* _STRING_H_ */ diff --git a/sgx-jvm/linux-sgx/common/inc/tlibc/sys/_types.h b/sgx-jvm/linux-sgx/common/inc/tlibc/sys/_types.h new file mode 100644 index 0000000000..b1b315c7ed --- /dev/null +++ b/sgx-jvm/linux-sgx/common/inc/tlibc/sys/_types.h @@ -0,0 +1,133 @@ +/* $OpenBSD: _types.h,v 1.2 2008/03/16 19:42:57 otto Exp $ */ + +/*- + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)types.h 8.3 (Berkeley) 1/5/94 + */ + +#ifndef _SYS__TYPES_H_ +#define _SYS__TYPES_H_ + +#include +/* 7.18.1.1 Exact-width integer types */ +typedef signed char __int8_t; +typedef unsigned char __uint8_t; +typedef short __int16_t; +typedef unsigned short __uint16_t; +typedef int __int32_t; +typedef unsigned int __uint32_t; +typedef long long __int64_t; +typedef unsigned long long __uint64_t; + +/* 7.18.1.2 Minimum-width integer types */ +typedef __int8_t __int_least8_t; +typedef __uint8_t __uint_least8_t; +typedef __int16_t __int_least16_t; +typedef __uint16_t __uint_least16_t; +typedef __int32_t __int_least32_t; +typedef __uint32_t __uint_least32_t; +typedef __int64_t __int_least64_t; +typedef __uint64_t __uint_least64_t; + +/* 7.18.1.3 Fastest minimum-width integer types */ +typedef __int8_t __int_fast8_t; +typedef __uint8_t __uint_fast8_t; +#ifdef __x86_64__ +/* Linux x86_64, from stdint.h */ +typedef long int __int_fast16_t; +typedef unsigned long int __uint_fast16_t; +typedef long int __int_fast32_t; +typedef unsigned long int __uint_fast32_t; +typedef long int __int_fast64_t; +typedef unsigned long int __uint_fast64_t; +#else +/* Android x86, and Linux x86 */ +typedef __int32_t __int_fast16_t; +typedef __uint32_t __uint_fast16_t; +typedef __int32_t __int_fast32_t; +typedef __uint32_t __uint_fast32_t; +typedef __int64_t __int_fast64_t; +typedef __uint64_t __uint_fast64_t; +#endif + +typedef long __off_t; + +/* 7.18.1.4 Integer types capable of holding object pointers */ +#ifdef __i386__ +typedef __int32_t __intptr_t; +typedef __uint32_t __uintptr_t; +typedef __int32_t __ptrdiff_t; +/* Standard system types */ +typedef __uint32_t __size_t; +typedef __int32_t __ssize_t; +typedef long double __double_t; +typedef long double __float_t; +#else +typedef __int64_t __intptr_t; +typedef __uint64_t __uintptr_t; +typedef __int64_t __ptrdiff_t; + +/* Standard system types */ +typedef unsigned long __size_t; +typedef long __ssize_t; +typedef double __double_t; +typedef float __float_t; + +#endif /* !__i386__ */ + +typedef long __clock_t; + +typedef long __time_t; +typedef __builtin_va_list __va_list; +typedef int __wint_t; +/* wctype_t and wctrans_t are defined in wchar.h */ +typedef unsigned long int __wctype_t; +typedef int * __wctrans_t; + +/* + * mbstate_t is an opaque object to keep conversion state, during multibyte + * stream conversions. The content must not be referenced by user programs. + */ +/* For Linux, __mbstate_t is defined in wchar.h */ +typedef struct { + int __c; + union { + __wint_t __wc; + char __wcb[4]; + } __v; +} __mbstate_t; + +/* 7.18.1.5 Greatest-width integer types */ +typedef __int64_t __intmax_t; +typedef __uint64_t __uintmax_t; + +#endif /* !_SYS__TYPES_H_ */ + + + diff --git a/sgx-jvm/linux-sgx/common/inc/tlibc/sys/cdefs.h b/sgx-jvm/linux-sgx/common/inc/tlibc/sys/cdefs.h new file mode 100644 index 0000000000..398a12bbc7 --- /dev/null +++ b/sgx-jvm/linux-sgx/common/inc/tlibc/sys/cdefs.h @@ -0,0 +1,132 @@ +/* $OpenBSD: cdefs.h,v 1.34 2012/08/14 20:11:37 matthew Exp $ */ +/* $NetBSD: cdefs.h,v 1.16 1996/04/03 20:46:39 christos Exp $ */ + +/* + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Berkeley Software Design, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)cdefs.h 8.7 (Berkeley) 1/21/94 + */ + +#ifndef _SYS_CDEFS_H_ +#define _SYS_CDEFS_H_ + +/* Declaration field in C/C++ headers */ +#if defined(__cplusplus) +# define __BEGIN_DECLS extern "C" { +# define __END_DECLS } +#else +# define __BEGIN_DECLS +# define __END_DECLS +#endif + +#if defined(__STDC__) || defined(__cplusplus) +# define __CONCAT(x,y) x ## y +# define __STRING(x) #x +#else +# define __CONCAT(x,y) x/**/y +# define __STRING(x) "x" +#endif +/* + * Macro to test if we're using a specific version of gcc or later. + */ +#if defined __GNUC__ && defined __GNUC_MINOR_ +# define __GNUC_PREREQ__(ma, mi) \ + ((__GNUC__ > (ma)) || (__GNUC__ == (ma) && __GNUC_MINOR__ >= (mi))) +#else +# define __GNUC_PREREQ__(ma, mi) 0 +#endif + +/* Calling Convention: cdecl */ +#define _TLIBC_CDECL_ + +/* Thread Directive */ +#define _TLIBC_THREAD_ /* __thread */ + +/* Deprecated Warnings */ +#define _TLIBC_DEPRECATED_MSG(x) __STRING(x)" is deprecated in tlibc." +#define _TLIBC_DEPRECATED_(x) __attribute__((deprecated(_TLIBC_DEPRECATED_MSG(x)))) + +#ifndef _TLIBC_WARN_DEPRECATED_FUNCTIONS_ +# define _TLIBC_DEPRECATED_FUNCTION_(__ret, __func, ...) +#else +# define _TLIBC_DEPRECATED_FUNCTION_(__ret, __func, ...) \ + _TLIBC_DEPRECATED_(__func) \ + __ret __func(__VA_ARGS__) +#endif + +/* Static analysis for printf format strings. + * _MSC_PRINTF_FORMAT_: MSVC SAL annotation for specifying format strings. + * _GCC_PRINTF_FORMAT_(x, y): GCC declaring attribute for checking format strings. + * x - index of the format string. In C++ non-static method, index 1 is reseved for 'this'. + * y - index of first variadic agrument in '...'. + */ +#define _GCC_PRINTF_FORMAT_(x, y) __attribute__((__format__ (printf, x, y))) + +/* Attribute - noreturn */ +#define _TLIBC_NORETURN_ __attribute__ ((__noreturn__)) + +/* + * GNU C version 2.96 adds explicit branch prediction so that + * the CPU back-end can hint the processor and also so that + * code blocks can be reordered such that the predicted path + * sees a more linear flow, thus improving cache behavior, etc. + * + * The following two macros provide us with a way to utilize this + * compiler feature. Use __predict_true() if you expect the expression + * to evaluate to true, and __predict_false() if you expect the + * expression to evaluate to false. + * + * A few notes about usage: + * + * * Generally, __predict_false() error condition checks (unless + * you have some _strong_ reason to do otherwise, in which case + * document it), and/or __predict_true() `no-error' condition + * checks, assuming you want to optimize for the no-error case. + * + * * Other than that, if you don't know the likelihood of a test + * succeeding from empirical or other `hard' evidence, don't + * make predictions. + * + * * These are meant to be used in places that are run `a lot'. + * It is wasteful to make predictions in code that is run + * seldomly (e.g. at subsystem initialization time) as the + * basic block reordering that this affects can often generate + * larger code. + */ +#if defined(__GNUC__) && __GNUC_PREREQ__(2, 96) +#define __predict_true(exp) __builtin_expect(((exp) != 0), 1) +#define __predict_false(exp) __builtin_expect(((exp) != 0), 0) +#else +#define __predict_true(exp) ((exp) != 0) +#define __predict_false(exp) ((exp) != 0) +#endif + +#endif /* !_SYS_CDEFS_H_ */ diff --git a/sgx-jvm/linux-sgx/common/inc/tlibc/sys/endian.h b/sgx-jvm/linux-sgx/common/inc/tlibc/sys/endian.h new file mode 100644 index 0000000000..29edd81c5c --- /dev/null +++ b/sgx-jvm/linux-sgx/common/inc/tlibc/sys/endian.h @@ -0,0 +1,54 @@ +/* $OpenBSD: endian.h,v 1.18 2006/03/27 07:09:24 otto Exp $ */ + +/*- + * Copyright (c) 1997 Niklas Hallqvist. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Generic definitions for little- and big-endian systems. Other endianesses + * has to be dealt with in the specific machine/endian.h file for that port. + * + * This file is meant to be included from a little- or big-endian port's + * machine/endian.h after setting _BYTE_ORDER to either 1234 for little endian + * or 4321 for big.. + */ + +#ifndef _SYS_ENDIAN_H_ +#define _SYS_ENDIAN_H_ + +#define _LITTLE_ENDIAN 1234 +#define _BIG_ENDIAN 4321 +#define _PDP_ENDIAN 3412 +#define _BYTE_ORDER _LITTLE_ENDIAN + +#define LITTLE_ENDIAN _LITTLE_ENDIAN +#define BIG_ENDIAN _BIG_ENDIAN +#define PDP_ENDIAN _PDP_ENDIAN +#define BYTE_ORDER _BYTE_ORDER + +#define __BYTE_ORDER _BYTE_ORDER +#define __BIG_ENDIAN _BIG_ENDIAN +#define __LITTLE_ENDIAN _LITTLE_ENDIAN + +#endif /* _SYS_ENDIAN_H_ */ + diff --git a/sgx-jvm/linux-sgx/common/inc/tlibc/sys/ieee.h b/sgx-jvm/linux-sgx/common/inc/tlibc/sys/ieee.h new file mode 100644 index 0000000000..8370cd8295 --- /dev/null +++ b/sgx-jvm/linux-sgx/common/inc/tlibc/sys/ieee.h @@ -0,0 +1,145 @@ +/* $OpenBSD: ieee.h,v 1.2 2008/09/07 20:36:06 martynas Exp $ */ +/* $NetBSD: ieee.h,v 1.1 1996/09/30 16:34:25 ws Exp $ */ + +/* + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Lawrence Berkeley Laboratory. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)ieee.h 8.1 (Berkeley) 6/11/93 + */ + +/* + * ieee.h defines the machine-dependent layout of the machine's IEEE + * floating point. It does *not* define (yet?) any of the rounding + * mode bits, exceptions, and so forth. + */ + +/* + * Define the number of bits in each fraction and exponent. + * + * k k+1 + * Note that 1.0 x 2 == 0.1 x 2 and that denorms are represented + * + * (-exp_bias+1) + * as fractions that look like 0.fffff x 2 . This means that + * + * -126 + * the number 0.10000 x 2 , for instance, is the same as the normalized + * + * -127 -128 + * float 1.0 x 2 . Thus, to represent 2 , we need one leading zero + * + * -129 + * in the fraction; to represent 2 , we need two, and so on. This + * + * (-exp_bias-fracbits+1) + * implies that the smallest denormalized number is 2 + * + * for whichever format we are talking about: for single precision, for + * + * -126 -149 + * instance, we get .00000000000000000000001 x 2 , or 1.0 x 2 , and + * + * -149 == -127 - 23 + 1. + */ + +#include + +#define SNG_EXPBITS 8 +#define SNG_FRACBITS 23 + +#define DBL_EXPBITS 11 +#define DBL_FRACHBITS 20 +#define DBL_FRACLBITS 32 +#define DBL_FRACBITS 52 + +#define EXT_EXPBITS 15 +#define EXT_FRACHBITS 32 +#define EXT_FRACLBITS 32 +#define EXT_FRACBITS 64 + +#define EXT_TO_ARRAY32(p, a) do { \ + (a)[0] = (uint32_t)(p)->ext_fracl; \ + (a)[1] = (uint32_t)(p)->ext_frach; \ +} while(0) + +struct ieee_single { + u_int sng_frac:23; + u_int sng_exp:8; + u_int sng_sign:1; +}; + +struct ieee_double { + u_int dbl_fracl; + u_int dbl_frach:20; + u_int dbl_exp:11; + u_int dbl_sign:1; +}; + +struct ieee_ext { + u_int ext_fracl; + u_int ext_frach; + u_int ext_exp:15; + u_int ext_sign:1; + u_int ext_padl:16; + u_int ext_padh; +}; + +/* + * Floats whose exponent is in [1..INFNAN) (of whatever type) are + * `normal'. Floats whose exponent is INFNAN are either Inf or NaN. + * Floats whose exponent is zero are either zero (iff all fraction + * bits are zero) or subnormal values. + * + * A NaN is a `signalling NaN' if its QUIETNAN bit is clear in its + * high fraction; if the bit is set, it is a `quiet NaN'. + */ +#define SNG_EXP_INFNAN 255 +#define DBL_EXP_INFNAN 2047 +#define EXT_EXP_INFNAN 32767 + +#if 0 +#define SNG_QUIETNAN (1 << 22) +#define DBL_QUIETNAN (1 << 19) +#define EXT_QUIETNAN (1 << 15) +#endif + +/* + * Exponent biases. + */ +#define SNG_EXP_BIAS 127 +#define DBL_EXP_BIAS 1023 +#define EXT_EXP_BIAS 16383 diff --git a/sgx-jvm/linux-sgx/common/inc/tlibc/sys/limits.h b/sgx-jvm/linux-sgx/common/inc/tlibc/sys/limits.h new file mode 100644 index 0000000000..3d1f9673ad --- /dev/null +++ b/sgx-jvm/linux-sgx/common/inc/tlibc/sys/limits.h @@ -0,0 +1,77 @@ +/* $OpenBSD: limits.h,v 1.8 2009/11/27 19:54:35 guenther Exp $ */ +/* + * Copyright (c) 2002 Marc Espie. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE OPENBSD PROJECT AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OPENBSD + * PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef _SYS_LIMITS_H_ +#define _SYS_LIMITS_H_ + +#include + +/* Common definitions for limits.h. */ + +#define CHAR_BIT 8 /* number of bits in a char */ + +#define SCHAR_MAX 0x7f /* max value for a signed char */ +#define SCHAR_MIN (-0x7f - 1) /* min value for a signed char */ + +#define UCHAR_MAX 0xff /* max value for an unsigned char */ +#ifdef __CHAR_UNSIGNED__ +# define CHAR_MIN 0 /* min value for a char */ +# define CHAR_MAX 0xff /* max value for a char */ +#else +# define CHAR_MAX 0x7f +# define CHAR_MIN (-0x7f-1) +#endif + +#define MB_LEN_MAX 1 /* Allow UTF-8 (RFC 3629) */ + +#define USHRT_MAX 0xffff /* max value for an unsigned short */ +#define SHRT_MAX 0x7fff /* max value for a short */ +#define SHRT_MIN (-0x7fff-1) /* min value for a short */ + +#define UINT_MAX 0xffffffffU /* max value for an unsigned int */ +#define INT_MAX 0x7fffffff /* max value for an int */ +#define INT_MIN (-0x7fffffff-1) /* min value for an int */ + +#ifdef __x86_64__ +# define ULONG_MAX 0xffffffffffffffffUL /* max value for unsigned long */ +# define LONG_MAX 0x7fffffffffffffffL /* max value for a signed long */ +# define LONG_MIN (-0x7fffffffffffffffL-1) /* min value for a signed long */ +#else +# define ULONG_MAX 0xffffffffUL /* max value for an unsigned long */ +# define LONG_MAX 0x7fffffffL /* max value for a long */ +# define LONG_MIN (-0x7fffffffL-1) /* min value for a long */ +#endif + +#define ULLONG_MAX 0xffffffffffffffffULL /* max value for unsigned long long */ +#define LLONG_MAX 0x7fffffffffffffffLL /* max value for a signed long long */ +#define LLONG_MIN (-0x7fffffffffffffffLL-1) /* min value for a signed long long */ + +#ifdef __x86_64__ +# define LONG_BIT 64 +#else +# define LONG_BIT 32 +#endif + +#endif /* !_SYS_LIMITS_H_ */ diff --git a/sgx-jvm/linux-sgx/common/inc/tlibc/sys/stdint.h b/sgx-jvm/linux-sgx/common/inc/tlibc/sys/stdint.h new file mode 100644 index 0000000000..b76cc52ed8 --- /dev/null +++ b/sgx-jvm/linux-sgx/common/inc/tlibc/sys/stdint.h @@ -0,0 +1,253 @@ +/* $OpenBSD: stdint.h,v 1.4 2006/12/10 22:17:55 deraadt Exp $ */ + +/* + * Copyright (c) 1997, 2005 Todd C. Miller + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _SYS_STDINT_H_ +#define _SYS_STDINT_H_ + +#include +#include + +/* 7.18.1.1 Exact-width integer types (also in sys/types.h) */ +#ifndef _INT8_T_DEFINED_ +#define _INT8_T_DEFINED_ +typedef __int8_t int8_t; +#endif + +#ifndef _UINT8_T_DEFINED_ +#define _UINT8_T_DEFINED_ +typedef __uint8_t uint8_t; +#endif + +#ifndef _INT16_T_DEFINED_ +#define _INT16_T_DEFINED_ +typedef __int16_t int16_t; +#endif + +#ifndef _UINT16_T_DEFINED_ +#define _UINT16_T_DEFINED_ +typedef __uint16_t uint16_t; +#endif + +#ifndef _INT32_T_DEFINED_ +#define _INT32_T_DEFINED_ +typedef __int32_t int32_t; +#endif + +#ifndef _UINT32_T_DEFINED_ +#define _UINT32_T_DEFINED_ +typedef __uint32_t uint32_t; +#endif + +#ifndef _INT64_T_DEFINED_ +#define _INT64_T_DEFINED_ +typedef __int64_t int64_t; +#endif + +#ifndef _UINT64_T_DEFINED_ +#define _UINT64_T_DEFINED_ +typedef __uint64_t uint64_t; +#endif + +/* 7.18.1.2 Minimum-width integer types */ +typedef __int_least8_t int_least8_t; +typedef __uint_least8_t uint_least8_t; +typedef __int_least16_t int_least16_t; +typedef __uint_least16_t uint_least16_t; +typedef __int_least32_t int_least32_t; +typedef __uint_least32_t uint_least32_t; +typedef __int_least64_t int_least64_t; +typedef __uint_least64_t uint_least64_t; + +/* 7.18.1.3 Fastest minimum-width integer types */ +typedef __int_fast8_t int_fast8_t; +typedef __uint_fast8_t uint_fast8_t; +typedef __int_fast16_t int_fast16_t; +typedef __uint_fast16_t uint_fast16_t; +typedef __int_fast32_t int_fast32_t; +typedef __uint_fast32_t uint_fast32_t; +typedef __int_fast64_t int_fast64_t; +typedef __uint_fast64_t uint_fast64_t; + +/* 7.18.1.4 Integer types capable of holding object pointers */ +#ifndef _INTPTR_T_DEFINED_ +#define _INTPTR_T_DEFINED_ +typedef __intptr_t intptr_t; +#endif + +#ifndef _UINTPTR_T_DEFINED_ +#define _UINTPTR_T_DEFINED_ +typedef __uintptr_t uintptr_t; +#endif + +/* 7.18.1.5 Greatest-width integer types */ +typedef __intmax_t intmax_t; +typedef __uintmax_t uintmax_t; + +//#if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) +/* + * 7.18.2 Limits of specified-width integer types. + * + * The following object-like macros specify the minimum and maximum limits + * of integer types corresponding to the typedef names defined above. + */ + +/* 7.18.2.1 Limits of exact-width integer types */ +#define INT8_MIN (-0x7f - 1) +#define INT16_MIN (-0x7fff - 1) +#define INT32_MIN (-0x7fffffff - 1) +#define INT64_MIN (-0x7fffffffffffffffLL - 1) + +#define INT8_MAX 0x7f +#define INT16_MAX 0x7fff +#define INT32_MAX 0x7fffffff +#define INT64_MAX 0x7fffffffffffffffLL + +#define UINT8_MAX 0xff +#define UINT16_MAX 0xffff +#define UINT32_MAX 0xffffffffU +#define UINT64_MAX 0xffffffffffffffffULL + +/* 7.18.2.2 Limits of minimum-width integer types */ +#define INT_LEAST8_MIN INT8_MIN +#define INT_LEAST16_MIN INT16_MIN +#define INT_LEAST32_MIN INT32_MIN +#define INT_LEAST64_MIN INT64_MIN + +#define INT_LEAST8_MAX INT8_MAX +#define INT_LEAST16_MAX INT16_MAX +#define INT_LEAST32_MAX INT32_MAX +#define INT_LEAST64_MAX INT64_MAX + +#define UINT_LEAST8_MAX UINT8_MAX +#define UINT_LEAST16_MAX UINT16_MAX +#define UINT_LEAST32_MAX UINT32_MAX +#define UINT_LEAST64_MAX UINT64_MAX + +/* 7.18.2.3 Limits of fastest minimum-width integer types */ +#define INT_FAST8_MIN INT8_MIN +#define INT_FAST16_MIN INT16_MIN +#define INT_FAST32_MIN INT32_MIN +#define INT_FAST64_MIN INT64_MIN + +#define INT_FAST8_MAX INT8_MAX +#ifdef __x86_64__ +#define INT_FAST16_MAX INT64_MAX +#define INT_FAST32_MAX INT64_MAX +#else +#define INT_FAST16_MAX INT32_MAX +#define INT_FAST32_MAX INT32_MAX +#endif +#define INT_FAST64_MAX INT64_MAX + +#define UINT_FAST8_MAX UINT8_MAX +#ifdef __x86_64__ +#define UINT_FAST16_MAX UINT64_MAX +#define UINT_FAST32_MAX UINT64_MAX +#else +#define UINT_FAST16_MAX UINT32_MAX +#define UINT_FAST32_MAX UINT32_MAX +#endif +#define UINT_FAST64_MAX UINT64_MAX + +/* 7.18.2.4 Limits of integer types capable of holding object pointers */ +#ifdef __x86_64__ +#define INTPTR_MIN INT64_MIN +#define INTPTR_MAX INT64_MAX +#define UINTPTR_MAX UINT64_MAX +#else +#define INTPTR_MIN INT32_MIN +#define INTPTR_MAX INT32_MAX +#define UINTPTR_MAX UINT32_MAX +#endif + +/* 7.18.2.5 Limits of greatest-width integer types */ +#define INTMAX_MIN INT64_MIN +#define INTMAX_MAX INT64_MAX +#define UINTMAX_MAX UINT64_MAX + +/* + * 7.18.3 Limits of other integer types. + * + * The following object-like macros specify the minimum and maximum limits + * of integer types corresponding to types specified in other standard + * header files. + */ + +/* Limits of ptrdiff_t */ +#define PTRDIFF_MIN INTPTR_MIN +#define PTRDIFF_MAX INTPTR_MAX + +/* Limits of size_t (also in limits.h) */ +#ifndef SIZE_MAX +#define SIZE_MAX UINTPTR_MAX +#endif + +/* Limits of wchar_t */ +#ifdef _TLIBC_WIN_ +# define WCHAR_MIN 0x0000 +# define WCHAR_MAX 0xffff +#else +# ifdef __WCHAR_MAX__ +# define WCHAR_MAX __WCHAR_MAX__ +# else +# define WCHAR_MAX (2147483647) +# endif +# ifdef __WCHAR_MIN__ +# define WCHAR_MIN __WCHAR_MIN__ +# elif L'\0' - 1 > 0 +# define WCHAR_MIN L'\0' +# else +# define WCHAR_MIN (-WCHAR_MAX - 1) +# endif +#endif + +/* Limits of wint_t */ +# define WINT_MIN (0u) +# define WINT_MAX (4294967295u) + +//#endif /* __cplusplus || __STDC_LIMIT_MACROS */ + +//#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) +/* + * 7.18.4 Macros for integer constants. + * + * The following function-like macros expand to integer constants + * suitable for initializing objects that have integer types corresponding + * to types defined in . The argument in any instance of + * these macros shall be a decimal, octal, or hexadecimal constant with + * a value that does not exceed the limits for the corresponding type. + */ + +/* 7.18.4.1 Macros for minimum-width integer constants. */ +#define INT8_C(_c) (_c) +#define INT16_C(_c) (_c) +#define INT32_C(_c) (_c) +#define INT64_C(_c) __CONCAT(_c, LL) + +#define UINT8_C(_c) (_c) +#define UINT16_C(_c) (_c) +#define UINT32_C(_c) __CONCAT(_c, U) +#define UINT64_C(_c) __CONCAT(_c, ULL) + +/* 7.18.4.2 Macros for greatest-width integer constants. */ +#define INTMAX_C(_c) __CONCAT(_c, LL) +#define UINTMAX_C(_c) __CONCAT(_c, ULL) + +//#endif /* __cplusplus || __STDC_CONSTANT_MACROS */ + +#endif /* _SYS_STDINT_H_ */ diff --git a/sgx-jvm/linux-sgx/common/inc/tlibc/sys/types.h b/sgx-jvm/linux-sgx/common/inc/tlibc/sys/types.h new file mode 100644 index 0000000000..474f3e93d9 --- /dev/null +++ b/sgx-jvm/linux-sgx/common/inc/tlibc/sys/types.h @@ -0,0 +1,128 @@ +/* $OpenBSD: types.h,v 1.31 2008/03/16 19:42:57 otto Exp $ */ +/* $NetBSD: types.h,v 1.29 1996/11/15 22:48:25 jtc Exp $ */ + +/*- + * Copyright (c) 1982, 1986, 1991, 1993 + * The Regents of the University of California. All rights reserved. + * (c) UNIX System Laboratories, Inc. + * All or some portions of this file are derived from material licensed + * to the University of California by American Telephone and Telegraph + * Co. or Unix System Laboratories, Inc. and are reproduced herein with + * the permission of UNIX System Laboratories, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)types.h 8.4 (Berkeley) 1/21/94 + */ + +#ifndef _SYS_TYPES_H_ +#define _SYS_TYPES_H_ + +#include +#include + +typedef unsigned char u_char; +typedef unsigned short u_short; +typedef unsigned int u_int; +typedef unsigned long u_long; + +typedef unsigned char unchar; /* Sys V compatibility */ +typedef unsigned short ushort; /* Sys V compatibility */ +typedef unsigned int uint; /* Sys V compatibility */ +typedef unsigned long ulong; /* Sys V compatibility */ + +#ifndef _INT8_T_DEFINED_ +#define _INT8_T_DEFINED_ +typedef __int8_t int8_t; +#endif + +#ifndef _UINT8_T_DEFINED_ +#define _UINT8_T_DEFINED_ +typedef __uint8_t uint8_t; +#endif + +#ifndef _INT16_T_DEFINED_ +#define _INT16_T_DEFINED_ +typedef __int16_t int16_t; +#endif + +#ifndef _UINT16_T_DEFINED_ +#define _UINT16_T_DEFINED_ +typedef __uint16_t uint16_t; +#endif + +#ifndef _INT32_T_DEFINED_ +#define _INT32_T_DEFINED_ +typedef __int32_t int32_t; +#endif + +#ifndef _UINT32_T_DEFINED_ +#define _UINT32_T_DEFINED_ +typedef __uint32_t uint32_t; +#endif + +#ifndef _INT64_T_DEFINED_ +#define _INT64_T_DEFINED_ +typedef __int64_t int64_t; +#endif + +#ifndef _UINT64_T_DEFINED_ +#define _UINT64_T_DEFINED_ +typedef __uint64_t uint64_t; +#endif + +#ifndef _INTPTR_T_DEFINED_ +#define _INTPTR_T_DEFINED_ +typedef __intptr_t intptr_t; +#endif + +#ifndef _UINTPTR_T_DEFINED_ +#define _UINTPTR_T_DEFINED_ +typedef __uintptr_t uintptr_t; +#endif + +/* BSD-style unsigned bits types */ +typedef __uint8_t u_int8_t; +typedef __uint16_t u_int16_t; +typedef __uint32_t u_int32_t; +typedef __uint64_t u_int64_t; + + +#ifndef _SIZE_T_DEFINED_ +#define _SIZE_T_DEFINED_ +typedef __size_t size_t; +#endif + +#ifndef _SSIZE_T_DEFINED_ +#define _SSIZE_T_DEFINED_ +typedef __ssize_t ssize_t; +#endif + +#ifndef _OFF_T_DEFINED_ +#define _OFF_T_DEFINED_ +typedef __off_t off_t; +#endif + +#endif /* !_SYS_TYPES_H_ */ diff --git a/sgx-jvm/linux-sgx/common/inc/tlibc/time.h b/sgx-jvm/linux-sgx/common/inc/tlibc/time.h new file mode 100644 index 0000000000..3880d3e9ac --- /dev/null +++ b/sgx-jvm/linux-sgx/common/inc/tlibc/time.h @@ -0,0 +1,104 @@ +/* $OpenBSD: time.h,v 1.18 2006/01/06 18:53:04 millert Exp $ */ +/* $NetBSD: time.h,v 1.9 1994/10/26 00:56:35 cgd Exp $ */ + +/* + * Copyright (c) 1989 The Regents of the University of California. + * All rights reserved. + * + * (c) UNIX System Laboratories, Inc. + * All or some portions of this file are derived from material licensed + * to the University of California by American Telephone and Telegraph + * Co. or Unix System Laboratories, Inc. and are reproduced herein with + * the permission of UNIX System Laboratories, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)time.h 5.12 (Berkeley) 3/9/91 + */ + +#ifndef _TIME_H_ +#define _TIME_H_ + +#include +#include + +#ifndef NULL +#ifdef __cplusplus +#define NULL 0 +#else +#define NULL ((void *)0) +#endif +#endif + +#if !defined (_CLOCK_T_DEFINED_) && !defined (_CLOCK_T_DEFINED) +#define _CLOCK_T_DEFINED_ +#define _CLOCK_T_DEFINED +typedef __clock_t clock_t; +#endif + +#if !defined (_TIME_T_DEFINED_) && !defined (_TIME_T_DEFINED) +#define _TIME_T_DEFINED_ +#define _TIME_T_DEFINED +typedef __time_t time_t; +#endif + +#if !defined (_SIZE_T_DEFINED_) && !defined (_SIZE_T_DEFINED) +#define _SIZE_T_DEFINED_ +#define _SIZE_T_DEFINED +typedef __size_t size_t; +#endif + +#if !defined (_TM_DEFINED) +#define _TM_DEFINED +struct tm { + int tm_sec; /* seconds after the minute [0-60] */ + int tm_min; /* minutes after the hour [0-59] */ + int tm_hour; /* hours since midnight [0-23] */ + int tm_mday; /* day of the month [1-31] */ + int tm_mon; /* months since January [0-11] */ + int tm_year; /* years since 1900 */ + int tm_wday; /* days since Sunday [0-6] */ + int tm_yday; /* days since January 1 [0-365] */ + int tm_isdst; /* Daylight Saving Time flag */ + /* FIXME: naming issue exists on Fedora/Ubuntu */ + long tm_gmtoff; /* offset from UTC in seconds */ + char *tm_zone; /* timezone abbreviation */ +}; +#endif + +__BEGIN_DECLS + +double _TLIBC_CDECL_ difftime(time_t, time_t); +char * _TLIBC_CDECL_ asctime(const struct tm *); +size_t _TLIBC_CDECL_ strftime(char *, size_t, const char *, const struct tm *); + +/* + * Non-C99 + */ +char * _TLIBC_CDECL_ asctime_r(const struct tm *, char *); + +__END_DECLS + +#endif /* !_TIME_H_ */ diff --git a/sgx-jvm/linux-sgx/common/inc/tlibc/unistd.h b/sgx-jvm/linux-sgx/common/inc/tlibc/unistd.h new file mode 100644 index 0000000000..2958a6ccc6 --- /dev/null +++ b/sgx-jvm/linux-sgx/common/inc/tlibc/unistd.h @@ -0,0 +1,59 @@ +/* $OpenBSD: unistd.h,v 1.62 2008/06/25 14:58:54 millert Exp $ */ +/* $NetBSD: unistd.h,v 1.26.4.1 1996/05/28 02:31:51 mrg Exp $ */ + +/*- + * Copyright (c) 1991 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)unistd.h 5.13 (Berkeley) 6/17/91 + */ + +#ifndef _UNISTD_H_ +#define _UNISTD_H_ + +#include +#include + +__BEGIN_DECLS + +void * _TLIBC_CDECL_ sbrk(intptr_t); + +/* + * Deprecated Non-C99. + */ +_TLIBC_DEPRECATED_FUNCTION_(int _TLIBC_CDECL_, execl, const char *, const char *, ...); +_TLIBC_DEPRECATED_FUNCTION_(int _TLIBC_CDECL_, execlp, const char *, const char *, ...); +_TLIBC_DEPRECATED_FUNCTION_(int _TLIBC_CDECL_, execle, const char *, const char *, ...); +_TLIBC_DEPRECATED_FUNCTION_(int _TLIBC_CDECL_, execv, const char *, char * const *); +_TLIBC_DEPRECATED_FUNCTION_(int _TLIBC_CDECL_, execve, const char *, char * const *, char * const *); +_TLIBC_DEPRECATED_FUNCTION_(int _TLIBC_CDECL_, execvp, const char *, char * const *); + +//_TLIBC_DEPRECATED_FUNCTION_(pid_t _TLIBC_CDECL_, fork, void); /* no pid_t */ + +__END_DECLS + +#endif /* !_UNISTD_H_ */ diff --git a/sgx-jvm/linux-sgx/common/inc/tlibc/wchar.h b/sgx-jvm/linux-sgx/common/inc/tlibc/wchar.h new file mode 100644 index 0000000000..4ca0b39f40 --- /dev/null +++ b/sgx-jvm/linux-sgx/common/inc/tlibc/wchar.h @@ -0,0 +1,139 @@ +/* $OpenBSD: wchar.h,v 1.11 2010/07/24 09:58:39 guenther Exp $ */ +/* $NetBSD: wchar.h,v 1.16 2003/03/07 07:11:35 tshiozak Exp $ */ + +/*- + * Copyright (c)1999 Citrus Project, + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/*- + * Copyright (c) 1999, 2000 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Julian Coleman. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _WCHAR_H_ +#define _WCHAR_H_ + +#include +#include +#include /* WCHAR_MAX/WCHAR_MIN */ + +#ifndef NULL +#ifdef __cplusplus +#define NULL 0 +#else +#define NULL ((void *)0) +#endif +#endif + +#if !defined(_WCHAR_T_DEFINED_) && !defined(__cplusplus) +#define _WCHAR_T_DEFINED_ +#ifndef __WCHAR_TYPE__ +#define __WCHAR_TYPE__ int +#endif +typedef __WCHAR_TYPE__ wchar_t; +#endif + +#ifndef _MBSTATE_T_DEFINED_ +#define _MBSTATE_T_DEFINED_ +typedef __mbstate_t mbstate_t; +#endif + +#ifndef _WINT_T_DEFINED_ +#define _WINT_T_DEFINED_ +typedef __wint_t wint_t; +#endif + +#ifndef _SIZE_T_DEFINED_ +#define _SIZE_T_DEFINED_ +typedef __size_t size_t; +#endif + +#ifndef WEOF +#define WEOF ((wint_t)-1) +#endif + +__BEGIN_DECLS + +wint_t _TLIBC_CDECL_ btowc(int); +int _TLIBC_CDECL_ wctob(wint_t); +size_t _TLIBC_CDECL_ mbrlen(const char *, size_t, mbstate_t *); +size_t _TLIBC_CDECL_ mbrtowc(wchar_t *, const char *, size_t, mbstate_t *); +int _TLIBC_CDECL_ mbsinit(const mbstate_t *); +size_t _TLIBC_CDECL_ mbsrtowcs(wchar_t *, const char **, size_t, mbstate_t *); +size_t _TLIBC_CDECL_ wcrtomb(char *, wchar_t, mbstate_t *); +wchar_t * _TLIBC_CDECL_ wcschr(const wchar_t *, wchar_t); +int _TLIBC_CDECL_ wcscmp(const wchar_t *, const wchar_t *); +int _TLIBC_CDECL_ wcscoll(const wchar_t *, const wchar_t *); +size_t _TLIBC_CDECL_ wcscspn(const wchar_t *, const wchar_t *); +size_t _TLIBC_CDECL_ wcslen(const wchar_t *); +wchar_t * _TLIBC_CDECL_ wcsncat(wchar_t *, const wchar_t *, size_t); +int _TLIBC_CDECL_ wcsncmp(const wchar_t *, const wchar_t *, size_t); +wchar_t * _TLIBC_CDECL_ wcsncpy(wchar_t *, const wchar_t *, size_t); +wchar_t * _TLIBC_CDECL_ wcspbrk(const wchar_t *, const wchar_t *); +wchar_t * _TLIBC_CDECL_ wcsrchr(const wchar_t *, wchar_t); +size_t _TLIBC_CDECL_ wcsrtombs(char *, const wchar_t **, size_t, mbstate_t *); +size_t _TLIBC_CDECL_ wcsspn(const wchar_t *, const wchar_t *); +wchar_t * _TLIBC_CDECL_ wcsstr(const wchar_t *, const wchar_t *); +wchar_t * _TLIBC_CDECL_ wcstok(wchar_t *, const wchar_t *, wchar_t **); +size_t _TLIBC_CDECL_ wcsxfrm(wchar_t *, const wchar_t *, size_t); +wchar_t * _TLIBC_CDECL_ wmemchr(const wchar_t *, wchar_t, size_t); +int _TLIBC_CDECL_ wmemcmp(const wchar_t *, const wchar_t *, size_t); +wchar_t * _TLIBC_CDECL_ wmemcpy(wchar_t *, const wchar_t *, size_t); +wchar_t * _TLIBC_CDECL_ wmemmove(wchar_t *, const wchar_t *, size_t); +wchar_t * _TLIBC_CDECL_ wmemset(wchar_t *, wchar_t, size_t); + +int _TLIBC_CDECL_ swprintf(wchar_t *, size_t, const wchar_t *, ...); +int _TLIBC_CDECL_ vswprintf(wchar_t *, size_t, const wchar_t *, __va_list); + +/* leagcy version of wcsstr */ +wchar_t * _TLIBC_CDECL_ wcswcs(const wchar_t *, const wchar_t *); + +__END_DECLS + +#endif /* !_WCHAR_H_ */ diff --git a/sgx-jvm/linux-sgx/common/inc/tlibc/wctype.h b/sgx-jvm/linux-sgx/common/inc/tlibc/wctype.h new file mode 100644 index 0000000000..25466f15d1 --- /dev/null +++ b/sgx-jvm/linux-sgx/common/inc/tlibc/wctype.h @@ -0,0 +1,83 @@ +/* $OpenBSD: wctype.h,v 1.5 2006/01/06 18:53:04 millert Exp $ */ +/* $NetBSD: wctype.h,v 1.5 2003/03/02 22:18:11 tshiozak Exp $ */ + +/*- + * Copyright (c)1999 Citrus Project, + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * citrus Id: wctype.h,v 1.4 2000/12/21 01:50:21 itojun Exp + */ + +#ifndef _WCTYPE_H_ +#define _WCTYPE_H_ + +#include +#include + +#ifndef _WINT_T_DEFINED_ +#define _WINT_T_DEFINED_ +typedef __wint_t wint_t; +#endif + +#ifndef _WCTRANS_T_DEFINED_ +#define _WCTRANS_T_DEFINED_ +typedef __wctrans_t wctrans_t; +#endif + +#ifndef _WCTYPE_T_DEFINED_ +#define _WCTYPE_T_DEFINED_ +typedef __wctype_t wctype_t; +#endif + +#ifndef WEOF +#define WEOF ((wint_t)-1) +#endif + +__BEGIN_DECLS + +/* + * Deprecated definitions. + */ +_TLIBC_DEPRECATED_FUNCTION_(int _TLIBC_CDECL_, iswalnum, wint_t); +_TLIBC_DEPRECATED_FUNCTION_(int _TLIBC_CDECL_, iswalpha, wint_t); +_TLIBC_DEPRECATED_FUNCTION_(int _TLIBC_CDECL_, iswblank, wint_t); +_TLIBC_DEPRECATED_FUNCTION_(int _TLIBC_CDECL_, iswcntrl, wint_t); +_TLIBC_DEPRECATED_FUNCTION_(int _TLIBC_CDECL_, iswdigit, wint_t); +_TLIBC_DEPRECATED_FUNCTION_(int _TLIBC_CDECL_, iswgraph, wint_t); +_TLIBC_DEPRECATED_FUNCTION_(int _TLIBC_CDECL_, iswlower, wint_t); +_TLIBC_DEPRECATED_FUNCTION_(int _TLIBC_CDECL_, iswprint, wint_t); +_TLIBC_DEPRECATED_FUNCTION_(int _TLIBC_CDECL_, iswpunct, wint_t); +_TLIBC_DEPRECATED_FUNCTION_(int _TLIBC_CDECL_, iswspace, wint_t); +_TLIBC_DEPRECATED_FUNCTION_(int _TLIBC_CDECL_, iswupper, wint_t); +_TLIBC_DEPRECATED_FUNCTION_(int _TLIBC_CDECL_, iswxdigit, wint_t); +_TLIBC_DEPRECATED_FUNCTION_(int _TLIBC_CDECL_, iswctype, wint_t, wctype_t); +_TLIBC_DEPRECATED_FUNCTION_(wint_t _TLIBC_CDECL_, towctrans, wint_t, wctrans_t); +_TLIBC_DEPRECATED_FUNCTION_(wint_t _TLIBC_CDECL_, towlower, wint_t); +_TLIBC_DEPRECATED_FUNCTION_(wint_t _TLIBC_CDECL_, towupper, wint_t); +_TLIBC_DEPRECATED_FUNCTION_(wctrans_t _TLIBC_CDECL_, wctrans, const char *); +_TLIBC_DEPRECATED_FUNCTION_(wctype_t _TLIBC_CDECL_, wctype, const char *); + +__END_DECLS + +#endif /* _WCTYPE_H_ */ diff --git a/sgx-jvm/linux-sgx/common/se_wrapper/Makefile b/sgx-jvm/linux-sgx/common/se_wrapper/Makefile new file mode 100644 index 0000000000..0cf6f20ebd --- /dev/null +++ b/sgx-jvm/linux-sgx/common/se_wrapper/Makefile @@ -0,0 +1,61 @@ +# +# Copyright (C) 2011-2016 Intel Corporation. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# + +include ../../buildenv.mk + +CFLAGS += -Werror -D_GNU_SOURCE -fPIC +CFLAGS += $(ADDED_INC) + +CPPFLAGS := -I$(COMMON_DIR)/inc/ \ + -I$(COMMON_DIR)/inc/internal + +OBJS := se_memory.o \ + se_thread.o \ + se_trace.o \ + se_event.o \ + se_rwlock.o \ + se_time.o \ + se_map.o + +LIBWRAPPER := libwrapper.a + +.PHONY: clean all +all: $(LIBWRAPPER) + +$(LIBWRAPPER): $(OBJS) + $(AR) rcs $@ $^ + +$(OBJS): %.o: $(COMMON_DIR)/src/%.c + $(CC) -c $(CFLAGS) $(CPPFLAGS) $< -o $@ + +.PHONY: clean +clean: + @$(RM) $(LIBWRAPPER) $(OBJS) diff --git a/sgx-jvm/linux-sgx/common/src/dh.cpp b/sgx-jvm/linux-sgx/common/src/dh.cpp new file mode 100644 index 0000000000..6b01601b9f --- /dev/null +++ b/sgx-jvm/linux-sgx/common/src/dh.cpp @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + + +/** +* File: +* dh.cpp +*Description: +* Encrypt and decrypt messages over DH session +*/ +#include "dh.h" +#include "sgx_tcrypto.h" + +bool encrypt_msg(pse_message_t* pse_msg, uint8_t* data, sgx_key_128bit_t* authenticated_encryption_key) +{ + /* get random IV */ + if(sgx_read_rand(pse_msg->payload_iv, PAYLOAD_IV_SIZE) != SGX_SUCCESS) + { + return false; + } + + return (SGX_SUCCESS == sgx_rijndael128GCM_encrypt( + authenticated_encryption_key, + data, + pse_msg->payload_size, + reinterpret_cast(&(pse_msg->payload)), + reinterpret_cast(&(pse_msg->payload_iv)), + 12, + NULL, + 0, + &pse_msg->payload_tag + )); +} + +bool decrypt_msg(pse_message_t* pse_msg, uint8_t* data, sgx_key_128bit_t* authenticated_encryption_key) +{ + return(SGX_SUCCESS == sgx_rijndael128GCM_decrypt( + authenticated_encryption_key, + pse_msg->payload, + pse_msg->payload_size, + data, + reinterpret_cast(&(pse_msg->payload_iv)), + 12, + NULL, + 0, + &pse_msg->payload_tag + )); +} + diff --git a/sgx-jvm/linux-sgx/common/src/ecp.cpp b/sgx-jvm/linux-sgx/common/src/ecp.cpp new file mode 100644 index 0000000000..ea632f9443 --- /dev/null +++ b/sgx-jvm/linux-sgx/common/src/ecp.cpp @@ -0,0 +1,111 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + + +#include "sgx_ecp_types.h" +#include "ecp_interface.h" +#include "stdlib.h" +#include "string.h" + +#ifndef ERROR_BREAK +#define ERROR_BREAK(x) if(x != ippStsNoErr){break;} +#endif +#ifndef NULL_BREAK +#define NULL_BREAK(x) if(!x){break;} +#endif +#ifndef SAFE_FREE +#define SAFE_FREE(ptr) {if (NULL != (ptr)) {free(ptr); (ptr)=NULL;}} +#endif + +#define MAC_KEY_SIZE 16 + +#define EC_DERIVATION_BUFFER_SIZE(label_length) ((label_length) +4) + +sgx_status_t derive_key( + const sgx_ec256_dh_shared_t* shared_key, + const char* label, + uint32_t label_length, + sgx_ec_key_128bit_t* derived_key) +{ + sgx_status_t se_ret = SGX_SUCCESS; + uint8_t cmac_key[MAC_KEY_SIZE]; + sgx_ec_key_128bit_t key_derive_key; + if (!shared_key || !derived_key || !label) + { + return SGX_ERROR_INVALID_PARAMETER; + } + + /*check integer overflow */ + if (label_length > EC_DERIVATION_BUFFER_SIZE(label_length)) + { + return SGX_ERROR_INVALID_PARAMETER; + } + + memset(cmac_key, 0, MAC_KEY_SIZE); + se_ret = sgx_rijndael128_cmac_msg((sgx_cmac_128bit_key_t *)cmac_key, + (uint8_t*)shared_key, + sizeof(sgx_ec256_dh_shared_t), + (sgx_cmac_128bit_tag_t *)&key_derive_key); + if (SGX_SUCCESS != se_ret) + { + memset_s(&key_derive_key, sizeof(key_derive_key), 0, sizeof(key_derive_key)); + INTERNAL_SGX_ERROR_CODE_CONVERTOR(se_ret); + return se_ret; + } + /* derivation_buffer = counter(0x01) || label || 0x00 || output_key_len(0x0080) */ + uint32_t derivation_buffer_length = EC_DERIVATION_BUFFER_SIZE(label_length); + uint8_t *p_derivation_buffer = (uint8_t *)malloc(derivation_buffer_length); + if (p_derivation_buffer == NULL) + { + return SGX_ERROR_OUT_OF_MEMORY; + } + memset(p_derivation_buffer, 0, derivation_buffer_length); + + /*counter = 0x01 */ + p_derivation_buffer[0] = 0x01; + /*label*/ + memcpy(&p_derivation_buffer[1], label, label_length); + /*output_key_len=0x0080*/ + uint16_t *key_len = (uint16_t *)&p_derivation_buffer[derivation_buffer_length - 2]; + *key_len = 0x0080; + + se_ret = sgx_rijndael128_cmac_msg((sgx_cmac_128bit_key_t *)&key_derive_key, + p_derivation_buffer, + derivation_buffer_length, + (sgx_cmac_128bit_tag_t *)derived_key); + memset_s(&key_derive_key, sizeof(key_derive_key), 0, sizeof(key_derive_key)); + free(p_derivation_buffer); + if(SGX_SUCCESS != se_ret) + { + INTERNAL_SGX_ERROR_CODE_CONVERTOR(se_ret); + } + return se_ret; +} diff --git a/sgx-jvm/linux-sgx/common/src/ipp_bn.cpp b/sgx-jvm/linux-sgx/common/src/ipp_bn.cpp new file mode 100644 index 0000000000..03b7cb6826 --- /dev/null +++ b/sgx-jvm/linux-sgx/common/src/ipp_bn.cpp @@ -0,0 +1,125 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + + +/** +* File: +* ipp_bn.cpp +*Description: +* Wrappers for Big number generation and free functions +* +*/ + + + +#include "ipp_wrapper.h" + +#include +#include + +#ifndef _TLIBC_CDECL_ +extern "C" int memset_s(void *s, size_t smax, int c, size_t n); +#endif + +extern "C" IppStatus + newBN(const Ipp32u *data, int size_in_bytes, IppsBigNumState **p_new_BN) +{ + IppsBigNumState *pBN=0; + int bn_size = 0; + + if(p_new_BN == NULL || size_in_bytes <= 0 || size_in_bytes % sizeof(Ipp32u)) + return ippStsBadArgErr; + + /* Get the size of the IppsBigNumState context in bytes */ + IppStatus error_code = ippsBigNumGetSize(size_in_bytes/(int)sizeof(Ipp32u), &bn_size); + if(error_code != ippStsNoErr) + { + *p_new_BN = 0; + return error_code; + } + pBN = (IppsBigNumState *) malloc(bn_size); + if(!pBN) + { + error_code = ippStsMemAllocErr; + *p_new_BN = 0; + return error_code; + } + /* Initializes context and partitions allocated buffer */ + error_code = ippsBigNumInit(size_in_bytes/(int)sizeof(Ipp32u), pBN); + if(error_code != ippStsNoErr) + { + SAFE_FREE_MM(pBN); + *p_new_BN = 0; + return error_code; + } + if(data) + { + error_code = ippsSet_BN(IppsBigNumPOS, size_in_bytes/(int)sizeof(Ipp32u), data, pBN); + if(error_code != ippStsNoErr) + { + SAFE_FREE_MM(pBN); + *p_new_BN = 0; + return error_code; + } + } + *p_new_BN = pBN; + return error_code; + +} + + +extern "C" void secure_free_BN(IppsBigNumState *pBN, int size_in_bytes) +{ + if(pBN == NULL || size_in_bytes <= 0 || size_in_bytes % sizeof(Ipp32u)) + { + if(pBN) + { + free(pBN); + } + return; + } + + int bn_size = 0; + + /* Get the size of the IppsBigNumState context in bytes + * Since we have checked the size_in_bytes before and the &bn_size is not NULL, + * ippsBigNumGetSize never returns failure + */ + if(ippsBigNumGetSize(size_in_bytes/(int)sizeof(Ipp32u), &bn_size) != ippStsNoErr) + { + free(pBN); + return; + } + /* Clear the buffer before free. */ + memset_s(pBN, bn_size, 0, bn_size); + free(pBN); + return; +} diff --git a/sgx-jvm/linux-sgx/common/src/ipp_rsa_key.cpp b/sgx-jvm/linux-sgx/common/src/ipp_rsa_key.cpp new file mode 100644 index 0000000000..e1ccd5513e --- /dev/null +++ b/sgx-jvm/linux-sgx/common/src/ipp_rsa_key.cpp @@ -0,0 +1,351 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + + +/** +* File: +* ipp_rsa_key.cpp +*Description: +* Wrapper for rsa key operation functions (public key generation and free excluded) +* +*/ + +#include "ipp_wrapper.h" +#include "util.h" + +#include +#include +#include +#include + +extern "C" int memset_s(void *s, size_t smax, int c, size_t n); + +static IppStatus newPRNG(IppsPRNGState **pRandGen) +{ + if(pRandGen == NULL) + return ippStsBadArgErr; + int ctxSize = 0; + IppStatus error_code = ippsPRNGGetSize(&ctxSize); + if(error_code != ippStsNoErr) + return error_code; + IppsPRNGState* pCtx = (IppsPRNGState *) malloc(ctxSize); + if(pCtx == NULL) + return ippStsMemAllocErr; + + error_code = ippsPRNGInit(160, pCtx); + if(error_code != ippStsNoErr) + { + free(pCtx); + return error_code; + } + + *pRandGen = pCtx; + return error_code; +} + +static IppStatus newPrimeGen(int nMaxBits, IppsPrimeState ** pPrimeG) +{ + if(pPrimeG == NULL || nMaxBits <= 0 ) + return ippStsBadArgErr; + int ctxSize = 0; + IppStatus error_code = ippsPrimeGetSize(nMaxBits, &ctxSize); + if(error_code != ippStsNoErr) + return error_code; + IppsPrimeState* pCtx = (IppsPrimeState *) malloc(ctxSize); + if(pCtx == NULL) + return ippStsMemAllocErr; + + error_code = ippsPrimeInit(nMaxBits, pCtx); + if(error_code != ippStsNoErr) + { + free(pCtx); + return error_code; + } + + *pPrimeG = pCtx; + return error_code; +} + + +extern "C" IppStatus create_rsa_priv2_key(int p_byte_size, const Ipp32u *p, const Ipp32u *q, + const Ipp32u *dmp1, const Ipp32u *dmq1, const Ipp32u *iqmp, + IppsRSAPrivateKeyState **new_pri_key2) +{ + IppsRSAPrivateKeyState *p_rsa2 = NULL; + IppsBigNumState *p_p = NULL, *p_q = NULL, *p_dmp1 = NULL, *p_dmq1 = NULL, *p_iqmp = NULL; + int rsa2_size = 0; + + if(p_byte_size <= 0 || p == NULL || q == NULL || dmp1 == NULL || dmq1 == NULL || iqmp == NULL || new_pri_key2 == NULL) + { + return ippStsBadArgErr; + } + + IppStatus error_code = ippStsNoErr; + do{ + error_code = newBN(p, p_byte_size, &p_p); + ERROR_BREAK(error_code); + error_code = newBN(q, p_byte_size, &p_q); + ERROR_BREAK(error_code); + error_code = newBN(dmp1, p_byte_size, &p_dmp1); + ERROR_BREAK(error_code); + error_code = newBN(dmq1, p_byte_size, &p_dmq1); + ERROR_BREAK(error_code); + error_code = newBN(iqmp, p_byte_size, &p_iqmp); + ERROR_BREAK(error_code); + error_code = ippsRSA_GetSizePrivateKeyType2(p_byte_size * 8, p_byte_size * 8, &rsa2_size); + ERROR_BREAK(error_code); + p_rsa2 = (IppsRSAPrivateKeyState *)malloc(rsa2_size); + NULL_BREAK(p_rsa2); + + error_code = ippsRSA_InitPrivateKeyType2(p_byte_size * 8, p_byte_size * 8, p_rsa2, rsa2_size); + ERROR_BREAK(error_code); + error_code = ippsRSA_SetPrivateKeyType2(p_p, p_q, p_dmp1, p_dmq1, p_iqmp, p_rsa2); + ERROR_BREAK(error_code); + }while(0); + + secure_free_BN(p_p, p_byte_size); + secure_free_BN(p_q, p_byte_size); + secure_free_BN(p_dmp1, p_byte_size); + secure_free_BN(p_dmq1, p_byte_size); + secure_free_BN(p_iqmp, p_byte_size); + + if(error_code != ippStsNoErr || p_rsa2 == NULL) + { + if(error_code == ippStsNoErr ) + error_code = ippStsMemAllocErr; + + /* Clear sensitive data before free */ + secure_free_rsa_pri2_key(p_byte_size, p_rsa2); + return error_code; + } + + *new_pri_key2 = p_rsa2; + return error_code; +} + +extern "C" IppStatus create_rsa_priv1_key(int n_byte_size, int d_byte_size, const Ipp32u *n, const Ipp32u *d, IppsRSAPrivateKeyState **new_pri_key1) +{ + IppsRSAPrivateKeyState *p_rsa1 = NULL; + IppsBigNumState *p_n = NULL, *p_d = NULL; + int rsa1_size = 0; + if(n_byte_size <= 0 || d_byte_size <= 0 || n == NULL || d == NULL || new_pri_key1 == NULL) + { + return ippStsBadArgErr; + } + IppStatus error_code = ippStsNoErr; + do{ + error_code = newBN(n, n_byte_size, &p_n); + ERROR_BREAK(error_code); + error_code = newBN(d, d_byte_size, &p_d); + ERROR_BREAK(error_code); + + error_code = ippsRSA_GetSizePrivateKeyType1(n_byte_size * 8, d_byte_size * 8, &rsa1_size); + ERROR_BREAK(error_code); + p_rsa1 = (IppsRSAPrivateKeyState *)malloc(rsa1_size); + NULL_BREAK(p_rsa1); + error_code = ippsRSA_InitPrivateKeyType1(n_byte_size * 8, d_byte_size * 8, p_rsa1, rsa1_size); + ERROR_BREAK(error_code); + error_code = ippsRSA_SetPrivateKeyType1(p_n, p_d, p_rsa1); + ERROR_BREAK(error_code); + }while(0); + secure_free_BN(p_n, n_byte_size); + secure_free_BN(p_d, d_byte_size); + if(error_code != ippStsNoErr || p_rsa1 == NULL) + { + if(error_code == ippStsNoErr ) + error_code = ippStsMemAllocErr; + + /* Clear sensitive data before free */ + secure_free_rsa_pri1_key(n_byte_size, d_byte_size, p_rsa1); + return error_code; + } + + *new_pri_key1 = p_rsa1; + return error_code; +} + + +extern "C" IppStatus create_validate_rsa_key_pair(int n_byte_size, int e_byte_size, const Ipp32u *n, const Ipp32u *d, const Ipp32u *e, const Ipp32u *p, const Ipp32u *q, + const Ipp32u *dmp1, const Ipp32u *dmq1, const Ipp32u *iqmp, + IppsRSAPrivateKeyState **new_pri_key, IppsRSAPublicKeyState **new_pub_key, int *validate_result) +{ + if(n_byte_size <= 0 || e_byte_size <= 0 || n == NULL || d == NULL || e == NULL || + p == NULL || q == NULL || dmp1 == NULL || dmq1 == NULL || iqmp == NULL || new_pri_key == NULL || + new_pub_key == NULL || validate_result == NULL) + { + return ippStsBadArgErr; + } + IppsRSAPrivateKeyState *p_pri_key1 = NULL, *p_pri_key2 = NULL; + IppsRSAPublicKeyState *p_pub_key = NULL; + IppStatus error_code = ippStsNoErr; + IppsPRNGState *p_rand = NULL; + IppsPrimeState *p_prime = NULL; + Ipp8u * scratch_buffer = NULL; + int result = IPP_IS_VALID; + int max_size = 0, pri1_size = 0, pri2_size = 0, pub_size = 0; + + do + { + /* Generate the pri_key1, pri_key2 and pub_key */ + error_code = create_rsa_priv1_key(n_byte_size, n_byte_size, n, d, &p_pri_key1); + ERROR_BREAK(error_code); + error_code = create_rsa_priv2_key(n_byte_size/2, p, q, dmp1, dmq1, iqmp, &p_pri_key2); + ERROR_BREAK(error_code); + error_code = create_rsa_pub_key(n_byte_size, e_byte_size, n, e, &p_pub_key); + ERROR_BREAK(error_code); + + /* Generate random state and prime state */ + error_code = newPRNG(&p_rand); + ERROR_BREAK(error_code); + error_code = newPrimeGen(n_byte_size * 8 / 2, &p_prime); + ERROR_BREAK(error_code); + + /* Allocate scratch buffer */ + error_code = ippsRSA_GetBufferSizePrivateKey(&pri1_size, p_pri_key1); + ERROR_BREAK(error_code); + error_code = ippsRSA_GetBufferSizePrivateKey(&pri2_size, p_pri_key2); + ERROR_BREAK(error_code); + max_size = MAX(pri1_size, pri2_size); + error_code = ippsRSA_GetBufferSizePublicKey(&pub_size, p_pub_key); + ERROR_BREAK(error_code); + max_size = MAX(max_size, pub_size); + scratch_buffer = (Ipp8u *)malloc(max_size); + NULL_BREAK(scratch_buffer); + memset(scratch_buffer, 0, max_size); + + /* Validate keys */ + error_code = ippsRSA_ValidateKeys(&result, p_pub_key, p_pri_key2, p_pri_key1, scratch_buffer, 10, p_prime, ippsPRNGen, p_rand); + ERROR_BREAK(error_code); + }while(0); + SAFE_FREE_MM(p_rand); + SAFE_FREE_MM(p_prime); + secure_free_rsa_pri2_key(n_byte_size/2, p_pri_key2); + + if(error_code != ippStsNoErr || scratch_buffer == NULL) + { + if(error_code == ippStsNoErr) + error_code = ippStsMemAllocErr; + + SAFE_FREE_MM(scratch_buffer); + secure_free_rsa_pri1_key(n_byte_size, n_byte_size, p_pri_key1); + secure_free_rsa_pub_key(n_byte_size, e_byte_size, p_pub_key); + return error_code; + } + SAFE_FREE_MM(scratch_buffer); + *new_pri_key = p_pri_key1; + *new_pub_key = p_pub_key; + *validate_result = result; + return error_code; +} + +extern "C" IppStatus get_pub_key(const IppsRSAPublicKeyState *pub_key, int *e_byte_size, Ipp32u *e, int *n_byte_size, Ipp32u *n) +{ + IppStatus error_code = ippStsNoErr; + IppsBigNumState *p_n=NULL, *p_e=NULL; + + if(!pub_key || !e_byte_size || !e || !n_byte_size || !n) + { + return ippStsBadArgErr; + } + do + { + error_code = newBN(NULL, SE_KEY_SIZE, &p_n); + ERROR_BREAK(error_code); + error_code = newBN(NULL, sizeof(Ipp32u), &p_e); + ERROR_BREAK(error_code); + + error_code = ippsRSA_GetPublicKey(p_n, p_e, pub_key); + ERROR_BREAK(error_code); + + IppsBigNumSGN sgn = IppsBigNumPOS; + Ipp32u *pdata = NULL; + int length_in_bit = 0; + + + error_code = ippsRef_BN(&sgn, &length_in_bit, &pdata, p_n); + ERROR_BREAK(error_code); + *n_byte_size = ROUND_TO(length_in_bit, 8)/8; + memset(n, 0, *n_byte_size); + memcpy(n, pdata, ROUND_TO(length_in_bit, 8)/8); + + error_code = ippsRef_BN(&sgn, &length_in_bit, &pdata, p_e); + ERROR_BREAK(error_code); + *e_byte_size = ROUND_TO(length_in_bit, 8)/8; + memset(e, 0, *e_byte_size); + memcpy(e, pdata, ROUND_TO(length_in_bit, 8)/8); + } while(0); + + secure_free_BN(p_n, SE_KEY_SIZE); + secure_free_BN(p_e, sizeof(Ipp32u)); + return error_code; +} + +extern "C" void secure_free_rsa_pri1_key(int n_byte_size, int d_byte_size, IppsRSAPrivateKeyState *pri_key1) +{ + if(n_byte_size <= 0 || d_byte_size <= 0 || pri_key1 == NULL) + { + if(pri_key1) + free(pri_key1); + return; + } + + int rsa1_size = 0; + if(ippsRSA_GetSizePrivateKeyType1(n_byte_size * 8, d_byte_size * 8, &rsa1_size) != ippStsNoErr) + { + free(pri_key1); + return; + } + /* Clear the buffer before free. */ + memset_s(pri_key1, rsa1_size, 0, rsa1_size); + free(pri_key1); + return; +} + +extern "C" void secure_free_rsa_pri2_key(int p_byte_size, IppsRSAPrivateKeyState *pri_key2) +{ + if(p_byte_size <= 0 || pri_key2 == NULL) + { + if(pri_key2) + free(pri_key2); + return; + } + + int rsa2_size = 0; + if(ippsRSA_GetSizePrivateKeyType2(p_byte_size * 8, p_byte_size * 8, &rsa2_size) != ippStsNoErr) + { + free(pri_key2); + return; + } + /* Clear the buffer before free. */ + memset_s(pri_key2, rsa2_size, 0, rsa2_size); + free(pri_key2); + return; +} diff --git a/sgx-jvm/linux-sgx/common/src/ipp_rsa_pub_key.cpp b/sgx-jvm/linux-sgx/common/src/ipp_rsa_pub_key.cpp new file mode 100644 index 0000000000..dfc3fc3488 --- /dev/null +++ b/sgx-jvm/linux-sgx/common/src/ipp_rsa_pub_key.cpp @@ -0,0 +1,110 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + + +/** +* File: +* ipp_rsa_pub_key.cpp +*Description: +* Wrapper for rsa public key generation and free +* +*/ + +#include "ipp_wrapper.h" + +#include +#include + +#ifndef _TLIBC_CDECL_ +extern "C" int memset_s(void *s, size_t smax, int c, size_t n); +#endif + +extern "C" IppStatus create_rsa_pub_key(int n_byte_size, int e_byte_size, const Ipp32u *n, const Ipp32u *e, IppsRSAPublicKeyState **new_pub_key) +{ + IppsRSAPublicKeyState *p_pub_key = NULL; + IppsBigNumState *p_n = NULL, *p_e = NULL; + int rsa_size = 0; + if(n_byte_size <= 0 || e_byte_size <= 0 || n == NULL || e == NULL || new_pub_key == NULL) + { + return ippStsBadArgErr; + } + + IppStatus error_code = ippStsNoErr; + do{ + error_code = newBN(n, n_byte_size, &p_n); + ERROR_BREAK(error_code); + error_code = newBN(e, e_byte_size, &p_e); + ERROR_BREAK(error_code); + + error_code = ippsRSA_GetSizePublicKey(n_byte_size * 8, e_byte_size * 8, &rsa_size); + ERROR_BREAK(error_code); + p_pub_key = (IppsRSAPublicKeyState *)malloc(rsa_size); + NULL_BREAK(p_pub_key); + error_code = ippsRSA_InitPublicKey(n_byte_size * 8, e_byte_size * 8, p_pub_key, rsa_size); + ERROR_BREAK(error_code); + error_code = ippsRSA_SetPublicKey(p_n, p_e, p_pub_key); + ERROR_BREAK(error_code); + }while(0); + secure_free_BN(p_n, n_byte_size); + secure_free_BN(p_e, e_byte_size); + if(error_code != ippStsNoErr || p_pub_key == NULL) + { + if(error_code == ippStsNoErr ) + error_code = ippStsMemAllocErr; + + secure_free_rsa_pub_key(n_byte_size, e_byte_size, p_pub_key); + return error_code; + } + + *new_pub_key = p_pub_key; + return error_code; + +} + +extern "C" void secure_free_rsa_pub_key(int n_byte_size, int e_byte_size, IppsRSAPublicKeyState *pub_key) +{ + if(n_byte_size <= 0 || e_byte_size <= 0 || pub_key == NULL) + { + if(pub_key) + free(pub_key); + return; + } + int rsa_size = 0; + if(ippsRSA_GetSizePublicKey(n_byte_size * 8, e_byte_size * 8, &rsa_size) != ippStsNoErr) + { + free(pub_key); + return; + } + /* Clear the buffer before free. */ + memset_s(pub_key, rsa_size, 0, rsa_size); + free(pub_key); + return; +} diff --git a/sgx-jvm/linux-sgx/common/src/se_event.c b/sgx-jvm/linux-sgx/common/src/se_event.c new file mode 100644 index 0000000000..132e48b204 --- /dev/null +++ b/sgx-jvm/linux-sgx/common/src/se_event.c @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + + +#include "se_event.h" + +#include + +se_handle_t se_event_init(void) +{ + return calloc(1, sizeof(int)); +} + +void se_event_destroy(se_handle_t se_event) +{ + if (se_event != NULL) + free(se_event); +} + +int se_event_wait(se_handle_t se_event) +{ + if (se_event == NULL) + return SE_MUTEX_INVALID; + + if (__sync_fetch_and_add((int*)se_event, -1) == 0) + syscall(__NR_futex, se_event, FUTEX_WAIT, -1, NULL, NULL, 0); + + return SE_MUTEX_SUCCESS; +} + +int se_event_wake(se_handle_t se_event) +{ + if (se_event == NULL) + return SE_MUTEX_INVALID; + + if (__sync_fetch_and_add((int*)se_event, 1) != 0) + syscall(__NR_futex, se_event, FUTEX_WAKE, 1, NULL, NULL, 0); + + return SE_MUTEX_SUCCESS; +} diff --git a/sgx-jvm/linux-sgx/common/src/se_map.c b/sgx-jvm/linux-sgx/common/src/se_map.c new file mode 100644 index 0000000000..687d035012 --- /dev/null +++ b/sgx-jvm/linux-sgx/common/src/se_map.c @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + + + +#include "se_map.h" +#include "se_trace.h" +#include + +map_handle_t* map_file(se_file_handle_t fd, uint32_t *size) +{ + struct stat st; + memset(&st, 0, sizeof(st)); + if (-1 == fstat(fd, &st)) + return NULL; + + map_handle_t* mh = (map_handle_t *)calloc(1, sizeof(map_handle_t)); + if (mh == NULL) + return NULL; + + mh->base_addr = (uint8_t *)mmap(NULL, (size_t)st.st_size, + PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0); + if(MAP_FAILED == mh->base_addr) + { + free(mh); + SE_TRACE(SE_TRACE_WARNING, "Couldn't map view of file, error code %x\n", errno); + return NULL; + } + + mh->length = (size_t)st.st_size; + if (size) *size = (uint32_t)st.st_size; + return mh; +} + +void unmap_file(map_handle_t* mh) +{ + munmap(mh->base_addr, mh->length); + free(mh); +} + + diff --git a/sgx-jvm/linux-sgx/common/src/se_memory.c b/sgx-jvm/linux-sgx/common/src/se_memory.c new file mode 100644 index 0000000000..d860b6bc34 --- /dev/null +++ b/sgx-jvm/linux-sgx/common/src/se_memory.c @@ -0,0 +1,153 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + + + +#include "se_memory.h" +#include "se_trace.h" +#include "util.h" + +void* se_virtual_alloc(void* address, size_t size, uint32_t type) +{ + UNUSED(type); + void* pRet = mmap(address, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + if(MAP_FAILED == pRet) + return NULL; + return pRet; +} + +int se_virtual_free(void* address, size_t size, uint32_t type) +{ + UNUSED(type); + + return !(munmap(address, size)); + +} + +int se_virtual_lock(void* address, size_t size) +{ + return !mlock(address, size); +} + +static unsigned int get_prot(uint64_t flags) +{ + if ((flags & SI_FLAG_PT_MASK) == SI_FLAG_TCS) + return PROT_READ|PROT_WRITE|PROT_EXEC; + + switch (flags & (SI_FLAG_R | SI_FLAG_W | SI_FLAG_X)) + { + case SI_FLAG_X: return PROT_EXEC; break; + case SI_FLAG_R | SI_FLAG_X: return PROT_READ|PROT_EXEC; break; + case SI_FLAG_R | SI_FLAG_W | SI_FLAG_X: return PROT_READ|PROT_WRITE|PROT_EXEC; break; + case SI_FLAG_R: return PROT_READ; break; + case SI_FLAG_R | SI_FLAG_W: return PROT_READ|PROT_WRITE; break; + /* This covers no access, W and WX */ + default: return PROT_NONE; break; + } + +} +int se_virtual_protect(void* address, size_t size, uint32_t prot) +{ + return !mprotect(address, size, (int)get_prot(prot)); +} + +se_proc_t get_self_proc() +{ + return getpid(); +} + +int put_self_proc(se_proc_t proc) +{ + UNUSED(proc); + return 1; +} + +int se_read_process_mem(se_proc_t proc, void* base_addr, void* buffer, size_t size, size_t* read_nr) +{ + char filename[64]; + int fd = -1; + int ret = FALSE; + ssize_t len = 0; + off64_t offset = (off64_t)(size_t) base_addr; + + snprintf (filename, 64, "/proc/%d/mem", (int)proc); + fd = open(filename, O_RDONLY | O_LARGEFILE); + if(fd == -1) + return FALSE; + + if(lseek64(fd, offset, SEEK_SET) == -1) + { + goto out; + } + if((len = read(fd, buffer, size)) < 0) + { + goto out; + } + else if(read_nr) + *read_nr = (size_t)len; /* len is a non-negative number */ + + ret = TRUE; + +out: + close (fd); + return ret; +} + +int se_write_process_mem(se_proc_t proc, void* base_addr, void* buffer, size_t size, size_t* write_nr) +{ + char filename[64]; + int fd = -1; + int ret = FALSE; + ssize_t len = 0; + off64_t offset = (off64_t)(size_t)base_addr; + + snprintf (filename, 64, "/proc/%d/mem", (int)proc); + fd = open(filename, O_RDWR | O_LARGEFILE); + if(fd == -1) + return FALSE; + + if(lseek64(fd, offset, SEEK_SET) == -1) + { + goto out; + } + if((len = write(fd, buffer, size)) < 0) + { + goto out; + } + else if(write_nr) + *write_nr = (size_t)len; /* len is a non-negative number */ + + ret = TRUE; +out: + close (fd); + return ret; +} + diff --git a/sgx-jvm/linux-sgx/common/src/se_rwlock.c b/sgx-jvm/linux-sgx/common/src/se_rwlock.c new file mode 100644 index 0000000000..9164a123f7 --- /dev/null +++ b/sgx-jvm/linux-sgx/common/src/se_rwlock.c @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + + +#include "se_rwlock.h" +#include "internal/util.h" + + +#include +void se_wtlock(se_prwlock_t lock) +{ + int ret = pthread_rwlock_wrlock(lock); + if(0 != ret) + abort(); +} + +void se_wtunlock(se_prwlock_t lock) +{ + int ret = pthread_rwlock_unlock(lock); + if(0 != ret) + abort(); +} + +int se_try_rdlock(se_prwlock_t lock) +{ + return (0 == pthread_rwlock_tryrdlock(lock)); +} + +void se_rdlock(se_prwlock_t lock) +{ + int ret = pthread_rwlock_rdlock(lock); + if(0 != ret) + abort(); +} + +void se_rdunlock(se_prwlock_t lock) +{ + int ret = pthread_rwlock_unlock(lock); + if(0 != ret) + abort(); +} + +void se_init_rwlock(se_prwlock_t lock) +{ + /* use the default attribute. */ + int ret = pthread_rwlock_init(lock, NULL); + if(0 != ret) + abort(); +} + +void se_fini_rwlock(se_prwlock_t lock) +{ + int ret = pthread_rwlock_destroy(lock); + if(0 != ret) + abort(); +} + diff --git a/sgx-jvm/linux-sgx/common/src/se_thread.c b/sgx-jvm/linux-sgx/common/src/se_thread.c new file mode 100644 index 0000000000..b188a049d1 --- /dev/null +++ b/sgx-jvm/linux-sgx/common/src/se_thread.c @@ -0,0 +1,87 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include "se_thread.h" +#include "se_types.h" + +void se_mutex_init(se_mutex_t* mutex) +{ +#ifdef PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP + se_mutex_t tmp = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP; +#elif defined(PTHREAD_RECURSIVE_MUTEX_INITIALIZER) + se_mutex_t tmp = PTHREAD_RECURSIVE_MUTEX_INITIALIZER; +#else +#error no pre-defined RECURSIVE_MUTEX found. +#endif + + /* C doesn't allow `*mutex = PTHREAD_..._INITIALIZER'.*/ + memcpy(mutex, &tmp, sizeof(tmp)); +} + +int se_mutex_lock(se_mutex_t* mutex) { return (0 == pthread_mutex_lock(mutex)); } +int se_mutex_unlock(se_mutex_t* mutex) { return (0 == pthread_mutex_unlock(mutex)); } +int se_mutex_destroy(se_mutex_t* mutex) { return (0 == pthread_mutex_destroy(mutex));} + +unsigned int se_get_threadid(void) { return (unsigned)syscall(__NR_gettid);} +/* tls functions */ +int se_tls_alloc(se_tls_index_t *tls_index) { return !pthread_key_create(tls_index, NULL); } +int se_tls_free(se_tls_index_t tls_index) { return !pthread_key_delete(tls_index); } +void * se_tls_get_value(se_tls_index_t tls_index) { return pthread_getspecific(tls_index); } +int se_tls_set_value(se_tls_index_t tls_index, void *tls_value) { return !pthread_setspecific(tls_index, tls_value); } +/* +se_thread_handle_t se_create_thread(size_t stack_size, thread_start_routine_t start_routine, void *param, se_thread_t *thread) +{ + pthread_attr_t attr, *attr_ptr = NULL; + int ret; + + if(stack_size > 0) + { + ret = pthread_attr_init(&attr); + if(ret) + return NULL; + ret = pthread_attr_setstacksize(&attr, stack_size); + if(ret) + return NULL; + attr_ptr = &attr; + } + else + { + attr_ptr = NULL; + } + ret = pthread_create(thread, attr_ptr, start_routine, param); + if(ret) + return NULL; + if(attr_ptr) + pthread_attr_destroy(&attr); + + return thread; + +} +*/ diff --git a/sgx-jvm/linux-sgx/common/src/se_time.c b/sgx-jvm/linux-sgx/common/src/se_time.c new file mode 100644 index 0000000000..20bc84fc38 --- /dev/null +++ b/sgx-jvm/linux-sgx/common/src/se_time.c @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + + +#include "se_time.h" + + +#include +#include +void se_sleep(uint32_t milli_seconds) +{ + usleep(milli_seconds * 1000); +} + +uint64_t se_get_tick_count_freq(void) +{ + return 1000000000ULL; +} + +uint64_t se_get_tick_count(void) +{ + struct timespec tm; + if (clock_gettime(CLOCK_MONOTONIC, &tm) != 0) + return 0; + return ((uint64_t)tm.tv_sec * 1000000000ULL) + ((uint64_t)tm.tv_nsec ); +} diff --git a/sgx-jvm/linux-sgx/common/src/se_trace.c b/sgx-jvm/linux-sgx/common/src/se_trace.c new file mode 100644 index 0000000000..ff81de827d --- /dev/null +++ b/sgx-jvm/linux-sgx/common/src/se_trace.c @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + + +#include "se_trace.h" +#include +int se_trace_internal(int debug_level, const char *fmt, ...) +{ + va_list args; + int ret = 0; + + va_start(args, fmt); + if(SE_TRACE_NOTICE == debug_level) + ret = vfprintf(stdout, fmt, args); + else + ret = vfprintf(stderr, fmt, args); + va_end(args); + + return ret; +} diff --git a/sgx-jvm/linux-sgx/common/src/sgx_memset_s.cpp b/sgx-jvm/linux-sgx/common/src/sgx_memset_s.cpp new file mode 100644 index 0000000000..816c1504e5 --- /dev/null +++ b/sgx-jvm/linux-sgx/common/src/sgx_memset_s.cpp @@ -0,0 +1,78 @@ +/*- + * Copyright (c) 2012 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Alan Barrett + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * ISO/IEC 9899:2011 section K.3.7.4.1 The memset_s function + */ + +#include "sgx_memset_s.h" +#include +#include +#include +/* + * __memset_vp is a volatile pointer to a function. + * It is initialised to point to memset, and should never be changed. + */ +static void * (* const volatile __memset_vp)(void *, int, size_t) + = (memset); + +#ifdef memset_s +#undef memset_s /* in case it was defined as a macro */ +#endif + +#ifdef __cplusplus +extern "C" +#endif +int memset_s(void *s, size_t smax, int c, size_t n) +{ + int err = 0; + + if (s == NULL) { + err = EINVAL; + goto out; + } + + if (n > smax) { + err = EOVERFLOW; + n = smax; + } + + /* Calling through a volatile pointer should never be optimised away. */ + (*__memset_vp)(s, c, n); + + out: + if (err == 0) + return 0; + else { + errno = err; + /* XXX call runtime-constraint handler */ + return err; + } +} + diff --git a/sgx-jvm/linux-sgx/common/src/sgx_profile.cpp b/sgx-jvm/linux-sgx/common/src/sgx_profile.cpp new file mode 100644 index 0000000000..17244cd008 --- /dev/null +++ b/sgx-jvm/linux-sgx/common/src/sgx_profile.cpp @@ -0,0 +1,149 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + + +#ifdef _PROFILE_ + +#include +#include +#include +#include "sgx_profile.h" +#include "se_time.h" +#include +using namespace std; + +typedef struct _profile_item_t{ + const char *str; /* tag */ + int flag; /* 0: start, 1: end */ + long long time; /* current time */ +} profile_item_t; + +static vector profile_items; +static int alloc_size; +static int used_size; +const int MALLOC_SIZE = 1000; +static long long freq = {0}; + +#define MALLOC_TAG "PROFILE_MALLOC_CONSUMED_TIME" + +extern "C" void profile_init() +{ + freq = se_get_tick_count_freq(); + profile_items.resize(MALLOC_SIZE); + alloc_size = MALLOC_SIZE; + used_size = 0; +} + +static void profile_add_info(const char *str, int flag) +{ + long long cur_time = se_get_tick_count(); + if(used_size==alloc_size){ + alloc_size+=MALLOC_SIZE; + profile_items.resize(alloc_size); + profile_items[used_size].flag = PRO_START; + profile_items[used_size].str = MALLOC_TAG; + profile_items[used_size].time = cur_time; + cur_time = se_get_tick_count(); + used_size++; + profile_items[used_size].flag = PRO_END; + profile_items[used_size].str = MALLOC_TAG; + profile_items[used_size].time = cur_time; + used_size++; + } + profile_items[used_size].flag = flag; + profile_items[used_size].str = str; + profile_items[used_size].time = cur_time; + used_size++; +} + +extern "C" void profile_start(const char* str) +{ + profile_add_info(str, PRO_START); +} + +extern "C" void profile_end(const char * str) +{ + profile_add_info(str, PRO_END); +} + +#include +std::string get_prof_fun_name(const char *s) +{ + std::string input(s); + size_t end = input.find("("); + size_t begin = input.substr(0,end).rfind(" ")+1; + end = end - begin; + return input.substr(begin,end); +} + +extern "C" void profile_output(const char* filename) +{ + int i,j; + + ofstream fs; + fs.open(filename); /* do not overwritten previous value */ + + fs << "freq: " << freq <str << endl; */ + return; + } + } + } + + if(j == used_size) + { + /* cout << "Error: not find end for " << it->str << endl; */ + return; + } + + fs << get_prof_fun_name(profile_items[i].str) << "," << profile_items[i].time << "," << profile_items[j].time << endl; + } + profile_items.clear(); + used_size=0; + alloc_size=0; + fs.close(); + +} +#endif diff --git a/sgx-jvm/linux-sgx/common/src/sgx_read_rand.cpp b/sgx-jvm/linux-sgx/common/src/sgx_read_rand.cpp new file mode 100644 index 0000000000..410ea6979c --- /dev/null +++ b/sgx-jvm/linux-sgx/common/src/sgx_read_rand.cpp @@ -0,0 +1,101 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + + +/* Please add external/rdrand into INCLUDE path and correpondent library to project */ + +#include +#include +#include +#include "sgx.h" +#include "sgx_defs.h" +#include "se_wrapper.h" +#include "rdrand.h" +#include "cpuid.h" +#include +#ifndef UINT32_MAX +#define UINT32_MAX 0xFFFFFFFFU +#endif + +static int g_is_rdrand_supported=-1; + +#define RDRAND_MASK 0x40000000 + +static int rdrand_cpuid() +{ + int info[4] = {-1, -1, -1, -1}; + + /* Are we on an Intel processor? */ + + __cpuid(info, 0); + + if (memcmp(&info[1], "Genu", 4) != 0 || + memcmp(&info[3], "ineI", 4) != 0 || + memcmp(&info[2], "ntel", 4) != 0 ) { + return 0; + } + + /* Do we have RDRAND? */ + + __cpuid(info, /*feature bits*/1); + + int ecx = info[2]; + if ((ecx & RDRAND_MASK) == RDRAND_MASK) + return 1; + else + return 0; +} + + +extern "C" sgx_status_t SGXAPI sgx_read_rand(uint8_t *buf, size_t size) +{ + if(buf == NULL || size == 0 || size> UINT32_MAX ){ + return SGX_ERROR_INVALID_PARAMETER; + } + if(g_is_rdrand_supported==-1){ + g_is_rdrand_supported = rdrand_cpuid(); + } + if(!g_is_rdrand_supported){ + uint32_t i; + for(i=0;i<(uint32_t)size;++i){ + buf[i]=(uint8_t)rand(); + } + }else{ + int rd_ret =rdrand_get_bytes((uint32_t)size, buf); + if(rd_ret != RDRAND_SUCCESS){ + rd_ret = rdrand_get_bytes((uint32_t)size, buf); + if(rd_ret != RDRAND_SUCCESS){ + return SGX_ERROR_UNEXPECTED; + } + } + } + return SGX_SUCCESS; +} diff --git a/sgx-jvm/linux-sgx/common/src/sgx_sha256_128.cpp b/sgx-jvm/linux-sgx/common/src/sgx_sha256_128.cpp new file mode 100644 index 0000000000..a12618b7d1 --- /dev/null +++ b/sgx-jvm/linux-sgx/common/src/sgx_sha256_128.cpp @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + + +#include "sgx_sha256_128.h" + +/* +** SHA256-128 implementation: +** out-length := x ¨C number of bits to output +** prefix := SHA-256(out-length) +** digest := SHA-256(prefix || m) +** output := truncate(digest, out-length) ? always return first out-length bits +*/ +sgx_status_t SGXAPI sgx_sha256_128_msg(const uint8_t *p_src, uint32_t src_len, sgx_sha256_128_hash_t *p_hash) +{ + uint32_t outlength = 128; /*number of bits to output */ + uint32_t sha256_128_digest_length; + sgx_status_t ret; + sgx_sha256_hash_t digest = {0}; + uint8_t* digest_buffer = NULL; + + /* check potential overflow and NULL pointer */ + if( (UINT32_MAX-src_len) < sizeof(sgx_sha256_hash_t) || !p_hash || !p_src) + return SGX_ERROR_INVALID_PARAMETER; + + sha256_128_digest_length = (uint32_t)sizeof(sgx_sha256_hash_t)+ src_len; + + digest_buffer = (uint8_t*)malloc(sha256_128_digest_length); + if(!digest_buffer) + return SGX_ERROR_OUT_OF_MEMORY; + memset(digest_buffer, 0, sha256_128_digest_length); + + /* get prefix := SHA-256(out-length) */ + ret = sgx_sha256_msg((const uint8_t*)&outlength, sizeof(uint32_t), (sgx_sha256_hash_t*)digest_buffer); + if(SGX_SUCCESS != ret) + goto clean_up; + + /* get digest := SHA-256(prefix || m) */ + memcpy(digest_buffer+sizeof(sgx_sha256_hash_t), p_src, src_len); /* copy m to digest_buffer */ + ret = sgx_sha256_msg((const uint8_t*)digest_buffer, sha256_128_digest_length, &digest); + if(SGX_SUCCESS != ret) + goto clean_up; + + /* output truncated hash + return the first 128 bits */ + memcpy(p_hash, &digest, sizeof(sgx_sha256_128_hash_t)); + +clean_up: + if(digest_buffer) + free(digest_buffer); + + return ret; +} diff --git a/sgx-jvm/linux-sgx/download_prebuilt.sh b/sgx-jvm/linux-sgx/download_prebuilt.sh new file mode 100755 index 0000000000..2d8214786e --- /dev/null +++ b/sgx-jvm/linux-sgx/download_prebuilt.sh @@ -0,0 +1,69 @@ +#!/usr/bin/env bash +# +# Copyright (C) 2011-2016 Intel Corporation. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# + + +top_dir=`dirname $0` +#out_dir=$top_dir/psw/ae/data/prebuilt +out_dir=$top_dir +optlib_name=optimized_libs-1.7.100.35958.tar +ae_file_name=prebuilt-ae-1.7.100.35958.tar +server_url_path=https://download.01.org/intel-sgx/linux-1.7/ +server_optlib_url=$server_url_path/$optlib_name +server_ae_url=$server_url_path/$ae_file_name +optlib_md5=d873e20155fceb870c2e14771cc2258a +ae_md5=ca7cf31f1e9fee06feea44732cfbc908 +rm -rf $out_dir/$optlib_name +wget $server_optlib_url -P $out_dir +if [ $? -ne 0 ]; then + echo "Fail to download file $server_optlib_url" + exit -1 +fi +md5sum $out_dir/$optlib_name > check_sum.txt +grep $optlib_md5 check_sum.txt +if [ $? -ne 0 ]; then + echo "File $server_optlib_url checksum failure" + exit -1 +fi +rm -rf $out_dir/$ae_file_name +wget $server_ae_url -P $out_dir +if [ $? -ne 0 ]; then + echo "Fail to download file $server_ae_url" + exit -1 +fi +md5sum $out_dir/$ae_file_name > check_sum.txt +grep $ae_md5 check_sum.txt +if [ $? -ne 0 ]; then + echo "File $server_optlib_url checksum failure" + exit -1 +fi + +pushd $out_dir;tar -xf $optlib_name;tar -xf $ae_file_name;rm -f $optlib_name;rm -f $ae_file_name;popd diff --git a/sgx-jvm/linux-sgx/external/crypto_px/Makefile b/sgx-jvm/linux-sgx/external/crypto_px/Makefile new file mode 100644 index 0000000000..6739cdaf32 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/crypto_px/Makefile @@ -0,0 +1,62 @@ +# +# Copyright (C) 2011-2016 Intel Corporation. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# + +include ../../buildenv.mk + +CFLAGS += -fPIC -D_PX +ifeq ($(ARCH), x86_64) + CFLAGS += -D_ARCH_EM64T +else + CFLAGS += -D_ARCH_IA32 +endif + +INC := -I./include \ + -I./sources/include \ + -I./sources/ippcp/src + +SRCS := $(wildcard ./sources/ippcp/src/*.c) +OBJS := $(SRCS:.c=.o) + +libcrypto_px.a: $(OBJS) + ar crv $@ $^ + +%.o :%.c + $(CC) -c $(INC) $(CFLAGS) $< -o $@ + +.PHONY: all +all: libcrypto_px.a + +.PHONY: clean +clean: + @$(RM) $(OBJS) libcrypto_px.a + +.PHONY: rebuild +rebuild: clean all diff --git a/sgx-jvm/linux-sgx/external/crypto_px/include/ippbase.h b/sgx-jvm/linux-sgx/external/crypto_px/include/ippbase.h new file mode 100755 index 0000000000..202cda8f26 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/crypto_px/include/ippbase.h @@ -0,0 +1,195 @@ +/* +* Copyright (C) 2016 Intel Corporation. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in +* the documentation and/or other materials provided with the +* distribution. +* * Neither the name of Intel Corporation nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ + +#ifndef __IPPBASE_H__ +#define __IPPBASE_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined( _WIN32 ) || defined ( _WIN64 ) + #define __STDCALL __stdcall + #define __CDECL __cdecl + #define __INT64 __int64 + #define __UINT64 unsigned __int64 +#else + #define __STDCALL + #define __CDECL + #define __INT64 long long + #define __UINT64 unsigned long long +#endif + +#define IPP_PI ( 3.14159265358979323846 ) /* ANSI C does not support M_PI */ +#define IPP_2PI ( 6.28318530717958647692 ) /* 2*pi */ +#define IPP_PI2 ( 1.57079632679489661923 ) /* pi/2 */ +#define IPP_PI4 ( 0.78539816339744830961 ) /* pi/4 */ +#define IPP_PI180 ( 0.01745329251994329577 ) /* pi/180 */ +#define IPP_RPI ( 0.31830988618379067154 ) /* 1/pi */ +#define IPP_SQRT2 ( 1.41421356237309504880 ) /* sqrt(2) */ +#define IPP_SQRT3 ( 1.73205080756887729353 ) /* sqrt(3) */ +#define IPP_LN2 ( 0.69314718055994530942 ) /* ln(2) */ +#define IPP_LN3 ( 1.09861228866810969139 ) /* ln(3) */ +#define IPP_E ( 2.71828182845904523536 ) /* e */ +#define IPP_RE ( 0.36787944117144232159 ) /* 1/e */ +#define IPP_EPS23 ( 1.19209289e-07f ) +#define IPP_EPS52 ( 2.2204460492503131e-016 ) + +#define IPP_MAX_8U ( 0xFF ) +#define IPP_MAX_16U ( 0xFFFF ) +#define IPP_MAX_32U ( 0xFFFFFFFF ) +#define IPP_MIN_8U ( 0 ) +#define IPP_MIN_16U ( 0 ) +#define IPP_MIN_32U ( 0 ) +#define IPP_MIN_8S (-128 ) +#define IPP_MAX_8S ( 127 ) +#define IPP_MIN_16S (-32768 ) +#define IPP_MAX_16S ( 32767 ) +#define IPP_MIN_32S (-2147483647 - 1 ) +#define IPP_MAX_32S ( 2147483647 ) +#define IPP_MIN_64U ( 0 ) + +#if defined( _WIN32 ) || defined ( _WIN64 ) + #define IPP_MAX_64S ( 9223372036854775807i64 ) + #define IPP_MIN_64S (-9223372036854775807i64 - 1 ) + #define IPP_MAX_64U ( 0xffffffffffffffffL ) /* 18446744073709551615 */ +#else + #define IPP_MAX_64S ( 9223372036854775807LL ) + #define IPP_MIN_64S (-9223372036854775807LL - 1 ) + #define IPP_MAX_64U ( 0xffffffffffffffffLL ) /* 18446744073709551615 */ +#endif + +#define IPP_MINABS_32F ( 1.175494351e-38f ) +#define IPP_MAXABS_32F ( 3.402823466e+38f ) +#define IPP_EPS_32F ( 1.192092890e-07f ) +#define IPP_MINABS_64F ( 2.2250738585072014e-308 ) +#define IPP_MAXABS_64F ( 1.7976931348623158e+308 ) +#define IPP_EPS_64F ( 2.2204460492503131e-016 ) + +#define IPP_MAX( a, b ) ( ((a) > (b)) ? (a) : (b) ) +#define IPP_MIN( a, b ) ( ((a) < (b)) ? (a) : (b) ) + +#define IPP_ABS( a ) ( ((a) < 0) ? (-(a)) : (a) ) + +typedef struct { + int major; /* e.g. 1 */ + int minor; /* e.g. 2 */ + int majorBuild; /* e.g. 3 */ + int build; /* e.g. 10, always >= majorBuild */ + char targetCpu[4]; /* corresponding to Intel(R) processor */ + const char* Name; /* e.g. "ippsw7" */ + const char* Version; /* e.g. "v1.2 Beta" */ + const char* BuildDate; /* e.g. "Jul 20 99" */ +} IppLibraryVersion; + +typedef unsigned char Ipp8u; +typedef unsigned short Ipp16u; +typedef unsigned int Ipp32u; +typedef signed char Ipp8s; +typedef signed short Ipp16s; +typedef signed int Ipp32s; +typedef float Ipp32f; +typedef __INT64 Ipp64s; +typedef __UINT64 Ipp64u; +typedef double Ipp64f; +typedef Ipp16s Ipp16f; + +typedef struct { + Ipp8s re; + Ipp8s im; +} Ipp8sc; + +typedef struct { + Ipp16s re; + Ipp16s im; +} Ipp16sc; + +typedef struct { + Ipp16u re; + Ipp16u im; +} Ipp16uc; + +typedef struct { + Ipp32s re; + Ipp32s im; +} Ipp32sc; + +typedef struct { + Ipp32f re; + Ipp32f im; +} Ipp32fc; + +typedef struct { + Ipp64s re; + Ipp64s im; +} Ipp64sc; + +typedef struct { + Ipp64f re; + Ipp64f im; +} Ipp64fc; + +typedef enum { + ippUndef = -1, + ipp1u = 0, + ipp8u = 1, + ipp8uc = 2, + ipp8s = 3, + ipp8sc = 4, + ipp16u = 5, + ipp16uc = 6, + ipp16s = 7, + ipp16sc = 8, + ipp32u = 9, + ipp32uc = 10, + ipp32s = 11, + ipp32sc = 12, + ipp32f = 13, + ipp32fc = 14, + ipp64u = 15, + ipp64uc = 16, + ipp64s = 17, + ipp64sc = 18, + ipp64f = 19, + ipp64fc = 20 +} IppDataType; + +typedef enum { + ippFalse = 0, + ippTrue = 1 +} IppBool; + +#ifdef __cplusplus +} +#endif + +#endif /* __IPPBASE_H__ */ + diff --git a/sgx-jvm/linux-sgx/external/crypto_px/include/ippcore.h b/sgx-jvm/linux-sgx/external/crypto_px/include/ippcore.h new file mode 100755 index 0000000000..ec5185923c --- /dev/null +++ b/sgx-jvm/linux-sgx/external/crypto_px/include/ippcore.h @@ -0,0 +1,395 @@ +/* +* Copyright (C) 2016 Intel Corporation. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in +* the documentation and/or other materials provided with the +* distribution. +* * Neither the name of Intel Corporation nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ + +#if !defined( __IPPCORE_H__ ) || defined( _OWN_BLDPCS ) +#define __IPPCORE_H__ + +#if defined (_WIN32_WCE) && defined (_M_IX86) && defined (__stdcall) + #define _IPP_STDCALL_CDECL + #undef __stdcall +#endif + +#ifndef __IPPDEFS_H__ + #include "ippdefs.h" +#endif + +#ifdef __cplusplus +extern "C" { +#endif + + +#if !defined( _IPP_NO_DEFAULT_LIB ) + #if defined( _IPP_SEQUENTIAL_DYNAMIC ) + #pragma comment( lib, __FILE__ "/../../lib/" _INTEL_PLATFORM "ippcore" ) + #elif defined( _IPP_SEQUENTIAL_STATIC ) + #pragma comment( lib, __FILE__ "/../../lib/" _INTEL_PLATFORM "ippcoremt" ) + #elif defined( _IPP_PARALLEL_DYNAMIC ) + #pragma comment( lib, __FILE__ "/../../lib/" _INTEL_PLATFORM "threaded/ippcore" ) + #elif defined( _IPP_PARALLEL_STATIC ) + #pragma comment( lib, __FILE__ "/../../lib/" _INTEL_PLATFORM "threaded/ippcoremt" ) + #endif +#endif + +/* ///////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Functions declarations +//////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// */ + + +/* ///////////////////////////////////////////////////////////////////////////// +// Name: ippGetLibVersion +// Purpose: getting of the library version +// Returns: the structure of information about version +// of ippcore library +// Parameters: +// +// Notes: not necessary to release the returned structure +*/ +IPPAPI( const IppLibraryVersion*, ippGetLibVersion, (void) ) + + +/* ///////////////////////////////////////////////////////////////////////////// +// Name: ippGetStatusString +// Purpose: convert the library status code to a readable string +// Parameters: +// StsCode IPP status code +// Returns: pointer to string describing the library status code +// +// Notes: don't free the pointer +*/ +IPPAPI( const char*, ippGetStatusString, ( IppStatus StsCode ) ) + + + +/* ///////////////////////////////////////////////////////////////////////////// +// Name: ippGetCpuClocks +// Purpose: reading of time stamp counter (TSC) register value +// Returns: TSC value +// +// Note: An hardware exception is possible if TSC reading is not supported by +/ the current chipset +*/ + +IPPAPI( Ipp64u, ippGetCpuClocks, (void) ) + + +/* /////////////////////////////////////////////////////////////////////////// +// Names: ippSetFlushToZero, +// ippSetDenormAreZero. +// +// Purpose: ippSetFlushToZero enables or disables the flush-to-zero mode, +// ippSetDenormAreZero enables or disables the denormals-are-zeros +// mode. +// +// Arguments: +// value - !0 or 0 - set or clear the corresponding bit of MXCSR +// pUMask - pointer to user store current underflow exception mask +// ( may be NULL if don't want to store ) +// +// Return: +// ippStsNoErr - Ok +// ippStsCpuNotSupportedErr - the mode is not supported +*/ + +IPPAPI( IppStatus, ippSetFlushToZero, ( int value, unsigned int* pUMask )) +IPPAPI( IppStatus, ippSetDenormAreZeros, ( int value )) + + + +/* ///////////////////////////////////////////////////////////////////////////// +// Name: ippAlignPtr +// Purpose: pointer aligning +// Returns: aligned pointer +// +// Parameter: +// ptr - pointer +// alignBytes - number of bytes to align +// +*/ +IPPAPI( void*, ippAlignPtr, ( void * ptr, int alignBytes ) ) + +/* ///////////////////////////////////////////////////////////////////////////// +// Functions to allocate and free memory +///////////////////////////////////////////////////////////////////////////// */ +/* ///////////////////////////////////////////////////////////////////////////// +// Name: ippMalloc +// Purpose: 64-byte aligned memory allocation +// Parameter: +// len number of bytes +// Returns: pointer to allocated memory +// +// Notes: the memory allocated by ippMalloc has to be free by ippFree +// function only. +*/ + +IPPAPI( void*, ippMalloc, (int length) ) + + +/* ///////////////////////////////////////////////////////////////////////////// +// Name: ippFree +// Purpose: free memory allocated by the ippMalloc function +// Parameter: +// ptr pointer to the memory allocated by the ippMalloc function +// +// Notes: use the function to free memory allocated by ippMalloc +*/ +IPPAPI( void, ippFree, (void* ptr) ) + + + +/* ///////////////////////////////////////////////////////////////////////////// +// Name: ippInit +// Purpose: Automatic switching to best for current cpu library code using. +// Returns: +// ippStsNoErr +// +// Parameter: nothing +// +// Notes: At the moment of this function execution no any other IPP function +// has to be working +*/ +IPPAPI( IppStatus, ippInit, ( void )) + + +/* //////////////////////////////////////////////////////////////////////////// +// Name: ippGetCpuFreqMhz +// +// Purpose: the function estimates cpu frequency and returns +// its value in MHz as a integer +// +// Return: +// ippStsNoErr Ok +// ippStsNullPtrErr null pointer to the freq value +// ippStsSizeErr wrong num of tries, internal var +// Arguments: +// pMhz pointer to the integer to write +// cpu freq value estimated +// +// Notes: no exact value is guaranteed, the value could +// vary with cpu workloading +*/ + +IPPAPI(IppStatus, ippGetCpuFreqMhz, ( int* pMhz ) ) + +/* //////////////////////////////////////////////////////////////////////////// +// Name: ippSetNumThreads +// +// Purpose: +// +// Return: +// ippStsNoErr Ok +// ippStsNoOperation For static library internal threading is not supported +// ippStsSizeErr Desired number of threads less or equal zero +// +// Arguments: +// numThr Desired number of threads +*/ +IPPAPI( IppStatus, ippSetNumThreads, ( int numThr ) ) + +/* //////////////////////////////////////////////////////////////////////////// +// Name: ippGetNumThreads +// +// Purpose: +// +// Return: +// ippStsNoErr Ok +// ippStsNullPtrErr Pointer to numThr is Null +// ippStsNoOperation For static library internal threading is not supported +// and return value is always == 1 +// +// Arguments: +// pNumThr Pointer to memory location where to store current numThr +*/ +IPPAPI( IppStatus, ippGetNumThreads, (int* pNumThr) ) + +/* //////////////////////////////////////////////////////////////////////////// +// Name: ippGetMaxCacheSizeB +// +// Purpose: Detects maximal from the sizes of L2 or L3 in bytes +// +// Return: +// ippStsNullPtrErr The result's pointer is NULL. +// ippStsNotSupportedCpu The cpu is not supported. +// ippStsUnknownCacheSize The cpu is supported, but the size of the cache is unknown. +// ippStsNoErr Ok +// +// Arguments: +// pSizeByte Pointer to the result +// +// Note: +// 1). Intel(R) processors are supported only. +// 2). Intel(R) Itanium(R) processors and platforms with Intel XScale(R) technology are unsupported +// 3). For unsupported processors the result is "0", +// and the return status is "ippStsNotSupportedCpu". +// 4). For supported processors the result is "0", +// and the return status is "ippStsUnknownCacheSize". +// if sizes of the cache is unknown. +// +*/ +IPPAPI( IppStatus, ippGetMaxCacheSizeB, ( int* pSizeByte ) ) + +/* +// Name: ippGetCpuFeatures +// Purpose: Detects CPU features. +// Parameters: +// pFeaturesMask Pointer to the features mask. +// Nonzero value of bit means the corresponding feature is supported. +// Features mask values are defined in the ippdefs.h +// [ 0] - MMX ( ippCPUID_MMX ) +// [ 1] - SSE ( ippCPUID_SSE ) +// [ 2] - SSE2 ( ippCPUID_SSE2 ) +// [ 3] - SSE3 ( ippCPUID_SSE3 ) +// [ 4] - SSSE3 ( ippCPUID_SSSE3 ) +// [ 5] - MOVBE ( ippCPUID_MOVBE ) +// [ 6] - SSE41 ( ippCPUID_SSE41 ) +// [ 7] - SSE42 ( ippCPUID_SSE42 ) +// [ 8] - AVX ( ippCPUID_AVX ) +// [ 9] - ENABLEDBYOS( ippAVX_ENABLEDBYOS ) +// [10] - AES ( ippCPUID_AES ) +// [11] - PCLMULQDQ ( ippCPUID_CLMUL ) +// [12] - ABR ( ippCPUID_ABR ) +// [13] - RDRAND ( ippCPUID_RDRAND ) +// [14] - F16C ( ippCPUID_F16C ) +// [15] - AVX2 ( ippCPUID_AVX2 ) +// [16] - ADOX/ADCX ( ippCPUID_ADCOX ) ADCX and ADOX instructions +// [17] - RDSEED ( ippCPUID_RDSEED ) The RDSEED instruction +// [18] - PREFETCHW ( ippCPUID_PREFETCHW ) The PREFETCHW instruction +// [19] - SHA ( ippCPUID_SHA ) Intel (R) SHA Extensions +// [20:63] - Reserved +// +// pCpuidInfoRegs Pointer to the 4-element vector. +// Result of CPUID.1 are stored in this vector. +// [0] - register EAX +// [1] - register EBX +// [2] - register ECX +// [3] - register EDX +// If pointer pCpuidInfoRegs is set to NULL, registers are not stored. +// +// Returns: +// ippStsNullPtrErr The pointer to the features mask (pFeaturesMask) is NULL. +// ippStsNotSupportedCpu CPU is not supported. +// ippStsNoErr Ok +// +// Note: Only IA-32 and Intel(R) 64 are supported +*/ +IPPAPI( IppStatus, ippGetCpuFeatures, ( Ipp64u* pFeaturesMask, + Ipp32u pCpuidInfoRegs[4] ) ) + +/* +// Name: ippGetEnabledCpuFeatures +// Purpose: Detects enabled features for loaded libraries +// Returns: Features mask +// Features mask values are defined in the ippdefs.h +// [ 0] - ippCPUID_MMX +// [ 1] - ippCPUID_SSE +// [ 2] - ippCPUID_SSE2 +// [ 3] - ippCPUID_SSE3 +// [ 4] - ippCPUID_SSSE3 +// [ 5] - ippCPUID_MOVBE +// [ 6] - ippCPUID_SSE41 +// [ 7] - ippCPUID_SSE42 +// [ 8] - ippCPUID_AVX +// [ 9] - ippAVX_ENABLEDBYOS +// [10] - ippCPUID_AES +// [11] - ippCPUID_CLMUL +// [12] - ippCPUID_ABR +// [13] - ippCPUID_RDRAND +// [14] - ippCPUID_F16C +// [15] - ippCPUID_AVX2 +// [16] - ippCPUID_ADCOX +// [17] - ippCPUID_RDSEED +// [18] - ippCPUID_PREFETCHW +// [19] - ippCPUID_SHA +// [20:63] - Reserved +// +*/ +IPPAPI( Ipp64u, ippGetEnabledCpuFeatures, ( void ) ) + +/* //////////////////////////////////////////////////////////////////////////// +// Name: ippSetCpuFeatures +// +// Purpose: Changes the set of enabled/disabled CPU features. +// This function sets the processor-specific code of the Intel IPP +// library according to the processor features specified in cpuFeatures. +// +// Return: +// ippStsNoErr No errors. +// Warnings: +// ippStsFeatureNotSupported Current CPU doesn't support at least 1 of the +// desired features; +// ippStsUnknownFeature At least one of the desired features is unknown; +// ippStsFeaturesCombination Wrong combination of features; +// ippStsCpuMismatch Indicates that the specified processor features +// are not valid. Previously set code is used. +// +// Arguments: +// cpuFeatures Desired features to support by the library +// (see ippdefs.h for ippCPUID_XX definition) +// +// NOTE: this function can re-initializes dispatcher and after the +// call another library (letter) may work +// CAUTION: At the moment of this function excecution no any other IPP +// function has to be working +// +// The next pre-defined sets of features can be used: +// 32-bit code: +// #define PX_FM ( ippCPUID_MMX | ippCPUID_SSE ) +// #define W7_FM ( PX_FM | ippCPUID_SSE2 ) +// #define V8_FM ( W7_FM | ippCPUID_SSE3 | ippCPUID_SSSE3 ) +// #define S8_FM ( V8_FM | ippCPUID_MOVBE ) +// #define P8_FM ( V8_FM | ippCPUID_SSE41 | ippCPUID_SSE42 | ippCPUID_AES | ippCPUID_CLMUL | ippCPUID_SHA ) +// #define G9_FM ( P8_FM | ippCPUID_AVX | ippAVX_ENABLEDBYOS | ippCPUID_RDRAND | ippCPUID_F16C ) +// #define H9_FM ( G9_FM | ippCPUID_AVX2 | ippCPUID_MOVBE | ippCPUID_ADCOX | ippCPUID_RDSEED | ippCPUID_PREFETCHW ) +// +// 64-bit code: +// #define PX_FM ( ippCPUID_MMX | ippCPUID_SSE | ippCPUID_SSE2 ) +// #define M7_FM ( PX_FM | ippCPUID_SSE3 ) +// #define N8_FM ( S8_FM ) +// #define U8_FM ( V8_FM ) +// #define Y8_FM ( P8_FM ) +// #define E9_FM ( G9_FM ) +// #define L9_FM ( H9_FM ) +// +*/ + +IPPAPI( IppStatus, ippSetCpuFeatures,( Ipp64u cpuFeatures )) + +#if defined (_IPP_STDCALL_CDECL) + #undef _IPP_STDCALL_CDECL + #define __stdcall __cdecl +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* __IPPCORE_H__ */ diff --git a/sgx-jvm/linux-sgx/external/crypto_px/include/ippcp.h b/sgx-jvm/linux-sgx/external/crypto_px/include/ippcp.h new file mode 100755 index 0000000000..48d1d81cce --- /dev/null +++ b/sgx-jvm/linux-sgx/external/crypto_px/include/ippcp.h @@ -0,0 +1,327 @@ +/* +* Copyright (C) 2016 Intel Corporation. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in +* the documentation and/or other materials provided with the +* distribution. +* * Neither the name of Intel Corporation nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ + +#if !defined( __IPPCP_H__ ) || defined( _OWN_BLDPCS ) +#define __IPPCP_H__ + + +#if defined (_WIN32_WCE) && defined (_M_IX86) && defined (__stdcall) + #define _IPP_STDCALL_CDECL + #undef __stdcall +#endif + + +#ifndef __IPPDEFS_H__ + #include "ippdefs.h" +#endif + +#ifndef __IPPCPDEFS_H__ + #include "ippcpdefs.h" +#endif + + +#ifdef __cplusplus +extern "C" { +#endif + + +/* ///////////////////////////////////////////////////////////////////////////// +// Name: ippcpGetLibVersion +// Purpose: getting of the library version +// Returns: the structure of information about version of ippCP library +// Parameters: +// +// Notes: not necessary to release the returned structure +*/ +IPPAPI( const IppLibraryVersion*, ippcpGetLibVersion, (void) ) + + +/* +// AES +*/ +IPPAPI(IppStatus, ippsAESGetSize,(int *pSize)) +IPPAPI(IppStatus, ippsAESInit,(const Ipp8u* pKey, int keyLen, IppsAESSpec* pCtx, int ctxSize)) + +/* AES-CTR */ +IPPAPI(IppStatus, ippsAESEncryptCTR,(const Ipp8u* pSrc, Ipp8u* pDst, int len, + const IppsAESSpec* pCtx, + Ipp8u* pCtrValue, int ctrNumBitSize)) +IPPAPI(IppStatus, ippsAESDecryptCTR,(const Ipp8u* pSrc, Ipp8u* pDst, int len, + const IppsAESSpec* pCtx, + Ipp8u* pCtrValue, int ctrNumBitSize)) + +/* AES-GCM */ +IPPAPI(IppStatus, ippsAES_GCMGetSize,(int * pSize)) +IPPAPI(IppStatus, ippsAES_GCMInit,(const Ipp8u* pKey, int keyLen, IppsAES_GCMState* pState, int ctxSize)) + +IPPAPI(IppStatus, ippsAES_GCMReset,(IppsAES_GCMState* pState)) +IPPAPI(IppStatus, ippsAES_GCMProcessIV,(const Ipp8u* pIV, int ivLen, + IppsAES_GCMState* pState)) +IPPAPI(IppStatus, ippsAES_GCMProcessAAD,(const Ipp8u* pAAD, int ivAAD, + IppsAES_GCMState* pState)) +IPPAPI(IppStatus, ippsAES_GCMStart,(const Ipp8u* pIV, int ivLen, + const Ipp8u* pAAD, int aadLen, + IppsAES_GCMState* pState)) +IPPAPI(IppStatus, ippsAES_GCMEncrypt,(const Ipp8u* pSrc, Ipp8u* pDst, int len, IppsAES_GCMState* pState)) +IPPAPI(IppStatus, ippsAES_GCMDecrypt,(const Ipp8u* pSrc, Ipp8u* pDst, int len, IppsAES_GCMState* pState)) +IPPAPI(IppStatus, ippsAES_GCMGetTag,(Ipp8u* pDstTag, int tagLen, const IppsAES_GCMState* pState)) + +/* AES-CMAC */ +IPPAPI(IppStatus, ippsAES_CMACGetSize,(int* pSize)) +IPPAPI(IppStatus, ippsAES_CMACInit,(const Ipp8u* pKey, int keyLen, IppsAES_CMACState* pState, int ctxSize)) + +IPPAPI(IppStatus, ippsAES_CMACUpdate,(const Ipp8u* pSrc, int len, IppsAES_CMACState* pState)) +IPPAPI(IppStatus, ippsAES_CMACFinal,(Ipp8u* pMD, int mdLen, IppsAES_CMACState* pState)) +IPPAPI(IppStatus, ippsAES_CMACGetTag,(Ipp8u* pMD, int mdLen, const IppsAES_CMACState* pState)) + +/* +// hash +*/ +IPPAPI(IppStatus, ippsHashGetSize,(int* pSize)) +IPPAPI(IppStatus, ippsHashInit,(IppsHashState* pCtx, IppHashAlgId hashAlg)) + +IPPAPI(IppStatus, ippsHashUpdate,(const Ipp8u* pSrc, int len, IppsHashState* pCtx)) +IPPAPI(IppStatus, ippsHashGetTag,(Ipp8u* pMD, int tagLen, const IppsHashState* pCtx)) +IPPAPI(IppStatus, ippsHashFinal,(Ipp8u* pMD, IppsHashState* pCtx)) +IPPAPI(IppStatus, ippsHashMessage,(const Ipp8u* pMsg, int len, Ipp8u* pMD, IppHashAlgId hashAlg)) + +IPPAPI(IppStatus, ippsMGF,(const Ipp8u* pSeed, int seedLen, Ipp8u* pMask, int maskLen, IppHashAlgId hashAlg)) + +IPPAPI(IppStatus, ippsHMAC_GetSize,(int* pSize)) +IPPAPI(IppStatus, ippsHMAC_Init,(const Ipp8u* pKey, int keyLen, IppsHMACState* pCtx, IppHashAlgId hashAlg)) + +IPPAPI(IppStatus, ippsHMAC_Update,(const Ipp8u* pSrc, int len, IppsHMACState* pCtx)) +IPPAPI(IppStatus, ippsHMAC_Final,(Ipp8u* pMD, int mdLen, IppsHMACState* pCtx)) +IPPAPI(IppStatus, ippsHMAC_GetTag,(Ipp8u* pMD, int mdLen, const IppsHMACState* pCtx)) +IPPAPI(IppStatus, ippsHMAC_Message,(const Ipp8u* pMsg, int msgLen, + const Ipp8u* pKey, int keyLen, + Ipp8u* pMD, int mdLen, + IppHashAlgId hashAlg)) + +/* +// Big Number Integer Arithmetic +*/ +IPPAPI(IppStatus, ippsBigNumGetSize,(int length, int* pSize)) +IPPAPI(IppStatus, ippsBigNumInit,(int length, IppsBigNumState* pBN)) + +IPPAPI(IppStatus, ippsSet_BN,(IppsBigNumSGN sgn, + int length, const Ipp32u* pData, + IppsBigNumState* pBN)) +IPPAPI(IppStatus, ippsRef_BN,(IppsBigNumSGN* pSgn, int* bitSize, Ipp32u** const ppData, + const IppsBigNumState* pBN)) + +IPPAPI(IppStatus, ippsAdd_BN, (IppsBigNumState* pA, IppsBigNumState* pB, IppsBigNumState* pR)) +IPPAPI(IppStatus, ippsSub_BN, (IppsBigNumState* pA, IppsBigNumState* pB, IppsBigNumState* pR)) +IPPAPI(IppStatus, ippsMod_BN, (IppsBigNumState* pA, IppsBigNumState* pM, IppsBigNumState* pR)) +IPPAPI(IppStatus, ippsModInv_BN,(IppsBigNumState* pA, IppsBigNumState* pM, IppsBigNumState* pInv)) +IPPAPI(IppStatus, ippsDiv_BN, (IppsBigNumState* pA, IppsBigNumState* pB, IppsBigNumState* pQ, IppsBigNumState* pR)) +IPPAPI(IppStatus, ippsCmpZero_BN,(const IppsBigNumState* pBN, Ipp32u* pResult)) +IPPAPI(IppStatus, ippsCmp_BN,(const IppsBigNumState* pA, const IppsBigNumState* pB, Ipp32u* pResult)) +IPPAPI(IppStatus, ippsMul_BN, (IppsBigNumState* pA, IppsBigNumState* pB, IppsBigNumState* pR)) +IPPAPI(IppStatus, ippsGcd_BN, (IppsBigNumState* pA, IppsBigNumState* pB, IppsBigNumState* pGCD)) + +IPPAPI(IppStatus, ippsSetOctString_BN,(const Ipp8u* pStr, int strLen, IppsBigNumState* pBN)) +IPPAPI(IppStatus, ippsGetOctString_BN,(Ipp8u* pStr, int strLen, const IppsBigNumState* pBN)) + +/* +// Montgomery Operations +*/ +IPPAPI(IppStatus, ippsMontGetSize,(IppsExpMethod method, int length, int* pSize)) +IPPAPI(IppStatus, ippsMontInit,(IppsExpMethod method, int length, IppsMontState* pCtx)) +IPPAPI(IppStatus, ippsMontSet,(const Ipp32u* pModulo, int size, IppsMontState* pCtx)) +IPPAPI(IppStatus, ippsMontMul, (const IppsBigNumState* pA, const IppsBigNumState* pB, IppsMontState* m, IppsBigNumState* pR)) + +/* +// PRNG +*/ +IPPAPI(IppStatus, ippsPRNGGetSize,(int* pSize)) +IPPAPI(IppStatus, ippsPRNGInit, (int seedBits, IppsPRNGState* pCtx)) +IPPAPI(IppStatus, ippsPRNGen, (Ipp32u* pRand, int nBits, void* pCtx)) + +/* +// Prime Number Generation +*/ +IPPAPI(IppStatus, ippsPrimeGetSize,(int nMaxBits, int* pSize)) +IPPAPI(IppStatus, ippsPrimeInit, (int nMaxBits, IppsPrimeState* pCtx)) + + +/* +// RSA +*/ +IPPAPI(IppStatus, ippsRSA_GetSizePublicKey,(int rsaModulusBitSize, int pubicExpBitSize, int* pKeySize)) +IPPAPI(IppStatus, ippsRSA_InitPublicKey,(int rsaModulusBitSize, int publicExpBitSize, + IppsRSAPublicKeyState* pKey, int keyCtxSize)) +IPPAPI(IppStatus, ippsRSA_SetPublicKey,(const IppsBigNumState* pModulus, + const IppsBigNumState* pPublicExp, + IppsRSAPublicKeyState* pKey)) +IPPAPI(IppStatus, ippsRSA_GetPublicKey,(IppsBigNumState* pModulus, + IppsBigNumState* pPublicExp, + const IppsRSAPublicKeyState* pKey)) + +IPPAPI(IppStatus, ippsRSA_GetSizePrivateKeyType1,(int rsaModulusBitSize, int privateExpBitSize, int* pKeySize)) +IPPAPI(IppStatus, ippsRSA_InitPrivateKeyType1,(int rsaModulusBitSize, int privateExpBitSize, + IppsRSAPrivateKeyState* pKey, int keyCtxSize)) +IPPAPI(IppStatus, ippsRSA_SetPrivateKeyType1,(const IppsBigNumState* pModulus, + const IppsBigNumState* pPrivateExp, + IppsRSAPrivateKeyState* pKey)) + +IPPAPI(IppStatus, ippsRSA_GetSizePrivateKeyType2,(int factorPbitSize, int factorQbitSize, int* pKeySize)) +IPPAPI(IppStatus, ippsRSA_InitPrivateKeyType2,(int factorPbitSize, int factorQbitSize, + IppsRSAPrivateKeyState* pKey, int keyCtxSize)) +IPPAPI(IppStatus, ippsRSA_SetPrivateKeyType2,(const IppsBigNumState* pFactorP, + const IppsBigNumState* pFactorQ, + const IppsBigNumState* pCrtExpP, + const IppsBigNumState* pCrtExpQ, + const IppsBigNumState* pInverseQ, + IppsRSAPrivateKeyState* pKey)) + +IPPAPI(IppStatus, ippsRSA_GetBufferSizePublicKey,(int* pBufferSize, const IppsRSAPublicKeyState* pKey)) +IPPAPI(IppStatus, ippsRSA_GetBufferSizePrivateKey,(int* pBufferSize, const IppsRSAPrivateKeyState* pKey)) + +IPPAPI(IppStatus, ippsRSA_Encrypt,(const IppsBigNumState* pPtxt, + IppsBigNumState* pCtxt, + const IppsRSAPublicKeyState* pKey, + Ipp8u* pScratchBuffer)) +IPPAPI(IppStatus, ippsRSA_Decrypt,(const IppsBigNumState* pCtxt, + IppsBigNumState* pPtxt, + const IppsRSAPrivateKeyState* pKey, + Ipp8u* pScratchBuffer)) + +IPPAPI(IppStatus, ippsRSA_ValidateKeys,(int* pResult, + const IppsRSAPublicKeyState* pPublicKey, + const IppsRSAPrivateKeyState* pPrivateKeyType2, + const IppsRSAPrivateKeyState* pPrivateKeyType1, + Ipp8u* pScratchBuffer, + int nTrials, + IppsPrimeState* pPrimeGen, + IppBitSupplier rndFunc, void* pRndParam)) + +/* encryption scheme: RSAES-OAEP */ +IPPAPI(IppStatus, ippsRSAEncrypt_OAEP,(const Ipp8u* pSrc, int srcLen, + const Ipp8u* pLabel, int labLen, + const Ipp8u* pSeed, + Ipp8u* pDst, + const IppsRSAPublicKeyState* pKey, + IppHashAlgId hashAlg, + Ipp8u* pBuffer)) +IPPAPI(IppStatus, ippsRSA_OAEPEncrypt_SHA256,(const Ipp8u* pSrc, int srcLen, + const Ipp8u* pLabel, int labLen, + const Ipp8u* pSeed, + Ipp8u* pDst, + const IppsRSAPublicKeyState* pKey, + Ipp8u* pBuffer)) + +/* signature scheme : RSA-SSA-PKCS1-v1_5 */ +IPPAPI(IppStatus, ippsRSASign_PKCS1v15,(const Ipp8u* pMsg, int msgLen, + Ipp8u* pSign, + const IppsRSAPrivateKeyState* pPrvKey, + const IppsRSAPublicKeyState* pPubKey, + IppHashAlgId hashAlg, + Ipp8u* pBuffer)) + + +IPPAPI(IppStatus, ippsRSAVerify_PKCS1v15,(const Ipp8u* pMsg, int msgLen, + const Ipp8u* pSign, int* pIsValid, + const IppsRSAPublicKeyState* pKey, + IppHashAlgId hashAlg, + Ipp8u* pBuffer)) + + +/* +// EC Cryptography +*/ +IPPAPI(IppStatus, ippsECCPGetSize,(int feBitSize, int* pSize)) +IPPAPI(IppStatus, ippsECCPInit,(int feBitSize, IppsECCPState* pECC)) + +IPPAPI(IppStatus, ippsECCPSet,(const IppsBigNumState* pPrime, + const IppsBigNumState* pA, const IppsBigNumState* pB, + const IppsBigNumState* pGX,const IppsBigNumState* pGY,const IppsBigNumState* pOrder, + int cofactor, + IppsECCPState* pECC)) + +IPPAPI(IppStatus, ippsECCPSetStd,(IppECCType flag, IppsECCPState* pECC)) + + +IPPAPI(IppStatus, ippsECCPPointGetSize,(int feBitSize, int* pSize)) +IPPAPI(IppStatus, ippsECCPPointInit,(int feBitSize, IppsECCPPointState* pPoint)) + +IPPAPI(IppStatus, ippsECCPSetPoint,(const IppsBigNumState* pX, const IppsBigNumState* pY, + IppsECCPPointState* pPoint, IppsECCPState* pECC)) +IPPAPI(IppStatus, ippsECCPSetPointAtInfinity,(IppsECCPPointState* pPoint, IppsECCPState* pECC)) + +IPPAPI(IppStatus, ippsECCPGetPoint,(IppsBigNumState* pX, IppsBigNumState* pY, + const IppsECCPPointState* pPoint, IppsECCPState* pECC)) + +IPPAPI(IppStatus, ippsECCPCheckPoint,(const IppsECCPPointState* pP, + IppECResult* pResult, IppsECCPState* pECC)) +IPPAPI(IppStatus, ippsECCPComparePoint,(const IppsECCPPointState* pP, const IppsECCPPointState* pQ, + IppECResult* pResult, IppsECCPState* pECC)) +IPPAPI(IppStatus, ippsECCPNegativePoint,(const IppsECCPPointState* pP, + IppsECCPPointState* pR, IppsECCPState* pECC)) +IPPAPI(IppStatus, ippsECCPAddPoint,(const IppsECCPPointState* pP, const IppsECCPPointState* pQ, + IppsECCPPointState* pR, IppsECCPState* pECC)) +IPPAPI(IppStatus, ippsECCPMulPointScalar,(const IppsECCPPointState* pP, const IppsBigNumState* pK, + IppsECCPPointState* pR, IppsECCPState* pECC)) + +IPPAPI(IppStatus, ippsECCPGenKeyPair,(IppsBigNumState* pPrivate, IppsECCPPointState* pPublic, + IppsECCPState* pECC, + IppBitSupplier rndFunc, void* pRndParam)) +IPPAPI(IppStatus, ippsECCPPublicKey,(const IppsBigNumState* pPrivate, + IppsECCPPointState* pPublic, + IppsECCPState* pECC)) +IPPAPI(IppStatus, ippsECCPSetKeyPair,(const IppsBigNumState* pPrivate, const IppsECCPPointState* pPublic, + IppBool regular, + IppsECCPState* pECC)) + +IPPAPI(IppStatus, ippsECCPSharedSecretDH,(const IppsBigNumState* pPrivateA, + const IppsECCPPointState* pPublicB, + IppsBigNumState* pShare, + IppsECCPState* pECC)) + +IPPAPI(IppStatus, ippsECCPSignDSA,(const IppsBigNumState* pMsgDigest, + const IppsBigNumState* pPrivate, + IppsBigNumState* pSignX, IppsBigNumState* pSignY, + IppsECCPState* pECC)) +IPPAPI(IppStatus, ippsECCPVerifyDSA,(const IppsBigNumState* pMsgDigest, + const IppsBigNumState* pSignX, const IppsBigNumState* pSignY, + IppECResult* pResult, + IppsECCPState* pECC)) + +#ifdef __cplusplus +} +#endif + +#if defined (_IPP_STDCALL_CDECL) + #undef _IPP_STDCALL_CDECL + #define __stdcall __cdecl +#endif + +#endif /* __IPPCP_H__ */ diff --git a/sgx-jvm/linux-sgx/external/crypto_px/include/ippcpdefs.h b/sgx-jvm/linux-sgx/external/crypto_px/include/ippcpdefs.h new file mode 100755 index 0000000000..612ed50dec --- /dev/null +++ b/sgx-jvm/linux-sgx/external/crypto_px/include/ippcpdefs.h @@ -0,0 +1,211 @@ +/* +* Copyright (C) 2016 Intel Corporation. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in +* the documentation and/or other materials provided with the +* distribution. +* * Neither the name of Intel Corporation nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ + +#ifndef __IPPCPDEFS_H__ +#define __IPPCPDEFS_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/* +// AES +*/ +#define IPP_AES_BLOCK_BITSIZE (128) /* cipher blocksizes (bits) */ + +typedef enum { /* cipher keysizes (bits) */ + ippRijndaelKey128 = 128, IppsRijndaelKey128 = 128, /* 128-bit key */ + ippRijndaelKey192 = 192, IppsRijndaelKey192 = 192, /* 192-bit key */ + ippRijndaelKey256 = 256, IppsRijndaelKey256 = 256 /* 256-bit key */ +} IppsRijndaelKeyLength; + +typedef struct _cpRijndael128 IppsAESSpec; +typedef struct _cpAES_GCM IppsAES_GCMState; +typedef struct _cpAES_CMAC IppsAES_CMACState; + + +/* +// hash +*/ +typedef enum { + ippHashAlg_Unknown, + ippHashAlg_SHA1, + ippHashAlg_SHA256, + ippHashAlg_SHA224, + ippHashAlg_SHA512, + ippHashAlg_SHA384, + ippHashAlg_MD5, + ippHashAlg_SHA512_224, + ippHashAlg_SHA512_256, + ippHashAlg_MaxNo +} IppHashAlgId; + +#define IPP_ALG_HASH_UNKNOWN (ippHashAlg_Unknown) /* unknown */ +#define IPP_ALG_HASH_SHA1 (ippHashAlg_SHA1) /* SHA1 */ +#define IPP_ALG_HASH_SHA256 (ippHashAlg_SHA256) /* SHA256 */ +#define IPP_ALG_HASH_SHA224 (ippHashAlg_SHA224) /* SHA224 or SHA256/224 */ +#define IPP_ALG_HASH_SHA512 (ippHashAlg_SHA512) /* SHA512 */ +#define IPP_ALG_HASH_SHA384 (ippHashAlg_SHA384) /* SHA384 or SHA512/384 */ +#define IPP_ALG_HASH_MD5 (ippHashAlg_MD5) /* MD5 */ +#define IPP_ALG_HASH_SHA512_224 (ippHashAlg_SHA512_224) /* SHA512/224 */ +#define IPP_ALG_HASH_SHA512_256 (ippHashAlg_SHA512_256) /* SHA512/256 */ +#define IPP_ALG_HASH_LIMIT (ippHashAlg_MaxNo) /* hash alg limiter*/ + +#define IPP_SHA1_DIGEST_BITSIZE 160 /* digest size (bits) */ +#define IPP_SHA256_DIGEST_BITSIZE 256 +#define IPP_SHA224_DIGEST_BITSIZE 224 +#define IPP_SHA384_DIGEST_BITSIZE 384 +#define IPP_SHA512_DIGEST_BITSIZE 512 +#define IPP_MD5_DIGEST_BITSIZE 128 +#define IPP_SHA512_224_DIGEST_BITSIZE 224 +#define IPP_SHA512_256_DIGEST_BITSIZE 256 + +typedef struct _cpHashCtx IppsHashState; +typedef struct _cpHMAC IppsHMACState; + + +/* +// Big Number Integer Arithmetic +*/ +#define BN_MAXBITSIZE (16*1024) /* bn max size (bits) */ + +/* operation results */ +#define IPP_IS_EQ (0) +#define IPP_IS_GT (1) +#define IPP_IS_LT (2) +#define IPP_IS_NE (3) +#define IPP_IS_NA (4) + +#define IPP_IS_PRIME (5) +#define IPP_IS_COMPOSITE (6) + +#define IPP_IS_VALID (7) +#define IPP_IS_INVALID (8) +#define IPP_IS_INCOMPLETE (9) +#define IPP_IS_ATINFINITY (10) + +#define IS_ZERO IPP_IS_EQ +#define GREATER_THAN_ZERO IPP_IS_GT +#define LESS_THAN_ZERO IPP_IS_LT +#define IS_PRIME IPP_IS_PRIME +#define IS_COMPOSITE IPP_IS_COMPOSITE +#define IS_VALID_KEY IPP_IS_VALID +#define IS_INVALID_KEY IPP_IS_INVALID +#define IS_INCOMPLETED_KEY IPP_IS_INCOMPLETE + +typedef enum { + ippBigNumNEG = 0, IppsBigNumNEG = 0, + ippBigNumPOS = 1, IppsBigNumPOS = 1 +} IppsBigNumSGN; + +typedef enum { + ippBinaryMethod = 0, IppsBinaryMethod = 0, + ippSlidingWindows = 1, IppsSlidingWindows = 1 +} IppsExpMethod; + +typedef struct _cpBigNum IppsBigNumState; +typedef struct _cpMontgomery IppsMontState; +typedef struct _cpPRNG IppsPRNGState; +typedef struct _cpPrime IppsPrimeState; + +/* External Bit Supplier */ +typedef IppStatus (__STDCALL *IppBitSupplier)(Ipp32u* pRand, int nBits, void* pEbsParams); + + +/* +// RSA +*/ +#define MIN_RSA_SIZE (8) +#define MAX_RSA_SIZE (4096) + +typedef struct _cpRSA IppsRSAState; +typedef struct _cpRSA_public_key IppsRSAPublicKeyState; +typedef struct _cpRSA_private_key IppsRSAPrivateKeyState; + + +/* +// EC Cryptography +*/ +#define EC_GFP_MAXBITSIZE (1024) + +typedef struct _cpECCP IppsECCPState; +typedef struct _cpECCPPoint IppsECCPPointState; + +/* operation result */ +typedef enum { + ippECValid, /* validation pass successfully */ + + ippECCompositeBase, /* field based on composite */ + ippECComplicatedBase, /* number of non-zero terms in the polynomial (> PRIME_ARR_MAX) */ + ippECIsZeroDiscriminant,/* zero discriminant */ + ippECCompositeOrder, /* composite order of base point */ + ippECInvalidOrder, /* invalid base point order */ + ippECIsWeakMOV, /* weak Meneze-Okamoto-Vanstone reduction attack */ + ippECIsWeakSSSA, /* weak Semaev-Smart,Satoh-Araki reduction attack */ + ippECIsSupersingular, /* supersingular curve */ + + ippECInvalidPrivateKey, /* !(0 < Private < order) */ + ippECInvalidPublicKey, /* (order*PublicKey != Infinity) */ + ippECInvalidKeyPair, /* (Private*BasePoint != PublicKey) */ + + ippECPointOutOfGroup, /* out of group (order*P != Infinity) */ + ippECPointIsAtInfinite, /* point (P=(Px,Py)) at Infinity */ + ippECPointIsNotValid, /* point (P=(Px,Py)) out-of EC */ + + ippECPointIsEqual, /* compared points are equal */ + ippECPointIsNotEqual, /* compared points are different */ + + ippECInvalidSignature /* invalid signature */ +} IppECResult; + +typedef enum { + ippECarbitrary =0x00000, IppECCArbitrary = 0x00000, /* arbitrary ECC */ + + ippECPstd = 0x10000, IppECCPStd = 0x10000, /* random (recommended) EC over FG(p): */ + ippECPstd112r1 = ippECPstd, IppECCPStd112r1 = IppECCPStd, /* secp112r1 curve */ + ippECPstd112r2 = ippECPstd+1, IppECCPStd112r2 = IppECCPStd+1, /* secp112r2 curve */ + ippECPstd128r1 = ippECPstd+2, IppECCPStd128r1 = IppECCPStd+2, /* secp128r1 curve */ + ippECPstd128r2 = ippECPstd+3, IppECCPStd128r2 = IppECCPStd+3, /* secp128r2 curve */ + ippECPstd160r1 = ippECPstd+4, IppECCPStd160r1 = IppECCPStd+4, /* secp160r1 curve */ + ippECPstd160r2 = ippECPstd+5, IppECCPStd160r2 = IppECCPStd+5, /* secp160r2 curve */ + ippECPstd192r1 = ippECPstd+6, IppECCPStd192r1 = IppECCPStd+6, /* secp192r1 curve */ + ippECPstd224r1 = ippECPstd+7, IppECCPStd224r1 = IppECCPStd+7, /* secp224r1 curve */ + ippECPstd256r1 = ippECPstd+8, IppECCPStd256r1 = IppECCPStd+8, /* secp256r1 curve */ + ippECPstd384r1 = ippECPstd+9, IppECCPStd384r1 = IppECCPStd+9, /* secp384r1 curve */ + ippECPstd521r1 = ippECPstd+10, IppECCPStd521r1 = IppECCPStd+10, /* secp521r1 curve */ +} IppsECType, IppECCType; + + +#ifdef __cplusplus +} +#endif + +#endif /* __IPPCPDEFS_H__ */ diff --git a/sgx-jvm/linux-sgx/external/crypto_px/include/ippdefs.h b/sgx-jvm/linux-sgx/external/crypto_px/include/ippdefs.h new file mode 100755 index 0000000000..1e78d0c76f --- /dev/null +++ b/sgx-jvm/linux-sgx/external/crypto_px/include/ippdefs.h @@ -0,0 +1,129 @@ +/* +* Copyright (C) 2016 Intel Corporation. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in +* the documentation and/or other materials provided with the +* distribution. +* * Neither the name of Intel Corporation nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ + +#ifndef __IPPDEFS_H__ +#define __IPPDEFS_H__ + +#ifdef __cplusplus +extern "C" { +#endif + + +#if defined (_WIN64) +#define _INTEL_PLATFORM "intel64/" +#elif defined (_WIN32) +#define _INTEL_PLATFORM "ia32/" +#endif + +#if !defined( IPPAPI ) + + #if defined( IPP_W32DLL ) && (defined( _WIN32 ) || defined( _WIN64 )) + #if defined( _MSC_VER ) || defined( __ICL ) + #define IPPAPI( type,name,arg ) \ + __declspec(dllimport) type __STDCALL name arg; + #else + #define IPPAPI( type,name,arg ) type __STDCALL name arg; + #endif + #else + #define IPPAPI( type,name,arg ) type __STDCALL name arg; + #endif + +#endif + +#if (defined( __ICL ) || defined( __ECL ) || defined(_MSC_VER)) && !defined( _PCS ) && !defined( _PCS_GENSTUBS ) + #if( __INTEL_COMPILER >= 1100 ) /* icl 11.0 supports additional comment */ + #if( _MSC_VER >= 1400 ) + #define IPP_DEPRECATED( comment ) __declspec( deprecated ( comment )) + #else + #pragma message ("your icl version supports additional comment for deprecated functions but it can't be displayed") + #pragma message ("because internal _MSC_VER macro variable setting requires compatibility with MSVC7.1") + #pragma message ("use -Qvc8 switch for icl command line to see these additional comments") + #define IPP_DEPRECATED( comment ) __declspec( deprecated ) + #endif + #elif( _MSC_FULL_VER >= 140050727 )&&( !defined( __INTEL_COMPILER )) /* VS2005 supports additional comment */ + #define IPP_DEPRECATED( comment ) __declspec( deprecated ( comment )) + #elif( _MSC_VER <= 1200 )&&( !defined( __INTEL_COMPILER )) /* VS 6 doesn't support deprecation */ + #define IPP_DEPRECATED( comment ) + #else + #define IPP_DEPRECATED( comment ) __declspec( deprecated ) + #endif +#elif (defined(__ICC) || defined(__ECC) || defined( __GNUC__ )) && !defined( _PCS ) && !defined( _PCS_GENSTUBS ) + #if defined( __GNUC__ ) + #if __GNUC__ >= 4 && __GNUC_MINOR__ >= 5 + #define IPP_DEPRECATED( message ) __attribute__(( deprecated( message ))) + #else + #define IPP_DEPRECATED( message ) __attribute__(( deprecated )) + #endif + #else + #define IPP_DEPRECATED( comment ) __attribute__(( deprecated )) + #endif +#else + #define IPP_DEPRECATED( comment ) +#endif + +#if (defined( __ICL ) || defined( __ECL ) || defined(_MSC_VER)) + #if !defined( _IPP_NO_DEFAULT_LIB ) + #if (( defined( _IPP_PARALLEL_DYNAMIC ) && !defined( _IPP_PARALLEL_STATIC ) && !defined( _IPP_SEQUENTIAL_DYNAMIC ) && !defined( _IPP_SEQUENTIAL_STATIC )) || \ + (!defined( _IPP_PARALLEL_DYNAMIC ) && defined( _IPP_PARALLEL_STATIC ) && !defined( _IPP_SEQUENTIAL_DYNAMIC ) && !defined( _IPP_SEQUENTIAL_STATIC )) || \ + (!defined( _IPP_PARALLEL_DYNAMIC ) && !defined( _IPP_PARALLEL_STATIC ) && defined( _IPP_SEQUENTIAL_DYNAMIC ) && !defined( _IPP_SEQUENTIAL_STATIC )) || \ + (!defined( _IPP_PARALLEL_DYNAMIC ) && !defined( _IPP_PARALLEL_STATIC ) && !defined( _IPP_SEQUENTIAL_DYNAMIC ) && defined( _IPP_SEQUENTIAL_STATIC ))) + #elif (!defined( _IPP_PARALLEL_DYNAMIC ) && !defined( _IPP_PARALLEL_STATIC ) && !defined( _IPP_SEQUENTIAL_DYNAMIC ) && !defined( _IPP_SEQUENTIAL_STATIC )) + #define _IPP_NO_DEFAULT_LIB + #else + #error Illegal combination of _IPP_PARALLEL_DYNAMIC/_IPP_PARALLEL_STATIC/_IPP_SEQUENTIAL_DYNAMIC/_IPP_SEQUENTIAL_STATIC, only one definition can be defined + #endif + #endif +#else + #define _IPP_NO_DEFAULT_LIB + #if (defined( _IPP_PARALLEL_DYNAMIC ) || defined( _IPP_PARALLEL_STATIC ) || defined(_IPP_SEQUENTIAL_DYNAMIC) || defined(_IPP_SEQUENTIAL_STATIC)) + #pragma message ("defines _IPP_PARALLEL_DYNAMIC/_IPP_PARALLEL_STATIC/_IPP_SEQUENTIAL_DYNAMIC/_IPP_SEQUENTIAL_STATIC do not have any effect in current configuration") + #endif +#endif + +#if !defined( _IPP_NO_DEFAULT_LIB ) + #if defined( _IPP_PARALLEL_STATIC ) + #pragma comment( lib, "libircmt" ) + #pragma comment( lib, "libmmt" ) + #pragma comment( lib, "svml_dispmt" ) + #pragma comment( lib, "libiomp5md" ) + #endif +#endif + +#include "ippbase.h" +#include "ipptypes.h" + +extern const IppiRect ippRectInfinite; + +#ifdef __cplusplus +} +#endif + +#endif /* __IPPDEFS_H__ */ diff --git a/sgx-jvm/linux-sgx/external/crypto_px/include/ipptypes.h b/sgx-jvm/linux-sgx/external/crypto_px/include/ipptypes.h new file mode 100755 index 0000000000..dedb27991c --- /dev/null +++ b/sgx-jvm/linux-sgx/external/crypto_px/include/ipptypes.h @@ -0,0 +1,1104 @@ +/* +* Copyright (C) 2016 Intel Corporation. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in +* the documentation and/or other materials provided with the +* distribution. +* * Neither the name of Intel Corporation nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ + +#ifndef __IPPTYPES_H__ +#define __IPPTYPES_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/*****************************************************************************/ +/* Below are ippCore domain specific definitions */ +/*****************************************************************************/ +#if !defined( _OWN_BLDPCS ) + +#define ippCPUID_MMX 0x00000001 /* Intel Architecture MMX technology supported */ +#define ippCPUID_SSE 0x00000002 /* Streaming SIMD Extensions */ +#define ippCPUID_SSE2 0x00000004 /* Streaming SIMD Extensions 2 */ +#define ippCPUID_SSE3 0x00000008 /* Streaming SIMD Extensions 3 */ +#define ippCPUID_SSSE3 0x00000010 /* Supplemental Streaming SIMD Extensions 3 */ +#define ippCPUID_MOVBE 0x00000020 /* The processor supports MOVBE instruction */ +#define ippCPUID_SSE41 0x00000040 /* Streaming SIMD Extensions 4.1 */ +#define ippCPUID_SSE42 0x00000080 /* Streaming SIMD Extensions 4.2 */ +#define ippCPUID_AVX 0x00000100 /* Advanced Vector Extensions instruction set */ +#define ippAVX_ENABLEDBYOS 0x00000200 /* The operating system supports AVX */ +#define ippCPUID_AES 0x00000400 /* AES instruction */ +#define ippCPUID_CLMUL 0x00000800 /* PCLMULQDQ instruction */ +#define ippCPUID_ABR 0x00001000 /* Reserved */ +#define ippCPUID_RDRAND 0x00002000 /* Read Random Number instructions */ +#define ippCPUID_F16C 0x00004000 /* Float16 instructions */ +#define ippCPUID_AVX2 0x00008000 /* Advanced Vector Extensions 2 instruction set */ +#define ippCPUID_ADCOX 0x00010000 /* ADCX and ADOX instructions */ +#define ippCPUID_RDSEED 0x00020000 /* The RDSEED instruction */ +#define ippCPUID_PREFETCHW 0x00040000 /* The PREFETCHW instruction */ +#define ippCPUID_SHA 0x00080000 /* Intel (R) SHA Extensions */ +#define ippCPUID_AVX512F 0x00100000 /* AVX-512 Foundation instructions */ +#define ippCPUID_AVX512CD 0x00200000 /* AVX-512 Conflict Detection instructions */ +#define ippCPUID_AVX512ER 0x00400000 /* AVX-512 Exponential & Reciprocal instructions*/ +#define ippCPUID_AVX512PF 0x00800000 /* AVX-512 Prefetch instructions */ +#define ippCPUID_AVX512BW 0x01000000 /* AVX-512 Byte & Word instructions */ +#define ippCPUID_AVX512DQ 0x02000000 /* AVX-512 DWord & QWord instructions */ +#define ippCPUID_AVX512VL 0x04000000 /* AVX-512 Vector Length extensions */ +#define ippCPUID_KNC 0x80000000 /* Intel(R) Xeon Phi(TM) Coprocessor */ +#if defined( _WIN32 ) || defined ( _WIN64 ) + #define ippCPUID_NOCHECK 0x8000000000000000L /* Force ippSetCpuFeatures to set CPU features without check */ +#else + #define ippCPUID_NOCHECK 0x8000000000000000LL +#endif + +#if defined( _WIN32 ) || defined ( _WIN64 ) + #define ippCPUID_GETINFO_A 0x616f666e69746567L /* Force ipp_GetCpuFeatures to work as cpuid instruction */ +#else + #define ippCPUID_GETINFO_A 0x616f666e69746567LL +#endif + +#define IPP_COUNT_OF( obj ) (sizeof(obj)/sizeof(obj[0])) + +/*****************************************************************************/ +/* Below are ippSP domain specific definitions */ +/*****************************************************************************/ +typedef enum { + ippRndZero, + ippRndNear, + ippRndFinancial, + ippRndHintAccurate=0x10 +} IppRoundMode; + + +typedef enum { + ippAlgHintNone, + ippAlgHintFast, + ippAlgHintAccurate +} IppHintAlgorithm; + +typedef enum { + ippCmpLess, + ippCmpLessEq, + ippCmpEq, + ippCmpGreaterEq, + ippCmpGreater +} IppCmpOp; + +typedef enum { + ippAlgAuto = 0x00000000, + ippAlgDirect = 0x00000001, + ippAlgFFT = 0x00000002, + ippAlgMask = 0x000000FF +} IppAlgType; + +typedef enum { + ippsNormNone = 0x00000000, /* default */ + ippsNormA = 0x00000100, /* biased normalization */ + ippsNormB = 0x00000200, /* unbiased normalization */ + ippsNormMask = 0x0000FF00 +} IppsNormOp; + +typedef enum { + ippNormInf = 0x00000001, + ippNormL1 = 0x00000002, + ippNormL2 = 0x00000004 +} IppNormType; + +enum { + IPP_FFT_DIV_FWD_BY_N = 1, + IPP_FFT_DIV_INV_BY_N = 2, + IPP_FFT_DIV_BY_SQRTN = 4, + IPP_FFT_NODIV_BY_ANY = 8 +}; + +enum { + IPP_DIV_FWD_BY_N = 1, + IPP_DIV_INV_BY_N = 2, + IPP_DIV_BY_SQRTN = 4, + IPP_NODIV_BY_ANY = 8 +}; + +typedef struct { + Ipp32f rho; + Ipp32f theta; +} IppPointPolar; + +typedef enum {ippWinBartlett,ippWinBlackman,ippWinHamming,ippWinHann,ippWinRect} IppWinType; + +typedef enum { ippButterworth, ippChebyshev1 } IppsIIRFilterType; + +typedef enum { ippZCR=0, ippZCXor, ippZCC } IppsZCType; + +#if !defined( _OWN_BLDPCS ) + +typedef struct { + int left; + int right; +} IppsROI; + +typedef struct RandUniState_8u IppsRandUniState_8u; +typedef struct RandUniState_16s IppsRandUniState_16s; +typedef struct RandUniState_32f IppsRandUniState_32f; +typedef struct RandUniState_64f IppsRandUniState_64f; + +typedef struct RandGaussState_8u IppsRandGaussState_8u; +typedef struct RandGaussState_16s IppsRandGaussState_16s; +typedef struct RandGaussState_32f IppsRandGaussState_32f; +typedef struct RandGaussState_64f IppsRandGaussState_64f; + +typedef struct FFTSpec_C_32fc IppsFFTSpec_C_32fc; +typedef struct FFTSpec_C_32f IppsFFTSpec_C_32f; +typedef struct FFTSpec_R_32f IppsFFTSpec_R_32f; + +typedef struct FFTSpec_C_64fc IppsFFTSpec_C_64fc; +typedef struct FFTSpec_C_64f IppsFFTSpec_C_64f; +typedef struct FFTSpec_R_64f IppsFFTSpec_R_64f; + +typedef struct DFTSpec_C_32fc IppsDFTSpec_C_32fc; +typedef struct DFTSpec_C_32f IppsDFTSpec_C_32f; +typedef struct DFTSpec_R_32f IppsDFTSpec_R_32f; + +typedef struct DFTSpec_C_64fc IppsDFTSpec_C_64fc; +typedef struct DFTSpec_C_64f IppsDFTSpec_C_64f; +typedef struct DFTSpec_R_64f IppsDFTSpec_R_64f; + +typedef struct DCTFwdSpec_32f IppsDCTFwdSpec_32f; +typedef struct DCTInvSpec_32f IppsDCTInvSpec_32f; + +typedef struct DCTFwdSpec_64f IppsDCTFwdSpec_64f; +typedef struct DCTInvSpec_64f IppsDCTInvSpec_64f; + +typedef struct sWTFwdState_32f IppsWTFwdState_32f; +typedef struct sWTFwdState_8u32f IppsWTFwdState_8u32f; +typedef struct sWTFwdState_16s32f IppsWTFwdState_16s32f; +typedef struct sWTFwdState_16u32f IppsWTFwdState_16u32f; +typedef struct sWTInvState_32f IppsWTInvState_32f; +typedef struct sWTInvState_32f8u IppsWTInvState_32f8u; +typedef struct sWTInvState_32f16s IppsWTInvState_32f16s; +typedef struct sWTInvState_32f16u IppsWTInvState_32f16u; + +typedef struct IIRState_32f IppsIIRState_32f; +typedef struct IIRState_32fc IppsIIRState_32fc; +typedef struct IIRState32f_16s IppsIIRState32f_16s; +typedef struct IIRState32fc_16sc IppsIIRState32fc_16sc; +typedef struct IIRState_64f IppsIIRState_64f; +typedef struct IIRState_64fc IppsIIRState_64fc; +typedef struct IIRState64f_32f IppsIIRState64f_32f; +typedef struct IIRState64fc_32fc IppsIIRState64fc_32fc; +typedef struct IIRState64f_32s IppsIIRState64f_32s; +typedef struct IIRState64fc_32sc IppsIIRState64fc_32sc; +typedef struct IIRState64f_16s IppsIIRState64f_16s; +typedef struct IIRState64fc_16sc IppsIIRState64fc_16sc; + +typedef struct FIRSpec_32f IppsFIRSpec_32f; +typedef struct FIRSpec_64f IppsFIRSpec_64f; +typedef struct FIRSpec_32fc IppsFIRSpec_32fc; +typedef struct FIRSpec_64fc IppsFIRSpec_64fc; + +typedef struct FIRLMSState_32f IppsFIRLMSState_32f; +typedef struct FIRLMSState32f_16s IppsFIRLMSState32f_16s; + +typedef struct HilbertSpec IppsHilbertSpec; + +typedef struct FIRSparseState_32f IppsFIRSparseState_32f; +typedef struct IIRSparseState_32f IppsIIRSparseState_32f; + +typedef struct ResamplingPolyphase_16s IppsResamplingPolyphase_16s; +typedef struct ResamplingPolyphaseFixed_16s IppsResamplingPolyphaseFixed_16s; +typedef struct ResamplingPolyphase_32f IppsResamplingPolyphase_32f; +typedef struct ResamplingPolyphaseFixed_32f IppsResamplingPolyphaseFixed_32f; + +#endif /* _OWN_BLDPCS */ + +/*****************************************************************************/ +/* Below are ippIP domain specific definitions */ +/*****************************************************************************/ +#define IPP_TEMPORAL_COPY 0x0 +#define IPP_NONTEMPORAL_STORE 0x01 +#define IPP_NONTEMPORAL_LOAD 0x02 + +typedef int IppEnum; + +#define IPP_DEG_TO_RAD( deg ) ( (deg)/180.0 * IPP_PI ) + +typedef enum { + ippiNormNone = 0x00000000, /* default */ + ippiNorm = 0x00000100, /* normalized form */ + ippiNormCoefficient = 0x00000200, /* correlation coefficient in the range [-1.0 ... 1.0] */ + ippiNormMask = 0x0000FF00 +} IppiNormOp; + +typedef enum { + ippiROIFull = 0x00000000, + ippiROIValid = 0x00010000, + ippiROISame = 0x00020000, + ippiROIMask = 0x00FF0000 +} IppiROIShape; + +typedef enum { + ippC0 = 0, + ippC1 = 1, + ippC2 = 2, + ippC3 = 3, + ippC4 = 4, + ippP2 = 5, + ippP3 = 6, + ippP4 = 7, + ippAC1 = 8, + ippAC4 = 9, + ippA0C4 = 10, + ippAP4 = 11 +} IppChannels; + +typedef enum _IppiBorderType { + ippBorderConst = 0, + ippBorderRepl = 1, + ippBorderWrap = 2, + ippBorderMirror = 3, /* left border: 012... -> 21012... */ + ippBorderMirrorR = 4, /* left border: 012... -> 210012... */ + ippBorderInMem = 6, + ippBorderTransp = 7, + ippBorderInMemTop = 0x0010, + ippBorderInMemBottom = 0x0020, + ippBorderInMemLeft = 0x0040, + ippBorderInMemRight = 0x0080 +} IppiBorderType; + +typedef enum { + ippAxsHorizontal, + ippAxsVertical, + ippAxsBoth, + ippAxs45, + ippAxs135 +} IppiAxis; + +typedef struct { + int x; + int y; + int width; + int height; +} IppiRect; + +typedef struct { + int x; + int y; +} IppiPoint; + +typedef struct { + int width; + int height; +} IppiSize; + +typedef struct { + Ipp32f x; + Ipp32f y; +} IppiPoint_32f; + +typedef enum _IppiMaskSize { + ippMskSize1x3 = 13, + ippMskSize1x5 = 15, + ippMskSize3x1 = 31, + ippMskSize3x3 = 33, + ippMskSize5x1 = 51, + ippMskSize5x5 = 55 +} IppiMaskSize; + +enum { + IPPI_INTER_NN = 1, + IPPI_INTER_LINEAR = 2, + IPPI_INTER_CUBIC = 4, + IPPI_INTER_CUBIC2P_BSPLINE, /* two-parameter cubic filter (B=1, C=0) */ + IPPI_INTER_CUBIC2P_CATMULLROM, /* two-parameter cubic filter (B=0, C=1/2) */ + IPPI_INTER_CUBIC2P_B05C03, /* two-parameter cubic filter (B=1/2, C=3/10) */ + IPPI_INTER_SUPER = 8, + IPPI_INTER_LANCZOS = 16, + IPPI_ANTIALIASING = (1 << 29), + IPPI_SUBPIXEL_EDGE = (1 << 30), + IPPI_SMOOTH_EDGE = (1 << 31) +}; + +typedef enum { + ippNearest = IPPI_INTER_NN, + ippLinear = IPPI_INTER_LINEAR, + ippCubic = IPPI_INTER_CUBIC2P_CATMULLROM, + ippLanczos = IPPI_INTER_LANCZOS, + ippHahn = 0, + ippSuper = IPPI_INTER_SUPER +} IppiInterpolationType; + +typedef enum { + ippPolyphase_1_2, + ippPolyphase_3_5, + ippPolyphase_2_3, + ippPolyphase_7_10, + ippPolyphase_3_4 +} IppiFraction; + +enum { + IPP_FASTN_ORIENTATION = 0x0001, + IPP_FASTN_NMS = 0x0002, + IPP_FASTN_CIRCLE = 0X0004, + IPP_FASTN_SCORE_MODE0 = 0X0020 +}; + +#if !defined( _OWN_BLDPCS ) + +typedef enum { + ippAlphaOver, + ippAlphaIn, + ippAlphaOut, + ippAlphaATop, + ippAlphaXor, + ippAlphaPlus, + ippAlphaOverPremul, + ippAlphaInPremul, + ippAlphaOutPremul, + ippAlphaATopPremul, + ippAlphaXorPremul, + ippAlphaPlusPremul +} IppiAlphaType; + +typedef struct DeconvFFTState_32f_C1R IppiDeconvFFTState_32f_C1R; +typedef struct DeconvFFTState_32f_C3R IppiDeconvFFTState_32f_C3R; +typedef struct DeconvLR_32f_C1R IppiDeconvLR_32f_C1R; +typedef struct DeconvLR_32f_C3R IppiDeconvLR_32f_C3R; + +typedef enum { + ippiFilterBilateralGauss = 100, + ippiFilterBilateralGaussFast = 101 +} IppiFilterBilateralType; + +typedef struct FilterBilateralSpec IppiFilterBilateralSpec; + +typedef enum { + ippDistNormL1 = 0x00000002 +} IppiDistanceMethodType; + +typedef enum { + ippResizeFilterHann, + ippResizeFilterLanczos +} IppiResizeFilterType; + +typedef struct ResizeFilterState IppiResizeFilterState; + +typedef struct { + Ipp32u borderLeft; + Ipp32u borderTop; + Ipp32u borderRight; + Ipp32u borderBottom; +} IppiBorderSize; + +typedef enum { + ippWarpForward, + ippWarpBackward, +} IppiWarpDirection; + +typedef enum { + ippWarpAffine, + ippWarpPerspective, + ippWarpBilinear, +} IppiWarpTransformType; + + +typedef struct ResizeSpec_32f IppiResizeSpec_32f; +typedef struct ResizeYUV422Spec IppiResizeYUV422Spec; +typedef struct ResizeYUV420Spec IppiResizeYUV420Spec; + +typedef struct ResizeSpec_64f IppiResizeSpec_64f; + +typedef struct IppiWarpSpec IppiWarpSpec; + +typedef struct FilterBorderSpec IppiFilterBorderSpec; + +typedef struct ThresholdAdaptiveSpec IppiThresholdAdaptiveSpec; + +typedef struct HistogramSpec IppiHistogramSpec; + +typedef struct { + int cvCompatible; /* openCV compatible output format */ + int cellSize; /* squre cell size (pixels) */ + int blockSize; /* square block size (pixels) */ + int blockStride; /* block displacement (the same for x- and y- directions) */ + int nbins; /* required number of bins */ + Ipp32f sigma; /* gaussian factor of HOG block weights */ + Ipp32f l2thresh; /* normalization factor */ + IppiSize winSize; /* detection window size (pixels) */ +} IppiHOGConfig; + +typedef struct FFT2DSpec_C_32fc IppiFFTSpec_C_32fc; +typedef struct FFT2DSpec_R_32f IppiFFTSpec_R_32f; + +typedef struct DFT2DSpec_C_32fc IppiDFTSpec_C_32fc; +typedef struct DFT2DSpec_R_32f IppiDFTSpec_R_32f; + +typedef struct DCT2DFwdSpec_32f IppiDCTFwdSpec_32f; +typedef struct DCT2DInvSpec_32f IppiDCTInvSpec_32f; + +typedef struct iWTFwdSpec_32f_C1R IppiWTFwdSpec_32f_C1R; +typedef struct iWTInvSpec_32f_C1R IppiWTInvSpec_32f_C1R; +typedef struct iWTFwdSpec_32f_C3R IppiWTFwdSpec_32f_C3R; +typedef struct iWTInvSpec_32f_C3R IppiWTInvSpec_32f_C3R; + +typedef struct MomentState64f IppiMomentState_64f; +typedef Ipp64f IppiHuMoment_64f[7]; + +typedef struct LUT_Spec IppiLUT_Spec; + +#define IPP_HOG_MAX_CELL (16) /* max size of CELL */ +#define IPP_HOG_MAX_BLOCK (64) /* max size of BLOCK */ +#define IPP_HOG_MAX_BINS (16) /* max number of BINS */ + +typedef struct _ipHOG IppiHOGSpec; + +#endif /* _OWN_BLDPCS */ + + + /**** Below are 3D Image (Volume) Processing specific definitions ****/ + +typedef struct { + int width; + int height; + int depth; +} IpprVolume; + +typedef struct { + int x; + int y; + int z; + int width; + int height; + int depth; +} IpprCuboid; + +typedef struct { + int x; + int y; + int z; +} IpprPoint; + +/*****************************************************************************/ +/* Below are ippCV domain specific definitions */ +/*****************************************************************************/ + +typedef enum _IppiDifferentialKernel +{ + ippFilterSobelVert, + ippFilterSobelHoriz, + ippFilterSobel, + ippFilterScharrVert, + ippFilterScharrHoriz, + ippFilterScharr, + ippFilterCentralDiffVert, + ippFilterCentralDiffHoriz, + ippFilterCentralDiff, +}IppiDifferentialKernel; + +#if !defined( _OWN_BLDPCS ) + +typedef enum _IppiKernelType { + ippKernelSobel = 0, + ippKernelScharr = 1, + ippKernelSobelNeg = 2 +} IppiKernelType; + +typedef enum _IppiNorm { + ippiNormInf = 0, + ippiNormL1 = 1, + ippiNormL2 = 2, + ippiNormFM = 3 +} IppiNorm; + +typedef struct ipcvMorphState IppiMorphState; +typedef struct ipcvMorphAdvState IppiMorphAdvState; +typedef struct ipcvMorphGrayState_8u IppiMorphGrayState_8u; +typedef struct ipcvMorphGrayState_32f IppiMorphGrayState_32f; + +typedef struct ipcvConvState IppiConvState; + +typedef struct _IppiConnectedComp { + Ipp64f area; /* area of the segmented component */ + Ipp64f value[3];/* gray scale value of the segmented component */ + IppiRect rect; /* bounding rectangle of the segmented component */ +} IppiConnectedComp; + +typedef struct PyramidState IppiPyramidState; + +typedef IppiPyramidState IppiPyramidDownState_8u_C1R; +typedef IppiPyramidState IppiPyramidDownState_16u_C1R; +typedef IppiPyramidState IppiPyramidDownState_32f_C1R; +typedef IppiPyramidState IppiPyramidDownState_8u_C3R; +typedef IppiPyramidState IppiPyramidDownState_16u_C3R; +typedef IppiPyramidState IppiPyramidDownState_32f_C3R; +typedef IppiPyramidState IppiPyramidUpState_8u_C1R; +typedef IppiPyramidState IppiPyramidUpState_16u_C1R; +typedef IppiPyramidState IppiPyramidUpState_32f_C1R; +typedef IppiPyramidState IppiPyramidUpState_8u_C3R; +typedef IppiPyramidState IppiPyramidUpState_16u_C3R; +typedef IppiPyramidState IppiPyramidUpState_32f_C3R; + + +typedef struct _IppiPyramid { + Ipp8u **pImage; + IppiSize *pRoi; + Ipp64f *pRate; + int *pStep; + Ipp8u *pState; + int level; +} IppiPyramid; + +typedef struct OptFlowPyrLK IppiOptFlowPyrLK; + +typedef IppiOptFlowPyrLK IppiOptFlowPyrLK_8u_C1R; +typedef IppiOptFlowPyrLK IppiOptFlowPyrLK_16u_C1R; +typedef IppiOptFlowPyrLK IppiOptFlowPyrLK_32f_C1R; + +typedef struct ipcvHaarClassifier_32f IppiHaarClassifier_32f; +typedef struct ipcvHaarClassifier_32s IppiHaarClassifier_32s; + +typedef struct ipcvFGHistogramState_8u_C1R IppFGHistogramState_8u_C1R; +typedef struct ipcvFGHistogramState_8u_C3R IppFGHistogramState_8u_C3R; + +typedef struct ipcvFGGaussianState_8u_C1R IppFGGaussianState_8u_C1R; +typedef struct ipcvFGGaussianState_8u_C3R IppFGGaussianState_8u_C3R; + +typedef enum _IppiInpaintFlag { + IPP_INPAINT_TELEA = 0, + IPP_INPAINT_NS = 1 +} IppiInpaintFlag; + +typedef struct ippcvFilterGaussianSpec IppFilterGaussianSpec; + +typedef struct ipcvInpaintState_8u IppiInpaintState_8u_C1R; +typedef struct ipcvInpaintState_8u IppiInpaintState_8u_C3R; + +typedef struct HoughProbSpec IppiHoughProbSpec; + +typedef struct FastNSpec IppiFastNSpec; + +typedef struct _IppiCornerFastN { + int x; + int y; + int cornerType; + int orientation; + float angle; + float score; +} IppiCornerFastN; + +typedef struct FGMMState_8u_C3R IppFGMMState_8u_C3R; + +typedef struct +{ + unsigned int numFrames; + unsigned int maxNGauss; + Ipp32f varInit; + Ipp32f varMin; + Ipp32f varMax; + Ipp32f varWBRatio; + Ipp32f bckgThr; + Ipp32f varNGRatio; + Ipp32f reduction; + Ipp8u shadowValue; + char shadowFlag; + Ipp32f shadowRatio; +} IppFGMModel; + +#endif /* _OWN_BLDPCS */ + +#define IPP_SEGMENT_QUEUE 0x01 +#define IPP_SEGMENT_DISTANCE 0x02 +#define IPP_SEGMENT_BORDER_4 0x40 +#define IPP_SEGMENT_BORDER_8 0x80 + +#define IPP_TRUNC(a,b) ((a)&~((b)-1)) +#define IPP_APPEND(a,b) (((a)+(b)-1)&~((b)-1)) + +/*****************************************************************************/ +/* Below are ippCC domain specific definitions */ +/*****************************************************************************/ +enum { + IPP_UPPER = 1, + IPP_LEFT = 2, + IPP_CENTER = 4, + IPP_RIGHT = 8, + IPP_LOWER = 16, + IPP_UPPER_LEFT = 32, + IPP_UPPER_RIGHT = 64, + IPP_LOWER_LEFT = 128, + IPP_LOWER_RIGHT = 256 +}; + +#if !defined( _OWN_BLDPCS ) + +typedef enum { + ippDitherNone, + ippDitherFS, + ippDitherJJN, + ippDitherStucki, + ippDitherBayer +} IppiDitherType; + +#endif /* _OWN_BLDPCS */ + +/*****************************************************************************/ +/* Below are ippCH domain specific definitions */ +/*****************************************************************************/ + +#if !defined( _OWN_BLDPCS ) + +typedef struct { + void *pFind; + int lenFind; +} IppRegExpFind; + +typedef struct RegExpState IppRegExpState; + +typedef enum { + ippFmtASCII = 0, + ippFmtUTF8 +} IppRegExpFormat; + +typedef struct RegExpReplaceState IppRegExpReplaceState; + +#endif /* _OWN_BLDPCS */ + +/*****************************************************************************/ +/* Below are ippDC domain specific definitions */ +/*****************************************************************************/ + +#if !defined ( _OWN_BLDPCS ) + +typedef struct MTFState_8u IppMTFState_8u; + +typedef enum { + ippBWTItohTanakaLimSort, + ippBWTItohTanakaUnlimSort, + ippBWTSuffixSort, + ippBWTAutoSort +} IppBWTSortAlgorithmHint; + +typedef struct LZSSState_8u IppLZSSState_8u; + +typedef struct LZ77State_8u IppLZ77State_8u; +typedef enum{ + IppLZ77FastCompr, + IppLZ77AverageCompr, + IppLZ77BestCompr +} IppLZ77ComprLevel; +typedef enum{ + IppLZ77NoChcksm, + IppLZ77Adler32, + IppLZ77CRC32 +} IppLZ77Chcksm; +typedef enum { + IppLZ77NoFlush, + IppLZ77SyncFlush, + IppLZ77FullFlush, + IppLZ77FinishFlush +} IppLZ77Flush; +typedef struct IppLZ77Pairs_16u { + Ipp16u length; + Ipp16u offset; +} IppLZ77Pair; +typedef enum { + IppLZ77StatusInit, + IppLZ77StatusLZ77Process, + IppLZ77StatusHuffProcess, + IppLZ77StatusFinal +} IppLZ77DeflateStatus; +typedef enum { + IppLZ77UseFixed, + IppLZ77UseDynamic, + IppLZ77UseStored +} IppLZ77HuffMode; +typedef enum { + IppLZ77InflateStatusInit, + IppLZ77InflateStatusHuffProcess, + IppLZ77InflateStatusLZ77Process, + IppLZ77InflateStatusFinal +} IppLZ77InflateStatus; + +typedef struct IppInflateState { + const Ipp8u* pWindow; /* pointer to the sliding window + (the dictionary for the LZ77 algorithm) */ + unsigned int winSize; /* size of the sliding window */ + unsigned int tableType; /* type of Huffman code tables + (for example, 0 - tables for Fixed Huffman codes) */ + unsigned int tableBufferSize; /* (ENOUGH = 2048) * (sizeof(code) = 4) - + sizeof(IppInflateState) */ +} IppInflateState; + +typedef enum { /* this type is used as a translator of the inflate_mode type from zlib */ + ippTYPE, + ippLEN, + ippLENEXT +} IppInflateMode; + +typedef struct { + Ipp16u freq; + Ipp16u code; +} IppDeflateFreqTable; + +typedef struct { + Ipp16u code; + Ipp16u len; +} IppDeflateHuffCode; + +typedef struct RLEState_BZ2 IppRLEState_BZ2; + +typedef struct EncodeHuffState_BZ2 IppEncodeHuffState_BZ2; + +typedef struct DecodeHuffState_BZ2 IppDecodeHuffState_BZ2; + +typedef enum { + IppLZO1XST, /* Single-threaded, generic LZO-compatible*/ + IppLZO1XMT /* Multi-threaded */ +} IppLZOMethod ; + +typedef struct LZOState_8u IppLZOState_8u; + +#endif /* _OWN_BLDPCS */ + +/* ///////////////////////////////////////////////////////////////////////////// +// The following enumerator defines a status of IPP operations +// negative value means error +*/ +typedef enum { + /* errors */ + ippStsNotSupportedModeErr = -9999,/* The requested mode is currently not supported. */ + ippStsCpuNotSupportedErr = -9998,/* The target CPU is not supported. */ + ippStsInplaceModeNotSupportedErr = -9997,/* The inplace operation is currently not supported. */ + + ippStsIIRIIRLengthErr = -234, /* Vector length for IIRIIR function is less than 3*(IIR order) */ + ippStsWarpTransformTypeErr = -233, /* The warp transform type is illegal */ + ippStsExceededSizeErr = -232, /* Requested size exceeded the maximum supported ROI size */ + ippStsWarpDirectionErr = -231, /* The warp transform direction is illegal */ + + ippStsFilterTypeErr = -230, /* The filter type is incorrect or not supported */ + + ippStsNormErr = -229, /* The norm is incorrect or not supported */ + + ippStsAlgTypeErr = -228, /* Algorithm type is not supported. */ + ippStsMisalignedOffsetErr = -227, /* The offset is not aligned with an element. */ + + ippStsQuadraticNonResidueErr = -226, /* SQRT operation on quadratic non-residue value. */ + + ippStsBorderErr = -225, /* Illegal value for border type.*/ + + ippStsDitherTypeErr = -224, /* Dithering type is not supported. */ + ippStsH264BufferFullErr = -223, /* Buffer for the output bitstream is full. */ + ippStsWrongAffinitySettingErr= -222, /* An affinity setting does not correspond to the affinity setting that was set by f.ippSetAffinity(). */ + ippStsLoadDynErr = -221, /* Error when loading the dynamic library. */ + + ippStsPointAtInfinity = -220, /* Point at infinity is detected. */ + + ippStsUnknownStatusCodeErr = -216, /* Unknown status code. */ + + ippStsOFBSizeErr = -215, /* Incorrect value for crypto OFB block size. */ + ippStsLzoBrokenStreamErr = -214, /* LZO safe decompression function cannot decode LZO stream. */ + + ippStsRoundModeNotSupportedErr = -213, /* Rounding mode is not supported. */ + ippStsDecimateFractionErr = -212, /* Fraction in Decimate is not supported. */ + ippStsWeightErr = -211, /* Incorrect value for weight. */ + + ippStsQualityIndexErr = -210, /* Cannot calculate the quality index for an image filled with a constant. */ + ippStsIIRPassbandRippleErr = -209, /* Ripple in passband for Chebyshev1 design is less than zero, equal to zero, or greater than 29. */ + ippStsFilterFrequencyErr = -208, /* Cutoff frequency of filter is less than zero, equal to zero, or greater than 0.5. */ + ippStsFIRGenOrderErr = -207, /* Order of the FIR filter for design is less than 1. */ + ippStsIIRGenOrderErr = -206, /* Order of the IIR filter for design is less than 1, or greater than 12. */ + + ippStsConvergeErr = -205, /* The algorithm does not converge. */ + ippStsSizeMatchMatrixErr = -204, /* The sizes of the source matrices are unsuitable. */ + ippStsCountMatrixErr = -203, /* Count value is less than, or equal to zero. */ + ippStsRoiShiftMatrixErr = -202, /* RoiShift value is negative or not divisible by the size of the data type. */ + + ippStsResizeNoOperationErr = -201, /* One of the output image dimensions is less than 1 pixel. */ + ippStsSrcDataErr = -200, /* The source buffer contains unsupported data. */ + ippStsMaxLenHuffCodeErr = -199, /* Huff: Max length of Huffman code is more than the expected one. */ + ippStsCodeLenTableErr = -198, /* Huff: Invalid codeLenTable. */ + ippStsFreqTableErr = -197, /* Huff: Invalid freqTable. */ + + ippStsIncompleteContextErr = -196, /* Crypto: set up of context is not complete. */ + + ippStsSingularErr = -195, /* Matrix is singular. */ + ippStsSparseErr = -194, /* Positions of taps are not in ascending order, or are negative, or repetitive. */ + ippStsBitOffsetErr = -193, /* Incorrect bit offset value. */ + ippStsQPErr = -192, /* Incorrect quantization parameter value. */ + ippStsVLCErr = -191, /* Illegal VLC or FLC is detected during stream decoding. */ + ippStsRegExpOptionsErr = -190, /* RegExp: Options for the pattern are incorrect. */ + ippStsRegExpErr = -189, /* RegExp: The structure pRegExpState contains incorrect data. */ + ippStsRegExpMatchLimitErr = -188, /* RegExp: The match limit is exhausted. */ + ippStsRegExpQuantifierErr = -187, /* RegExp: Incorrect quantifier. */ + ippStsRegExpGroupingErr = -186, /* RegExp: Incorrect grouping. */ + ippStsRegExpBackRefErr = -185, /* RegExp: Incorrect back reference. */ + ippStsRegExpChClassErr = -184, /* RegExp: Incorrect character class. */ + ippStsRegExpMetaChErr = -183, /* RegExp: Incorrect metacharacter. */ + ippStsStrideMatrixErr = -182, /* Stride value is not positive or not divisible by the size of the data type. */ + ippStsCTRSizeErr = -181, /* Incorrect value for crypto CTR block size. */ + ippStsJPEG2KCodeBlockIsNotAttached =-180, /* Codeblock parameters are not attached to the state structure. */ + ippStsNotPosDefErr = -179, /* Matrix is not positive definite. */ + + ippStsEphemeralKeyErr = -178, /* ECC: Invalid ephemeral key. */ + ippStsMessageErr = -177, /* ECC: Invalid message digest. */ + ippStsShareKeyErr = -176, /* ECC: Invalid share key. */ + ippStsIvalidPublicKey = -175, /* ECC: Invalid public key. */ + ippStsIvalidPrivateKey = -174, /* ECC: Invalid private key. */ + ippStsOutOfECErr = -173, /* ECC: Point out of EC. */ + ippStsECCInvalidFlagErr = -172, /* ECC: Invalid Flag. */ + + ippStsMP3FrameHeaderErr = -171, /* Error in fields of the IppMP3FrameHeader structure. */ + ippStsMP3SideInfoErr = -170, /* Error in fields of the IppMP3SideInfo structure. */ + + ippStsBlockStepErr = -169, /* Step for Block is less than 8. */ + ippStsMBStepErr = -168, /* Step for MB is less than 16. */ + + ippStsAacPrgNumErr = -167, /* AAC: Invalid number of elements for one program. */ + ippStsAacSectCbErr = -166, /* AAC: Invalid section codebook. */ + ippStsAacSfValErr = -164, /* AAC: Invalid scalefactor value. */ + ippStsAacCoefValErr = -163, /* AAC: Invalid quantized coefficient value. */ + ippStsAacMaxSfbErr = -162, /* AAC: Invalid coefficient index. */ + ippStsAacPredSfbErr = -161, /* AAC: Invalid predicted coefficient index. */ + ippStsAacPlsDataErr = -160, /* AAC: Invalid pulse data attributes. */ + ippStsAacGainCtrErr = -159, /* AAC: Gain control is not supported. */ + ippStsAacSectErr = -158, /* AAC: Invalid number of sections. */ + ippStsAacTnsNumFiltErr = -157, /* AAC: Invalid number of TNS filters. */ + ippStsAacTnsLenErr = -156, /* AAC: Invalid length of TNS region. */ + ippStsAacTnsOrderErr = -155, /* AAC: Invalid order of TNS filter. */ + ippStsAacTnsCoefResErr = -154, /* AAC: Invalid bit-resolution for TNS filter coefficients. */ + ippStsAacTnsCoefErr = -153, /* AAC: Invalid coefficients of TNS filter. */ + ippStsAacTnsDirectErr = -152, /* AAC: Invalid direction TNS filter. */ + ippStsAacTnsProfileErr = -151, /* AAC: Invalid TNS profile. */ + ippStsAacErr = -150, /* AAC: Internal error. */ + ippStsAacBitOffsetErr = -149, /* AAC: Invalid current bit offset in bitstream. */ + ippStsAacAdtsSyncWordErr = -148, /* AAC: Invalid ADTS syncword. */ + ippStsAacSmplRateIdxErr = -147, /* AAC: Invalid sample rate index. */ + ippStsAacWinLenErr = -146, /* AAC: Invalid window length (not short or long). */ + ippStsAacWinGrpErr = -145, /* AAC: Invalid number of groups for current window length. */ + ippStsAacWinSeqErr = -144, /* AAC: Invalid window sequence range. */ + ippStsAacComWinErr = -143, /* AAC: Invalid common window flag. */ + ippStsAacStereoMaskErr = -142, /* AAC: Invalid stereo mask. */ + ippStsAacChanErr = -141, /* AAC: Invalid channel number. */ + ippStsAacMonoStereoErr = -140, /* AAC: Invalid mono-stereo flag. */ + ippStsAacStereoLayerErr = -139, /* AAC: Invalid this Stereo Layer flag. */ + ippStsAacMonoLayerErr = -138, /* AAC: Invalid this Mono Layer flag. */ + ippStsAacScalableErr = -137, /* AAC: Invalid scalable object flag. */ + ippStsAacObjTypeErr = -136, /* AAC: Invalid audio object type. */ + ippStsAacWinShapeErr = -135, /* AAC: Invalid window shape. */ + ippStsAacPcmModeErr = -134, /* AAC: Invalid PCM output interleaving indicator. */ + ippStsVLCUsrTblHeaderErr = -133, /* VLC: Invalid header inside table. */ + ippStsVLCUsrTblUnsupportedFmtErr = -132, /* VLC: Table format is not supported. */ + ippStsVLCUsrTblEscAlgTypeErr = -131, /* VLC: Ecs-algorithm is not supported. */ + ippStsVLCUsrTblEscCodeLengthErr = -130, /* VLC: Esc-code length inside table header is incorrect. */ + ippStsVLCUsrTblCodeLengthErr = -129, /* VLC: Code length inside table is incorrect. */ + ippStsVLCInternalTblErr = -128, /* VLC: Invalid internal table. */ + ippStsVLCInputDataErr = -127, /* VLC: Invalid input data. */ + ippStsVLCAACEscCodeLengthErr = -126, /* VLC: Invalid AAC-Esc code length. */ + ippStsNoiseRangeErr = -125, /* Noise value for Wiener Filter is out of range. */ + ippStsUnderRunErr = -124, /* Error in data under run. */ + ippStsPaddingErr = -123, /* Detected padding error indicates the possible data corruption. */ + ippStsCFBSizeErr = -122, /* Incorrect value for crypto CFB block size. */ + ippStsPaddingSchemeErr = -121, /* Invalid padding scheme. */ + ippStsInvalidCryptoKeyErr = -120, /* A compromised key causes suspansion of the requested cryptographic operation. */ + ippStsLengthErr = -119, /* Incorrect value for string length. */ + ippStsBadModulusErr = -118, /* Bad modulus caused a failure in module inversion. */ + ippStsLPCCalcErr = -117, /* Cannot evaluate linear prediction. */ + ippStsRCCalcErr = -116, /* Cannot compute reflection coefficients. */ + ippStsIncorrectLSPErr = -115, /* Incorrect values for Linear Spectral Pair. */ + ippStsNoRootFoundErr = -114, /* No roots are found for equation. */ + ippStsJPEG2KBadPassNumber = -113, /* Pass number exceeds allowed boundaries [0,nOfPasses-1]. */ + ippStsJPEG2KDamagedCodeBlock= -112, /* Codeblock for decoding contains damaged data. */ + ippStsH263CBPYCodeErr = -111, /* Illegal Huffman code is detected through CBPY stream processing. */ + ippStsH263MCBPCInterCodeErr = -110, /* Illegal Huffman code is detected through MCBPC Inter stream processing. */ + ippStsH263MCBPCIntraCodeErr = -109, /* Illegal Huffman code is detected through MCBPC Intra stream processing. */ + ippStsNotEvenStepErr = -108, /* Step value is not pixel multiple. */ + ippStsHistoNofLevelsErr = -107, /* Number of levels for histogram is less than 2. */ + ippStsLUTNofLevelsErr = -106, /* Number of levels for LUT is less than 2. */ + ippStsMP4BitOffsetErr = -105, /* Incorrect bit offset value. */ + ippStsMP4QPErr = -104, /* Incorrect quantization parameter. */ + ippStsMP4BlockIdxErr = -103, /* Incorrect block index. */ + ippStsMP4BlockTypeErr = -102, /* Incorrect block type. */ + ippStsMP4MVCodeErr = -101, /* Illegal Huffman code is detected during MV stream processing. */ + ippStsMP4VLCCodeErr = -100, /* Illegal Huffman code is detected during VLC stream processing. */ + ippStsMP4DCCodeErr = -99, /* Illegal code is detected during DC stream processing. */ + ippStsMP4FcodeErr = -98, /* Incorrect fcode value. */ + ippStsMP4AlignErr = -97, /* Incorrect buffer alignment . */ + ippStsMP4TempDiffErr = -96, /* Incorrect temporal difference. */ + ippStsMP4BlockSizeErr = -95, /* Incorrect size of a block or macroblock. */ + ippStsMP4ZeroBABErr = -94, /* All BAB values are equal to zero. */ + ippStsMP4PredDirErr = -93, /* Incorrect prediction direction. */ + ippStsMP4BitsPerPixelErr = -92, /* Incorrect number of bits per pixel. */ + ippStsMP4VideoCompModeErr = -91, /* Incorrect video component mode. */ + ippStsMP4LinearModeErr = -90, /* Incorrect DC linear mode. */ + ippStsH263PredModeErr = -83, /* Incorrect Prediction Mode value. */ + ippStsH263BlockStepErr = -82, /* The step value is less than 8. */ + ippStsH263MBStepErr = -81, /* The step value is less than 16. */ + ippStsH263FrameWidthErr = -80, /* The frame width is less than 8. */ + ippStsH263FrameHeightErr = -79, /* The frame height is less than, or equal to zero. */ + ippStsH263ExpandPelsErr = -78, /* Expand pixels number is less than 8. */ + ippStsH263PlaneStepErr = -77, /* Step value is less than the plane width. */ + ippStsH263QuantErr = -76, /* Quantizer value is less than, or equal to zero, or greater than 31. */ + ippStsH263MVCodeErr = -75, /* Illegal Huffman code is detected during MV stream processing. */ + ippStsH263VLCCodeErr = -74, /* Illegal Huffman code is detected during VLC stream processing. */ + ippStsH263DCCodeErr = -73, /* Illegal code is detected during DC stream processing. */ + ippStsH263ZigzagLenErr = -72, /* Zigzag compact length is more than 64. */ + ippStsFBankFreqErr = -71, /* Incorrect value for the filter bank frequency parameter. */ + ippStsFBankFlagErr = -70, /* Incorrect value for the filter bank parameter. */ + ippStsFBankErr = -69, /* Filter bank is not correctly initialized. */ + ippStsNegOccErr = -67, /* Occupation count is negative. */ + ippStsCdbkFlagErr = -66, /* Incorrect value for the codebook flag parameter. */ + ippStsSVDCnvgErr = -65, /* SVD algorithm does not converge. */ + ippStsJPEGHuffTableErr = -64, /* JPEG Huffman table is destroyed. */ + ippStsJPEGDCTRangeErr = -63, /* JPEG DCT coefficient is out of range. */ + ippStsJPEGOutOfBufErr = -62, /* Attempt to access out of the buffer limits. */ + ippStsDrawTextErr = -61, /* System error in the draw text operation. */ + ippStsChannelOrderErr = -60, /* Incorrect order of the destination channels. */ + ippStsZeroMaskValuesErr = -59, /* All values of the mask are equal to zero. */ + ippStsQuadErr = -58, /* The quadrangle is nonconvex or degenerates into triangle, line, or point */ + ippStsRectErr = -57, /* Size of the rectangle region is less than, or equal to 1. */ + ippStsCoeffErr = -56, /* Incorrect values for transformation coefficients. */ + ippStsNoiseValErr = -55, /* Incorrect value for noise amplitude for dithering. */ + ippStsDitherLevelsErr = -54, /* Number of dithering levels is out of range. */ + ippStsNumChannelsErr = -53, /* Number of channels is incorrect, or not supported. */ + ippStsCOIErr = -52, /* COI is out of range. */ + ippStsDivisorErr = -51, /* Divisor is equal to zero, function is aborted. */ + ippStsAlphaTypeErr = -50, /* Illegal type of image compositing operation. */ + ippStsGammaRangeErr = -49, /* Gamma range bounds is less than, or equal to zero. */ + ippStsGrayCoefSumErr = -48, /* Sum of the conversion coefficients must be less than, or equal to 1. */ + ippStsChannelErr = -47, /* Illegal channel number. */ + ippStsToneMagnErr = -46, /* Tone magnitude is less than, or equal to zero. */ + ippStsToneFreqErr = -45, /* Tone frequency is negative, or greater than, or equal to 0.5. */ + ippStsTonePhaseErr = -44, /* Tone phase is negative, or greater than, or equal to 2*PI. */ + ippStsTrnglMagnErr = -43, /* Triangle magnitude is less than, or equal to zero. */ + ippStsTrnglFreqErr = -42, /* Triangle frequency is negative, or greater than, or equal to 0.5. */ + ippStsTrnglPhaseErr = -41, /* Triangle phase is negative, or greater than, or equal to 2*PI. */ + ippStsTrnglAsymErr = -40, /* Triangle asymmetry is less than -PI, or greater than, or equal to PI. */ + ippStsHugeWinErr = -39, /* Kaiser window is too big. */ + ippStsJaehneErr = -38, /* Magnitude value is negative. */ + ippStsStrideErr = -37, /* Stride value is less than the length of the row. */ + ippStsEpsValErr = -36, /* Negative epsilon value. */ + ippStsWtOffsetErr = -35, /* Invalid offset value for wavelet filter. */ + ippStsAnchorErr = -34, /* Anchor point is outside the mask. */ + ippStsMaskSizeErr = -33, /* Invalid mask size. */ + ippStsShiftErr = -32, /* Shift value is less than zero. */ + ippStsSampleFactorErr = -31, /* Sampling factor is less than, or equal to zero. */ + ippStsSamplePhaseErr = -30, /* Phase value is out of range: 0 <= phase < factor. */ + ippStsFIRMRFactorErr = -29, /* MR FIR sampling factor is less than, or equal to zero. */ + ippStsFIRMRPhaseErr = -28, /* MR FIR sampling phase is negative, or greater than, or equal to the sampling factor. */ + ippStsRelFreqErr = -27, /* Relative frequency value is out of range. */ + ippStsFIRLenErr = -26, /* Length of a FIR filter is less than, or equal to zero. */ + ippStsIIROrderErr = -25, /* Order of an IIR filter is not valid. */ + ippStsDlyLineIndexErr = -24, /* Invalid value for the delay line sample index. */ + ippStsResizeFactorErr = -23, /* Resize factor(s) is less than, or equal to zero. */ + ippStsInterpolationErr = -22, /* Invalid interpolation mode. */ + ippStsMirrorFlipErr = -21, /* Invalid flip mode. */ + ippStsMoment00ZeroErr = -20, /* Moment value M(0,0) is too small to continue calculations. */ + ippStsThreshNegLevelErr = -19, /* Negative value of the level in the threshold operation. */ + ippStsThresholdErr = -18, /* Invalid threshold bounds. */ + ippStsContextMatchErr = -17, /* Context parameter does not match the operation. */ + ippStsFftFlagErr = -16, /* Invalid value for the FFT flag parameter. */ + ippStsFftOrderErr = -15, /* Invalid value for the FFT order parameter. */ + ippStsStepErr = -14, /* Step value is not valid. */ + ippStsScaleRangeErr = -13, /* Scale bounds are out of range. */ + ippStsDataTypeErr = -12, /* Data type is incorrect or not supported. */ + ippStsOutOfRangeErr = -11, /* Argument is out of range, or point is outside the image. */ + ippStsDivByZeroErr = -10, /* An attempt to divide by zero. */ + ippStsMemAllocErr = -9, /* Memory allocated for the operation is not enough.*/ + ippStsNullPtrErr = -8, /* Null pointer error. */ + ippStsRangeErr = -7, /* Incorrect values for bounds: the lower bound is greater than the upper bound. */ + ippStsSizeErr = -6, /* Incorrect value for data size. */ + ippStsBadArgErr = -5, /* Incorrect arg/param of the function. */ + ippStsNoMemErr = -4, /* Not enough memory for the operation. */ + ippStsSAReservedErr3 = -3, /* Unknown/unspecified error, -3. */ + ippStsErr = -2, /* Unknown/unspecified error, -2. */ + ippStsSAReservedErr1 = -1, /* Unknown/unspecified error, -1. */ + + /* no errors */ + ippStsNoErr = 0, /* No errors. */ + + /* warnings */ + ippStsNoOperation = 1, /* No operation has been executed. */ + ippStsMisalignedBuf = 2, /* Misaligned pointer in operation in which it must be aligned. */ + ippStsSqrtNegArg = 3, /* Negative value(s) for the argument in the Sqrt function. */ + ippStsInvZero = 4, /* INF result. Zero value was met by InvThresh with zero level. */ + ippStsEvenMedianMaskSize= 5, /* Even size of the Median Filter mask was replaced with the odd one. */ + ippStsDivByZero = 6, /* Zero value(s) for the divisor in the Div function. */ + ippStsLnZeroArg = 7, /* Zero value(s) for the argument in the Ln function. */ + ippStsLnNegArg = 8, /* Negative value(s) for the argument in the Ln function. */ + ippStsNanArg = 9, /* Argument value is not a number. */ + ippStsJPEGMarker = 10, /* JPEG marker in the bitstream. */ + ippStsResFloor = 11, /* All result values are floored. */ + ippStsOverflow = 12, /* Overflow in the operation. */ + ippStsLSFLow = 13, /* Quantized LP synthesis filter stability check is applied at the low boundary of [0,pi]. */ + ippStsLSFHigh = 14, /* Quantized LP synthesis filter stability check is applied at the high boundary of [0,pi]. */ + ippStsLSFLowAndHigh = 15, /* Quantized LP synthesis filter stability check is applied at both boundaries of [0,pi]. */ + ippStsZeroOcc = 16, /* Zero occupation count. */ + ippStsUnderflow = 17, /* Underflow in the operation. */ + ippStsSingularity = 18, /* Singularity in the operation. */ + ippStsDomain = 19, /* Argument is out of the function domain. */ + ippStsNonIntelCpu = 20, /* The target CPU is not Genuine Intel. */ + ippStsCpuMismatch = 21, /* Cannot set the library for the given CPU. */ + ippStsNoIppFunctionFound = 22, /* Application does not contain Intel IPP function calls. */ + ippStsDllNotFoundBestUsed = 23, /* Dispatcher cannot find the newest version of the Intel IPP dll. */ + ippStsNoOperationInDll = 24, /* The function does nothing in the dynamic version of the library. */ + ippStsInsufficientEntropy= 25, /* Generation of the prime/key failed due to insufficient entropy in the random seed and stimulus bit string. */ + ippStsOvermuchStrings = 26, /* Number of destination strings is more than expected. */ + ippStsOverlongString = 27, /* Length of one of the destination strings is more than expected. */ + ippStsAffineQuadChanged = 28, /* 4th vertex of destination quad is not equal to customer's one. */ + ippStsWrongIntersectROI = 29, /* ROI has no intersection with the source or destination ROI. No operation. */ + ippStsWrongIntersectQuad = 30, /* Quadrangle has no intersection with the source or destination ROI. No operation. */ + ippStsSmallerCodebook = 31, /* Size of created codebook is less than the cdbkSize argument. */ + ippStsSrcSizeLessExpected = 32, /* DC: Size of the source buffer is less than the expected one. */ + ippStsDstSizeLessExpected = 33, /* DC: Size of the destination buffer is less than the expected one. */ + ippStsStreamEnd = 34, /* DC: The end of stream processed. */ + ippStsDoubleSize = 35, /* Width or height of image is odd. */ + ippStsNotSupportedCpu = 36, /* The CPU is not supported. */ + ippStsUnknownCacheSize = 37, /* The CPU is supported, but the size of the cache is unknown. */ + ippStsSymKernelExpected = 38, /* The Kernel is not symmetric. */ + ippStsEvenMedianWeight = 39, /* Even weight of the Weighted Median Filter is replaced with the odd one. */ + ippStsWrongIntersectVOI = 40, /* VOI has no intersection with the source or destination volume. No operation. */ + ippStsI18nMsgCatalogInvalid=41, /* Message Catalog is invalid, English message returned. */ + ippStsI18nGetMessageFail = 42, /* Failed to fetch a localized message, English message returned. For more information use errno on Linux* OS and GetLastError on Windows* OS. */ + ippStsWaterfall = 43, /* Cannot load required library, waterfall is used. */ + ippStsPrevLibraryUsed = 44, /* Cannot load required library, previous dynamic library is used. */ + ippStsLLADisabled = 45, /* OpenMP* Low Level Affinity is disabled. */ + ippStsNoAntialiasing = 46, /* The mode does not support antialiasing. */ + ippStsRepetitiveSrcData = 47, /* DC: The source data is too repetitive. */ + ippStsSizeWrn = 48, /* The size does not allow to perform full operation. */ + ippStsFeatureNotSupported = 49, /* Current CPU doesn't support at least 1 of the desired features. */ + ippStsUnknownFeature = 50, /* At least one of the desired features is unknown. */ + ippStsFeaturesCombination = 51, /* Wrong combination of features. */ + ippStsAccurateModeNotSupported = 52 /* Accurate mode is not supported. */ +} IppStatus; + +#define ippStsOk ippStsNoErr + +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* __IPPTYPES_H__ */ diff --git a/sgx-jvm/linux-sgx/external/crypto_px/include/ippversion.h b/sgx-jvm/linux-sgx/external/crypto_px/include/ippversion.h new file mode 100755 index 0000000000..478ac0b0cf --- /dev/null +++ b/sgx-jvm/linux-sgx/external/crypto_px/include/ippversion.h @@ -0,0 +1,41 @@ +/* +* Copyright (C) 2016 Intel Corporation. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in +* the documentation and/or other materials provided with the +* distribution. +* * Neither the name of Intel Corporation nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ + +#if !defined( __IPPVERSION_H__ ) +#define __IPPVERSION_H__ + +#define IPP_VERSION_MAJOR 9 +#define IPP_VERSION_MINOR 0 +#define IPP_VERSION_UPDATE 2 + +#define IPP_VERSION_STR "9.0.2" + +#endif /* __IPPVERSION_H__ */ diff --git a/sgx-jvm/linux-sgx/external/crypto_px/sources/include/cpudef.h b/sgx-jvm/linux-sgx/external/crypto_px/sources/include/cpudef.h new file mode 100644 index 0000000000..3d9cde6c64 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/crypto_px/sources/include/cpudef.h @@ -0,0 +1,264 @@ +/* +* Copyright (C) 2016 Intel Corporation. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in +* the documentation and/or other materials provided with the +* distribution. +* * Neither the name of Intel Corporation nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ + +#ifndef __CPUDEF_H__ +#define __CPUDEF_H__ + +#include "ippcore.h" + +#if defined( __cplusplus ) +extern "C" { +#endif + +#undef __CDECL +#if defined( _WIN32 ) || defined ( _WIN64 ) + #define __CDECL __cdecl +#else + #define __CDECL +#endif + + +/* Intel CPU informator */ + +typedef struct { + int family; + int stepping; + int model; + int type; + int feature; + int tlb; + int cache; + int mmx; + int freq; + int ssx; + int wni; + int htt; + int pni; + int em64t; + int mni; + int phcores; + int sse41; + int sse42; + int ext_family; + int ext_model; + int movbe_instr; + int avx; + int xsavexgetbv; +} ippIntelCpuId; + +int __CDECL ownGetMaskFeatures( Ipp64u* pFeaturesMask ); +int __CDECL ownGetFeature( Ipp64u MaskOfFeature ); +int __CDECL ipp_is_avx_extension( void ); + +__INT64 __CDECL ipp_get_pentium_counter (void); +int __CDECL ipp_is_mmx_extension (void); +int __CDECL ipp_is_ssx_extension (void); +int __CDECL ipp_is_wni_extension (void); +int __CDECL ipp_is_htt_extension( void ); +int __CDECL ipp_is_pni_extension( void ); +int __CDECL ipp_is_mni_extension( void ); +int __CDECL ipp_is_sse41_extension( void ); +int __CDECL ipp_is_sse42_extension( void ); +int __CDECL ipp_is_movbe( void ); +int __CDECL ipp_get_cores_on_die( void ); +int __CDECL ipp_is_em64t_extension( void ); +int __CDECL ipp_has_cpuid ( void ); +int __CDECL ipp_has_rdtsc( void ); + +void __CDECL ipp_get_pentium_ident ( ippIntelCpuId* cpuid ); +int __CDECL ipp_is_GenuineIntel ( void ); +int __CDECL ipp_max_cpuid_input( void ); +int __CDECL ipp_get_cpuid( int regs[4], int valEAX, int valECX ); +void __CDECL ipp_get_cache_line_size( int* szCacheLine ); + +int __CDECL ipp_isnan( double x ); +int __CDECL ipp_finite( double x ); +int __CDECL ipp_isnan_32f( float x ); +int __CDECL ipp_finite_32f( float x ); +#define ipp_isfinite ipp_finite + +unsigned int __CDECL ipp_control87 ( unsigned int newcw, unsigned int mask ); +unsigned int __CDECL ipp_status87 ( void ); +unsigned int __CDECL ipp_clear87 ( void ); + +unsigned int __CDECL ipp_clear_ssx (void); +/* topology/affinity */ + +/* here are definitions of the CW bits exactly as x87 and ssx have */ + +#define IPP_FPU_MASK_RC 0x0c00 +#define IPP_FPU_MASK_PC 0x0300 +#define IPP_FPU_MASK_RCPC 0x0f00 + +#define IPP_FPU_RC_NEAR 0x0000 +#define IPP_FPU_RC_DOWN 0x0400 +#define IPP_FPU_RC_UP 0x0800 +#define IPP_FPU_RC_ZERO 0x0c00 + +#define IPP_FPU_PC_24 0x0000 +#define IPP_FPU_PC_53 0x0200 +#define IPP_FPU_PC_64 0x0300 + + +unsigned int __CDECL ipp_set_rcpc_fpu( unsigned int newrcpc, unsigned int mask); +void __CDECL ipp_set_cw_fpu( unsigned int cw ); + +#define IPP_SSX_RC_NEAR 0x0000 +#define IPP_SSX_RC_DOWN 0x2000 +#define IPP_SSX_RC_UP 0x4000 +#define IPP_SSX_RC_ZERO 0x6000 +#define IPP_SSX_MASK_RC 0x6000 + + +unsigned int __CDECL ipp_set_rc_ssx( unsigned int newrc ); +void __CDECL ipp_set_cw_ssx( unsigned int cw ); + +/* ================= FPU section ===================== */ + +/* Control bits - disable exceptions */ +#define FPU_EXC_MSK 0x003f /* Exception Masks Mask */ +#define FPU_MSK_INVALID 0x0001 /* invalid operation */ +#define FPU_MSK_DENORMAL 0x0002 /* denormalized operand */ +#define FPU_MSK_ZERODIV 0x0004 /* zero divide */ +#define FPU_MSK_OVERFLOW 0x0008 /* overflow */ +#define FPU_MSK_UNDERFLOW 0x0010 /* underflow */ +#define FPU_MSK_INEXACT 0x0020 /* inexact (precision) */ + +/* Status bits - exceptions */ +#define FPU_EXC_FLG 0x003f /* Exception Flags Mask */ +#define FPU_FLG_INVALID 0x0001 /* invalid operation */ +#define FPU_FLG_DENORMAL 0x0002 /* denormalized operand */ +#define FPU_FLG_ZERODIV 0x0004 /* zero divide */ +#define FPU_FLG_OVERFLOW 0x0008 /* overflow */ +#define FPU_FLG_UNDERFLOW 0x0010 /* underflow */ +#define FPU_FLG_INEXACT 0x0020 /* inexact (precision) */ + +/* Control bits - rounding control */ +#define FPU_RND 0x0c00 /* Rounding Control Mask */ +#define FPU_RND_NEAR 0x0000 /* near */ +#define FPU_RND_DOWN 0x0400 /* down */ +#define FPU_RND_UP 0x0800 /* up */ +#define FPU_RND_CHOP 0x0c00 /* chop */ + +/* Control bits - precision control */ +#define FPU_PRC 0x0300 /* Precision Control Mask */ +#define FPU_PRC_64 0x0300 /* 64 bits */ +#define FPU_PRC_53 0x0200 /* 53 bits */ +#define FPU_PRC_24 0x0000 /* 24 bits */ + +/* Control bits - all masks */ +#define FPU_ALL 0x0f3f /* all masks */ + +/* ============= definition for control/status world ============== */ + +#define FPU_SET_EXC_MASK(mask) ps_set_cw_fpu(mask,FPU_EXC_MSK) +#define FPU_GET_EXC_MASK() (ps_set_cw_fpu(0,0) & FPU_EXC_MSK) + +#define FPU_GET_EXC_FLAG() (ps_get_sw_fpu() & FPU_EXC_FLG) + +#define FPU_SET_RND_MODE(mode) ps_set_cw_fpu(mode,FPU_RND) +#define FPU_GET_RND_MODE() (ps_set_cw_fpu(0,0) & FPU_RND) + +#define FPU_SET_PRC_MODE(mode) ps_set_cw_fpu(mode,FPU_PRC) +#define FPU_GET_PRC_MODE() (ps_set_cw_fpu(0,0) & FPU_PRC) + +unsigned int __CDECL ps_set_cw_fpu( unsigned int newcw, unsigned int msk); +unsigned int __CDECL ps_get_cw_fpu(void); +unsigned int __CDECL ps_get_sw_fpu(void); +unsigned int __CDECL ps_clear_fpu(void); + +/* ======================= SSX section ============================ */ + +/* Control bits - disable exceptions */ +#define SSX_EXC_MSK 0x1f80 /* Disabling exception mask */ +#define SSX_MSK_INEXACT 0x1000 /* precision (inexact) */ +#define SSX_MSK_UNDERFLOW 0x0800 /* underflow */ +#define SSX_MSK_OVERFLOW 0x0400 /* overflow */ +#define SSX_MSK_ZERODIV 0x0200 /* divide by zero */ +#define SSX_MSK_DENORMAL 0x0100 /* denormalized */ +#define SSX_MSK_INVALID 0x0080 /* invalid operation */ + +/* Status bits - exceptions */ +#define SSX_EXC_FLG 0x003f /* Exception flags mask */ +#define SSX_FLG_INEXACT 0x0020 /* precision (inexact) */ +#define SSX_FLG_UNDERFLOW 0x0010 /* underflow */ +#define SSX_FLG_OVERFLOW 0x0008 /* overflow */ +#define SSX_FLG_ZERODIV 0x0004 /* divide by zero */ +#define SSX_FLG_DENORMAL 0x0002 /* denormalized */ +#define SSX_FLG_INVALID 0x0001 /* invalid operation */ + +/* Control bits - rounding control */ +#define SSX_RND 0x6000 /* Rounding control mask */ +#define SSX_RND_NEAR 0x0000 /* near */ +#define SSX_RND_DOWN 0x2000 /* down */ +#define SSX_RND_UP 0x4000 /* up */ +#define SSX_RND_CHOP 0x6000 /* chop */ + +/* Control bits - flush to zero mode */ +#define SSX_FZ 0x8000 /* Flush to zero mask */ +#define SSX_FZ_ENABLE 0x8000 /* flush to zero */ +#define SSX_FZ_DISABLE 0x0000 /* not flush to zero */ + +/* Control bits - denormals are zero mode */ +#define SSX_DAZ 0x0040 /* denorm. are zero mask */ +#define SSX_DAZ_ENABLE 0x0040 /* denorm. are zero */ +#define SSX_DAZ_DISABLE 0x0000 /* denorm. are not zero */ + +#define SSX_ALL 0xffbf /* All masks */ + +/* ==================== definition for SSX register =============== */ + +#define SSX_SET_EXC_MASK(mask) ps_set_ssx(mask,SSX_EXC_MSK) +#define SSX_GET_EXC_MASK() (ps_get_ssx() & SSX_EXC_MSK) + +#define SSX_SET_EXC_FLAG(flag) ps_set_ssx(flag,SSX_EXC_FLG) +#define SSX_GET_EXC_FLAG() (ps_get_ssx() & SSX_EXC_FLG) + +#define SSX_SET_RND_MODE(mode) ps_set_ssx(mode,SSX_RND) +#define SSX_GET_RND_MODE() (ps_get_ssx() & SSX_RND) + +#define SSX_SET_FZ_MODE(mode) ps_set_ssx(mode,SSX_FZ) +#define SSX_GET_FZ_MODE() (ps_get_ssx() & SSX_FZ) + +#define SSX_SET_DAZ_MODE(mode) ps_set_ssx(mode,SSX_DAZ) +#define SSX_GET_DAZ_MODE() (ps_get_ssx() & SSX_DAZ) + +unsigned int __CDECL ps_set_ssx(unsigned int newssx, unsigned int msk); +unsigned int __CDECL ps_get_ssx(void); +unsigned int __CDECL ipp_tst_daz_ssx(void); + +#if defined( __cplusplus ) +} +#endif + +#endif /* __CPUDEF_H__ */ + +/* ////////////////////////// End of file "cpudef.h" //////////////////////// */ diff --git a/sgx-jvm/linux-sgx/external/crypto_px/sources/include/ippver.gen b/sgx-jvm/linux-sgx/external/crypto_px/sources/include/ippver.gen new file mode 100644 index 0000000000..51c4a2d51d --- /dev/null +++ b/sgx-jvm/linux-sgx/external/crypto_px/sources/include/ippver.gen @@ -0,0 +1,56 @@ +/* +* Copyright (C) 2016 Intel Corporation. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in +* the documentation and/or other materials provided with the +* distribution. +* * Neither the name of Intel Corporation nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ + +#if !defined(_IPP_DYNAMIC) || defined(_CORE) +#include "owndefs.h" + +#ifndef _IPP_VERSION +#define _IPP_VERSION "" +#endif + +#define GET_LIB_NAME01(pref) pref ## GetLibVersion + +#define GET_LIB_NAME(pref) GET_LIB_NAME01(pref) + +#define LIBVERNAME s_libVer + +#define SLIBVERNAME LIBVERNAME +#include "ippverstr.gen" + +#include "cpudef.h" + +extern int ippJumpIndexForMergedDLL; + +IPPFUN( const IppLibraryVersion*, GET_LIB_NAME(LIB_PREFIX), (void) ) +{ + return &LIBVERNAME; +} +#endif diff --git a/sgx-jvm/linux-sgx/external/crypto_px/sources/include/ippver.h b/sgx-jvm/linux-sgx/external/crypto_px/sources/include/ippver.h new file mode 100644 index 0000000000..ef6868a967 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/crypto_px/sources/include/ippver.h @@ -0,0 +1,46 @@ +/* +* Copyright (C) 2016 Intel Corporation. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in +* the documentation and/or other materials provided with the +* distribution. +* * Neither the name of Intel Corporation nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ + +#include "ippversion.h" +#ifndef BASE_VERSION +#define BASE_VERSION() IPP_VERSION_MAJOR,IPP_VERSION_MINOR,IPP_VERSION_UPDATE +#endif + +#ifndef STR_VERSION + #ifdef IPP_REVISION + #define STR_VERSION() IPP_VERSION_STR " (r" STR( IPP_REVISION ) ")" + #else + #define STR_VERSION() IPP_VERSION_STR " (-)" + #endif +#endif + + +/* ////////////////////////////// End of file /////////////////////////////// */ diff --git a/sgx-jvm/linux-sgx/external/crypto_px/sources/include/ippverstr.gen b/sgx-jvm/linux-sgx/external/crypto_px/sources/include/ippverstr.gen new file mode 100644 index 0000000000..edbcad3309 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/crypto_px/sources/include/ippverstr.gen @@ -0,0 +1,120 @@ +/* +* Copyright (C) 2016 Intel Corporation. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in +* the documentation and/or other materials provided with the +* distribution. +* * Neither the name of Intel Corporation nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ + +#ifdef _IPP_OMP_STATIC +#define LIB_THREADS " threaded" +#define CORE_THREADS " (threaded)" +#else +#define LIB_THREADS "" +#define CORE_THREADS "" +#endif + +#define GET_LIBRARY_NAME( cpu, is ) #cpu, IPP_LIB_SHORTNAME() " " is " (" #cpu LIB_THREADS ")" + +static const IppLibraryVersion SLIBVERNAME = { + +/* major, minor, update (ex-majorBuild) */ + BASE_VERSION(), + +#if defined IPP_REVISION + IPP_REVISION, +#else + -1, +#endif /* IPP_REVISION */ + +#if defined( _CORE ) + /*GET_LIBRARY_NAME( core )*/ + "core", + "ippCore" CORE_THREADS + +#elif ( _IPP_ARCH == _IPP_ARCH_IA32 ) || ( _IPP_ARCH == _IPP_ARCH_LP32 ) + #if ( _IPP == _IPP_M5 ) + GET_LIBRARY_NAME( m5, "586" ) + #elif ( _IPP == _IPP_H9 ) + GET_LIBRARY_NAME( h9, "AVX2" ) + #elif ( _IPP == _IPP_G9 ) + GET_LIBRARY_NAME( g9, "AVX" ) + #elif ( _IPP == _IPP_P8 ) + GET_LIBRARY_NAME( p8, "SSE4.2" ) + #elif ( _IPPLP32 == _IPPLP32_S8 ) + GET_LIBRARY_NAME( s8, "Atom" ) + #elif ( _IPP == _IPP_V8 ) + GET_LIBRARY_NAME( v8, "SSSE3" ) + #elif ( _IPP == _IPP_W7 ) + GET_LIBRARY_NAME( w7, "SSE2" ) + #else + GET_LIBRARY_NAME( px, "PX" ) + #endif + +#elif ( _IPP_ARCH == _IPP_ARCH_EM64T ) || ( _IPP_ARCH == _IPP_ARCH_LP64 ) + #if ( _IPP32E == _IPP32E_K0 ) + GET_LIBRARY_NAME( k0, "AVX-512F/CD/BW/DQ/VL" ) + #elif ( _IPP32E == _IPP32E_N0 ) + GET_LIBRARY_NAME( n0, "AVX-512F/CD/ER/PF" ) + #elif ( _IPP32E == _IPP32E_E9 ) + GET_LIBRARY_NAME( e9, "AVX" ) + #elif ( _IPP32E == _IPP32E_L9 ) + GET_LIBRARY_NAME( l9, "AVX2" ) + #elif ( _IPP32E == _IPP32E_Y8 ) + GET_LIBRARY_NAME( y8, "SSE4.2" ) + #elif ( _IPPLP64 == _IPPLP64_N8 ) + GET_LIBRARY_NAME( n8, "Atom" ) + #elif ( _IPP32E == _IPP32E_U8 ) + GET_LIBRARY_NAME( u8, "SSSE3" ) + #elif ( _IPP32E == _IPP32E_M7 ) + GET_LIBRARY_NAME( m7, "SSE3" ) + #else + GET_LIBRARY_NAME( mx, "PX" ) + #endif + +#elif ( _IPP_ARCH == _IPP_ARCH_LRB2 ) + #if ( _IPPLRB == _IPPLRB_BX ) + GET_LIBRARY_NAME( bx, "PX" ) + #elif ( _IPPLRB == _IPPLRB_B2 ) + GET_LIBRARY_NAME( b2, "KNC" ) + #endif + +#else + #error ARCH not supported + +#endif + +#if defined( TICKTOCK ) + "+" +#endif + +/* release Version (by Manager) */ + ,STR_VERSION() + +/* BuildDate (by QA person) */ + ,__DATE__ + +}; diff --git a/sgx-jvm/linux-sgx/external/crypto_px/sources/include/owndefs.h b/sgx-jvm/linux-sgx/external/crypto_px/sources/include/owndefs.h new file mode 100644 index 0000000000..6d9b386375 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/crypto_px/sources/include/owndefs.h @@ -0,0 +1,944 @@ +/* +* Copyright (C) 2016 Intel Corporation. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in +* the documentation and/or other materials provided with the +* distribution. +* * Neither the name of Intel Corporation nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ + +#ifndef __OWNDEFS_H__ +#define __OWNDEFS_H__ + +#if defined( _VXWORKS ) + #include + #undef NONE +#endif + +#include "ippdefs.h" + +#if defined(__INTEL_COMPILER) || defined(_MSC_VER) + #define __INLINE static __inline +#elif defined( __GNUC__ ) + #define __INLINE static __inline__ +#else + #define __INLINE static +#endif + +#if defined(__INTEL_COMPILER) + #define __RESTRICT restrict +#elif !defined( __RESTRICT ) + #define __RESTRICT +#endif + +#if defined( IPP_W32DLL ) + #if defined( _MSC_VER ) || defined( __INTEL_COMPILER ) + #define IPPFUN(type,name,arg) __declspec(dllexport) type __STDCALL name arg + #else + #define IPPFUN(type,name,arg) extern type __STDCALL name arg + #endif +#else + #define IPPFUN(type,name,arg) extern type __STDCALL name arg +#endif + + +/* structure represeting 128 bit unsigned integer type */ + +typedef struct{ + Ipp64u low; + Ipp64u high; +}Ipp128u; + +#define _IPP_PX 0 /* pure C-code ia32 */ +#define _IPP_M5 1 /* Quark (Pentium) - x86+x87 ia32 */ +#define _IPP_M6 2 /* Pentium MMX - MMX ia32 */ +#define _IPP_A6 4 /* Pentium III - SSE ia32 */ +#define _IPP_W7 8 /* Pentium 4 - SSE2 ia32 */ +#define _IPP_T7 16 /* Pentium with x64 support (Nocona) - SSE3 ia32 */ +#define _IPP_V8 32 /* Merom - SSSE3 ia32 */ +#define _IPP_P8 64 /* Penryn - SSE4.1 + tick for SSE4.2 ia32 */ +#define _IPP_G9 128 /* SandyBridge (GSSE) - AVX ia32 */ +#define _IPP_H9 256 /* Haswell (AVX2) ia32 */ +#define _IPP_I0 512 /* KNL (AVX-512) ia32 */ +#define _IPP_S0 1024 /* SkyLake Xeon (AVX-512) ia32 */ + +#define _IPPXSC_PX 0 +#define _IPPXSC_S1 1 +#define _IPPXSC_S2 2 +#define _IPPXSC_C2 4 + +#define _IPPLRB_PX 0 +#define _IPPLRB_B1 1 +#define _IPPLRB_B2 2 + +#define _IPP64_PX _IPP_PX +#define _IPP64_I7 64 + +#define _IPP32E_PX _IPP_PX /* pure C-code x64 */ +#define _IPP32E_M7 32 /* Pentium with x64 support (Nocona) - SSE3 x64 */ +#define _IPP32E_U8 64 /* Merom - SSSE3 x64 */ +#define _IPP32E_Y8 128 /* Penryn - SSE4.1 + tick for SSE4.2 x64 */ +#define _IPP32E_E9 256 /* SandyBridge (GSSE) - AVX x64 */ +#define _IPP32E_L9 512 /* Haswell (AVX2) x64 */ +#define _IPP32E_N0 1024 /* KNL (AVX-512) x64 */ +#define _IPP32E_K0 2048 /* SkyLake Xeon (AVX-512) x64 */ + +#define _IPPLP32_PX _IPP_PX +#define _IPPLP32_S8 1 /* old Atom (SSSE3+movbe) (Silverthorne) ia32 */ + +#define _IPPLP64_PX _IPP_PX +#define _IPPLP64_N8 1 /* old Atom (SSSE3+movbe) (Silverthorne) x64 */ + +#if defined(__INTEL_COMPILER) || (_MSC_VER >= 1300) + #define __ALIGN8 __declspec (align(8)) + #define __ALIGN16 __declspec (align(16)) +#if !defined( OSX32 ) + #define __ALIGN32 __declspec (align(32)) +#else + #define __ALIGN32 __declspec (align(16)) +#endif + #define __ALIGN64 __declspec (align(64)) +#elif defined (__GNUC__) + #define __ALIGN8 __attribute((aligned(8))) + #define __ALIGN16 __attribute((aligned(16))) + #define __ALIGN32 __attribute((aligned(32))) + #define __ALIGN64 __attribute((aligned(64))) +#else + #define __ALIGN8 + #define __ALIGN16 + #define __ALIGN32 + #define __ALIGN64 +#endif + +#if defined ( _M5 ) /* Quark (Pentium) - x86+x87 ia32 */ + #define _IPP _IPP_M5 + #define _IPP32E _IPP32E_PX + #define _IPPLRB _IPPLRB_PX + #define _IPPLP32 _IPPLP32_PX + #define _IPPLP64 _IPPLP64_PX + +#elif defined ( _M6 ) /* Pentium MMX - MMX ia32 */ + #define _IPP _IPP_M6 + #define _IPP32E _IPP32E_PX + #define _IPPLRB _IPPLRB_PX + #define _IPPLP32 _IPPLP32_PX + #define _IPPLP64 _IPPLP64_PX + +#elif defined( _A6 ) /* Pentium III - SSE ia32 */ + #define _IPP _IPP_A6 + #define _IPP32E _IPP32E_PX + #define _IPPLRB _IPPLRB_PX + #define _IPPLP32 _IPPLP32_PX + #define _IPPLP64 _IPPLP64_PX + +#elif defined( _W7 ) /* Pentium 4 - SSE2 ia32 */ + #define _IPP _IPP_W7 + #define _IPP32E _IPP32E_PX + #define _IPPLRB _IPPLRB_PX + #define _IPPLP32 _IPPLP32_PX + #define _IPPLP64 _IPPLP64_PX + +#elif defined( _T7 ) /* Pentium with x64 support (Nocona) - SSE3 ia32 */ + #define _IPP _IPP_T7 + #define _IPP32E _IPP32E_PX + #define _IPPLRB _IPPLRB_PX + #define _IPPLP32 _IPPLP32_PX + #define _IPPLP64 _IPPLP64_PX + +#elif defined( _V8 ) /* Merom - SSSE3 ia32 */ + #define _IPP _IPP_V8 + #define _IPP32E _IPP32E_PX + #define _IPPLRB _IPPLRB_PX + #define _IPPLP32 _IPPLP32_PX + #define _IPPLP64 _IPPLP64_PX + +#elif defined( _P8 ) /* Penryn - SSE4.1 + tick for SSE4.2 ia32 */ + #define _IPP _IPP_P8 + #define _IPP32E _IPP32E_PX + #define _IPPLRB _IPPLRB_PX + #define _IPPLP32 _IPPLP32_PX + #define _IPPLP64 _IPPLP64_PX + +#elif defined( _G9 ) /* SandyBridge (GSSE) - AVX ia32 */ + #define _IPP _IPP_G9 + #define _IPP32E _IPP32E_PX + #define _IPPLRB _IPPLRB_PX + #define _IPPLP32 _IPPLP32_PX + #define _IPPLP64 _IPPLP64_PX + +#elif defined( _H9 ) /* Haswell (AVX2) ia32 */ + #define _IPP _IPP_H9 + #define _IPP32E _IPP32E_PX + #define _IPPLRB _IPPLRB_PX + #define _IPPLP32 _IPPLP32_PX + #define _IPPLP64 _IPPLP64_PX + +#elif defined( _M7 ) /* Pentium with x64 support (Nocona) - SSE3 x64 */ + #define _IPP _IPP_PX + #define _IPP32E _IPP32E_M7 + #define _IPPLRB _IPPLRB_PX + #define _IPPLP32 _IPPLP32_PX + #define _IPPLP64 _IPPLP64_PX + +#elif defined( _U8 ) /* Merom - SSSE3 x64 */ + #define _IPP _IPP_PX + #define _IPP32E _IPP32E_U8 + #define _IPPLRB _IPPLRB_PX + #define _IPPLP32 _IPPLP32_PX + #define _IPPLP64 _IPPLP64_PX + +#elif defined( _Y8 ) /* Penryn - SSE4.1 + tick for SSE4.2 x64 */ + #define _IPP _IPP_PX + #define _IPP32E _IPP32E_Y8 + #define _IPPLRB _IPPLRB_PX + #define _IPPLP32 _IPPLP32_PX + #define _IPPLP64 _IPPLP64_PX + +#elif defined( _E9 ) /* SandyBridge (GSSE) - AVX x64 */ + #define _IPP _IPP_PX + #define _IPP32E _IPP32E_E9 + #define _IPPLRB _IPPLRB_PX + #define _IPPLP32 _IPPLP32_PX + #define _IPPLP64 _IPPLP64_PX + +#elif defined( _L9 ) /* Haswell (AVX2) x64 */ + #define _IPP _IPP_PX + #define _IPP32E _IPP32E_L9 + #define _IPPLRB _IPPLRB_PX + #define _IPPLP32 _IPPLP32_PX + #define _IPPLP64 _IPPLP64_PX + +#elif defined( _N0 ) /* KNL (AVX-512) x64 */ + #define _IPP _IPP_PX + #define _IPP32E _IPP32E_N0 + #define _IPPLRB _IPPLRB_PX + #define _IPPLP32 _IPPLP32_PX + #define _IPPLP64 _IPPLP64_PX + +#elif defined( _K0 ) /* SkyLake Xeon (AVX-512) x64 */ + #define _IPP _IPP_PX + #define _IPP32E _IPP32E_K0 + #define _IPPLRB _IPPLRB_PX + #define _IPPLP32 _IPPLP32_PX + #define _IPPLP64 _IPPLP64_PX + +#elif defined( _B2 ) /* KNC (MIC) */ + #define _IPP _IPP_PX + #define _IPP32E _IPP32E_PX + #define _IPPLRB _IPPLRB_B2 + #define _IPPLP32 _IPPLP32_PX + #define _IPPLP64 _IPPLP64_PX + +#elif defined( _S8 ) /* old Atom (SSSE3+movbe) (Silverthorne) ia32 */ + #define _IPP _IPP_V8 + #define _IPP32E _IPP32E_PX + #define _IPPLRB _IPPLRB_PX + #define _IPPLP32 _IPPLP32_S8 + #define _IPPLP64 _IPPLP64_PX + +#elif defined( _N8 ) /* old Atom (SSSE3+movbe) (Silverthorne) x64 */ + #define _IPP _IPP_PX + #define _IPP32E _IPP32E_U8 + #define _IPPLRB _IPPLRB_PX + #define _IPPLP32 _IPPLP32_PX + #define _IPPLP64 _IPPLP64_N8 + +#else + #define _IPP _IPP_PX + #define _IPP32E _IPP32E_PX + #define _IPPLRB _IPPLRB_PX + #define _IPPLP32 _IPPLP32_PX + #define _IPPLP64 _IPPLP64_PX + +#endif + + +#define _IPP_ARCH_IA32 1 +#define _IPP_ARCH_IA64 2 +#define _IPP_ARCH_EM64T 4 +#define _IPP_ARCH_XSC 8 +#define _IPP_ARCH_LRB 16 +#define _IPP_ARCH_LP32 32 +#define _IPP_ARCH_LP64 64 +#define _IPP_ARCH_LRB2 128 + +#if defined ( _ARCH_IA32 ) + #define _IPP_ARCH _IPP_ARCH_IA32 + +#elif defined( _ARCH_EM64T ) + #define _IPP_ARCH _IPP_ARCH_EM64T + +#elif defined( _ARCH_LRB2 ) + #define _IPP_ARCH _IPP_ARCH_LRB2 + +#elif defined( _ARCH_LP32 ) + #define _IPP_ARCH _IPP_ARCH_LP32 + +#elif defined( _ARCH_LP64 ) + #define _IPP_ARCH _IPP_ARCH_LP64 + +#else + #if defined(_M_AMD64) || defined(__x86_64) || defined(__x86_64__) + #define _IPP_ARCH _IPP_ARCH_EM64T + + #else + #define _IPP_ARCH _IPP_ARCH_IA32 + + #endif +#endif + +#if ((_IPP_ARCH == _IPP_ARCH_IA32) || (_IPP_ARCH == _IPP_ARCH_LP32)) +__INLINE +Ipp32s IPP_INT_PTR( const void* ptr ) { + union { + void* Ptr; + Ipp32s Int; + } dd; + dd.Ptr = (void*)ptr; + return dd.Int; +} + +__INLINE +Ipp32u IPP_UINT_PTR( const void* ptr ) { + union { + void* Ptr; + Ipp32u Int; + } dd; + dd.Ptr = (void*)ptr; + return dd.Int; +} +#elif ((_IPP_ARCH == _IPP_ARCH_EM64T) || (_IPP_ARCH == _IPP_ARCH_LRB2) || (_IPP_ARCH == _IPP_ARCH_LP64)) +__INLINE +Ipp64s IPP_INT_PTR( const void* ptr ) { + union { + void* Ptr; + Ipp64s Int; + } dd; + dd.Ptr = (void*)ptr; + return dd.Int; +} + +__INLINE +Ipp64u IPP_UINT_PTR( const void* ptr ) { + union { + void* Ptr; + Ipp64u Int; + } dd; + dd.Ptr = (void*)ptr; + return dd.Int; +} +#else + #define IPP_INT_PTR( ptr ) ( (long)(ptr) ) + #define IPP_UINT_PTR( ptr ) ( (unsigned long)(ptr) ) +#endif + +#define IPP_ALIGN_TYPE(type, align) ((align)/sizeof(type)-1) +#define IPP_BYTES_TO_ALIGN(ptr, align) ((-(IPP_INT_PTR(ptr)&((align)-1)))&((align)-1)) +#define IPP_ALIGNED_PTR(ptr, align) (void*)( (unsigned char*)(ptr) + (IPP_BYTES_TO_ALIGN( ptr, align )) ) + +#define IPP_ALIGNED_SIZE(size, align) (((size)+(align)-1)&~((align)-1)) + +#define IPP_MALLOC_ALIGNED_BYTES 64 +#define IPP_MALLOC_ALIGNED_8BYTES 8 +#define IPP_MALLOC_ALIGNED_16BYTES 16 +#define IPP_MALLOC_ALIGNED_32BYTES 32 + +#define IPP_ALIGNED_ARRAY(align,arrtype,arrname,arrlength)\ + char arrname##AlignedArrBuff[sizeof(arrtype)*(arrlength)+IPP_ALIGN_TYPE(char, align)];\ + arrtype *arrname = (arrtype*)IPP_ALIGNED_PTR(arrname##AlignedArrBuff,align) + +#if defined( __cplusplus ) +extern "C" { +#endif + +/* ///////////////////////////////////////////////////////////////////////////// + + IPP Context Identification + + /////////////////////////////////////////////////////////////////////////// */ + +#define IPP_CONTEXT( a, b, c, d) \ + (int)(((unsigned)(a) << 24) | ((unsigned)(b) << 16) | \ + ((unsigned)(c) << 8) | (unsigned)(d)) + +typedef enum { + idCtxUnknown = 0, + idCtxFFT_C_16sc, + idCtxFFT_C_16s, + idCtxFFT_R_16s, + idCtxFFT_C_32fc, + idCtxFFT_C_32f, + idCtxFFT_R_32f, + idCtxFFT_C_64fc, + idCtxFFT_C_64f, + idCtxFFT_R_64f, + idCtxDFT_C_16sc, + idCtxDFT_C_16s, + idCtxDFT_R_16s, + idCtxDFT_C_32fc, + idCtxDFT_C_32f, + idCtxDFT_R_32f, + idCtxDFT_C_64fc, + idCtxDFT_C_64f, + idCtxDFT_R_64f, + idCtxDCTFwd_16s, + idCtxDCTInv_16s, + idCtxDCTFwd_32f, + idCtxDCTInv_32f, + idCtxDCTFwd_64f, + idCtxDCTInv_64f, + idCtxFFT2D_C_32fc, + idCtxFFT2D_R_32f, + idCtxDFT2D_C_32fc, + idCtxDFT2D_R_32f, + idCtxFFT2D_R_32s, + idCtxDFT2D_R_32s, + idCtxDCT2DFwd_32f, + idCtxDCT2DInv_32f, + idCtxMoment64f, + idCtxMoment64s, + idCtxRandUni_8u, + idCtxRandUni_16s, + idCtxRandUni_32f, + idCtxRandUni_64f, + idCtxRandGauss_8u, + idCtxRandGauss_16s, + idCtxRandGauss_32f, + idCtxRandGauss_64f, + idCtxWTFwd_32f, + idCtxWTFwd_8u32f, + idCtxWTFwd_8s32f, + idCtxWTFwd_16u32f, + idCtxWTFwd_16s32f, + idCtxWTFwd2D_32f_C1R, + idCtxWTInv2D_32f_C1R, + idCtxWTFwd2D_32f_C3R, + idCtxWTInv2D_32f_C3R, + idCtxWTInv_32f, + idCtxWTInv_32f8u, + idCtxWTInv_32f8s, + idCtxWTInv_32f16u, + idCtxWTInv_32f16s, + idCtxMDCTFwd_32f, + idCtxMDCTInv_32f, + idCtxMDCTFwd_16s, + idCtxFIRBlock_32f, + idCtxFDP_32f, + idCtxRLMS_32f = IPP_CONTEXT( 'L', 'M', 'S', '1'), + idCtxRLMS32f_16s = IPP_CONTEXT( 'L', 'M', 'S', 0 ), + idCtxIIRAR_32f = IPP_CONTEXT( 'I', 'I', '0', '1'), + idCtxIIRBQ_32f = IPP_CONTEXT( 'I', 'I', '0', '2'), + idCtxIIRAR_32fc = IPP_CONTEXT( 'I', 'I', '0', '3'), + idCtxIIRBQ_32fc = IPP_CONTEXT( 'I', 'I', '0', '4'), + idCtxIIRAR32f_16s = IPP_CONTEXT( 'I', 'I', '0', '5'), + idCtxIIRBQ32f_16s = IPP_CONTEXT( 'I', 'I', '0', '6'), + idCtxIIRAR32fc_16sc = IPP_CONTEXT( 'I', 'I', '0', '7'), + idCtxIIRBQ32fc_16sc = IPP_CONTEXT( 'I', 'I', '0', '8'), + idCtxIIRAR32s_16s = IPP_CONTEXT( 'I', 'I', '0', '9'), + idCtxIIRBQ32s_16s = IPP_CONTEXT( 'I', 'I', '1', '0'), + idCtxIIRAR32sc_16sc = IPP_CONTEXT( 'I', 'I', '1', '1'), + idCtxIIRBQ32sc_16sc = IPP_CONTEXT( 'I', 'I', '1', '2'), + idCtxIIRAR_64f = IPP_CONTEXT( 'I', 'I', '1', '3'), + idCtxIIRBQ_64f = IPP_CONTEXT( 'I', 'I', '1', '4'), + idCtxIIRAR_64fc = IPP_CONTEXT( 'I', 'I', '1', '5'), + idCtxIIRBQ_64fc = IPP_CONTEXT( 'I', 'I', '1', '6'), + idCtxIIRAR64f_32f = IPP_CONTEXT( 'I', 'I', '1', '7'), + idCtxIIRBQ64f_32f = IPP_CONTEXT( 'I', 'I', '1', '8'), + idCtxIIRAR64fc_32fc = IPP_CONTEXT( 'I', 'I', '1', '9'), + idCtxIIRBQ64fc_32fc = IPP_CONTEXT( 'I', 'I', '2', '0'), + idCtxIIRAR64f_32s = IPP_CONTEXT( 'I', 'I', '2', '1'), + idCtxIIRBQ64f_32s = IPP_CONTEXT( 'I', 'I', '2', '2'), + idCtxIIRAR64fc_32sc = IPP_CONTEXT( 'I', 'I', '2', '3'), + idCtxIIRBQ64fc_32sc = IPP_CONTEXT( 'I', 'I', '2', '4'), + idCtxIIRAR64f_16s = IPP_CONTEXT( 'I', 'I', '2', '5'), + idCtxIIRBQ64f_16s = IPP_CONTEXT( 'I', 'I', '2', '6'), + idCtxIIRAR64fc_16sc = IPP_CONTEXT( 'I', 'I', '2', '7'), + idCtxIIRBQ64fc_16sc = IPP_CONTEXT( 'I', 'I', '2', '8'), + idCtxIIRBQDF1_32f = IPP_CONTEXT( 'I', 'I', '2', '9'), + idCtxIIRBQDF164f_32s= IPP_CONTEXT( 'I', 'I', '3', '0'), + idCtxFIRSR_32f = IPP_CONTEXT( 'F', 'I', '0', '1'), + idCtxFIRSR_32fc = IPP_CONTEXT( 'F', 'I', '0', '2'), + idCtxFIRMR_32f = IPP_CONTEXT( 'F', 'I', '0', '3'), + idCtxFIRMR_32fc = IPP_CONTEXT( 'F', 'I', '0', '4'), + idCtxFIRSR32f_16s = IPP_CONTEXT( 'F', 'I', '0', '5'), + idCtxFIRSR32fc_16sc = IPP_CONTEXT( 'F', 'I', '0', '6'), + idCtxFIRMR32f_16s = IPP_CONTEXT( 'F', 'I', '0', '7'), + idCtxFIRMR32fc_16sc = IPP_CONTEXT( 'F', 'I', '0', '8'), + idCtxFIRSR32s_16s = IPP_CONTEXT( 'F', 'I', '0', '9'), + idCtxFIRSR32sc_16sc = IPP_CONTEXT( 'F', 'I', '1', '0'), + idCtxFIRMR32s_16s = IPP_CONTEXT( 'F', 'I', '1', '1'), + idCtxFIRMR32sc_16sc = IPP_CONTEXT( 'F', 'I', '1', '2'), + idCtxFIRSR_64f = IPP_CONTEXT( 'F', 'I', '1', '3'), + idCtxFIRSR_64fc = IPP_CONTEXT( 'F', 'I', '1', '4'), + idCtxFIRMR_64f = IPP_CONTEXT( 'F', 'I', '1', '5'), + idCtxFIRMR_64fc = IPP_CONTEXT( 'F', 'I', '1', '6'), + idCtxFIRSR64f_32f = IPP_CONTEXT( 'F', 'I', '1', '7'), + idCtxFIRSR64fc_32fc = IPP_CONTEXT( 'F', 'I', '1', '8'), + idCtxFIRMR64f_32f = IPP_CONTEXT( 'F', 'I', '1', '9'), + idCtxFIRMR64fc_32fc = IPP_CONTEXT( 'F', 'I', '2', '0'), + idCtxFIRSR64f_32s = IPP_CONTEXT( 'F', 'I', '2', '1'), + idCtxFIRSR64fc_32sc = IPP_CONTEXT( 'F', 'I', '2', '2'), + idCtxFIRMR64f_32s = IPP_CONTEXT( 'F', 'I', '2', '3'), + idCtxFIRMR64fc_32sc = IPP_CONTEXT( 'F', 'I', '2', '4'), + idCtxFIRSR64f_16s = IPP_CONTEXT( 'F', 'I', '2', '5'), + idCtxFIRSR64fc_16sc = IPP_CONTEXT( 'F', 'I', '2', '6'), + idCtxFIRMR64f_16s = IPP_CONTEXT( 'F', 'I', '2', '7'), + idCtxFIRMR64fc_16sc = IPP_CONTEXT( 'F', 'I', '2', '8'), + idCtxFIRSR_16s = IPP_CONTEXT( 'F', 'I', '2', '9'), + idCtxFIRMR_16s = IPP_CONTEXT( 'F', 'I', '3', '0'), + idCtxFIRSRStream_16s= IPP_CONTEXT( 'F', 'I', '3', '1'), + idCtxFIRMRStream_16s= IPP_CONTEXT( 'F', 'I', '3', '2'), + idCtxFIRSRStream_32f= IPP_CONTEXT( 'F', 'I', '3', '3'), + idCtxFIRMRStream_32f= IPP_CONTEXT( 'F', 'I', '3', '4'), + idCtxRLMS32s_16s = IPP_CONTEXT( 'L', 'M', 'S', 'R'), + idCtxCLMS32s_16s = IPP_CONTEXT( 'L', 'M', 'S', 'C'), + idCtxEncode_JPEG2K, + idCtxDES = IPP_CONTEXT( ' ', 'D', 'E', 'S'), + idCtxBlowfish = IPP_CONTEXT( ' ', ' ', 'B', 'F'), + idCtxRijndael = IPP_CONTEXT( ' ', 'R', 'I', 'J'), + idCtxSMS4 = IPP_CONTEXT( 'S', 'M', 'S', '4'), + idCtxTwofish = IPP_CONTEXT( ' ', ' ', 'T', 'F'), + idCtxARCFOUR = IPP_CONTEXT( ' ', 'R', 'C', '4'), + idCtxRC564 = IPP_CONTEXT( 'R', 'C', '5', '1'), + idCtxRC5128 = IPP_CONTEXT( 'R', 'C', '5', '2'), + idCtxSHA1 = IPP_CONTEXT( 'S', 'H', 'S', '1'), + idCtxSHA224 = IPP_CONTEXT( 'S', 'H', 'S', '3'), + idCtxSHA256 = IPP_CONTEXT( 'S', 'H', 'S', '2'), + idCtxSHA384 = IPP_CONTEXT( 'S', 'H', 'S', '4'), + idCtxSHA512 = IPP_CONTEXT( 'S', 'H', 'S', '5'), + idCtxMD5 = IPP_CONTEXT( ' ', 'M', 'D', '5'), + idCtxHMAC = IPP_CONTEXT( 'H', 'M', 'A', 'C'), + idCtxDAA = IPP_CONTEXT( ' ', 'D', 'A', 'A'), + idCtxBigNum = IPP_CONTEXT( 'B', 'I', 'G', 'N'), + idCtxMontgomery = IPP_CONTEXT( 'M', 'O', 'N', 'T'), + idCtxPrimeNumber = IPP_CONTEXT( 'P', 'R', 'I', 'M'), + idCtxPRNG = IPP_CONTEXT( 'P', 'R', 'N', 'G'), + idCtxRSA = IPP_CONTEXT( ' ', 'R', 'S', 'A'), + idCtxRSA_PubKey = IPP_CONTEXT( 'R', 'S', 'A', '0'), + idCtxRSA_PrvKey1 = IPP_CONTEXT( 'R', 'S', 'A', '1'), + idCtxRSA_PrvKey2 = IPP_CONTEXT( 'R', 'S', 'A', '2'), + idCtxDSA = IPP_CONTEXT( ' ', 'D', 'S', 'A'), + idCtxECCP = IPP_CONTEXT( ' ', 'E', 'C', 'P'), + idCtxECCB = IPP_CONTEXT( ' ', 'E', 'C', 'B'), + idCtxECCPPoint = IPP_CONTEXT( 'P', 'E', 'C', 'P'), + idCtxECCBPoint = IPP_CONTEXT( 'P', 'E', 'C', 'B'), + idCtxDH = IPP_CONTEXT( ' ', ' ', 'D', 'H'), + idCtxDLP = IPP_CONTEXT( ' ', 'D', 'L', 'P'), + idCtxCMAC = IPP_CONTEXT( 'C', 'M', 'A', 'C'), + idCtxRFFT2_8u, + idCtxHilbert_32f32fc, + idCtxHilbert_16s32fc, + idCtxHilbert_16s16sc, + idCtxTone_16s, + idCtxTriangle_16s, + idCtxDFTOutOrd_C_32fc, + idCtxDFTOutOrd_C_64fc, + idCtxFFT_C_32sc, + idCtxFFT_C_32s, + idCtxFFT_R_32s, + idCtxFFT_R_16s32s, + idCtxDecodeProgr_JPEG2K, + idCtxWarp_MPEG4, + idCtxQuantInvIntra_MPEG4, + idCtxQuantInvInter_MPEG4, + idCtxQuantIntra_MPEG4, + idCtxQuantInter_MPEG4, + idCtxAnalysisFilter_SBR_C_32f32fc, + idCtxAnalysisFilter_SBR_C_32f, + idCtxAnalysisFilter_SBR_R_32f, + idCtxSynthesisFilter_SBR_C_32fc32f, + idCtxSynthesisFilter_SBR_C_32f, + idCtxSynthesisFilter_SBR_R_32f, + idCtxSynthesisDownFilter_SBR_C_32fc32f, + idCtxSynthesisDownFilter_SBR_C_32f, + idCtxSynthesisDownFilter_SBR_R_32f, + idCtxVLCEncode, + idCtxVLCDecode, + idCtxAnalysisFilter_SBR_C_32s32sc, + idCtxAnalysisFilter_SBR_R_32s, + idCtxSynthesisFilter_SBR_C_32sc32s, + idCtxSynthesisFilter_SBR_R_32s, + idCtxSynthesisDownFilter_SBR_C_32sc32s, + idCtxSynthesisDownFilter_SBR_R_32s, + idCtxSynthesisFilter_PQMF_MP3_32f, + idCtxAnalysisFilter_PQMF_MP3_32f, + idCtxResampleRow, + idCtxAnalysisFilter_SBR_Enc_C_32f32fc, + idCtxSynthesisFilter_DTS_32f, + idCtxFilterBilateralGauss_8u, + idCtxFilterBilateralGaussFast_8u, + idCtxBGF, + idCtxPolyGF, + idCtxRSenc, + idCtxRSdec, + idCtxSnow3g = IPP_CONTEXT( 'S', 'n', 'o', 'w'), + idCtxSnow3gF8, + idCtxSnow3gF9, + idCtxKasumi = IPP_CONTEXT( 'K', 'a', 's', 'u'), + idCtxKasumiF8, + idCtxKasumiF9, + idCtxResizeHannFilter_8u, + idCtxResizeLanczosFilter_8u, + idCtxAESXCBC, + idCtxAESCCM, + idCtxAESGCM, + idCtxMsgCatalog, + idCtxGFP, + idCtxGFPE, + idCtxGFPX, + idCtxGFPXE, + idCtxGFPXQX, + idCtxGFPXQXE, + idCtxGFPEC, + idCtxGFPPoint, + idCtxGFPXEC, + idCtxGFPXECPoint, + idCtxPairing, + idCtxResize_32f, + idCtxResizeYUV420, + idCtxResizeYUV422, + idCtxResize_64f, + idCtxFilterBilateralBorder, + idCtxThresholdAdaptiveGauss, + idCtxHOG, + idCtxFastN, + idCtxHash, + idCtxSM3 +} IppCtxId; + + + + +/* ///////////////////////////////////////////////////////////////////////////// + Helpers + /////////////////////////////////////////////////////////////////////////// */ + +#define IPP_NOERROR_RET() return ippStsNoErr +#define IPP_ERROR_RET( ErrCode ) return (ErrCode) + +#ifdef _IPP_DEBUG + + #define IPP_BADARG_RET( expr, ErrCode )\ + {if (expr) { IPP_ERROR_RET( ErrCode ); }} + +#else + + #define IPP_BADARG_RET( expr, ErrCode ) + +#endif + + + #define IPP_BAD_SIZE_RET( n )\ + IPP_BADARG_RET( (n)<=0, ippStsSizeErr ) + + #define IPP_BAD_STEP_RET( n )\ + IPP_BADARG_RET( (n)<=0, ippStsStepErr ) + + #define IPP_BAD_PTR1_RET( ptr )\ + IPP_BADARG_RET( NULL==(ptr), ippStsNullPtrErr ) + + #define IPP_BAD_PTR2_RET( ptr1, ptr2 )\ + {IPP_BAD_PTR1_RET( ptr1 ); IPP_BAD_PTR1_RET( ptr2 )} + + #define IPP_BAD_PTR3_RET( ptr1, ptr2, ptr3 )\ + {IPP_BAD_PTR2_RET( ptr1, ptr2 ); IPP_BAD_PTR1_RET( ptr3 )} + + #define IPP_BAD_PTR4_RET( ptr1, ptr2, ptr3, ptr4 )\ + {IPP_BAD_PTR2_RET( ptr1, ptr2 ); IPP_BAD_PTR2_RET( ptr3, ptr4 )} + + #define IPP_BAD_ISIZE_RET(roi) \ + IPP_BADARG_RET( ((roi).width<=0 || (roi).height<=0), ippStsSizeErr) + +/* ////////////////////////////////////////////////////////////////////////// */ +/* internal messages */ + +#define MSG_LOAD_DLL_ERR (-9700) /* Error at loading of %s library */ +#define MSG_NO_DLL (-9701) /* No DLLs were found in the Waterfall procedure */ +#define MSG_NO_SHARED (-9702) /* No shared libraries were found in the Waterfall procedure */ + +/* ////////////////////////////////////////////////////////////////////////// */ + + +typedef union { /* double precision */ + Ipp64s hex; + Ipp64f fp; +} IppFP_64f; + +typedef union { /* single precision */ + Ipp32s hex; + Ipp32f fp; +} IppFP_32f; + + +extern const IppFP_32f ippConstantOfNAN_32f; +extern const IppFP_64f ippConstantOfNAN_64f; + +extern const IppFP_32f ippConstantOfINF_32f; +extern const IppFP_64f ippConstantOfINF_64f; +extern const IppFP_32f ippConstantOfINF_NEG_32f; +extern const IppFP_64f ippConstantOfINF_NEG_64f; + +#define NAN_32F (ippConstantOfNAN_32f.fp) +#define NAN_64F (ippConstantOfNAN_64f.fp) +#define INF_32F (ippConstantOfINF_32f.fp) +#define INF_64F (ippConstantOfINF_64f.fp) +#define INF_NEG_32F (ippConstantOfINF_NEG_32f.fp) +#define INF_NEG_64F (ippConstantOfINF_NEG_64f.fp) + +/* ////////////////////////////////////////////////////////////////////////// */ + +typedef enum { + ippunreg=-1, + ippac = 0, + ippcc = 1, + ippch = 2, + ippcp = 3, + ippcv = 4, + ippdc = 5, + ippdi = 6, + ippgen = 7, + ippi = 8, + ippj = 9, + ippm = 10, + ippr = 11, + ipps = 12, + ippsc = 13, + ippsr = 14, + ippvc = 15, + ippvm = 16, + ippmsdk = 17, + ippcpepid = 18, + ippe = 19, + ipprs = 20, + ippsq = 21, + ippnomore +} IppDomain; + +int __CDECL ownGetNumThreads( void ); +int __CDECL ownGetFeature( Ipp64u MaskOfFeature ); /* the main function of tick-tock dispatcher */ + +#ifdef _IPP_DYNAMIC +typedef IppStatus (__STDCALL *DYN_RELOAD)( int ); +void __CDECL ownRegisterLib( IppDomain, DYN_RELOAD ); +void __CDECL ownUnregisterLib( IppDomain ); +#endif + +/* the number of threads available for any ipp function that uses OMP; */ +/* at the ippxx.dll loading time is equal to the number of logical processors, */ +/* and can be changed ONLY externally by library user to any desired number */ +/* by means of ippSetNumThreads() function */ +#define IPP_GET_NUM_THREADS() ( ownGetNumThreads() ) +#define IPP_OMP_NUM_THREADS() num_threads( IPP_GET_NUM_THREADS() ) +#define IPP_OMP_LIMIT_MAX_NUM_THREADS(n) num_threads( IPP_MIN(IPP_GET_NUM_THREADS(),(n))) + + +/* ////////////////////////////////////////////////////////////////////////// */ + +/* Define NULL pointer value */ +#ifndef NULL +#ifdef __cplusplus +#define NULL 0 +#else +#define NULL ((void *)0) +#endif +#endif + +#define UNREFERENCED_PARAMETER(p) (p)=(p) + +#if defined( _IPP_MARK_LIBRARY ) +static char G[] = {73, 80, 80, 71, 101, 110, 117, 105, 110, 101, 243, 193, 210, 207, 215}; +#endif + + +#define STR2(x) #x +#define STR(x) STR2(x) +#define MESSAGE( desc )\ + message(__FILE__ "(" STR(__LINE__) "):" #desc) + +/* +// endian definition +*/ +#define IPP_LITTLE_ENDIAN (0) +#define IPP_BIG_ENDIAN (1) + +#if defined( _IPP_LE ) + #define IPP_ENDIAN IPP_LITTLE_ENDIAN + +#elif defined( _IPP_BE ) + #define IPP_ENDIAN IPP_BIG_ENDIAN + +#else + #if defined( __ARMEB__ ) + #define IPP_ENDIAN IPP_BIG_ENDIAN + + #else + #define IPP_ENDIAN IPP_LITTLE_ENDIAN + + #endif +#endif + + +/* ////////////////////////////////////////////////////////////////////////// */ + +/* intrinsics */ +#if (_IPP >= _IPP_A6) || (_IPP32E >= _IPP32E_M7) + #if defined(__INTEL_COMPILER) || (_MSC_VER >= 1300) + #if (_IPP == _IPP_A6) + #include "xmmintrin.h" + #elif (_IPP == _IPP_W7) + #if defined(__INTEL_COMPILER) + #include "emmintrin.h" + #else + #undef _W7 + #include "emmintrin.h" + #define _W7 + #endif + #define _mm_loadu _mm_loadu_si128 + #elif (_IPP == _IPP_T7) || (_IPP32E == _IPP32E_M7) + #if defined(__INTEL_COMPILER) + #include "pmmintrin.h" + #define _mm_loadu _mm_lddqu_si128 + #elif (_MSC_FULL_VER >= 140050110) + #include "intrin.h" + #define _mm_loadu _mm_lddqu_si128 + #elif (_MSC_FULL_VER < 140050110) + #include "emmintrin.h" + #define _mm_loadu _mm_loadu_si128 + #endif + #elif (_IPP == _IPP_V8) || (_IPP32E == _IPP32E_U8) + #if defined(__INTEL_COMPILER) + #include "tmmintrin.h" + #define _mm_loadu _mm_lddqu_si128 + #elif (_MSC_FULL_VER >= 140050110) + #include "intrin.h" + #define _mm_loadu _mm_lddqu_si128 + #elif (_MSC_FULL_VER < 140050110) + #include "emmintrin.h" + #define _mm_loadu _mm_loadu_si128 + #endif + #elif (_IPP == _IPP_P8) || (_IPP32E == _IPP32E_Y8) + #if defined(__INTEL_COMPILER) + #include "smmintrin.h" + #define _mm_loadu _mm_lddqu_si128 + #elif (_MSC_FULL_VER >= 140050110) + #include "intrin.h" + #define _mm_loadu _mm_lddqu_si128 + #elif (_MSC_FULL_VER < 140050110) + #include "emmintrin.h" + #define _mm_loadu _mm_loadu_si128 + #endif + #elif (_IPP >= _IPP_G9) || (_IPP32E >= _IPP32E_E9) + #if defined(__INTEL_COMPILER) + #include "immintrin.h" + #define _mm_loadu _mm_lddqu_si128 + #elif (_MSC_FULL_VER >= 160021003) + #include "immintrin.h" + #define _mm_loadu _mm_lddqu_si128 + #endif + #endif + #endif +#elif (_IPPLP32 >= _IPPLP32_S8) || (_IPPLP64 >= _IPPLP64_N8) + #if defined(__INTEL_COMPILER) + #include "tmmintrin.h" + #define _mm_loadu _mm_lddqu_si128 + #elif (_MSC_FULL_VER >= 140050110) + #include "intrin.h" + #define _mm_loadu _mm_lddqu_si128 + #elif (_MSC_FULL_VER < 140050110) + #include "emmintrin.h" + #define _mm_loadu _mm_loadu_si128 + #endif +#elif (_IPPLRB >= _IPPLRB_B2) + #if defined(__INTEL_COMPILER) || defined(_REF_LIB) + #include "immintrin.h" + #endif +#endif + +// **** intrinsics for bit casting **** +#if defined(__INTEL_COMPILER) +extern unsigned int __intel_castf32_u32(float val); +extern float __intel_castu32_f32(unsigned int val); +extern unsigned __int64 __intel_castf64_u64(double val); +extern double __intel_castu64_f64(unsigned __int64 val); + #define __CAST_32f32u(val) __intel_castf32_u32((Ipp32f)val) + #define __CAST_32u32f(val) __intel_castu32_f32((Ipp32u)val) + #define __CAST_64f64u(val) __intel_castf64_u64((Ipp64f)val) + #define __CAST_64u64f(val) __intel_castu64_f64((Ipp64u)val) +#else + #define __CAST_32f32u(val) ( *((Ipp32u*)&val) ) + #define __CAST_32u32f(val) ( *((Ipp32f*)&val) ) + #define __CAST_64f64u(val) ( *((Ipp64u*)&val) ) + #define __CAST_64u64f(val) ( *((Ipp64f*)&val) ) +#endif + + +// short names for vector registers casting +#define _pd2ps _mm_castpd_ps +#define _ps2pd _mm_castps_pd +#define _pd2pi _mm_castpd_si128 +#define _pi2pd _mm_castsi128_pd +#define _ps2pi _mm_castps_si128 +#define _pi2ps _mm_castsi128_ps + +#define _ypd2ypi _mm256_castpd_si256 +#define _ypi2ypd _mm256_castsi256_pd +#define _yps2ypi _mm256_castps_si256 +#define _ypi2yps _mm256_castsi256_ps +#define _ypd2yps _mm256_castpd_ps +#define _yps2ypd _mm256_castps_pd + +#define _yps2ps _mm256_castps256_ps128 +#define _ypi2pi _mm256_castsi256_si128 +#define _ypd2pd _mm256_castpd256_pd128 +#define _ps2yps _mm256_castps128_ps256 +#define _pi2ypi _mm256_castsi128_si256 +#define _pd2ypd _mm256_castpd128_pd256 + + +#if defined(__INTEL_COMPILER) +#define __IVDEP ivdep +#else +#define __IVDEP message("message :: 'ivdep' is not defined") +#endif +//usage: #pragma __IVDEP + +/* ////////////////////////////////////////////////////////////////////////// + _IPP_DATA shoul be defined only: + - if compile not merged library + - only for 1 CPU for merged library to avoid data duplication +*/ +#if defined( _MERGED_BLD ) && ( defined(_G9) || defined(_E9) ) /* compile data only for g9 and e9 CPU */ + #define _IPP_DATA 1 +#elif !defined( _MERGED_BLD ) /* compile data if it isn't merged library */ + #define _IPP_DATA 1 +#endif + + +#if defined( __cplusplus ) +} +#endif + +#endif /* __OWNDEFS_H__ */ + diff --git a/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/owncp.h b/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/owncp.h new file mode 100644 index 0000000000..5793989761 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/owncp.h @@ -0,0 +1,149 @@ +/* +* Copyright (C) 2016 Intel Corporation. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in +* the documentation and/or other materials provided with the +* distribution. +* * Neither the name of Intel Corporation nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ + +#ifndef __OWNCP_H__ +#define __OWNCP_H__ + +#ifndef __OWNDEFS_H__ + #include "owndefs.h" +#endif + +#ifndef __IPPCP_H__ + #include "ippcp.h" +#endif + +#pragma warning( disable : 4324) + +/* ippCP length */ +typedef int cpSize; + +/* +// common macros & definitions +*/ + +/* size of cache line (bytes) */ +#define CACHE_LINE_SIZE (64) +#define LOG_CACHE_LINE_SIZE (6) + +/* swap data & pointers */ +#define SWAP_PTR(ATYPE, pX,pY) { ATYPE* aPtr=(pX); (pX)=(pY); (pY)=aPtr; } +#define SWAP(x,y) {(x)^=(y); (y)^=(x); (x)^=(y);} + +/* alignment value */ +#define ALIGN_VAL ((int)sizeof(void*)) + +/* bitsize */ +#define BYTESIZE (8) +#define BITSIZE(x) ((int)(sizeof(x)*BYTESIZE)) + +/* bit length -> byte/word length conversion */ +#define BITS2WORD8_SIZE(x) (((x)+ 7)>>3) +#define BITS2WORD16_SIZE(x) (((x)+15)>>4) +#define BITS2WORD32_SIZE(x) (((x)+31)>>5) +#define BITS2WORD64_SIZE(x) (((x)+63)>>6) + +/* WORD and DWORD manipulators */ +#define LODWORD(x) ((Ipp32u)(x)) +#define HIDWORD(x) ((Ipp32u)(((Ipp64u)(x) >>32) & 0xFFFFFFFF)) + +#define MAKEHWORD(bLo,bHi) ((Ipp16u)(((Ipp8u)(bLo)) | ((Ipp16u)((Ipp8u)(bHi))) << 8)) +#define MAKEWORD(hLo,hHi) ((Ipp32u)(((Ipp16u)(hLo)) | ((Ipp32u)((Ipp16u)(hHi))) << 16)) +#define MAKEDWORD(wLo,wHi) ((Ipp64u)(((Ipp32u)(wLo)) | ((Ipp64u)((Ipp32u)(wHi))) << 32)) + +/* extract byte */ +#define EBYTE(w,n) ((Ipp8u)((w) >> (8 * (n)))) + +/* hexString <-> Ipp32u conversion */ +#define HSTRING_TO_U32(ptrByte) \ + (((ptrByte)[0]) <<24) \ + +(((ptrByte)[1]) <<16) \ + +(((ptrByte)[2]) <<8) \ + +((ptrByte)[3]) +#define U32_TO_HSTRING(ptrByte, x) \ + (ptrByte)[0] = (Ipp8u)((x)>>24); \ + (ptrByte)[1] = (Ipp8u)((x)>>16); \ + (ptrByte)[2] = (Ipp8u)((x)>>8); \ + (ptrByte)[3] = (Ipp8u)(x) + +/* 32- and 64-bit masks for MSB of nbits-sequence */ +#define MAKEMASK32(nbits) (0xFFFFFFFF >>((32 - ((nbits)&0x1F)) &0x1F)) +#define MAKEMASK64(nbits) (0xFFFFFFFFFFFFFFFF >>((64 - ((nbits)&0x3F)) &0x3F)) + +/* Logical Shifts (right and left) of WORD */ +#define LSR32(x,nBits) ((x)>>(nBits)) +#define LSL32(x,nBits) ((x)<<(nBits)) + +/* Rorate (right and left) of WORD */ +#if defined(_MSC_VER) +# include +# define ROR32(x, nBits) _lrotr((x),(nBits)) +# define ROL32(x, nBits) _lrotl((x),(nBits)) +#else +# define ROR32(x, nBits) (LSR32((x),(nBits)) | LSL32((x),32-(nBits))) +# define ROL32(x, nBits) ROR32((x),(32-(nBits))) +#endif + +/* Logical Shifts (right and left) of DWORD */ +#define LSR64(x,nBits) ((x)>>(nBits)) +#define LSL64(x,nBits) ((x)<<(nBits)) + +/* Rorate (right and left) of DWORD */ +#define ROR64(x, nBits) (LSR64((x),(nBits)) | LSL64((x),64-(nBits))) +#define ROL64(x, nBits) ROR64((x),(64-(nBits))) + +/* change endian */ +#if defined(_MSC_VER) +# define ENDIANNESS(x) _byteswap_ulong((x)) +# define ENDIANNESS32(x) ENDIANNESS((x)) +# define ENDIANNESS64(x) _byteswap_uint64((x)) +#else +# define ENDIANNESS(x) ((ROR32((x), 24) & 0x00ff00ff) | (ROR32((x), 8) & 0xff00ff00)) +# define ENDIANNESS32(x) ENDIANNESS((x)) +# define ENDIANNESS64(x) MAKEDWORD(ENDIANNESS(HIDWORD((x))), ENDIANNESS(LODWORD((x)))) +#endif + +#define IPP_MAKE_MULTIPLE_OF_8(x) ((x) = ((x)+7)&(~7)) +#define IPP_MAKE_MULTIPLE_OF_16(x) ((x) = ((x)+15)&(~15)) + +/* 64-bit constant */ +#if !defined(__GNUC__) + #define CONST_64(x) (x) /*(x##i64)*/ +#else + #define CONST_64(x) (x##LL) +#endif + +/* copy under mask */ +#define MASKED_COPY_BNU(dst, mask, src1, src2, len) { \ + cpSize i; \ + for(i=0; i<(len); i++) (dst)[i] = ((mask) & (src1)[i]) | (~(mask) & (src2)[i]); \ +} + +#endif /* __OWNCP_H__ */ diff --git a/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpaesauthcmacca.c b/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpaesauthcmacca.c new file mode 100644 index 0000000000..0443664763 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpaesauthcmacca.c @@ -0,0 +1,396 @@ +/* +* Copyright (C) 2016 Intel Corporation. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in +* the documentation and/or other materials provided with the +* distribution. +* * Neither the name of Intel Corporation nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ + +#include "owndefs.h" +#include "owncp.h" +#include "pcpcmac.h" +#include "pcpaesm.h" +#include "pcptool.h" + +#include "pcprijtables.h" + +/*F* +// Name: ippsAES_CMACGetSize +// +// Purpose: Returns size of AES-CMAC context (in bytes). +// +// Returns: Reason: +// ippStsNullPtrErr pSzie == NULL +// ippStsNoErr no errors +// +// Parameters: +// pSize pointer to the AES-CMAC size of context +// +*F*/ +static int cpSizeofCtx_AESCMAC(void) +{ + return sizeof(IppsAES_CMACState) + AESCMAC_ALIGNMENT-1; +} + +IPPFUN(IppStatus, ippsAES_CMACGetSize,(int* pSize)) +{ + /* test size's pointer */ + IPP_BAD_PTR1_RET(pSize); + + *pSize = cpSizeofCtx_AESCMAC(); + + return ippStsNoErr; +} + + +/*F* +// Name: ippsAES_CMACInit +// +// Purpose: Init AES-CMAC context. +// +// Returns: Reason: +// ippStsNullPtrErr pCtx == NULL +// ippStsMemAllocErr size of buffer is not match fro operation +// ippStsLengthErr keyLen != 16 +// keyLen != 24 +// keyLen != 32 +// ippStsNoErr no errors +// +// Parameters: +// pKey pointer to the secret key +// keyLen length of secret key +// pCtx pointer to the CMAC context +// ctxSize available size (in bytes) of buffer above +// +*F*/ +static +void init(IppsAES_CMACState* pCtx) +{ + /* buffer is empty */ + CMAC_INDX(pCtx) = 0; + /* zeros MAC */ + PaddBlock(0, CMAC_MAC(pCtx), MBS_RIJ128); +} + +static +void LogicalLeftSift16(const Ipp8u* pSrc, Ipp8u* pDst) +{ + Ipp32u carry = 0; + int n; + for(n=0; n<16; n++) { + Ipp32u x = pSrc[16-1-n] + pSrc[16-1-n] + carry; + pDst[16-1-n] = (Ipp8u)x; + carry = (x>>8) & 0xFF; + } +} + +IPPFUN(IppStatus, ippsAES_CMACInit,(const Ipp8u* pKey, int keyLen, IppsAES_CMACState* pCtx, int ctxSize)) +{ + /* test pCtx pointer */ + IPP_BAD_PTR1_RET(pCtx); + + /* test available size of context buffer */ + IPP_BADARG_RET(ctxSize>7)) & 0x87); /* ^ Rb changed for constant time execution */ + + /* precompute k2 subkey */ + msb = (CMAC_K1(pCtx))[0]; + LogicalLeftSift16(CMAC_K1(pCtx),CMAC_K2(pCtx)); + (CMAC_K2(pCtx))[MBS_RIJ128-1] ^= (Ipp8u)((0-(msb>>7)) & 0x87); /* ^ Rb changed for constant time execution */ + } + + return sts; + } +} + + +/*F* +// Name: ippsAES_CMACUpdate +// +// Purpose: Updates intermadiate digest based on input stream. +// +// Returns: Reason: +// ippStsNullPtrErr pSrc == NULL +// pCtx == NULL +// ippStsContextMatchErr !VALID_AESCMAC_ID() +// ippStsLengthErr len <0 +// ippStsNoErr no errors +// +// Parameters: +// pSrc pointer to the input stream +// len input stream length +// pCtx pointer to the CMAC context +// +*F*/ +static +void AES_CMAC_processing(Ipp8u* pDigest, const Ipp8u* pSrc, int processedLen, const IppsAESSpec* pAES) +{ + /* setup encoder method */ + RijnCipher encoder = RIJ_ENCODER(pAES); + + while(processedLen) { + ((Ipp32u*)pDigest)[0] ^= ((Ipp32u*)pSrc)[0]; + ((Ipp32u*)pDigest)[1] ^= ((Ipp32u*)pSrc)[1]; + ((Ipp32u*)pDigest)[2] ^= ((Ipp32u*)pSrc)[2]; + ((Ipp32u*)pDigest)[3] ^= ((Ipp32u*)pSrc)[3]; + + encoder(pDigest, pDigest, RIJ_NR(pAES), RIJ_EKEYS(pAES), RijEncSbox); + + pSrc += MBS_RIJ128; + processedLen -= MBS_RIJ128; + } +} + +IPPFUN(IppStatus, ippsAES_CMACUpdate,(const Ipp8u* pSrc, int len, IppsAES_CMACState* pCtx)) +{ + int processedLen; + + /* test context pointer */ + IPP_BAD_PTR1_RET(pCtx); + /* use aligned context */ + pCtx = (IppsAES_CMACState*)( IPP_ALIGNED_PTR(pCtx, AESCMAC_ALIGNMENT) ); + + /* test ID */ + IPP_BADARG_RET(!VALID_AESCMAC_ID(pCtx), ippStsContextMatchErr); + /* test input message and it's length */ + IPP_BADARG_RET((len<0 && pSrc), ippStsLengthErr); + /* test source pointer */ + IPP_BADARG_RET((len && !pSrc), ippStsNullPtrErr); + + if(!len) + return ippStsNoErr; + + { + /* + // test internal buffer filling + */ + if(CMAC_INDX(pCtx)) { + /* copy from input stream to the internal buffer as match as possible */ + processedLen = IPP_MIN(len, (MBS_RIJ128 - CMAC_INDX(pCtx))); + CopyBlock(pSrc, CMAC_BUFF(pCtx)+CMAC_INDX(pCtx), processedLen); + + /* internal buffer filling */ + CMAC_INDX(pCtx) += processedLen; + + /* update message pointer and length */ + pSrc += processedLen; + len -= processedLen; + + if(!len) + return ippStsNoErr; + + /* update CMAC if buffer full but not the last */ + if(MBS_RIJ128==CMAC_INDX(pCtx) ) { + const IppsAESSpec* pAES = &CMAC_CIPHER(pCtx); + /* setup encoder method */ + RijnCipher encoder = RIJ_ENCODER(pAES); + XorBlock16(CMAC_BUFF(pCtx), CMAC_MAC(pCtx), CMAC_MAC(pCtx)); + + encoder(CMAC_MAC(pCtx), CMAC_MAC(pCtx), RIJ_NR(pAES), RIJ_EKEYS(pAES), RijEncSbox); + + CMAC_INDX(pCtx) = 0; + } + } + + /* + // main part + */ + processedLen = len & ~(MBS_RIJ128-1); + if(!(len & (MBS_RIJ128-1))) + processedLen -= MBS_RIJ128; + if(processedLen) { + const IppsAESSpec* pAES = &CMAC_CIPHER(pCtx); + + AES_CMAC_processing(CMAC_MAC(pCtx), pSrc, processedLen, pAES); + + /* update message pointer and length */ + pSrc += processedLen; + len -= processedLen; + } + + /* + // remaind + */ + if(len) { + CopyBlock(pSrc, (Ipp8u*)(&CMAC_BUFF(pCtx)), len); + /* update internal buffer filling */ + CMAC_INDX(pCtx) += len; + } + + return ippStsNoErr; + } +} + + +/*F* +// Name: ippsAES_CMACFinal +// +// Purpose: Stop message digesting and return MD. +// +// Returns: Reason: +// ippStsNullPtrErr pMD == NULL +// pCtx == NULL +// ippStsContextMatchErr !VALID_AESCMAC_ID() +// ippStsLengthErr MBS_RIJ128 < mdLen <1 +// ippStsNoErr no errors +// +// Parameters: +// pMD pointer to the output message digest +// mdLen requested length of the message digest +// pCtx pointer to the CMAC context +// +*F*/ +IPPFUN(IppStatus, ippsAES_CMACFinal,(Ipp8u* pMD, int mdLen, IppsAES_CMACState* pCtx)) +{ + /* test context pointer and ID */ + IPP_BAD_PTR1_RET(pCtx); + /* use aligned context */ + pCtx = (IppsAES_CMACState*)( IPP_ALIGNED_PTR(pCtx, AESCMAC_ALIGNMENT) ); + + IPP_BADARG_RET(!VALID_AESCMAC_ID(pCtx), ippStsContextMatchErr); + /* test DAC pointer */ + IPP_BAD_PTR1_RET(pMD); + IPP_BADARG_RET((mdLen<1)||(MBS_RIJ128idCtx) +#define AESGCM_STATE(stt) ((stt)->state) + +#define AESGCM_IV_LEN(stt) ((stt)->ivLen) +#define AESGCM_AAD_LEN(stt) ((stt)->aadLen) +#define AESGCM_TXT_LEN(stt) ((stt)->txtLen) + +#define AESGCM_BUFLEN(stt) ((stt)->bufLen) +#define AESGCM_COUNTER(stt) ((stt)->counter) +#define AESGCM_ECOUNTER0(stt) ((stt)->ecounter0) +#define AESGCM_ECOUNTER(stt) ((stt)->ecounter) +#define AESGCM_GHASH(stt) ((stt)->ghash) + +#define AESGCM_HASH(stt) ((stt)->hashFun) +#define AESGCM_AUTH(stt) ((stt)->authFun) +#define AESGCM_ENC(stt) ((stt)->encFun) +#define AESGCM_DEC(stt) ((stt)->decFun) + +#define AESGCM_CIPHER(stt) (IppsAESSpec*)(&((stt)->cipher)) + +#define AESGCM_HKEY(stt) ((stt)->multiplier) +#define AESGCM_CPWR(stt) ((stt)->multiplier) +#define AES_GCM_MTBL(stt) ((stt)->multiplier) + +#define AESGCM_VALID_ID(stt) (AESGCM_ID((stt))==idCtxAESGCM) + + +__INLINE void IncrementCounter32(Ipp8u* pCtr) +{ + int i; + for(i=BLOCK_SIZE-1; i>=CTR_POS && 0==(Ipp8u)(++pCtr[i]); i--) ; +} + + +void AesGcmPrecompute_table2K(Ipp8u* pPrecomputeData, const Ipp8u* pHKey); +void AesGcmMulGcm_table2K(Ipp8u* pGhash, const Ipp8u* pHkey, const void* pParam); +void AesGcmAuth_table2K(Ipp8u* pGhash, const Ipp8u* pSrc, int len, const Ipp8u* pHkey, const void* pParam); +void wrpAesGcmEnc_table2K(Ipp8u* pDst, const Ipp8u* pSrc, int len, IppsAES_GCMState* pCtx); +void wrpAesGcmDec_table2K(Ipp8u* pDst, const Ipp8u* pSrc, int len, IppsAES_GCMState* pCtx); + +extern const Ipp16u AesGcmConst_table[256]; /* precomputed reduction table */ + +#endif /* _CP_AESAUTH_GCM_H*/ diff --git a/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpaesauthgcmca.c b/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpaesauthgcmca.c new file mode 100644 index 0000000000..bf8d8264b4 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpaesauthgcmca.c @@ -0,0 +1,731 @@ +/* +* Copyright (C) 2016 Intel Corporation. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in +* the documentation and/or other materials provided with the +* distribution. +* * Neither the name of Intel Corporation nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ + +#include "owndefs.h" +#include "owncp.h" + +#include "pcpaesauthgcm.h" +#include "pcptool.h" + +#include "pcprijtables.h" + +/*F* +// Name: ippsAES_GCMGetSize +// +// Purpose: Returns size of AES_GCM state (in bytes). +// +// Returns: Reason: +// ippStsNullPtrErr pSize == NULL +// ippStsNoErr no errors +// +// Parameters: +// pSize pointer to size of context +// +*F*/ +static int cpSizeofCtx_AESGCM(void) +{ + int precomp_size; + + precomp_size = PRECOMP_DATA_SIZE_FAST2K; + + /* decrease precomp_size as soon as BLOCK_SIZE bytes already reserved in context */ + precomp_size -= BLOCK_SIZE; + + return sizeof(IppsAES_GCMState) + +precomp_size + +AESGCM_ALIGNMENT-1; +} + +IPPFUN(IppStatus, ippsAES_GCMGetSize,(int* pSize)) +{ + /* test size's pointer */ + IPP_BAD_PTR1_RET(pSize); + + *pSize = cpSizeofCtx_AESGCM(); + + return ippStsNoErr; +} + + +/*F* +// Name: ippsAES_GCMReset +// +// Purpose: Resets AES_GCM context. +// +// Returns: Reason: +// ippStsNullPtrErr pState== NULL +// ippStsContextMatchErr pState points on invalid context +// ippStsNoErr no errors +// +// Parameters: +// pState pointer to the context +// +*F*/ +IPPFUN(IppStatus, ippsAES_GCMReset,(IppsAES_GCMState* pState)) +{ + /* test pState pointer */ + IPP_BAD_PTR1_RET(pState); + + /* use aligned context */ + pState = (IppsAES_GCMState*)( IPP_ALIGNED_PTR(pState, AESGCM_ALIGNMENT) ); + /* test context validity */ + IPP_BADARG_RET(!AESGCM_VALID_ID(pState), ippStsContextMatchErr); + + /* reset GCM */ + AESGCM_STATE(pState) = GcmInit; + AESGCM_IV_LEN(pState) = CONST_64(0); + AESGCM_AAD_LEN(pState) = CONST_64(0); + AESGCM_TXT_LEN(pState) = CONST_64(0); + + AESGCM_BUFLEN(pState) = 0; + PaddBlock(0, AESGCM_COUNTER(pState), BLOCK_SIZE); + PaddBlock(0, AESGCM_ECOUNTER(pState), BLOCK_SIZE); + PaddBlock(0, AESGCM_ECOUNTER0(pState), BLOCK_SIZE); + PaddBlock(0, AESGCM_GHASH(pState), BLOCK_SIZE); + + return ippStsNoErr; +} + + +/*F* +// Name: ippsAES_GCMInit +// +// Purpose: Init AES_GCM context for future usage. +// +// Returns: Reason: +// ippStsNullPtrErr pState == NULL +// ippStsMemAllocErr size of buffer is not match fro operation +// ippStsLengthErr keyLen != 16 && +// != 24 && +// != 32 +// ippStsNoErr no errors +// +// Parameters: +// pKey pointer to the secret key +// keyLen length of secret key +// pState pointer to the AES-GCM context +// ctxSize available size (in bytes) of buffer above +// +*F*/ +IPPFUN(IppStatus, ippsAES_GCMInit,(const Ipp8u* pKey, int keyLen, IppsAES_GCMState* pState, int ctxSize)) +{ + /* test pCtx pointer */ + IPP_BAD_PTR1_RET(pState); + + /* test available size of context buffer */ + IPP_BADARG_RET(ctxSize0 +// ippStsContextMatchErr !AESGCM_VALID_ID() +// ippStsLengthErr ivLen <0 +// ippStsBadArgErr illegal sequence call +// ippStsNoErr no errors +// +// Parameters: +// pIV pointer to the IV +// ivLen length of IV (it could be 0) +// pState pointer to the context +// +*F*/ +IPPFUN(IppStatus, ippsAES_GCMProcessIV,(const Ipp8u* pIV, int ivLen, IppsAES_GCMState* pState)) +{ + /* test pState pointer */ + IPP_BAD_PTR1_RET(pState); + + /* test IV pointer and length */ + IPP_BADARG_RET(ivLen && !pIV, ippStsNullPtrErr); + IPP_BADARG_RET(ivLen<0, ippStsLengthErr); + + /* use aligned context */ + pState = (IppsAES_GCMState*)( IPP_ALIGNED_PTR(pState, AESGCM_ALIGNMENT) ); + /* test context validity */ + IPP_BADARG_RET(!AESGCM_VALID_ID(pState), ippStsContextMatchErr); + + IPP_BADARG_RET(!(GcmInit==AESGCM_STATE(pState) || GcmIVprocessing==AESGCM_STATE(pState)), ippStsBadArgErr); + + /* switch IVprocessing on */ + AESGCM_STATE(pState) = GcmIVprocessing; + + /* test if buffer is not empty */ + if(AESGCM_BUFLEN(pState)) { + int locLen = IPP_MIN(ivLen, BLOCK_SIZE-AESGCM_BUFLEN(pState)); + XorBlock(pIV, AESGCM_COUNTER(pState)+AESGCM_BUFLEN(pState), AESGCM_COUNTER(pState)+AESGCM_BUFLEN(pState), locLen); + AESGCM_BUFLEN(pState) += locLen; + + /* if buffer full */ + if(BLOCK_SIZE==AESGCM_BUFLEN(pState)) { + MulGcm_ ghashFunc = AESGCM_HASH(pState); + ghashFunc(AESGCM_COUNTER(pState), AESGCM_HKEY(pState), AesGcmConst_table); + AESGCM_BUFLEN(pState) = 0; + } + + AESGCM_IV_LEN(pState) += locLen; + pIV += locLen; + ivLen -= locLen; + } + + /* process main part of IV */ + { + int lenBlks = ivLen & (-BLOCK_SIZE); + if(lenBlks) { + Auth_ authFunc = AESGCM_AUTH(pState); + + authFunc(AESGCM_COUNTER(pState), pIV, lenBlks, AESGCM_HKEY(pState), AesGcmConst_table); + + AESGCM_IV_LEN(pState) += lenBlks; + pIV += lenBlks; + ivLen -= lenBlks; + } + } + + /* copy the rest of IV into the buffer */ + if(ivLen) { + XorBlock(pIV, AESGCM_COUNTER(pState), AESGCM_COUNTER(pState), ivLen); + AESGCM_IV_LEN(pState) += ivLen; + AESGCM_BUFLEN(pState) += ivLen; + } + + return ippStsNoErr; +} + + +/*F* +// Name: ippsAES_GCMProcessAAD +// +// Purpose: AAD processing. +// +// Returns: Reason: +// ippStsNullPtrErr pState == NULL +// pAAD == NULL, aadLen>0 +// ippStsContextMatchErr !AESGCM_VALID_ID() +// ippStsLengthErr aadLen <0 +// ippStsBadArgErr illegal sequence call +// ippStsNoErr no errors +// +// Parameters: +// pAAD pointer to the AAD +// aadlen length of AAD (it could be 0) +// pState pointer to the context +// +*F*/ +IPPFUN(IppStatus, ippsAES_GCMProcessAAD,(const Ipp8u* pAAD, int aadLen, IppsAES_GCMState* pState)) +{ + /* test pState pointer */ + IPP_BAD_PTR1_RET(pState); + /* use aligned context */ + pState = (IppsAES_GCMState*)( IPP_ALIGNED_PTR(pState, AESGCM_ALIGNMENT) ); + /* test if context is valid */ + IPP_BADARG_RET(!AESGCM_VALID_ID(pState), ippStsContextMatchErr); + + /* test AAD pointer and length */ + IPP_BADARG_RET(aadLen && !pAAD, ippStsNullPtrErr); + IPP_BADARG_RET(aadLen<0, ippStsLengthErr); + + IPP_BADARG_RET(!(GcmIVprocessing==AESGCM_STATE(pState) || GcmAADprocessing==AESGCM_STATE(pState)), ippStsBadArgErr); + + { + /* get method */ + MulGcm_ hashFunc = AESGCM_HASH(pState); + + if( GcmIVprocessing==AESGCM_STATE(pState) ) { + IPP_BADARG_RET(0==AESGCM_IV_LEN(pState), ippStsBadArgErr); + + /* complete IV processing */ + if(CTR_POS==AESGCM_IV_LEN(pState)) { + /* apply special format if IV length is 12 bytes */ + AESGCM_COUNTER(pState)[12] = 0; + AESGCM_COUNTER(pState)[13] = 0; + AESGCM_COUNTER(pState)[14] = 0; + AESGCM_COUNTER(pState)[15] = 1; + } + else { + /* process the rest of IV */ + if(AESGCM_BUFLEN(pState)) + hashFunc(AESGCM_COUNTER(pState), AESGCM_HKEY(pState), AesGcmConst_table); + + /* add IV bit length */ + { + Ipp64u ivBitLen = AESGCM_IV_LEN(pState)*BYTESIZE; + Ipp8u tmp[BLOCK_SIZE]; + PaddBlock(0, tmp, BLOCK_SIZE-8); + U32_TO_HSTRING(tmp+8, HIDWORD(ivBitLen)); + U32_TO_HSTRING(tmp+12, LODWORD(ivBitLen)); + XorBlock16(tmp, AESGCM_COUNTER(pState), AESGCM_COUNTER(pState)); + hashFunc(AESGCM_COUNTER(pState), AESGCM_HKEY(pState), AesGcmConst_table); + } + } + + /* prepare initial counter */ + { + IppsAESSpec* pAES = AESGCM_CIPHER(pState); + RijnCipher encoder = RIJ_ENCODER(pAES); + encoder(AESGCM_COUNTER(pState), AESGCM_ECOUNTER0(pState), RIJ_NR(pAES), RIJ_EKEYS(pAES), RijEncSbox); + } + + /* switch mode and init counters */ + AESGCM_STATE(pState) = GcmAADprocessing; + AESGCM_AAD_LEN(pState) = CONST_64(0); + AESGCM_BUFLEN(pState) = 0; + } + + /* + // AAD processing + */ + + /* test if buffer is not empty */ + if(AESGCM_BUFLEN(pState)) { + int locLen = IPP_MIN(aadLen, BLOCK_SIZE-AESGCM_BUFLEN(pState)); + XorBlock(pAAD, AESGCM_GHASH(pState)+AESGCM_BUFLEN(pState), AESGCM_GHASH(pState)+AESGCM_BUFLEN(pState), locLen); + AESGCM_BUFLEN(pState) += locLen; + + /* if buffer full */ + if(BLOCK_SIZE==AESGCM_BUFLEN(pState)) { + hashFunc(AESGCM_GHASH(pState), AESGCM_HKEY(pState), AesGcmConst_table); + AESGCM_BUFLEN(pState) = 0; + } + + AESGCM_AAD_LEN(pState) += locLen; + pAAD += locLen; + aadLen -= locLen; + } + + /* process main part of AAD */ + { + int lenBlks = aadLen & (-BLOCK_SIZE); + if(lenBlks) { + Auth_ authFunc = AESGCM_AUTH(pState); + + authFunc(AESGCM_GHASH(pState), pAAD, lenBlks, AESGCM_HKEY(pState), AesGcmConst_table); + + AESGCM_AAD_LEN(pState) += lenBlks; + pAAD += lenBlks; + aadLen -= lenBlks; + } + } + + /* copy the rest of AAD into the buffer */ + if(aadLen) { + XorBlock(pAAD, AESGCM_GHASH(pState), AESGCM_GHASH(pState), aadLen); + AESGCM_AAD_LEN(pState) += aadLen; + AESGCM_BUFLEN(pState) = aadLen; + } + + return ippStsNoErr; + } +} + + +/*F* +// Name: ippsAES_GCMStart +// +// Purpose: Start the process of encryption or decryption and authentication tag generation. +// +// Returns: Reason: +// ippStsNullPtrErr pState == NULL +// pIV == NULL, ivLen>0 +// pAAD == NULL, aadLen>0 +// ippStsContextMatchErr !AESGCM_VALID_ID() +// ippStsLengthErr ivLen < 0 +// aadLen < 0 +// ippStsNoErr no errors +// +// Parameters: +// pIV pointer to the IV (nonce) +// ivLen length of the IV in bytes +// pAAD pointer to the Addition Authenticated Data (header) +// aadLen length of the AAD in bytes +// pState pointer to the AES-GCM state +// +*F*/ +IPPFUN(IppStatus, ippsAES_GCMStart,(const Ipp8u* pIV, int ivLen, + const Ipp8u* pAAD, int aadLen, + IppsAES_GCMState* pState)) +{ + IppStatus sts = ippsAES_GCMReset(pState); + if(ippStsNoErr==sts) + sts = ippsAES_GCMProcessIV(pIV, ivLen, pState); + if(ippStsNoErr==sts) + sts = ippsAES_GCMProcessAAD(pAAD, aadLen, pState); + return sts; +} + + +/*F* +// Name: ippsAES_GCMEncrypt +// +// Purpose: Encrypts a data buffer in the GCM mode. +// +// Returns: Reason: +// ippStsNullPtrErr pSrc == NULL +// pDst == NULL +// pState == NULL +// ippStsContextMatchErr !AESGCM_VALID_ID() +// ippStsLengthErr txtLen<0 +// ippStsNoErr no errors +// +// Parameters: +// pSrc Pointer to plaintext. +// pDst Pointer to ciphertext. +// len Length of the plaintext and ciphertext in bytes +// pState pointer to the context +// +*F*/ +IPPFUN(IppStatus, ippsAES_GCMEncrypt,(const Ipp8u* pSrc, Ipp8u* pDst, int txtLen, + IppsAES_GCMState* pState)) +{ + /* test pState pointer */ + IPP_BAD_PTR1_RET(pState); + /* use aligned context */ + pState = (IppsAES_GCMState*)( IPP_ALIGNED_PTR(pState, AESGCM_ALIGNMENT) ); + /* test state ID */ + IPP_BADARG_RET(!AESGCM_VALID_ID(pState), ippStsContextMatchErr); + /* test context validity */ + IPP_BADARG_RET(!(GcmAADprocessing==AESGCM_STATE(pState) || GcmTXTprocessing==AESGCM_STATE(pState)), ippStsBadArgErr); + + /* test text pointers and length */ + IPP_BAD_PTR2_RET(pSrc, pDst); + IPP_BADARG_RET(txtLen<0, ippStsLengthErr); + + + { + /* get method */ + IppsAESSpec* pAES = AESGCM_CIPHER(pState); + RijnCipher encoder = RIJ_ENCODER(pAES); + MulGcm_ hashFunc = AESGCM_HASH(pState); + + if( GcmAADprocessing==AESGCM_STATE(pState) ) { + /* complete AAD processing */ + if(AESGCM_BUFLEN(pState)) + hashFunc(AESGCM_GHASH(pState), AESGCM_HKEY(pState), AesGcmConst_table); + + /* increment counter block */ + IncrementCounter32(AESGCM_COUNTER(pState)); + /* and encrypt counter */ + encoder(AESGCM_COUNTER(pState), AESGCM_ECOUNTER(pState), RIJ_NR(pAES), RIJ_EKEYS(pAES), RijEncSbox); + + /* switch mode and init counters */ + AESGCM_STATE(pState) = GcmTXTprocessing; + AESGCM_TXT_LEN(pState) = CONST_64(0); + AESGCM_BUFLEN(pState) = 0; + } + + /* + // process text (encrypt and authenticate) + */ + /* process partial block */ + if(AESGCM_BUFLEN(pState)) { + int locLen = IPP_MIN(txtLen, BLOCK_SIZE-AESGCM_BUFLEN(pState)); + /* ctr encryption */ + XorBlock(pSrc, AESGCM_ECOUNTER(pState)+AESGCM_BUFLEN(pState), pDst, locLen); + /* authentication */ + XorBlock(pDst, AESGCM_GHASH(pState)+AESGCM_BUFLEN(pState), AESGCM_GHASH(pState)+AESGCM_BUFLEN(pState), locLen); + + AESGCM_BUFLEN(pState) += locLen; + AESGCM_TXT_LEN(pState) += locLen; + pSrc += locLen; + pDst += locLen; + txtLen -= locLen; + + /* if buffer full */ + if(BLOCK_SIZE==AESGCM_BUFLEN(pState)) { + /* hash buffer */ + hashFunc(AESGCM_GHASH(pState), AESGCM_HKEY(pState), AesGcmConst_table); + AESGCM_BUFLEN(pState) = 0; + + /* increment counter block */ + IncrementCounter32(AESGCM_COUNTER(pState)); + /* and encrypt counter */ + encoder(AESGCM_COUNTER(pState), AESGCM_ECOUNTER(pState), RIJ_NR(pAES), RIJ_EKEYS(pAES), RijEncSbox); + } + } + + /* process the main part of text */ + { + int lenBlks = txtLen & (-BLOCK_SIZE); + if(lenBlks) { + Encrypt_ encFunc = AESGCM_ENC(pState); + + encFunc(pDst, pSrc, lenBlks, pState); + + AESGCM_TXT_LEN(pState) += lenBlks; + pSrc += lenBlks; + pDst += lenBlks; + txtLen -= lenBlks; + } + } + + /* process the rest of text */ + if(txtLen) { + XorBlock(pSrc, AESGCM_ECOUNTER(pState)+AESGCM_BUFLEN(pState), pDst, txtLen); + XorBlock(pDst, AESGCM_GHASH(pState)+AESGCM_BUFLEN(pState), AESGCM_GHASH(pState)+AESGCM_BUFLEN(pState), txtLen); + + AESGCM_BUFLEN(pState) += txtLen; + AESGCM_TXT_LEN(pState) += txtLen; + } + + return ippStsNoErr; + } +} + + +/*F* +// Name: ippsAES_GCMDecrypt +// +// Purpose: Decrypts a data buffer in the GCM mode. +// +// Returns: Reason: +// ippStsNullPtrErr pSrc == NULL +// pDst == NULL +// pState == NULL +// ippStsContextMatchErr !AESGCM_VALID_ID() +// ippStsLengthErr txtLen<0 +// ippStsNoErr no errors +// +// Parameters: +// pSrc Pointer to ciphertext. +// pDst Pointer to plaintext. +// len Length of the plaintext and ciphertext in bytes +// pState pointer to the context +// +*F*/ +IPPFUN(IppStatus, ippsAES_GCMDecrypt,(const Ipp8u* pSrc, Ipp8u* pDst, int txtLen, IppsAES_GCMState* pState)) +{ + /* test pState pointer */ + IPP_BAD_PTR1_RET(pState); + /* use aligned context */ + pState = (IppsAES_GCMState*)( IPP_ALIGNED_PTR(pState, AESGCM_ALIGNMENT) ); + /* test state ID */ + IPP_BADARG_RET(!AESGCM_VALID_ID(pState), ippStsContextMatchErr); + /* test context validity */ + IPP_BADARG_RET(!(GcmAADprocessing==AESGCM_STATE(pState) || GcmTXTprocessing==AESGCM_STATE(pState)), ippStsBadArgErr); + + /* test text pointers and length */ + IPP_BAD_PTR2_RET(pSrc, pDst); + IPP_BADARG_RET(txtLen<0, ippStsLengthErr); + + + { + /* get method */ + IppsAESSpec* pAES = AESGCM_CIPHER(pState); + RijnCipher encoder = RIJ_ENCODER(pAES); + MulGcm_ hashFunc = AESGCM_HASH(pState); + + if( GcmAADprocessing==AESGCM_STATE(pState) ) { + /* complete AAD processing */ + if(AESGCM_BUFLEN(pState)) + hashFunc(AESGCM_GHASH(pState), AESGCM_HKEY(pState), AesGcmConst_table); + + /* increment counter block */ + IncrementCounter32(AESGCM_COUNTER(pState)); + /* and encrypt counter */ + encoder(AESGCM_COUNTER(pState), AESGCM_ECOUNTER(pState), RIJ_NR(pAES), RIJ_EKEYS(pAES), RijEncSbox); + + /* switch mode and init counters */ + AESGCM_BUFLEN(pState) = 0; + AESGCM_TXT_LEN(pState) = CONST_64(0); + AESGCM_STATE(pState) = GcmTXTprocessing; + } + + /* + // process text (authenticate and decrypt ) + */ + /* process partial block */ + if(AESGCM_BUFLEN(pState)) { + int locLen = IPP_MIN(txtLen, BLOCK_SIZE-AESGCM_BUFLEN(pState)); + /* authentication */ + XorBlock(pSrc, AESGCM_GHASH(pState)+AESGCM_BUFLEN(pState), AESGCM_GHASH(pState)+AESGCM_BUFLEN(pState), locLen); + /* ctr decryption */ + XorBlock(pSrc, AESGCM_ECOUNTER(pState)+AESGCM_BUFLEN(pState), pDst, locLen); + + AESGCM_BUFLEN(pState) += locLen; + AESGCM_TXT_LEN(pState) += locLen; + pSrc += locLen; + pDst += locLen; + txtLen -= locLen; + + /* if buffer full */ + if(BLOCK_SIZE==AESGCM_BUFLEN(pState)) { + /* hash buffer */ + hashFunc(AESGCM_GHASH(pState), AESGCM_HKEY(pState), AesGcmConst_table); + AESGCM_BUFLEN(pState) = 0; + + /* increment counter block */ + IncrementCounter32(AESGCM_COUNTER(pState)); + /* and encrypt counter */ + encoder(AESGCM_COUNTER(pState), AESGCM_ECOUNTER(pState), RIJ_NR(pAES), RIJ_EKEYS(pAES), RijEncSbox); + } + } + + /* process the main part of text */ + { + int lenBlks = txtLen & (-BLOCK_SIZE); + if(lenBlks) { + Decrypt_ decFunc = AESGCM_DEC(pState); + + decFunc(pDst, pSrc, lenBlks, pState); + + AESGCM_TXT_LEN(pState) += lenBlks; + pSrc += lenBlks; + pDst += lenBlks; + txtLen -= lenBlks; + } + } + + /* process the rest of text */ + if(txtLen) { + /* ctr encryption */ + XorBlock(pSrc, AESGCM_GHASH(pState)+AESGCM_BUFLEN(pState), AESGCM_GHASH(pState)+AESGCM_BUFLEN(pState), txtLen); + XorBlock(pSrc, AESGCM_ECOUNTER(pState)+AESGCM_BUFLEN(pState), pDst, txtLen); + + AESGCM_BUFLEN(pState) += txtLen; + AESGCM_TXT_LEN(pState) += txtLen; + } + + return ippStsNoErr; + } +} + + +/*F* +// Name: ippsAES_GCMGetTag +// +// Purpose: Generates authentication tag in the GCM mode. +// +// Returns: Reason: +// ippStsNullPtrErr pDstTag == NULL +// pState == NULL +// ippStsLengthErr tagLen<=0 || tagLen>16 +// ippStsContextMatchErr !AESGCM_VALID_ID() +// ippStsNoErr no errors +// +// Parameters: +// pDstTag pointer to the authentication tag. +// tagLen length of the authentication tag *pDstTag in bytes +// pState pointer to the context +// +*F*/ +IPPFUN(IppStatus, ippsAES_GCMGetTag,(Ipp8u* pTag, int tagLen, const IppsAES_GCMState* pState)) +{ + /* test State pointer */ + IPP_BAD_PTR1_RET(pState); + /* use aligned context */ + pState = (IppsAES_GCMState*)( IPP_ALIGNED_PTR(pState, AESGCM_ALIGNMENT) ); + /* test state ID */ + IPP_BADARG_RET(!AESGCM_VALID_ID(pState), ippStsContextMatchErr); + + /* test tag pointer and length */ + IPP_BAD_PTR1_RET(pTag); + IPP_BADARG_RET(tagLen<=0 || tagLen>BLOCK_SIZE, ippStsLengthErr); + + + { + /* get method */ + MulGcm_ hashFunc = AESGCM_HASH(pState); + + __ALIGN16 Ipp8u tmpHash[BLOCK_SIZE]; + Ipp8u tmpCntr[BLOCK_SIZE]; + + /* local copy of AAD and text counters (in bits) */ + Ipp64u aadBitLen = AESGCM_AAD_LEN(pState)*BYTESIZE; + Ipp64u txtBitLen = AESGCM_TXT_LEN(pState)*BYTESIZE; + + /* do local copy of ghash */ + CopyBlock16(AESGCM_GHASH(pState), tmpHash); + + /* complete text processing */ + if(AESGCM_BUFLEN(pState)) { + hashFunc(tmpHash, AESGCM_HKEY(pState), AesGcmConst_table); + } + + /* process lengths of AAD and text */ + U32_TO_HSTRING(tmpCntr, HIDWORD(aadBitLen)); + U32_TO_HSTRING(tmpCntr+4, LODWORD(aadBitLen)); + U32_TO_HSTRING(tmpCntr+8, HIDWORD(txtBitLen)); + U32_TO_HSTRING(tmpCntr+12,LODWORD(txtBitLen)); + + XorBlock16(tmpHash, tmpCntr, tmpHash); + hashFunc(tmpHash, AESGCM_HKEY(pState), AesGcmConst_table); + + /* add encrypted initial counter */ + XorBlock16(tmpHash, AESGCM_ECOUNTER0(pState), tmpHash); + + /* return tag of required lenth */ + CopyBlock(tmpHash, pTag, tagLen); + + return ippStsNoErr; + } +} diff --git a/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpaesgcmtableca.c b/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpaesgcmtableca.c new file mode 100644 index 0000000000..ca4f51afe1 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpaesgcmtableca.c @@ -0,0 +1,52 @@ +/* +* Copyright (C) 2016 Intel Corporation. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in +* the documentation and/or other materials provided with the +* distribution. +* * Neither the name of Intel Corporation nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ + +#include "owndefs.h" +#include "owncp.h" + +const Ipp16u AesGcmConst_table[256] = { +0x0000, 0xc201, 0x8403, 0x4602, 0x0807, 0xca06, 0x8c04, 0x4e05, 0x100e, 0xd20f, 0x940d, 0x560c, 0x1809, 0xda08, 0x9c0a, 0x5e0b, +0x201c, 0xe21d, 0xa41f, 0x661e, 0x281b, 0xea1a, 0xac18, 0x6e19, 0x3012, 0xf213, 0xb411, 0x7610, 0x3815, 0xfa14, 0xbc16, 0x7e17, +0x4038, 0x8239, 0xc43b, 0x063a, 0x483f, 0x8a3e, 0xcc3c, 0x0e3d, 0x5036, 0x9237, 0xd435, 0x1634, 0x5831, 0x9a30, 0xdc32, 0x1e33, +0x6024, 0xa225, 0xe427, 0x2626, 0x6823, 0xaa22, 0xec20, 0x2e21, 0x702a, 0xb22b, 0xf429, 0x3628, 0x782d, 0xba2c, 0xfc2e, 0x3e2f, +0x8070, 0x4271, 0x0473, 0xc672, 0x8877, 0x4a76, 0x0c74, 0xce75, 0x907e, 0x527f, 0x147d, 0xd67c, 0x9879, 0x5a78, 0x1c7a, 0xde7b, +0xa06c, 0x626d, 0x246f, 0xe66e, 0xa86b, 0x6a6a, 0x2c68, 0xee69, 0xb062, 0x7263, 0x3461, 0xf660, 0xb865, 0x7a64, 0x3c66, 0xfe67, +0xc048, 0x0249, 0x444b, 0x864a, 0xc84f, 0x0a4e, 0x4c4c, 0x8e4d, 0xd046, 0x1247, 0x5445, 0x9644, 0xd841, 0x1a40, 0x5c42, 0x9e43, +0xe054, 0x2255, 0x6457, 0xa656, 0xe853, 0x2a52, 0x6c50, 0xae51, 0xf05a, 0x325b, 0x7459, 0xb658, 0xf85d, 0x3a5c, 0x7c5e, 0xbe5f, +0x00e1, 0xc2e0, 0x84e2, 0x46e3, 0x08e6, 0xcae7, 0x8ce5, 0x4ee4, 0x10ef, 0xd2ee, 0x94ec, 0x56ed, 0x18e8, 0xdae9, 0x9ceb, 0x5eea, +0x20fd, 0xe2fc, 0xa4fe, 0x66ff, 0x28fa, 0xeafb, 0xacf9, 0x6ef8, 0x30f3, 0xf2f2, 0xb4f0, 0x76f1, 0x38f4, 0xfaf5, 0xbcf7, 0x7ef6, +0x40d9, 0x82d8, 0xc4da, 0x06db, 0x48de, 0x8adf, 0xccdd, 0x0edc, 0x50d7, 0x92d6, 0xd4d4, 0x16d5, 0x58d0, 0x9ad1, 0xdcd3, 0x1ed2, +0x60c5, 0xa2c4, 0xe4c6, 0x26c7, 0x68c2, 0xaac3, 0xecc1, 0x2ec0, 0x70cb, 0xb2ca, 0xf4c8, 0x36c9, 0x78cc, 0xbacd, 0xfccf, 0x3ece, +0x8091, 0x4290, 0x0492, 0xc693, 0x8896, 0x4a97, 0x0c95, 0xce94, 0x909f, 0x529e, 0x149c, 0xd69d, 0x9898, 0x5a99, 0x1c9b, 0xde9a, +0xa08d, 0x628c, 0x248e, 0xe68f, 0xa88a, 0x6a8b, 0x2c89, 0xee88, 0xb083, 0x7282, 0x3480, 0xf681, 0xb884, 0x7a85, 0x3c87, 0xfe86, +0xc0a9, 0x02a8, 0x44aa, 0x86ab, 0xc8ae, 0x0aaf, 0x4cad, 0x8eac, 0xd0a7, 0x12a6, 0x54a4, 0x96a5, 0xd8a0, 0x1aa1, 0x5ca3, 0x9ea2, +0xe0b5, 0x22b4, 0x64b6, 0xa6b7, 0xe8b2, 0x2ab3, 0x6cb1, 0xaeb0, 0xf0bb, 0x32ba, 0x74b8, 0xb6b9, 0xf8bc, 0x3abd, 0x7cbf, 0xbebe +}; diff --git a/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpaesgcmtbl2kca.c b/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpaesgcmtbl2kca.c new file mode 100644 index 0000000000..edbdfd291a --- /dev/null +++ b/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpaesgcmtbl2kca.c @@ -0,0 +1,229 @@ +/* +* Copyright (C) 2016 Intel Corporation. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in +* the documentation and/or other materials provided with the +* distribution. +* * Neither the name of Intel Corporation nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ + +#include "owndefs.h" +#include "owncp.h" + +#include "pcpaesauthgcm.h" +#include "pcptool.h" + +#include "pcprijtables.h" + + +/* +// AES-GCM precomputations. +*/ +static void RightShiftBlock16(Ipp8u* pBlock) +{ + Ipp8u v0 = 0; + int i; + for(i=0; i<16; i++) { + Ipp8u v1 = pBlock[i]; + Ipp8u tmp = (Ipp8u)( (v1>>1) | (v0<<7) ); + pBlock[i] = tmp; + v0 = v1; + } +} +void AesGcmPrecompute_table2K(Ipp8u* pPrecomputeData, const Ipp8u* pHKey) +{ + Ipp8u t[BLOCK_SIZE]; + int n; + + CopyBlock16(pHKey, t); + + for(n=0; n<128-24; n++) { + /* get msb */ + int hBit = t[15]&1; + + int k = n%32; + if(k<4) { + CopyBlock16(t, pPrecomputeData +1024 +(n/32)*256 +(Ipp32u)(1<<(7-k))); + } + else if(k<8) { + CopyBlock16(t, pPrecomputeData +(n/32)*256 +(Ipp32u)(1<<(11-k))); + } + + /* shift */ + RightShiftBlock16(t); + /* xor if msb=1 */ + if(hBit) + t[0] ^= 0xe1; + } + + for(n=0; n<4; n++) { + int m, k; + XorBlock16(pPrecomputeData +n*256, pPrecomputeData +n*256, pPrecomputeData +n*256); + XorBlock16(pPrecomputeData +1024 +n*256, pPrecomputeData +1024 +n*256, pPrecomputeData +1024 +n*256); + for(m=2; m<=8; m*=2) + for(k=1; k=BLOCK_SIZE) { + /* add src */ + XorBlock16(pSrc, pHash, pHash); + /* hash it */ + AesGcmMulGcm_table2K(pHash, pHKey, AesGcmConst_table); + + pSrc += BLOCK_SIZE; + len -= BLOCK_SIZE; + } +} + + +/* +// encrypts and authenticates n*BLOCK_SIZE bytes +*/ +void wrpAesGcmEnc_table2K(Ipp8u* pDst, const Ipp8u* pSrc, int len, IppsAES_GCMState* pState) +{ + Ipp8u* pHashedData = pDst; + int hashedDataLen = len; + + Ipp8u* pCounter = AESGCM_COUNTER(pState); + Ipp8u* pECounter = AESGCM_ECOUNTER(pState); + + IppsAESSpec* pAES = AESGCM_CIPHER(pState); + RijnCipher encoder = RIJ_ENCODER(pAES); + + while(len>=BLOCK_SIZE) { + /* encrypt whole AES block */ + XorBlock16(pSrc, pECounter, pDst); + + pSrc += BLOCK_SIZE; + pDst += BLOCK_SIZE; + len -= BLOCK_SIZE; + + /* increment counter block */ + IncrementCounter32(pCounter); + /* and encrypt counter */ + encoder(pCounter, pECounter, RIJ_NR(pAES), RIJ_EKEYS(pAES), RijEncSbox); + } + + AesGcmAuth_table2K(AESGCM_GHASH(pState), pHashedData, hashedDataLen, AESGCM_HKEY(pState), AesGcmConst_table); +} + + +/* +// authenticates and decrypts n*BLOCK_SIZE bytes +*/ +void wrpAesGcmDec_table2K(Ipp8u* pDst, const Ipp8u* pSrc, int len, IppsAES_GCMState* pState) +{ + AesGcmAuth_table2K(AESGCM_GHASH(pState), pSrc, len, AESGCM_HKEY(pState), AesGcmConst_table); + + { + Ipp8u* pCounter = AESGCM_COUNTER(pState); + Ipp8u* pECounter = AESGCM_ECOUNTER(pState); + + IppsAESSpec* pAES = AESGCM_CIPHER(pState); + RijnCipher encoder = RIJ_ENCODER(pAES); + + while(len>=BLOCK_SIZE) { + /* encrypt whole AES block */ + XorBlock16(pSrc, pECounter, pDst); + + pSrc += BLOCK_SIZE; + pDst += BLOCK_SIZE; + len -= BLOCK_SIZE; + + /* increment counter block */ + IncrementCounter32(pCounter); + /* and encrypt counter */ + encoder(pCounter, pECounter, RIJ_NR(pAES), RIJ_EKEYS(pAES), RijEncSbox); + } + } +} diff --git a/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpaesm.h b/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpaesm.h new file mode 100644 index 0000000000..924fcf238e --- /dev/null +++ b/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpaesm.h @@ -0,0 +1,50 @@ +/* +* Copyright (C) 2016 Intel Corporation. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in +* the documentation and/or other materials provided with the +* distribution. +* * Neither the name of Intel Corporation nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ + +#if !defined(_PCP_AES_H) +#define _PCP_AES_H + +#include "pcprij.h" + +/* alignment of AES context */ +#define AES_ALIGNMENT (RIJ_ALIGNMENT) + +/* valid AES context ID */ +#define VALID_AES_ID(ctx) (RIJ_ID((ctx))==idCtxRijndael) + +/* size of AES context */ +__INLINE int cpSizeofCtx_AES(void) +{ + return sizeof(IppsAESSpec) + +(AES_ALIGNMENT-1); +} + +#endif /* _PCP_AES_H */ diff --git a/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpaesmctrca.c b/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpaesmctrca.c new file mode 100644 index 0000000000..6aac2fc218 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpaesmctrca.c @@ -0,0 +1,150 @@ +/* +* Copyright (C) 2016 Intel Corporation. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in +* the documentation and/or other materials provided with the +* distribution. +* * Neither the name of Intel Corporation nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ + +#include "owndefs.h" + +#include "owncp.h" +#include "pcpaesm.h" +#include "pcptool.h" + +#include "pcprijtables.h" + +/* +// AES-CRT processing. +// +// Returns: Reason: +// ippStsNullPtrErr pCtx == NULL +// pSrc == NULL +// pDst == NULL +// pCtrValue ==NULL +// ippStsContextMatchErr !VALID_AES_ID() +// ippStsLengthErr len <1 +// ippStsCTRSizeErr 128 < ctrNumBitSize < 1 +// ippStsNoErr no errors +// +// Parameters: +// pSrc pointer to the source data buffer +// pDst pointer to the target data buffer +// dataLen input/output buffer length (in bytes) +// pCtx pointer to rge AES context +// pCtrValue pointer to the counter block +// ctrNumBitSize counter block size (bits) +// +// Note: +// counter will updated on return +// +*/ +static +IppStatus cpProcessAES_ctr(const Ipp8u* pSrc, Ipp8u* pDst, int dataLen, + const IppsAESSpec* pCtx, + Ipp8u* pCtrValue, int ctrNumBitSize) +{ + /* test context */ + IPP_BAD_PTR1_RET(pCtx); + /* use aligned AES context */ + pCtx = (IppsAESSpec*)( IPP_ALIGNED_PTR(pCtx, AES_ALIGNMENT) ); + /* test the context ID */ + IPP_BADARG_RET(!VALID_AES_ID(pCtx), ippStsContextMatchErr); + + /* test source, target and counter block pointers */ + IPP_BAD_PTR3_RET(pSrc, pDst, pCtrValue); + /* test stream length */ + IPP_BADARG_RET((dataLen<1), ippStsLengthErr); + + /* test counter block size */ + IPP_BADARG_RET(((MBS_RIJ128*8)= MBS_RIJ128) { + /* encrypt counter block */ + encoder((Ipp8u*)counter, (Ipp8u*)output, RIJ_NR(pCtx), RIJ_EKEYS(pCtx), RijEncSbox); + + /* compute ciphertext block */ + if( !(IPP_UINT_PTR(pSrc) & 0x3) && !(IPP_UINT_PTR(pDst) & 0x3)) { + ((Ipp32u*)pDst)[0] = output[0]^((Ipp32u*)pSrc)[0]; + ((Ipp32u*)pDst)[1] = output[1]^((Ipp32u*)pSrc)[1]; + ((Ipp32u*)pDst)[2] = output[2]^((Ipp32u*)pSrc)[2]; + ((Ipp32u*)pDst)[3] = output[3]^((Ipp32u*)pSrc)[3]; + } + else + XorBlock16(pSrc, output, pDst); + /* encrement counter block */ + StdIncrement((Ipp8u*)counter,MBS_RIJ128*8, ctrNumBitSize); + + pSrc += MBS_RIJ128; + pDst += MBS_RIJ128; + dataLen -= MBS_RIJ128; + } + /* + // encrypt last data block + */ + if(dataLen) { + /* encrypt counter block */ + encoder((Ipp8u*)counter, (Ipp8u*)output, RIJ_NR(pCtx), RIJ_EKEYS(pCtx), RijEncSbox); + + /* compute ciphertext block */ + XorBlock(pSrc, output, pDst,dataLen); + /* encrement counter block */ + StdIncrement((Ipp8u*)counter,MBS_RIJ128*8, ctrNumBitSize); + } + + /* update counter */ + CopyBlock16(counter, pCtrValue); + + return ippStsNoErr; + } +} + +IPPFUN(IppStatus, ippsAESEncryptCTR,(const Ipp8u* pSrc, Ipp8u* pDst, int dataLen, + const IppsAESSpec* pCtx, + Ipp8u* pCtrValue, int ctrNumBitSize)) +{ + return cpProcessAES_ctr(pSrc, pDst, dataLen, pCtx, pCtrValue, ctrNumBitSize); +} + +IPPFUN(IppStatus, ippsAESDecryptCTR,(const Ipp8u* pSrc, Ipp8u* pDst, int dataLen, + const IppsAESSpec* pCtx, + Ipp8u* pCtrValue, int ctrNumBitSize)) +{ + return cpProcessAES_ctr(pSrc, pDst, dataLen, pCtx, pCtrValue, ctrNumBitSize); +} diff --git a/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpaesminitca.c b/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpaesminitca.c new file mode 100644 index 0000000000..262fa85e90 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpaesminitca.c @@ -0,0 +1,173 @@ +/* +* Copyright (C) 2016 Intel Corporation. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in +* the documentation and/or other materials provided with the +* distribution. +* * Neither the name of Intel Corporation nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ + +#include "owndefs.h" +#include "owncp.h" +#include "pcpaesm.h" +#include "pcptool.h" + +#include "pcprijtables.h" + +/*F* +// Name: ippsAESGetSize +// +// Purpose: Returns size of AES context (in bytes). +// +// Returns: Reason: +// ippStsNullPtrErr pSzie == NULL +// ippStsNoErr no errors +// +// Parameters: +// pSize pointer to AES size of context(in bytes) +// +*F*/ +IPPFUN(IppStatus, ippsAESGetSize,(int* pSize)) +{ + /* test size's pointer */ + IPP_BAD_PTR1_RET(pSize); + + *pSize = cpSizeofCtx_AES(); + + return ippStsNoErr; +} + +/* number of rounds (use [NK] for access) */ +static int rij128nRounds[3] = {NR128_128, NR128_192, NR128_256}; + +/* +// number of keys (estimation only!) (use [NK] for access) +// +// accurate number of keys necassary for encrypt/decrypt are: +// nKeys = NB * (NR+1) +// where NB - data block size (32-bit words) +// NR - number of rounds (depend on NB and keyLen) +// +// but the estimation +// estnKeys = (NK*n) >= nKeys +// or +// estnKeys = ( (NB*(NR+1) + (NK-1)) / NK) * NK +// where NK - key length (words) +// NB - data block size (word) +// NR - number of rounds (depend on NB and keyLen) +// nKeys - accurate numner of keys +// is more convinient when calculates key extension +*/ +static int rij128nKeys[3] = {44, 54, 64 }; + +/* +// helper for nRounds[] and estnKeys[] access +// note: x is length in 32-bits words +*/ +__INLINE int rij_index(int x) +{ return (x-NB(128))>>1; } + +/*F* +// Name: ippsAESInit +// +// Purpose: Init AES context for future usage +// and setup secret key. +// +// Returns: Reason: +// ippStsNullPtrErr pCtx == NULL +// ippStsMemAllocErr size of buffer is not match fro operation +// ippStsLengthErr keyLen != 16 +// keyLen != 24 +// keyLen != 32 +// +// Parameters: +// pKey secret key +// keyLen length of the secret key (in bytes) +// pCtx pointer to buffer initialized as AES context +// ctxSize available size (in bytes) of buffer above +// +// Note: +// if pKey==NULL, then AES initialized by zero value key +// +*F*/ +IPPFUN(IppStatus, ippsAESInit,(const Ipp8u* pKey, int keyLen, + IppsAESSpec* pCtxRaw, int rawCtxSize)) +{ + /* test context pointer */ + IPP_BAD_PTR1_RET(pCtxRaw); + + /* make sure in legal keyLen */ + IPP_BADARG_RET(keyLen!=16 && keyLen!=24 && keyLen!=32, ippStsLengthErr); + + { + /* use aligned Rijndael context */ + IppsAESSpec* pCtx = (IppsAESSpec*)( IPP_ALIGNED_PTR(pCtxRaw, AES_ALIGNMENT) ); + + /* test available size of context buffer */ + if(((Ipp8u*)pCtx+sizeof(IppsAESSpec)) > ((Ipp8u*)pCtxRaw+rawCtxSize)) + IPP_ERROR_RET(ippStsMemAllocErr); + + else { + int keyWords = NK(keyLen*BITSIZE(Ipp8u)); + int nExpKeys = rij128nKeys [ rij_index(keyWords) ]; + int nRounds = rij128nRounds[ rij_index(keyWords) ]; + + Ipp8u zeroKey[32] = {0}; + const Ipp8u* pActualKey = pKey? pKey : zeroKey; + + /* clear context */ + PaddBlock(0, pCtx, sizeof(IppsAESSpec)); + + /* init spec */ + RIJ_ID(pCtx) = idCtxRijndael; + RIJ_NB(pCtx) = NB(128); + RIJ_NK(pCtx) = keyWords; + RIJ_NR(pCtx) = nRounds; + RIJ_SAFE_INIT(pCtx) = 1; + + /* set key expansion */ + ExpandRijndaelKey(pActualKey, keyWords, NB(128), nRounds, nExpKeys, + RIJ_EKEYS(pCtx), + RIJ_DKEYS(pCtx)); + { + int nr; + Ipp8u* pEnc_key = (Ipp8u*)(RIJ_EKEYS(pCtx)); + /* update key material: transpose inplace */ + for(nr=0; nr<(1+nRounds); nr++, pEnc_key+=16) { + SWAP(pEnc_key[ 1], pEnc_key[ 4]); + SWAP(pEnc_key[ 2], pEnc_key[ 8]); + SWAP(pEnc_key[ 3], pEnc_key[12]); + SWAP(pEnc_key[ 6], pEnc_key[ 9]); + SWAP(pEnc_key[ 7], pEnc_key[13]); + SWAP(pEnc_key[11], pEnc_key[14]); + } + } + RIJ_ENCODER(pCtx) = Safe2Encrypt_RIJ128; /* safe encoder (compact Sbox)) */ + RIJ_DECODER(pCtx) = Safe2Decrypt_RIJ128; /* safe decoder (compact Sbox)) */ + + return ippStsNoErr; + } + } +} diff --git a/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpbn.h b/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpbn.h new file mode 100644 index 0000000000..180f59c5fd --- /dev/null +++ b/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpbn.h @@ -0,0 +1,210 @@ +/* +* Copyright (C) 2016 Intel Corporation. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in +* the documentation and/or other materials provided with the +* distribution. +* * Neither the name of Intel Corporation nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ + +#if !defined(_CP_BN_H) +#define _CP_BN_H + +#include "pcpbnuimpl.h" +#include "pcpbnuarith.h" +#include "pcpbnumisc.h" +#include "pcpbnu32arith.h" +#include "pcpbnu32misc.h" + +/* +// Big Number context +*/ +struct _cpBigNum +{ + IppCtxId idCtx; /* BigNum ctx id */ + IppsBigNumSGN sgn; /* sign */ + cpSize size; /* BigNum size (BNU_CHUNK_T) */ + cpSize room; /* BigNum max size (BNU_CHUNK_T) */ + BNU_CHUNK_T* number; /* BigNum value */ + BNU_CHUNK_T* buffer; /* temporary buffer */ +}; + +/* BN accessory macros */ +#define BN_ID(pBN) ((pBN)->idCtx) +#define BN_SIGN(pBN) ((pBN)->sgn) +#define BN_POSITIVE(pBN) (BN_SIGN(pBN)==ippBigNumPOS) +#define BN_NEGATIVE(pBN) (BN_SIGN(pBN)==ippBigNumNEG) +#define BN_NUMBER(pBN) ((pBN)->number) +#define BN_BUFFER(pBN) ((pBN)->buffer) +#define BN_ROOM(pBN) ((pBN)->room) +#define BN_SIZE(pBN) ((pBN)->size) +#define BN_SIZE32(pBN) ((pBN)->size*(sizeof(BNU_CHUNK_T)/sizeof(Ipp32u))) +//#define BN_SIZE32(pBN) (BITS2WORD32_SIZE( BITSIZE_BNU(BN_NUMBER((pBN)),BN_SIZE((pBN))))) + +#define BN_VALID_ID(pBN) (BN_ID((pBN))==idCtxBigNum) + +#define INVERSE_SIGN(s) (((s)==ippBigNumPOS)? ippBigNumNEG : ippBigNumPOS) + +#define BN_ALIGNMENT ((int)sizeof(void*)) + + +/* pack-unpack context */ +void cpPackBigNumCtx(const IppsBigNumState* pBN, Ipp8u* pBuffer); +void cpUnpackBigNumCtx(const Ipp8u* pBuffer, IppsBigNumState* pBN); + +/* copy BN */ +__INLINE IppsBigNumState* cpBN_copy(IppsBigNumState* pDst, const IppsBigNumState* pSrc) +{ + BN_SIGN(pDst) = BN_SIGN(pSrc); + BN_SIZE(pDst) = BN_SIZE(pSrc); + ZEXPAND_COPY_BNU(BN_NUMBER(pDst), BN_ROOM(pDst), BN_NUMBER(pSrc), BN_SIZE(pSrc)); + return pDst; +} +/* set BN to zero */ +__INLINE IppsBigNumState* cpBN_zero(IppsBigNumState* pBN) +{ + BN_SIGN(pBN) = ippBigNumPOS; + BN_SIZE(pBN) = 1; + ZEXPAND_BNU(BN_NUMBER(pBN),0, (int)BN_ROOM(pBN)); + return pBN; +} +/* fixup BN */ +__INLINE IppsBigNumState* cpBN_fix(IppsBigNumState* pBN) +{ + cpSize len = BN_SIZE(pBN); + FIX_BNU(BN_NUMBER(pBN), len); + BN_SIZE(pBN) = len; + return pBN; +} +/* set BN to chunk */ +__INLINE IppsBigNumState* cpBN_chunk(IppsBigNumState* pBN, BNU_CHUNK_T a) +{ + BN_SIGN(pBN) = ippBigNumPOS; + BN_SIZE(pBN) = 1; + ZEXPAND_BNU(BN_NUMBER(pBN),0, (int)BN_ROOM(pBN)); + BN_NUMBER(pBN)[0] = a; + return pBN; +} +/* set BN to 2^m */ +__INLINE IppsBigNumState* cpBN_power2(IppsBigNumState* pBN, int power) +{ + cpSize size = BITS_BNU_CHUNK(power+1); + if(BN_ROOM(pBN) >= size) { + BN_SIGN(pBN) = ippBigNumPOS; + BN_SIZE(pBN) = size; + ZEXPAND_BNU(BN_NUMBER(pBN),0, BN_ROOM(pBN)); + SET_BIT(BN_NUMBER(pBN), power); + return pBN; + } + else return NULL; +} + +/* bitsize of BN */ +__INLINE int cpBN_bitsize(const IppsBigNumState* pA) +{ + int bitsize = BITSIZE_BNU(BN_NUMBER(pA), BN_SIZE(pA)); + return bitsize; +} + +/* returns -1/0/+1 depemding on A~B comparison */ +__INLINE int cpBN_cmp(const IppsBigNumState* pA, const IppsBigNumState* pB) +{ + IppsBigNumSGN signA = BN_SIGN(pA); + IppsBigNumSGN signB = BN_SIGN(pB); + + if(signA==signB) { + int result = cpCmp_BNU(BN_NUMBER(pA), BN_SIZE(pA), BN_NUMBER(pB), BN_SIZE(pB)); + return (ippBigNumPOS==signA)? result : -result; + } + return (ippBigNumPOS==signA)? 1 : -1; +} + +/* returns -1/0/+1 depemding on A comparison 00 */ +__INLINE int cpBN_tst(const IppsBigNumState* pA) +{ + if(1==BN_SIZE(pA) && 0==BN_NUMBER(pA)[0]) + return 0; + else + return BN_POSITIVE(pA)? 1 : -1; +} + + +// some addtition functions +__INLINE int IsZero_BN(const IppsBigNumState* pA) +{ + return ( BN_SIZE(pA)==1 ) && ( BN_NUMBER(pA)[0]==0 ); +} +__INLINE int IsOdd_BN(const IppsBigNumState* pA) +{ + return BN_NUMBER(pA)[0] & 1; +} + +__INLINE IppsBigNumState* BN_Word(IppsBigNumState* pBN, BNU_CHUNK_T w) +{ + BN_SIGN(pBN) = ippBigNumPOS; + BN_SIZE(pBN) = 1; + ZEXPAND_BNU(BN_NUMBER(pBN),0, BN_ROOM(pBN)); + BN_NUMBER(pBN)[0] = w; + return pBN; +} +__INLINE IppsBigNumState* BN_Set(const BNU_CHUNK_T* pData, cpSize len, IppsBigNumState* pBN) +{ + BN_SIGN(pBN) = ippBigNumPOS; + BN_SIZE(pBN) = len; + ZEXPAND_COPY_BNU(BN_NUMBER(pBN), BN_ROOM(pBN), pData, len); + return pBN; +} +__INLINE IppsBigNumState* BN_Make(BNU_CHUNK_T* pData, BNU_CHUNK_T* pBuffer, cpSize len, IppsBigNumState* pBN) +{ + BN_ID(pBN) = idCtxBigNum; + BN_SIGN(pBN) = ippBigNumPOS; + BN_SIZE(pBN) = 1; + BN_ROOM(pBN) = len; + BN_NUMBER(pBN) = pData; + BN_BUFFER(pBN) = pBuffer; + return pBN; +} + + + +/* +// fixed single chunk BN +*/ +typedef struct _ippcpBigNumChunk { + IppsBigNumState bn; + BNU_CHUNK_T value; + BNU_CHUNK_T temporary; +} IppsBigNumStateChunk; + +/* reference to BN(1) and BN(2) */ +IppsBigNumState* cpBN_OneRef(void); +IppsBigNumState* cpBN_TwoRef(void); +IppsBigNumState* cpBN_ThreeRef(void); + +#define BN_ONE_REF() cpBN_OneRef() +#define BN_TWO_REF() cpBN_TwoRef() +#define BN_THREE_REF() cpBN_ThreeRef() + +#endif /* _CP_BN_H */ diff --git a/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpbnca.c b/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpbnca.c new file mode 100644 index 0000000000..5e1e2a3d38 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpbnca.c @@ -0,0 +1,1058 @@ +/* +* Copyright (C) 2016 Intel Corporation. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in +* the documentation and/or other materials provided with the +* distribution. +* * Neither the name of Intel Corporation nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ + +#include "owndefs.h" +#include "owncp.h" +#include "pcpbn.h" +#include "pcptool.h" + +/* BN(1) and reference */ +static IppsBigNumStateChunk cpChunk_BN1 = { + { + idCtxBigNum, + ippBigNumPOS, + 1,1, + &cpChunk_BN1.value,&cpChunk_BN1.temporary + }, + 1,0 +}; +IppsBigNumState* cpBN_OneRef(void) +{ return &cpChunk_BN1.bn; }; + +/* BN(2) and reference */ +static IppsBigNumStateChunk cpChunk_BN2 = { + { + idCtxBigNum, + ippBigNumPOS, + 1,1, + &cpChunk_BN2.value,&cpChunk_BN2.temporary + }, + 2,0 +}; +IppsBigNumState* cpBN_TwoRef(void) +{ return &cpChunk_BN2.bn; }; + +/* BN(3) and reference */ +static IppsBigNumStateChunk cpChunk_BN3 = { + { + idCtxBigNum, + ippBigNumPOS, + 1,1, + &cpChunk_BN3.value,&cpChunk_BN3.temporary + }, + 3,0 +}; +IppsBigNumState* cpBN_ThreeRef(void) +{ return &cpChunk_BN3.bn; }; + + + +/*F* +// Name: ippsBigNumGetSize +// +// Purpose: Returns size of BigNum ctx (bytes). +// +// Returns: Reason: +// ippStsNullPtrErr pCtxSize == NULL +// ippStsLengthErr len32 < 1 +// len32 > BITS2WORD32_SIZE(BN_MAXBITSIZE) +// ippStsNoErr no errors +// +// Parameters: +// pCtxSize pointer BigNum ctx size +// +*F*/ +IPPFUN(IppStatus, ippsBigNumGetSize, (cpSize len32, cpSize *pCtxSize)) +{ + IPP_BAD_PTR1_RET(pCtxSize); + IPP_BADARG_RET(len32<1 || len32>BITS2WORD32_SIZE(BN_MAXBITSIZE), ippStsLengthErr); + + { + /* convert length to the number of BNU_CHUNK_T */ + cpSize len = INTERNAL_BNU_LENGTH(len32); + + /* reserve one BNU_CHUNK_T more for cpDiv_BNU, + mul, mont exp operations */ + len++; + + *pCtxSize = sizeof(IppsBigNumState) + + len*sizeof(BNU_CHUNK_T) + + len*sizeof(BNU_CHUNK_T) + + BN_ALIGNMENT-1; + + return ippStsNoErr; + } +} + + +/*F* +// Name: ippsBigNumInit +// +// Purpose: Init BigNum spec for future usage. +// +// Returns: Reason: +// ippStsNullPtrErr pBN == NULL +// ippStsLengthErr len32<1 +// len32 > BITS2WORD32_SIZE(BN_MAXBITSIZE) +// ippStsNoErr no errors +// +// Parameters: +// len32 max BN length (32-bits segments) +// pBN BigNum ctx +// +*F*/ +IPPFUN(IppStatus, ippsBigNumInit, (cpSize len32, IppsBigNumState* pBN)) +{ + IPP_BADARG_RET(len32<1 || len32>BITS2WORD32_SIZE(BN_MAXBITSIZE), ippStsLengthErr); + IPP_BAD_PTR1_RET(pBN); + pBN = (IppsBigNumState*)( IPP_ALIGNED_PTR(pBN, BN_ALIGNMENT) ); + + { + Ipp8u* ptr = (Ipp8u*)pBN; + + /* convert length to the number of BNU_CHUNK_T */ + cpSize len = INTERNAL_BNU_LENGTH(len32); + + BN_ID(pBN) = idCtxUnknown; + BN_SIGN(pBN) = ippBigNumPOS; + BN_SIZE(pBN) = 1; /* initial valie is zero */ + BN_ROOM(pBN) = len; /* close to what has been passed by user */ + + /* reserve one BNU_CHUNK_T more for cpDiv_BNU, + mul, mont exp operations */ + len++; + + /* allocate buffers */ + BN_NUMBER(pBN) = (BNU_CHUNK_T*)(ptr += sizeof(IppsBigNumState)); + BN_BUFFER(pBN) = (BNU_CHUNK_T*)(ptr += len*sizeof(BNU_CHUNK_T)); /* use expanded length here */ + + /* set BN value and buffer to zero */ + ZEXPAND_BNU(BN_NUMBER(pBN), 0, len); + ZEXPAND_BNU(BN_BUFFER(pBN), 0, len); + + BN_ID(pBN) = idCtxBigNum; + return ippStsNoErr; + } +} + + +/*F* +// Name: ippsCmpZero_BN +// +// Purpose: Test BigNum value. +// +// Returns: Reason: +// ippStsNullPtrErr pBN == NULL +// pResult == NULL +// ippStsContextMatchErr BN_VALID_ID() +// ippStsNoErr no errors +// +// Parameters: +// pBN BigNum ctx +// pResult result of comparison +// +*F*/ +IPPFUN(IppStatus, ippsCmpZero_BN, (const IppsBigNumState* pBN, Ipp32u* pResult)) +{ + IPP_BAD_PTR2_RET(pBN, pResult); + + pBN = (IppsBigNumState*)( IPP_ALIGNED_PTR(pBN, BN_ALIGNMENT) ); + IPP_BADARG_RET(!BN_VALID_ID(pBN), ippStsContextMatchErr); + + if(BN_SIZE(pBN)==1 && BN_NUMBER(pBN)[0]==0) + *pResult = IS_ZERO; + else if (BN_SIGN(pBN)==ippBigNumPOS) + *pResult = GREATER_THAN_ZERO; + else if (BN_SIGN(pBN)==ippBigNumNEG) + *pResult = LESS_THAN_ZERO; + + return ippStsNoErr; +} + + +/*F* +// Name: ippsCmp_BN +// +// Purpose: Compare two BigNums. +// +// Returns: Reason: +// ippStsNullPtrErr pA == NULL +// pB == NULL +// pResult == NULL +// ippStsContextMatchErr BN_VALID_ID(pA) +// BN_VALID_ID(pB) +// ippStsNoErr no errors +// +// Parameters: +// pA BigNum ctx +// pB BigNum ctx +// pResult result of comparison +// +*F*/ +IPPFUN(IppStatus, ippsCmp_BN,(const IppsBigNumState* pA, const IppsBigNumState* pB, Ipp32u *pResult)) +{ + IPP_BAD_PTR3_RET(pA, pB, pResult); + + pA = (IppsBigNumState*)( IPP_ALIGNED_PTR(pA, BN_ALIGNMENT) ); + IPP_BADARG_RET(!BN_VALID_ID(pA), ippStsContextMatchErr); + pB = (IppsBigNumState*)( IPP_ALIGNED_PTR(pB, BN_ALIGNMENT) ); + IPP_BADARG_RET(!BN_VALID_ID(pB), ippStsContextMatchErr); + + { + int res; + if(BN_SIGN(pA)==BN_SIGN(pB)) { + res = cpCmp_BNU(BN_NUMBER(pA), BN_SIZE(pA), BN_NUMBER(pB), BN_SIZE(pB)); + if(ippBigNumNEG==BN_SIGN(pA)) + res = -res; + } + else + res = (ippBigNumPOS==BN_SIGN(pA))? 1 :-1; + + *pResult = (1==res)? IPP_IS_GT : (-1==res)? IPP_IS_LT : IPP_IS_EQ; + + return ippStsNoErr; + } +} + + +/*F* +// Name: ippsSet_BN +// +// Purpose: Set BigNum. +// +// Returns: Reason: +// ippStsNullPtrErr pBN == NULL +// pData == NULL +// ippStsContextMatchErr BN_VALID_ID(pBN) +// ippStsLengthErr len32 < 1 +// ippStsOutOfRangeErr len32 > BN_ROOM() +// ippStsNoErr no errors +// +// Parameters: +// sgn sign +// len32 data size (in Ipp32u chunks) +// pData source data pointer +// pBn BigNum ctx +// +*F*/ +IPPFUN(IppStatus, ippsSet_BN, (IppsBigNumSGN sgn, cpSize len32, const Ipp32u* pData, + IppsBigNumState* pBN)) +{ + IPP_BAD_PTR2_RET(pData, pBN); + + pBN = (IppsBigNumState*)( IPP_ALIGNED_PTR(pBN, BN_ALIGNMENT) ); + IPP_BADARG_RET(!BN_VALID_ID(pBN), ippStsContextMatchErr); + + IPP_BADARG_RET(len32<1, ippStsLengthErr); + + /* compute real size */ + FIX_BNU(pData, len32); + + { + cpSize len = INTERNAL_BNU_LENGTH(len32); + IPP_BADARG_RET(len > BN_ROOM(pBN), ippStsOutOfRangeErr); + + ZEXPAND_COPY_BNU((Ipp32u*)BN_NUMBER(pBN), BN_ROOM(pBN)*(int)(sizeof(BNU_CHUNK_T)/sizeof(Ipp32u)), pData, len32); + + BN_SIZE(pBN) = len; + + if(len32==1 && pData[0] == 0) + sgn = ippBigNumPOS; /* consider zero value as positive */ + BN_SIGN(pBN) = sgn; + + return ippStsNoErr; + } +} + + +/*F* +// Name: ippsRef_BN +// +// Purpose: Get BigNum info. +// +// Returns: Reason: +// ippStsNullPtrErr pBN == NULL +// ippStsContextMatchErr BN_VALID_ID(pBN) +// ippStsNoErr no errors +// +// Parameters: +// pSgn pointer to the sign +// pBitSize pointer to the data size (in bits) +// ppData pointer to the data buffer +// pBN BigNum ctx +// +*F*/ +IPPFUN(IppStatus, ippsRef_BN, (IppsBigNumSGN* pSgn, cpSize* pBitSize, Ipp32u** const ppData, + const IppsBigNumState *pBN)) +{ + IPP_BAD_PTR1_RET(pBN); + + pBN = (IppsBigNumState*)( IPP_ALIGNED_PTR(pBN, BN_ALIGNMENT) ); + IPP_BADARG_RET(!BN_VALID_ID(pBN), ippStsContextMatchErr); + + if(pSgn) + *pSgn = BN_SIGN(pBN); + if(pBitSize) { + cpSize bitLen = BITSIZE_BNU(BN_NUMBER(pBN), BN_SIZE(pBN)); + *pBitSize = bitLen? bitLen : 1; + } + + if(ppData) + *ppData = (Ipp32u*)BN_NUMBER(pBN); + + return ippStsNoErr; +} + + +/*F* +// Name: ippsAdd_BN +// +// Purpose: Add BigNum. +// +// Returns: Reason: +// ippStsNullPtrErr pA == NULL +// pB == NULL +// pR == NULL +// ippStsContextMatchErr BN_VALID_ID(pA) +// BN_VALID_ID(pB) +// BN_VALID_ID(pR) +// ippStsOutOfRangeErr pR can not hold result +// ippStsNoErr no errors +// +// Parameters: +// pA source BigNum +// pB source BigNum +// pR resultant BigNum +// +*F*/ +IPPFUN(IppStatus, ippsAdd_BN, (IppsBigNumState* pA, IppsBigNumState* pB, IppsBigNumState* pR)) +{ + IPP_BAD_PTR3_RET(pA, pB, pR); + + pA = (IppsBigNumState*)( IPP_ALIGNED_PTR(pA, BN_ALIGNMENT) ); + IPP_BADARG_RET(!BN_VALID_ID(pA), ippStsContextMatchErr); + pB = (IppsBigNumState*)( IPP_ALIGNED_PTR(pB, BN_ALIGNMENT) ); + IPP_BADARG_RET(!BN_VALID_ID(pB), ippStsContextMatchErr); + pR = (IppsBigNumState*)( IPP_ALIGNED_PTR(pR, BN_ALIGNMENT) ); + IPP_BADARG_RET(!BN_VALID_ID(pR), ippStsContextMatchErr); + + { + cpSize nsA = BN_SIZE(pA); + cpSize nsB = BN_SIZE(pB); + cpSize nsR = BN_ROOM(pR); + IPP_BADARG_RET(nsR < IPP_MAX(nsA, nsB), ippStsOutOfRangeErr); + + { + BNU_CHUNK_T* pDataR = BN_NUMBER(pR); + + IppsBigNumSGN sgnA = BN_SIGN(pA); + IppsBigNumSGN sgnB = BN_SIGN(pB); + BNU_CHUNK_T* pDataA = BN_NUMBER(pA); + BNU_CHUNK_T* pDataB = BN_NUMBER(pB); + + BNU_CHUNK_T carry; + + if(sgnA==sgnB) { + if(nsA < nsB) { + SWAP(nsA, nsB); + SWAP_PTR(BNU_CHUNK_T, pDataA, pDataB); + } + + carry = cpAdd_BNU(pDataR, pDataA, pDataB, nsB); + if(nsA>nsB) + carry = cpInc_BNU(pDataR+nsB, pDataA+nsB, nsA-nsB, carry); + if(carry) { + if(nsR>nsA) + pDataR[nsA++] = carry; + else + IPP_ERROR_RET(ippStsOutOfRangeErr); + } + BN_SIGN(pR) = sgnA; + } + + else { + int cmpRes = cpCmp_BNU(pDataA, nsA, pDataB, nsB); + + if(0==cmpRes) { + pDataR[0] = 0; + BN_SIZE(pR) = 1; + BN_SIGN(pR) = ippBigNumPOS; + return ippStsNoErr; + } + + if(0>cmpRes) { + SWAP(nsA, nsB); + SWAP_PTR(BNU_CHUNK_T, pDataA, pDataB); + } + + carry = cpSub_BNU(pDataR, pDataA, pDataB, nsB); + if(nsA>nsB) + cpDec_BNU(pDataR+nsB, pDataA+nsB, nsA-nsB, carry); + + BN_SIGN(pR) = cmpRes>0? sgnA : INVERSE_SIGN(sgnA); + } + + FIX_BNU(pDataR, nsA); + BN_SIZE(pR) = nsA; + + return ippStsNoErr; + } + } +} + + +/*F* +// Name: ippsSub_BN +// +// Purpose: Subtcrac BigNum. +// +// Returns: Reason: +// ippStsNullPtrErr pA == NULL +// pB == NULL +// pR == NULL +// ippStsContextMatchErr BN_VALID_ID(pA) +// BN_VALID_ID(pB) +// BN_VALID_ID(pR) +// ippStsOutOfRangeErr pR can not hold result +// ippStsNoErr no errors +// +// Parameters: +// pA source BigNum +// pB source BigNum +// pR resultant BigNum +// +*F*/ +IPPFUN(IppStatus, ippsSub_BN, (IppsBigNumState* pA, IppsBigNumState* pB, IppsBigNumState* pR)) +{ + IPP_BAD_PTR3_RET(pA, pB, pR); + + pA = (IppsBigNumState*)( IPP_ALIGNED_PTR(pA, BN_ALIGNMENT) ); + IPP_BADARG_RET(!BN_VALID_ID(pA), ippStsContextMatchErr); + pB = (IppsBigNumState*)( IPP_ALIGNED_PTR(pB, BN_ALIGNMENT) ); + IPP_BADARG_RET(!BN_VALID_ID(pB), ippStsContextMatchErr); + pR = (IppsBigNumState*)( IPP_ALIGNED_PTR(pR, BN_ALIGNMENT) ); + IPP_BADARG_RET(!BN_VALID_ID(pR), ippStsContextMatchErr); + + { + cpSize nsA = BN_SIZE(pA); + cpSize nsB = BN_SIZE(pB); + cpSize nsR = BN_ROOM(pR); + IPP_BADARG_RET(nsR < IPP_MAX(nsA, nsB), ippStsOutOfRangeErr); + + { + BNU_CHUNK_T* pDataR = BN_NUMBER(pR); + + IppsBigNumSGN sgnA = BN_SIGN(pA); + IppsBigNumSGN sgnB = BN_SIGN(pB); + BNU_CHUNK_T* pDataA = BN_NUMBER(pA); + BNU_CHUNK_T* pDataB = BN_NUMBER(pB); + + BNU_CHUNK_T carry; + + if(sgnA!=sgnB) { + if(nsA < nsB) { + SWAP(nsA, nsB); + SWAP_PTR(BNU_CHUNK_T, pDataA, pDataB); + } + + carry = cpAdd_BNU(pDataR, pDataA, pDataB, nsB); + if(nsA>nsB) + carry = cpInc_BNU(pDataR+nsB, pDataA+nsB, nsA-nsB, carry); + if(carry) { + if(nsR > nsA) + pDataR[nsA++] = carry; + else + IPP_ERROR_RET(ippStsOutOfRangeErr); + } + BN_SIGN(pR) = sgnA; + } + + else { + int cmpRes= cpCmp_BNU(pDataA, nsA, pDataB, nsB); + + if(0==cmpRes) { + ZEXPAND_BNU(pDataR,0, nsR); + BN_SIZE(pR) = 1; + BN_SIGN(pR) = ippBigNumPOS; + return ippStsNoErr; + } + + if(0>cmpRes) { + SWAP(nsA, nsB); + SWAP_PTR(BNU_CHUNK_T, pDataA, pDataB); + } + + carry = cpSub_BNU(pDataR, pDataA, pDataB, nsB); + if(nsA>nsB) + cpDec_BNU(pDataR+nsB, pDataA+nsB, nsA-nsB, carry); + + BN_SIGN(pR) = cmpRes>0? sgnA : INVERSE_SIGN(sgnA); + } + + FIX_BNU(pDataR, nsA); + BN_SIZE(pR) = nsA; + + return ippStsNoErr; + } + } +} + + +/*F* +// Name: ippsMul_BN +// +// Purpose: Multiply BigNum. +// +// Returns: Reason: +// ippStsNullPtrErr pA == NULL +// pB == NULL +// pR == NULL +// ippStsContextMatchErr BN_VALID_ID(pA) +// BN_VALID_ID(pB) +// BN_VALID_ID(pR) +// ippStsOutOfRangeErr pR can not hold result +// ippStsNoErr no errors +// +// Parameters: +// pA source BigNum +// pB source BigNum +// pR resultant BigNum +// +*F*/ +IPPFUN(IppStatus, ippsMul_BN, (IppsBigNumState* pA, IppsBigNumState* pB, IppsBigNumState* pR)) +{ + IPP_BAD_PTR3_RET(pA, pB, pR); + + pA = (IppsBigNumState*)( IPP_ALIGNED_PTR(pA, BN_ALIGNMENT) ); + IPP_BADARG_RET(!BN_VALID_ID(pA), ippStsContextMatchErr); + pB = (IppsBigNumState*)( IPP_ALIGNED_PTR(pB, BN_ALIGNMENT) ); + IPP_BADARG_RET(!BN_VALID_ID(pB), ippStsContextMatchErr); + pR = (IppsBigNumState*)( IPP_ALIGNED_PTR(pR, BN_ALIGNMENT) ); + IPP_BADARG_RET(!BN_VALID_ID(pR), ippStsContextMatchErr); + + { + BNU_CHUNK_T* pDataA = BN_NUMBER(pA); + BNU_CHUNK_T* pDataB = BN_NUMBER(pB); + BNU_CHUNK_T* pDataR = BN_NUMBER(pR); + + cpSize nsA = BN_SIZE(pA); + cpSize nsB = BN_SIZE(pB); + cpSize nsR = BN_ROOM(pR); + + cpSize bitSizeA = BITSIZE_BNU(pDataA, nsA); + cpSize bitSizeB = BITSIZE_BNU(pDataB, nsB); + + /* test if multiplicant/multiplier is zero */ + if(!bitSizeA || !bitSizeB) { + BN_SIZE(pR) = 1; + BN_SIGN(pR) = IppsBigNumPOS; + pDataR[0] = 0; + return ippStsNoErr; + } + + /* test if even low estimation of product A*B exceeded */ + IPP_BADARG_RET(nsR*BNU_CHUNK_BITS < (bitSizeA+bitSizeB-1), ippStsOutOfRangeErr); + + { + BNU_CHUNK_T* aData = pDataA; + BNU_CHUNK_T* bData = pDataB; + + if(pA == pR) { + aData = BN_BUFFER(pR); + COPY_BNU(aData, pDataA, nsA); + } + if((pB == pR) && (pA != pB)) { + bData = BN_BUFFER(pR); + COPY_BNU(bData, pDataB, nsB); + } + + /* clear result */ + ZEXPAND_BNU(pDataR, 0, nsR+1); + + cpMul_BNU_school(pDataR, aData, nsA, bData, nsB); + + nsR = (bitSizeA + bitSizeB + BNU_CHUNK_BITS - 1) /BNU_CHUNK_BITS; + FIX_BNU(pDataR, nsR); + IPP_BADARG_RET(nsR>BN_ROOM(pR), ippStsOutOfRangeErr); + + BN_SIZE(pR) = nsR; + BN_SIGN(pR) = (BN_SIGN(pA)==BN_SIGN(pB)? ippBigNumPOS : ippBigNumNEG); + return ippStsNoErr; + } + } +} + + +/*F* +// Name: ippsDiv_BN +// +// Purpose: Divide BigNum. +// +// Returns: Reason: +// ippStsNullPtrErr pA == NULL +// pB == NULL +// pQ == NULL +// pR == NULL +// ippStsContextMatchErr BN_VALID_ID(pA) +// BN_VALID_ID(pB) +// BN_VALID_ID(pQ) +// BN_VALID_ID(pR) +// ippStsOutOfRangeErr pQ and/or pR can not hold result +// ippStsNoErr no errors +// +// Parameters: +// pA source BigNum +// pB source BigNum +// pQ quotient BigNum +// pR reminder BigNum +// +// A = Q*B + R, 0 <= val(R) < val(B), sgn(A)==sgn(R) +// +*F*/ +IPPFUN(IppStatus, ippsDiv_BN, (IppsBigNumState* pA, IppsBigNumState* pB, IppsBigNumState* pQ, IppsBigNumState* pR)) +{ + IPP_BAD_PTR4_RET(pA, pB, pQ, pR); + + pA = (IppsBigNumState*)( IPP_ALIGNED_PTR(pA, BN_ALIGNMENT) ); + IPP_BADARG_RET(!BN_VALID_ID(pA), ippStsContextMatchErr); + pB = (IppsBigNumState*)( IPP_ALIGNED_PTR(pB, BN_ALIGNMENT) ); + IPP_BADARG_RET(!BN_VALID_ID(pB), ippStsContextMatchErr); + pQ = (IppsBigNumState*)( IPP_ALIGNED_PTR(pQ, BN_ALIGNMENT) ); + IPP_BADARG_RET(!BN_VALID_ID(pQ), ippStsContextMatchErr); + pR = (IppsBigNumState*)( IPP_ALIGNED_PTR(pR, BN_ALIGNMENT) ); + IPP_BADARG_RET(!BN_VALID_ID(pR), ippStsContextMatchErr); + + IPP_BADARG_RET(BN_SIZE(pB)== 1 && BN_NUMBER(pB)[0]==0, ippStsDivByZeroErr); + + IPP_BADARG_RET(BN_ROOM(pR)cmpRes) + SWAP_PTR(IppsBigNumState, x, y); + if(0==cmpRes) { + COPY_BNU(BN_NUMBER(g), BN_NUMBER(x), BN_SIZE(x)); + BN_SIGN(g) = ippBigNumPOS; + BN_SIZE(g) = BN_SIZE(x); + return ippStsNoErr; + } + if(BN_SIZE(x)==1) { + BNU_CHUNK_T gcd = cpGcd_BNU(BN_NUMBER(x)[0], BN_NUMBER(y)[0]); + BN_NUMBER(g)[0] = gcd; + BN_SIZE(g) = 1; + return ippStsNoErr; + } + } + + { + Ipp32u* xBuffer = (Ipp32u*)BN_BUFFER(x); + Ipp32u* yBuffer = (Ipp32u*)BN_BUFFER(y); + Ipp32u* gBuffer = (Ipp32u*)BN_BUFFER(g); + Ipp32u* xData = (Ipp32u*)BN_NUMBER(x); + Ipp32u* yData = (Ipp32u*)BN_NUMBER(y); + Ipp32u* gData = (Ipp32u*)BN_NUMBER(g); + cpSize nsXmax = BN_ROOM(x)*(sizeof(BNU_CHUNK_T)/sizeof(Ipp32u)); + cpSize nsYmax = BN_ROOM(y)*(sizeof(BNU_CHUNK_T)/sizeof(Ipp32u)); + cpSize nsGmax = BN_ROOM(g)*(sizeof(BNU_CHUNK_T)/sizeof(Ipp32u)); + cpSize nsX = BN_SIZE(x)*(sizeof(BNU_CHUNK_T)/sizeof(Ipp32u)); + cpSize nsY = BN_SIZE(y)*(sizeof(BNU_CHUNK_T)/sizeof(Ipp32u)); + + Ipp32u* T; + Ipp32u* u; + + FIX_BNU(xData, nsX); + FIX_BNU(yData, nsY); + + /* init buffers */ + ZEXPAND_COPY_BNU(xBuffer, nsX, xData, nsXmax); + ZEXPAND_COPY_BNU(yBuffer, nsY, yData, nsYmax); + + T = gBuffer; + u = gData; + ZEXPAND_BNU(T, 0, nsGmax); + ZEXPAND_BNU(u, 0, nsGmax); + + while(nsX > (cpSize)(sizeof(BNU_CHUNK_T)/sizeof(Ipp32u))) { + /* xx and yy is the high-order digits of x and y (yy could be 0) */ + + Ipp64u xx = (Ipp64u)(xBuffer[nsX-1]); + Ipp64u yy = (nsY < nsX)? 0 : (Ipp64u)(yBuffer[nsY-1]); + + Ipp64s AA = 1; + Ipp64s BB = 0; + Ipp64s CC = 0; + Ipp64s DD = 1; + Ipp64s t; + + while((yy+CC)!=0 && (yy+DD)!=0) { + Ipp64u q = ( xx + AA ) / ( yy + CC ); + Ipp64u q1 = ( xx + BB ) / ( yy + DD ); + if(q!=q1) + break; + t = AA - q*CC; + AA = CC; + CC = t; + t = BB - q*DD; + BB = DD; + DD = t; + t = xx - q*yy; + xx = yy; + yy = t; + } + + if(BB == 0) { + /* T = x mod y */ + cpSize nsT = cpMod_BNU32(xBuffer, nsX, yBuffer, nsY); + ZEXPAND_BNU(T, 0, nsGmax); + COPY_BNU(T, xBuffer, nsT); + /* a = b; b = T; */ + ZEXPAND_BNU(xBuffer, 0, nsXmax); + COPY_BNU(xBuffer, yBuffer, nsY); + ZEXPAND_BNU(yBuffer, 0, nsYmax); + COPY_BNU(yBuffer, T, nsY); + } + + else { + Ipp32u carry; + /* + // T = AA*x + BB*y; + // u = CC*x + DD*y; + // b = u; a = T; + */ + if((AA <= 0)&&(BB>=0)) { + Ipp32u a1 = (Ipp32u)(-AA); + carry = cpMulDgt_BNU32(T, yBuffer, nsY, (Ipp32u)BB); + carry = cpMulDgt_BNU32(u, xBuffer, nsY, a1); + /* T = BB*y - AA*x; */ + carry = cpSub_BNU32(T, T, u, nsY); + } + else { + if((AA >= 0)&&(BB<=0)) { + Ipp32u b1 = (Ipp32u)(-BB); + carry = cpMulDgt_BNU32(T, xBuffer, nsY, (Ipp32u)AA); + carry = cpMulDgt_BNU32(u, yBuffer, nsY, b1); + /* T = AA*x - BB*y; */ + carry = cpSub_BNU32(T, T, u, nsY); + } + else { + /*AA*BB>=0 */ + carry = cpMulDgt_BNU32(T, xBuffer, nsY, (Ipp32u)AA); + carry = cpMulDgt_BNU32(u, yBuffer, nsY, (Ipp32u)BB); + /* T = AA*x + BB*y; */ + carry = cpAdd_BNU32(T, T, u, nsY); + } + } + + /* Now T is reserved. We use only u for intermediate results. */ + if((CC <= 0)&&(DD>=0)){ + Ipp32u c1 = (Ipp32u)(-CC); + /* u = x*CC; x = u; */ + carry = cpMulDgt_BNU32(u, xBuffer, nsY, c1); + COPY_BNU(xBuffer, u, nsY); + /* u = y*DD; */ + carry = cpMulDgt_BNU32(u, yBuffer, nsY, (Ipp32u)DD); + /* u = DD*y - CC*x; */ + carry = cpSub_BNU32(u, u, xBuffer, nsY); + } + else { + if((CC >= 0)&&(DD<=0)){ + Ipp32u d1 = (Ipp32u)(-DD); + /* u = y*DD; y = u */ + carry = cpMulDgt_BNU32(u, yBuffer, nsY, d1); + COPY_BNU(yBuffer, u, nsY); + /* u = CC*x; */ + carry = cpMulDgt_BNU32(u, xBuffer, nsY, (Ipp32u)CC); + /* u = CC*x - DD*y; */ + carry = cpSub_BNU32(u, u, yBuffer, nsY); + } + else { + /*CC*DD>=0 */ + /* y = y*DD */ + carry = cpMulDgt_BNU32(u, yBuffer, nsY, (Ipp32u)DD); + COPY_BNU(yBuffer, u, nsY); + /* u = x*CC */ + carry = cpMulDgt_BNU32(u, xBuffer, nsY, (Ipp32u)CC); + /* u = x*CC + y*DD */ + carry = cpAdd_BNU32(u, u, yBuffer, nsY); + } + } + + /* y = u; x = T; */ + COPY_BNU(yBuffer, u, nsY); + COPY_BNU(xBuffer, T, nsY); + } + + FIX_BNU(xBuffer, nsX); + FIX_BNU(yBuffer, nsY); + + if (nsY > nsX) { + SWAP_PTR(IppsBigNumState, x, y); + SWAP(nsX, nsY); + } + + if (nsY==1 && yBuffer[nsY-1]==0) { + /* End evaluation */ + ZEXPAND_BNU(gData, 0, nsGmax); + COPY_BNU(gData, xBuffer, nsX); + BN_SIZE(g) = INTERNAL_BNU_LENGTH(nsX); + BN_SIGN(g) = ippBigNumPOS; + return ippStsNoErr; + } + } + + BN_NUMBER(g)[0] = cpGcd_BNU(((BNU_CHUNK_T*)xBuffer)[0], ((BNU_CHUNK_T*)yBuffer)[0]); + BN_SIZE(g) = 1; + BN_SIGN(g) = ippBigNumPOS; + return ippStsNoErr; + } + } +} + + +/*F* +// Name: ippsModInv_BN +// +// Purpose: Multiplicative Inversion BigNum. +// +// Returns: Reason: +// ippStsNullPtrErr pA == NULL +// pM == NULL +// pR == NULL +// ippStsContextMatchErr BN_VALID_ID(pA) +// BN_VALID_ID(pM) +// BN_VALID_ID(pR) +// ippStsBadArgErr A<=0 +// ippStsBadModulusErr M<=0 +// ippStsScaleRangeErr A>=M +// ippStsOutOfRangeErr pR can not hold result +// ippStsNoErr no errors +// ippStsBadModulusErr inversion not found +// +// Parameters: +// pA source (value) BigNum +// pM source (modulus) BigNum +// pR reminder BigNum +// +*F*/ +IPPFUN(IppStatus, ippsModInv_BN, (IppsBigNumState* pA, IppsBigNumState* pM, IppsBigNumState* pR) ) +{ + IPP_BAD_PTR3_RET(pA, pM, pR); + + pA = (IppsBigNumState*)( IPP_ALIGNED_PTR(pA, BN_ALIGNMENT) ); + IPP_BADARG_RET(!BN_VALID_ID(pA), ippStsContextMatchErr); + pM = (IppsBigNumState*)( IPP_ALIGNED_PTR(pM, BN_ALIGNMENT) ); + IPP_BADARG_RET(!BN_VALID_ID(pM), ippStsContextMatchErr); + pR = (IppsBigNumState*)( IPP_ALIGNED_PTR(pR, BN_ALIGNMENT) ); + IPP_BADARG_RET(!BN_VALID_ID(pR), ippStsContextMatchErr); + + IPP_BADARG_RET(BN_ROOM(pR) < BN_SIZE(pM), ippStsOutOfRangeErr); + IPP_BADARG_RET(BN_NEGATIVE(pA) || (BN_SIZE(pA)==1 && BN_NUMBER(pA)[0]==0), ippStsBadArgErr); + IPP_BADARG_RET(BN_NEGATIVE(pM) || (BN_SIZE(pM)==1 && BN_NUMBER(pM)[0]==0), ippStsBadModulusErr); + IPP_BADARG_RET(cpCmp_BNU(BN_NUMBER(pA), BN_SIZE(pA), BN_NUMBER(pM), BN_SIZE(pM)) >= 0, ippStsScaleRangeErr); + + { + cpSize nsR = cpModInv_BNU(BN_NUMBER(pR), + BN_NUMBER(pA), BN_SIZE(pA), + BN_NUMBER(pM), BN_SIZE(pM), + BN_BUFFER(pR), BN_BUFFER(pA), BN_BUFFER(pM)); + if(nsR) { + BN_SIGN(pR) = ippBigNumPOS; + BN_SIZE(pR) = nsR; + return ippStsNoErr; + } + else + return ippStsBadModulusErr; + } +} diff --git a/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpbnresource.h b/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpbnresource.h new file mode 100644 index 0000000000..0358aaed4e --- /dev/null +++ b/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpbnresource.h @@ -0,0 +1,51 @@ +/* +* Copyright (C) 2016 Intel Corporation. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in +* the documentation and/or other materials provided with the +* distribution. +* * Neither the name of Intel Corporation nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ + +#if !defined(_PCP_BNRESOURCE_H) +#define _PCP_BNRESOURCE_H + + +typedef struct { + void* pNext; + IppsBigNumState* pBN; +} BigNumNode; + + +/* size (byte) of BN resource */ +int cpBigNumListGetSize(int feBitSize, int nodes); + +/* init BN resource */ +void cpBigNumListInit(int feBitSize, int nodes, BigNumNode* pList); + +/* get BN from resource */ +IppsBigNumState* cpBigNumListGet(BigNumNode** pList); + +#endif /* _PCP_BNRESOURCE_H */ diff --git a/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpbnresourceca.c b/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpbnresourceca.c new file mode 100644 index 0000000000..63bdd6737f --- /dev/null +++ b/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpbnresourceca.c @@ -0,0 +1,93 @@ +/* +* Copyright (C) 2016 Intel Corporation. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in +* the documentation and/or other materials provided with the +* distribution. +* * Neither the name of Intel Corporation nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ + +#include "owndefs.h" +#include "owncp.h" +#include "pcpbnresource.h" +#include "pcpbn.h" + +/* +// Size of BigNum List Buffer +*/ +int cpBigNumListGetSize(int feBitSize, int nodes) +{ + /* size of buffer per single big number */ + int bnSize; + ippsBigNumGetSize(BITS2WORD32_SIZE(feBitSize), &bnSize); + + /* size of buffer for whole list */ + return (ALIGN_VAL-1) + (sizeof(BigNumNode) + bnSize) * nodes; +} + +/* +// Init list +// +// Note: buffer for BN list must have appropriate alignment +*/ +void cpBigNumListInit(int feBitSize, int nodes, BigNumNode* pList) +{ + int itemSize; + /* length of Big Num */ + int bnLen = BITS2WORD32_SIZE(feBitSize); + /* size of buffer per single big number */ + ippsBigNumGetSize(bnLen, &itemSize); + /* size of list item */ + itemSize += sizeof(BigNumNode); + + { + int n; + /* init all nodes */ + BigNumNode* pNode = (BigNumNode*)( (Ipp8u*)pList + (nodes-1)*itemSize ); + BigNumNode* pNext = NULL; + for(n=0; npNext = pNext; + pNode->pBN = (IppsBigNumState*)( IPP_ALIGNED_PTR(tbnPtr, ALIGN_VAL) ); + ippsBigNumInit(bnLen, pNode->pBN); + pNext = pNode; + pNode = (BigNumNode*)( (Ipp8u*)pNode - itemSize); + } + } +} + +/* +// Get BigNum reference +*/ +IppsBigNumState* cpBigNumListGet(BigNumNode** ppList) +{ + if(*ppList) { + IppsBigNumState* ret = (*ppList)->pBN; + *ppList = (BigNumNode*)((*ppList)->pNext); + return ret; + } + else + return NULL; +} diff --git a/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpbnsetca.c b/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpbnsetca.c new file mode 100644 index 0000000000..728ec45c8d --- /dev/null +++ b/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpbnsetca.c @@ -0,0 +1,119 @@ +/* +* Copyright (C) 2016 Intel Corporation. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in +* the documentation and/or other materials provided with the +* distribution. +* * Neither the name of Intel Corporation nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ + +#include "owndefs.h" +#include "owncp.h" +#include "pcpbn.h" + + +/*F* +// Name: ippsSetOctString_BN +// +// Purpose: Convert octet string into the BN value. +// +// Returns: Reason: +// ippStsNullPtrErr NULL == pOctStr +// NULL == pBN +// +// ippStsLengthErr 0>strLen +// +// ippStsSizeErr BN_ROOM() is enough for keep actual strLen +// +// ippStsNoErr no errors +// +// Parameters: +// pOctStr pointer to the source octet string +// strLen octet string length +// pBN pointer to the target BN +// +*F*/ +IPPFUN(IppStatus, ippsSetOctString_BN,(const Ipp8u* pOctStr, cpSize strLen, + IppsBigNumState* pBN)) +{ + IPP_BAD_PTR2_RET(pOctStr, pBN); + + pBN = (IppsBigNumState*)( IPP_ALIGNED_PTR(pBN, BN_ALIGNMENT) ); + IPP_BADARG_RET(!BN_VALID_ID(pBN), ippStsContextMatchErr); + + IPP_BADARG_RET((0>strLen), ippStsLengthErr); + + /* remove leading zeros */ + while(strLen && (0==pOctStr[0])) { + strLen--; + pOctStr++; + } + + /* test BN size */ + IPP_BADARG_RET((int)(sizeof(BNU_CHUNK_T)*BN_ROOM(pBN))strLen), ippStsLengthErr); + + return cpToOctStr_BNU(pOctStr,strLen, BN_NUMBER(pBN),BN_SIZE(pBN))? ippStsNoErr : ippStsLengthErr; +} diff --git a/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpbnu32arith.c b/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpbnu32arith.c new file mode 100644 index 0000000000..79779fd27c --- /dev/null +++ b/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpbnu32arith.c @@ -0,0 +1,234 @@ +/* +* Copyright (C) 2016 Intel Corporation. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in +* the documentation and/or other materials provided with the +* distribution. +* * Neither the name of Intel Corporation nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ + +#include "owncp.h" +#include "pcpbnumisc.h" +#include "pcpbnu32misc.h" +#include "pcpbnu32arith.h" + + +/* +// BNU32 addition +*/ +Ipp32u cpAdd_BNU32(Ipp32u* pR, const Ipp32u* pA, const Ipp32u* pB, cpSize ns) +{ + Ipp32u carry = 0; + cpSize i; + for(i=0; i>(32-1); + } + return borrow; +} + +/* +// BNU32 mul_by_digit +*/ +Ipp32u cpMulDgt_BNU32(Ipp32u* pR, const Ipp32u* pA, cpSize nsA, Ipp32u val) +{ + Ipp32u carry = 0; + cpSize i; + for(i=0; i0; nsA--) { + Ipp64u r = (Ipp64u)*pR - (Ipp64u)(*pA++) * val - carry; + *pR++ = LODWORD(r); + carry = 0-HIDWORD(r); + } + return carry; +} + +/* +// BNU32 division +*/ +int cpDiv_BNU32(Ipp32u* pQ, cpSize* sizeQ, + Ipp32u* pX, cpSize sizeX, + Ipp32u* pY, cpSize sizeY) +{ + FIX_BNU(pY,sizeY); + FIX_BNU(pX,sizeX); + + /* special case */ + if(sizeX < sizeY) { + + if(pQ) { + pQ[0] = 0; + *sizeQ = 1; + } + + return sizeX; + } + + /* special case */ + if(1 == sizeY) { + int i; + Ipp32u r = 0; + for(i=(int)sizeX-1; i>=0; i--) { + Ipp64u tmp = MAKEDWORD(pX[i],r); + Ipp32u q = LODWORD(tmp / pY[0]); + r = LODWORD(tmp - q*pY[0]); + if(pQ) pQ[i] = q; + } + + pX[0] = r; + + if(pQ) { + FIX_BNU(pQ,sizeX); + *sizeQ = sizeX; + } + + return 1; + } + + + /* common case */ + { + cpSize qs = sizeX-sizeY+1; + + cpSize nlz = cpNLZ_BNU32(pY[sizeY-1]); + + /* normalization */ + pX[sizeX] = 0; + if(nlz) { + cpSize ni; + + pX[sizeX] = pX[sizeX-1] >> (32-nlz); + for(ni=sizeX-1; ni>0; ni--) + pX[ni] = (pX[ni]<>(32-nlz)); + pX[0] <<= nlz; + + for(ni=sizeY-1; ni>0; ni--) + pY[ni] = (pY[ni]<>(32-nlz)); + pY[0] <<= nlz; + } + + /* + // division + */ + { + Ipp32u yHi = pY[sizeY-1]; + + int i; + for(i=(int)qs-1; i>=0; i--) { + Ipp32u extend; + + /* estimate digit of quotient */ + Ipp64u tmp = MAKEDWORD(pX[i+sizeY-1], pX[i+sizeY]); + Ipp64u q = tmp / yHi; + Ipp64u r = tmp - q*yHi; + + /* tune estimation above */ + for(; HIDWORD(q) || (Ipp64u)q*pY[sizeY-2] > MAKEDWORD(pX[i+sizeY-2],r); ) { + q -= 1; + r += yHi; + if( HIDWORD(r) ) + break; + } + + /* multiply and subtract */ + extend = cpSubMulDgt_BNU32(pX+i, pY, sizeY, (Ipp32u)q); + extend = (pX[i+sizeY] -= extend); + + if(extend) { /* subtracted too much */ + q -= 1; + extend = cpAdd_BNU32(pX+i, pY, pX+i, sizeY); + pX[i+sizeY] += extend; + } + + /* store quotation digit */ + if(pQ) pQ[i] = LODWORD(q); + } + } + + /* de-normalization */ + if(nlz) { + cpSize ni; + for(ni=0; ni>nlz) | (pX[ni+1]<<(32-nlz)); + for(ni=0; ni>nlz) | (pY[ni+1]<<(32-nlz)); + pY[sizeY-1] >>= nlz; + } + + FIX_BNU(pX,sizeX); + + if(pQ) { + FIX_BNU(pQ,qs); + *sizeQ = qs; + } + + return sizeX; + } +} diff --git a/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpbnu32arith.h b/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpbnu32arith.h new file mode 100644 index 0000000000..96cfe24231 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpbnu32arith.h @@ -0,0 +1,46 @@ +/* +* Copyright (C) 2016 Intel Corporation. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in +* the documentation and/or other materials provided with the +* distribution. +* * Neither the name of Intel Corporation nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ + +#if !defined(_CP_BNU32_ARITH_H) +#define _CP_BNU32_ARITH_H + +Ipp32u cpAdd_BNU32(Ipp32u* pR, const Ipp32u* pA, const Ipp32u* pB, int ns); +Ipp32u cpSub_BNU32(Ipp32u* pR, const Ipp32u* pA, const Ipp32u* pB, int ns); +Ipp32u cpInc_BNU32(Ipp32u* pR, const Ipp32u* pA, cpSize ns, Ipp32u val); +Ipp32u cpDec_BNU32(Ipp32u* pR, const Ipp32u* pA, cpSize ns, Ipp32u val); + +Ipp32u cpMulDgt_BNU32(Ipp32u* pR, const Ipp32u* pA, int ns, Ipp32u val); +Ipp32u cpSubMulDgt_BNU32(Ipp32u* pR, const Ipp32u* pA, int nsA, Ipp32u val); + +int cpDiv_BNU32(Ipp32u* pQ, int* nsQ, Ipp32u* pX, int nsX, Ipp32u* pY, int nsY); +#define cpMod_BNU32(pX,sizeX, pM,sizeM) cpDiv_BNU32(NULL,NULL, (pX),(sizeX), (pM),(sizeM)) + +#endif /* _CP_BNU32_ARITH_H */ diff --git a/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpbnu32misc.c b/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpbnu32misc.c new file mode 100644 index 0000000000..6680a497d7 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpbnu32misc.c @@ -0,0 +1,53 @@ +/* +* Copyright (C) 2016 Intel Corporation. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in +* the documentation and/or other materials provided with the +* distribution. +* * Neither the name of Intel Corporation nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ + +#include "owncp.h" +#include "pcpbnuimpl.h" +#include "pcpbnumisc.h" +#include "pcpbnu32misc.h" + + +/* +// number of leading zeros +*/ +cpSize cpNLZ_BNU32(Ipp32u x) +{ + cpSize nlz = BITSIZE(Ipp32u); + if(x) { + nlz = 0; + if( 0==(x & 0xFFFF0000) ) { nlz +=16; x<<=16; } + if( 0==(x & 0xFF000000) ) { nlz += 8; x<<= 8; } + if( 0==(x & 0xF0000000) ) { nlz += 4; x<<= 4; } + if( 0==(x & 0xC0000000) ) { nlz += 2; x<<= 2; } + if( 0==(x & 0x80000000) ) { nlz++; } + } + return nlz; +} diff --git a/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpbnu32misc.h b/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpbnu32misc.h new file mode 100644 index 0000000000..cda2eca224 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpbnu32misc.h @@ -0,0 +1,49 @@ +/* +* Copyright (C) 2016 Intel Corporation. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in +* the documentation and/or other materials provided with the +* distribution. +* * Neither the name of Intel Corporation nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ + +#if !defined(_CP_BNU32_MISC_H) +#define _CP_BNU32_MISC_H + + +/* bit operations */ +#define BITSIZE_BNU32(p,ns) ((ns)*BNU_CHUNK_32BIT-cpNLZ_BNU32((p)[(ns)-1])) + +/* number of leading/trailing zeros */ +cpSize cpNLZ_BNU32(Ipp32u x); + +/* most significant BNU bit */ +__INLINE int cpMSBit_BNU32(const Ipp32u* pA, cpSize nsA) +{ + FIX_BNU(pA, nsA); + return nsA*BITSIZE(Ipp32u) - cpNLZ_BNU32(pA[nsA-1]) -1; +} + +#endif /* _CP_BNU32_MISC_H */ diff --git a/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpbnuarith.c b/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpbnuarith.c new file mode 100644 index 0000000000..93822f3f67 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpbnuarith.c @@ -0,0 +1,301 @@ +/* +* Copyright (C) 2016 Intel Corporation. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in +* the documentation and/or other materials provided with the +* distribution. +* * Neither the name of Intel Corporation nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ + +#include "owncp.h" +#include "pcpbnuarith.h" +#include "pcpbnumisc.h" + + +/* Function cpAdd_BNU - addition of 2 BigNumbers */ +BNU_CHUNK_T cpAdd_BNU(BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, const BNU_CHUNK_T* pB, cpSize ns) +{ + BNU_CHUNK_T carry = 0; + cpSize i; + for(i=0; i b){ + gcd = a; + t = b; + } else { + t = a; + gcd = b; + } + + while (t != 0) { + r = gcd % t; + gcd = t; + t = r; + } + return gcd; +} + + +/* +// cpMAC_BNU +// +// Multiply with ACcumulation +// Computes r <- r + a * b, returns real size of the r in the size_r variable +// Returns 0 if there are no enought buffer size to write to r[MAX(size_r + 1, size_a + size_b) - 1] +// Returns 1 if no error +// +// Note: +// DO NOT run in inplace mode +// The minimum buffer size for the r must be (size_a + size_b - 1) +// the maximum buffer size for the r is MAX(size_r + 1, size_a + size_b) +*/ +static int cpMac_BNU(BNU_CHUNK_T* pR, cpSize nsR, + const BNU_CHUNK_T* pA, cpSize nsA, + const BNU_CHUNK_T* pB, cpSize nsB) +{ + /* cleanup the rest of destination buffer */ + ZEXPAND_BNU(pR, nsR, nsA+nsB-1); + + { + BNU_CHUNK_T expansion = 0; + cpSize i; + for(i=0; i> (BNU_CHUNK_BITS/2)) + +/* (carry,R) = A+B */ +#define ADD_AB(CARRY,R, A,B) \ +do { \ + BNU_CHUNK_T __s = (A) + (B); \ + (CARRY) = __s < (A); \ + (R) = __s; \ +} while(0) + +/* (carry,R) = A+B+C */ +#define ADD_ABC(CARRY,R, A,B,C) \ +do { \ + BNU_CHUNK_T __s = (A) + (B); \ + BNU_CHUNK_T __t1= __s < (A); \ + BNU_CHUNK_T __r = __s + (C); \ + BNU_CHUNK_T __t2 = __r < __s; \ + (CARRY) = __t1 + __t2; \ + (R) = __r; \ +} while(0) + +/* (borrow,R) = A-B */ +#define SUB_AB(BORROW,R, A,B) \ +do { \ + (BORROW) = (A)<(B); \ + (R) = (A)-(B); \ +} while(0) + +/* (borrow,R) = A-B-C */ +#define SUB_ABC(BORROW,R, A,B,C) \ +do { \ + BNU_CHUNK_T __s = (A) -( B); \ + BNU_CHUNK_T __t1= __s > (A); \ + BNU_CHUNK_T __r = __s - (C); \ + BNU_CHUNK_T __t2 = __r > __s; \ + (BORROW) = __t1 + __t2; \ + (R) = __r; \ +} while(0) + +/* (RH,RL) = A*B */ +#define MUL_AB(RH, RL, A, B) \ + do { \ + BNU_CHUNK_T __aL = LO_CHUNK((A)); \ + BNU_CHUNK_T __aH = HI_CHUNK((A)); \ + BNU_CHUNK_T __bL = LO_CHUNK((B)); \ + BNU_CHUNK_T __bH = HI_CHUNK((B)); \ + \ + BNU_CHUNK_T __x0 = (BNU_CHUNK_T) __aL * __bL; \ + BNU_CHUNK_T __x1 = (BNU_CHUNK_T) __aL * __bH; \ + BNU_CHUNK_T __x2 = (BNU_CHUNK_T) __aH * __bL; \ + BNU_CHUNK_T __x3 = (BNU_CHUNK_T) __aH * __bH; \ + \ + __x1 += HI_CHUNK(__x0); \ + __x1 += __x2; \ + if(__x1 < __x2) \ + __x3 += BNU_CHUNK_2H; \ + \ + (RH) = __x3 + HI_CHUNK(__x1); \ + (RL) = (__x1 << BNU_CHUNK_BITS/2) + LO_CHUNK(__x0); \ + } while (0) + +#endif /* _CP_BNU_IMPL_H */ diff --git a/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpbnumisc.c b/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpbnumisc.c new file mode 100644 index 0000000000..3b0bb839fc --- /dev/null +++ b/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpbnumisc.c @@ -0,0 +1,208 @@ +/* +* Copyright (C) 2016 Intel Corporation. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in +* the documentation and/or other materials provided with the +* distribution. +* * Neither the name of Intel Corporation nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ + +#include "owncp.h" +#include "pcpbnumisc.h" + + +/* +// number of leading zeros +*/ +cpSize cpNLZ_BNU(BNU_CHUNK_T x) +{ + cpSize nlz = BNU_CHUNK_BITS; + if(x) { + nlz = 0; + #if (BNU_CHUNK_BITS == BNU_CHUNK_64BIT) + if( 0==(x & 0xFFFFFFFF00000000) ) { nlz +=32; x<<=32; } + if( 0==(x & 0xFFFF000000000000) ) { nlz +=16; x<<=16; } + if( 0==(x & 0xFF00000000000000) ) { nlz += 8; x<<= 8; } + if( 0==(x & 0xF000000000000000) ) { nlz += 4; x<<= 4; } + if( 0==(x & 0xC000000000000000) ) { nlz += 2; x<<= 2; } + if( 0==(x & 0x8000000000000000) ) { nlz++; } + #else + if( 0==(x & 0xFFFF0000) ) { nlz +=16; x<<=16; } + if( 0==(x & 0xFF000000) ) { nlz += 8; x<<= 8; } + if( 0==(x & 0xF0000000) ) { nlz += 4; x<<= 4; } + if( 0==(x & 0xC0000000) ) { nlz += 2; x<<= 2; } + if( 0==(x & 0x80000000) ) { nlz++; } + #endif + } + return nlz; +} + +/* +// number of trailing zeros +*/ +cpSize cpNTZ_BNU(BNU_CHUNK_T x) +{ + cpSize ntz = BNU_CHUNK_BITS; + if(x) { + ntz = 0; + #if (BNU_CHUNK_BITS==BNU_CHUNK_64BIT) + if( 0==(x & 0x00000000FFFFFFFF) ) { ntz+=32; x>>=32; } + if( 0==(x & 0x000000000000FFFF) ) { ntz+=16; x>>=16; } + if( 0==(x & 0x00000000000000FF) ) { ntz+= 8; x>>= 8; } + if( 0==(x & 0x000000000000000F) ) { ntz+= 4; x>>= 4; } + if( 0==(x & 0x0000000000000003) ) { ntz+= 2; x>>= 2; } + if( 0==(x & 0x0000000000000001) ) { ntz++; } + #else + if( 0==(x & 0x0000FFFF) ) { ntz+=16; x>>=16; } + if( 0==(x & 0x000000FF) ) { ntz+= 8; x>>= 8; } + if( 0==(x & 0x0000000F) ) { ntz+= 4; x>>= 4; } + if( 0==(x & 0x00000003) ) { ntz+= 2; x>>= 2; } + if( 0==(x & 0x00000001) ) { ntz++; } + #endif + } + return ntz; +} + + +/* +// Logical shift right (including inplace) +// +// Returns new length +// +*/ +cpSize cpLSR_BNU(BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, cpSize nsA, cpSize nBits) +{ + cpSize nw = nBits/BNU_CHUNK_BITS; + cpSize n; + + pA += nw; + nsA -= nw; + + nBits %= BNU_CHUNK_BITS; + if(nBits) { + BNU_CHUNK_T hi; + BNU_CHUNK_T lo = pA[0]; + + for(n=0; n<(nsA-1); n++) { + hi = pA[n+1]; + pR[n] = (lo>>nBits) | (hi<<(BNU_CHUNK_BITS-nBits)); + lo = hi; + } + pR[nsA-1] = (lo>>nBits); + } + else { + for(n=0; n=(int)sizeof(BNU_CHUNK_T); nsA++,strLen-=(int)(sizeof(BNU_CHUNK_T))) { + /* pack sizeof(BNU_CHUNK_T) bytes into single BNU_CHUNK_T value*/ + *pA++ = + #if (BNU_CHUNK_BITS==BNU_CHUNK_64BIT) + +( (BNU_CHUNK_T)pStr[strLen-8]<<(8*7) ) + +( (BNU_CHUNK_T)pStr[strLen-7]<<(8*6) ) + +( (BNU_CHUNK_T)pStr[strLen-6]<<(8*5) ) + +( (BNU_CHUNK_T)pStr[strLen-5]<<(8*4) ) + #endif + +( (BNU_CHUNK_T)pStr[strLen-4]<<(8*3) ) + +( (BNU_CHUNK_T)pStr[strLen-3]<<(8*2) ) + +( (BNU_CHUNK_T)pStr[strLen-2]<<(8*1) ) + + (BNU_CHUNK_T)pStr[strLen-1]; + } + + /* convert the beginning of the string */ + if(strLen) { + BNU_CHUNK_T x = 0; + for(x=0; strLen>0; strLen--) { + BNU_CHUNK_T d = *pStr++; + x = (x<<8) + d; + } + *pA++ = x; + nsA++; + } + + return nsA; +} + +/* +// Convert BNU into HexString representation +// +// Returns length of the string or 0 if no success +*/ +cpSize cpToOctStr_BNU(Ipp8u* pStr, cpSize strLen, const BNU_CHUNK_T* pA, cpSize nsA) +{ + FIX_BNU(pA, nsA); + { + cpSize bnuBitSize = BITSIZE_BNU(pA, nsA); + if(bnuBitSize <= strLen*BYTESIZE) { + int cnvLen = 0; + BNU_CHUNK_T x = pA[nsA-1]; + + ZEXPAND_BNU(pStr, 0, strLen); + pStr += strLen - BITS2WORD8_SIZE(bnuBitSize); + + if(x) { + //int nb; + cpSize nb; + for(nb=cpNLZ_BNU(x)/BYTESIZE; nb<(cpSize)(sizeof(BNU_CHUNK_T)); cnvLen++, nb++) + *pStr++ = EBYTE(x, sizeof(BNU_CHUNK_T)-1-nb); + + for(--nsA; nsA>0; cnvLen+=sizeof(BNU_CHUNK_T), nsA--) { + x = pA[nsA-1]; + #if (BNU_CHUNK_BITS==BNU_CHUNK_64BIT) + *pStr++ = EBYTE(x,7); + *pStr++ = EBYTE(x,6); + *pStr++ = EBYTE(x,5); + *pStr++ = EBYTE(x,4); + #endif + *pStr++ = EBYTE(x,3); + *pStr++ = EBYTE(x,2); + *pStr++ = EBYTE(x,1); + *pStr++ = EBYTE(x,0); + } + } + return strLen; + } + else + return 0; + } +} diff --git a/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpbnumisc.h b/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpbnumisc.h new file mode 100644 index 0000000000..cbb8d60dbc --- /dev/null +++ b/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpbnumisc.h @@ -0,0 +1,149 @@ +/* +* Copyright (C) 2016 Intel Corporation. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in +* the documentation and/or other materials provided with the +* distribution. +* * Neither the name of Intel Corporation nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ + +#if !defined(_PCP_BNUMISC_H) +#define _PCP_BNUMISC_H + +#include "pcpbnuimpl.h" + + +/* bit operations */ +#define BITSIZE_BNU(p,ns) ((ns)*BNU_CHUNK_BITS-cpNLZ_BNU((p)[(ns)-1])) +#define BIT_BNU(bnu, ns,nbit) ((((nbit)>>BNU_CHUNK_LOG2) < (ns))? ((((bnu))[(nbit)>>BNU_CHUNK_LOG2] >>((nbit)&(BNU_CHUNK_BITS))) &1) : 0) +#define TST_BIT(bnu, nbit) ((((bnu))[(nbit)>>BNU_CHUNK_LOG2]) & ((BNU_CHUNK_T)1<<((nbit)&(BNU_CHUNK_BITS-1)))) +#define SET_BIT(bnu, nbit) ((((bnu))[(nbit)>>BNU_CHUNK_LOG2]) |= ((BNU_CHUNK_T)1<<((nbit)&(BNU_CHUNK_BITS-1)))) +#define CLR_BIT(bnu, nbit) ((((bnu))[(nbit)>>BNU_CHUNK_LOG2]) &=~((BNU_CHUNK_T)1<<((nbit)&(BNU_CHUNK_BITS-1)))) + +/* convert bitsize nbits into the number of BNU_CHUNK_T */ +#define BITS_BNU_CHUNK(nbits) (((nbits)+BNU_CHUNK_BITS-1)/BNU_CHUNK_BITS) + +/* mask for top BNU_CHUNK_T */ +#define MASK_BNU_CHUNK(nbits) ((BNU_CHUNK_T)(-1) >>((BNU_CHUNK_BITS- ((nbits)&(BNU_CHUNK_BITS-1))) &(BNU_CHUNK_BITS-1))) + +/* copy BNU content */ +#define COPY_BNU(dst, src, len) \ +{ \ + cpSize __idx; \ + for(__idx=0; __idx<(len); __idx++) (dst)[__idx] = (src)[__idx]; \ +} + +/* expand by zeros */ +#define ZEXPAND_BNU(srcdst,srcLen, dstLen) \ +{ \ + cpSize __idx; \ + for(__idx=(srcLen); __idx<(dstLen); __idx++) (srcdst)[__idx] = 0; \ +} + +/* copy and expand by zeros */ +#define ZEXPAND_COPY_BNU(dst,dstLen, src,srcLen) \ +{ \ + cpSize __idx; \ + for(__idx=0; __idx<(srcLen); __idx++) (dst)[__idx] = (src)[__idx]; \ + for(; __idx<(dstLen); __idx++) (dst)[__idx] = 0; \ +} + +/* fix actual length */ +#define FIX_BNU(src,srcLen) \ + for(; ((srcLen)>1) && (0==(src)[(srcLen)-1]); (srcLen)--) + + +/* copy and set */ +__INLINE void cpCpy_BNU(BNU_CHUNK_T* pDst, const BNU_CHUNK_T* pSrc, cpSize ns) +{ COPY_BNU(pDst, pSrc, ns); } + +__INLINE void cpSet_BNU(BNU_CHUNK_T* pDst, cpSize ns, BNU_CHUNK_T val) +{ + ZEXPAND_BNU(pDst, 0, ns); + pDst[0] = val; +} + +/* fix up */ +__INLINE int cpFix_BNU(const BNU_CHUNK_T* pA, int nsA) +{ + FIX_BNU(pA, nsA); + return nsA; +} + +/* comparison +// +// returns +// negative, if A < B +// 0, if A = B +// positive, if A > B +*/ +__INLINE int cpCmp_BNU(const BNU_CHUNK_T* pA, cpSize nsA, const BNU_CHUNK_T* pB, cpSize nsB) +{ + if(nsA!=nsB) + return nsA>nsB? 1 : -1; + else { + for(; nsA>0; nsA--) { + if(pA[nsA-1] > pB[nsA-1]) + return 1; + else if(pA[nsA-1] < pB[nsA-1]) + return -1; + } + return 0; + } +} +__INLINE int cpEqu_BNU_CHUNK(const BNU_CHUNK_T* pA, cpSize nsA, BNU_CHUNK_T b) +{ + return (pA[0]==b && 1==cpFix_BNU(pA, nsA)); +} + +/* +// test +// +// returns +// 0, if A = 0 +// >0, if A > 0 +// <0, looks like impossible (or error) case +*/ +__INLINE int cpTst_BNU(const BNU_CHUNK_T* pA, int nsA) +{ + for(; (nsA>0) && (0==pA[nsA-1]); nsA--) ; + return nsA; +} + +/* number of leading/trailing zeros */ +cpSize cpNLZ_BNU(BNU_CHUNK_T x); +cpSize cpNTZ_BNU(BNU_CHUNK_T x); + +/* logical shift left/right */ +int cpLSR_BNU(BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, cpSize nsA, cpSize nBits); + +/* least and most significant BNU bit */ +int cpMSBit_BNU(const BNU_CHUNK_T* pA, cpSize nsA); + +/* BNU <-> hex-string conversion */ +int cpToOctStr_BNU(Ipp8u* pStr, cpSize strLen, const BNU_CHUNK_T* pA, cpSize nsA); +int cpFromOctStr_BNU(BNU_CHUNK_T* pA, const Ipp8u* pStr, cpSize strLen); + +#endif /* _PCP_BNUMISC_H */ diff --git a/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpcmac.h b/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpcmac.h new file mode 100644 index 0000000000..47eee76e9c --- /dev/null +++ b/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpcmac.h @@ -0,0 +1,70 @@ +/* +* Copyright (C) 2016 Intel Corporation. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in +* the documentation and/or other materials provided with the +* distribution. +* * Neither the name of Intel Corporation nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ + +#if !defined(_PCP_CMAC_H) +#define _PCP_CMAC_H + +#include "pcprij.h" + + +/* +// Rijndael128 based CMAC context +*/ +struct _cpAES_CMAC { + IppCtxId idCtx; /* CMAC identifier */ + int index; /* internal buffer entry (free) */ + int dummy[2]; /* align-16 */ + Ipp8u k1[MBS_RIJ128]; /* k1 subkey */ + Ipp8u k2[MBS_RIJ128]; /* k2 subkey */ + Ipp8u mBuffer[MBS_RIJ128];/* buffer */ + Ipp8u mMAC[MBS_RIJ128]; /* intermediate digest */ + __ALIGN16 /* aligned AES context */ + IppsAESSpec mCipherCtx; +}; + +/* alignment */ +#define AESCMAC_ALIGNMENT (RIJ_ALIGNMENT) + +/* +// Useful macros +*/ +#define CMAC_ID(stt) ((stt)->idCtx) +#define CMAC_INDX(stt) ((stt)->index) +#define CMAC_K1(stt) ((stt)->k1) +#define CMAC_K2(stt) ((stt)->k2) +#define CMAC_BUFF(stt) ((stt)->mBuffer) +#define CMAC_MAC(stt) ((stt)->mMAC) +#define CMAC_CIPHER(stt) ((stt)->mCipherCtx) + +/* valid context ID */ +#define VALID_AESCMAC_ID(ctx) (CMAC_ID((ctx))==idCtxCMAC) + +#endif /* _PCP_CMAC_H */ diff --git a/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpeccp.h b/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpeccp.h new file mode 100644 index 0000000000..34871a136f --- /dev/null +++ b/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpeccp.h @@ -0,0 +1,230 @@ +/* +* Copyright (C) 2016 Intel Corporation. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in +* the documentation and/or other materials provided with the +* distribution. +* * Neither the name of Intel Corporation nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ + +#if !defined(_PCP_ECCP_H) +#define _PCP_ECCP_H + +#include "pcpbnresource.h" +#include "pcppma.h" +#include "pcpeccppoint.h" +#include "pcpeccpsscm.h" + + +typedef struct eccp_method_st ECCP_METHOD; + +/* +// ECC over prime GF(p) Context +*/ +struct _cpECCP { + IppCtxId idCtx; /* prime EC identifier */ + + IppsBigNumState* pPrime; /* specify finite field GF(p) */ + IppsBigNumState* pA; /* scecify A & B of EC equation: */ + IppsBigNumState* pB; /* y^2 = x^3 + A*x + B (mod)p */ + + IppsBigNumState* pGX; /* Base Point (X coordinate) */ + IppsBigNumState* pGY; /* Base Point (Y coordinate) */ + IppsBigNumState* pR; /* order (r) of Base Point */ + /* fields above mainly for ippsECCPSet()/ippsECCPGet() */ + + Ipp32u eccStandard;/* generic/standard ecc */ + + ECCP_METHOD* pMethod; + + int gfeBitSize; /* size (bits) of field element */ + int ordBitSize; /* size (bits) of BP order */ + + int a_3; /* ==1 if A==-3 or A==P-3 */ + IppsBigNumState* pAenc; /* internal formatted pA value */ + IppsBigNumState* pBenc; /* internal formatted pB value */ + IppsMontState* pMontP; /* montromery engine (modulo p) */ + + IppsECCPPointState* pGenc; /* internal formatted Base Point */ + IppsBigNumState* pCofactor; /* cofactor = #E/base_point_order*/ + IppsMontState* pMontR; /* montromery engine (modulo r) */ + + IppsBigNumState* pPrivate; /* private key */ + IppsECCPPointState* pPublic; /* public key (affine) */ + IppsBigNumState* pPrivateE; /* ephemeral private key */ + IppsECCPPointState* pPublicE; /* ephemeral public key (affine) */ + + IppsPrimeState* pPrimary; /* prime engine */ + + Ipp8u* pSscmBuffer;/* pointer to sscm buffer */ + + BigNumNode* pBnList; /* list of big numbers */ +}; + +/* some useful constants */ +#define BNLISTSIZE (32) /* list size (probably less) */ + +/* +// Contetx Access Macros +*/ +#define ECP_ID(ctx) ((ctx)->idCtx) + +#define ECP_PRIME(ctx) ((ctx)->pPrime) +#define ECP_A(ctx) ((ctx)->pA) +#define ECP_B(ctx) ((ctx)->pB) + +#define ECP_GX(ctx) ((ctx)->pGX) +#define ECP_GY(ctx) ((ctx)->pGY) +#define ECP_ORDER(ctx) ((ctx)->pR) + +#define ECP_TYPE(ctx) ((ctx)->eccStandard) + +#define ECP_METHOD(ctx) ((ctx)->pMethod) + +#define ECP_GFEBITS(ctx) ((ctx)->gfeBitSize) +#define ECP_ORDBITS(ctx) ((ctx)->ordBitSize) + +#define ECP_AMI3(ctx) ((ctx)->a_3) +#define ECP_AENC(ctx) ((ctx)->pAenc) +#define ECP_BENC(ctx) ((ctx)->pBenc) +#define ECP_PMONT(ctx) ((ctx)->pMontP) + +#define ECP_GENC(ctx) ((ctx)->pGenc) +#define ECP_COFACTOR(ctx) ((ctx)->pCofactor) +#define ECP_RMONT(ctx) ((ctx)->pMontR) + +#define ECP_PRIVATE(ctx) ((ctx)->pPrivate) +#define ECP_PUBLIC(ctx) ((ctx)->pPublic) +#define ECP_PRIVATE_E(ctx) ((ctx)->pPrivateE) +#define ECP_PUBLIC_E(ctx) ((ctx)->pPublicE) + +#define ECP_PRIMARY(ctx) ((ctx)->pPrimary) +#define ECP_SCCMBUFF(ctx) ((ctx)->pSscmBuffer) +#define ECP_BNCTX(ctx) ((ctx)->pBnList) + +#define ECP_VALID_ID(ctx) (ECP_ID((ctx))==idCtxECCP) + +/* +// Recommended (Standard) Domain Parameters +*/ +extern const Ipp32u secp112r1_p[]; // (2^128 -3)/76439 +extern const Ipp32u secp112r1_a[]; +extern const Ipp32u secp112r1_b[]; +extern const Ipp32u secp112r1_gx[]; +extern const Ipp32u secp112r1_gy[]; +extern const Ipp32u secp112r1_r[]; +extern Ipp32u secp112r1_h; + +extern const Ipp32u secp112r2_p[]; // (2^128 -3)/76439 +extern const Ipp32u secp112r2_a[]; +extern const Ipp32u secp112r2_b[]; +extern const Ipp32u secp112r2_gx[]; +extern const Ipp32u secp112r2_gy[]; +extern const Ipp32u secp112r2_r[]; +extern Ipp32u secp112r2_h; + +extern const Ipp32u secp128r1_p[]; // 2^128 -2^97 -1 +extern const Ipp32u secp128r1_a[]; +extern const Ipp32u secp128r1_b[]; +extern const Ipp32u secp128r1_gx[]; +extern const Ipp32u secp128r1_gy[]; +extern const Ipp32u secp128r1_r[]; +extern Ipp32u secp128r1_h; + +extern const Ipp32u* secp128_mx[]; + +extern const Ipp32u secp128r2_p[]; // 2^128 -2^97 -1 +extern const Ipp32u secp128r2_a[]; +extern const Ipp32u secp128r2_b[]; +extern const Ipp32u secp128r2_gx[]; +extern const Ipp32u secp128r2_gy[]; +extern const Ipp32u secp128r2_r[]; +extern Ipp32u secp128r2_h; + +extern const Ipp32u secp160r1_p[]; // 2^160 -2^31 -1 +extern const Ipp32u secp160r1_a[]; +extern const Ipp32u secp160r1_b[]; +extern const Ipp32u secp160r1_gx[]; +extern const Ipp32u secp160r1_gy[]; +extern const Ipp32u secp160r1_r[]; +extern Ipp32u secp160r1_h; + +extern const Ipp32u secp160r2_p[]; // 2^160 -2^32 -2^14 -2^12 -2^9 -2^8 -2^7 -2^2 -1 +extern const Ipp32u secp160r2_a[]; +extern const Ipp32u secp160r2_b[]; +extern const Ipp32u secp160r2_gx[]; +extern const Ipp32u secp160r2_gy[]; +extern const Ipp32u secp160r2_r[]; +extern Ipp32u secp160r2_h; + +extern const Ipp32u secp192r1_p[]; // 2^192 -2^64 -1 +extern const Ipp32u secp192r1_a[]; +extern const Ipp32u secp192r1_b[]; +extern const Ipp32u secp192r1_gx[]; +extern const Ipp32u secp192r1_gy[]; +extern const Ipp32u secp192r1_r[]; +extern Ipp32u secp192r1_h; + +extern const Ipp32u secp224r1_p[]; // 2^224 -2^96 +1 +extern const Ipp32u secp224r1_a[]; +extern const Ipp32u secp224r1_b[]; +extern const Ipp32u secp224r1_gx[]; +extern const Ipp32u secp224r1_gy[]; +extern const Ipp32u secp224r1_r[]; +extern Ipp32u secp224r1_h; + +extern const Ipp32u secp256r1_p[]; // 2^256 -2^224 +2^192 +2^96 -1 +extern const Ipp32u secp256r1_a[]; +extern const Ipp32u secp256r1_b[]; +extern const Ipp32u secp256r1_gx[]; +extern const Ipp32u secp256r1_gy[]; +extern const Ipp32u secp256r1_r[]; +extern Ipp32u secp256r1_h; + +extern const Ipp32u secp384r1_p[]; // 2^384 -2^128 -2^96 +2^32 -1 +extern const Ipp32u secp384r1_a[]; +extern const Ipp32u secp384r1_b[]; +extern const Ipp32u secp384r1_gx[]; +extern const Ipp32u secp384r1_gy[]; +extern const Ipp32u secp384r1_r[]; +extern Ipp32u secp384r1_h; + +extern const Ipp32u secp521r1_p[]; // 2^521 -1 +extern const Ipp32u secp521r1_a[]; +extern const Ipp32u secp521r1_b[]; +extern const Ipp32u secp521r1_gx[]; +extern const Ipp32u secp521r1_gy[]; +extern const Ipp32u secp521r1_r[]; +extern Ipp32u secp521r1_h; + +/* half of some std modulus */ +extern const Ipp32u h_secp128r1_p[]; +extern const Ipp32u h_secp192r1_p[]; +extern const Ipp32u h_secp224r1_p[]; +extern const Ipp32u h_secp256r1_p[]; +extern const Ipp32u h_secp384r1_p[]; +extern const Ipp32u h_secp521r1_p[]; + +#endif /* _PCP_ECCP_H */ diff --git a/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpeccpdpca.c b/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpeccpdpca.c new file mode 100644 index 0000000000..e4c88689d4 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpeccpdpca.c @@ -0,0 +1,370 @@ +/* +* Copyright (C) 2016 Intel Corporation. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in +* the documentation and/or other materials provided with the +* distribution. +* * Neither the name of Intel Corporation nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ + +#include "owndefs.h" +#include "owncp.h" +#include "pcpeccp.h" +#include "pcpeccppoint.h" +#include "pcpbnresource.h" +#include "pcpeccpmethod.h" +#include "pcpeccpmethodcom.h" +#include "pcppma.h" + + +/*F* +// Name: ippsECCPSet +// +// Purpose: Set EC Domain Parameters. +// +// Returns: Reason: +// ippStsNullPtrErr NULL == pPrime +// NULL == pA +// NULL == pB +// NULL == pGX +// NULL == pGY +// NULL == pOrder +// NULL == pECC +// +// ippStsContextMatchErr illegal pPrime->idCtx +// illegal pA->idCtx +// illegal pB->idCtx +// illegal pGX->idCtx +// illegal pGY->idCtx +// illegal pOrder->idCtx +// illegal pECC->idCtx +// +// ippStsRangeErr not enough room for: +// pPrime +// pA, pB, +// pGX,pGY +// pOrder +// +// ippStsRangeErr 0>= cofactor +// +// ippStsNoErr no errors +// +// Parameters: +// pPrime pointer to the prime (specify FG(p)) +// pA pointer to the A coefficient of EC equation +// pB pointer to the B coefficient of EC equation +// pGX,pGY pointer to the Base Point (x and y coordinates) of EC +// pOrder pointer to the Base Point order +// cofactor cofactor value +// pECC pointer to the ECC context +// +*F*/ +static +void ECCPSetDP(IppECCType flag, + int primeSize, const Ipp32u* pPrime, + int aSize, const Ipp32u* pA, + int bSize, const Ipp32u* pB, + int gxSize, const Ipp32u* pGx, + int gySize, const Ipp32u* pGy, + int orderSize, const Ipp32u* pOrder, + Ipp32u cofactor, + IppsECCPState* pECC) +{ + ECP_TYPE(pECC) = flag; + + /* reset size (bits) of field element */ + ECP_GFEBITS(pECC) = cpMSBit_BNU32(pPrime, primeSize) +1; + /* reset size (bits) of Base Point order */ + ECP_ORDBITS(pECC) = cpMSBit_BNU32(pOrder, orderSize) +1; + + /* set up prime */ + ippsSet_BN(ippBigNumPOS, primeSize, pPrime, ECP_PRIME(pECC)); + /* set up A */ + ippsSet_BN(ippBigNumPOS, aSize, pA, ECP_A(pECC)); + /* test A */ + BN_Word(ECP_B(pECC), 3); + PMA_add(ECP_B(pECC), ECP_A(pECC), ECP_B(pECC), ECP_PRIME(pECC)); + ECP_AMI3(pECC) = IsZero_BN(ECP_B(pECC)); + /* set up B */ + ippsSet_BN(ippBigNumPOS, bSize, pB, ECP_B(pECC)); + + /* set up affine coordinates of Base Point and order */ + ippsSet_BN(ippBigNumPOS, gxSize, pGx, ECP_GX(pECC)); + ippsSet_BN(ippBigNumPOS, gySize, pGy, ECP_GY(pECC)); + ippsSet_BN(ippBigNumPOS, orderSize, pOrder, ECP_ORDER(pECC)); + + /* set up cofactor */ + //ippsSet_BN(ippBigNumPOS, 1, &((Ipp32u)cofactor), ECP_COFACTOR(pECC)); + ippsSet_BN(ippBigNumPOS, 1, &cofactor, ECP_COFACTOR(pECC)); + + /* montgomery engine (prime) */ + if( ippStsNoErr == ippsMontSet((Ipp32u*)BN_NUMBER(ECP_PRIME(pECC)), BN_SIZE32(ECP_PRIME(pECC)), ECP_PMONT(pECC)) ) { + /* modulo reduction and montgomery form of A and B */ + PMA_mod(ECP_AENC(pECC), ECP_A(pECC), ECP_PRIME(pECC)); + PMA_enc(ECP_AENC(pECC), ECP_AENC(pECC), ECP_PMONT(pECC)); + PMA_mod(ECP_BENC(pECC), ECP_B(pECC), ECP_PRIME(pECC)); + PMA_enc(ECP_BENC(pECC), ECP_BENC(pECC), ECP_PMONT(pECC)); + /* projective coordinates and montgomery form of of Base Point */ + if( ( IsZero_BN(ECP_BENC(pECC)) && ECCP_IsPointAtAffineInfinity1(ECP_GX(pECC), ECP_GY(pECC))) || + (!IsZero_BN(ECP_BENC(pECC)) && ECCP_IsPointAtAffineInfinity0(ECP_GX(pECC), ECP_GY(pECC))) ) + ECCP_SetPointToInfinity(ECP_GENC(pECC)); + else { + ECP_METHOD(pECC)->SetPointProjective(ECP_GX(pECC), ECP_GY(pECC), BN_ONE_REF(), ECP_GENC(pECC), pECC); + } + } + + /* montgomery engine (order) */ + if( ippStsNoErr == ippsMontSet((Ipp32u*)BN_NUMBER(ECP_ORDER(pECC)), BN_SIZE32(ECP_ORDER(pECC)), ECP_RMONT(pECC)) ) + PMA_enc(ECP_COFACTOR(pECC), ECP_COFACTOR(pECC), ECP_RMONT(pECC)); + + /* set zero private keys */ + BN_Word(ECP_PRIVATE(pECC), 0); + BN_Word(ECP_PRIVATE_E(pECC), 0); + + /* set infinity public keys */ + ECCP_SetPointToInfinity(ECP_PUBLIC(pECC)); + ECCP_SetPointToInfinity(ECP_PUBLIC_E(pECC)); +} + + +IPPFUN(IppStatus, ippsECCPSet, (const IppsBigNumState* pPrime, + const IppsBigNumState* pA, const IppsBigNumState* pB, + const IppsBigNumState* pGX,const IppsBigNumState* pGY,const IppsBigNumState* pOrder, + int cofactor, + IppsECCPState* pECC)) +{ + /* test pECC */ + IPP_BAD_PTR1_RET(pECC); + /* use aligned EC context */ + pECC = (IppsECCPState*)( IPP_ALIGNED_PTR(pECC, ALIGN_VAL) ); + /* test ID */ + IPP_BADARG_RET(!ECP_VALID_ID(pECC), ippStsContextMatchErr); + + /* test pPrime */ + IPP_BAD_PTR1_RET(pPrime); + pPrime = (IppsBigNumState*)( IPP_ALIGNED_PTR(pPrime, ALIGN_VAL) ); + IPP_BADARG_RET(!BN_VALID_ID(pPrime), ippStsContextMatchErr); + IPP_BADARG_RET((cpBN_bitsize(pPrime)>ECP_GFEBITS(pECC)), ippStsRangeErr); + + /* test pA and pB */ + IPP_BAD_PTR2_RET(pA,pB); + pA = (IppsBigNumState*)( IPP_ALIGNED_PTR(pA, ALIGN_VAL) ); + pB = (IppsBigNumState*)( IPP_ALIGNED_PTR(pB, ALIGN_VAL) ); + IPP_BADARG_RET(!BN_VALID_ID(pA), ippStsContextMatchErr); + IPP_BADARG_RET(!BN_VALID_ID(pB), ippStsContextMatchErr); + IPP_BADARG_RET((cpBN_bitsize(pA)>ECP_GFEBITS(pECC)), ippStsRangeErr); + IPP_BADARG_RET((cpBN_bitsize(pB)>ECP_GFEBITS(pECC)), ippStsRangeErr); + + /* test pG and pGorder pointers */ + IPP_BAD_PTR3_RET(pGX,pGY, pOrder); + pGX = (IppsBigNumState*)( IPP_ALIGNED_PTR(pGX, ALIGN_VAL) ); + pGY = (IppsBigNumState*)( IPP_ALIGNED_PTR(pGY, ALIGN_VAL) ); + pOrder = (IppsBigNumState*)( IPP_ALIGNED_PTR(pOrder, ALIGN_VAL) ); + IPP_BADARG_RET(!BN_VALID_ID(pGX), ippStsContextMatchErr); + IPP_BADARG_RET(!BN_VALID_ID(pGY), ippStsContextMatchErr); + IPP_BADARG_RET(!BN_VALID_ID(pOrder), ippStsContextMatchErr); + IPP_BADARG_RET((cpBN_bitsize(pGX)>ECP_GFEBITS(pECC)), ippStsRangeErr); + IPP_BADARG_RET((cpBN_bitsize(pGY)>ECP_GFEBITS(pECC)), ippStsRangeErr); + IPP_BADARG_RET((cpBN_bitsize(pOrder)>ECP_ORDBITS(pECC)), ippStsRangeErr); + + /* test cofactor */ + IPP_BADARG_RET(!(0idCtx +// +// ippStsECCInvalidFlagErr invalid flag +// +// ippStsNoErr no errors +// +// Parameters: +// flag specify standard ECC parameter(s) to be setup +// pECC pointer to the ECC context +// +*F*/ +IPPFUN(IppStatus, ippsECCPSetStd, (IppECCType flag, IppsECCPState* pECC)) +{ + /* test pECC */ + IPP_BAD_PTR1_RET(pECC); + /* use aligned EC context */ + pECC = (IppsECCPState*)( IPP_ALIGNED_PTR(pECC, ALIGN_VAL) ); + /* test ID */ + IPP_BADARG_RET(!ECP_VALID_ID(pECC), ippStsContextMatchErr); + + *(ECP_METHOD(pECC)) = *(ECCPcom_Methods()); + + switch(flag) { + case IppECCPStd112r1: + ECCPSetDP(IppECCPStd112r1, + BITS2WORD32_SIZE(112), secp112r1_p, + BITS2WORD32_SIZE(112), secp112r1_a, + BITS2WORD32_SIZE(112), secp112r1_b, + BITS2WORD32_SIZE(112), secp112r1_gx, + BITS2WORD32_SIZE(112), secp112r1_gy, + BITS2WORD32_SIZE(112), secp112r1_r, + secp112r1_h, pECC); + break; + + case IppECCPStd112r2: + ECCPSetDP(IppECCPStd112r2, + BITS2WORD32_SIZE(112), secp112r2_p, + BITS2WORD32_SIZE(112), secp112r2_a, + BITS2WORD32_SIZE(112), secp112r2_b, + BITS2WORD32_SIZE(112), secp112r2_gx, + BITS2WORD32_SIZE(112), secp112r2_gy, + BITS2WORD32_SIZE(112), secp112r2_r, + secp112r2_h, pECC); + break; + + case IppECCPStd128r1: + ECCPSetDP(IppECCPStd128r1, + BITS2WORD32_SIZE(128), secp128r1_p, + BITS2WORD32_SIZE(128), secp128r1_a, + BITS2WORD32_SIZE(128), secp128r1_b, + BITS2WORD32_SIZE(128), secp128r1_gx, + BITS2WORD32_SIZE(128), secp128r1_gy, + BITS2WORD32_SIZE(128), secp128r1_r, + secp128r1_h, pECC); + break; + + case IppECCPStd128r2: + ECCPSetDP(IppECCPStd128r2, + BITS2WORD32_SIZE(128), secp128r2_p, + BITS2WORD32_SIZE(128), secp128r2_a, + BITS2WORD32_SIZE(128), secp128r2_b, + BITS2WORD32_SIZE(128), secp128r2_gx, + BITS2WORD32_SIZE(128), secp128r2_gy, + BITS2WORD32_SIZE(128), secp128r2_r, + secp128r2_h, pECC); + break; + + case IppECCPStd160r1: + ECCPSetDP(IppECCPStd160r1, + BITS2WORD32_SIZE(160), secp160r1_p, + BITS2WORD32_SIZE(160), secp160r1_a, + BITS2WORD32_SIZE(160), secp160r1_b, + BITS2WORD32_SIZE(160), secp160r1_gx, + BITS2WORD32_SIZE(160), secp160r1_gy, + BITS2WORD32_SIZE(161), secp160r1_r, + secp160r1_h, pECC); + break; + + case IppECCPStd160r2: + ECCPSetDP(IppECCPStd160r2, + BITS2WORD32_SIZE(160), secp160r2_p, + BITS2WORD32_SIZE(160), secp160r2_a, + BITS2WORD32_SIZE(160), secp160r2_b, + BITS2WORD32_SIZE(160), secp160r2_gx, + BITS2WORD32_SIZE(160), secp160r2_gy, + BITS2WORD32_SIZE(161), secp160r2_r, + secp160r2_h, pECC); + break; + + case IppECCPStd192r1: + ECCPSetDP(IppECCPStd192r1, + BITS2WORD32_SIZE(192), secp192r1_p, + BITS2WORD32_SIZE(192), secp192r1_a, + BITS2WORD32_SIZE(192), secp192r1_b, + BITS2WORD32_SIZE(192), secp192r1_gx, + BITS2WORD32_SIZE(192), secp192r1_gy, + BITS2WORD32_SIZE(192), secp192r1_r, + secp192r1_h, pECC); + break; + + case IppECCPStd224r1: + ECCPSetDP(IppECCPStd224r1, + BITS2WORD32_SIZE(224), secp224r1_p, + BITS2WORD32_SIZE(224), secp224r1_a, + BITS2WORD32_SIZE(224), secp224r1_b, + BITS2WORD32_SIZE(224), secp224r1_gx, + BITS2WORD32_SIZE(224), secp224r1_gy, + BITS2WORD32_SIZE(224), secp224r1_r, + secp224r1_h, pECC); + break; + + case IppECCPStd256r1: + ECCPSetDP(IppECCPStd256r1, + BITS2WORD32_SIZE(256), secp256r1_p, + BITS2WORD32_SIZE(256), secp256r1_a, + BITS2WORD32_SIZE(256), secp256r1_b, + BITS2WORD32_SIZE(256), secp256r1_gx, + BITS2WORD32_SIZE(256), secp256r1_gy, + BITS2WORD32_SIZE(256), secp256r1_r, + secp256r1_h, pECC); + break; + + case IppECCPStd384r1: + ECCPSetDP(IppECCPStd384r1, + BITS2WORD32_SIZE(384), secp384r1_p, + BITS2WORD32_SIZE(384), secp384r1_a, + BITS2WORD32_SIZE(384), secp384r1_b, + BITS2WORD32_SIZE(384), secp384r1_gx, + BITS2WORD32_SIZE(384), secp384r1_gy, + BITS2WORD32_SIZE(384), secp384r1_r, + secp384r1_h, pECC); + break; + + case IppECCPStd521r1: + ECCPSetDP(IppECCPStd521r1, + BITS2WORD32_SIZE(521), secp521r1_p, + BITS2WORD32_SIZE(521), secp521r1_a, + BITS2WORD32_SIZE(521), secp521r1_b, + BITS2WORD32_SIZE(521), secp521r1_gx, + BITS2WORD32_SIZE(521), secp521r1_gy, + BITS2WORD32_SIZE(521), secp521r1_r, + secp521r1_h, pECC); + break; + + default: + return ippStsECCInvalidFlagErr; + } + + return ippStsNoErr; +} diff --git a/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpeccpgenkeyca.c b/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpeccpgenkeyca.c new file mode 100644 index 0000000000..b152a7b82c --- /dev/null +++ b/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpeccpgenkeyca.c @@ -0,0 +1,107 @@ +/* +* Copyright (C) 2016 Intel Corporation. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in +* the documentation and/or other materials provided with the +* distribution. +* * Neither the name of Intel Corporation nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ + +#include "owndefs.h" +#include "owncp.h" +#include "pcpeccppoint.h" +#include "pcpeccpmethod.h" +#include "pcpeccpmethodcom.h" + + +/*F* +// Name: ippsECCPGenKeyPair +// +// Purpose: Generate (private,public) Key Pair +// +// Returns: Reason: +// ippStsNullPtrErr NULL == pECC +// NULL == pPrivate +// NULL == pPublic +// +// ippStsContextMatchErr illegal pECC->idCtx +// illegal pPrivate->idCtx +// illegal pPublic->idCtx +// +// ippStsNoErr no errors +// +// Parameters: +// pPrivate pointer to the resultant private key +// pPublic pointer to the resultant public key +// pECC pointer to the ECCP context +// +*F*/ +IPPFUN(IppStatus, ippsECCPGenKeyPair, (IppsBigNumState* pPrivate, IppsECCPPointState* pPublic, + IppsECCPState* pECC, + IppBitSupplier rndFunc, void* pRndParam)) +{ + IPP_BAD_PTR2_RET(pECC, rndFunc); + + /* use aligned EC context */ + pECC = (IppsECCPState*)( IPP_ALIGNED_PTR(pECC, ALIGN_VAL) ); + /* test ID */ + IPP_BADARG_RET(!ECP_VALID_ID(pECC), ippStsContextMatchErr); + + /* test private/public keys */ + IPP_BAD_PTR2_RET(pPrivate,pPublic); + pPrivate = (IppsBigNumState*)( IPP_ALIGNED_PTR(pPrivate, ALIGN_VAL) ); + pPublic = (IppsECCPPointState*)( IPP_ALIGNED_PTR(pPublic, ALIGN_VAL) ); + IPP_BADARG_RET(!BN_VALID_ID(pPrivate), ippStsContextMatchErr); + IPP_BADARG_RET((BN_ROOM(pPrivate)*BITSIZE(BNU_CHUNK_T)MulBasePoint(pPrivate, pPublic, pECC, ECP_BNCTX(pECC)); + + return ippStsNoErr; + } +} diff --git a/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpeccpinitca.c b/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpeccpinitca.c new file mode 100644 index 0000000000..ee54bb844b --- /dev/null +++ b/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpeccpinitca.c @@ -0,0 +1,305 @@ +/* +* Copyright (C) 2016 Intel Corporation. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in +* the documentation and/or other materials provided with the +* distribution. +* * Neither the name of Intel Corporation nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ + +#include "owndefs.h" +#include "owncp.h" +#include "pcpeccp.h" +#include "pcpeccppoint.h" +#include "pcpbnresource.h" +#include "pcpeccpmethod.h" +#include "pcpeccpsscm.h" +#include "pcptool.h" + + +/*F* +// Name: ippsECCPGetSize +// +// Purpose: Returns size of ECC context (bytes). +// +// Returns: Reason: +// ippStsNullPtrErr NULL == pSize +// +// ippStsSizeErr 2>feBitSize +// +// ippStsNoErr no errors +// +// Parameters: +// feBitSize size of field element (bits) +// pSize pointer to the size of internal ECC context +// +*F*/ +IPPFUN(IppStatus, ippsECCPGetSize, (int feBitSize, int *pSize)) +{ + /* test size's pointer */ + IPP_BAD_PTR1_RET(pSize); + + /* test size of field element */ + IPP_BADARG_RET((2>feBitSize || feBitSize>EC_GFP_MAXBITSIZE), ippStsSizeErr); + + { + int bn1Size; + int bn2Size; + int pointSize; + int mont1Size; + int mont2Size; + int primeSize; + int listSize; + + /* size of field element */ + int gfeSize = BITS2WORD32_SIZE(feBitSize); + /* size of order */ + int ordSize = BITS2WORD32_SIZE(feBitSize+1); + + /* size of sscm buffer */ + int w = cpECCP_OptimalWinSize(feBitSize+1); + int nPrecomputed = 1<feBitSize +// +// ippStsNoErr no errors +// +// Parameters: +// feBitSize size of field element (bits) +// pECC pointer to the ECC context +// +*F*/ +IPPFUN(IppStatus, ippsECCPInit, (int feBitSize, IppsECCPState* pECC)) +{ + /* test pECC pointer */ + IPP_BAD_PTR1_RET(pECC); + /* use aligned EC context */ + pECC = (IppsECCPState*)( IPP_ALIGNED_PTR(pECC, ALIGN_VAL) ); + + /* test size of field element */ + IPP_BADARG_RET((2>feBitSize || feBitSize>EC_GFP_MAXBITSIZE), ippStsSizeErr); + + /* clear context */ + PaddBlock(0, pECC, sizeof(IppsECCPState)); + + /* context ID */ + ECP_ID(pECC) = idCtxECCP; + + /* generic EC */ + ECP_TYPE(pECC) = IppECCArbitrary; + + /* size of field element & BP order */ + ECP_GFEBITS(pECC) = feBitSize; + ECP_ORDBITS(pECC) = feBitSize+1; + + /* + // init other context fields + */ + { + int bn1Size; + int bn2Size; + int pointSize; + int mont1Size; + int mont2Size; + int primeSize; + + /* size of field element */ + int gfeSize = BITS2WORD32_SIZE(feBitSize); + /* size of order */ + int ordSize = BITS2WORD32_SIZE(feBitSize+1); + + /* size of sscm buffer */ + int w = cpECCP_OptimalWinSize(feBitSize+1); + int nPrecomputed = 1< pP==pQ (maybe both pP and pQ are at Infinity) +// returns 1 => pP!=pQ +// +// Note +// In general we check: +// P_X*Q_Z^2 ~ Q_X*P_Z^2 +// P_Y*Q_Z^3 ~ Q_Y*P_Z^3 +*/ +int ECCP_ComparePoint(const IppsECCPPointState* pP, + const IppsECCPPointState* pQ, + const IppsECCPState* pECC, + BigNumNode* pList) +{ + /* P or/and Q at Infinity */ + if( ECCP_IsPointAtInfinity(pP) ) + return ECCP_IsPointAtInfinity(pQ)? 0:1; + if( ECCP_IsPointAtInfinity(pQ) ) + return ECCP_IsPointAtInfinity(pP)? 0:1; + + /* (P_Z==1) && (Q_Z==1) */ + if( ECP_POINT_AFFINE(pP) && ECP_POINT_AFFINE(pQ) ) + return ((0==cpBN_cmp(ECP_POINT_X(pP),ECP_POINT_X(pQ))) && (0==cpBN_cmp(ECP_POINT_Y(pP),ECP_POINT_Y(pQ))))? 0:1; + + { + IppsMontState* pMont = ECP_PMONT(pECC); + + IppsBigNumState* pPtmp = cpBigNumListGet(&pList); + IppsBigNumState* pQtmp = cpBigNumListGet(&pList); + IppsBigNumState* pPZ = cpBigNumListGet(&pList); + IppsBigNumState* pQZ = cpBigNumListGet(&pList); + + /* P_X*Q_Z^2 ~ Q_X*P_Z^2 */ + if( !ECP_POINT_AFFINE(pQ) ) { + PMA_sqre(pQZ, ECP_POINT_Z(pQ), pMont); /* Ptmp = P_X*Q_Z^2 */ + PMA_mule(pPtmp, ECP_POINT_X(pP), pQZ, pMont); + } + else { + PMA_set(pPtmp, ECP_POINT_X(pP)); + } + if( !ECP_POINT_AFFINE(pP) ) { + PMA_sqre(pPZ, ECP_POINT_Z(pP), pMont); /* Qtmp = Q_X*P_Z^2 */ + PMA_mule(pQtmp, ECP_POINT_X(pQ), pPZ, pMont); + } + else { + PMA_set(pQtmp, ECP_POINT_X(pQ)); + } + if ( cpBN_cmp(pPtmp, pQtmp) ) + return 1; /* points are different: (P_X*Q_Z^2) != (Q_X*P_Z^2) */ + + /* P_Y*Q_Z^3 ~ Q_Y*P_Z^3 */ + if( !ECP_POINT_AFFINE(pQ) ) { + PMA_mule(pQZ, pQZ, ECP_POINT_Z(pQ), pMont); /* Ptmp = P_Y*Q_Z^3 */ + PMA_mule(pPtmp, ECP_POINT_Y(pP), pQZ, pMont); + } + else { + PMA_set(pPtmp, ECP_POINT_Y(pP)); + } + if( !ECP_POINT_AFFINE(pP) ) { + PMA_mule(pPZ, pPZ, ECP_POINT_Z(pP), pMont); /* Qtmp = Q_Y*P_Z^3 */ + PMA_mule(pQtmp, ECP_POINT_Y(pQ), pPZ, pMont); + } + else { + PMA_set(pQtmp, ECP_POINT_Y(pQ)); + } + return cpBN_cmp(pPtmp, pQtmp)? 1:0; + } +} + +/* +// ECCP_NegPoint +// +// Negative point +*/ +void ECCP_NegPoint(const IppsECCPPointState* pP, + IppsECCPPointState* pR, + const IppsECCPState* pECC) +{ + /* test point at Infinity */ + if( ECCP_IsPointAtInfinity(pP) ) + ECCP_SetPointToInfinity(pR); + + else { + IppsBigNumState* pModulo = ECP_PRIME(pECC); + + if( pP!=pR ) { + PMA_set(ECP_POINT_X(pR), ECP_POINT_X(pP)); + PMA_set(ECP_POINT_Z(pR), ECP_POINT_Z(pP)); + } + PMA_sub(ECP_POINT_Y(pR), pModulo, ECP_POINT_Y(pP), pModulo); + ECP_POINT_AFFINE(pR) = ECP_POINT_AFFINE(pP); + } +} + +/* +// ECCP_DblPoint +// +// Double point +*/ +void ECCP_DblPoint(const IppsECCPPointState* pP, + IppsECCPPointState* pR, + const IppsECCPState* pECC, + BigNumNode* pList) +{ + /* P at infinity */ + if( ECCP_IsPointAtInfinity(pP) ) + ECCP_SetPointToInfinity(pR); + + else { + IppsMontState* pMont = ECP_PMONT(pECC); + + IppsBigNumState* bnV = cpBigNumListGet(&pList); + IppsBigNumState* bnU = cpBigNumListGet(&pList); + IppsBigNumState* bnM = cpBigNumListGet(&pList); + IppsBigNumState* bnS = cpBigNumListGet(&pList); + IppsBigNumState* bnT = cpBigNumListGet(&pList); + IppsBigNumState* pModulo = ECP_PRIME(pECC); + + /* M = 3*X^2 + A*Z^4 */ + if( ECP_POINT_AFFINE(pP) ) { + PMA_sqre(bnU, ECP_POINT_X(pP), pMont); + PMA_add(bnM, bnU, bnU, pModulo); + PMA_add(bnM, bnM, bnU, pModulo); + PMA_add(bnM, bnM, ECP_AENC(pECC), pModulo); + } + else if( ECP_AMI3(pECC) ) { + PMA_sqre(bnU, ECP_POINT_Z(pP), pMont); + PMA_add(bnS, ECP_POINT_X(pP), bnU, pModulo); + PMA_sub(bnT, ECP_POINT_X(pP), bnU, pModulo); + PMA_mule(bnM, bnS, bnT, pMont); + PMA_add(bnU, bnM, bnM, pModulo); + PMA_add(bnM, bnU, bnM, pModulo); + } + else { + PMA_sqre(bnU, ECP_POINT_X(pP), pMont); + PMA_add(bnM, bnU, bnU, pModulo); + PMA_add(bnM, bnM, bnU, pModulo); + PMA_sqre(bnU, ECP_POINT_Z(pP), pMont); + PMA_sqre(bnU, bnU, pMont); + PMA_mule(bnU, bnU, ECP_AENC(pECC), pMont); + PMA_add(bnM, bnM, bnU, pModulo); + } + + PMA_add(bnV, ECP_POINT_Y(pP), ECP_POINT_Y(pP), pModulo); + + /* R_Z = 2*Y*Z */ + if( ECP_POINT_AFFINE(pP) ) { + PMA_set(ECP_POINT_Z(pR), bnV); + } + else { + PMA_mule(ECP_POINT_Z(pR), bnV, ECP_POINT_Z(pP), pMont); + } + + /* S = 4*X*Y^2 */ + PMA_sqre(bnT, bnV, pMont); + PMA_mule(bnS, bnT, ECP_POINT_X(pP), pMont); + + /* R_X = M^2 - 2*S */ + PMA_sqre(bnU, bnM, pMont); + PMA_sub(bnU, bnU, bnS, pModulo); + PMA_sub(ECP_POINT_X(pR), bnU, bnS, pModulo); + + /* T = 8*Y^4 */ + PMA_mule(bnV, bnV, ECP_POINT_Y(pP), pMont); + PMA_mule(bnT, bnT, bnV, pMont); + + /* R_Y = M*(S - R_X) - T */ + PMA_sub(bnS, bnS, ECP_POINT_X(pR), pModulo); + PMA_mule(bnS, bnS, bnM, pMont); + PMA_sub(ECP_POINT_Y(pR), bnS, bnT, pModulo); + + ECP_POINT_AFFINE(pR) = 0; + } +} + +/* +// ECCP_AddPoint +// +// Add points +*/ +void ECCP_AddPoint(const IppsECCPPointState* pP, + const IppsECCPPointState* pQ, + IppsECCPPointState* pR, + const IppsECCPState* pECC, + BigNumNode* pList) +{ + /* prevent operation with point at Infinity */ + if( ECCP_IsPointAtInfinity(pP) ) { + ECCP_CopyPoint(pQ, pR); + return; + } + if( ECCP_IsPointAtInfinity(pQ) ) { + ECCP_CopyPoint(pP, pR); + return; + } + + /* + // addition + */ + { + IppsMontState* pMont = ECP_PMONT(pECC); + + IppsBigNumState* bnU0 = cpBigNumListGet(&pList); + IppsBigNumState* bnS0 = cpBigNumListGet(&pList); + IppsBigNumState* bnU1 = cpBigNumListGet(&pList); + IppsBigNumState* bnS1 = cpBigNumListGet(&pList); + IppsBigNumState* bnW = cpBigNumListGet(&pList); + IppsBigNumState* bnR = cpBigNumListGet(&pList); + IppsBigNumState *bnT = bnU0; + IppsBigNumState *bnM = bnS0; + IppsBigNumState* pModulo = ECP_PRIME(pECC); + + /* U0 = P_X * Q_Z^2 */ + /* S0 = P_Y * Q_Z^3 */ + if( ECP_POINT_AFFINE(pQ) ) { + PMA_set(bnU0, ECP_POINT_X(pP)); + PMA_set(bnS0, ECP_POINT_Y(pP)); + } + else { + PMA_sqre(bnW, ECP_POINT_Z(pQ), pMont); + PMA_mule(bnU0,ECP_POINT_X(pP), bnW, pMont); + PMA_mule(bnW, ECP_POINT_Z(pQ), bnW, pMont); + PMA_mule(bnS0,ECP_POINT_Y(pP), bnW, pMont); + } + + /* U1 = Q_X * P_Z^2 */ + /* S1 = Q_Y * P_Z^3 */ + if( ECP_POINT_AFFINE(pP) ) { + PMA_set(bnU1, ECP_POINT_X(pQ)); + PMA_set(bnS1, ECP_POINT_Y(pQ)); + } + else { + PMA_sqre(bnW, ECP_POINT_Z(pP), pMont); + PMA_mule(bnU1,ECP_POINT_X(pQ), bnW, pMont); + PMA_mule(bnW, ECP_POINT_Z(pP), bnW, pMont); + PMA_mule(bnS1,ECP_POINT_Y(pQ), bnW, pMont); + } + + /* W = U0-U1 */ + /* R = S0-S1 */ + PMA_sub(bnW, bnU0, bnU1, pModulo); + PMA_sub(bnR, bnS0, bnS1, pModulo); + + if( IsZero_BN(bnW) ) { + if( IsZero_BN(bnR) ) { + ECCP_DblPoint(pP, pR, pECC, pList); + return; + } + else { + ECCP_SetPointToInfinity(pR); + return; + } + } + + /* T = U0+U1 */ + /* M = S0+S1 */ + PMA_add(bnT, bnU0, bnU1, pModulo); + PMA_add(bnM, bnS0, bnS1, pModulo); + + /* R_Z = P_Z * Q_Z * W */ + if( ECP_POINT_AFFINE(pQ) && ECP_POINT_AFFINE(pP) ) { + PMA_set(ECP_POINT_Z(pR), bnW); + } + else { + if( ECP_POINT_AFFINE(pQ) ) { + PMA_set(bnU1, ECP_POINT_Z(pP)); + } + else if( ECP_POINT_AFFINE(pP) ) { + PMA_set(bnU1, ECP_POINT_Z(pQ)); + } + else { + PMA_mule(bnU1, ECP_POINT_Z(pP), ECP_POINT_Z(pQ), pMont); + } + PMA_mule(ECP_POINT_Z(pR), bnU1, bnW, pMont); + } + + PMA_sqre(bnU1, bnW, pMont); /* U1 = W^2 */ + PMA_mule(bnS1, bnT, bnU1, pMont); /* S1 = T * W^2 */ + + /* R_X = R^2 - T * W^2 */ + PMA_sqre(ECP_POINT_X(pR), bnR, pMont); + PMA_sub(ECP_POINT_X(pR), ECP_POINT_X(pR), bnS1, pModulo); + + /* V = T * W^2 - 2 * R_X (S1) */ + PMA_sub(bnS1, bnS1, ECP_POINT_X(pR), pModulo); + PMA_sub(bnS1, bnS1, ECP_POINT_X(pR), pModulo); + + /* R_Y = (V * R - M * W^3) /2 */ + PMA_mule(ECP_POINT_Y(pR), bnS1, bnR, pMont); + PMA_mule(bnU1, bnU1, bnW, pMont); + PMA_mule(bnU1, bnU1, bnM, pMont); + PMA_sub(bnU1, ECP_POINT_Y(pR), bnU1, pModulo); + PMA_div2(ECP_POINT_Y(pR), bnU1, pModulo); + + ECP_POINT_AFFINE(pR) = 0; + } +} + +/* +// ECCP_MulPoint +// +// Multiply point by scalar +*/ +void ECCP_MulPoint(const IppsECCPPointState* pP, + const IppsBigNumState* bnN, + IppsECCPPointState* pR, + const IppsECCPState* pECC, + BigNumNode* pList) +{ + /* test zero scalar or input point at Infinity */ + if( IsZero_BN(bnN) || ECCP_IsPointAtInfinity(pP) ) { + ECCP_SetPointToInfinity(pR); + return; + } + + /* + // scalar multiplication + */ + else { + Ipp8u* pScratchAligned = ECP_SCCMBUFF(pECC); + + BNU_CHUNK_T* pN = BN_NUMBER(bnN); + cpSize nsN = BN_SIZE(bnN); + /* scalar bitsize */ + int scalarBitSize = BITSIZE_BNU(pN, nsN); + /* optimal size of window */ + int w = cpECCP_OptimalWinSize(scalarBitSize); + /* number of table entries */ + int nPrecomputed = 1<>shift) & dmask; + + /* initialize result (ECP_FINITE_POINT|ECP_PROJECTIVE) */ + cpECCP_ScrambleGet(pR, coordSize, pScratchAligned+windowVal, nPrecomputed); + ECP_POINT_AFFINE(pR) = 0; + + /* initialize temporary T (ECP_PROJECTIVE) */ + ECP_POINT_AFFINE(&T) = 0; + + for(wPosition-=w; wPosition>=0; wPosition-=w) { + /* w times doubling */ + int k; + for(k=0; k>shift) & dmask; + + /* extract value from the pre-computed table */ + cpECCP_ScrambleGet(&T, coordSize, pScratchAligned+windowVal, nPrecomputed); + + /* and add it */ + ECCP_AddPoint(pR, &T, pR, pECC, pList); + } + } + } +} + + +void ECCP_MulBasePoint(const IppsBigNumState* pK, + IppsECCPPointState* pR, + const IppsECCPState* pECC, + BigNumNode* pList) +{ + ECCP_MulPoint(ECP_GENC(pECC), pK, pR, pECC, pList); +} + +/* +// ECCP_ProdPoint +// +// Point product +*/ +void ECCP_ProdPoint(const IppsECCPPointState* pP, + const IppsBigNumState* bnPscalar, + const IppsECCPPointState* pQ, + const IppsBigNumState* bnQscalar, + IppsECCPPointState* pR, + const IppsECCPState* pECC, + BigNumNode* pList) +{ + IppsECCPPointState T; + IppsECCPPointState U; + + ECP_POINT_X(&T) = cpBigNumListGet(&pList); + ECP_POINT_Y(&T) = cpBigNumListGet(&pList); + ECP_POINT_Z(&T) = cpBigNumListGet(&pList); + + ECP_POINT_X(&U) = cpBigNumListGet(&pList); + ECP_POINT_Y(&U) = cpBigNumListGet(&pList); + ECP_POINT_Z(&U) = cpBigNumListGet(&pList); + + ECCP_MulPoint(pP, bnPscalar, &T, (IppsECCPState*)pECC, pList); + ECCP_MulPoint(pQ, bnQscalar, &U, (IppsECCPState*)pECC, pList); + ECCP_AddPoint(&T, &U, pR, pECC, pList); +} diff --git a/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpeccppoint.h b/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpeccppoint.h new file mode 100644 index 0000000000..a72b0ea1ef --- /dev/null +++ b/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpeccppoint.h @@ -0,0 +1,60 @@ +/* +* Copyright (C) 2016 Intel Corporation. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in +* the documentation and/or other materials provided with the +* distribution. +* * Neither the name of Intel Corporation nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ + +#if !defined(_PCP_ECCPPOINT_H) +#define _PCP_ECCPPOINT_H + +#include "pcpeccp.h" + + +/* +// EC Point context +*/ +struct _cpECCPPoint { + IppCtxId idCtx; /* EC Point identifier */ + + IppsBigNumState* pX; /* projective X */ + IppsBigNumState* pY; /* Y */ + IppsBigNumState* pZ; /* Z coordinates */ + int affine; /* impotrant case Z=1 */ +}; + +/* +// Contetx Access Macros +*/ +#define ECP_POINT_ID(ctx) ((ctx)->idCtx) +#define ECP_POINT_X(ctx) ((ctx)->pX) +#define ECP_POINT_Y(ctx) ((ctx)->pY) +#define ECP_POINT_Z(ctx) ((ctx)->pZ) +#define ECP_POINT_AFFINE(ctx) ((ctx)->affine) +#define ECP_POINT_VALID_ID(ctx) (ECP_POINT_ID((ctx))==idCtxECCPPoint) + +#endif /* _PCP_ECCPPOINT_H */ diff --git a/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpeccppointca.c b/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpeccppointca.c new file mode 100644 index 0000000000..04dd7ca4a7 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpeccppointca.c @@ -0,0 +1,128 @@ +/* +* Copyright (C) 2016 Intel Corporation. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in +* the documentation and/or other materials provided with the +* distribution. +* * Neither the name of Intel Corporation nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ + +#include "owndefs.h" +#include "owncp.h" +#include "pcpeccppoint.h" + + +/*F* +// Name: ippsECCPPointGetSize +// +// Purpose: Returns size of EC Point context (bytes). +// +// Returns: Reason: +// ippStsNullPtrErr NULL == pSzie +// ippStsSizeErr 2>feBitSize +// ippStsNoErr no errors +// +// Parameters: +// feBitSize size of field element (bits) +// pSize pointer to the size of EC Point context +// +*F*/ +IPPFUN(IppStatus, ippsECCPPointGetSize, (int feBitSize, int* pSize)) +{ + /* test size's pointer */ + IPP_BAD_PTR1_RET(pSize); + + /* test size of field element */ + IPP_BADARG_RET((2>feBitSize), ippStsSizeErr); + + { + int bnSize; + ippsBigNumGetSize(BITS2WORD32_SIZE(feBitSize), &bnSize); + *pSize = sizeof(IppsECCPPointState) + + bnSize /* X coodinate */ + + bnSize /* Y coodinate */ + + bnSize /* Z coodinate */ + +(ALIGN_VAL-1); + } + return ippStsNoErr; +} + + +/*F* +// Name: ippsECCPPointInit +// +// Purpose: Init EC Point context. +// +// Returns: Reason: +// ippStsNullPtrErr NULL == pPoint +// ippStsSizeErr 2>feBitSize +// ippStsNoErr no errors +// +// Parameters: +// feBitSize size of field element (bits) +// pECC pointer to ECC context +// +*F*/ +IPPFUN(IppStatus, ippsECCPPointInit, (int feBitSize, IppsECCPPointState* pPoint)) +{ + /* test pEC pointer */ + IPP_BAD_PTR1_RET(pPoint); + + /* use aligned context */ + pPoint = (IppsECCPPointState*)( IPP_ALIGNED_PTR(pPoint, ALIGN_VAL) ); + + /* test size of field element */ + IPP_BADARG_RET((2>feBitSize), ippStsSizeErr); + + /* context ID */ + ECP_POINT_ID(pPoint) = idCtxECCPPoint; + + /* meaning: point was not set */ + ECP_POINT_AFFINE(pPoint) =-1; + + /* + // init other context fields + */ + { + Ipp8u* ptr = (Ipp8u*)pPoint; + int bnLen = BITS2WORD32_SIZE(feBitSize); + int bnSize; + ippsBigNumGetSize(bnLen, &bnSize); + + /* allocate coordinate buffers */ + ptr += sizeof(IppsECCPPointState); + ECP_POINT_X(pPoint) = (IppsBigNumState*)( IPP_ALIGNED_PTR(ptr,ALIGN_VAL) ); + ptr += bnSize; + ECP_POINT_Y(pPoint) = (IppsBigNumState*)( IPP_ALIGNED_PTR(ptr,ALIGN_VAL) ); + ptr += bnSize; + ECP_POINT_Z(pPoint) = (IppsBigNumState*)( IPP_ALIGNED_PTR(ptr,ALIGN_VAL) ); + + /* init coordinate buffers */ + ippsBigNumInit(bnLen, ECP_POINT_X(pPoint)); + ippsBigNumInit(bnLen, ECP_POINT_Y(pPoint)); + ippsBigNumInit(bnLen, ECP_POINT_Z(pPoint)); + } + return ippStsNoErr; +} diff --git a/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpeccppointopca.c b/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpeccppointopca.c new file mode 100644 index 0000000000..df81d08f93 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpeccppointopca.c @@ -0,0 +1,476 @@ +/* +* Copyright (C) 2016 Intel Corporation. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in +* the documentation and/or other materials provided with the +* distribution. +* * Neither the name of Intel Corporation nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ + +#include "owndefs.h" +#include "owncp.h" +#include "pcpeccppoint.h" +#include "pcpeccpmethod.h" +#include "pcpeccpmethodcom.h" + + +/*F* +// Name: ippsECCPSetPoint +// +// Purpose: Converts regular affine coordinates EC point (pX,pY) +// into internal presentation - montgomery projective. +// +// Returns: Reason: +// ippStsNullPtrErr NULL == pECC +// NULL == pPoint +// NULL == pX +// NULL == pY +// +// ippStsContextMatchErr illegal pECC->idCtx +// illegal pX->idCtx +// illegal pY->idCtx +// illegal pPoint->idCtx +// +// ippStsOutOfECErr point out-of EC +// +// ippStsNoErr no errors +// +// Parameters: +// pX pointer to the regular affine coordinate X +// pY pointer to the regular affine coordinate Y +// pPoint pointer to the EC Point context +// pECC pointer to the ECCP context +// +// Note: +// if B==0 and (x,y)=(0,y) then point at Infinity will be set up +// if B!=0 and (x,y)=(0,0) then point at Infinity will be set up +// else point with requested coordinates (x,y) wil be set up +// There are no check validation inside! +// +*F*/ +IPPFUN(IppStatus, ippsECCPSetPoint,(const IppsBigNumState* pX, + const IppsBigNumState* pY, + IppsECCPPointState* pPoint, + IppsECCPState* pECC)) +{ + /* test pECC */ + IPP_BAD_PTR1_RET(pECC); + /* use aligned EC context */ + pECC = (IppsECCPState*)( IPP_ALIGNED_PTR(pECC, ALIGN_VAL) ); + /* test ID */ + IPP_BADARG_RET(!ECP_VALID_ID(pECC), ippStsContextMatchErr); + + /* test pX and pY */ + IPP_BAD_PTR2_RET(pX,pY); + pX = (IppsBigNumState*)( IPP_ALIGNED_PTR(pX, ALIGN_VAL) ); + pY = (IppsBigNumState*)( IPP_ALIGNED_PTR(pY, ALIGN_VAL) ); + IPP_BADARG_RET(!BN_VALID_ID(pX), ippStsContextMatchErr); + IPP_BADARG_RET(!BN_VALID_ID(pY), ippStsContextMatchErr); + + /* test pPoint */ + IPP_BAD_PTR1_RET(pPoint); + pPoint = (IppsECCPPointState*)( IPP_ALIGNED_PTR(pPoint, ALIGN_VAL) ); + IPP_BADARG_RET(!ECP_POINT_VALID_ID(pPoint), ippStsContextMatchErr); + + /* set affine coordinates at Infinity */ + if( ( IsZero_BN(ECP_BENC(pECC)) && ECCP_IsPointAtAffineInfinity1(pX,pY)) || + (!IsZero_BN(ECP_BENC(pECC)) && ECCP_IsPointAtAffineInfinity0(pX,pY)) ) + ECCP_SetPointToInfinity(pPoint); + /* set point */ + else { + ECP_METHOD(pECC)->SetPointProjective(pX, pY, BN_ONE_REF(), pPoint, pECC); + } + + return ippStsNoErr; +} + + +/*F* +// Name: ippsECCPSetPointAtInfinity +// +// Purpose: Set point at Infinity +// +// Returns: Reason: +// ippStsNullPtrErr NULL == pECC +// NULL == pPoint +// +// ippStsContextMatchErr illegal pECC->idCtx +// illegal pPoint->idCtx +// +// ippStsNoErr no errors +// +// Parameters: +// pPoint pointer to the EC Point context +// pECC pointer to the ECCP context +// +*F*/ +IPPFUN(IppStatus, ippsECCPSetPointAtInfinity,(IppsECCPPointState* pPoint, + IppsECCPState* pECC)) +{ + /* test pECC */ + IPP_BAD_PTR1_RET(pECC); + /* use aligned EC context */ + pECC = (IppsECCPState*)( IPP_ALIGNED_PTR(pECC, ALIGN_VAL) ); + /* test ID */ + IPP_BADARG_RET(!ECP_VALID_ID(pECC), ippStsContextMatchErr); + + /* test pPoint */ + IPP_BAD_PTR1_RET(pPoint); + pPoint = (IppsECCPPointState*)( IPP_ALIGNED_PTR(pPoint, ALIGN_VAL) ); + IPP_BADARG_RET(!ECP_POINT_VALID_ID(pPoint), ippStsContextMatchErr); + + ECCP_SetPointToInfinity(pPoint); + return ippStsNoErr; +} + + +/*F* +// Name: ippsECCPGetPoint +// +// Purpose: Converts internal presentation EC point - montgomery projective +// into regular affine coordinates EC point (pX,pY) +// +// Returns: Reason: +// ippStsNullPtrErr NULL == pECC +// NULL == pPoint +// +// ippStsContextMatchErr illegal pECC->idCtx +// illegal pPoint->idCtx +// NULL != pX, illegal pX->idCtx +// NULL != pY, illegal pY->idCtx +// +// ippStsNoErr no errors +// +// Parameters: +// pX pointer to the regular affine coordinate X +// pY pointer to the regular affine coordinate Y +// pLength pointer to the length of coordinates +// pPoint pointer to the EC Point context +// pECC pointer to the ECCP context +// +*F*/ +IPPFUN(IppStatus, ippsECCPGetPoint,(IppsBigNumState* pX, + IppsBigNumState* pY, + const IppsECCPPointState* pPoint, + IppsECCPState* pECC)) +{ + /* test pECC */ + IPP_BAD_PTR1_RET(pECC); + /* use aligned EC context */ + pECC = (IppsECCPState*)( IPP_ALIGNED_PTR(pECC, ALIGN_VAL) ); + /* test ID */ + IPP_BADARG_RET(!ECP_VALID_ID(pECC), ippStsContextMatchErr); + + /* test source point */ + IPP_BAD_PTR1_RET(pPoint); + pPoint = (IppsECCPPointState*)( IPP_ALIGNED_PTR(pPoint, ALIGN_VAL) ); + IPP_BADARG_RET(!ECP_POINT_VALID_ID(pPoint), ippStsContextMatchErr); + + /* test pX and pY */ + if(pX) { + pX = (IppsBigNumState*)( IPP_ALIGNED_PTR(pX, ALIGN_VAL) ); + IPP_BADARG_RET(!BN_VALID_ID(pX), ippStsContextMatchErr); + } + if(pY) { + pY = (IppsBigNumState*)( IPP_ALIGNED_PTR(pY, ALIGN_VAL) ); + IPP_BADARG_RET(!BN_VALID_ID(pY), ippStsContextMatchErr); + } + + if( ECCP_IsPointAtInfinity(pPoint) ) { + if( IsZero_BN(ECP_BENC(pECC)) ) + ECCP_SetPointToAffineInfinity1(pX, pY); + else + ECCP_SetPointToAffineInfinity0(pX, pY); + } + else + ECP_METHOD(pECC)->GetPointAffine(pX, pY, pPoint, pECC, ECP_BNCTX(pECC)); + return ippStsNoErr; +} + + +/*F* +// Name: ippsECCPCheckPoint +// +// Purpose: Check EC point: +// - is point lie on EC +// - is point at infinity +// +// Returns: Reason: +// ippStsNullPtrErr NULL == pECC +// NULL == pP +// NULL == pResult +// +// ippStsContextMatchErr illegal pECC->idCtx +// illegal pP->idCtx +// +// ippStsNoErr no errors +// +// Parameters: +// pPoint pointer to the EC Point context +// pECC pointer to the ECCP context +// pResult pointer to the result: +// ippECValid +// ippECPointIsNotValid +// ippECPointIsAtInfinite +// +*F*/ +IPPFUN(IppStatus, ippsECCPCheckPoint,(const IppsECCPPointState* pP, + IppECResult* pResult, + IppsECCPState* pECC)) +{ + /* test pECC */ + IPP_BAD_PTR1_RET(pECC); + /* use aligned EC context */ + pECC = (IppsECCPState*)( IPP_ALIGNED_PTR(pECC, ALIGN_VAL) ); + /* test ID */ + IPP_BADARG_RET(!ECP_VALID_ID(pECC), ippStsContextMatchErr); + + /* test point */ + IPP_BAD_PTR1_RET(pP); + pP = (IppsECCPPointState*)( IPP_ALIGNED_PTR(pP, ALIGN_VAL) ); + IPP_BADARG_RET(!ECP_POINT_VALID_ID(pP), ippStsContextMatchErr); + + /* test pResult */ + IPP_BAD_PTR1_RET(pResult); + + if( ECCP_IsPointAtInfinity(pP) ) + *pResult = ippECPointIsAtInfinite; + else if( ECP_METHOD(pECC)->IsPointOnCurve(pP, pECC, ECP_BNCTX(pECC)) ) + *pResult = ippECValid; + else + *pResult = ippECPointIsNotValid; + + return ippStsNoErr; +} + + +/*F* +// Name: ippsECCPComparePoint +// +// Purpose: Compare two EC points +// +// Returns: Reason: +// ippStsNullPtrErr NULL == pECC +// NULL == pP +// NULL == pQ +// NULL == pResult +// +// ippStsContextMatchErr illegal pECC->idCtx +// illegal pP->idCtx +// illegal pQ->idCtx +// +// ippStsNoErr no errors +// +// Parameters: +// pP pointer to the EC Point context +// pQ pointer to the EC Point context +// pECC pointer to the ECCP context +// pResult pointer to the result: +// ippECPointIsEqual +// ippECPointIsNotEqual +// +*F*/ +IPPFUN(IppStatus, ippsECCPComparePoint,(const IppsECCPPointState* pP, + const IppsECCPPointState* pQ, + IppECResult* pResult, + IppsECCPState* pECC)) +{ + /* test pECC */ + IPP_BAD_PTR1_RET(pECC); + /* use aligned EC context */ + pECC = (IppsECCPState*)( IPP_ALIGNED_PTR(pECC, ALIGN_VAL) ); + /* test ID */ + IPP_BADARG_RET(!ECP_VALID_ID(pECC), ippStsContextMatchErr); + + /* test points */ + IPP_BAD_PTR2_RET(pP,pQ); + pP = (IppsECCPPointState*)( IPP_ALIGNED_PTR(pP, ALIGN_VAL) ); + pQ = (IppsECCPPointState*)( IPP_ALIGNED_PTR(pQ, ALIGN_VAL) ); + IPP_BADARG_RET(!ECP_POINT_VALID_ID(pP), ippStsContextMatchErr); + IPP_BADARG_RET(!ECP_POINT_VALID_ID(pQ), ippStsContextMatchErr); + + /* test pResult */ + IPP_BAD_PTR1_RET(pResult); + + *pResult = ECP_METHOD(pECC)->ComparePoint(pP, pQ, pECC, ECP_BNCTX(pECC))? ippECPointIsNotEqual : ippECPointIsEqual; + + return ippStsNoErr; +} + + +/*F* +// Name: ippsECCPNegativePoint +// +// Purpose: Perforn EC point operation: R = -P +// +// Returns: Reason: +// ippStsNullPtrErr NULL == pECC +// NULL == pP +// NULL == pR +// +// ippStsContextMatchErr illegal pECC->idCtx +// illegal pP->idCtx +// illegal pR->idCtx +// +// ippStsNoErr no errors +// +// Parameters: +// pP pointer to the source EC Point context +// pR pointer to the resultant EC Point context +// pECC pointer to the ECCP context +// +*F*/ +IPPFUN(IppStatus, ippsECCPNegativePoint, (const IppsECCPPointState* pP, + IppsECCPPointState* pR, + IppsECCPState* pECC)) +{ + /* test pECC */ + IPP_BAD_PTR1_RET(pECC); + /* use aligned EC context */ + pECC = (IppsECCPState*)( IPP_ALIGNED_PTR(pECC, ALIGN_VAL) ); + /* test ID */ + IPP_BADARG_RET(!ECP_VALID_ID(pECC), ippStsContextMatchErr); + + /* test points */ + IPP_BAD_PTR2_RET(pP,pR); + pP = (IppsECCPPointState*)( IPP_ALIGNED_PTR(pP, ALIGN_VAL) ); + pR = (IppsECCPPointState*)( IPP_ALIGNED_PTR(pR, ALIGN_VAL) ); + IPP_BADARG_RET(!ECP_POINT_VALID_ID(pP), ippStsContextMatchErr); + IPP_BADARG_RET(!ECP_POINT_VALID_ID(pR), ippStsContextMatchErr); + + ECP_METHOD(pECC)->NegPoint(pP, pR, pECC); + + return ippStsNoErr; +} + + +/*F* +// Name: ippsECCPAddPoint +// +// Purpose: Perforn EC point operation: R = P+Q +// +// Returns: Reason: +// ippStsNullPtrErr NULL == pECC +// NULL == pP +// NULL == pQ +// NULL == pR +// +// ippStsContextMatchErr illegal pECC->idCtx +// illegal pP->idCtx +// illegal pQ->idCtx +// illegal pR->idCtx +// +// ippStsNoErr no errors +// +// Parameters: +// pP pointer to the source EC Point context +// pQ pointer to the source EC Point context +// pR pointer to the resultant EC Point context +// pECC pointer to the ECCP context +// +*F*/ +IPPFUN(IppStatus, ippsECCPAddPoint,(const IppsECCPPointState* pP, + const IppsECCPPointState* pQ, + IppsECCPPointState* pR, + IppsECCPState* pECC)) +{ + /* test pECC */ + IPP_BAD_PTR1_RET(pECC); + /* use aligned EC context */ + pECC = (IppsECCPState*)( IPP_ALIGNED_PTR(pECC, ALIGN_VAL) ); + /* test ID */ + IPP_BADARG_RET(!ECP_VALID_ID(pECC), ippStsContextMatchErr); + + /* test points */ + IPP_BAD_PTR3_RET(pP,pQ,pR); + pP = (IppsECCPPointState*)( IPP_ALIGNED_PTR(pP, ALIGN_VAL) ); + pQ = (IppsECCPPointState*)( IPP_ALIGNED_PTR(pQ, ALIGN_VAL) ); + pR = (IppsECCPPointState*)( IPP_ALIGNED_PTR(pR, ALIGN_VAL) ); + IPP_BADARG_RET(!ECP_POINT_VALID_ID(pP), ippStsContextMatchErr); + IPP_BADARG_RET(!ECP_POINT_VALID_ID(pQ), ippStsContextMatchErr); + IPP_BADARG_RET(!ECP_POINT_VALID_ID(pR), ippStsContextMatchErr); + + if(pP==pQ) + ECP_METHOD(pECC)->DblPoint(pP, pR, pECC, ECP_BNCTX(pECC)); + else + ECP_METHOD(pECC)->AddPoint(pP, pQ, pR, pECC, ECP_BNCTX(pECC)); + + return ippStsNoErr; +} + + +/*F* +// Name: ippsECCPMulPointScalar +// +// Purpose: Perforn EC point operation: R = k*P +// +// Returns: Reason: +// ippStsNullPtrErr NULL == pECC +// NULL == pP +// NULL == pK +// NULL == pR +// +// ippStsContextMatchErr illegal pECC->idCtx +// illegal pP->idCtx +// illegal pK->idCtx +// illegal pR->idCtx +// +// ippStsNoErr no errors +// +// Parameters: +// pP pointer to the source EC Point context +// pK pointer to the source BigNum multiplier context +// pR pointer to the resultant EC Point context +// pECC pointer to the ECCP context +// +*F*/ +IPPFUN(IppStatus, ippsECCPMulPointScalar,(const IppsECCPPointState* pP, + const IppsBigNumState* pK, + IppsECCPPointState* pR, + IppsECCPState* pECC)) +{ + /* test pECC */ + IPP_BAD_PTR1_RET(pECC); + /* use aligned EC context */ + pECC = (IppsECCPState*)( IPP_ALIGNED_PTR(pECC, ALIGN_VAL) ); + /* test ID */ + IPP_BADARG_RET(!ECP_VALID_ID(pECC), ippStsContextMatchErr); + + /* test points */ + IPP_BAD_PTR2_RET(pP,pR); + pP = (IppsECCPPointState*)( IPP_ALIGNED_PTR(pP, ALIGN_VAL) ); + pR = (IppsECCPPointState*)( IPP_ALIGNED_PTR(pR, ALIGN_VAL) ); + IPP_BADARG_RET(!ECP_POINT_VALID_ID(pP), ippStsContextMatchErr); + IPP_BADARG_RET(!ECP_POINT_VALID_ID(pR), ippStsContextMatchErr); + + /* test scalar */ + IPP_BAD_PTR1_RET(pK); + pK = (IppsBigNumState*)( IPP_ALIGNED_PTR(pK, ALIGN_VAL) ); + IPP_BADARG_RET(!BN_VALID_ID(pK), ippStsContextMatchErr); + + ECP_METHOD(pECC)->MulPoint(pP, pK, pR, pECC, ECP_BNCTX(pECC)); + + return ippStsNoErr; +} diff --git a/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpeccppublickeyca.c b/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpeccppublickeyca.c new file mode 100644 index 0000000000..42b2515cf4 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpeccppublickeyca.c @@ -0,0 +1,89 @@ +/* +* Copyright (C) 2016 Intel Corporation. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in +* the documentation and/or other materials provided with the +* distribution. +* * Neither the name of Intel Corporation nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ + +#include "owndefs.h" +#include "owncp.h" +#include "pcpeccppoint.h" +#include "pcpeccpmethod.h" +#include "pcpeccpmethodcom.h" + + +/*F* +// Name: ippsECCPPublicKey +// +// Purpose: Calculate Public Key +// +// Returns: Reason: +// ippStsNullPtrErr NULL == pECC +// NULL == pPrivate +// NULL == pPublic +// +// ippStsContextMatchErr illegal pECC->idCtx +// illegal pPrivate->idCtx +// illegal pPublic->idCtx +// +// ippStsIvalidPrivateKey !(0 < pPrivate < order) +// +// ippStsNoErr no errors +// +// Parameters: +// pPrivate pointer to the private key +// pPublic pointer to the resultant public key +// pECC pointer to the ECCP context +// +*F*/ +IPPFUN(IppStatus, ippsECCPPublicKey, (const IppsBigNumState* pPrivate, + IppsECCPPointState* pPublic, + IppsECCPState* pECC)) +{ + /* test pECC */ + IPP_BAD_PTR1_RET(pECC); + /* use aligned EC context */ + pECC = (IppsECCPState*)( IPP_ALIGNED_PTR(pECC, ALIGN_VAL) ); + /* test ID */ + IPP_BADARG_RET(!ECP_VALID_ID(pECC), ippStsContextMatchErr); + + /* test public key */ + IPP_BAD_PTR1_RET(pPublic); + pPublic = (IppsECCPPointState*)( IPP_ALIGNED_PTR(pPublic, ALIGN_VAL) ); + IPP_BADARG_RET(!ECP_POINT_VALID_ID(pPublic), ippStsContextMatchErr); + + /* test private keys */ + IPP_BAD_PTR1_RET(pPrivate); + pPrivate = (IppsBigNumState*)( IPP_ALIGNED_PTR(pPrivate, ALIGN_VAL) ); + IPP_BADARG_RET(!BN_VALID_ID(pPrivate), ippStsContextMatchErr); + IPP_BADARG_RET(!((0cpBN_cmp(pPrivate, ECP_ORDER(pECC))) ), ippStsIvalidPrivateKey); + + /* calculates public key */ + ECP_METHOD(pECC)->MulBasePoint(pPrivate, pPublic, pECC, ECP_BNCTX(pECC)); + + return ippStsNoErr; +} diff --git a/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpeccpsecretdhca.c b/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpeccpsecretdhca.c new file mode 100644 index 0000000000..3fec05a086 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpeccpsecretdhca.c @@ -0,0 +1,116 @@ +/* +* Copyright (C) 2016 Intel Corporation. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in +* the documentation and/or other materials provided with the +* distribution. +* * Neither the name of Intel Corporation nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ + +#include "owndefs.h" +#include "owncp.h" +#include "pcpeccp.h" +#include "pcpeccppoint.h" +#include "pcpeccpmethod.h" +#include "pcpeccpmethodcom.h" + + +/*F* +// Name: ippsECCPSharedSecretDH +// +// Purpose: Shared Secret Value Derivation +// (Diffie-Hellman version). +// +// Returns: Reason: +// ippStsNullPtrErr NULL == pECC +// NULL == pPrivateA +// NULL == pPublicB +// NULL == pShare +// +// ippStsContextMatchErr illegal pECC->idCtx +// illegal pPrivateA->idCtx +// illegal pPublicB->idCtx +// illegal pShare->idCtx +// +// ippStsRangeErr not enough room for share key +// +// ippStsShareKeyErr (infinity) => z +// +// ippStsNoErr no errors +// +// Parameters: +// pPrivateA pointer to own private key +// pPublicB pointer to alien public key +// pShare pointer to the shareds secret value +// pECC pointer to the ECCP context +// +*F*/ +IPPFUN(IppStatus, ippsECCPSharedSecretDH,(const IppsBigNumState* pPrivateA, + const IppsECCPPointState* pPublicB, + IppsBigNumState* pShare, + IppsECCPState* pECC)) +{ + /* test pECC */ + IPP_BAD_PTR1_RET(pECC); + /* use aligned EC context */ + pECC = (IppsECCPState*)( IPP_ALIGNED_PTR(pECC, ALIGN_VAL) ); + /* test ID */ + IPP_BADARG_RET(!ECP_VALID_ID(pECC), ippStsContextMatchErr); + + /* test private (own) key */ + IPP_BAD_PTR1_RET(pPrivateA); + pPrivateA = (IppsBigNumState*)( IPP_ALIGNED_PTR(pPrivateA, ALIGN_VAL) ); + IPP_BADARG_RET(!BN_VALID_ID(pPrivateA), ippStsContextMatchErr); + + /* test public (other party) key */ + IPP_BAD_PTR1_RET(pPublicB); + pPublicB = (IppsECCPPointState*)( IPP_ALIGNED_PTR(pPublicB, ALIGN_VAL) ); + IPP_BADARG_RET(!ECP_POINT_VALID_ID(pPublicB), ippStsContextMatchErr); + + /* test share secret value */ + IPP_BAD_PTR1_RET(pShare); + pShare = (IppsBigNumState*)( IPP_ALIGNED_PTR(pShare, ALIGN_VAL) ); + IPP_BADARG_RET(!BN_VALID_ID(pShare), ippStsContextMatchErr); + IPP_BADARG_RET((BN_ROOM(pShare)*BITSIZE(BNU_CHUNK_T)MulPoint(pPublicB, pPrivateA, &Tmp, pECC, pList); + + /* test: Tmp ~ point at Infinity */ + if( ECCP_IsPointAtInfinity(&Tmp) ) + return ippStsShareKeyErr; + else { + ECP_METHOD(pECC)->GetPointAffine(pShare, NULL, &Tmp, pECC, pList); + return ippStsNoErr; + } + } +} diff --git a/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpeccpsetkeyca.c b/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpeccpsetkeyca.c new file mode 100644 index 0000000000..c1644c06ae --- /dev/null +++ b/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpeccpsetkeyca.c @@ -0,0 +1,105 @@ +/* +* Copyright (C) 2016 Intel Corporation. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in +* the documentation and/or other materials provided with the +* distribution. +* * Neither the name of Intel Corporation nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ + +#include "owndefs.h" +#include "owncp.h" +#include "pcpeccp.h" +#include "pcpeccppoint.h" +#include "pcpeccpmethod.h" +#include "pcpeccpmethodcom.h" + + +/*F* +// Name: ippsECCPSetKeyPair +// +// Purpose: Generate (private,public) Key Pair +// +// Returns: Reason: +// ippStsNullPtrErr NULL == pECC +// NULL == pPrivate +// NULL == pPublic +// +// ippStsContextMatchErr illegal pECC->idCtx +// illegal pPrivate->idCtx +// illegal pPublic->idCtx +// +// ippStsNoErr no errors +// +// Parameters: +// pPrivate pointer to the private key +// pPublic pointer to the public key +// regular flag regular/ephemeral keys +// pECC pointer to the ECCP context +// +*F*/ +IPPFUN(IppStatus, ippsECCPSetKeyPair, (const IppsBigNumState* pPrivate, const IppsECCPPointState* pPublic, + IppBool regular, + IppsECCPState* pECC)) +{ + /* test pECC */ + IPP_BAD_PTR1_RET(pECC); + /* use aligned EC context */ + pECC = (IppsECCPState*)( IPP_ALIGNED_PTR(pECC, ALIGN_VAL) ); + /* test ID */ + IPP_BADARG_RET(!ECP_VALID_ID(pECC), ippStsContextMatchErr); + + { + IppsBigNumState* targetPrivate; + IppsECCPPointState* targetPublic; + + if( regular ) { + targetPrivate = ECP_PRIVATE(pECC); + targetPublic = ECP_PUBLIC(pECC); + } + else { + targetPrivate = ECP_PRIVATE_E(pECC); + targetPublic = ECP_PUBLIC_E(pECC); + } + + /* set up private key request */ + if( pPrivate ) { + pPrivate = (IppsBigNumState*)( IPP_ALIGNED_PTR(pPrivate, ALIGN_VAL) ); + IPP_BADARG_RET(!BN_VALID_ID(pPrivate), ippStsContextMatchErr); + ippsSet_BN(ippBigNumPOS, BN_SIZE32(pPrivate), (Ipp32u*)BN_NUMBER(pPrivate), targetPrivate); + } + + /* set up public key request */ + if( pPublic ) { + pPublic = (IppsECCPPointState*)( IPP_ALIGNED_PTR(pPublic, ALIGN_VAL) ); + IPP_BADARG_RET(!ECP_POINT_VALID_ID(pPublic), ippStsContextMatchErr); + + ECP_METHOD(pECC)->GetPointAffine(ECP_POINT_X(targetPublic), ECP_POINT_Y(targetPublic), pPublic, pECC, ECP_BNCTX(pECC)); + ECP_METHOD(pECC)->SetPointAffine(ECP_POINT_X(targetPublic), ECP_POINT_Y(targetPublic), targetPublic, pECC); + } + + return ippStsNoErr; + } +} diff --git a/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpeccpsigndsaca.c b/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpeccpsigndsaca.c new file mode 100644 index 0000000000..bcda1d76ad --- /dev/null +++ b/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpeccpsigndsaca.c @@ -0,0 +1,149 @@ +/* +* Copyright (C) 2016 Intel Corporation. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in +* the documentation and/or other materials provided with the +* distribution. +* * Neither the name of Intel Corporation nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ + +#include "owndefs.h" +#include "owncp.h" +#include "pcpeccp.h" +#include "pcpeccppoint.h" +#include "pcpeccpmethod.h" +#include "pcpeccpmethodcom.h" + + +/*F* +// Name: ippsECCPSignDSA +// +// Purpose: Signing of message representative. +// (DSA version). +// +// Returns: Reason: +// ippStsNullPtrErr NULL == pECC +// NULL == pMsgDigest +// NULL == pPrivate +// NULL == pSignX +// NULL == pSignY +// +// ippStsContextMatchErr illegal pECC->idCtx +// illegal pMsgDigest->idCtx +// illegal pPrivate->idCtx +// illegal pSignX->idCtx +// illegal pSignY->idCtx +// +// ippStsMessageErr MsgDigest >= order +// +// ippStsRangeErr not enough room for: +// signX +// signY +// +// ippStsEphemeralKeyErr (0==signX) || (0==signY) +// +// ippStsNoErr no errors +// +// Parameters: +// pMsgDigest pointer to the message representative to be signed +// pPrivate pointer to the regular private key +// pSignX,pSignY pointer to the signature +// pECC pointer to the ECCP context +// +// Note: +// - ephemeral key pair extracted from pECC and +// must be generated and before ippsECCPDSASign() usage +// - ephemeral key pair destroy before exit +// +*F*/ +IPPFUN(IppStatus, ippsECCPSignDSA,(const IppsBigNumState* pMsgDigest, + const IppsBigNumState* pPrivate, + IppsBigNumState* pSignX, IppsBigNumState* pSignY, + IppsECCPState* pECC)) +{ + /* test pECC */ + IPP_BAD_PTR1_RET(pECC); + /* use aligned EC context */ + pECC = (IppsECCPState*)( IPP_ALIGNED_PTR(pECC, ALIGN_VAL) ); + IPP_BADARG_RET(!ECP_VALID_ID(pECC), ippStsContextMatchErr); + + /* test private key*/ + IPP_BAD_PTR1_RET(pPrivate); + pPrivate = (IppsBigNumState*)( IPP_ALIGNED_PTR(pPrivate, ALIGN_VAL) ); + IPP_BADARG_RET(!BN_VALID_ID(pPrivate), ippStsContextMatchErr); + + /* test message representative */ + IPP_BAD_PTR1_RET(pMsgDigest); + pMsgDigest = (IppsBigNumState*)( IPP_ALIGNED_PTR(pMsgDigest, ALIGN_VAL) ); + IPP_BADARG_RET(!BN_VALID_ID(pMsgDigest), ippStsContextMatchErr); + IPP_BADARG_RET((0<=cpBN_cmp(pMsgDigest, ECP_ORDER(pECC))), ippStsMessageErr); + + /* test signature */ + IPP_BAD_PTR2_RET(pSignX,pSignY); + pSignX = (IppsBigNumState*)( IPP_ALIGNED_PTR(pSignX, ALIGN_VAL) ); + pSignY = (IppsBigNumState*)( IPP_ALIGNED_PTR(pSignY, ALIGN_VAL) ); + IPP_BADARG_RET(!BN_VALID_ID(pSignX), ippStsContextMatchErr); + IPP_BADARG_RET(!BN_VALID_ID(pSignY), ippStsContextMatchErr); + IPP_BADARG_RET((BN_ROOM(pSignX)*BITSIZE(BNU_CHUNK_T)GetPointAffine(pTmp, NULL, ECP_PUBLIC_E(pECC), pECC, pList); + + /* + // compute + // signX = eph_pub_x (mod order) + */ + PMA_mod(pSignX, pTmp, pOrder); + if( !IsZero_BN(pSignX) ) { + + IppsBigNumState* pEncMsg = cpBigNumListGet(&pList); + IppsBigNumState* pEncSignX = cpBigNumListGet(&pList); + PMA_enc(pEncMsg, (IppsBigNumState*)pMsgDigest, rMont); + PMA_enc(pEncSignX, pSignX, rMont); + + /* + // compute + // signY = (1/eph_private)*(pMsgDigest + private*signX) (mod order) + */ + PMA_inv(pSignY, ECP_PRIVATE_E(pECC), pOrder); + PMA_enc(ECP_PRIVATE_E(pECC), pPrivate, rMont); + PMA_mule(pTmp, ECP_PRIVATE_E(pECC), pEncSignX, rMont); + PMA_add(pTmp, pTmp, pEncMsg, pOrder); + PMA_mule(pSignY, pSignY, pTmp, rMont); + if( !IsZero_BN(pSignY) ) + return ippStsNoErr; + } + + return ippStsEphemeralKeyErr; + } +} diff --git a/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpeccpsscm.c b/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpeccpsscm.c new file mode 100644 index 0000000000..32ab537cf1 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpeccpsscm.c @@ -0,0 +1,161 @@ +/* +* Copyright (C) 2016 Intel Corporation. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in +* the documentation and/or other materials provided with the +* distribution. +* * Neither the name of Intel Corporation nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ + +#include "owndefs.h" +#include "owncp.h" +#include "pcpbn.h" +#include "pcpeccppoint.h" + + +#define LOG2_CACHE_LINE_SIZE (LOG_CACHE_LINE_SIZE) + +static int div_upper(int a, int d) +{ return (a+d-1)/d; } + +static int getNumOperations(int bitsize, int w) +{ + int n_overhead = (1<=n_opt) break; + w_opt = w_trial; + n_opt = n_trial; + } + return w_opt; +#undef LIMIT +} + +int cpECCP_ConvertRepresentation(BNU_CHUNK_T* pInput, int inpBits, int w) +{ + Ipp32u* pR = (Ipp32u*)pInput; + Ipp16u* pR16 = (Ipp16u*)pInput; + + int outBits = 0; + Ipp32u base = (BNU_CHUNK_T)1<>digitShift) &digitMask; + + Ipp32u delta = (base-digit) & ~digitMask; + delta <<= digitShift; + cpDec_BNU32((Ipp32u*)(pR16+chunkIdx), (Ipp32u*)(pR16+chunkIdx), (2*nsR-chunkIdx+1)/2, delta); + + inpBits = BITSIZE_BNU32(pR, nsR); + outBits += w; + } + + return outBits; +} + +/* +// cpsScramblePut/cpsScrambleGet +// stores to/retrieves from pScrambleEntry position +// pre-computed data if fixed window method is used +*/ +void cpECCP_ScramblePut(Ipp8u* pScrambleEntry, int proposity, + const IppsECCPPointState* pPoint, cpSize coordLen) +{ + int i; + Ipp8u* pCoord; + + BNU_CHUNK_T* pX = BN_NUMBER(ECP_POINT_X(pPoint)); + BNU_CHUNK_T* pY = BN_NUMBER(ECP_POINT_Y(pPoint)); + BNU_CHUNK_T* pZ = BN_NUMBER(ECP_POINT_Z(pPoint)); + int coordSize = coordLen*sizeof(BNU_CHUNK_T); + + ZEXPAND_BNU(pX, BN_SIZE(ECP_POINT_X(pPoint)), coordLen); + ZEXPAND_BNU(pY, BN_SIZE(ECP_POINT_Y(pPoint)), coordLen); + ZEXPAND_BNU(pZ, BN_SIZE(ECP_POINT_Z(pPoint)), coordLen); + + pCoord = (Ipp8u*)pX; + for(i=0; iidCtx +// illegal pMsgDigest->idCtx +// illegal pSignX->idCtx +// illegal pSignY->idCtx +// +// ippStsMessageErr MsgDigest >= order +// +// ippStsNoErr no errors +// +// Parameters: +// pMsgDigest pointer to the message representative to be signed +// pSignX,pSignY pointer to the signature +// pResult pointer to the result: ippECValid/ippECInvalidSignature +// pECC pointer to the ECCP context +// +// Note: +// - signer's key must be set up in ECCP context +// before ippsECCPVerifyDSA() usage +// +*F*/ +IPPFUN(IppStatus, ippsECCPVerifyDSA,(const IppsBigNumState* pMsgDigest, + const IppsBigNumState* pSignX, const IppsBigNumState* pSignY, + IppECResult* pResult, + IppsECCPState* pECC)) +{ + IppsMontState* rMont; + + /* test pECC */ + IPP_BAD_PTR1_RET(pECC); + /* use aligned EC context */ + pECC = (IppsECCPState*)( IPP_ALIGNED_PTR(pECC, ALIGN_VAL) ); + IPP_BADARG_RET(!ECP_VALID_ID(pECC), ippStsContextMatchErr); + + /* test message representative */ + IPP_BAD_PTR1_RET(pMsgDigest); + pMsgDigest = (IppsBigNumState*)( IPP_ALIGNED_PTR(pMsgDigest, ALIGN_VAL) ); + IPP_BADARG_RET(!BN_VALID_ID(pMsgDigest), ippStsContextMatchErr); + rMont = ECP_RMONT(pECC); + IPP_BADARG_RET((0<=cpBN_cmp(pMsgDigest, ECP_ORDER(pECC))), ippStsMessageErr); + + /* test result */ + IPP_BAD_PTR1_RET(pResult); + + /* test signature */ + IPP_BAD_PTR2_RET(pSignX,pSignY); + pSignX = (IppsBigNumState*)( IPP_ALIGNED_PTR(pSignX, ALIGN_VAL) ); + pSignY = (IppsBigNumState*)( IPP_ALIGNED_PTR(pSignY, ALIGN_VAL) ); + IPP_BADARG_RET(!BN_VALID_ID(pSignX), ippStsContextMatchErr); + IPP_BADARG_RET(!BN_VALID_ID(pSignY), ippStsContextMatchErr); + + /* test signature value */ + if( (0>cpBN_tst(pSignX)) || (0>cpBN_tst(pSignY)) || + (0<=cpBN_cmp(pSignX, ECP_ORDER(pECC))) || + (0<=cpBN_cmp(pSignY, ECP_ORDER(pECC))) ) { + *pResult = ippECInvalidSignature; + return ippStsNoErr; + } + + /* validate signature */ + else { + IppsECCPPointState P1; + + BigNumNode* pList = ECP_BNCTX(pECC); + IppsBigNumState* pH1 = cpBigNumListGet(&pList); + IppsBigNumState* pH2 = cpBigNumListGet(&pList); + IppsBigNumState* pOrder = cpBigNumListGet(&pList); + BN_Set(MNT_MODULUS(rMont), MNT_SIZE(rMont), pOrder); + + ECP_POINT_X(&P1) = cpBigNumListGet(&pList); + ECP_POINT_Y(&P1) = cpBigNumListGet(&pList); + ECP_POINT_Z(&P1) = cpBigNumListGet(&pList); + + PMA_inv(pH1, (IppsBigNumState*)pSignY, pOrder);/* h = 1/signY (mod order) */ + PMA_enc(pH1, pH1, rMont); + PMA_mule(pH2, (IppsBigNumState*)pSignX, pH1, rMont); /* h2 = pSignX * h (mod order) */ + PMA_mule(pH1, (IppsBigNumState*)pMsgDigest, pH1, rMont); /* h1 = pMsgDigest * h (mod order) */ + + /* compute h1*BasePoint + h2*publicKey */ + ECP_METHOD(pECC)->ProdPoint(ECP_GENC(pECC), pH1, + ECP_PUBLIC(pECC), pH2, + &P1, pECC, pList); + + if( ECCP_IsPointAtInfinity(&P1) ) { + *pResult = ippECInvalidSignature; + return ippStsNoErr; + } + /* extract X component */ + ECP_METHOD(pECC)->GetPointAffine(pH1, NULL, &P1, pECC, pList); + /* compare with signX */ + PMA_mod(pH1, pH1, pOrder); + *pResult = (0==cpBN_cmp(pH1, pSignX))? ippECValid : ippECInvalidSignature; + return ippStsNoErr; + } +} diff --git a/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcphash.h b/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcphash.h new file mode 100644 index 0000000000..669f3e3467 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcphash.h @@ -0,0 +1,159 @@ +/* +* Copyright (C) 2016 Intel Corporation. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in +* the documentation and/or other materials provided with the +* distribution. +* * Neither the name of Intel Corporation nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ + +#if !defined(_PCP_HASH_H) +#define _PCP_HASH_H + + +/* messge block size */ +#define MBS_SHA1 (64) /* SHA1 message block size (bytes) */ +#define MBS_SHA256 (64) /* SHA256 and SHA224 */ +#define MBS_SHA224 (64) /* SHA224 */ +#define MBS_SHA512 (128) /* SHA512 and SHA384 */ +#define MBS_SHA384 (128) /* SHA384 */ +#define MBS_MD5 (64) /* MD5 */ +#define MBS_HASH_MAX (MBS_SHA512) /* max message block size (bytes) */ +#define MAX_HASH_SIZE (IPP_SHA512_DIGEST_BITSIZE/8) /* hash of the max len (bytes) */ + +/* +// Useful macros +*/ +#define SHS_ID(stt) ((stt)->idCtx) +#define SHS_INDX(stt) ((stt)->index) +#define SHS_LENL(stt) ((stt)->msgLenLo) +#define SHS_LENH(stt) ((stt)->msgLenHi) +#define SHS_BUFF(stt) ((stt)->msgBuffer) +#define SHS_HASH(stt) ((stt)->msgHash) + +/* initial hash values */ +extern const Ipp32u SHA1_IV[]; +extern const Ipp32u SHA256_IV[]; +extern const Ipp32u SHA224_IV[]; +extern const Ipp64u SHA512_IV[]; +extern const Ipp64u SHA384_IV[]; +extern const Ipp32u MD5_IV[]; +extern const Ipp64u SHA512_224_IV[]; +extern const Ipp64u SHA512_256_IV[]; + +/* hash alg additive constants */ +extern __ALIGN16 const Ipp32u SHA1_cnt[]; +extern __ALIGN16 const Ipp32u SHA256_cnt[]; +extern __ALIGN16 const Ipp64u SHA512_cnt[]; +extern __ALIGN16 const Ipp32u MD5_cnt[]; + + +/* hash alg attributes */ +typedef struct _cpHashAttr { + int ivSize; /* attr: length (bytes) of initial value cpHashIV */ + int hashSize; /* attr: length (bytes) of hash */ + int msgBlkSize; /* attr: length (bytes) of message block */ + int msgLenRepSize; /* attr: length (bytes) in representation of processed message length */ + Ipp64u msgLenMax[2]; /* attr: max message length (bytes) (low high) */ +} cpHashAttr; + + +/* hash value */ +typedef Ipp64u cpHash[IPP_SHA512_DIGEST_BITSIZE/BITSIZE(Ipp64u)]; /* hash value */ + +/* hash update function */ +typedef void (*cpHashProc)(void* pHash, const Ipp8u* pMsg, int msgLen, const void* pParam); + + + +/* hash context */ +struct _cpHashCtx { + IppCtxId idCtx; /* hash identifier */ + IppHashAlgId algID; /* hash algorithm ID */ + Ipp64u msgLenLo; /* length (bytes) of processed message: */ + Ipp64u msgLenHi; /* low and high parts */ + cpHashProc hashProc; /* hash update function */ + const void* pParam; /* optional hashProc's parameter */ + cpHash hashVal; /* intermadiate has value */ + int buffOffset; /* current buffer position */ + Ipp8u msgBuffer[MBS_HASH_MAX]; /* buffer */ +}; + +/* accessors */ +#define HASH_CTX_ID(stt) ((stt)->idCtx) +#define HASH_ALG_ID(stt) ((stt)->algID) +#define HASH_LENLO(stt) ((stt)->msgLenLo) +#define HASH_LENHI(stt) ((stt)->msgLenHi) +#define HASH_FUNC(stt) ((stt)->hashProc) +#define HASH_FUNC_PAR(stt) ((stt)->pParam) +#define HASH_VALUE(stt) ((stt)->hashVal) +#define HAHS_BUFFIDX(stt) ((stt)->buffOffset) +#define HASH_BUFF(stt) ((stt)->msgBuffer) +#define HASH_VALID_ID(pCtx) (HASH_CTX_ID((pCtx))==idCtxHash) + + +/* hash alg opt argument */ +extern const void* cpHashProcFuncOpt[]; + +/* enabled hash alg */ +extern const IppHashAlgId cpEnabledHashAlgID[]; + +/* hash alg IV (init value) */ +extern const Ipp8u* cpHashIV[]; + +/* hash alg attribute DB */ +extern const cpHashAttr cpHashAlgAttr[]; + +/* IV size helper */ +__INLINE int cpHashIvSize(IppHashAlgId algID) +{ return cpHashAlgAttr[algID].ivSize; } + +/* hash size helper */ +__INLINE int cpHashSize(IppHashAlgId algID) +{ return cpHashAlgAttr[algID].hashSize; } + +/* message block size helper */ +__INLINE int cpHashMBS(IppHashAlgId algID) +{ return cpHashAlgAttr[algID].msgBlkSize; } + +/* maps algID into enabled IppHashAlgId value */ +__INLINE IppHashAlgId cpValidHashAlg(IppHashAlgId algID) +{ + /* maps algID into the valid range */ + algID = (((int)ippHashAlg_Unknown < (int)algID) && ((int)algID < (int)ippHashAlg_MaxNo))? algID : ippHashAlg_Unknown; + return cpEnabledHashAlgID[algID]; +} + + +/* processing functions */ +void UpdateSHA1 (void* pHash, const Ipp8u* mblk, int mlen, const void* pParam); +void UpdateSHA256(void* pHash, const Ipp8u* mblk, int mlen, const void* pParam); +void UpdateSHA512(void* pHash, const Ipp8u* mblk, int mlen, const void* pParam); +void UpdateMD5 (void* pHash, const Ipp8u* mblk, int mlen, const void* pParam); + +/* general methods */ +int cpReInitHash(IppsHashState* pCtx, IppHashAlgId algID); + +#endif /* _PCP_HASH_H */ diff --git a/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcphashca.c b/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcphashca.c new file mode 100644 index 0000000000..47b2a8b670 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcphashca.c @@ -0,0 +1,513 @@ +/* +* Copyright (C) 2016 Intel Corporation. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in +* the documentation and/or other materials provided with the +* distribution. +* * Neither the name of Intel Corporation nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ + +#include "owndefs.h" +#include "owncp.h" +#include "pcphash.h" +#include "pcptool.h" + + +/*F* +// Name: ippsHashGetSize +// +// Purpose: Returns size (bytes) of IppsHashState state. +// +// Returns: Reason: +// ippStsNullPtrErr pSize == NULL +// ippStsNoErr no errors +// +// Parameters: +// pSize pointer to state size +// +*F*/ +IPPFUN(IppStatus, ippsHashGetSize,(int* pSize)) +{ + /* test pointers */ + IPP_BAD_PTR1_RET(pSize); + + *pSize = sizeof(IppsHashState); + return ippStsNoErr; +} + + +/*F* +// Name: ippsHashInit +// +// Purpose: Init Hash state. +// +// Returns: Reason: +// ippStsNullPtrErr pState == NULL +// ippStsNotSupportedModeErr if algID is not match to supported hash alg +// ippStsNoErr no errors +// +// Parameters: +// pCtx pointer to the Hash state +// algID hash alg ID +// +*F*/ +int cpReInitHash(IppsHashState* pCtx, IppHashAlgId algID) +{ + int hashIvSize = cpHashIvSize(algID); + const Ipp8u* iv = cpHashIV[algID]; + + HASH_LENLO(pCtx) = CONST_64(0); + HASH_LENHI(pCtx) = CONST_64(0); + HAHS_BUFFIDX(pCtx) = 0; + CopyBlock(iv, HASH_VALUE(pCtx), hashIvSize); + + return hashIvSize; +} + +/* +// hash alg default processing functions and opt argument +*/ +static cpHashProc cpHashProcFunc[] = { + (cpHashProc)NULL, + UpdateSHA1, + UpdateSHA256, + UpdateSHA256, + UpdateSHA512, + UpdateSHA512, + UpdateMD5, + UpdateSHA512, + UpdateSHA512, +}; + +int cpInitHash(IppsHashState* pCtx, IppHashAlgId algID) +{ + /* setup default processing function */ + HASH_FUNC(pCtx) = cpHashProcFunc[algID]; + + /* setup optional agr of processing function */ + HASH_FUNC_PAR(pCtx) = cpHashProcFuncOpt[algID]; + + return cpReInitHash(pCtx, algID); +} + +IPPFUN(IppStatus, ippsHashInit,(IppsHashState* pCtx, IppHashAlgId algID)) +{ + /* get algorithm id */ + algID = cpValidHashAlg(algID); + /* test hash alg */ + IPP_BADARG_RET(ippHashAlg_Unknown==algID, ippStsNotSupportedModeErr); + + /* test ctx pointer */ + IPP_BAD_PTR1_RET(pCtx); + /* test hash alg */ + + /* set ctx ID */ + HASH_CTX_ID(pCtx) = idCtxHash; + HASH_ALG_ID(pCtx) = algID; + + /* init context */ + cpInitHash(pCtx, algID); + return ippStsNoErr; +} + + +/*F* +// Name: ippsHashUpdate +// +// Purpose: Updates intermediate hash value based on input stream. +// +// Returns: Reason: +// ippStsNullPtrErr pCtx == NULL +// ippStsNullPtrErr pSrc==0 but len!=0 +// ippStsContextMatchErr pCtx->idCtx != idCtxHash +// ippStsLengthErr len <0 +// ippStsNoErr no errors +// +// Parameters: +// pSrc pointer to the input stream +// len input stream length +// pCtx pointer to the Hash context +// +*F*/ +__INLINE int IsExceedMsgLen(Ipp64u maxLo, Ipp64u maxHi, Ipp64u lenLo, Ipp64u lenHi) +{ + int isExceed = lenLo > maxLo; + isExceed = (lenHi+isExceed) > maxHi; + return isExceed; +} + +IPPFUN(IppStatus, ippsHashUpdate,(const Ipp8u* pSrc, int len, IppsHashState* pCtx)) +{ + /* test state pointer and ID */ + IPP_BAD_PTR1_RET(pCtx); + /* test the context */ + IPP_BADARG_RET(!HASH_VALID_ID(pCtx), ippStsContextMatchErr); + /* test input length */ + IPP_BADARG_RET((len<0 && pSrc), ippStsLengthErr); + /* test source pointer */ + IPP_BADARG_RET((len && !pSrc), ippStsNullPtrErr); + + /* handle non empty input */ + if(len) { + const cpHashAttr* pAttr = &cpHashAlgAttr[HASH_ALG_ID(pCtx)]; + + /* test if size of message is being processed not exceeded yet */ + Ipp64u lenLo = HASH_LENLO(pCtx); + Ipp64u lenHi = HASH_LENHI(pCtx); + lenLo += len; + if(lenLo < HASH_LENLO(pCtx)) lenHi++; + if(IsExceedMsgLen(pAttr->msgLenMax[0],pAttr->msgLenMax[1], lenLo,lenHi)) + IPP_ERROR_RET(ippStsLengthErr); + + else { + cpHashProc hashFunc = HASH_FUNC(pCtx); /* processing function */ + const void* pParam = HASH_FUNC_PAR(pCtx); /* and it's addition params */ + int mbs = pAttr->msgBlkSize; /* data block size */ + + /* + // processing + */ + { + int procLen; + + /* test if internal buffer is not empty */ + int n = HAHS_BUFFIDX(pCtx); + if(n) { + procLen = IPP_MIN(len, (mbs-n)); + CopyBlock(pSrc, HASH_BUFF(pCtx)+n, procLen); + HAHS_BUFFIDX(pCtx) = n += procLen; + + /* block processing */ + if(mbs==n) { + hashFunc(HASH_VALUE(pCtx), HASH_BUFF(pCtx), mbs, pParam); + HAHS_BUFFIDX(pCtx) = 0; + } + + /* update message pointer and length */ + pSrc += procLen; + len -= procLen; + } + + /* main processing part */ + procLen = len & ~(mbs-1); + if(procLen) { + hashFunc(HASH_VALUE(pCtx), pSrc, procLen, pParam); + pSrc += procLen; + len -= procLen; + } + + /* rest of input message */ + if(len) { + CopyBlock(pSrc, HASH_BUFF(pCtx), len); + HAHS_BUFFIDX(pCtx) += len; + } + } + + /* update length of processed message */ + HASH_LENLO(pCtx) = lenLo; + HASH_LENHI(pCtx) = lenHi; + + return ippStsNoErr; + } + } + + return ippStsNoErr; +} + + +static void cpComputeDigest(Ipp8u* pHashTag, int hashTagLen, const IppsHashState* pCtx) +{ + /* hash alg and parameters */ + cpHashProc hashFunc = HASH_FUNC(pCtx); /* processing function */ + const void* pParam = HASH_FUNC_PAR(pCtx); /* and it's addition params */ + + /* attributes */ + const cpHashAttr* pAttr = &cpHashAlgAttr[HASH_ALG_ID(pCtx)]; + int mbs = pAttr->msgBlkSize; /* data block size */ + int ivSize = pAttr->ivSize; /* size of hash's IV */ + int msgLenRepSize = pAttr->msgLenRepSize; /* length of the message representation */ + + /* number of bytes in context buffer */ + int n = HAHS_BUFFIDX(pCtx); + /* buffer and it actual length */ + Ipp8u buffer[MBS_HASH_MAX*2]; + int bufferLen = n < (mbs-msgLenRepSize)? mbs : mbs*2; + + /* copy current hash value */ + cpHash hash; + CopyBlock(HASH_VALUE(pCtx), hash, ivSize); + + /* copy of state's buffer */ + CopyBlock(HASH_BUFF(pCtx), buffer, bufferLen); + /* end of message bit */ + buffer[n++] = 0x80; + /* padd buffer */ + PaddBlock(0, buffer+n, bufferLen-n-msgLenRepSize); + + /* message length representation in bits (remember about big endian) */ + { + /* convert processed message length bytes ->bits */ + Ipp64u lo = HASH_LENLO(pCtx); + Ipp64u hi = HASH_LENHI(pCtx); + hi = LSL64(hi,3) | LSR64(lo,63-3); + lo = LSL64(lo,3); + + if(msgLenRepSize>(int)(sizeof(Ipp64u))) { + #if (IPP_ENDIAN == IPP_BIG_ENDIAN) + ((Ipp64u*)(buffer+bufferLen))[-2] = hi; + #else + ((Ipp64u*)(buffer+bufferLen))[-2] = ENDIANNESS64(hi); + #endif + } + + /* recall about MD5 specific */ + if(ippHashAlg_MD5!=HASH_ALG_ID(pCtx)) { + #if (IPP_ENDIAN == IPP_BIG_ENDIAN) + ((Ipp64u*)(buffer+bufferLen))[-1] = lo; + #else + ((Ipp64u*)(buffer+bufferLen))[-1] = ENDIANNESS64(lo); + #endif + } + else { + #if (IPP_ENDIAN == IPP_BIG_ENDIAN) + ((Ipp64u*)(buffer+bufferLen))[-1] = ENDIANNESS64(lo); + #else + ((Ipp64u*)(buffer+bufferLen))[-1] = lo; + #endif + } + } + + /* copmplete hash computation */ + hashFunc(hash, buffer, bufferLen, pParam); + + /* store digest into the user buffer (remember digest in big endian) */ + if(msgLenRepSize>(int)(sizeof(Ipp64u))) { + /* ippHashAlg_SHA384, ippHashAlg_SHA512, ippHashAlg_SHA512_224 and ippHashAlg_SHA512_256 */ + hash[0] = ENDIANNESS64(hash[0]); + hash[1] = ENDIANNESS64(hash[1]); + hash[2] = ENDIANNESS64(hash[2]); + hash[3] = ENDIANNESS64(hash[3]); + hash[4] = ENDIANNESS64(hash[4]); + hash[5] = ENDIANNESS64(hash[5]); + hash[6] = ENDIANNESS64(hash[6]); + hash[7] = ENDIANNESS64(hash[7]); + } + else if(ippHashAlg_MD5!=HASH_ALG_ID(pCtx)) { + ((Ipp32u*)hash)[0] = ENDIANNESS32(((Ipp32u*)hash)[0]); + ((Ipp32u*)hash)[1] = ENDIANNESS32(((Ipp32u*)hash)[1]); + ((Ipp32u*)hash)[2] = ENDIANNESS32(((Ipp32u*)hash)[2]); + ((Ipp32u*)hash)[3] = ENDIANNESS32(((Ipp32u*)hash)[3]); + ((Ipp32u*)hash)[4] = ENDIANNESS32(((Ipp32u*)hash)[4]); + if(ippHashAlg_SHA1!=HASH_ALG_ID(pCtx)) { + ((Ipp32u*)hash)[5] = ENDIANNESS32(((Ipp32u*)hash)[5]); + ((Ipp32u*)hash)[6] = ENDIANNESS32(((Ipp32u*)hash)[6]); + ((Ipp32u*)hash)[7] = ENDIANNESS32(((Ipp32u*)hash)[7]); + } + } + CopyBlock(hash, pHashTag, hashTagLen); +} + + +/*F* +// Name: ippsHashGetTag +// +// Purpose: Compute digest based on current state. +// Note, that futher digest update is possible +// +// Returns: Reason: +// ippStsNullPtrErr pTag == NULL +// pCtx == NULL +// ippStsContextMatchErr pCtx->idCtx != idCtxHash +// ippStsLengthErr hashSize < tagLen <1 +// ippStsNoErr no errors +// +// Parameters: +// pTag address of the output digest +// tagLen length of digest +// pCtx pointer to the SHS state +// +*F*/ +IPPFUN(IppStatus, ippsHashGetTag,(Ipp8u* pTag, int tagLen, const IppsHashState* pCtx)) +{ + /* test state pointer and ID */ + IPP_BAD_PTR2_RET(pTag, pCtx); + /* test the context */ + IPP_BADARG_RET(!HASH_VALID_ID(pCtx), ippStsContextMatchErr); + + { + /* size of hash */ + int hashSize = cpHashAlgAttr[HASH_ALG_ID(pCtx)].hashSize; + if(tagLen<1||hashSizeidCtx != idCtxHash +// ippStsNoErr no errors +// +// Parameters: +// pMD address of the output digest +// pCtx pointer to the SHS state +// +*F*/ +IPPFUN(IppStatus, ippsHashFinal,(Ipp8u* pMD, IppsHashState* pCtx)) +{ + /* test state pointer and ID */ + IPP_BAD_PTR2_RET(pMD, pCtx); + /* test the context */ + IPP_BADARG_RET(!HASH_VALID_ID(pCtx), ippStsContextMatchErr); + + { + IppHashAlgId algID = HASH_ALG_ID(pCtx); + int hashSize = cpHashAlgAttr[algID].hashSize; + + cpComputeDigest(pMD, hashSize, pCtx); + cpReInitHash(pCtx, algID); + + return ippStsNoErr; + } +} + + +/*F* +// Name: ippsHashMessage +// +// Purpose: Hash of the whole message. +// +// Returns: Reason: +// ippStsNullPtrErr pMD == NULL +// pMsg == NULL but msgLen!=0 +// ippStsLengthErr msgLen <0 +// ippStsNotSupportedModeErr if algID is not match to supported hash alg +// ippStsNoErr no errors +// +// Parameters: +// pMsg pointer to the input message +// msgLen input message length +// pMD address of the output digest +// algID hash alg ID +// +*F*/ +IPPFUN(IppStatus, ippsHashMessage,(const Ipp8u* pMsg, int msgLen, Ipp8u* pMD, IppHashAlgId algID)) +{ + /* get algorithm id */ + algID = cpValidHashAlg(algID); + /* test hash alg */ + IPP_BADARG_RET(ippHashAlg_Unknown==algID, ippStsNotSupportedModeErr); + + /* test digest pointer */ + IPP_BAD_PTR1_RET(pMD); + /* test message length */ + IPP_BADARG_RET((msgLen<0), ippStsLengthErr); + /* test message pointer */ + IPP_BADARG_RET((msgLen && !pMsg), ippStsNullPtrErr); + + { + /* processing function and parameter */ + cpHashProc hashFunc = cpHashProcFunc[algID]; + const void* pParam = cpHashProcFuncOpt[algID]; + + /* attributes */ + const cpHashAttr* pAttr = &cpHashAlgAttr[algID]; + int mbs = pAttr->msgBlkSize; /* data block size */ + int ivSize = pAttr->ivSize; /* size of hash's IV */ + int hashSize = pAttr->hashSize; /* hash size */ + int msgLenRepSize = pAttr->msgLenRepSize; /* length of the message representation */ + + /* message bitlength representation */ + Ipp64u msgLenBits = (Ipp64u)msgLen*8; + /* length of main message part */ + int msgLenBlks = msgLen & (-mbs); + /* rest of message length */ + int msgLenRest = msgLen - msgLenBlks; + + /* end of message buffer */ + Ipp8u buffer[MBS_HASH_MAX*2]; + int bufferLen = (msgLenRest < (mbs-msgLenRepSize))? mbs : mbs*2; + + /* init hash */ + cpHash hash; + const Ipp8u* iv = cpHashIV[algID]; + CopyBlock(iv, hash, ivSize); + + /*construct last messge block(s) */ + #define MSG_LEN_REP (sizeof(Ipp64u)) + + /* copy end of message */ + CopyBlock(pMsg+msgLen-msgLenRest, buffer, msgLenRest); + /* end of message bit */ + buffer[msgLenRest++] = 0x80; + /* padd buffer */ + PaddBlock(0, buffer+msgLenRest, bufferLen-msgLenRest-MSG_LEN_REP); + /* copy message bitlength representation */ + if(ippHashAlg_MD5!=algID) + msgLenBits = ENDIANNESS64(msgLenBits); + ((Ipp64u*)(buffer+bufferLen))[-1] = msgLenBits; + + #undef MSG_LEN_REP + + /* message processing */ + if(msgLenBlks) + hashFunc(hash, pMsg, msgLenBlks, pParam); + hashFunc(hash, buffer, bufferLen, pParam); + + /* store digest into the user buffer (remember digest in big endian) */ + if(msgLenRepSize > (int)(sizeof(Ipp64u))) { + /* ippHashAlg_SHA384, ippHashAlg_SHA512, ippHashAlg_SHA512_224 and ippHashAlg_SHA512_256 */ + hash[0] = ENDIANNESS64(hash[0]); + hash[1] = ENDIANNESS64(hash[1]); + hash[2] = ENDIANNESS64(hash[2]); + hash[3] = ENDIANNESS64(hash[3]); + hash[4] = ENDIANNESS64(hash[4]); + hash[5] = ENDIANNESS64(hash[5]); + hash[6] = ENDIANNESS64(hash[6]); + hash[7] = ENDIANNESS64(hash[7]); + } + else if(ippHashAlg_MD5!=algID) { + /* ippHashAlg_SHA1, ippHashAlg_SHA224, ippHashAlg_SHA256 and ippHashAlg_SM3 */ + ((Ipp32u*)hash)[0] = ENDIANNESS32(((Ipp32u*)hash)[0]); + ((Ipp32u*)hash)[1] = ENDIANNESS32(((Ipp32u*)hash)[1]); + ((Ipp32u*)hash)[2] = ENDIANNESS32(((Ipp32u*)hash)[2]); + ((Ipp32u*)hash)[3] = ENDIANNESS32(((Ipp32u*)hash)[3]); + ((Ipp32u*)hash)[4] = ENDIANNESS32(((Ipp32u*)hash)[4]); + ((Ipp32u*)hash)[5] = ENDIANNESS32(((Ipp32u*)hash)[5]); + ((Ipp32u*)hash)[6] = ENDIANNESS32(((Ipp32u*)hash)[6]); + ((Ipp32u*)hash)[7] = ENDIANNESS32(((Ipp32u*)hash)[7]); + } + CopyBlock(hash, pMD, hashSize); + + return ippStsNoErr; + } +} diff --git a/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcphashcnt.c b/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcphashcnt.c new file mode 100644 index 0000000000..37e0188172 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcphashcnt.c @@ -0,0 +1,216 @@ +/* +* Copyright (C) 2016 Intel Corporation. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in +* the documentation and/or other materials provided with the +* distribution. +* * Neither the name of Intel Corporation nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ + +#include "owndefs.h" +#include "owncp.h" +#include "pcphash.h" + +/* +// enabled hash alg IDs +*/ +const IppHashAlgId cpEnabledHashAlgID[] = { + IPP_ALG_HASH_UNKNOWN, + IPP_ALG_HASH_SHA1, + IPP_ALG_HASH_SHA256, + IPP_ALG_HASH_SHA224, + IPP_ALG_HASH_SHA512, + IPP_ALG_HASH_SHA384, + IPP_ALG_HASH_MD5, + IPP_ALG_HASH_SHA512_224, + IPP_ALG_HASH_SHA512_256 +}; +//////////////////////////////////////////////////////////// + +/* +// hash init values +*/ +const Ipp32u UnknownHash_IV[] = { + 0}; + +const Ipp32u SHA1_IV[] = { + 0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0}; + +const Ipp32u SHA256_IV[] = { + 0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A, + 0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19}; + +const Ipp32u SHA224_IV[] = { + 0xC1059ED8, 0x367CD507, 0x3070DD17, 0xF70E5939, + 0xFFC00B31, 0x68581511, 0x64F98FA7, 0xBEFA4FA4}; + +const Ipp64u SHA512_IV[] = { + CONST_64(0x6A09E667F3BCC908), CONST_64(0xBB67AE8584CAA73B), + CONST_64(0x3C6EF372FE94F82B), CONST_64(0xA54FF53A5F1D36F1), + CONST_64(0x510E527FADE682D1), CONST_64(0x9B05688C2B3E6C1F), + CONST_64(0x1F83D9ABFB41BD6B), CONST_64(0x5BE0CD19137E2179)}; + +const Ipp64u SHA384_IV[] = { + CONST_64(0xCBBB9D5DC1059ED8), CONST_64(0x629A292A367CD507), + CONST_64(0x9159015A3070DD17), CONST_64(0x152FECD8F70E5939), + CONST_64(0x67332667FFC00B31), CONST_64(0x8EB44A8768581511), + CONST_64(0xDB0C2E0D64F98FA7), CONST_64(0x47B5481DBEFA4FA4)}; + +const Ipp32u MD5_IV[] = { + 0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476}; + +const Ipp64u SHA512_224_IV[] = { + CONST_64(0x8C3D37C819544DA2), CONST_64(0x73E1996689DCD4D6), + CONST_64(0x1DFAB7AE32FF9C82), CONST_64(0x679DD514582F9FCF), + CONST_64(0x0F6D2B697BD44DA8), CONST_64(0x77E36F7304C48942), + CONST_64(0x3F9D85A86A1D36C8), CONST_64(0x1112E6AD91D692A1)}; + +const Ipp64u SHA512_256_IV[] = { + CONST_64(0x22312194FC2BF72C), CONST_64(0x9F555FA3C84C64C2), + CONST_64(0x2393B86B6F53B151), CONST_64(0x963877195940EABD), + CONST_64(0x96283EE2A88EFFE3), CONST_64(0xBE5E1E2553863992), + CONST_64(0x2B0199FC2C85B8AA), CONST_64(0x0EB72DDC81C52CA2)}; + +const Ipp8u* cpHashIV[] = { + (Ipp8u*)UnknownHash_IV, + (Ipp8u*)SHA1_IV, + (Ipp8u*)SHA256_IV, + (Ipp8u*)SHA224_IV, + (Ipp8u*)SHA512_IV, + (Ipp8u*)SHA384_IV, + (Ipp8u*)MD5_IV, + (Ipp8u*)SHA512_224_IV, + (Ipp8u*)SHA512_256_IV, +}; + +//////////////////////////////////////////////////////////// + +/* +// additive constatns +*/ +__ALIGN16 const Ipp32u SHA1_cnt[] = { + 0x5A827999, 0x6ED9EBA1, 0x8F1BBCDC, 0xCA62C1D6 +}; + +__ALIGN16 const Ipp32u SHA256_cnt[] = { + 0x428A2F98, 0x71374491, 0xB5C0FBCF, 0xE9B5DBA5, + 0x3956C25B, 0x59F111F1, 0x923F82A4, 0xAB1C5ED5, + 0xD807AA98, 0x12835B01, 0x243185BE, 0x550C7DC3, + 0x72BE5D74, 0x80DEB1FE, 0x9BDC06A7, 0xC19BF174, + 0xE49B69C1, 0xEFBE4786, 0x0FC19DC6, 0x240CA1CC, + 0x2DE92C6F, 0x4A7484AA, 0x5CB0A9DC, 0x76F988DA, + 0x983E5152, 0xA831C66D, 0xB00327C8, 0xBF597FC7, + 0xC6E00BF3, 0xD5A79147, 0x06CA6351, 0x14292967, + 0x27B70A85, 0x2E1B2138, 0x4D2C6DFC, 0x53380D13, + 0x650A7354, 0x766A0ABB, 0x81C2C92E, 0x92722C85, + 0xA2BFE8A1, 0xA81A664B, 0xC24B8B70, 0xC76C51A3, + 0xD192E819, 0xD6990624, 0xF40E3585, 0x106AA070, + 0x19A4C116, 0x1E376C08, 0x2748774C, 0x34B0BCB5, + 0x391C0CB3, 0x4ED8AA4A, 0x5B9CCA4F, 0x682E6FF3, + 0x748F82EE, 0x78A5636F, 0x84C87814, 0x8CC70208, + 0x90BEFFFA, 0xA4506CEB, 0xBEF9A3F7, 0xC67178F2 +}; + +__ALIGN16 const Ipp64u SHA512_cnt[] = { + CONST_64(0x428A2F98D728AE22), CONST_64(0x7137449123EF65CD), CONST_64(0xB5C0FBCFEC4D3B2F), CONST_64(0xE9B5DBA58189DBBC), + CONST_64(0x3956C25BF348B538), CONST_64(0x59F111F1B605D019), CONST_64(0x923F82A4AF194F9B), CONST_64(0xAB1C5ED5DA6D8118), + CONST_64(0xD807AA98A3030242), CONST_64(0x12835B0145706FBE), CONST_64(0x243185BE4EE4B28C), CONST_64(0x550C7DC3D5FFB4E2), + CONST_64(0x72BE5D74F27B896F), CONST_64(0x80DEB1FE3B1696B1), CONST_64(0x9BDC06A725C71235), CONST_64(0xC19BF174CF692694), + CONST_64(0xE49B69C19EF14AD2), CONST_64(0xEFBE4786384F25E3), CONST_64(0x0FC19DC68B8CD5B5), CONST_64(0x240CA1CC77AC9C65), + CONST_64(0x2DE92C6F592B0275), CONST_64(0x4A7484AA6EA6E483), CONST_64(0x5CB0A9DCBD41FBD4), CONST_64(0x76F988DA831153B5), + CONST_64(0x983E5152EE66DFAB), CONST_64(0xA831C66D2DB43210), CONST_64(0xB00327C898FB213F), CONST_64(0xBF597FC7BEEF0EE4), + CONST_64(0xC6E00BF33DA88FC2), CONST_64(0xD5A79147930AA725), CONST_64(0x06CA6351E003826F), CONST_64(0x142929670A0E6E70), + CONST_64(0x27B70A8546D22FFC), CONST_64(0x2E1B21385C26C926), CONST_64(0x4D2C6DFC5AC42AED), CONST_64(0x53380D139D95B3DF), + CONST_64(0x650A73548BAF63DE), CONST_64(0x766A0ABB3C77B2A8), CONST_64(0x81C2C92E47EDAEE6), CONST_64(0x92722C851482353B), + CONST_64(0xA2BFE8A14CF10364), CONST_64(0xA81A664BBC423001), CONST_64(0xC24B8B70D0F89791), CONST_64(0xC76C51A30654BE30), + CONST_64(0xD192E819D6EF5218), CONST_64(0xD69906245565A910), CONST_64(0xF40E35855771202A), CONST_64(0x106AA07032BBD1B8), + CONST_64(0x19A4C116B8D2D0C8), CONST_64(0x1E376C085141AB53), CONST_64(0x2748774CDF8EEB99), CONST_64(0x34B0BCB5E19B48A8), + CONST_64(0x391C0CB3C5C95A63), CONST_64(0x4ED8AA4AE3418ACB), CONST_64(0x5B9CCA4F7763E373), CONST_64(0x682E6FF3D6B2B8A3), + CONST_64(0x748F82EE5DEFB2FC), CONST_64(0x78A5636F43172F60), CONST_64(0x84C87814A1F0AB72), CONST_64(0x8CC702081A6439EC), + CONST_64(0x90BEFFFA23631E28), CONST_64(0xA4506CEBDE82BDE9), CONST_64(0xBEF9A3F7B2C67915), CONST_64(0xC67178F2E372532B), + CONST_64(0xCA273ECEEA26619C), CONST_64(0xD186B8C721C0C207), CONST_64(0xEADA7DD6CDE0EB1E), CONST_64(0xF57D4F7FEE6ED178), + CONST_64(0x06F067AA72176FBA), CONST_64(0x0A637DC5A2C898A6), CONST_64(0x113F9804BEF90DAE), CONST_64(0x1B710B35131C471B), + CONST_64(0x28DB77F523047D84), CONST_64(0x32CAAB7B40C72493), CONST_64(0x3C9EBE0A15C9BEBC), CONST_64(0x431D67C49C100D4C), + CONST_64(0x4CC5D4BECB3E42B6), CONST_64(0x597F299CFC657E2A), CONST_64(0x5FCB6FAB3AD6FAEC), CONST_64(0x6C44198C4A475817) +}; + +__ALIGN16 const Ipp32u MD5_cnt[] = { + 0xD76AA478, 0xE8C7B756, 0x242070DB, 0xC1BDCEEE, + 0xF57C0FAF, 0x4787C62A, 0xA8304613, 0xFD469501, + 0x698098D8, 0x8B44F7AF, 0xFFFF5BB1, 0x895CD7BE, + 0x6B901122, 0xFD987193, 0xA679438E, 0x49B40821, + + 0xF61E2562, 0xC040B340, 0x265E5A51, 0xE9B6C7AA, + 0xD62F105D, 0x02441453, 0xD8A1E681, 0xE7D3FBC8, + 0x21E1CDE6, 0xC33707D6, 0xF4D50D87, 0x455A14ED, + 0xA9E3E905, 0xFCEFA3F8, 0x676F02D9, 0x8D2A4C8A, + + 0xFFFA3942, 0x8771F681, 0x6D9D6122, 0xFDE5380C, + 0xA4BEEA44, 0x4BDECFA9, 0xF6BB4B60, 0xBEBFBC70, + 0x289B7EC6, 0xEAA127FA, 0xD4EF3085, 0x04881D05, + 0xD9D4D039, 0xE6DB99E5, 0x1FA27CF8, 0xC4AC5665, + + 0xF4292244, 0x432AFF97, 0xAB9423A7, 0xFC93A039, + 0x655B59C3, 0x8F0CCC92, 0xFFEFF47D, 0x85845DD1, + 0x6FA87E4F, 0xFE2CE6E0, 0xA3014314, 0x4E0811A1, + 0xF7537E82, 0xBD3AF235, 0x2AD7D2BB, 0xEB86D391 +}; + +/* +// hash alg default processing opt argument +*/ +const void* cpHashProcFuncOpt[] = { + NULL, + SHA1_cnt, + SHA256_cnt, + SHA256_cnt, + SHA512_cnt, + SHA512_cnt, + MD5_cnt, + SHA512_cnt, + SHA512_cnt, +}; +//////////////////////////////////////////////////////////// + +/* hash alg attributes */ +const cpHashAttr cpHashAlgAttr[] = { + {0, 0, 0, 0, {CONST_64(0),CONST_64(0)}}, /* unknown */ + + {IPP_SHA1_DIGEST_BITSIZE/8, IPP_SHA1_DIGEST_BITSIZE/8, MBS_SHA1, sizeof(Ipp64u), {CONST_64(0x2000000000000000-1),CONST_64(0)}}, + + {IPP_SHA256_DIGEST_BITSIZE/8,IPP_SHA256_DIGEST_BITSIZE/8, MBS_SHA256, sizeof(Ipp64u), {CONST_64(0x2000000000000000-1),CONST_64(0)}}, + + {IPP_SHA256_DIGEST_BITSIZE/8,IPP_SHA224_DIGEST_BITSIZE/8, MBS_SHA224, sizeof(Ipp64u), {CONST_64(0x2000000000000000-1),CONST_64(0)}}, + + {IPP_SHA512_DIGEST_BITSIZE/8,IPP_SHA512_DIGEST_BITSIZE/8, MBS_SHA512, sizeof(Ipp64u)*2, {CONST_64(0xFFFFFFFFFFFFFFFF),CONST_64(0x2000000000000000-1)}}, + + {IPP_SHA512_DIGEST_BITSIZE/8,IPP_SHA384_DIGEST_BITSIZE/8, MBS_SHA384, sizeof(Ipp64u)*2, {CONST_64(0xFFFFFFFFFFFFFFFF),CONST_64(0x2000000000000000-1)}}, + + {IPP_MD5_DIGEST_BITSIZE/8,IPP_MD5_DIGEST_BITSIZE/8, MBS_MD5, sizeof(Ipp64u), {CONST_64(0x2000000000000000-1),CONST_64(0)}}, + + {IPP_SHA512_DIGEST_BITSIZE/8,IPP_SHA512_224_DIGEST_BITSIZE/8, MBS_SHA512, sizeof(Ipp64u)*2, {CONST_64(0xFFFFFFFFFFFFFFFF),CONST_64(0x2000000000000000-1)}}, + + {IPP_SHA512_DIGEST_BITSIZE/8,IPP_SHA512_256_DIGEST_BITSIZE/8, MBS_SHA512, sizeof(Ipp64u)*2, {CONST_64(0xFFFFFFFFFFFFFFFF),CONST_64(0x2000000000000000-1)}} +}; diff --git a/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcphashmd5px.c b/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcphashmd5px.c new file mode 100644 index 0000000000..d6a93dd22f --- /dev/null +++ b/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcphashmd5px.c @@ -0,0 +1,197 @@ +/* +* Copyright (C) 2016 Intel Corporation. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in +* the documentation and/or other materials provided with the +* distribution. +* * Neither the name of Intel Corporation nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ + +#include "owndefs.h" +#include "owncp.h" +#include "pcphash.h" +#include "pcptool.h" + +#pragma message("IPP_ALG_HASH_MD5 enabled") + + +/* +// Magic functions defined in RFC 1321 +// +*/ +#define F(X,Y,Z) ((Z) ^ ((X) & ((Y) ^ (Z)))) /* sightly optimized form of (((X) & (Y)) | ((~(X) & (Z)))*/ +#define G(X,Y,Z) F((Z),(X),(Y)) /* replace the original (((X) & (Z)) | ((Y) & ~(Z))) */ +#define H(X,Y,Z) ((X) ^ (Y) ^ (Z)) +#define I(X,Y,Z) ((Y) ^ ((X) | ~(Z))) + +/* +// MD5 step +*/ +#define MD5_STEP(MAGIC, A,B,C,D, data, constant, nrot) \ + (A = B +ROL32((A +MAGIC(B,C,D) +data +constant), nrot)) + +/* +// MD5 left rotations (number of bits) +// depends on round type +*/ +#define F1 7 +#define F2 12 +#define F3 17 +#define F4 22 + +#define G1 5 +#define G2 9 +#define G3 14 +#define G4 20 + +#define H1 4 +#define H2 11 +#define H3 16 +#define H4 23 + +#define I1 6 +#define I2 10 +#define I3 15 +#define I4 21 + +/*F* +// Name: UpdateMD5 +// +// Purpose: Update internal hash according to input message stream. +// +// Parameters: +// uniHash pointer to in/out hash +// mblk pointer to message stream +// mlen message stream length (multiple by message block size) +// uniParam pointer to the optional parameter +// +*F*/ +void UpdateMD5(void* uinHash, const Ipp8u* mblk, int mlen, const void* uniParam) +{ + Ipp32u* digest = (Ipp32u*)uinHash; + Ipp32u* MD5_cnt_loc = (Ipp32u*)uniParam; + + for(; mlen>=MBS_MD5; mblk += MBS_MD5, mlen -= MBS_MD5) { + + /* allocate data */ + #if (IPP_ENDIAN == IPP_BIG_ENDIAN) + Ipp32u data[MBS_MD5/sizeof(Ipp32u)]; + #else + /* or just word alias */ + Ipp32u* data = (Ipp32u*)mblk; + #endif + + /* init variables */ + Ipp32u a = digest[0]; + Ipp32u b = digest[1]; + Ipp32u c = digest[2]; + Ipp32u d = digest[3]; + + #if (IPP_ENDIAN == IPP_BIG_ENDIAN) + int t; + for(t=0; t<16; t++) { + data[t] = ENDIANNESS(((Ipp32u*)mblk)[t]); + } + #endif + + /* rounds type F */ + MD5_STEP(F, a,b,c,d, data[ 0], MD5_cnt_loc[ 0], F1); + MD5_STEP(F, d,a,b,c, data[ 1], MD5_cnt_loc[ 1], F2); + MD5_STEP(F, c,d,a,b, data[ 2], MD5_cnt_loc[ 2], F3); + MD5_STEP(F, b,c,d,a, data[ 3], MD5_cnt_loc[ 3], F4); + MD5_STEP(F, a,b,c,d, data[ 4], MD5_cnt_loc[ 4], F1); + MD5_STEP(F, d,a,b,c, data[ 5], MD5_cnt_loc[ 5], F2); + MD5_STEP(F, c,d,a,b, data[ 6], MD5_cnt_loc[ 6], F3); + MD5_STEP(F, b,c,d,a, data[ 7], MD5_cnt_loc[ 7], F4); + MD5_STEP(F, a,b,c,d, data[ 8], MD5_cnt_loc[ 8], F1); + MD5_STEP(F, d,a,b,c, data[ 9], MD5_cnt_loc[ 9], F2); + MD5_STEP(F, c,d,a,b, data[10], MD5_cnt_loc[10], F3); + MD5_STEP(F, b,c,d,a, data[11], MD5_cnt_loc[11], F4); + MD5_STEP(F, a,b,c,d, data[12], MD5_cnt_loc[12], F1); + MD5_STEP(F, d,a,b,c, data[13], MD5_cnt_loc[13], F2); + MD5_STEP(F, c,d,a,b, data[14], MD5_cnt_loc[14], F3); + MD5_STEP(F, b,c,d,a, data[15], MD5_cnt_loc[15], F4); + + /* rounds type G */ + MD5_STEP(G, a,b,c,d, data[ 1], MD5_cnt_loc[16], G1); + MD5_STEP(G, d,a,b,c, data[ 6], MD5_cnt_loc[17], G2); + MD5_STEP(G, c,d,a,b, data[11], MD5_cnt_loc[18], G3); + MD5_STEP(G, b,c,d,a, data[ 0], MD5_cnt_loc[19], G4); + MD5_STEP(G, a,b,c,d, data[ 5], MD5_cnt_loc[20], G1); + MD5_STEP(G, d,a,b,c, data[10], MD5_cnt_loc[21], G2); + MD5_STEP(G, c,d,a,b, data[15], MD5_cnt_loc[22], G3); + MD5_STEP(G, b,c,d,a, data[ 4], MD5_cnt_loc[23], G4); + MD5_STEP(G, a,b,c,d, data[ 9], MD5_cnt_loc[24], G1); + MD5_STEP(G, d,a,b,c, data[14], MD5_cnt_loc[25], G2); + MD5_STEP(G, c,d,a,b, data[ 3], MD5_cnt_loc[26], G3); + MD5_STEP(G, b,c,d,a, data[ 8], MD5_cnt_loc[27], G4); + MD5_STEP(G, a,b,c,d, data[13], MD5_cnt_loc[28], G1); + MD5_STEP(G, d,a,b,c, data[ 2], MD5_cnt_loc[29], G2); + MD5_STEP(G, c,d,a,b, data[ 7], MD5_cnt_loc[30], G3); + MD5_STEP(G, b,c,d,a, data[12], MD5_cnt_loc[31], G4); + + /* rounds type H */ + MD5_STEP(H, a,b,c,d, data[ 5], MD5_cnt_loc[32], H1); + MD5_STEP(H, d,a,b,c, data[ 8], MD5_cnt_loc[33], H2); + MD5_STEP(H, c,d,a,b, data[11], MD5_cnt_loc[34], H3); + MD5_STEP(H, b,c,d,a, data[14], MD5_cnt_loc[35], H4); + MD5_STEP(H, a,b,c,d, data[ 1], MD5_cnt_loc[36], H1); + MD5_STEP(H, d,a,b,c, data[ 4], MD5_cnt_loc[37], H2); + MD5_STEP(H, c,d,a,b, data[ 7], MD5_cnt_loc[38], H3); + MD5_STEP(H, b,c,d,a, data[10], MD5_cnt_loc[39], H4); + MD5_STEP(H, a,b,c,d, data[13], MD5_cnt_loc[40], H1); + MD5_STEP(H, d,a,b,c, data[ 0], MD5_cnt_loc[41], H2); + MD5_STEP(H, c,d,a,b, data[ 3], MD5_cnt_loc[42], H3); + MD5_STEP(H, b,c,d,a, data[ 6], MD5_cnt_loc[43], H4); + MD5_STEP(H, a,b,c,d, data[ 9], MD5_cnt_loc[44], H1); + MD5_STEP(H, d,a,b,c, data[12], MD5_cnt_loc[45], H2); + MD5_STEP(H, c,d,a,b, data[15], MD5_cnt_loc[46], H3); + MD5_STEP(H, b,c,d,a, data[ 2], MD5_cnt_loc[47], H4); + + /* rounds type I */ + MD5_STEP(I, a,b,c,d, data[ 0], MD5_cnt_loc[48], I1); + MD5_STEP(I, d,a,b,c, data[ 7], MD5_cnt_loc[49], I2); + MD5_STEP(I, c,d,a,b, data[14], MD5_cnt_loc[50], I3); + MD5_STEP(I, b,c,d,a, data[ 5], MD5_cnt_loc[51], I4); + MD5_STEP(I, a,b,c,d, data[12], MD5_cnt_loc[52], I1); + MD5_STEP(I, d,a,b,c, data[ 3], MD5_cnt_loc[53], I2); + MD5_STEP(I, c,d,a,b, data[10], MD5_cnt_loc[54], I3); + MD5_STEP(I, b,c,d,a, data[ 1], MD5_cnt_loc[55], I4); + MD5_STEP(I, a,b,c,d, data[ 8], MD5_cnt_loc[56], I1); + MD5_STEP(I, d,a,b,c, data[15], MD5_cnt_loc[57], I2); + MD5_STEP(I, c,d,a,b, data[ 6], MD5_cnt_loc[58], I3); + MD5_STEP(I, b,c,d,a, data[13], MD5_cnt_loc[59], I4); + MD5_STEP(I, a,b,c,d, data[ 4], MD5_cnt_loc[60], I1); + MD5_STEP(I, d,a,b,c, data[11], MD5_cnt_loc[61], I2); + MD5_STEP(I, c,d,a,b, data[ 2], MD5_cnt_loc[62], I3); + MD5_STEP(I, b,c,d,a, data[ 9], MD5_cnt_loc[63], I4); + + /* update digest */ + digest[0] += a; + digest[1] += b; + digest[2] += c; + digest[3] += d; + } +} diff --git a/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcphashsha1px.c b/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcphashsha1px.c new file mode 100644 index 0000000000..77b7c184e1 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcphashsha1px.c @@ -0,0 +1,174 @@ +/* +* Copyright (C) 2016 Intel Corporation. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in +* the documentation and/or other materials provided with the +* distribution. +* * Neither the name of Intel Corporation nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ + +#include "owndefs.h" +#include "owncp.h" +#include "pcphash.h" +#include "pcptool.h" + + +/* +// Magic functions defined in FIPS 180-1 +// +*/ +#define MAGIC_F0(B,C,D) (((B) & (C)) | ((~(B)) & (D))) +#define MAGIC_F1(B,C,D) ((B) ^ (C) ^ (D)) +#define MAGIC_F2(B,C,D) (((B) & (C)) | ((B) & (D)) | ((C) & (D))) +#define MAGIC_F3(B,C,D) ((B) ^ (C) ^ (D)) + +#define SHA1_STEP(A,B,C,D,E, MAGIC_FUN, W,K) \ + (E)+= ROL32((A),5) + MAGIC_FUN((B),(C),(D)) + (W) + (K); \ + (B) = ROL32((B),30) + +#define COMPACT_SHA1_STEP(A,B,C,D,E, MAGIC_FUN, W,K, t) { \ + Ipp32u _T = ROL32((A),5) + MAGIC_FUN((t)/20, (B),(C),(D)) + (E) + (W)[(t)] + (K)[(t)/20]; \ + (E) = (D); \ + (D) = (C); \ + (C) = ROL32((B),30); \ + (B) = (A); \ + (A) = _T; \ +} + +#if defined(_ALG_SHA1_COMPACT_) +__INLINE Ipp32u MagicFun(int s, Ipp32u b, Ipp32u c, Ipp32u d) +{ + switch(s) { + case 0: return MAGIC_F0(b,c,d); + case 2: return MAGIC_F2(b,c,d); + default:return MAGIC_F1(b,c,d); + } +} +#endif + + +/*F* +// Name: UpdateSHA1 +// +// Purpose: Update internal hash according to input message stream. +// +// Parameters: +// uniHash pointer to in/out hash +// mblk pointer to message stream +// mlen message stream length (multiple by message block size) +// uniParam pointer to the optional parameter +// +*F*/ +#if defined(_ALG_SHA1_COMPACT_) +#pragma message("SHA1 compact") +#endif + +void UpdateSHA1(void* uinHash, const Ipp8u* mblk, int mlen, const void *uniParam) +{ + Ipp32u* data = (Ipp32u*)mblk; + + Ipp32u* digest = (Ipp32u*)uinHash; + Ipp32u* SHA1_cnt_loc = (Ipp32u*)uniParam; + + for(; mlen>=MBS_SHA1; data += MBS_SHA1/sizeof(Ipp32u), mlen -= MBS_SHA1) { + int t; + + /* + // expand message block + */ + Ipp32u W[80]; + /* initialize the first 16 words in the array W (remember about endian) */ + for(t=0; t<16; t++) { + #if (IPP_ENDIAN == IPP_BIG_ENDIAN) + W[t] = data[t]; + #else + W[t] = ENDIANNESS(data[t]); + #endif + } + /* schedule another 80-16 words in the array W */ + for(; t<80; t++) { + W[t] = ROL32(W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16], 1); + } + + /* + // update hash + */ + { + /* init A, B, C, D, E by the the input hash */ + Ipp32u A = digest[0]; + Ipp32u B = digest[1]; + Ipp32u C = digest[2]; + Ipp32u D = digest[3]; + Ipp32u E = digest[4]; + + #if defined(_ALG_SHA1_COMPACT_) + /* steps 0-79 */ + for(t=0; t<80; t++) + COMPACT_SHA1_STEP(A,B,C,D,E, MagicFun, W, SHA1_cnt_loc, t); + + #else + /* perform 0-19 steps */ + for(t=0; t<20; t+=5) { + SHA1_STEP(A,B,C,D,E, MAGIC_F0, W[t ],SHA1_cnt_loc[0]); + SHA1_STEP(E,A,B,C,D, MAGIC_F0, W[t+1],SHA1_cnt_loc[0]); + SHA1_STEP(D,E,A,B,C, MAGIC_F0, W[t+2],SHA1_cnt_loc[0]); + SHA1_STEP(C,D,E,A,B, MAGIC_F0, W[t+3],SHA1_cnt_loc[0]); + SHA1_STEP(B,C,D,E,A, MAGIC_F0, W[t+4],SHA1_cnt_loc[0]); + } + /* perform 20-39 steps */ + for(; t<40; t+=5) { + SHA1_STEP(A,B,C,D,E, MAGIC_F1, W[t ],SHA1_cnt_loc[1]); + SHA1_STEP(E,A,B,C,D, MAGIC_F1, W[t+1],SHA1_cnt_loc[1]); + SHA1_STEP(D,E,A,B,C, MAGIC_F1, W[t+2],SHA1_cnt_loc[1]); + SHA1_STEP(C,D,E,A,B, MAGIC_F1, W[t+3],SHA1_cnt_loc[1]); + SHA1_STEP(B,C,D,E,A, MAGIC_F1, W[t+4],SHA1_cnt_loc[1]); + } + /* perform 40-59 steps */ + for(; t<60; t+=5) { + SHA1_STEP(A,B,C,D,E, MAGIC_F2, W[t ],SHA1_cnt_loc[2]); + SHA1_STEP(E,A,B,C,D, MAGIC_F2, W[t+1],SHA1_cnt_loc[2]); + SHA1_STEP(D,E,A,B,C, MAGIC_F2, W[t+2],SHA1_cnt_loc[2]); + SHA1_STEP(C,D,E,A,B, MAGIC_F2, W[t+3],SHA1_cnt_loc[2]); + SHA1_STEP(B,C,D,E,A, MAGIC_F2, W[t+4],SHA1_cnt_loc[2]); + } + /* perform 60-79 steps */ + for(; t<80; t+=5) { + SHA1_STEP(A,B,C,D,E, MAGIC_F3, W[t ],SHA1_cnt_loc[3]); + SHA1_STEP(E,A,B,C,D, MAGIC_F3, W[t+1],SHA1_cnt_loc[3]); + SHA1_STEP(D,E,A,B,C, MAGIC_F3, W[t+2],SHA1_cnt_loc[3]); + SHA1_STEP(C,D,E,A,B, MAGIC_F3, W[t+3],SHA1_cnt_loc[3]); + SHA1_STEP(B,C,D,E,A, MAGIC_F3, W[t+4],SHA1_cnt_loc[3]); + } + #endif + + /* update digest */ + digest[0] += A; + digest[1] += B; + digest[2] += C; + digest[3] += D; + digest[4] += E; + } + } +} diff --git a/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcphashsha256px.c b/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcphashsha256px.c new file mode 100644 index 0000000000..932b9cb335 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcphashsha256px.c @@ -0,0 +1,199 @@ +/* +* Copyright (C) 2016 Intel Corporation. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in +* the documentation and/or other materials provided with the +* distribution. +* * Neither the name of Intel Corporation nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ + +#include "owndefs.h" +#include "owncp.h" +#include "pcphash.h" +#include "pcptool.h" + + +/* +// SHA256 Specific Macros (reference proposal 256-384-512) +*/ +#define CH(x,y,z) (((x) & (y)) ^ (~(x) & (z))) +#define MAJ(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z))) + +#define SUM0(x) (ROR32((x), 2) ^ ROR32((x),13) ^ ROR32((x),22)) +#define SUM1(x) (ROR32((x), 6) ^ ROR32((x),11) ^ ROR32((x),25)) + +#define SIG0(x) (ROR32((x), 7) ^ ROR32((x),18) ^ LSR32((x), 3)) +#define SIG1(x) (ROR32((x),17) ^ ROR32((x),19) ^ LSR32((x),10)) + +#define SHA256_UPDATE(i) \ + wdat[i & 15] += SIG1(wdat[(i+14)&15]) + wdat[(i+9)&15] + SIG0(wdat[(i+1)&15]) + +#define SHA256_STEP(i,j) \ + v[(7 - i) & 7] += (j ? SHA256_UPDATE(i) : wdat[i&15]) \ + + SHA256_cnt_loc[i + j] \ + + SUM1(v[(4-i)&7]) \ + + CH(v[(4-i)&7], v[(5-i)&7], v[(6-i)&7]); \ + v[(3-i)&7] += v[(7-i)&7]; \ + v[(7-i)&7] += SUM0(v[(0-i)&7]) + MAJ(v[(0-i)&7], v[(1-i)&7], v[(2-i)&7]) + +#define COMPACT_SHA256_STEP(A,B,C,D,E,F,G,H, W,K, r) { \ + Ipp32u _T1 = (H) + SUM1((E)) + CH((E),(F),(G)) + (W)[(r)] + (K)[(r)]; \ + Ipp32u _T2 = SUM0((A)) + MAJ((A),(B),(C)); \ + (H) = (G); \ + (G) = (F); \ + (F) = (E); \ + (E) = (D)+_T1; \ + (D) = (C); \ + (C) = (B); \ + (B) = (A); \ + (A) = _T1+_T2; \ +} + +/*F* +// Name: UpdateSHA256 +// +// Purpose: Update internal hash according to input message stream. +// +// Parameters: +// uniHash pointer to in/out hash +// mblk pointer to message stream +// mlen message stream length (multiple by message block size) +// uniParam pointer to the optional parameter +// +*F*/ +#if defined(_ALG_SHA256_COMPACT_) +#pragma message("SHA256 compact") + +void UpdateSHA256(void* uniHash, const Ipp8u* mblk, int mlen, const void* uniParam) +{ + Ipp32u* data = (Ipp32u*)mblk; + + Ipp32u* digest = (Ipp32u*)uniHash; + Ipp32u* SHA256_cnt_loc = (Ipp32u*)uniParam; + + for(; mlen>=MBS_SHA256; data += MBS_SHA256/sizeof(Ipp32u), mlen -= MBS_SHA256) { + int t; + + /* + // expand message block + */ + Ipp32u W[64]; + /* initialize the first 16 words in the array W (remember about endian) */ + for(t=0; t<16; t++) { + #if (IPP_ENDIAN == IPP_BIG_ENDIAN) + W[t] = data[t]; + #else + W[t] = ENDIANNESS( data[t] ); + #endif + } + for(; t<64; t++) + W[t] = SIG1(W[t-2]) + W[t-7] + SIG0(W[t-15]) + W[t-16]; + + /* + // update hash + */ + { + /* init A, B, C, D, E, F, G, H by the input hash */ + Ipp32u A = digest[0]; + Ipp32u B = digest[1]; + Ipp32u C = digest[2]; + Ipp32u D = digest[3]; + Ipp32u E = digest[4]; + Ipp32u F = digest[5]; + Ipp32u G = digest[6]; + Ipp32u H = digest[7]; + + for(t=0; t<64; t++) + COMPACT_SHA256_STEP(A,B,C,D,E,F,G,H, W,SHA256_cnt_loc, t); + + /* update hash*/ + digest[0] += A; + digest[1] += B; + digest[2] += C; + digest[3] += D; + digest[4] += E; + digest[5] += F; + digest[6] += G; + digest[7] += H; + } + } +} + +#else +void UpdateSHA256(void* uniHash, const Ipp8u* mblk, int mlen, const void* uniParam) +{ + Ipp32u* data = (Ipp32u*)mblk; + + Ipp32u* digest = (Ipp32u*)uniHash; + Ipp32u* SHA256_cnt_loc = (Ipp32u*)uniParam; + + for(; mlen>=MBS_SHA256; data += MBS_SHA256/sizeof(Ipp32u), mlen -= MBS_SHA256) { + Ipp32u wdat[16]; + int j; + + /* copy digest */ + Ipp32u v[8]; + CopyBlock(digest, v, IPP_SHA256_DIGEST_BITSIZE/BYTESIZE); + + /* initialize the first 16 words in the array W (remember about endian) */ + for(j=0; j<16; j++) { + #if (IPP_ENDIAN == IPP_BIG_ENDIAN) + wdat[j] = data[j]; + #else + wdat[j] = ENDIANNESS( data[j] ); + #endif + } + + for(j=0; j<64; j+=16) { + SHA256_STEP( 0, j); + SHA256_STEP( 1, j); + SHA256_STEP( 2, j); + SHA256_STEP( 3, j); + SHA256_STEP( 4, j); + SHA256_STEP( 5, j); + SHA256_STEP( 6, j); + SHA256_STEP( 7, j); + SHA256_STEP( 8, j); + SHA256_STEP( 9, j); + SHA256_STEP(10, j); + SHA256_STEP(11, j); + SHA256_STEP(12, j); + SHA256_STEP(13, j); + SHA256_STEP(14, j); + SHA256_STEP(15, j); + } + + /* update digest */ + digest[0] += v[0]; + digest[1] += v[1]; + digest[2] += v[2]; + digest[3] += v[3]; + digest[4] += v[4]; + digest[5] += v[5]; + digest[6] += v[6]; + digest[7] += v[7]; + } +} +#endif diff --git a/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcphashsha512px.c b/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcphashsha512px.c new file mode 100644 index 0000000000..6b8983d467 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcphashsha512px.c @@ -0,0 +1,207 @@ +/* +* Copyright (C) 2016 Intel Corporation. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in +* the documentation and/or other materials provided with the +* distribution. +* * Neither the name of Intel Corporation nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ + +#include "owndefs.h" +#include "owncp.h" +#include "pcphash.h" +#include "pcptool.h" + + +/* +// SHA512 Specific Macros (reference proposal 256-384-512) +// +// Note: All operations act on DWORDs (64-bits) +*/ +#define CH(x,y,z) (((x) & (y)) ^ (~(x) & (z))) +#define MAJ(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z))) + +#define SUM0(x) (ROR64((x),28) ^ ROR64((x),34) ^ ROR64((x),39)) +#define SUM1(x) (ROR64((x),14) ^ ROR64((x),18) ^ ROR64((x),41)) + +#define SIG0(x) (ROR64((x), 1) ^ ROR64((x), 8) ^ LSR64((x), 7)) +#define SIG1(x) (ROR64((x),19) ^ ROR64((x),61) ^ LSR64((x), 6)) + +#define SHA512_UPDATE(i) \ + wdat[i&15] += SIG1(wdat[(i+14)&15]) + wdat[(i+9)&15] + SIG0(wdat[(i+1)&15]) + +#define SHA512_STEP(i,j) \ + v[(7-i)&7] += (j ? SHA512_UPDATE(i) : wdat[i&15]) \ + + SHA512_cnt_loc[i+j] \ + + SUM1(v[(4-i)&7]) \ + + CH(v[(4-i)&7], v[(5-i)&7], v[(6-i)&7]); \ + v[(3-i)&7] += v[(7-i)&7]; \ + v[(7-i)&7] += SUM0(v[(0-i)&7]) + MAJ(v[(0-i)&7], v[(1-i)&7], v[(2-i)&7]) + +#define COMPACT_SHA512_STEP(A,B,C,D,E,F,G,H, W,K, r) { \ + Ipp64u _T1 = (H) + SUM1((E)) + CH((E),(F),(G)) + (W)[(r)] + (K)[(r)]; \ + Ipp64u _T2 = SUM0((A)) + MAJ((A),(B),(C)); \ + (H) = (G); \ + (G) = (F); \ + (F) = (E); \ + (E) = (D)+_T1; \ + (D) = (C); \ + (C) = (B); \ + (B) = (A); \ + (A) = _T1+_T2; \ +} + +/*F* +// Name: UpdateSHA512 +// +// Purpose: Update internal hash according to input message stream. +// +// Parameters: +// uniHash pointer to in/out hash +// mblk pointer to message stream +// mlen message stream length (multiple by message block size) +// uniParam pointer to the optional parameter +// +*F*/ +#if defined(_ALG_SHA512_COMPACT_) +#pragma message("SHA512 compact") + +void UpdateSHA512(void* uniHash, const Ipp8u* mblk, int mlen, const void* uniPraram) +{ + Ipp32u* data = (Ipp32u*)mblk; + + Ipp64u* digest = (Ipp64u*)uniHash; + Ipp64u* SHA512_cnt_loc = (Ipp64u*)uniPraram; + + + for(; mlen>=MBS_SHA512; data += MBS_SHA512/sizeof(Ipp32u), mlen -= MBS_SHA512) { + int t; + Ipp64u W[80]; + + /* + // expand message block + */ + /* initialize the first 16 words in the array W (remember about endian) */ + for(t=0; t<16; t++) { + Ipp32u hiX = data[2*t]; + Ipp32u loX = data[2*t+1]; + #if (IPP_ENDIAN == IPP_BIG_ENDIAN) + W[t] = MAKEDWORD(loX, hiX); + #else + W[t] = MAKEDWORD( ENDIANNESS(loX), ENDIANNESS(hiX) ); + #endif + } + for(; t<80; t++) + W[t] = SIG1(W[t-2]) + W[t-7] + SIG0(W[t-15]) + W[t-16]; + + /* + // update hash + */ + { + /* init A, B, C, D, E, F, G, H by the input hash */ + Ipp64u A = digest[0]; + Ipp64u B = digest[1]; + Ipp64u C = digest[2]; + Ipp64u D = digest[3]; + Ipp64u E = digest[4]; + Ipp64u F = digest[5]; + Ipp64u G = digest[6]; + Ipp64u H = digest[7]; + + for(t=0; t<80; t++) + COMPACT_SHA512_STEP(A,B,C,D,E,F,G,H, W,SHA512_cnt_loc, t); + + /* update hash*/ + digest[0] += A; + digest[1] += B; + digest[2] += C; + digest[3] += D; + digest[4] += E; + digest[5] += F; + digest[6] += G; + digest[7] += H; + } + } +} + +#else +void UpdateSHA512(void* uniHash, const Ipp8u* mblk, int mlen, const void* uniPraram) +{ + Ipp32u* data = (Ipp32u*)mblk; + + Ipp64u* digest = (Ipp64u*)uniHash; + Ipp64u* SHA512_cnt_loc = (Ipp64u*)uniPraram; + + for(; mlen>=MBS_SHA512; data += MBS_SHA512/sizeof(Ipp32u), mlen -= MBS_SHA512) { + Ipp64u wdat[16]; + int j; + + Ipp64u v[8]; + + /* initialize the first 16 words in the array W (remember about endian) */ + for(j=0; j<16; j++) { + Ipp32u hiX = data[2*j]; + Ipp32u loX = data[2*j+1]; + #if (IPP_ENDIAN == IPP_BIG_ENDIAN) + wdat[j] = MAKEDWORD(loX, hiX); + #else + wdat[j] = MAKEDWORD( ENDIANNESS(loX), ENDIANNESS(hiX) ); + #endif + } + + /* copy digest */ + CopyBlock(digest, v, IPP_SHA512_DIGEST_BITSIZE/BYTESIZE); + + for(j=0; j<80; j+=16) { + SHA512_STEP( 0, j); + SHA512_STEP( 1, j); + SHA512_STEP( 2, j); + SHA512_STEP( 3, j); + SHA512_STEP( 4, j); + SHA512_STEP( 5, j); + SHA512_STEP( 6, j); + SHA512_STEP( 7, j); + SHA512_STEP( 8, j); + SHA512_STEP( 9, j); + SHA512_STEP(10, j); + SHA512_STEP(11, j); + SHA512_STEP(12, j); + SHA512_STEP(13, j); + SHA512_STEP(14, j); + SHA512_STEP(15, j); + } + + /* update digest */ + digest[0] += v[0]; + digest[1] += v[1]; + digest[2] += v[2]; + digest[3] += v[3]; + digest[4] += v[4]; + digest[5] += v[5]; + digest[6] += v[6]; + digest[7] += v[7]; + } +} +#endif diff --git a/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcphmac.h b/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcphmac.h new file mode 100644 index 0000000000..65374dbb87 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcphmac.h @@ -0,0 +1,55 @@ +/* +* Copyright (C) 2016 Intel Corporation. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in +* the documentation and/or other materials provided with the +* distribution. +* * Neither the name of Intel Corporation nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ + +#if !defined(_PCP_HMAC_H) +#define _PCP_HMAC_H + +#include "pcphash.h" + +/* +// HMAC context +*/ +struct _cpHMAC { + IppCtxId idCtx; /* HMAC identifier */ + Ipp8u ipadKey[MBS_HASH_MAX]; /* inner padding key */ + Ipp8u opadKey[MBS_HASH_MAX]; /* outer padding key */ + IppsHashState hashCtx; /* hash context */ +}; + +/* accessors */ +#define HMAC_CTX_ID(stt) ((stt)->idCtx) +#define HASH_CTX(stt) ((stt)->hashCtx) +#define HMAC_VALID_ID(stt) (HMAC_CTX_ID((stt))==idCtxHMAC) + +#define IPAD (0x36) /* inner padding value */ +#define OPAD (0x5C) /* outer padding value */ + +#endif /* _PCP_HMAC_H */ diff --git a/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcphmacca.c b/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcphmacca.c new file mode 100644 index 0000000000..524d26f49b --- /dev/null +++ b/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcphmacca.c @@ -0,0 +1,332 @@ +/* +* Copyright (C) 2016 Intel Corporation. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in +* the documentation and/or other materials provided with the +* distribution. +* * Neither the name of Intel Corporation nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ + +#include "owndefs.h" +#include "owncp.h" +#include "pcphmac.h" +#include "pcptool.h" + +/*F* +// Name: ippsHMAC_GetSize +// +// Purpose: Returns size of HMAC state (bytes). +// +// Returns: Reason: +// ippStsNullPtrErr pSzie == NULL +// ippStsNoErr no errors +// +// Parameters: +// pSize pointer to the HMAC state size +// +*F*/ +IPPFUN(IppStatus, ippsHMAC_GetSize,(int* pSize)) +{ + /* test size's pointer */ + IPP_BAD_PTR1_RET(pSize); + + *pSize = sizeof(IppsHMACState); + return ippStsNoErr; +} + +/*F* +// Name: ippsHMAC_Init +// +// Purpose: Init HMAC state. +// +// Returns: Reason: +// ippStsNullPtrErr pKey == NULL +// pState == NULL +// ippStsLengthErr keyLen <0 +// ippStsNotSupportedModeErr if algID is not match to supported hash alg +// ippStsNoErr no errors +// +// Parameters: +// pKey pointer to the secret key +// keyLen length (bytes) of the secret key +// pState pointer to the HMAC state +// hashAlg hash alg ID +// +*F*/ +IPPFUN(IppStatus, ippsHMAC_Init,(const Ipp8u* pKey, int keyLen, IppsHMACState* pCtx, IppHashAlgId hashAlg)) +{ + //int mbs; + + /* get algorithm id */ + hashAlg = cpValidHashAlg(hashAlg); + /* test hash alg */ + IPP_BADARG_RET(ippHashAlg_Unknown==hashAlg, ippStsNotSupportedModeErr); + //mbs = cpHashMBS(hashAlg); + + /* test pState pointer */ + IPP_BAD_PTR1_RET(pCtx); + + /* test key pointer and key length */ + IPP_BAD_PTR1_RET(pKey); + IPP_BADARG_RET(0>keyLen, ippStsLengthErr); + + /* set state ID */ + HMAC_CTX_ID(pCtx) = idCtxHMAC; + + /* init hash context */ + ippsHashInit(&HASH_CTX(pCtx), hashAlg); + + { + int n; + + /* hash specific */ + IppsHashState* pHashCtx = &HASH_CTX(pCtx); + int mbs = cpHashMBS(hashAlg); + int hashSize = cpHashSize(hashAlg); + + /* copyMask = keyLen>mbs? 0xFF : 0x00 */ + int copyMask = (mbs-keyLen) >>(BITSIZE(int)-1); + + /* actualKeyLen = keyLen>mbs? hashSize:keyLen */ + int actualKeyLen = (hashSize & copyMask) | (keyLen & ~copyMask); + + /* compute hash(key, keyLen) just in case */ + ippsHashUpdate(pKey, keyLen, pHashCtx); + ippsHashFinal(HASH_BUFF(pHashCtx), pHashCtx); + + /* copy either key or hash(key) into ipad- and opad- buffers */ + MASKED_COPY_BNU(pCtx->ipadKey, (Ipp8u)copyMask, HASH_BUFF(pHashCtx), pKey, actualKeyLen); + MASKED_COPY_BNU(pCtx->opadKey, (Ipp8u)copyMask, HASH_BUFF(pHashCtx), pKey, actualKeyLen); + + /* XOR-ing key */ + for(n=0; nipadKey[n] ^= (Ipp8u)IPAD; + pCtx->opadKey[n] ^= (Ipp8u)OPAD; + } + for(; nipadKey[n] = (Ipp8u)IPAD; + pCtx->opadKey[n] = (Ipp8u)OPAD; + } + + /* ipad key processing */ + ippsHashUpdate(pCtx->ipadKey, mbs, pHashCtx); + + return ippStsNoErr; + } +} + +/*F* +// Name: ippsHMAC_Update +// +// Purpose: Updates intermadiate MAC based on input stream. +// +// Returns: Reason: +// ippStsNullPtrErr pSrc == NULL +// pState == NULL +// ippStsContextMatchErr pState->idCtx != idCtxHMAC +// ippStsLengthErr len <0 +// ippStsNoErr no errors +// +// Parameters: +// pSrc pointer to the input stream +// len input stream length +// pState pointer to the HMAC state +// +*F*/ +IPPFUN(IppStatus, ippsHMAC_Update,(const Ipp8u* pSrc, int len, IppsHMACState* pCtx)) +{ + /* test state pointers */ + IPP_BAD_PTR1_RET(pCtx); + + /* test state ID */ + IPP_BADARG_RET(!HMAC_VALID_ID(pCtx), ippStsContextMatchErr); + /* test input length */ + IPP_BADARG_RET((len<0), ippStsLengthErr); + /* test source pointer */ + IPP_BADARG_RET((len && !pSrc), ippStsNullPtrErr); + + if(len) + return ippsHashUpdate(pSrc, len, &HASH_CTX(pCtx)); + else + return ippStsNoErr; +} + +/*F* +// Name: ippsHMAC_Final +// +// Purpose: Stop message digesting and return digest. +// +// Returns: Reason: +// ippStsNullPtrErr pMD == NULL +// pState == NULL +// ippStsContextMatchErr pState->idCtx != idCtxHMAC +// ippStsLengthErr sizeof(DigestMD5) < mdLen <1 +// ippStsNoErr no errors +// +// Parameters: +// pMD address of the output digest +// pState pointer to the HMAC state +// +*F*/ +IPPFUN(IppStatus, ippsHMAC_Final,(Ipp8u* pMD, int mdLen, IppsHMACState* pCtx)) +{ + /* test state pointer and ID */ + IPP_BAD_PTR1_RET(pCtx); + IPP_BADARG_RET(!HMAC_VALID_ID(pCtx), ippStsContextMatchErr); + + /* test MD pointer and length */ + IPP_BAD_PTR1_RET(pMD); + IPP_BADARG_RET(mdLen<=0, ippStsLengthErr); + + { + /* hash specific */ + IppsHashState* pHashCtx = &HASH_CTX(pCtx); + int mbs = cpHashMBS(HASH_ALG_ID(pHashCtx)); + int hashSize = cpHashSize(HASH_ALG_ID(pHashCtx)); + if(mdLen>hashSize) + IPP_ERROR_RET(ippStsLengthErr); + + /* + // finalize hmac + */ + { + /* finalize 1-st step */ + Ipp8u md[IPP_SHA512_DIGEST_BITSIZE/8]; + IppStatus sts = ippsHashFinal(md, pHashCtx); + + if(ippStsNoErr==sts) { + /* perform outer hash */ + ippsHashUpdate(pCtx->opadKey, mbs, pHashCtx); + ippsHashUpdate(md, hashSize, pHashCtx); + + /* complete HMAC */ + ippsHashFinal(md, pHashCtx); + CopyBlock(md, pMD, IPP_MIN(hashSize, mdLen)); + + /* ready to the next HMAC computation */ + ippsHashUpdate(pCtx->ipadKey, mbs, pHashCtx); + } + + return sts; + } + } +} + +/*F* +// Name: ippsHMAC_GetTag +// +// Purpose: Compute digest with further digesting ability. +// +// Returns: Reason: +// ippStsNullPtrErr pMD == NULL +// pState == NULL +// ippStsContextMatchErr pState->idCtx != idCtxHMAC +// ippStsLengthErr size_of_digest < mdLen <1 +// ippStsNoErr no errors +// +// Parameters: +// pMD address of the output digest +// mdLen length of the digest +// pState pointer to the HMAC state +// +*F*/ +IPPFUN(IppStatus, ippsHMAC_GetTag,(Ipp8u* pMD, int mdLen, const IppsHMACState* pCtx)) +{ + /* test state pointer and ID */ + IPP_BAD_PTR1_RET(pCtx); + IPP_BADARG_RET(!HMAC_VALID_ID(pCtx), ippStsContextMatchErr); + + /* test MD pointer */ + IPP_BAD_PTR1_RET(pMD); + + { + IppsHMACState tmpCtx; + CopyBlock(pCtx, &tmpCtx, sizeof(IppsHMACState)); + return ippsHMAC_Final(pMD, mdLen, &tmpCtx); + } +} + +/*F* +// Name: ippsHMAC_Message +// +// Purpose: MAC of the whole message. +// +// Returns: Reason: +// ippStsNullPtrErr pMsg == NULL +// pKey == NULL +// pMD == NULL +// ippStsLengthErr msgLen <0 +// keyLen <0 +// size_of_digest < mdLen <1 +// ippStsNotSupportedModeErr if algID is not match to supported hash alg +// ippStsNoErr no errors +// +// Parameters: +// pMsg pointer to the input message +// msgLen input message length +// pKey pointer to the secret key +// keyLen secret key length +// pMD pointer to message digest +// mdLen MD length +// hashAlg hash alg ID +// +*F*/ +IPPFUN(IppStatus, ippsHMAC_Message,(const Ipp8u* pMsg, int msgLen, + const Ipp8u* pKey, int keyLen, + Ipp8u* pMD, int mdLen, + IppHashAlgId hashAlg)) +{ + /* get algorithm id */ + hashAlg = cpValidHashAlg(hashAlg); + /* test hash alg */ + IPP_BADARG_RET(ippHashAlg_Unknown==hashAlg, ippStsNotSupportedModeErr); + + /* test secret key pointer and length */ + IPP_BAD_PTR1_RET(pKey); + IPP_BADARG_RET((keyLen<0), ippStsLengthErr); + + /* test input message pointer and length */ + IPP_BADARG_RET((msgLen<0), ippStsLengthErr); + IPP_BADARG_RET((msgLen && !pMsg), ippStsNullPtrErr); + + /* test MD pointer and length */ + IPP_BAD_PTR1_RET(pMD); + IPP_BADARG_RET(0>=mdLen || mdLen>cpHashSize(hashAlg), ippStsLengthErr); + + { + IppsHMACState ctx; + IppStatus sts = ippsHMAC_Init(pKey, keyLen, &ctx, hashAlg); + if(ippStsNoErr!=sts) goto exit; + + sts = ippsHashUpdate(pMsg,msgLen, &HASH_CTX(&ctx)); + if(ippStsNoErr!=sts) goto exit; + + sts = ippsHMAC_Final(pMD, mdLen, &ctx); + + exit: + PurgeBlock(&ctx, sizeof(IppsHMACState)); + return sts; + } +} diff --git a/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpmontexpbinca.c b/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpmontexpbinca.c new file mode 100644 index 0000000000..fdc43b5127 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpmontexpbinca.c @@ -0,0 +1,116 @@ +/* +* Copyright (C) 2016 Intel Corporation. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in +* the documentation and/or other materials provided with the +* distribution. +* * Neither the name of Intel Corporation nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ + +#include "owndefs.h" +#include "owncp.h" +#include "pcpbn.h" +#include "pcpmontgomery.h" + + +/* +// Binary method of Exponentiation +*/ +cpSize cpMontExpBin_BNU(BNU_CHUNK_T* dataY, + const BNU_CHUNK_T* dataX, cpSize nsX, + const BNU_CHUNK_T* dataE, cpSize nsE, + IppsMontState* pMont) +{ + cpSize nsM = MNT_SIZE(pMont); + + /* + // test for special cases: + // x^0 = 1 + // 0^e = 0 + */ + if( cpEqu_BNU_CHUNK(dataE, nsE, 0) ) { + COPY_BNU(dataY, MNT_1(pMont), nsM); + } + else if( cpEqu_BNU_CHUNK(dataX, nsX, 0) ) { + ZEXPAND_BNU(dataY, 0, nsM); + } + + /* general case */ + else { + BNU_CHUNK_T* dataM = MNT_MODULUS(pMont); + BNU_CHUNK_T m0 = MNT_HELPER(pMont); + + /* Montgomery engine buffers */ + BNU_CHUNK_T* pKBuffer = MNT_KBUFFER(pMont); + BNU_CHUNK_T* pProduct = MNT_PRODUCT(pMont); + + BNU_CHUNK_T* dataT = MNT_TBUFFER(pMont); + + /* execute most significant part pE */ + BNU_CHUNK_T eValue = dataE[nsE-1]; + int n = cpNLZ_BNU(eValue)+1; + + /* expand base and init result */ + ZEXPAND_COPY_BNU(dataT, nsM, dataX, nsX); + COPY_BNU(dataY, dataT, nsM); + + eValue <<= n; + for(; n0; nsE--) { + eValue = dataE[nsE-1]; + + for(n=0; nidCtx) +#define MNT_ROOM(eng) ((eng)->maxLen) +#define MNT_SIZE(eng) ((eng)->modLen) +#define MNT_HELPER(eng) ((eng)->m0) +#define MNT_MODULUS(eng) ((eng)->pModulus) +#define MNT_1(eng) ((eng)->pIdentity) +#define MNT_IDENT_R(eng) (MNT_1((eng))) +#define MNT_SQUARE_R(eng) ((eng)->pSquare) +#define MNT_CUBE_R(eng) ((eng)->pCube) +#define MNT_TBUFFER(eng) ((eng)->pTBuffer) +#define MNT_SBUFFER(eng) ((eng)->pSBuffer) +#define MNT_PRODUCT(eng) ((eng)->pProduct) +#define MNT_KBUFFER(eng) ((eng)->pKBuffer) + +#define MNT_VALID_ID(eng) (MNT_ID((eng))==idCtxMontgomery) + +/* default methos */ +#define EXPONENT_METHOD (ippBinaryMethod) + +/* alignment */ +#define MONT_ALIGNMENT ((int)(sizeof(void*))) + + +/* +// Pacp/unpack Montgomery context +*/ +void cpPackMontCtx(const IppsMontState* pCtx, Ipp8u* pBuffer); +void cpUnpackMontCtx(const Ipp8u* pBuffer, IppsMontState* pCtx); + + +/* +// Montgomery reduction, multiplication and squaring +*/ +void cpMontRedAdc_BNU(BNU_CHUNK_T* pR, + BNU_CHUNK_T* pProduct, + const BNU_CHUNK_T* pModulus, cpSize nsM, BNU_CHUNK_T m0); + +__INLINE void cpMontRed_BNU(BNU_CHUNK_T* pR, + BNU_CHUNK_T* pProduct, + const BNU_CHUNK_T* pModulus, cpSize nsM, BNU_CHUNK_T m0) +{ + cpMontRedAdc_BNU(pR, pProduct, pModulus, nsM, m0); +} + +__INLINE void cpMontMul_BNU(BNU_CHUNK_T* pR, + const BNU_CHUNK_T* pX, cpSize nsX, + const BNU_CHUNK_T* pY, cpSize nsY, + const BNU_CHUNK_T* pModulus, cpSize nsM, BNU_CHUNK_T m0, + BNU_CHUNK_T* pProduct, BNU_CHUNK_T* pKBuffer) +{ + cpMul_BNU(pProduct, pX,nsX, pY,nsY, pKBuffer); + ZEXPAND_BNU(pProduct,nsX+nsY, 2*nsM); + cpMontRed_BNU(pR, pProduct, pModulus, nsM, m0); +} + +__INLINE void cpMontSqr_BNU(BNU_CHUNK_T* pR, + const BNU_CHUNK_T* pX, cpSize nsX, + const BNU_CHUNK_T* pModulus, cpSize nsM, BNU_CHUNK_T m0, + BNU_CHUNK_T* pProduct, BNU_CHUNK_T* pKBuffer) +{ + cpSqr_BNU(pProduct, pX,nsX, pKBuffer); + ZEXPAND_BNU(pProduct, 2*nsX, 2*nsM); + cpMontRed_BNU(pR, pProduct, pModulus, nsM, m0); +} + +/* +// Montgomery encoding/decoding +*/ +__INLINE cpSize cpMontEnc_BNU(BNU_CHUNK_T* pR, + const BNU_CHUNK_T* pXreg, cpSize nsX, + IppsMontState* pMont) +{ + cpSize nsM = MNT_SIZE(pMont); + cpMontMul_BNU(pR, + pXreg, nsX, MNT_SQUARE_R(pMont), nsM, + MNT_MODULUS(pMont), nsM, MNT_HELPER(pMont), + MNT_PRODUCT(pMont), MNT_KBUFFER(pMont)); + + FIX_BNU(pR, nsM); + return nsM; +} + +__INLINE cpSize cpMontDec_BNU(BNU_CHUNK_T* pR, + const BNU_CHUNK_T* pXmont, cpSize nsX, + IppsMontState* pMont) +{ + cpSize nsM = MNT_SIZE(pMont); + ZEXPAND_COPY_BNU(MNT_PRODUCT(pMont), 2*nsM, pXmont, nsX); + + cpMontRed_BNU(pR, MNT_PRODUCT(pMont), MNT_MODULUS(pMont), nsM, MNT_HELPER(pMont)); + + FIX_BNU(pR, nsM); + return nsM; +} + +__INLINE void cpMontEnc_BN(IppsBigNumState* pRbn, + const IppsBigNumState* pXbn, + IppsMontState* pMont) +{ + BNU_CHUNK_T* pR = BN_NUMBER(pRbn); + cpSize nsM = MNT_SIZE(pMont); + cpMontMul_BNU(pR, + BN_NUMBER(pXbn), BN_SIZE(pXbn), + MNT_SQUARE_R(pMont), nsM, + MNT_MODULUS(pMont), nsM, MNT_HELPER(pMont), + MNT_PRODUCT(pMont), MNT_KBUFFER(pMont)); + + FIX_BNU(pR, nsM); + BN_SIZE(pRbn) = nsM; + BN_SIGN(pRbn) = ippBigNumPOS; +} + +__INLINE void cpMontDec_BN(IppsBigNumState* pRbn, + const IppsBigNumState* pXbn, + IppsMontState* pMont) +{ + BNU_CHUNK_T* pR = BN_NUMBER(pRbn); + cpSize nsM = MNT_SIZE(pMont); + ZEXPAND_COPY_BNU(MNT_PRODUCT(pMont), 2*nsM, BN_NUMBER(pXbn), BN_SIZE(pXbn)); + + cpMontRed_BNU(pR, MNT_PRODUCT(pMont), MNT_MODULUS(pMont), nsM, MNT_HELPER(pMont)); + + FIX_BNU(pR, nsM); + BN_SIZE(pRbn) = nsM; + BN_SIGN(pRbn) = ippBigNumPOS; +} + +/* +// Montgomery exponentiation (binary) +*/ +cpSize cpMontExpBin_BNU(BNU_CHUNK_T* pY, + const BNU_CHUNK_T* pX, cpSize nsX, + const BNU_CHUNK_T* pE, cpSize nsE, + IppsMontState* pMont); + +#endif /* _CP_MONTGOMETRY_H */ diff --git a/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpmontgomeryca.c b/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpmontgomeryca.c new file mode 100644 index 0000000000..8459fd0249 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpmontgomeryca.c @@ -0,0 +1,296 @@ +/* +* Copyright (C) 2016 Intel Corporation. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in +* the documentation and/or other materials provided with the +* distribution. +* * Neither the name of Intel Corporation nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ + +#include "owndefs.h" +#include "owncp.h" +#include "pcpbn.h" +#include "pcpmontgomery.h" +#include "pcptool.h" + +/*F* +// Name: ippsMontGetSize +// +// Purpose: Specifies size of buffer in bytes. +// +// Returns: Reason: +// ippStsNullPtrErr pCtxSize==NULL +// ippStsLengthErr maxLen32 < 1 +// maxLen32 > BITS2WORD32_SIZE(BN_MAXBITSIZE) +// ippStsNoErr no errors +// +// Parameters: +// method selected exponential method (unused parameter) +// maxLen32 max modulus length (in Ipp32u chunks) +// pCtxSize size of context +// +// Notes: Function always use method=ippBinaryMethod, +// so this parameter is ignored +*F*/ +IPPFUN(IppStatus, ippsMontGetSize, (IppsExpMethod method, cpSize maxLen32, cpSize* pCtxSize)) +{ + IPP_BAD_PTR1_RET(pCtxSize); + IPP_BADARG_RET(maxLen32<1 || maxLen32>BITS2WORD32_SIZE(BN_MAXBITSIZE), ippStsLengthErr); + + UNREFERENCED_PARAMETER(method); + + { + /* convert modulus length to the number of BNU_CHUNK_T */ + cpSize modSize = INTERNAL_BNU_LENGTH(maxLen32); + + *pCtxSize= sizeof(IppsMontState) + + modSize*sizeof(BNU_CHUNK_T) /* modulus */ + + modSize*sizeof(BNU_CHUNK_T) /* identity */ + + modSize*sizeof(BNU_CHUNK_T) /* square R */ + + modSize*sizeof(BNU_CHUNK_T) /* cube R */ + + modSize*sizeof(BNU_CHUNK_T) /* internal buffer */ + + modSize*sizeof(BNU_CHUNK_T) /* internal sscm buffer */ + + modSize*sizeof(BNU_CHUNK_T)*2 /* internal product */ + + MONT_ALIGNMENT-1; + + return ippStsNoErr; + } +} + + +/*F* +// Name: ippsMontInit +// +// Purpose: Initializes the symbolic data structure and partitions the +// specified buffer space. +// +// Returns: Reason: +// ippStsNullPtrErr pMont==NULL +// ippStsLengthErr maxLen32 < 1 +// maxLen32 > BITS2WORD32_SIZE(BN_MAXBITSIZE) +// ippStsNoErr no errors +// +// Parameters: +// method selected exponential method (unused parameter) +// maxLen32 max modulus length (in Ipp32u chunks) +// pMont pointer to Montgomery context +*F*/ +IPPFUN(IppStatus, ippsMontInit,(IppsExpMethod method, int maxLen32, IppsMontState* pMont)) +{ + IPP_BADARG_RET(maxLen32<1 || maxLen32>BITS2WORD32_SIZE(BN_MAXBITSIZE), ippStsLengthErr); + + IPP_BAD_PTR1_RET(pMont); + pMont = (IppsMontState*)( IPP_ALIGNED_PTR(pMont, MONT_ALIGNMENT) ); + + UNREFERENCED_PARAMETER(method); + + MNT_ID(pMont) = idCtxUnknown; + MNT_ROOM(pMont) = INTERNAL_BNU_LENGTH(maxLen32); + MNT_SIZE(pMont) = 0; + MNT_HELPER(pMont) = 0; + + { + Ipp8u* ptr = (Ipp8u*)pMont; + + /* convert modulus length to the number of BNU_CHUNK_T */ + cpSize modSize = MNT_ROOM(pMont); + + /* assign internal buffers */ + MNT_MODULUS(pMont) = (BNU_CHUNK_T*)( ptr += sizeof(IppsMontState) ); + + MNT_1(pMont) = (BNU_CHUNK_T*)( ptr += modSize*sizeof(BNU_CHUNK_T) ); + MNT_SQUARE_R(pMont)= (BNU_CHUNK_T*)( ptr += modSize*sizeof(BNU_CHUNK_T) ); + MNT_CUBE_R(pMont) = (BNU_CHUNK_T*)( ptr += modSize*sizeof(BNU_CHUNK_T) ); + + MNT_TBUFFER(pMont) = (BNU_CHUNK_T*)( ptr += modSize*sizeof(BNU_CHUNK_T) ); + MNT_SBUFFER(pMont) = (BNU_CHUNK_T*)( ptr += modSize*sizeof(BNU_CHUNK_T) ); + MNT_PRODUCT(pMont) = (BNU_CHUNK_T*)( ptr += modSize*sizeof(BNU_CHUNK_T) ); + MNT_KBUFFER(pMont) = (BNU_CHUNK_T*)NULL; + + /* init internal buffers */ + ZEXPAND_BNU(MNT_MODULUS(pMont), 0, modSize); + ZEXPAND_BNU(MNT_1(pMont), 0, modSize); + ZEXPAND_BNU(MNT_SQUARE_R(pMont), 0, modSize); + ZEXPAND_BNU(MNT_CUBE_R(pMont), 0, modSize); + + MNT_ID(pMont) = idCtxMontgomery; + return ippStsNoErr; + } +} + + +/*F* +// Name: ippsMontSet +// +// Purpose: Setup modulus value +// +// Returns: Reason: +// ippStsNullPtrErr pMont==NULL +// pModulus==NULL +// ippStsContextMatchErr !MNT_VALID_ID() +// ippStsLengthErr len32<1 +// ippStsNoErr no errors +// +// Parameters: +// pModulus pointer to the modulus buffer +// len32 length of the modulus (in Ipp32u chunks). +// pMont pointer to the context +*F*/ +static BNU_CHUNK_T cpMontHelper(BNU_CHUNK_T m0) +{ + BNU_CHUNK_T y = 1; + BNU_CHUNK_T x = 2; + BNU_CHUNK_T mask = 2*x-1; + + int i; + for(i=2; i<=BNU_CHUNK_BITS; i++, x<<=1) { + BNU_CHUNK_T rH, rL; + MUL_AB(rH, rL, m0, y); + if( x < (rL & mask) ) /* x < ((m0*y) mod (2*x)) */ + y+=x; + mask += mask + 1; + } + return 0-y; +} + +IPPFUN(IppStatus, ippsMontSet,(const Ipp32u* pModulus, cpSize len32, IppsMontState* pMont)) +{ + IPP_BAD_PTR2_RET(pModulus, pMont); + pMont = (IppsMontState*)(IPP_ALIGNED_PTR((pMont), MONT_ALIGNMENT)); + IPP_BADARG_RET(!MNT_VALID_ID(pMont), ippStsContextMatchErr); + + IPP_BADARG_RET(len32<1, ippStsLengthErr); + + /* modulus is not an odd number */ + IPP_BADARG_RET((pModulus[0] & 1) == 0, ippStsBadModulusErr); + IPP_BADARG_RET(MNT_ROOM(pMont)<(int)(INTERNAL_BNU_LENGTH(len32)), ippStsOutOfRangeErr); + + { + BNU_CHUNK_T m0; + cpSize len; + + /* fix input modulus */ + FIX_BNU(pModulus, len32); + + /* store modulus */ + ZEXPAND_BNU(MNT_MODULUS(pMont), 0, MNT_ROOM(pMont)); + COPY_BNU((Ipp32u*)(MNT_MODULUS(pMont)), pModulus, len32); + /* store modulus length */ + len = INTERNAL_BNU_LENGTH(len32); + MNT_SIZE(pMont) = len; + + /* pre-compute helper m0, m0*m = -1 mod R */ + m0 = cpMontHelper(MNT_MODULUS(pMont)[0]); + MNT_HELPER(pMont) = m0; + + /* setup identity */ + ZEXPAND_BNU(MNT_1(pMont), 0, len); + MNT_1(pMont)[len] = 1; + cpMod_BNU(MNT_1(pMont), len+1, MNT_MODULUS(pMont), len); + + /* setup square */ + ZEXPAND_BNU(MNT_SQUARE_R(pMont), 0, len); + COPY_BNU(MNT_SQUARE_R(pMont)+len, MNT_1(pMont), len); + cpMod_BNU(MNT_SQUARE_R(pMont), 2*len, MNT_MODULUS(pMont), len); + + /* setup cube */ + ZEXPAND_BNU(MNT_CUBE_R(pMont), 0, len); + COPY_BNU(MNT_CUBE_R(pMont)+len, MNT_SQUARE_R(pMont), len); + cpMod_BNU(MNT_CUBE_R(pMont), 2*len, MNT_MODULUS(pMont), len); + + /* clear buffers */ + ZEXPAND_BNU(MNT_TBUFFER(pMont), 0, len); + ZEXPAND_BNU(MNT_SBUFFER(pMont), 0, len); + ZEXPAND_BNU(MNT_PRODUCT(pMont), 0, 2*len); + + return ippStsNoErr; + } +} + + +/*F* +// Name: ippsMontMul +// +// Purpose: Computes Montgomery modular multiplication for positive big +// number integers of Montgomery form. The following pseudocode +// represents this function: +// r <- ( a * b * R^(-1) ) mod m +// +// Returns: Reason: +// ippStsNoErr Returns no error. +// ippStsNullPtrErr Returns an error when pointers are null. +// ippStsBadArgErr Returns an error when a or b is a negative integer. +// ippStsScaleRangeErr Returns an error when a or b is more than m. +// ippStsOutOfRangeErr Returns an error when IppsBigNumState *r is larger than +// IppsMontState *m. +// ippStsContextMatchErr Returns an error when the context parameter does +// not match the operation. +// +// Parameters: +// a Multiplicand within the range [0, m - 1]. +// b Multiplier within the range [0, m - 1]. +// m Modulus. +// r Montgomery multiplication result. +// +// Notes: The size of IppsBigNumState *r should not be less than the data +// length of the modulus m. +*F*/ +IPPFUN(IppStatus, ippsMontMul, (const IppsBigNumState* pA, const IppsBigNumState* pB, IppsMontState* pMont, IppsBigNumState* pR)) +{ + IPP_BAD_PTR4_RET(pA, pB, pMont, pR); + + pMont = (IppsMontState*)(IPP_ALIGNED_PTR((pMont), MONT_ALIGNMENT)); + pA = (IppsBigNumState*)( IPP_ALIGNED_PTR(pA, BN_ALIGNMENT) ); + pB = (IppsBigNumState*)( IPP_ALIGNED_PTR(pB, BN_ALIGNMENT) ); + pR = (IppsBigNumState*)( IPP_ALIGNED_PTR(pR, BN_ALIGNMENT) ); + + IPP_BADARG_RET(!MNT_VALID_ID(pMont), ippStsContextMatchErr); + IPP_BADARG_RET(!BN_VALID_ID(pA), ippStsContextMatchErr); + IPP_BADARG_RET(!BN_VALID_ID(pB), ippStsContextMatchErr); + IPP_BADARG_RET(!BN_VALID_ID(pR), ippStsContextMatchErr); + + IPP_BADARG_RET(BN_NEGATIVE(pA) || BN_NEGATIVE(pB), ippStsBadArgErr); + IPP_BADARG_RET(cpCmp_BNU(BN_NUMBER(pA), BN_SIZE(pA), MNT_MODULUS(pMont), MNT_SIZE(pMont)) >= 0, ippStsScaleRangeErr); + IPP_BADARG_RET(cpCmp_BNU(BN_NUMBER(pB), BN_SIZE(pB), MNT_MODULUS(pMont), MNT_SIZE(pMont)) >= 0, ippStsScaleRangeErr); + IPP_BADARG_RET(BN_ROOM(pR) < MNT_SIZE(pMont), ippStsOutOfRangeErr); + + { + BNU_CHUNK_T* pDataR = BN_NUMBER(pR); + cpSize nsM = MNT_SIZE(pMont); + + cpMontMul_BNU(pDataR, + BN_NUMBER(pA), BN_SIZE(pA), + BN_NUMBER(pB), BN_SIZE(pB), + MNT_MODULUS(pMont), nsM, + MNT_HELPER(pMont), + MNT_PRODUCT(pMont), MNT_KBUFFER(pMont)); + + FIX_BNU(pDataR, nsM); + BN_SIZE(pR) = nsM; + BN_SIGN(pR) = ippBigNumPOS; + + return ippStsNoErr; + } +} diff --git a/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpmontred.c b/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpmontred.c new file mode 100644 index 0000000000..a7851d6ec8 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpmontred.c @@ -0,0 +1,64 @@ +/* +* Copyright (C) 2016 Intel Corporation. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in +* the documentation and/or other materials provided with the +* distribution. +* * Neither the name of Intel Corporation nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ + +#include "owncp.h" +#include "pcpbnuarith.h" + + +void cpMontRedAdc_BNU(BNU_CHUNK_T* pR, + BNU_CHUNK_T* pProduct, + const BNU_CHUNK_T* pModulus, cpSize nsM, BNU_CHUNK_T m0) +{ + BNU_CHUNK_T carry; + BNU_CHUNK_T extension; + + cpSize n; + for(n=0, carry = 0; n<(nsM-1); n++) { + BNU_CHUNK_T u = pProduct[n]*m0; + BNU_CHUNK_T t = pProduct[nsM +n +1] + carry; + + extension = cpAddMulDgt_BNU(pProduct+n, pModulus, nsM, u); + ADD_AB(carry, pProduct[nsM+n], pProduct[nsM+n], extension); + t += carry; + + carry = tmaxbitSizeN) +#define RSA_PUB_KEY_MAXSIZE_E(x) ((x)->maxbitSizeE) +#define RSA_PUB_KEY_ID(x) ((x)->id) +#define RSA_PUB_KEY_BITSIZE_N(x) ((x)->bitSizeN) +#define RSA_PUB_KEY_BITSIZE_E(x) ((x)->bitSizeE) +#define RSA_PUB_KEY_E(x) ((x)->pDataE) +#define RSA_PUB_KEY_NMONT(x) ((x)->pMontN) +#define RSA_PUB_KEY_VALID_ID(x) (RSA_PUB_KEY_ID((x))==idCtxRSA_PubKey) +#define RSA_PUB_KEY_IS_SET(x) (RSA_PUB_KEY_BITSIZE_N((x))>0) + +/* alignment */ +#define RSA_PUBLIC_KEY_ALIGNMENT ((int)(sizeof(void*))) + +struct _cpRSA_private_key { + IppCtxId id; /* key ID */ + int maxbitSizeN; + int maxbitSizeD; + int bitSizeN; /* RSA modulus bitsize */ + int bitSizeD; /* RSA private exp bitsize */ + int bitSizeP; /* RSA p-factor bitsize */ + int bitSizeQ; /* RSA q-factor bitsize */ + + BNU_CHUNK_T* pDataD; /* private exp */ + BNU_CHUNK_T* pDataDp; /* dp private exp */ + BNU_CHUNK_T* pDataDq; /* dq private exp */ + BNU_CHUNK_T* pDataQinv; /* qinv coeff */ + + IppsMontState* pMontP; /* montgomery engine (P) */ + IppsMontState* pMontQ; /* montgomery engine (Q) */ + IppsMontState* pMontN; /* montgomery engine (N) */ +}; + +/* access */ +#define RSA_PRV_KEY_MAXSIZE_N(x) ((x)->maxbitSizeN) +#define RSA_PRV_KEY_MAXSIZE_D(x) ((x)->maxbitSizeD) +#define RSA_PRV_KEY_ID(x) ((x)->id) +#define RSA_PRV_KEY_BITSIZE_N(x) ((x)->bitSizeN) +#define RSA_PRV_KEY_BITSIZE_D(x) ((x)->bitSizeD) +#define RSA_PRV_KEY_BITSIZE_P(x) ((x)->bitSizeP) +#define RSA_PRV_KEY_BITSIZE_Q(x) ((x)->bitSizeQ) +#define RSA_PRV_KEY_D(x) ((x)->pDataD) +#define RSA_PRV_KEY_DP(x) ((x)->pDataDp) +#define RSA_PRV_KEY_DQ(x) ((x)->pDataDq) +#define RSA_PRV_KEY_INVQ(x) ((x)->pDataQinv) +#define RSA_PRV_KEY_PMONT(x) ((x)->pMontP) +#define RSA_PRV_KEY_QMONT(x) ((x)->pMontQ) +#define RSA_PRV_KEY_NMONT(x) ((x)->pMontN) +#define RSA_PRV_KEY1_VALID_ID(x) (RSA_PRV_KEY_ID((x))==idCtxRSA_PrvKey1) +#define RSA_PRV_KEY2_VALID_ID(x) (RSA_PRV_KEY_ID((x))==idCtxRSA_PrvKey2) +#define RSA_PRV_KEY_VALID_ID(x) (RSA_PRV_KEY1_VALID_ID((x)) || RSA_PRV_KEY2_VALID_ID((x))) +#define RSA_PRV_KEY_IS_SET(x) (RSA_PRV_KEY_BITSIZE_N((x))>0) + +/* alignment */ +#define RSA_PRIVATE_KEY_ALIGNMENT ((int)(sizeof(void*))) + +/* pubic and private key operations */ +void gsRSApub_cipher(IppsBigNumState* pY, const IppsBigNumState* pX, const IppsRSAPublicKeyState* pKey, BNU_CHUNK_T* pScratchBuffer); +void gsRSAprv_cipher(IppsBigNumState* pY, const IppsBigNumState* pX, const IppsRSAPrivateKeyState* pKey, BNU_CHUNK_T* pScratchBuffer); +void gsRSAprv_cipher_crt(IppsBigNumState* pY, const IppsBigNumState* pX, const IppsRSAPrivateKeyState* pKey, BNU_CHUNK_T* pScratchBuffer); + +#endif /* _CP_NG_RSA_H */ diff --git a/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpngrsaencodec.c b/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpngrsaencodec.c new file mode 100644 index 0000000000..4d147ad395 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpngrsaencodec.c @@ -0,0 +1,437 @@ +/* +* Copyright (C) 2016 Intel Corporation. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in +* the documentation and/or other materials provided with the +* distribution. +* * Neither the name of Intel Corporation nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ + +#include "owndefs.h" +#include "owncp.h" +#include "pcpbn.h" +#include "pcpngrsa.h" +#include "pcpngrsamontstuff.h" + + +/*F* +// Name: ippsRSA_GetBufferSizePublicKey +// +// Purpose: Returns size of temporary buffer (in bytes) for public key operation +// +// Returns: Reason: +// ippStsNullPtrErr NULL == pKey +// NULL == pBufferSize +// +// ippStsContextMatchErr !RSA_PUB_KEY_VALID_ID() +// +// ippStsIncompleteContextErr no ippsRSA_SetPublicKey() call +// +// ippStsNoErr no error +// +// Parameters: +// pBufferSize pointer to size of temporary buffer +// pKey pointer to the key context +*F*/ +IPPFUN(IppStatus, ippsRSA_GetBufferSizePublicKey,(int* pBufferSize, const IppsRSAPublicKeyState* pKey)) +{ + IPP_BAD_PTR1_RET(pKey); + pKey = (IppsRSAPublicKeyState*)( IPP_ALIGNED_PTR(pKey, RSA_PUBLIC_KEY_ALIGNMENT) ); + IPP_BADARG_RET(!RSA_PUB_KEY_VALID_ID(pKey), ippStsContextMatchErr); + IPP_BADARG_RET(!RSA_PUB_KEY_IS_SET(pKey), ippStsIncompleteContextErr); + + IPP_BAD_PTR1_RET(pBufferSize); + + { + cpSize expBitSize = RSA_PUB_KEY_BITSIZE_E(pKey); + cpSize w = gsMontExp_WinSize(expBitSize); + cpSize precompLen = (1==w)? 0 : (1<1) + // temporary product (2) + */ + cpSize bufferLen = ((nsM+1)*2)*2 + +precompLen*nsM + +nsM + +nsM*2; + + *pBufferSize = bufferLen*sizeof(BNU_CHUNK_T) + + sizeof(BNU_CHUNK_T)-1 + + (CACHE_LINE_SIZE-1); + return ippStsNoErr; + } +} + + +/*F* +// Name: ippsRSA_GetBufferSizePublicKey +// +// Purpose: Returns size of temporary buffer (in bytes) for public key operation +// +// Returns: Reason: +// ippStsNullPtrErr NULL == pKey +// NULL == pBufferSize +// +// ippStsContextMatchErr !RSA_PRV_KEY_VALID_ID() +// +// ippStsIncompleteContextErr (type1) private key is not set up +// +// ippStsNoErr no error +// +// Parameters: +// pBufferSize pointer to size of temporary buffer +// pKey pointer to the key context +*F*/ +IPPFUN(IppStatus, ippsRSA_GetBufferSizePrivateKey,(int* pBufferSize, const IppsRSAPrivateKeyState* pKey)) +{ + IPP_BAD_PTR1_RET(pKey); + pKey = (IppsRSAPrivateKeyState*)( IPP_ALIGNED_PTR(pKey, RSA_PUBLIC_KEY_ALIGNMENT) ); + IPP_BADARG_RET(!RSA_PRV_KEY_VALID_ID(pKey), ippStsContextMatchErr); + IPP_BADARG_RET(RSA_PRV_KEY1_VALID_ID(pKey) && !RSA_PRV_KEY_IS_SET(pKey), ippStsIncompleteContextErr); + + IPP_BAD_PTR1_RET(pBufferSize); + + { + cpSize bufferLen; + if(RSA_PRV_KEY1_VALID_ID(pKey)) { + cpSize expBitSize = RSA_PRV_KEY_BITSIZE_D(pKey); + cpSize w = gsMontExp_WinSize(expBitSize); + cpSize precompLen = (1==w)? 0 : (1<1) + // temporary product (2) + */ + bufferLen = ((nsN+1)*2)*2 + +gsPrecompResourcelen(precompLen,nsN) //+precompLen*nsN + +nsN + +nsN + +nsN*2; + } + else { + cpSize expBitSize = IPP_MAX(RSA_PRV_KEY_BITSIZE_P(pKey), RSA_PRV_KEY_BITSIZE_Q(pKey)); + cpSize w = gsMontExp_WinSize(expBitSize); + cpSize precompLen = (1==w)? 0 : (1<1) + // recoure to keep "masked" multipler (x|1) (1), (w=1) + // or resource to keep zero-extended power e (1), (w>1) + // temporary product (2) + */ + bufferLen = ((nsP*2+1)*2)*2 + +gsPrecompResourcelen(precompLen, nsP) //+precompLen*nsP + +nsP + +nsP + +nsP*2; + bufferLen = IPP_MAX( IPP_MAX(validationBufferLen,generationBufferLen), bufferLen ); + } + *pBufferSize = bufferLen*sizeof(BNU_CHUNK_T) + + sizeof(BNU_CHUNK_T)-1 + + (CACHE_LINE_SIZE-1); + return ippStsNoErr; + } +} + + + +void gsRSApub_cipher(IppsBigNumState* pY, + const IppsBigNumState* pX, + const IppsRSAPublicKeyState* pKey, + BNU_CHUNK_T* pScratchBuffer) +{ + IppsMontState* pMontN = RSA_PUB_KEY_NMONT(pKey); + gsMontEnc_BN(pY, pX, pMontN, pScratchBuffer); + + { + /* optimal size of window */ + BNU_CHUNK_T* pExp = RSA_PUB_KEY_E(pKey); + cpSize nsExp = BITS_BNU_CHUNK(RSA_PUB_KEY_BITSIZE_E(pKey)); + cpSize w = gsMontExp_WinSize(RSA_PUB_KEY_BITSIZE_E(pKey)); + + if(1==w) + gsMontExpBin_BN(pY, pY, pExp, nsExp, pMontN, pScratchBuffer); + else + gsMontExpWin_BN(pY, pY, pExp, nsExp, w, pMontN, pScratchBuffer); + } + + gsMontDec_BN(pY, pY, pMontN, pScratchBuffer); +} + + +/*F* +// Name: ippsRSA_Encrypt +// +// Purpose: Performs RSA Encryprion +// +// Returns: Reason: +// ippStsNullPtrErr NULL == pKey +// NULL == pPtxt +// NULL == pCtxt +// NULL == pBuffer +// +// ippStsContextMatchErr !RSA_PUB_KEY_VALID_ID() +// !BN_VALID_ID(pPtxt) +// !BN_VALID_ID(pCtxt) +// +// ippStsIncompleteContextErr public key is not setup +// +// ippStsOutOfRangeErr pPtxt >= modulus +// pPtxt <0 +// +// ippStsSizeErr BN_ROOM(pCtxt) is not enough +// +// ippStsNoErr no error +// +// Parameters: +// pPtxt pointer to the plaintext +// pCtxt pointer to the ciphertext +// pKey pointer to the key context +// pScratchBuffer pointer to the temporary buffer +*F*/ +IPPFUN(IppStatus, ippsRSA_Encrypt,(const IppsBigNumState* pPtxt, + IppsBigNumState* pCtxt, + const IppsRSAPublicKeyState* pKey, + Ipp8u* pScratchBuffer)) +{ + IPP_BAD_PTR2_RET(pKey, pScratchBuffer); + pKey = (IppsRSAPublicKeyState*)( IPP_ALIGNED_PTR(pKey, RSA_PUBLIC_KEY_ALIGNMENT) ); + IPP_BADARG_RET(!RSA_PUB_KEY_VALID_ID(pKey), ippStsContextMatchErr); + IPP_BADARG_RET(!RSA_PUB_KEY_IS_SET(pKey), ippStsIncompleteContextErr); + + IPP_BAD_PTR1_RET(pPtxt); + pPtxt = (IppsBigNumState*)( IPP_ALIGNED_PTR(pPtxt, BN_ALIGNMENT) ); + IPP_BADARG_RET(!BN_VALID_ID(pPtxt), ippStsContextMatchErr); + IPP_BADARG_RET(BN_NEGATIVE(pPtxt), ippStsOutOfRangeErr); + IPP_BADARG_RET(0 <= cpCmp_BNU(BN_NUMBER(pPtxt), BN_SIZE(pPtxt), + MNT_MODULUS(RSA_PUB_KEY_NMONT(pKey)), MNT_SIZE(RSA_PUB_KEY_NMONT(pKey))), ippStsOutOfRangeErr); + + IPP_BAD_PTR1_RET(pCtxt); + pCtxt = (IppsBigNumState*)( IPP_ALIGNED_PTR(pCtxt, BN_ALIGNMENT) ); + IPP_BADARG_RET(!BN_VALID_ID(pCtxt), ippStsContextMatchErr); + IPP_BADARG_RET(BN_ROOM(pCtxt) < BITS_BNU_CHUNK(RSA_PUB_KEY_BITSIZE_N(pKey)), ippStsSizeErr); + + gsRSApub_cipher(pCtxt, + pPtxt, + pKey, + (BNU_CHUNK_T*)(IPP_ALIGNED_PTR((pScratchBuffer), (int)sizeof(BNU_CHUNK_T))) ); + return ippStsNoErr; +} + + + +void gsRSAprv_cipher(IppsBigNumState* pY, + const IppsBigNumState* pX, + const IppsRSAPrivateKeyState* pKey, + BNU_CHUNK_T* pScratchBuffer) +{ + IppsMontState* pMontN = RSA_PRV_KEY_NMONT(pKey); + gsMontEnc_BN(pY, pX, pMontN, pScratchBuffer); + + { + /* optimal size of window */ + BNU_CHUNK_T* pExp = RSA_PRV_KEY_D(pKey); + cpSize nsExp = BITS_BNU_CHUNK(RSA_PRV_KEY_BITSIZE_D(pKey)); + cpSize w = gsMontExp_WinSize(RSA_PRV_KEY_BITSIZE_D(pKey)); + + if(1==w) + gsMontExpBin_BN_sscm(pY, pY, pExp, nsExp, pMontN, pScratchBuffer); + else + gsMontExpWin_BN_sscm(pY, pY, pExp, nsExp, w, pMontN, pScratchBuffer); + } + + gsMontDec_BN(pY, pY, pMontN, pScratchBuffer); +} + +void gsRSAprv_cipher_crt(IppsBigNumState* pY, + const IppsBigNumState* pX, + const IppsRSAPrivateKeyState* pKey, + BNU_CHUNK_T* pScratchBuffer) +{ + /* P- and Q- montgometry engines */ + IppsMontState* pMontP = RSA_PRV_KEY_PMONT(pKey); + IppsMontState* pMontQ = RSA_PRV_KEY_QMONT(pKey); + cpSize nsP = MNT_SIZE(pMontP); + cpSize nsQ = MNT_SIZE(pMontQ); + + const BNU_CHUNK_T* dataX = BN_NUMBER(pX); + cpSize nsX = BN_SIZE(pX); + BNU_CHUNK_T* dataXp = BN_NUMBER(pY); + BNU_CHUNK_T* dataXq = BN_BUFFER(pY); + + cpSize bitSizeDP = BITSIZE_BNU(RSA_PRV_KEY_DP(pKey), nsP); + cpSize bitSizeDQ = BITSIZE_BNU(RSA_PRV_KEY_DQ(pKey), nsQ); + cpSize w; + BNU_CHUNK_T cf; + + /* compute xq = x^dQ mod Q */ + COPY_BNU(dataXq, dataX, nsX); + cpMod_BNU(dataXq, nsX, MNT_MODULUS(pMontQ), nsQ); + gsMontEnc_BNU(dataXq, dataXq, nsQ, pMontQ, pScratchBuffer); + w = gsMontExp_WinSize(bitSizeDQ); + + if(1==w) + gsMontExpBin_BNU_sscm(dataXq, + dataXq, nsQ, + RSA_PRV_KEY_DQ(pKey), BITS_BNU_CHUNK(bitSizeDQ), + pMontQ, pScratchBuffer); + else + gsMontExpWin_BNU_sscm(dataXq, + dataXq, nsQ, + RSA_PRV_KEY_DQ(pKey), BITS_BNU_CHUNK(bitSizeDQ), w, + pMontQ, pScratchBuffer); + + gsMontDec_BNU(dataXq, dataXq, nsQ, pMontQ, pScratchBuffer); + + /* compute xp = x^dP mod P */ + COPY_BNU(dataXp, dataX, nsX); + cpMod_BNU(dataXp, nsX, MNT_MODULUS(pMontP), nsP); + gsMontEnc_BNU(dataXp, dataXp, nsP, pMontP, pScratchBuffer); + w = gsMontExp_WinSize(bitSizeDP); + + if(1==w) + gsMontExpBin_BNU_sscm(dataXp, + dataXp, nsP, + RSA_PRV_KEY_DP(pKey), BITS_BNU_CHUNK(bitSizeDP), + pMontP, pScratchBuffer); + else + gsMontExpWin_BNU_sscm(dataXp, + dataXp, nsP, + RSA_PRV_KEY_DP(pKey), BITS_BNU_CHUNK(bitSizeDP), w, + pMontP, pScratchBuffer); + + gsMontDec_BNU(dataXp, dataXp, nsP, pMontP, pScratchBuffer); + + /* xp -= xq */ + cf = cpSub_BNU(dataXp, dataXp, dataXq, nsQ); + if(nsP-nsQ) + cf = cpDec_BNU(dataXp+nsQ, dataXp+nsQ, (nsP-nsQ), cf); + if(cf) + cpAdd_BNU(dataXp, dataXp, MNT_MODULUS(pMontP), nsP); + + /* xp = xp*qInv mod P */ + cpMontMul_BNU(dataXp, + dataXp, nsP, + RSA_PRV_KEY_INVQ(pKey), nsP, + MNT_MODULUS(pMontP), nsP, MNT_HELPER(pMontP), + pScratchBuffer, NULL); + + /* Y = xq + xp*Q */ + cpMul_BNU_school(pScratchBuffer, + dataXp, nsP, + MNT_MODULUS(pMontQ), nsQ); + cf = cpAdd_BNU(BN_NUMBER(pY), pScratchBuffer, dataXq, nsQ); + cpInc_BNU(BN_NUMBER(pY)+nsQ, pScratchBuffer+nsQ, nsP, cf); + + nsX = nsP+nsQ; + FIX_BNU(BN_NUMBER(pY), nsX); + BN_SIZE(pY) = nsX; + BN_SIGN(pY) = ippBigNumPOS; +} + +/*F* +// Name: ippsRSA_Decrypt +// +// Purpose: Performs RSA Decryprion +// +// Returns: Reason: +// ippStsNullPtrErr NULL == pKey +// NULL == pCtxt +// NULL == pPtxt +// NULL == pBuffer +// +// ippStsContextMatchErr !RSA_PUB_KEY_VALID_ID() +// !BN_VALID_ID(pCtxt) +// !BN_VALID_ID(pPtxt) +// +// ippStsIncompleteContextErr private key is not set up +// +// ippStsOutOfRangeErr pCtxt >= modulus +// pCtxt <0 +// +// ippStsSizeErr BN_ROOM(pPtxt) is not enough +// +// ippStsNoErr no error +// +// Parameters: +// pCtxt pointer to the ciphertext +// pPtxt pointer to the plaintext +// pKey pointer to the key context +// pScratchBuffer pointer to the temporary buffer +*F*/ +IPPFUN(IppStatus, ippsRSA_Decrypt,(const IppsBigNumState* pCtxt, + IppsBigNumState* pPtxt, + const IppsRSAPrivateKeyState* pKey, + Ipp8u* pScratchBuffer)) +{ + IPP_BAD_PTR2_RET(pKey, pScratchBuffer); + pKey = (IppsRSAPrivateKeyState*)( IPP_ALIGNED_PTR(pKey, RSA_PRIVATE_KEY_ALIGNMENT) ); + IPP_BADARG_RET(!RSA_PRV_KEY_VALID_ID(pKey), ippStsContextMatchErr); + IPP_BADARG_RET(!RSA_PRV_KEY_IS_SET(pKey), ippStsIncompleteContextErr); + + IPP_BAD_PTR1_RET(pCtxt); + pCtxt = (IppsBigNumState*)( IPP_ALIGNED_PTR(pCtxt, BN_ALIGNMENT) ); + IPP_BADARG_RET(!BN_VALID_ID(pCtxt), ippStsContextMatchErr); + IPP_BADARG_RET(BN_NEGATIVE(pCtxt), ippStsOutOfRangeErr); + IPP_BADARG_RET(0 <= cpCmp_BNU(BN_NUMBER(pCtxt), BN_SIZE(pCtxt), + MNT_MODULUS(RSA_PRV_KEY_NMONT(pKey)), MNT_SIZE(RSA_PRV_KEY_NMONT(pKey))), ippStsOutOfRangeErr); + + IPP_BAD_PTR1_RET(pPtxt); + pPtxt = (IppsBigNumState*)( IPP_ALIGNED_PTR(pPtxt, BN_ALIGNMENT) ); + IPP_BADARG_RET(!BN_VALID_ID(pPtxt), ippStsContextMatchErr); + IPP_BADARG_RET(BN_ROOM(pPtxt) < BITS_BNU_CHUNK(RSA_PRV_KEY_BITSIZE_N(pKey)), ippStsSizeErr); + + if(RSA_PRV_KEY1_VALID_ID(pKey)) + gsRSAprv_cipher(pPtxt, + pCtxt, + pKey, + (BNU_CHUNK_T*)(IPP_ALIGNED_PTR((pScratchBuffer), (int)sizeof(BNU_CHUNK_T))) ); + else + gsRSAprv_cipher_crt(pPtxt, + pCtxt, + pKey, + (BNU_CHUNK_T*)(IPP_ALIGNED_PTR((pScratchBuffer), (int)sizeof(BNU_CHUNK_T))) ); + return ippStsNoErr; +} diff --git a/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpngrsaesoaepca.c b/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpngrsaesoaepca.c new file mode 100644 index 0000000000..ac9ce14f14 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpngrsaesoaepca.c @@ -0,0 +1,176 @@ +/* +* Copyright (C) 2016 Intel Corporation. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in +* the documentation and/or other materials provided with the +* distribution. +* * Neither the name of Intel Corporation nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ + +#include "owndefs.h" +#include "owncp.h" +#include "pcptool.h" +#include "pcpngrsa.h" +#include "pcphash.h" + + +/*F* +// Name: ippsRSAEncrypt_OAEP +// +// Purpose: Performs RSAES-OAEP encryprion scheme +// +// Returns: Reason: +// ippStsNotSupportedModeErr unknown hashAlg +// +// ippStsNullPtrErr NULL == pKey +// NULL == pSrc +// NULL == pDst +// NULL == pLabel +// NULL == pSeed +// NULL == pBuffer +// +// ippStsLengthErr srcLen <0 +// labLen <0 +// srcLen > RSAsize -2*hashLen -2 +// RSAsize < 2*hashLen +2 +// +// ippStsContextMatchErr !RSA_PUB_KEY_VALID_ID() +// +// ippStsIncompleteContextErr public key is not set up +// +// ippStsNoErr no error +// +// Parameters: +// pSrc pointer to the plaintext +// srcLen plaintext length (bytes) +// pLabel (optional) pointer to the label associated with plaintext +// labLen label length (bytes) +// pSeed seed string of hashLen size +// pDst pointer to the ciphertext (length of pdst is not less then size of RSA modulus) +// pKey pointer to the RSA public key context +// hashAlg hash alg ID +// pBuffer pointer to scratch buffer +*F*/ +IPPFUN(IppStatus, ippsRSAEncrypt_OAEP,(const Ipp8u* pSrc, int srcLen, + const Ipp8u* pLabel, int labLen, + const Ipp8u* pSeed, + Ipp8u* pDst, + const IppsRSAPublicKeyState* pKey, + IppHashAlgId hashAlg, + Ipp8u* pBuffer)) +{ + int hashLen; + + /* test hash algorith ID */ + hashAlg = cpValidHashAlg(hashAlg); + IPP_BADARG_RET(ippHashAlg_Unknown==hashAlg, ippStsNotSupportedModeErr); + + /* test data pointer */ + IPP_BAD_PTR3_RET(pSrc,pDst, pSeed); + + IPP_BADARG_RET(!pLabel && labLen, ippStsNullPtrErr); + + /* test public key context */ + IPP_BAD_PTR2_RET(pKey, pBuffer); + pKey = (IppsRSAPublicKeyState*)( IPP_ALIGNED_PTR(pKey, RSA_PUBLIC_KEY_ALIGNMENT) ); + IPP_BADARG_RET(!RSA_PUB_KEY_VALID_ID(pKey), ippStsContextMatchErr); + IPP_BADARG_RET(!RSA_PUB_KEY_IS_SET(pKey), ippStsIncompleteContextErr); + + /* test length */ + IPP_BADARG_RET(srcLen<0||labLen<0, ippStsLengthErr); + + hashLen = cpHashSize(hashAlg); + /* test compatibility of RSA and hash length */ + IPP_BADARG_RET(BITS2WORD8_SIZE(RSA_PRV_KEY_BITSIZE_N(pKey)) < (2*hashLen +2), ippStsLengthErr); + /* test compatibility of msg length and other (RSA and hash) lengths */ + IPP_BADARG_RET(BITS2WORD8_SIZE(RSA_PRV_KEY_BITSIZE_N(pKey))-(2*hashLen +2) < srcLen, ippStsLengthErr); + + { + /* size of RSA modulus in bytes and chunks */ + int k = BITS2WORD8_SIZE(RSA_PUB_KEY_BITSIZE_N(pKey)); + cpSize nsN = BITS_BNU_CHUNK(RSA_PUB_KEY_BITSIZE_N(pKey)); + + /* + // EME-OAEP encoding + */ + { + Ipp8u seedMask[BITS2WORD8_SIZE(IPP_SHA512_DIGEST_BITSIZE)]; + + Ipp8u* pMaskedSeed = pDst+1; + Ipp8u* pMaskedDB = pDst +hashLen +1; + + pDst[0] = 0; + + /* maskedDB = MGF(seed, k-1-hashLen)*/ + ippsMGF(pSeed, hashLen, pMaskedDB, k-1-hashLen, hashAlg); + + /* seedMask = HASH(pLab) */ + ippsHashMessage(pLabel, labLen, seedMask, hashAlg); + + /* maskedDB ^= concat(HASH(pLab),PS,0x01,pSc) */ + XorBlock(pMaskedDB, seedMask, pMaskedDB, hashLen); + pMaskedDB[k-srcLen-hashLen-2] ^= 0x01; + XorBlock(pMaskedDB+k-srcLen-hashLen-2+1, pSrc, pMaskedDB+k-srcLen-hashLen-2+1, srcLen); + + /* seedMask = MGF(maskedDB, hashLen) */ + ippsMGF(pMaskedDB, k-1-hashLen, seedMask, hashLen, hashAlg); + /* maskedSeed = seed ^ seedMask */ + XorBlock(pSeed, seedMask, pMaskedSeed, hashLen); + } + + /* RSA encryption */ + { + /* align buffer */ + BNU_CHUNK_T* pScratchBuffer = (BNU_CHUNK_T*)(IPP_ALIGNED_PTR(pBuffer, (int)sizeof(BNU_CHUNK_T)) ); + + /* temporary BN */ + __ALIGN8 IppsBigNumState tmpBN; + BN_Make(pScratchBuffer, pScratchBuffer+nsN+1, nsN, &tmpBN); + + /* updtae buffer pointer */ + pScratchBuffer += (nsN+1)*2; + + ippsSetOctString_BN(pDst, k, &tmpBN); + + gsRSApub_cipher(&tmpBN, &tmpBN, pKey, pScratchBuffer); + + ippsGetOctString_BN(pDst, k, &tmpBN); + } + + return ippStsNoErr; + } +} + + +IPPFUN(IppStatus, ippsRSA_OAEPEncrypt_SHA256,(const Ipp8u* pSrc, int srcLen, + const Ipp8u* pLabel, int labLen, + const Ipp8u* pSeed, + Ipp8u* pDst, + const IppsRSAPublicKeyState* pKey, + Ipp8u* pBuffer)) +{ return ippsRSAEncrypt_OAEP(pSrc,srcLen, pLabel,labLen, pSeed, + pDst, pKey, + IPP_ALG_HASH_SHA256, + pBuffer); } diff --git a/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpngrsagenerate.c b/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpngrsagenerate.c new file mode 100644 index 0000000000..2896ffdc89 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpngrsagenerate.c @@ -0,0 +1,323 @@ +/* +* Copyright (C) 2016 Intel Corporation. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in +* the documentation and/or other materials provided with the +* distribution. +* * Neither the name of Intel Corporation nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ + +#include "owndefs.h" +#include "owncp.h" +#include "pcpbn.h" +#include "pcpprimeg.h" +#include "pcpngrsa.h" +#include "pcpngrsamontstuff.h" + +/*F* +// Name: ippsRSA_ValidateKeys +// +// Purpose: Validate RSA keys +// +// Returns: Reason: +// ippStsNullPtrErr NULL == pPublicKey +// NULL == pPrivateKeyType2 +// NULL == pPrivateKeyType1 +// NULL == pBuffer +// NULL == pPrimeGen +// NULL == rndFunc +// NULL == pResult +// +// ippStsContextMatchErr !RSA_PUB_KEY_VALID_ID(pPublicKey) +// !RSA_PRV_KEY2_VALID_ID(pPrivateKeyType2) +// !RSA_PRV_KEY1_VALID_ID(pPrivateKeyType1) +// !PRIME_VALID_ID(pPrimeGen) +// +// ippStsIncompleteContextErr public and.or private key is not set up +// +// ippStsSizeErr PRIME_MAXBITSIZE(pPrimeGen) < factorPbitSize +// +// ippStsBadArgErr nTrials < 1 +// +// ippStsNoErr no error +// +// Parameters: +// pResult pointer to the validation result +// pPublicKey pointer to the public key context +// pPrivateKeyType2 pointer to the private key type2 context +// pPrivateKeyType1 (optional) pointer to the private key type1 context +// pBuffer pointer to the temporary buffer +// nTrials parameter of Miller-Rabin Test +// pPrimeGen pointer to the Prime generator context +// rndFunc external PRNG +// pRndParam pointer to the external PRNG parameters +*F*/ +/* +// make sure D*E = 1 mod(phi(P,Q)) +// where phi(P,Q) = (P-1)*(Q-1) +*/ +static +int isValidPriv1_classic(const BNU_CHUNK_T* pN, int nsN, + const BNU_CHUNK_T* pE, int nsE, + const BNU_CHUNK_T* pD, int nsD, + const BNU_CHUNK_T* pFactorP, int nsP, + const BNU_CHUNK_T* pFactorQ, int nsQ, + BNU_CHUNK_T* pBuffer) +{ + BNU_CHUNK_T* pPhi = pBuffer; + BNU_CHUNK_T* pProduct = pPhi + nsN; + BNU_CHUNK_T c = cpSub_BNU(pPhi, pN, pFactorP, nsP); + int prodLen; + if(nsN>1) cpDec_BNU(pPhi+nsP, pN+nsP, nsQ, c); + c = cpSub_BNU(pPhi,pPhi, pFactorQ, nsQ); + if(nsN>1) cpDec_BNU(pPhi+nsQ, pPhi+nsQ, nsP, c); + cpInc_BNU(pPhi, pPhi, nsP+nsQ, 1); + + cpMul_BNU_school(pProduct, pE, nsE, pD, nsD); + prodLen = cpMod_BNU(pProduct, nsE+nsD, pPhi, nsN); + + return 1==cpEqu_BNU_CHUNK(pProduct, prodLen, 1)? IPP_IS_VALID : IPP_IS_INVALID; +} + +/* +// make sure D*E = 1 mod(lcm(P-1,Q-1)) +// where lcm(P-1,Q-1) = (P-1)*(Q-1)/gcd(P-1,Q-1) +*/ +static +int isValidPriv1_rsa(const BNU_CHUNK_T* pN, int nsN, + const BNU_CHUNK_T* pE, int nsE, + const BNU_CHUNK_T* pD, int nsD, + BNU_CHUNK_T* pFactorP, int nsP, + BNU_CHUNK_T* pFactorQ, int nsQ, + BNU_CHUNK_T* pBuffer) +{ + __ALIGN8 IppsBigNumState tmpBN1; + __ALIGN8 IppsBigNumState tmpBN2; + __ALIGN8 IppsBigNumState tmpBN3; + + BNU_CHUNK_T* pProduct = pBuffer; + BNU_CHUNK_T* pGcd = pProduct+(nsN+1); + BNU_CHUNK_T* pLcm; + int nsLcm; + int prodLen; + pBuffer = pGcd + (nsP+1)*2; + + /* P = P-1 and Q = Q-1 */ + pFactorP[0]--; + pFactorQ[0]--; + + /* compute product (P-1)*(Q-1) = P*Q -P -Q +1 = N -(P-1) -(Q-1) -1 */ + { + BNU_CHUNK_T c = cpSub_BNU(pProduct, pN, pFactorP, nsP); + if(nsN>1) cpDec_BNU(pProduct+nsP, pN+nsP, nsQ, c); + c = cpSub_BNU(pProduct, pProduct, pFactorQ, nsQ); + if(nsN>1) cpDec_BNU(pProduct+nsQ, pProduct+nsQ, nsP, c); + cpDec_BNU(pProduct, pProduct, nsN, 1); + } + + /* compute gcd(p-1, q-1) */ + BN_Make(pGcd, pGcd+nsP+1, nsP, &tmpBN1); /* BN(gcd) */ + BN_SIZE(&tmpBN1) = nsP; + BN_Make(pFactorP, pBuffer, nsP, &tmpBN2); /* BN(P-1) */ + BN_SIZE(&tmpBN2) = nsP; + BN_Make(pFactorQ, pBuffer+nsP+1, nsQ, &tmpBN3); /* BN(Q-1) */ + BN_SIZE(&tmpBN3) = nsQ; + ippsGcd_BN(&tmpBN2, &tmpBN3, &tmpBN1); + + /* compute lcm(p-1, q-1) = (p-1)(q-1)/gcd(p-1, q-1) */ + pLcm = pBuffer; + cpDiv_BNU(pLcm, &nsLcm, pProduct, nsN, pGcd, BN_SIZE(&tmpBN1)); + + /* test E*D = 1 mod lcm */ + cpMul_BNU_school(pProduct, pE, nsE, pD, nsD); + prodLen = cpMod_BNU(pProduct, nsE+nsD, pLcm, nsLcm); + + /* restore P and Q */ + pFactorP[0]++; + pFactorQ[0]++; + + return 1==cpEqu_BNU_CHUNK(pProduct, prodLen, 1)? IPP_IS_VALID : IPP_IS_INVALID; +} + +IPPFUN(IppStatus, ippsRSA_ValidateKeys,(int* pResult, + const IppsRSAPublicKeyState* pPublicKey, + const IppsRSAPrivateKeyState* pPrivateKeyType2, + const IppsRSAPrivateKeyState* pPrivateKeyType1, /*optional */ + Ipp8u* pBuffer, + int nTrials, + IppsPrimeState* pPrimeGen, + IppBitSupplier rndFunc, void* pRndParam)) +{ + IPP_BAD_PTR1_RET(pPublicKey); + pPublicKey = (IppsRSAPublicKeyState*)( IPP_ALIGNED_PTR(pPublicKey, RSA_PUBLIC_KEY_ALIGNMENT) ); + IPP_BADARG_RET(!RSA_PUB_KEY_VALID_ID(pPublicKey), ippStsContextMatchErr); + IPP_BADARG_RET(!RSA_PUB_KEY_IS_SET(pPublicKey), ippStsIncompleteContextErr); + + IPP_BAD_PTR1_RET(pPrivateKeyType2); + pPrivateKeyType2 = (IppsRSAPrivateKeyState*)( IPP_ALIGNED_PTR(pPrivateKeyType2, RSA_PRIVATE_KEY_ALIGNMENT) ); + IPP_BADARG_RET(!RSA_PRV_KEY2_VALID_ID(pPrivateKeyType2), ippStsContextMatchErr); + IPP_BADARG_RET(!RSA_PRV_KEY_IS_SET(pPrivateKeyType2), ippStsIncompleteContextErr); + + if(pPrivateKeyType1) { /* pPrivateKeyType1 is optional */ + pPrivateKeyType1 = (IppsRSAPrivateKeyState*)( IPP_ALIGNED_PTR(pPrivateKeyType1, RSA_PRIVATE_KEY_ALIGNMENT) ); + IPP_BADARG_RET(!RSA_PRV_KEY1_VALID_ID(pPrivateKeyType1), ippStsContextMatchErr); + IPP_BADARG_RET(!RSA_PRV_KEY_IS_SET(pPrivateKeyType1), ippStsIncompleteContextErr); + } + + IPP_BAD_PTR1_RET(pPrimeGen); + pPrimeGen = (IppsPrimeState*)( IPP_ALIGNED_PTR(pPrimeGen, PRIME_ALIGNMENT) ); + IPP_BADARG_RET(!PRIME_VALID_ID(pPrimeGen), ippStsContextMatchErr); + IPP_BADARG_RET(PRIME_MAXBITSIZE(pPrimeGen) < RSA_PRV_KEY_BITSIZE_P(pPrivateKeyType2), ippStsSizeErr); + + IPP_BAD_PTR3_RET(pResult, pBuffer, rndFunc); + + /* test security parameter parameter */ + IPP_BADARG_RET((1>nTrials), ippStsBadArgErr); + + { + BNU_CHUNK_T* pScratchBuffer = (BNU_CHUNK_T*)(IPP_ALIGNED_PTR(pBuffer, (int)sizeof(BNU_CHUNK_T))); + + /* E key component */ + BNU_CHUNK_T* pExpE = RSA_PUB_KEY_E(pPublicKey); + cpSize nsE = BITS_BNU_CHUNK(RSA_PUB_KEY_BITSIZE_E(pPublicKey)); + /* P, dP, invQ key components */ + BNU_CHUNK_T* pFactorP= MNT_MODULUS(RSA_PRV_KEY_PMONT(pPrivateKeyType2)); + BNU_CHUNK_T* pExpDp = RSA_PRV_KEY_DP(pPrivateKeyType2); + BNU_CHUNK_T* pInvQ = RSA_PRV_KEY_INVQ(pPrivateKeyType2); + cpSize nsP = MNT_SIZE(RSA_PRV_KEY_PMONT(pPrivateKeyType2)); + /* Q, dQ key components */ + BNU_CHUNK_T* pFactorQ= MNT_MODULUS(RSA_PRV_KEY_QMONT(pPrivateKeyType2)); + BNU_CHUNK_T* pExpDq = RSA_PRV_KEY_DQ(pPrivateKeyType2); + cpSize nsQ = MNT_SIZE(RSA_PRV_KEY_QMONT(pPrivateKeyType2)); + + /*const*/ BNU_CHUNK_T* pN0 = MNT_MODULUS(RSA_PUB_KEY_NMONT(pPublicKey)); + cpSize nsN = MNT_SIZE(RSA_PUB_KEY_NMONT(pPublicKey)); + + *pResult = IPP_IS_VALID; + + /* make sure P is prime */ + if(!cpPrimeTest(pFactorP, nsP, nTrials, pPrimeGen, rndFunc, pRndParam)) { + *pResult = IPP_IS_COMPOSITE; + return ippStsNoErr; + } + + /* make sure Q is prime */ + if(!cpPrimeTest(pFactorQ, nsQ, nTrials, pPrimeGen, rndFunc, pRndParam)) { + *pResult = IPP_IS_COMPOSITE; + return ippStsNoErr; + } + + /* make sure PubKey(N)==PrivKeytype2(N) and PubKey(N)==PrivKeytype1(N) */ + if(cpCmp_BNU(pN0, nsN, + MNT_MODULUS(RSA_PRV_KEY_NMONT(pPrivateKeyType2)), MNT_SIZE(RSA_PRV_KEY_NMONT(pPrivateKeyType2)))) { + *pResult = IPP_IS_INVALID; + return ippStsNoErr; + } + if(pPrivateKeyType1) { + if(cpCmp_BNU(pN0, nsN, + MNT_MODULUS(RSA_PRV_KEY_NMONT(pPrivateKeyType1)), MNT_SIZE(RSA_PRV_KEY_NMONT(pPrivateKeyType1)))) { + *pResult = IPP_IS_INVALID; + return ippStsNoErr; + } + } + + /* make sure 3 <= E < N */ + if(1==nsE && pExpE[0]<3) { + *pResult = IPP_IS_INVALID; + return ippStsNoErr; + } + if(0 <= cpCmp_BNU(pExpE, nsE, pN0, nsN)) { + *pResult = IPP_IS_INVALID; + return ippStsNoErr; + } + + { + BNU_CHUNK_T* pFactor1 = pScratchBuffer; + BNU_CHUNK_T* pInv = pFactor1 +nsP+1; + BNU_CHUNK_T* pBufInv = pInv +nsP+1; + BNU_CHUNK_T* pBufE = pBufInv +nsP+1; + BNU_CHUNK_T* pBufFact = pBufE +nsP+1; + BNU_CHUNK_T* pProduct = pBufInv; + + /* make sure E*dP = 1 mod (P-1) */ + cpDec_BNU(pFactor1, pFactorP, nsP, 1); + cpMul_BNU_school(pProduct, pExpDp, nsP, pExpE, nsE); + cpMod_BNU(pProduct, nsP+nsE, pFactor1, nsP); + if(!cpEqu_BNU_CHUNK(pProduct, nsP, 1)) { + *pResult = IPP_IS_INVALID; + return ippStsNoErr; + } + /* make sure 1==GCD(E,P-1) => exist Inv(E,P-1) */ + if(!cpModInv_BNU(pInv, pExpE, nsE, pFactor1, nsP, pBufInv, pBufE, pBufFact)) { + *pResult = IPP_IS_INVALID; + return ippStsNoErr; + } + + /* make sure E*dQ = 1 mod (Q-1) */ + cpDec_BNU(pFactor1, pFactorQ, nsQ, 1); + cpMul_BNU_school(pProduct, pExpDq, nsQ, pExpE, nsE); + cpMod_BNU(pProduct, nsQ+nsE, pFactor1, nsQ); + if(!cpEqu_BNU_CHUNK(pProduct, nsQ, 1)) { + *pResult = IPP_IS_INVALID; + return ippStsNoErr; + } + /* make sure 1==GCD(E,Q-1) => exist Inv(E,Q-1) */ + if(!cpModInv_BNU(pInv, pExpE, nsE, pFactor1, nsQ, pBufInv, pBufE, pBufFact)) { + *pResult = IPP_IS_INVALID; + return ippStsNoErr; + } + } + + /* make sure Q*Qinv = 1 mod P */ + cpMontMul_BNU(pScratchBuffer, + pFactorQ, nsQ, + pInvQ, nsP, + pFactorP, nsP, MNT_HELPER(RSA_PRV_KEY_PMONT(pPrivateKeyType2)), + pScratchBuffer+nsP, NULL); + if(!cpEqu_BNU_CHUNK(pScratchBuffer, nsP, 1)) { + *pResult = IPP_IS_INVALID; + return ippStsNoErr; + } + + /* test priva exponent (optiobal) */ + if(pPrivateKeyType1) { + const BNU_CHUNK_T* pExpD = RSA_PRV_KEY_D(pPrivateKeyType1); + cpSize nsD = nsN; + + int resilt1 = isValidPriv1_classic(pN0,nsN, pExpE,nsE, pExpD,nsD, + pFactorP,nsP, pFactorQ,nsQ, + (BNU_CHUNK_T*)pScratchBuffer); + int resilt2 = isValidPriv1_rsa(pN0,nsN, pExpE,nsE, pExpD,nsD, + pFactorP,nsP, pFactorQ,nsQ, + (BNU_CHUNK_T*)pScratchBuffer); + if(IPP_IS_VALID!=resilt1 && IPP_IS_VALID!=resilt2) { + *pResult = IPP_IS_INVALID; + return ippStsNoErr; + } + } + + return ippStsNoErr; + } +} diff --git a/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpngrsakeyprivate.c b/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpngrsakeyprivate.c new file mode 100644 index 0000000000..5c4c13e845 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpngrsakeyprivate.c @@ -0,0 +1,496 @@ +/* +* Copyright (C) 2016 Intel Corporation. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in +* the documentation and/or other materials provided with the +* distribution. +* * Neither the name of Intel Corporation nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ + +#include "owndefs.h" +#include "owncp.h" +#include "pcpbn.h" +#include "pcpngrsa.h" +#include "pcpngrsamontstuff.h" + +/*F* +// Name: ippsRSA_GetSizePrivateKeyType1 +// +// Purpose: Returns context size (bytes) of RSA private key (type1) context +// +// Returns: Reason: +// ippStsNullPtrErr NULL == pSize +// +// ippStsNotSupportedModeErr MIN_RSA_SIZE > rsaModulusBitSize +// MAX_RSA_SIZE < rsaModulusBitSize +// +// ippStsBadArgErr 0 >= privateExpBitSize +// privateExpBitSize > rsaModulusBitSize +// +// ippStsNoErr no error +// +// Parameters: +// rsaModulusBitSize bitsize of RSA modulus (bitsize of N) +// privateExpBitSize bitsize of private exponent (bitsize of D) +// pSize pointer to the size of RSA key context (bytes) +*F*/ +static int cpSizeof_RSA_privateKey1(int rsaModulusBitSize, int privateExpBitSize) +{ + int prvExpLen = BITS_BNU_CHUNK(privateExpBitSize); + int modulusLen32 = BITS2WORD32_SIZE(rsaModulusBitSize); + int montNsize; + gsMontGetSize(ippBinaryMethod, modulusLen32, &montNsize); + + return sizeof(IppsRSAPrivateKeyState) + + prvExpLen*sizeof(BNU_CHUNK_T) + + sizeof(BNU_CHUNK_T)-1 + + montNsize + + (RSA_PRIVATE_KEY_ALIGNMENT-1); +} + +IPPFUN(IppStatus, ippsRSA_GetSizePrivateKeyType1,(int rsaModulusBitSize, int privateExpBitSize, int* pKeySize)) +{ + IPP_BAD_PTR1_RET(pKeySize); + IPP_BADARG_RET((MIN_RSA_SIZE>rsaModulusBitSize) || (rsaModulusBitSize>MAX_RSA_SIZE), ippStsNotSupportedModeErr); + IPP_BADARG_RET(!((0 rsaModulusBitSize +// MAX_RSA_SIZE < rsaModulusBitSize +// +// ippStsBadArgErr 0 >= privateExpBitSize +// privateExpBitSize > rsaModulusBitSize +// +// ippStsMemAllocErr keyCtxSize is not enough for operation +// +// ippStsNoErr no error +// +// Parameters: +// rsaModulusBitSize bitsize of RSA modulus (bitsize of N) +// privateExpBitSize bitsize of private exponent (bitsize of D) +// pKey pointer to the key context +// keyCtxSize size of memmory accosizted with key comtext +*F*/ +IPPFUN(IppStatus, ippsRSA_InitPrivateKeyType1,(int rsaModulusBitSize, int privateExpBitSize, + IppsRSAPrivateKeyState* pKey, int keyCtxSize)) +{ + IPP_BAD_PTR1_RET(pKey); + pKey = (IppsRSAPrivateKeyState*)( IPP_ALIGNED_PTR(pKey, RSA_PRIVATE_KEY_ALIGNMENT) ); + + IPP_BADARG_RET((MIN_RSA_SIZE>rsaModulusBitSize) || (rsaModulusBitSize>MAX_RSA_SIZE), ippStsNotSupportedModeErr); + IPP_BADARG_RET(!((0= pModulus +// 0 >= pPrivateExp +// +// ippStsSizeErr bitsize(pModulus) exceeds requested value +// bitsize(pPrivateExp) exceeds requested value +// +// ippStsNoErr no error +// +// Parameters: +// pModulus pointer to modulus (N) +// pPrivateExp pointer to public exponent (D) +// pKey pointer to the key context +*F*/ +IPPFUN(IppStatus, ippsRSA_SetPrivateKeyType1,(const IppsBigNumState* pModulus, + const IppsBigNumState* pPrivateExp, + IppsRSAPrivateKeyState* pKey)) +{ + IPP_BAD_PTR1_RET(pKey); + pKey = (IppsRSAPrivateKeyState*)( IPP_ALIGNED_PTR(pKey, RSA_PRIVATE_KEY_ALIGNMENT) ); + IPP_BADARG_RET(!RSA_PRV_KEY1_VALID_ID(pKey), ippStsContextMatchErr); + + IPP_BAD_PTR1_RET(pModulus); + pModulus = (IppsBigNumState*)( IPP_ALIGNED_PTR(pModulus, BN_ALIGNMENT) ); + IPP_BADARG_RET(!BN_VALID_ID(pModulus), ippStsContextMatchErr); + IPP_BADARG_RET(!(0 < cpBN_tst(pModulus)), ippStsOutOfRangeErr); + IPP_BADARG_RET(BITSIZE_BNU(BN_NUMBER(pModulus), BN_SIZE(pModulus)) > RSA_PRV_KEY_MAXSIZE_N(pKey), ippStsSizeErr); + + IPP_BAD_PTR1_RET(pPrivateExp); + pPrivateExp = (IppsBigNumState*)( IPP_ALIGNED_PTR(pPrivateExp, BN_ALIGNMENT) ); + IPP_BADARG_RET(!BN_VALID_ID(pPrivateExp), ippStsContextMatchErr); + IPP_BADARG_RET(!(0 < cpBN_tst(pPrivateExp)), ippStsOutOfRangeErr); + IPP_BADARG_RET(BITSIZE_BNU(BN_NUMBER(pPrivateExp), BN_SIZE(pPrivateExp)) > RSA_PRV_KEY_MAXSIZE_D(pKey), ippStsSizeErr); + + { + /* store D */ + ZEXPAND_COPY_BNU(RSA_PRV_KEY_D(pKey), BITS_BNU_CHUNK(RSA_PRV_KEY_MAXSIZE_D(pKey)), BN_NUMBER(pPrivateExp), BN_SIZE(pPrivateExp)); + + /* setup montgomery engine */ + gsMontSet((Ipp32u*)BN_NUMBER(pModulus), BN_SIZE32(pModulus), RSA_PRV_KEY_NMONT(pKey)); + + RSA_PRV_KEY_BITSIZE_N(pKey) = cpBN_bitsize(pModulus); + RSA_PRV_KEY_BITSIZE_D(pKey) = cpBN_bitsize(pPrivateExp); + + return ippStsNoErr; + } +} + + +/*F* +// Name: ippsRSA_GetSizePrivateKeyType2 +// +// Purpose: Returns context size (bytes) of RSA private key (type2) context +// +// Returns: Reason: +// ippStsNullPtrErr NULL == pSize +// +// ippStsNotSupportedModeErr MIN_RSA_SIZE > (factorPbitSize+factorQbitSize) +// MAX_RSA_SIZE < (factorPbitSize+factorQbitSize) +// +// ippStsBadArgErr 0 >= factorPbitSize +// 0 >= factorQbitSize +// factorQbitSize > factorPbitSize +// +// ippStsNoErr no error +// +// Parameters: +// factorPbitSize bitsize of RSA modulus (bitsize of P) +// factorPbitSize bitsize of private exponent (bitsize of Q) +// pSize pointer to the size of RSA key context (bytes) +*F*/ +static int cpSizeof_RSA_privateKey2(int factorPbitSize, int factorQbitSize) +{ + int factorPlen = BITS_BNU_CHUNK(factorPbitSize); + int factorQlen = BITS_BNU_CHUNK(factorQbitSize); + int factorPlen32 = BITS2WORD32_SIZE(factorPbitSize); + int factorQlen32 = BITS2WORD32_SIZE(factorQbitSize); + int rsaModulusLen32 = BITS2WORD32_SIZE(factorPbitSize+factorQbitSize); + int montPsize; + int montQsize; + int montNsize; + gsMontGetSize(ippBinaryMethod, factorPlen32, &montPsize); + gsMontGetSize(ippBinaryMethod, factorQlen32, &montQsize); + gsMontGetSize(ippBinaryMethod, rsaModulusLen32, &montNsize); + + return sizeof(IppsRSAPrivateKeyState) + + factorPlen*sizeof(BNU_CHUNK_T) /* dp slot */ + + factorQlen*sizeof(BNU_CHUNK_T) /* dq slot */ + + factorPlen*sizeof(BNU_CHUNK_T) /* qinv slot */ + + sizeof(BNU_CHUNK_T)-1 + + montPsize + + montQsize + + montNsize + + (RSA_PRIVATE_KEY_ALIGNMENT-1); +} + +IPPFUN(IppStatus, ippsRSA_GetSizePrivateKeyType2,(int factorPbitSize, int factorQbitSize, int* pKeySize)) +{ + IPP_BAD_PTR1_RET(pKeySize); + IPP_BADARG_RET((factorPbitSize<=0) || (factorQbitSize<=0), ippStsBadArgErr); + IPP_BADARG_RET((factorPbitSize < factorQbitSize), ippStsBadArgErr); + IPP_BADARG_RET((MIN_RSA_SIZE>(factorPbitSize+factorQbitSize) || (factorPbitSize+factorQbitSize)>MAX_RSA_SIZE), ippStsNotSupportedModeErr); + + *pKeySize = cpSizeof_RSA_privateKey2(factorPbitSize, factorQbitSize); + return ippStsNoErr; +} + + +/*F* +// Name: ippsRSA_InitPrivateKeyType2 +// +// Purpose: Init RSA private key context +// +// Returns: Reason: +// ippStsNullPtrErr NULL == pKey +// +// ippStsNotSupportedModeErr MIN_RSA_SIZE > (factorPbitSize+factorQbitSize) +// MAX_RSA_SIZE < (factorPbitSize+factorQbitSize) +// +// ippStsBadArgErr 0 >= factorPbitSize +// 0 >= factorQbitSize +// factorQbitSize > factorPbitSize +// +// ippStsMemAllocErr keyCtxSize is not enough for operation +// +// ippStsNoErr no error +// +// Parameters: +// factorPbitSize bitsize of RSA modulus (bitsize of P) +// factorQbitSize bitsize of private exponent (bitsize of Q) +// pKey pointer to the key context +// keyCtxSize size of memmory accosizted with key comtext +*F*/ +IPPFUN(IppStatus, ippsRSA_InitPrivateKeyType2,(int factorPbitSize, int factorQbitSize, + IppsRSAPrivateKeyState* pKey, int keyCtxSize)) +{ + IPP_BAD_PTR1_RET(pKey); + IPP_BADARG_RET((factorPbitSize<=0) || (factorQbitSize<=0), ippStsBadArgErr); + IPP_BADARG_RET((factorPbitSize < factorQbitSize), ippStsBadArgErr); + IPP_BADARG_RET((MIN_RSA_SIZE>(factorPbitSize+factorQbitSize) || (factorPbitSize+factorQbitSize)>MAX_RSA_SIZE), ippStsNotSupportedModeErr); + + /* test available size of context buffer */ + IPP_BADARG_RET(keyCtxSize= pFactorP, 0 >= pFactorQ +// 0 >= pCrtExpP, 0 >= pCrtExpQ +// 0 >= pInverseQ +// +// ippStsSizeErr bitsize(pFactorP) exceeds requested value +// bitsize(pFactorQ) exceeds requested value +// bitsize(pCrtExpP) > bitsize(pFactorP) +// bitsize(pCrtExpQ) > bitsize(pFactorQ) +// bitsize(pInverseQ) > bitsize(pFactorP) +// +// ippStsNoErr no error +// +// Parameters: +// pFactorP, pFactorQ pointer to the RSA modulus (N) prime factors +// pCrtExpP, pCrtExpQ pointer to CTR's exponent +// pInverseQ 1/Q mod P +// pKey pointer to the key context +*F*/ +IPPFUN(IppStatus, ippsRSA_SetPrivateKeyType2,(const IppsBigNumState* pFactorP, + const IppsBigNumState* pFactorQ, + const IppsBigNumState* pCrtExpP, + const IppsBigNumState* pCrtExpQ, + const IppsBigNumState* pInverseQ, + IppsRSAPrivateKeyState* pKey)) +{ + IPP_BAD_PTR1_RET(pKey); + pKey = (IppsRSAPrivateKeyState*)( IPP_ALIGNED_PTR(pKey, RSA_PRIVATE_KEY_ALIGNMENT) ); + IPP_BADARG_RET(!RSA_PRV_KEY2_VALID_ID(pKey), ippStsContextMatchErr); + + IPP_BAD_PTR1_RET(pFactorP); + pFactorP = (IppsBigNumState*)( IPP_ALIGNED_PTR(pFactorP, BN_ALIGNMENT) ); + IPP_BADARG_RET(!BN_VALID_ID(pFactorP), ippStsContextMatchErr); + IPP_BADARG_RET(!(0 < cpBN_tst(pFactorP)), ippStsOutOfRangeErr); + IPP_BADARG_RET(BITSIZE_BNU(BN_NUMBER(pFactorP), BN_SIZE(pFactorP)) > RSA_PRV_KEY_BITSIZE_P(pKey), ippStsSizeErr); + + IPP_BAD_PTR1_RET(pFactorQ); + pFactorQ = (IppsBigNumState*)( IPP_ALIGNED_PTR(pFactorQ, BN_ALIGNMENT) ); + IPP_BADARG_RET(!BN_VALID_ID(pFactorQ), ippStsContextMatchErr); + IPP_BADARG_RET(!(0 < cpBN_tst(pFactorQ)), ippStsOutOfRangeErr); + IPP_BADARG_RET(BITSIZE_BNU(BN_NUMBER(pFactorQ), BN_SIZE(pFactorQ)) > RSA_PRV_KEY_BITSIZE_Q(pKey), ippStsSizeErr); + + /* let P>Q */ + IPP_BADARG_RET(0>=cpBN_cmp(pFactorP,pFactorQ), ippStsBadArgErr); + + IPP_BAD_PTR1_RET(pCrtExpP); + pCrtExpP = (IppsBigNumState*)( IPP_ALIGNED_PTR(pCrtExpP, BN_ALIGNMENT) ); + IPP_BADARG_RET(!BN_VALID_ID(pCrtExpP), ippStsContextMatchErr); + IPP_BADARG_RET(!(0 < cpBN_tst(pCrtExpP)), ippStsOutOfRangeErr); + IPP_BADARG_RET(BITSIZE_BNU(BN_NUMBER(pCrtExpP), BN_SIZE(pCrtExpP)) > RSA_PRV_KEY_BITSIZE_P(pKey), ippStsSizeErr); + + IPP_BAD_PTR1_RET(pCrtExpQ); + pCrtExpQ = (IppsBigNumState*)( IPP_ALIGNED_PTR(pCrtExpQ, BN_ALIGNMENT) ); + IPP_BADARG_RET(!BN_VALID_ID(pCrtExpQ), ippStsContextMatchErr); + IPP_BADARG_RET(!(0 < cpBN_tst(pCrtExpQ)), ippStsOutOfRangeErr); + IPP_BADARG_RET(BITSIZE_BNU(BN_NUMBER(pCrtExpQ), BN_SIZE(pCrtExpQ)) > RSA_PRV_KEY_BITSIZE_Q(pKey), ippStsSizeErr); + + IPP_BAD_PTR1_RET(pInverseQ); + pInverseQ = (IppsBigNumState*)( IPP_ALIGNED_PTR(pInverseQ, BN_ALIGNMENT) ); + IPP_BADARG_RET(!BN_VALID_ID(pInverseQ), ippStsContextMatchErr); + IPP_BADARG_RET(!(0 < cpBN_tst(pInverseQ)), ippStsOutOfRangeErr); + IPP_BADARG_RET(BITSIZE_BNU(BN_NUMBER(pInverseQ), BN_SIZE(pInverseQ)) > RSA_PRV_KEY_BITSIZE_P(pKey), ippStsSizeErr); + + /* set bitsize(N) = 0, so the key contex is not ready */ + RSA_PRV_KEY_BITSIZE_N(pKey) = 0; + RSA_PRV_KEY_BITSIZE_D(pKey) = 0; + + /* setup montgomery engine P */ + gsMontSet((Ipp32u*)BN_NUMBER(pFactorP), BN_SIZE32(pFactorP), RSA_PRV_KEY_PMONT(pKey)); + /* setup montgomery engine Q */ + gsMontSet((Ipp32u*)BN_NUMBER(pFactorQ), BN_SIZE32(pFactorQ), RSA_PRV_KEY_QMONT(pKey)); + + /* actual size of key components */ + RSA_PRV_KEY_BITSIZE_P(pKey) = cpBN_bitsize(pFactorP); + RSA_PRV_KEY_BITSIZE_Q(pKey) = cpBN_bitsize(pFactorQ); + + /* store CTR's exp dp */ + ZEXPAND_COPY_BNU(RSA_PRV_KEY_DP(pKey), BITS_BNU_CHUNK(RSA_PRV_KEY_BITSIZE_P(pKey)), BN_NUMBER(pCrtExpP), BN_SIZE(pCrtExpP)); + /* store CTR's exp dq */ + ZEXPAND_COPY_BNU(RSA_PRV_KEY_DQ(pKey), BITS_BNU_CHUNK(RSA_PRV_KEY_BITSIZE_Q(pKey)), BN_NUMBER(pCrtExpQ), BN_SIZE(pCrtExpQ)); + /* store mont encoded CTR's coeff qinv */ + { + IppsMontState* pMontP = RSA_PRV_KEY_PMONT(pKey); + BNU_CHUNK_T* pTmpProduct = MNT_MODULUS(RSA_PRV_KEY_NMONT(pKey)); + cpMontMul_BNU(RSA_PRV_KEY_INVQ(pKey), + BN_NUMBER(pInverseQ), BN_SIZE(pInverseQ), + MNT_SQUARE_R(pMontP), MNT_SIZE(pMontP), + MNT_MODULUS(pMontP), MNT_SIZE(pMontP), MNT_HELPER(pMontP), + pTmpProduct, NULL); + } + + /* setup montgomery engine N = P*Q */ + { + BNU_CHUNK_T* pN = MNT_MODULUS(RSA_PRV_KEY_NMONT(pKey)); + cpSize nsN = BITS_BNU_CHUNK(RSA_PRV_KEY_BITSIZE_P(pKey) + RSA_PRV_KEY_BITSIZE_Q(pKey)); + + cpMul_BNU_school(pN, + BN_NUMBER(pFactorP), BN_SIZE(pFactorP), + BN_NUMBER(pFactorQ), BN_SIZE(pFactorQ)); + + gsMontSet((Ipp32u*)MNT_MODULUS(RSA_PRV_KEY_NMONT(pKey)), BITS2WORD32_SIZE(RSA_PRV_KEY_BITSIZE_P(pKey)+RSA_PRV_KEY_BITSIZE_Q(pKey)), RSA_PRV_KEY_NMONT(pKey)); + + FIX_BNU(pN, nsN); + RSA_PRV_KEY_BITSIZE_N(pKey) = BITSIZE_BNU(pN, nsN); + } + + return ippStsNoErr; +} diff --git a/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpngrsakeypublic.c b/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpngrsakeypublic.c new file mode 100644 index 0000000000..a76c955d2a --- /dev/null +++ b/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpngrsakeypublic.c @@ -0,0 +1,272 @@ +/* +* Copyright (C) 2016 Intel Corporation. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in +* the documentation and/or other materials provided with the +* distribution. +* * Neither the name of Intel Corporation nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ + +#include "owndefs.h" +#include "owncp.h" +#include "pcpbn.h" +#include "pcpngrsa.h" +#include "pcpngrsamontstuff.h" + + +/*F* +// Name: ippsRSA_GetSizePublicKey +// +// Purpose: Returns context size (bytes) of RSA public key context +// +// Returns: Reason: +// ippStsNullPtrErr NULL == pSize +// +// ippStsNotSupportedModeErr MIN_RSA_SIZE > rsaModulusBitSize +// MAX_RSA_SIZE < rsaModulusBitSize +// +// ippStsBadArgErr 0 >= publicExpBitSize +// publicExpBitSize > rsaModulusBitSize +// +// ippStsNoErr no error +// +// Parameters: +// rsaModulusBitSize bitsize of RSA modulus (bitsize of N) +// publicExpBitSize bitsize of public exponent (bitsize of E) +// pSize pointer to the size of RSA key context (bytes) +*F*/ +static int cpSizeof_RSA_publicKey(int rsaModulusBitSize, int publicExpBitSize) +{ + int pubExpLen = BITS_BNU_CHUNK(publicExpBitSize); + int modulusLen32 = BITS2WORD32_SIZE(rsaModulusBitSize); + int montNsize; + gsMontGetSize(ippBinaryMethod, modulusLen32, &montNsize); + + return sizeof(IppsRSAPublicKeyState) + + pubExpLen*sizeof(BNU_CHUNK_T) + + sizeof(BNU_CHUNK_T)-1 + + montNsize + + (RSA_PUBLIC_KEY_ALIGNMENT-1); +} + +IPPFUN(IppStatus, ippsRSA_GetSizePublicKey,(int rsaModulusBitSize, int publicExpBitSize, int* pKeySize)) +{ + IPP_BAD_PTR1_RET(pKeySize); + IPP_BADARG_RET((MIN_RSA_SIZE>rsaModulusBitSize) || (rsaModulusBitSize>MAX_RSA_SIZE), ippStsNotSupportedModeErr); + IPP_BADARG_RET(!((0 rsaModulusBitSize +// MAX_RSA_SIZE < rsaModulusBitSize +// +// ippStsBadArgErr 0 >= publicExpBitSize +// publicExpBitSize > rsaModulusBitSize +// +// ippStsMemAllocErr keyCtxSize is not enough for operation +// +// ippStsNoErr no error +// +// Parameters: +// rsaModulusBitSize bitsize of RSA modulus (bitsize of N) +// publicExpBitSize bitsize of public exponent (bitsize of E) +// pKey pointer to the key context +// keyCtxSize size of memmory accosizted with key comtext +*F*/ +IPPFUN(IppStatus, ippsRSA_InitPublicKey,(int rsaModulusBitSize, int publicExpBitSize, + IppsRSAPublicKeyState* pKey, int keyCtxSize)) +{ + IPP_BAD_PTR1_RET(pKey); + pKey = (IppsRSAPublicKeyState*)( IPP_ALIGNED_PTR(pKey, RSA_PUBLIC_KEY_ALIGNMENT) ); + + IPP_BADARG_RET((MIN_RSA_SIZE>rsaModulusBitSize) || (rsaModulusBitSize>MAX_RSA_SIZE), ippStsNotSupportedModeErr); + IPP_BADARG_RET(!((0= pModulus +// 0 >= pPublicExp +// +// ippStsSizeErr bitsize(pModulus) exceeds requested value +// bitsize(pPublicExp) exceeds requested value +// +// ippStsNoErr no error +// +// Parameters: +// pModulus pointer to modulus (N) +// pPublicExp pointer to public exponent (E) +// pKey pointer to the key context +*F*/ +IPPFUN(IppStatus, ippsRSA_SetPublicKey,(const IppsBigNumState* pModulus, + const IppsBigNumState* pPublicExp, + IppsRSAPublicKeyState* pKey)) +{ + IPP_BAD_PTR1_RET(pKey); + pKey = (IppsRSAPublicKeyState*)( IPP_ALIGNED_PTR(pKey, RSA_PUBLIC_KEY_ALIGNMENT) ); + IPP_BADARG_RET(!RSA_PUB_KEY_VALID_ID(pKey), ippStsContextMatchErr); + + IPP_BAD_PTR1_RET(pModulus); + pModulus = (IppsBigNumState*)( IPP_ALIGNED_PTR(pModulus, BN_ALIGNMENT) ); + IPP_BADARG_RET(!BN_VALID_ID(pModulus), ippStsContextMatchErr); + IPP_BADARG_RET(!(0 < cpBN_tst(pModulus)), ippStsOutOfRangeErr); + IPP_BADARG_RET(BITSIZE_BNU(BN_NUMBER(pModulus), BN_SIZE(pModulus)) > RSA_PUB_KEY_MAXSIZE_N(pKey), ippStsSizeErr); + + IPP_BAD_PTR1_RET(pPublicExp); + pPublicExp = (IppsBigNumState*)( IPP_ALIGNED_PTR(pPublicExp, BN_ALIGNMENT) ); + IPP_BADARG_RET(!BN_VALID_ID(pPublicExp), ippStsContextMatchErr); + IPP_BADARG_RET(!(0 < cpBN_tst(pPublicExp)), ippStsOutOfRangeErr); + IPP_BADARG_RET(BITSIZE_BNU(BN_NUMBER(pPublicExp), BN_SIZE(pPublicExp)) > RSA_PUB_KEY_MAXSIZE_E(pKey), ippStsSizeErr); + + { + RSA_PUB_KEY_BITSIZE_N(pKey) = 0; + RSA_PUB_KEY_BITSIZE_E(pKey) = 0; + + /* store E */ + ZEXPAND_COPY_BNU(RSA_PUB_KEY_E(pKey), BITS_BNU_CHUNK(RSA_PUB_KEY_MAXSIZE_E(pKey)), BN_NUMBER(pPublicExp), BN_SIZE(pPublicExp)); + + /* setup montgomery engine */ + gsMontSet((Ipp32u*)BN_NUMBER(pModulus), BN_SIZE32(pModulus), RSA_PUB_KEY_NMONT(pKey)); + + RSA_PUB_KEY_BITSIZE_N(pKey) = cpBN_bitsize(pModulus); + RSA_PUB_KEY_BITSIZE_E(pKey) = cpBN_bitsize(pPublicExp); + + return ippStsNoErr; + } +} + + +/*F* +// Name: ippsRSA_GetPublicKey +// +// Purpose: Extract key component from the key context +// +// Returns: Reason: +// ippStsNullPtrErr NULL == pKey +// +// ippStsContextMatchErr !RSA_PUB_KEY_VALID_ID() +// !BN_VALID_ID(pModulus) +// !BN_VALID_ID(pExp) +// +// ippStsIncompleteContextErr public key is not set up +// +// ippStsSizeErr BN_ROOM(pModulus), BN_ROOM(pExp) is not enough +// +// ippStsNoErr no error +// +// Parameters: +// pModulus (optional) pointer to the modulus (N) +// pExp (optional) pointer to the public exponent (E) +// pKey pointer to the key context +*F*/ +IPPFUN(IppStatus, ippsRSA_GetPublicKey,(IppsBigNumState* pModulus, + IppsBigNumState* pExp, + const IppsRSAPublicKeyState* pKey)) +{ + IPP_BAD_PTR1_RET(pKey); + pKey = (IppsRSAPublicKeyState*)( IPP_ALIGNED_PTR(pKey, RSA_PUBLIC_KEY_ALIGNMENT) ); + IPP_BADARG_RET(!RSA_PUB_KEY_VALID_ID(pKey), ippStsContextMatchErr); + + if(pModulus) { + pModulus = (IppsBigNumState*)( IPP_ALIGNED_PTR(pModulus, BN_ALIGNMENT) ); + IPP_BADARG_RET(!BN_VALID_ID(pModulus), ippStsContextMatchErr); + IPP_BADARG_RET(!RSA_PUB_KEY_IS_SET(pKey), ippStsIncompleteContextErr); + IPP_BADARG_RET(BN_ROOM(pModulus)0; nsE--) { + eValue = dataE[nsE-1]; + + for(n=0; n=0; j--) { + mask_pattern = (BNU_CHUNK_T)(back_step-1); + + /* safeBuffer = (Y[] and mask_pattern) or (X[] and ~mask_pattern) */ + for(i=0; i>j) & 0x1) & (back_step^1); + j += back_step; + } + + /* execute rest bits of E */ + for(--nsE; nsE>0; nsE--) { + eValue = dataE[nsE-1]; + + for(j=BNU_CHUNK_BITS-1; j>=0; j--) { + mask_pattern = (BNU_CHUNK_T)(back_step-1); + + /* safeBuffer = (Y[] and mask_pattern) or (X[] and ~mask_pattern) */ + for(i=0; i>j) & 0x1) & (back_step^1); + j += back_step; + } + } + } + + return nsM; +} + + +/* +// "fast" fixed-size window montgomery exponentiation +// +// scratch buffer structure: +// precomutation resource[(1<>shift) &mask; + + /* initialize result */ + COPY_BNU(dataY, pResource+windowVal*nsM, nsM); + + for(eBit-=wBitSize; eBit>=0; eBit-=wBitSize) { + /* do square window times */ + for(n=0,windowVal=0; n>shift) &mask; + + if(windowVal) { + /* extract precomputed value and muptiply */ + cpMul_BNU(pProduct, dataY, nsM, pResource+windowVal*nsM, nsM, pBufferMulK); + cpMontRed_BNU(dataY, pProduct, dataM, nsM, m0); + } + } + } + } + + return nsM; +} + + +/* +// "safe" fixed-size window montgomery exponentiation +// +// scratch buffer structure: +// precomutation resource[(1<>shift) &mask; + + /* initialize result */ + cpScrambleGet((Ipp32u*)dataY, nsM*sizeof(BNU_CHUNK_T)/sizeof(Ipp32u), ((Ipp8u*)pResource)+windowVal*chunkSize, chunkSize); + + for(eBit-=bitsizeEwin; eBit>=0; eBit-=bitsizeEwin) { + /* do square window times */ + for(n=0,windowVal=0; n>shift) &mask; + + /* exptact precomputed value and muptiply */ + cpScrambleGet((Ipp32u*)dataT, nsM*sizeof(BNU_CHUNK_T)/sizeof(Ipp32u), ((Ipp8u*)pResource)+windowVal*chunkSize, chunkSize); + + cpMul_BNU(pProduct, dataY, nsM, dataT, nsM, pBufferMulK); + cpMontRed_BNU(dataY, pProduct, dataM, nsM, m0); + } + } + } + + return nsM; +} diff --git a/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpngrsamontstuff.h b/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpngrsamontstuff.h new file mode 100644 index 0000000000..2c69c8f0b3 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpngrsamontstuff.h @@ -0,0 +1,229 @@ +/* +* Copyright (C) 2016 Intel Corporation. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in +* the documentation and/or other materials provided with the +* distribution. +* * Neither the name of Intel Corporation nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ + +#if !defined(_CP_NG_RSA_MONT_STUFF_H) +#define _CP_NG_RSA_MONT_STUFF_H + +#include "pcpbn.h" +#include "pcpmontgomery.h" + +/* +// Montgomery engine preparation (GetSize/init/Set) +*/ +void gsMontGetSize(IppsExpMethod method, int length, int* pSize); +void gsMontInit(IppsExpMethod method, int length, IppsMontState* pCtx); +void gsMontSet(const Ipp32u* pModulo, int size, IppsMontState* pCtx); + + +/* +// optimal size of fixed window exponentiation +*/ +__INLINE cpSize gsMontExp_WinSize(cpSize bitsize) +{ + return + bitsize> 4096? 6 : /* 4096- .. . */ + bitsize> 2666? 5 : /* 2666 - 4095 */ + bitsize> 717? 4 : /* 717 - 2665 */ + bitsize> 178? 3 : /* 178 - 716 */ + bitsize> 41? 2 : 1; /* 41 - 177 */ +} + +/* +// Montgomery encoding/decoding +*/ +__INLINE cpSize gsMontEnc_BNU(BNU_CHUNK_T* pR, + const BNU_CHUNK_T* pXreg, cpSize nsX, + const IppsMontState* pMont, + BNU_CHUNK_T* pBuffer) +{ + cpSize nsM = MNT_SIZE(pMont); + BNU_CHUNK_T* pProduct = pBuffer; + BNU_CHUNK_T* pBufferKmul = NULL; + + cpMontMul_BNU(pR, + pXreg, nsX, MNT_SQUARE_R(pMont), nsM, + MNT_MODULUS(pMont), nsM, MNT_HELPER(pMont), + pProduct, pBufferKmul); + return nsM; +} + +__INLINE cpSize gsMontDec_BNU(BNU_CHUNK_T* pR, + const BNU_CHUNK_T* pXmont, cpSize nsX, + const IppsMontState* pMont, + BNU_CHUNK_T* pBuffer) +{ + cpSize nsM = MNT_SIZE(pMont); + ZEXPAND_COPY_BNU(pBuffer, 2*nsM, pXmont, nsX); + + cpMontRed_BNU(pR, pBuffer, MNT_MODULUS(pMont), nsM, MNT_HELPER(pMont)); + return nsM; +} + +__INLINE void gsMontEnc_BN(IppsBigNumState* pRbn, + const IppsBigNumState* pXbn, + const IppsMontState* pMont, + BNU_CHUNK_T* pBuffer) +{ + BNU_CHUNK_T* pR = BN_NUMBER(pRbn); + cpSize nsM = MNT_SIZE(pMont); + + gsMontEnc_BNU(pR, BN_NUMBER(pXbn), BN_SIZE(pXbn), pMont, pBuffer); + + FIX_BNU(pR, nsM); + BN_SIZE(pRbn) = nsM; + BN_SIGN(pRbn) = ippBigNumPOS; +} + +__INLINE void gsMontDec_BN(IppsBigNumState* pRbn, + const IppsBigNumState* pXbn, + const IppsMontState* pMont, + BNU_CHUNK_T* pBuffer) +{ + BNU_CHUNK_T* pR = BN_NUMBER(pRbn); + cpSize nsM = MNT_SIZE(pMont); + + gsMontDec_BNU(pR, BN_NUMBER(pXbn), BN_SIZE(pXbn), pMont, pBuffer); + + FIX_BNU(pR, nsM); + BN_SIZE(pRbn) = nsM; + BN_SIGN(pRbn) = ippBigNumPOS; +} + + +/* +// binary montgomery exponentiation ("fast" version) +*/ +cpSize gsMontExpBin_BNU(BNU_CHUNK_T* dataY, + const BNU_CHUNK_T* dataX, cpSize nsX, + const BNU_CHUNK_T* dataE, cpSize nsE, + const IppsMontState* pMont, + BNU_CHUNK_T* pBuffer); + +__INLINE void gsMontExpBin_BN(IppsBigNumState* pY, + const IppsBigNumState* pX, + const BNU_CHUNK_T* dataE, cpSize nsE, + const IppsMontState* pMont, + BNU_CHUNK_T* pBuffer) +{ + BNU_CHUNK_T* dataY = BN_NUMBER(pY); + cpSize nsY = gsMontExpBin_BNU(dataY, + BN_NUMBER(pX), BN_SIZE(pX), + dataE, nsE, + pMont, pBuffer); + FIX_BNU(dataY, nsY); + BN_SIZE(pY) = nsY; + BN_SIGN(pY) = ippBigNumPOS; +} + +/* +// fixed-size window montgomery exponentiation ("fast" version) +*/ +cpSize gsMontExpWin_BNU(BNU_CHUNK_T* pY, + const BNU_CHUNK_T* pX, cpSize nsX, + const BNU_CHUNK_T* dataE, cpSize nsE, cpSize bitsieW, + const IppsMontState* pMont, + BNU_CHUNK_T* pBuffer); + +__INLINE void gsMontExpWin_BN(IppsBigNumState* pY, + const IppsBigNumState* pX, + const BNU_CHUNK_T* dataE, cpSize nsE, cpSize bitsieW, + const IppsMontState* pMont, + BNU_CHUNK_T* pBuffer) +{ + BNU_CHUNK_T* dataY = BN_NUMBER(pY); + cpSize nsY = gsMontExpWin_BNU(dataY, + BN_NUMBER(pX), BN_SIZE(pX), + dataE, nsE, bitsieW, + pMont, pBuffer); + FIX_BNU(dataY, nsY); + BN_SIZE(pY) = nsY; + BN_SIGN(pY) = ippBigNumPOS; +} + +/* +// binary montgomery exponentiation ("safe" version) +*/ +__INLINE cpSize gsPrecompResourcelen(int n, cpSize nsM) +{ + cpSize nsR = sizeof(BNU_CHUNK_T)*nsM*n + (CACHE_LINE_SIZE-1); + nsR /=CACHE_LINE_SIZE; /* num of cashe lines */ + nsR *= (CACHE_LINE_SIZE/sizeof(BNU_CHUNK_T)); + return nsR; +} + +cpSize gsMontExpBin_BNU_sscm(BNU_CHUNK_T* pY, + const BNU_CHUNK_T* pX, cpSize nsX, + const BNU_CHUNK_T* pE, cpSize nsE, + const IppsMontState* pMont, + BNU_CHUNK_T* pBuffer); + +__INLINE void gsMontExpBin_BN_sscm(IppsBigNumState* pY, + const IppsBigNumState* pX, + const BNU_CHUNK_T* dataE, cpSize nsE, + const IppsMontState* pMont, + BNU_CHUNK_T* pBuffer) +{ + BNU_CHUNK_T* dataY = BN_NUMBER(pY); + cpSize nsY = gsMontExpBin_BNU_sscm(dataY, + BN_NUMBER(pX), BN_SIZE(pX), + dataE, nsE, + pMont, pBuffer); + FIX_BNU(dataY, nsY); + BN_SIZE(pY) = nsY; + BN_SIGN(pY) = ippBigNumPOS; +} + +/* +// fixed-size window montgomery exponentiation ("safe" version) +*/ +cpSize gsMontExpWin_BNU_sscm(BNU_CHUNK_T* dataY, + const BNU_CHUNK_T* dataX, cpSize nsX, + const BNU_CHUNK_T* dataE, cpSize nsE, cpSize bitsieEwin, + const IppsMontState* pMont, + BNU_CHUNK_T* pBuffer); + +__INLINE void gsMontExpWin_BN_sscm(IppsBigNumState* pY, + const IppsBigNumState* pX, + const BNU_CHUNK_T* dataE, cpSize nsE, cpSize bitsieEwin, + const IppsMontState* pMont, + BNU_CHUNK_T* pBuffer) +{ + BNU_CHUNK_T* dataY = BN_NUMBER(pY); + cpSize nsY = gsMontExpWin_BNU_sscm(dataY, + BN_NUMBER(pX), BN_SIZE(pX), + dataE, nsE, bitsieEwin, + pMont, pBuffer); + FIX_BNU(dataY, nsY); + BN_SIZE(pY) = nsY; + BN_SIGN(pY) = ippBigNumPOS; +} + +#endif /* _CP_NG_RSA_MONT_STUFF_H */ diff --git a/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpngrsassapkcsv15ca.c b/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpngrsassapkcsv15ca.c new file mode 100644 index 0000000000..c16699fc14 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpngrsassapkcsv15ca.c @@ -0,0 +1,278 @@ +/* +* Copyright (C) 2016 Intel Corporation. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in +* the documentation and/or other materials provided with the +* distribution. +* * Neither the name of Intel Corporation nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ + +#include "owndefs.h" +#include "owncp.h" + +#include "pcpngrsa.h" +#include "pcphash.h" +#include "pcptool.h" + +static int EMSA_PKCSv15(const Ipp8u* msgDg, int lenMsgDg, + const Ipp8u* fixPS, int lenFixPS, + Ipp8u* pEM, int lenEM) +{ + /* + // encoded message format: + // EM = 00 || 01 || PS=(FF..FF) || 00 || T + // T = fixPS || msgDg + // len(PS) >= 8 + */ + int tLen = lenFixPS + lenMsgDg; + + if(lenEM >= tLen+11) { + int psLen = lenEM - 3 - tLen; + + PaddBlock(0xFF, pEM, lenEM); + pEM[0] = 0x00; + pEM[1] = 0x01; + pEM[2+psLen] = 0x00; + CopyBlock(fixPS, pEM+3+psLen, lenFixPS); + CopyBlock(msgDg, pEM+3+psLen+lenFixPS, lenMsgDg); + return 1; + } + else + return 0; /* encoded message length too long */ +} + +/* +// The DER encoding T of the DigestInfo value is equal to the following (see PKCS-1v2-2): +*/ +static const Ipp8u SHA1_fixPS[] = "\x30\x21\x30\x09\x06\x05\x2b\x0e\x03\x02\x1a\x05\x00\x04\x14"; +static const Ipp8u SHA224_fixPS[] = "\x30\x2d\x30\x0d\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x04\x05\x00\x04\x1c"; +static const Ipp8u SHA256_fixPS[] = "\x30\x31\x30\x0d\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x01\x05\x00\x04\x20"; +static const Ipp8u SHA384_fixPS[] = "\x30\x41\x30\x0d\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x02\x05\x00\x04\x30"; +static const Ipp8u SHA512_fixPS[] = "\x30\x51\x30\x0d\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x03\x05\x00\x04\x40"; +static const Ipp8u MD5_fixPS[] = "\x30\x20\x30\x0c\x06\x08\x2a\x86\x48\x86\xf7\x0d\x02\x05\x05\x00\x04\x10"; +static const Ipp8u SHA512_224_fixPS[] = "\x30\x2d\x30\x0d\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x05\x05\x00\x04\x1c"; +static const Ipp8u SHA512_256_fixPS[] = "\x30\x31\x30\x0d\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x06\x05\x00\x04\x20"; + +typedef struct { + const Ipp8u* pSalt; + int saltLen; +} SaltInfo; + +static SaltInfo pksc15_salt[] = { + {NULL, 0}, + {SHA1_fixPS, sizeof(SHA1_fixPS)-1}, + {SHA256_fixPS, sizeof(SHA256_fixPS)-1}, + {SHA224_fixPS, sizeof(SHA224_fixPS)-1}, + {SHA512_fixPS, sizeof(SHA512_fixPS)-1}, + {SHA384_fixPS, sizeof(SHA384_fixPS)-1}, + { MD5_fixPS, sizeof(MD5_fixPS)-1}, + {NULL, 0}, + {SHA512_224_fixPS, sizeof(SHA512_224_fixPS)-1}, + {SHA512_256_fixPS, sizeof(SHA512_256_fixPS)-1}, +}; +/* //////////////////////////////////////////////////////////////////////////////////////////////// */ + +static int GenerateSing(const Ipp8u* pMsg, int msgLen, /* message representation */ + const Ipp8u* pSalt, int saltLen, /* fied string */ + Ipp8u* pSign, + const IppsRSAPrivateKeyState* pPrvKey, + const IppsRSAPublicKeyState* pPubKey, + Ipp8u* pBuffer) +{ + /* size of RSA modulus in bytes and chunks */ + cpSize rsaBits = RSA_PRV_KEY_BITSIZE_N(pPrvKey); + cpSize k = BITS2WORD8_SIZE(rsaBits); + cpSize nsN = BITS_BNU_CHUNK(rsaBits); + + /* EMSA-PKCS-v1_5 encoding */ + int result = EMSA_PKCSv15(pMsg,msgLen, pSalt,saltLen, pSign, k); + + if(result) { + /* align buffer */ + BNU_CHUNK_T* pScratchBuffer = (BNU_CHUNK_T*)(IPP_ALIGNED_PTR(pBuffer, (int)sizeof(BNU_CHUNK_T)) ); + + /* temporary BNs */ + __ALIGN8 IppsBigNumState bnC; + __ALIGN8 IppsBigNumState bnP; + + /* make BNs */ + BN_Make(pScratchBuffer, pScratchBuffer+nsN+1, nsN, &bnC); + pScratchBuffer += (nsN+1)*2; + BN_Make(pScratchBuffer, pScratchBuffer+nsN+1, nsN, &bnP); + pScratchBuffer += (nsN+1)*2; + + /* + // private-key operation + */ + ippsSetOctString_BN(pSign, k, &bnC); + + if(RSA_PRV_KEY1_VALID_ID(pPrvKey)) + gsRSAprv_cipher(&bnP, &bnC, pPrvKey, pScratchBuffer); + else + gsRSAprv_cipher_crt(&bnP, &bnC, pPrvKey, pScratchBuffer); + + ippsGetOctString_BN(pSign, k, &bnP); + + /* check the result before send it out (fault attack mitigatioin) */ + if(pPubKey) { + gsRSApub_cipher(&bnP, &bnP, pPubKey, pScratchBuffer); + + /* check signature before send it out (fault attack mitigatioin) */ + if(0!=cpBN_cmp(&bnP, &bnC)) { + PaddBlock(0, pSign, k); + result = 0; + } + } + } + + return result; +} + +IPPFUN(IppStatus, ippsRSASign_PKCS1v15,(const Ipp8u* pMsg, int msgLen, + Ipp8u* pSign, + const IppsRSAPrivateKeyState* pPrvKey, + const IppsRSAPublicKeyState* pPubKey, + IppHashAlgId hashAlg, + Ipp8u* pBuffer)) +{ + /* test private key context */ + IPP_BAD_PTR2_RET(pPrvKey, pBuffer); + pPrvKey = (IppsRSAPrivateKeyState*)( IPP_ALIGNED_PTR(pPrvKey, RSA_PRIVATE_KEY_ALIGNMENT) ); + IPP_BADARG_RET(!RSA_PRV_KEY_VALID_ID(pPrvKey), ippStsContextMatchErr); + IPP_BADARG_RET(!RSA_PRV_KEY_IS_SET(pPrvKey), ippStsIncompleteContextErr); + + /* test hash algorith ID */ + hashAlg = cpValidHashAlg(hashAlg); + IPP_BADARG_RET(ippHashAlg_Unknown==hashAlg, ippStsNotSupportedModeErr); + + /* use aligned public key context if defined */ + if(pPubKey) { + pPubKey = (IppsRSAPublicKeyState*)( IPP_ALIGNED_PTR(pPubKey, RSA_PUBLIC_KEY_ALIGNMENT) ); + IPP_BADARG_RET(!RSA_PUB_KEY_VALID_ID(pPubKey), ippStsContextMatchErr); + IPP_BADARG_RET(!RSA_PUB_KEY_IS_SET(pPubKey), ippStsIncompleteContextErr); + } + + /* test data pointer */ + IPP_BAD_PTR2_RET(pMsg, pSign); + /* test length */ + IPP_BADARG_RET(msgLen<0, ippStsLengthErr); + + { + Ipp8u md[IPP_SHA512_DIGEST_BITSIZE/BYTESIZE]; + int mdLen = cpHashSize(hashAlg); + ippsHashMessage(pMsg, msgLen, md, hashAlg); + + { + const Ipp8u* pSalt = pksc15_salt[hashAlg].pSalt; + int saltLen = pksc15_salt[hashAlg].saltLen; + + int sts = GenerateSing(md, mdLen, + pSalt, saltLen, + pSign, + pPrvKey, pPubKey, pBuffer); + + return (1==sts)? ippStsNoErr : ippStsSizeErr; + } + } +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +static int VerifySing(const Ipp8u* pMsg, int msgLen, /* message representation */ + const Ipp8u* pSalt, int saltLen, /* fied string */ + const Ipp8u* pSign, + int* pIsValid, + const IppsRSAPublicKeyState* pKey, + Ipp8u* pBuffer) +{ + /* size of RSA modulus in bytes and chunks */ + cpSize rsaBits = RSA_PUB_KEY_BITSIZE_N(pKey); + cpSize k = BITS2WORD8_SIZE(rsaBits); + cpSize nsN = BITS_BNU_CHUNK(rsaBits); + + /* align buffer */ + BNU_CHUNK_T* pScratchBuffer = (BNU_CHUNK_T*)(IPP_ALIGNED_PTR(pBuffer, (int)sizeof(BNU_CHUNK_T)) ); + + /* temporary BNs */ + __ALIGN8 IppsBigNumState bnC; + __ALIGN8 IppsBigNumState bnP; + + /* make BNs */ + BN_Make(pScratchBuffer, pScratchBuffer+nsN+1, nsN, &bnC); + pScratchBuffer += (nsN+1)*2; + BN_Make(pScratchBuffer, pScratchBuffer+nsN+1, nsN, &bnP); + pScratchBuffer += (nsN+1)*2; + + /* + // public-key operation + */ + ippsSetOctString_BN(pSign, k, &bnP); + gsRSApub_cipher(&bnC, &bnP, pKey, pScratchBuffer); + + /* convert EM into the string */ + ippsGetOctString_BN((Ipp8u*)(BN_BUFFER(&bnC)), k, &bnC); + + /* EMSA-PKCS-v1_5 encoding */ + if( EMSA_PKCSv15(pMsg,msgLen, pSalt,saltLen, (Ipp8u*)(BN_NUMBER(&bnC)), k) ) { + *pIsValid = 1==EquBlock((Ipp8u*)(BN_BUFFER(&bnC)), (Ipp8u*)(BN_NUMBER(&bnC)), k); + return 1; + } + else + return 0; +} + +IPPFUN(IppStatus, ippsRSAVerify_PKCS1v15,(const Ipp8u* pMsg, int msgLen, + const Ipp8u* pSign, int* pIsValid, + const IppsRSAPublicKeyState* pKey, + IppHashAlgId hashAlg, + Ipp8u* pBuffer)) +{ + /* test public key context */ + IPP_BAD_PTR2_RET(pKey, pBuffer); + pKey = (IppsRSAPublicKeyState*)( IPP_ALIGNED_PTR(pKey, RSA_PUBLIC_KEY_ALIGNMENT) ); + IPP_BADARG_RET(!RSA_PUB_KEY_VALID_ID(pKey), ippStsContextMatchErr); + IPP_BADARG_RET(!RSA_PUB_KEY_IS_SET(pKey), ippStsIncompleteContextErr); + + /* test hash algorith ID */ + hashAlg = cpValidHashAlg(hashAlg); + IPP_BADARG_RET(ippHashAlg_Unknown==hashAlg, ippStsNotSupportedModeErr); + + /* test data pointer */ + IPP_BAD_PTR3_RET(pMsg, pSign, pIsValid); + /* test length */ + IPP_BADARG_RET(msgLen<0, ippStsLengthErr); + + *pIsValid = 0; + { + Ipp8u md[IPP_SHA512_DIGEST_BITSIZE/BYTESIZE]; + int mdLen = cpHashSize(hashAlg); + ippsHashMessage(pMsg, msgLen, md, hashAlg); + + return VerifySing(md, mdLen, + pksc15_salt[hashAlg].pSalt, pksc15_salt[hashAlg].saltLen, + pSign, pIsValid, + pKey, pBuffer)? ippStsNoErr : ippStsSizeErr; + } +} diff --git a/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcppma.h b/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcppma.h new file mode 100644 index 0000000000..66f5da33fe --- /dev/null +++ b/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcppma.h @@ -0,0 +1,83 @@ +/* +* Copyright (C) 2016 Intel Corporation. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in +* the documentation and/or other materials provided with the +* distribution. +* * Neither the name of Intel Corporation nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ + +#if !defined(_PCP_PMA_H) +#define _PCP_PMA_H + +#include "pcpbn.h" +#include "pcpmontgomery.h" + + +/* +// Prime Modulo Arithmetic +*/ +#define PMA_set(r,a) \ + BN_SIGN((r)) = BN_SIGN((a)); \ + BN_SIZE((r)) = BN_SIZE((a)); \ + ZEXPAND_COPY_BNU(BN_NUMBER((r)),BN_ROOM((r)), BN_NUMBER((a)),BN_SIZE((a))) \ + +#define PMA_mod(r,a,modulo) \ + ippsMod_BN((a),(modulo),(r)) + +#define PMA_inv(r,a,modulo) \ + ippsModInv_BN((a),(modulo),(r)) + +#define PMA_div2(r,a,modulo) { \ + if( IsOdd_BN((a)) ) { \ + ippsAdd_BN((a), (modulo), (a)); \ + } \ + BN_SIZE((r)) = cpLSR_BNU(BN_NUMBER((r)), BN_NUMBER((a)), (int)BN_SIZE((a)), 1); \ + cpBN_fix((r)); \ +} + +#define PMA_add(r,a,b,modulo) \ + ippsAdd_BN((a),(b),(r)); \ + if( cpCmp_BNU(BN_NUMBER((r)),BN_SIZE((r)),BN_NUMBER((modulo)),BN_SIZE(modulo)) >= 0 ) \ + ippsSub_BN((r),(modulo),(r)) + +#define PMA_sub(r,a,b,modulo) \ + ippsSub_BN((a),(b),(r)); \ + if( BN_NEGATIVE((r)) ) \ + ippsAdd_BN((r),(modulo),(r)) + +#define PMA_enc(r,a,mont) \ + cpMontEnc_BN((r), (a), (mont)) + +#define PMA_dec(r,a,mont) \ + cpMontDec_BN((r), (a), (mont)) + +#define PMA_sqre(r,a,mont) \ + ippsMontMul((a),(a), (mont),(r)) + +#define PMA_mule(r,a,b,mont) \ + ippsMontMul((a),(b), (mont),(r)) + +#endif /* _PCP_PMA_H */ diff --git a/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpprimeg.h b/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpprimeg.h new file mode 100644 index 0000000000..7e54efbe61 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpprimeg.h @@ -0,0 +1,78 @@ +/* +* Copyright (C) 2016 Intel Corporation. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in +* the documentation and/or other materials provided with the +* distribution. +* * Neither the name of Intel Corporation nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ + +#if !defined(_CP_PRIME_H) +#define _CP_PRIME_H + +#include "pcpbn.h" +#include "pcpmontgomery.h" + + +/* +// Prime context +*/ +struct _cpPrime { + IppCtxId idCtx; /* Prime context identifier */ + cpSize maxBitSize; /* max bit length */ + BNU_CHUNK_T* pPrime; /* prime value */ + BNU_CHUNK_T* pT1; /* temporary BNU */ + BNU_CHUNK_T* pT2; /* temporary BNU */ + BNU_CHUNK_T* pT3; /* temporary BNU */ + IppsMontState* pMont; /* montgomery engine */ +}; + +/* alignment */ +#define PRIME_ALIGNMENT ((int)sizeof(void*)) + +/* Prime accessory macros */ +#define PRIME_ID(ctx) ((ctx)->idCtx) +#define PRIME_MAXBITSIZE(ctx) ((ctx)->maxBitSize) +#define PRIME_NUMBER(ctx) ((ctx)->pPrime) +#define PRIME_TEMP1(ctx) ((ctx)->pT1) +#define PRIME_TEMP2(ctx) ((ctx)->pT2) +#define PRIME_TEMP3(ctx) ((ctx)->pT3) +#define PRIME_MONT(ctx) ((ctx)->pMont) + +#define PRIME_VALID_ID(ctx) (PRIME_ID((ctx))==idCtxPrimeNumber) + +/* easy prime test */ +int cpMimimalPrimeTest(const Ipp32u* pPrime, cpSize ns); + +/* prime test */ +int cpPrimeTest(const BNU_CHUNK_T* pPrime, cpSize primeLen, + cpSize nTrials, + IppsPrimeState* pCtx, + IppBitSupplier rndFunc, void* pRndParam); + +void cpPackPrimeCtx(const IppsPrimeState* pCtx, Ipp8u* pBuffer); +void cpUnpackPrimeCtx(const Ipp8u* pBuffer, IppsPrimeState* pCtx); + +#endif /* _CP_PRIME_H */ diff --git a/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpprimegenca.c b/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpprimegenca.c new file mode 100644 index 0000000000..6b105e8c16 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpprimegenca.c @@ -0,0 +1,472 @@ +/* +* Copyright (C) 2016 Intel Corporation. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in +* the documentation and/or other materials provided with the +* distribution. +* * Neither the name of Intel Corporation nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ + +#include "owncp.h" +#include "pcpprimeg.h" +#include "pcptool.h" + + +/*F* +// Name: ippsPrimeTest +// +// Purpose: Tests the set BN for being a probable prime. +// +// Returns: Reason: +// ippStsNullPtrErr NULL == pCtx +// NULL == pResult +// NULL == rndFunc +// ippStsContextMatchErr illegal pCtx->idCtx +// ippStsOutOfRangeErr zero value under the test +// ippStsBadArgErr 1 > nTrials +// ippStsNoErr no error +// +// Parameters: +// nTrials parameter for the Miller-Rabin probable primality test +// pResult pointer to the test result (IS_COMPOSITE / IS_PRIME) +// pCtx pointer to the context +// rndFunc external PRNG +// pRndParam pointer to the external PRNG parameters +*F*/ + +/* minimal prime test */ +static Ipp32u PrimeList[] = { + 2, 3, 5, 7, 11, 13, 17, 19, + 23, 29, 31, 37, 41, 43, 47, 53, + 59, 61, 67, 71, 73, 79, 83, 89, + 97, 101, 103, 107, 109, 113, 127, 131, + 137, 139, 149, 151, 157, 163, 167, 173, + 179, 181, 191, 193, 197, 199, 211, 223, + 227, 229, 233, 239, 241, 251, 257, 263, + 269, 271, 277, 281, 283, 293, 307, 311, + 313, 317, 331, 337, 347, 349, 353, 359, + 367, 373, 379, 383, 389, 397, 401, 409, + 419, 421, 431, 433, 439, 443, 449, 457, + 461, 463, 467, 479, 487, 491, 499, 503, + 509, 521, 523, 541, 547, 557, 563, 569, + 571, 577, 587, 593, 599, 601, 607, 613, + 617, 619, 631, 641, 643, 647, 653, 659, + 661, 673, 677, 683, 691, 701, 709, 719, + 727, 733, 739, 743, 751, 757, 761, 769, + 773, 787, 797, 809, 811, 821, 823, 827, + 829, 839, 853, 857, 859, 863, 877, 881, + 883, 887, 907, 911, 919, 929, 937, 941, + 947, 953, 967, 971, 977, 983, 991, 997, + 1009,1013,1019,1021,1031,1033,1039,1049, + 1051,1061,1063,1069,1087,1091,1093,1097, + 1103,1109,1117,1123,1129,1151,1153,1163, + 1171,1181,1187,1193,1201,1213,1217,1223, + 1229,1231,1237,1249,1259,1277,1279,1283, + 1289,1291,1297,1301,1303,1307,1319,1321, + 1327,1361,1367,1373,1381,1399,1409,1423, + 1427,1429,1433,1439,1447,1451,1453,1459, + 1471,1481,1483,1487,1489,1493,1499,1511, + 1523,1531,1543,1549,1553,1559,1567,1571, + 1579,1583,1597,1601,1607,1609,1613,1619, + 1621,1627,1637,1657,1663,1667,1669,1693, + 1697,1699,1709,1721,1723,1733,1741,1747, + 1753,1759,1777,1783,1787,1789,1801,1811, + 1823,1831,1847,1861,1867,1871,1873,1877, + 1879,1889,1901,1907,1913,1931,1933,1949, + 1951,1973,1979,1987,1993,1997,1999,2003, + 2011,2017,2027,2029,2039,2053,2063,2069, + 2081,2083,2087,2089,2099,2111,2113,2129, + 2131,2137,2141,2143,2153,2161,2179,2203, + 2207,2213,2221,2237,2239,2243,2251,2267, + 2269,2273,2281,2287,2293,2297,2309,2311, + 2333,2339,2341,2347,2351,2357,2371,2377, + 2381,2383,2389,2393,2399,2411,2417,2423, + 2437,2441,2447,2459,2467,2473,2477,2503, + 2521,2531,2539,2543,2549,2551,2557,2579, + 2591,2593,2609,2617,2621,2633,2647,2657, + 2659,2663,2671,2677,2683,2687,2689,2693, + 2699,2707,2711,2713,2719,2729,2731,2741, + 2749,2753,2767,2777,2789,2791,2797,2801, + 2803,2819,2833,2837,2843,2851,2857,2861, + 2879,2887,2897,2903,2909,2917,2927,2939, + 2953,2957,2963,2969,2971,2999,3001,3011, + 3019,3023,3037,3041,3049,3061,3067,3079, + 3083,3089,3109,3119,3121,3137,3163,3167, + 3169,3181,3187,3191,3203,3209,3217,3221, + 3229,3251,3253,3257,3259,3271,3299,3301, + 3307,3313,3319,3323,3329,3331,3343,3347, + 3359,3361,3371,3373,3389,3391,3407,3413, + 3433,3449,3457,3461,3463,3467,3469,3491, + 3499,3511,3517,3527,3529,3533,3539,3541, + 3547,3557,3559,3571,3581,3583,3593,3607, + 3613,3617,3623,3631,3637,3643,3659,3671, + 3673,3677,3691,3697,3701,3709,3719,3727, + 3733,3739,3761,3767,3769,3779,3793,3797, + 3803,3821,3823,3833,3847,3851,3853,3863, + 3877,3881,3889,3907,3911,3917,3919,3923, + 3929,3931,3943,3947,3967,3989,4001,4003, + 4007,4013,4019,4021,4027,4049,4051,4057, + 4073,4079,4091,4093,4099,4111,4127,4129, + 4133,4139,4153,4157,4159,4177,4201,4211, + 4217,4219,4229,4231,4241,4243,4253,4259, + 4261,4271,4273,4283,4289,4297,4327,4337, + 4339,4349,4357,4363,4373,4391,4397,4409, + 4421,4423,4441,4447,4451,4457,4463,4481, + 4483,4493,4507,4513,4517,4519,4523,4547, + 4549,4561,4567,4583,4591,4597,4603,4621, + 4637,4639,4643,4649,4651,4657,4663,4673, + 4679,4691,4703,4721,4723,4729,4733,4751, + 4759,4783,4787,4789,4793,4799,4801,4813, + 4817,4831,4861,4871,4877,4889,4903,4909, + 4919,4931,4933,4937,4943,4951,4957,4967, + 4969,4973,4987,4993,4999,5003,5009,5011, + 5021,5023,5039,5051,5059,5077,5081,5087, + 5099,5101,5107,5113,5119,5147,5153,5167, + 5171,5179,5189,5197,5209,5227,5231,5233, + 5237,5261,5273,5279,5281,5297,5303,5309, + 5323,5333,5347,5351,5381,5387,5393,5399, + 5407,5413,5417,5419,5431,5437,5441,5443, + 5449,5471,5477,5479,5483,5501,5503,5507, + 5519,5521,5527,5531,5557,5563,5569,5573, + 5581,5591,5623,5639,5641,5647,5651,5653, + 5657,5659,5669,5683,5689,5693,5701,5711, + 5717,5737,5741,5743,5749,5779,5783,5791, + 5801,5807,5813,5821,5827,5839,5843,5849, + 5851,5857,5861,5867,5869,5879,5881,5897, + 5903,5923,5927,5939,5953,5981,5987,6007, + 6011,6029,6037,6043,6047,6053,6067,6073, + 6079,6089,6091,6101,6113,6121,6131,6133, + 6143,6151,6163,6173,6197,6199,6203,6211, + 6217,6221,6229,6247,6257,6263,6269,6271, + 6277,6287,6299,6301,6311,6317,6323,6329, + 6337,6343,6353,6359,6361,6367,6373,6379, + 6389,6397,6421,6427,6449,6451,6469,6473, + 6481,6491,6521,6529,6547,6551,6553,6563, + 6569,6571,6577,6581,6599,6607,6619,6637, + 6653,6659,6661,6673,6679,6689,6691,6701, + 6703,6709,6719,6733,6737,6761,6763,6779, + 6781,6791,6793,6803,6823,6827,6829,6833, + 6841,6857,6863,6869,6871,6883,6899,6907, + 6911,6917,6947,6949,6959,6961,6967,6971, + 6977,6983,6991,6997,7001,7013,7019,7027, + 7039,7043,7057,7069,7079,7103,7109,7121, + 7127,7129,7151,7159,7177,7187,7193,7207, + 7211,7213,7219,7229,7237,7243,7247,7253, + 7283,7297,7307,7309,7321,7331,7333,7349, + 7351,7369,7393,7411,7417,7433,7451,7457, + 7459,7477,7481,7487,7489,7499,7507,7517, + 7523,7529,7537,7541,7547,7549,7559,7561, + 7573,7577,7583,7589,7591,7603,7607,7621, + 7639,7643,7649,7669,7673,7681,7687,7691, + 7699,7703,7717,7723,7727,7741,7753,7757, + 7759,7789,7793,7817,7823,7829,7841,7853, + 7867,7873,7877,7879,7883,7901,7907,7919, + 7927,7933,7937,7949,7951,7963,7993,8009, + 8011,8017,8039,8053,8059,8069,8081,8087, + 8089,8093,8101,8111,8117,8123,8147,8161, + 8167,8171,8179,8191,8209,8219,8221,8231, + 8233,8237,8243,8263,8269,8273,8287,8291, + 8293,8297,8311,8317,8329,8353,8363,8369, + 8377,8387,8389,8419,8423,8429,8431,8443, + 8447,8461,8467,8501,8513,8521,8527,8537, + 8539,8543,8563,8573,8581,8597,8599,8609, + 8623,8627,8629,8641,8647,8663,8669,8677, + 8681,8689,8693,8699,8707,8713,8719,8731, + 8737,8741,8747,8753,8761,8779,8783,8803, + 8807,8819,8821,8831,8837,8839,8849,8861, + 8863,8867,8887,8893,8923,8929,8933,8941, + 8951,8963,8969,8971,8999,9001,9007,9011, + 9013,9029,9041,9043,9049,9059,9067,9091, + 9103,9109,9127,9133,9137,9151,9157,9161, + 9173,9181,9187,9199,9203,9209,9221,9227, + 9239,9241,9257,9277,9281,9283,9293,9311, + 9319,9323,9337,9341,9343,9349,9371,9377, + 9391,9397,9403,9413,9419,9421,9431,9433, + 9437,9439,9461,9463,9467,9473,9479,9491, + 9497,9511,9521,9533,9539,9547,9551,9587, + 9601,9613,9619,9623,9629,9631,9643,9649, + 9661,9677,9679,9689,9697,9719,9721,9733, + 9739,9743,9749,9767,9769,9781,9787,9791, + 9803,9811,9817,9829,9833,9839,9851,9857, + 9859,9871,9883,9887,9901,9907,9923,9929, + 9931,9941,9949,9967,9973,10007,10009,10037, + 10039,10061,10067,10069,10079,10091,10093,10099, + 10103,10111,10133,10139,10141,10151,10159,10163, + 10169,10177,10181,10193,10211,10223,10243,10247, + 10253,10259,10267,10271,10273,10289,10301,10303, + 10313,10321,10331,10333,10337,10343,10357,10369, + 10391,10399,10427,10429,10433,10453,10457,10459, + 10463,10477,10487,10499,10501,10513,10529,10531, + 10559,10567,10589,10597,10601,10607,10613,10627, + 10631,10639,10651,10657,10663,10667,10687,10691, + 10709,10711,10723,10729,10733,10739,10753,10771, + 10781,10789,10799,10831,10837,10847,10853,10859, + 10861,10867,10883,10889,10891,10903,10909,10937, + 10939,10949,10957,10973,10979,10987,10993,11003, + 11027,11047,11057,11059,11069,11071,11083,11087, + 11093,11113,11117,11119,11131,11149,11159,11161, + 11171,11173,11177,11197,11213,11239,11243,11251, + 11257,11261,11273,11279,11287,11299,11311,11317, + 11321,11329,11351,11353,11369,11383,11393,11399, + 11411,11423,11437,11443,11447,11467,11471,11483, + 11489,11491,11497,11503,11519,11527,11549,11551, + 11579,11587,11593,11597,11617,11621,11633,11657, + 11677,11681,11689,11699,11701,11717,11719,11731, + 11743,11777,11779,11783,11789,11801,11807,11813, + 11821,11827,11831,11833,11839,11863,11867,11887, + 11897,11903,11909,11923,11927,11933,11939,11941, + 11953,11959,11969,11971,11981,11987,12007,12011, + 12037,12041,12043,12049,12071,12073,12097,12101, + 12107,12109,12113,12119,12143,12149,12157,12161, + 12163,12197,12203,12211,12227,12239,12241,12251, + 12253,12263,12269,12277,12281,12289,12301,12323, + 12329,12343,12347,12373,12377,12379,12391,12401, + 12409,12413,12421,12433,12437,12451,12457,12473, + 12479,12487,12491,12497,12503,12511,12517,12527, + 12539,12541,12547,12553,12569,12577,12583,12589, + 12601,12611,12613,12619,12637,12641,12647,12653, + 12659,12671,12689,12697,12703,12713,12721,12739, + 12743,12757,12763,12781,12791,12799,12809,12821, + 12823,12829,12841,12853,12889,12893,12899,12907, + 12911,12917,12919,12923,12941,12953,12959,12967, + 12973,12979,12983,13001,13003,13007,13009,13033, + 13037,13043,13049,13063,13093,13099,13103,13109, + 13121,13127,13147,13151,13159,13163,13171,13177, + 13183,13187,13217,13219,13229,13241,13249,13259, + 13267,13291,13297,13309,13313,13327,13331,13337, + 13339,13367,13381,13397,13399,13411,13417,13421, + 13441,13451,13457,13463,13469,13477,13487,13499, + 13513,13523,13537,13553,13567,13577,13591,13597, + 13613,13619,13627,13633,13649,13669,13679,13681, + 13687,13691,13693,13697,13709,13711,13721,13723, + 13729,13751,13757,13759,13763,13781,13789,13799, + 13807,13829,13831,13841,13859,13873,13877,13879, + 13883,13901,13903,13907,13913,13921,13931,13933, + 13963,13967,13997,13999,14009,14011,14029,14033, + 14051,14057,14071,14081,14083,14087,14107,14143, + 14149,14153,14159,14173,14177,14197,14207,14221, + 14243,14249,14251,14281,14293,14303,14321,14323, + 14327,14341,14347,14369,14387,14389,14401,14407, + 14411,14419,14423,14431,14437,14447,14449,14461, + 14479,14489,14503,14519,14533,14537,14543,14549, + 14551,14557,14561,14563,14591,14593,14621,14627, + 14629,14633,14639,14653,14657,14669,14683,14699, + 14713,14717,14723,14731,14737,14741,14747,14753, + 14759,14767,14771,14779,14783,14797,14813,14821, + 14827,14831,14843,14851,14867,14869,14879,14887, + 14891,14897,14923,14929,14939,14947,14951,14957, + 14969,14983,15013,15017,15031,15053,15061,15073, + 15077,15083,15091,15101,15107,15121,15131,15137, + 15139,15149,15161,15173,15187,15193,15199,15217, + 15227,15233,15241,15259,15263,15269,15271,15277, + 15287,15289,15299,15307,15313,15319,15329,15331, + 15349,15359,15361,15373,15377,15383,15391,15401, + 15413,15427,15439,15443,15451,15461,15467,15473, + 15493,15497,15511,15527,15541,15551,15559,15569, + 15581,15583,15601,15607,15619,15629,15641,15643, + 15647,15649,15661,15667,15671,15679,15683,15727, + 15731,15733,15737,15739,15749,15761,15767,15773, + 15787,15791,15797,15803,15809,15817,15823,15859, + 15877,15881,15887,15889,15901,15907,15913,15919, + 15923,15937,15959,15971,15973,15991,16001,16007, + 16033,16057,16061,16063,16067,16069,16073,16087, + 16091,16097,16103,16111,16127,16139,16141,16183, + 16187,16189,16193,16217,16223,16229,16231,16249, + 16253,16267,16273,16301,16319,16333,16339,16349, + 16361,16363,16369,16381,16411,16417,16421,16427, + 16433,16447,16451,16453,16477,16481,16487,16493, + 16519,16529,16547,16553,16561,16567,16573,16603, + 16607,16619,16631,16633,16649,16651,16657,16661, + 16673,16691,16693,16699,16703,16729,16741,16747, + 16759,16763,16787,16811,16823,16829,16831,16843, + 16871,16879,16883,16889,16901,16903,16921,16927, + 16931,16937,16943,16963,16979,16981,16987,16993, + 17011,17021,17027,17029,17033,17041,17047,17053, + 17077,17093,17099,17107,17117,17123,17137,17159, + 17167,17183,17189,17191,17203,17207,17209,17231, + 17239,17257,17291,17293,17299,17317,17321,17327, + 17333,17341,17351,17359,17377,17383,17387,17389, + 17393,17401,17417,17419,17431,17443,17449,17467, + 17471,17477,17483,17489,17491,17497,17509,17519, + 17539,17551,17569,17573,17579,17581,17597,17599, + 17609,17623,17627,17657,17659,17669,17681,17683, + 17707,17713,17729,17737,17747,17749,17761,17783, + 17789,17791,17807,17827,17837,17839,17851,17863 +}; + +static +Ipp32u cpMod32(const Ipp32u* pX, cpSize sizeX, Ipp32u divider) +{ + cpSize n; + Ipp32u r; + for(n=sizeX, r=0; n>0; n--) { + Ipp64u tmp = MAKEDWORD(pX[n-1],r); + r = (Ipp32u)(tmp%divider); + } + return r; +} + +int cpMimimalPrimeTest(const Ipp32u* pPrime, cpSize len32) +{ + cpSize i; + + FIX_BNU(pPrime, len32); + + /* take a look in the list */ + if(1==len32) { + for(i=0; i<(cpSize)(sizeof(PrimeList)/sizeof(Ipp32u)); i++) { + if(pPrime[0]==PrimeList[i]) + return 1; + } + } + + /* test if value under the test is divisible by first prime numbers 2,3,5, ... */ + for(i=0; i<(cpSize)(sizeof(PrimeList)/sizeof(Ipp32u)); i++) { + if(0 == cpMod32(pPrime, len32, PrimeList[i])) + return 0; + } + + return 1; +} + +/* Rabin-Miller test */ +static +int RabinMiller(int a, + BNU_CHUNK_T* pZ, + BNU_CHUNK_T* pR, cpSize nsR, + BNU_CHUNK_T* pM, cpSize nsM, + IppsMontState* pMont) +{ + /* modulus and it length and other parameters */ + const BNU_CHUNK_T* pModulus = MNT_MODULUS(pMont); + cpSize modLen = MNT_SIZE(pMont); + BNU_CHUNK_T m0 = MNT_HELPER(pMont); + BNU_CHUNK_T* pProduct = MNT_PRODUCT(pMont); + BNU_CHUNK_T* pKBuffer = MNT_KBUFFER(pMont); + + /* compute z = r^m mod prime */ + nsR = cpMontEnc_BNU(pR, pR, nsR, pMont); + cpMontExpBin_BNU(pZ, pR, nsR, pM, nsM, pMont); + + /* if z==1 => probably prime */ + if(0==cpCmp_BNU(pZ, modLen, MNT_1(pMont), modLen)) + return 1; + + /* if z==prime-1 => probably prime */ + cpSub_BNU(MNT_PRODUCT(pMont), pModulus, MNT_1(pMont), modLen); + if(0==cpCmp_BNU(pZ, modLen, MNT_PRODUCT(pMont), modLen)) + return 1; + + while(--a) { + + /* z = z^2 mod w */ + cpMontSqr_BNU(pZ, pZ, modLen, pModulus, modLen, m0, pProduct, pKBuffer); + + /* if z==1 => definitely composite */ + if(0==cpCmp_BNU(pZ, modLen, MNT_1(pMont), modLen)) + return 1; + + /* if z==w-1 => probably prime */ + cpSub_BNU(MNT_PRODUCT(pMont), pModulus, MNT_1(pMont), modLen); + if(0==cpCmp_BNU(pZ, modLen, MNT_PRODUCT(pMont), modLen)) + return 1; + } + + /* if we are here, then we deal with composize */ + return 0; +} + +int cpPrimeTest(const BNU_CHUNK_T* pPrime, cpSize primeLen, + cpSize nTrials, + IppsPrimeState* pCtx, + IppBitSupplier rndFunc, void* pRndParam) +{ + FIX_BNU(pPrime, primeLen); + + /* 0 is composite number */ + if( primeLen==1 && pPrime[0]==0) + return 0; + + /* 2 is prime number */ + else if( primeLen==1 && pPrime[0]==2) + return 1; + + /* + // test number + */ + else { + cpSize primeBitsize = BITSIZE_BNU(pPrime, primeLen); + cpSize primeLen32 = BITS2WORD32_SIZE(primeBitsize); + + /* apply easy prime test */ + if( 0==cpMimimalPrimeTest((Ipp32u*)pPrime, primeLen32) ) + return 0; + + /* continue test */ + else { + cpSize n, a; + + IppsMontState* pMont = PRIME_MONT(pCtx); + BNU_CHUNK_T* pMdata = PRIME_TEMP1(pCtx); + BNU_CHUNK_T* pRdata = PRIME_TEMP2(pCtx); + BNU_CHUNK_T* pZdata = PRIME_TEMP3(pCtx); + cpSize lenM, lenR; + + /* set up Montgomery engine (and save value being under the test) */ + ippsMontSet((Ipp32u*)pPrime, primeLen32, pMont); + + /* express w = m*2^a + 1 */ + cpDec_BNU(pMdata, pPrime, primeLen, 1); + for(n=0,a=0; n=1 */ + if(!cpTst_BNU(pRdata, lenR)) + pRdata[0] |= 1; + FIX_BNU(pRdata, lenR); + + /* Rabin-Miller test */ + if(0==RabinMiller(a, pZdata, pRdata,lenR, pMdata,lenM, pMont)) + return 0; + } + + return 1; + } + } +} diff --git a/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpprimeginitca.c b/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpprimeginitca.c new file mode 100644 index 0000000000..2a8af24616 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpprimeginitca.c @@ -0,0 +1,124 @@ +/* +* Copyright (C) 2016 Intel Corporation. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in +* the documentation and/or other materials provided with the +* distribution. +* * Neither the name of Intel Corporation nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ + +#include "owncp.h" +#include "pcpprimeg.h" +#include "pcptool.h" + + +/*F* +// Name: ippsPrimeGetSize +// +// Purpose: Returns size of Prime Number Generator context (bytes). +// +// Returns: Reason: +// ippStsNullPtrErr NULL == pSize +// ippStsLengthErr 1 > maxBits +// ippStsNoErr no error +// +// Parameters: +// maxBits max length of a prime number +// pSize pointer to the size of internal context +*F*/ +IPPFUN(IppStatus, ippsPrimeGetSize, (cpSize maxBits, cpSize* pSize)) +{ + IPP_BAD_PTR1_RET(pSize); + IPP_BADARG_RET(maxBits<1, ippStsLengthErr); + + { + cpSize len = BITS_BNU_CHUNK(maxBits); + cpSize len32 = BITS2WORD32_SIZE(maxBits); + cpSize montSize; + ippsMontGetSize(ippBinaryMethod, len32, &montSize); + + *pSize = sizeof(IppsPrimeState) + +len*sizeof(BNU_CHUNK_T) + +len*sizeof(BNU_CHUNK_T) + +len*sizeof(BNU_CHUNK_T) + +len*sizeof(BNU_CHUNK_T) + +montSize + +PRIME_ALIGNMENT-1; + + return ippStsNoErr; + } +} + + +/*F* +// Name: ippsPrimeInit +// +// Purpose: Initializes Prime Number Generator context +// +// Returns: Reason: +// ippStsNullPtrErr NULL == pCtx +// ippStsLengthErr 1 > maxBits +// ippStsNoErr no error +// +// Parameters: +// maxBits max length of a prime number +// pCtx pointer to the context to be initialized +*F*/ +IPPFUN(IppStatus, ippsPrimeInit, (cpSize maxBits, IppsPrimeState* pCtx)) +{ + IPP_BAD_PTR1_RET(pCtx); + IPP_BADARG_RET(maxBits<1, ippStsLengthErr); + + /* use aligned PRNG context */ + pCtx = (IppsPrimeState*)( IPP_ALIGNED_PTR(pCtx, PRIME_ALIGNMENT) ); + + { + Ipp8u* ptr = (Ipp8u*)pCtx; + + cpSize len = BITS_BNU_CHUNK(maxBits); + cpSize len32 = BITS2WORD32_SIZE(maxBits); + + PRIME_ID(pCtx) = idCtxPrimeNumber; + PRIME_MAXBITSIZE(pCtx) = maxBits; + + ptr += sizeof(IppsPrimeState); + PRIME_NUMBER(pCtx) = (BNU_CHUNK_T*)ptr; + + ptr += len*sizeof(BNU_CHUNK_T); + PRIME_TEMP1(pCtx) = (BNU_CHUNK_T*)ptr; + + ptr += len*sizeof(BNU_CHUNK_T); + PRIME_TEMP2(pCtx) = (BNU_CHUNK_T*)ptr; + + ptr += len*sizeof(BNU_CHUNK_T); + PRIME_TEMP3(pCtx) = (BNU_CHUNK_T*)ptr; + + ptr += len*sizeof(BNU_CHUNK_T); + PRIME_MONT(pCtx) = (IppsMontState*)( IPP_ALIGNED_PTR((ptr), MONT_ALIGNMENT) ); + ippsMontInit(ippBinaryMethod, len32, PRIME_MONT(pCtx)); + + return ippStsNoErr; + } +} diff --git a/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpprng.h b/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpprng.h new file mode 100644 index 0000000000..2c0201df48 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpprng.h @@ -0,0 +1,65 @@ +/* +* Copyright (C) 2016 Intel Corporation. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in +* the documentation and/or other materials provided with the +* distribution. +* * Neither the name of Intel Corporation nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ + +#if !defined(_CP_PRNG_H) +#define _CP_PRNG_H + +/* +// Pseudo-random generation context +*/ + +#define MAX_XKEY_SIZE 512 +#define DEFAULT_XKEY_SIZE 512 /* must be >=160 || <=512 */ + +struct _cpPRNG { + IppCtxId idCtx; /* PRNG identifier */ + cpSize seedBits; /* secret seed-key bitsize */ + BNU_CHUNK_T Q[BITS_BNU_CHUNK(160)]; /* modulus */ + BNU_CHUNK_T T[BITS_BNU_CHUNK(160)]; /* parameter of SHA_G() funct */ + BNU_CHUNK_T xAug[BITS_BNU_CHUNK(MAX_XKEY_SIZE)]; /* optional entropy augment */ + BNU_CHUNK_T xKey[BITS_BNU_CHUNK(MAX_XKEY_SIZE)]; /* secret seed-key */ +}; + +/* alignment */ +#define PRNG_ALIGNMENT ((int)(sizeof(void*))) + +#define RAND_ID(ctx) ((ctx)->idCtx) +#define RAND_SEEDBITS(ctx) ((ctx)->seedBits) +#define RAND_Q(ctx) ((ctx)->Q) +#define RAND_T(ctx) ((ctx)->T) +#define RAND_XAUGMENT(ctx) ((ctx)->xAug) +#define RAND_XKEY(ctx) ((ctx)->xKey) + +#define RAND_VALID_ID(ctx) (RAND_ID((ctx))==idCtxPRNG) + +int cpPRNGen(Ipp32u* pBuffer, cpSize bitLen, IppsPRNGState* pCtx); + +#endif /* _CP_PRNG_H */ diff --git a/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpprngenca.c b/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpprngenca.c new file mode 100644 index 0000000000..066c3caa54 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpprngenca.c @@ -0,0 +1,178 @@ +/* +* Copyright (C) 2016 Intel Corporation. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in +* the documentation and/or other materials provided with the +* distribution. +* * Neither the name of Intel Corporation nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ + +#include "owndefs.h" + +#include "owncp.h" +#include "pcpbn.h" +#include "pcphash.h" +#include "pcpprng.h" +#include "pcptool.h" + +/* +// G() function based on SHA1 +// +// Parameters: +// T 160 bit parameter +// pHexStr input hex string +// hexStrLen size of hex string (Ipp8u segnments) +// xBNU 160 bit BNU result +// +// Note 1: +// must to be hexStrLen <= 64 (512 bits) +*/ +static +void SHA1_G(Ipp32u* xBNU, const Ipp32u* T, Ipp8u* pHexStr, int hexStrLen) +{ + /* select processing function */ + cpHashProc updateFunc = UpdateSHA1; + + /* pad HexString zeros */ + PaddBlock(0, pHexStr+hexStrLen, BITS2WORD8_SIZE(MAX_XKEY_SIZE)-hexStrLen); + + /* reset initial HASH value */ + xBNU[0] = T[0]; + xBNU[1] = T[1]; + xBNU[2] = T[2]; + xBNU[3] = T[3]; + xBNU[4] = T[4]; + + /* SHA1 */ + //UpdateSHA1(xBNU, pHexStr, BITS2WORD8_SIZE(MAX_XKEY_SIZE), SHA1_cnt); + updateFunc(xBNU, pHexStr, BITS2WORD8_SIZE(MAX_XKEY_SIZE), SHA1_cnt); + + /* swap back */ + SWAP(xBNU[0],xBNU[4]); + SWAP(xBNU[1],xBNU[3]); +} + +/* +// Returns bitsize of the bitstring has beed added +*/ +int cpPRNGen(Ipp32u* pRand, cpSize nBits, IppsPRNGState* pRnd) +{ + BNU_CHUNK_T Xj [BITS_BNU_CHUNK(MAX_XKEY_SIZE)]; + BNU_CHUNK_T XVAL[BITS_BNU_CHUNK(MAX_XKEY_SIZE)]; + + Ipp8u TXVAL[BITS2WORD8_SIZE(MAX_XKEY_SIZE)]; + + /* XKEY length in BNU_CHUNK_T */ + cpSize xKeyLen = BITS_BNU_CHUNK(RAND_SEEDBITS(pRnd)); + /* XKEY length in bytes */ + cpSize xKeySize= BITS2WORD8_SIZE(RAND_SEEDBITS(pRnd)); + /* XKEY word's mask */ + BNU_CHUNK_T xKeyMsk = MASK_BNU_CHUNK(RAND_SEEDBITS(pRnd)); + + /* number of Ipp32u chunks to be generated */ + cpSize genlen = BITS2WORD32_SIZE(nBits); + + ZEXPAND_BNU(Xj, 0, BITS_BNU_CHUNK(MAX_XKEY_SIZE)); + ZEXPAND_BNU(XVAL, 0, BITS_BNU_CHUNK(MAX_XKEY_SIZE)); + + while(genlen) { + cpSize len; + + /* Step 1: XVAL=(Xkey+Xseed) mod 2^b */ + BNU_CHUNK_T carry = cpAdd_BNU(XVAL, RAND_XKEY(pRnd), RAND_XAUGMENT(pRnd), xKeyLen); + XVAL[xKeyLen-1] &= xKeyMsk; + + /* Step 2: xj=G(t, XVAL) mod Q */ + cpToOctStr_BNU(TXVAL, xKeySize, XVAL, xKeyLen); + SHA1_G((Ipp32u*)Xj, (Ipp32u*)RAND_T(pRnd), TXVAL, xKeySize); + + { + cpSize sizeXj = BITS_BNU_CHUNK(160); + if(0 <= cpCmp_BNU(Xj, BITS_BNU_CHUNK(IPP_SHA1_DIGEST_BITSIZE), RAND_Q(pRnd),BITS_BNU_CHUNK(IPP_SHA1_DIGEST_BITSIZE)) ) + sizeXj = cpMod_BNU(Xj, BITS_BNU_CHUNK(IPP_SHA1_DIGEST_BITSIZE), RAND_Q(pRnd), BITS_BNU_CHUNK(IPP_SHA1_DIGEST_BITSIZE)); + FIX_BNU(Xj, sizeXj); + ZEXPAND_BNU(Xj, sizeXj, BITS_BNU_CHUNK(MAX_XKEY_SIZE)); + } + + /* Step 3: Xkey=(1+Xkey+Xj) mod 2^b */ + cpInc_BNU(RAND_XKEY(pRnd), RAND_XKEY(pRnd), xKeyLen, 1); + carry = cpAdd_BNU(RAND_XKEY(pRnd), RAND_XKEY(pRnd), Xj, xKeyLen); + RAND_XKEY(pRnd)[xKeyLen-1] &= xKeyMsk; + + /* fill out result */ + len = genlenidCtx +// +// ippStsLengthErr 1 > nBits +// +// ippStsNoErr no error +// +// Parameters: +// pBuffer pointer to the buffer +// nBits number of bits be requested +// pRndCtx pointer to the context +*F*/ +IPPFUN(IppStatus, ippsPRNGen,(Ipp32u* pBuffer, cpSize nBits, void* pRnd)) +{ + IppsPRNGState* pRndCtx = (IppsPRNGState*)pRnd; + + /* test PRNG context */ + IPP_BAD_PTR2_RET(pBuffer, pRnd); + + pRndCtx = (IppsPRNGState*)( IPP_ALIGNED_PTR(pRndCtx, PRNG_ALIGNMENT) ); + IPP_BADARG_RET(!RAND_VALID_ID(pRndCtx), ippStsContextMatchErr); + + /* test sizes */ + IPP_BADARG_RET(nBits< 1, ippStsLengthErr); + + { + cpSize rndSize = BITS2WORD32_SIZE(nBits); + Ipp32u rndMask = MAKEMASK32(nBits); + + cpPRNGen(pBuffer, nBits, pRndCtx); + pBuffer[rndSize-1] &= rndMask; + + return ippStsNoErr; + } +} diff --git a/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpprnginitca.c b/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpprnginitca.c new file mode 100644 index 0000000000..9f42b23ff8 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpprnginitca.c @@ -0,0 +1,113 @@ +/* +* Copyright (C) 2016 Intel Corporation. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in +* the documentation and/or other materials provided with the +* distribution. +* * Neither the name of Intel Corporation nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ + +#include "owndefs.h" + +#include "owncp.h" +#include "pcpbn.h" +#include "pcpprng.h" +#include "pcphash.h" +#include "pcptool.h" + + +/*F* +// Name: ippsPRNGGetSize +// +// Purpose: Returns size of PRNG context (bytes). +// +// Returns: Reason: +// ippStsNullPtrErr NULL == pSize +// +// ippStsNoErr no error +// +// Parameters: +// pSize pointer to the size of internal context +*F*/ +IPPFUN(IppStatus, ippsPRNGGetSize, (int* pSize)) +{ + IPP_BAD_PTR1_RET(pSize); + + *pSize = sizeof(IppsPRNGState) + +PRNG_ALIGNMENT-1; + return ippStsNoErr; +} + + +/*F* +// Name: ippsPRNGInit +// +// Purpose: Initializes PRNG context +// +// Returns: Reason: +// ippStsNullPtrErr NULL == pRnd +// +// ippStsLengthErr seedBits < 1 +// seedBits < MAX_XKEY_SIZE +// seedBits%8 !=0 +// +// ippStsNoErr no error +// +// Parameters: +// seedBits seed bitsize +// pRnd pointer to the context to be initialized +*F*/ +IPPFUN(IppStatus, ippsPRNGInit, (int seedBits, IppsPRNGState* pRnd)) +{ + /* test PRNG context */ + IPP_BAD_PTR1_RET(pRnd); + pRnd = (IppsPRNGState*)( IPP_ALIGNED_PTR(pRnd, PRNG_ALIGNMENT) ); + + /* test sizes */ + IPP_BADARG_RET((1>seedBits) || (seedBits>MAX_XKEY_SIZE) ||(seedBits&7), ippStsLengthErr); + + { + int hashIvSize = cpHashIvSize(ippHashAlg_SHA1); + const Ipp8u* iv = cpHashIV[ippHashAlg_SHA1]; + + /* cleanup context */ + ZEXPAND_BNU((Ipp8u*)pRnd, 0, (cpSize)(sizeof(IppsPRNGState))); + + RAND_ID(pRnd) = idCtxPRNG; + RAND_SEEDBITS(pRnd) = seedBits; + + /* default Q parameter */ + ((Ipp32u*)RAND_Q(pRnd))[0] = 0xFFFFFFFF; + ((Ipp32u*)RAND_Q(pRnd))[1] = 0xFFFFFFFF; + ((Ipp32u*)RAND_Q(pRnd))[2] = 0xFFFFFFFF; + ((Ipp32u*)RAND_Q(pRnd))[3] = 0xFFFFFFFF; + ((Ipp32u*)RAND_Q(pRnd))[4] = 0xFFFFFFFF; + + /* default T parameter */ + CopyBlock(iv, RAND_T(pRnd), hashIvSize); + + return ippStsNoErr; + } +} diff --git a/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcprij.h b/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcprij.h new file mode 100644 index 0000000000..f2e59a558d --- /dev/null +++ b/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcprij.h @@ -0,0 +1,141 @@ +/* +* Copyright (C) 2016 Intel Corporation. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in +* the documentation and/or other materials provided with the +* distribution. +* * Neither the name of Intel Corporation nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ + +#if !defined(_PCP_RIJ_H) +#define _PCP_RIJ_H + + +/* +// The GF(256) modular polynomial and elements +*/ +#define WPOLY 0x011B +#define BPOLY 0x1B + +/* +// Make WORD using 4 arbitrary bytes +*/ +#define BYTES_TO_WORD(b0,b1,b2,b3) ( ( ((Ipp32u)((Ipp8u)(b3))) <<24 ) \ + |( ((Ipp32u)((Ipp8u)(b2))) <<16 ) \ + |( ((Ipp32u)((Ipp8u)(b1))) << 8 ) \ + |( ((Ipp32u)((Ipp8u)(b0))) ) ) +/* +// Make WORD setting byte in specified position +*/ +#define BYTE0_TO_WORD(b) BYTES_TO_WORD((b), 0, 0, 0) +#define BYTE1_TO_WORD(b) BYTES_TO_WORD( 0, (b), 0, 0) +#define BYTE2_TO_WORD(b) BYTES_TO_WORD( 0, 0, (b), 0) +#define BYTE3_TO_WORD(b) BYTES_TO_WORD( 0, 0, 0, (b)) + +/* +// Extract byte from specified position n. +// Sure, n=0,1,2 or 3 only +*/ +#define EBYTE(w,n) ((Ipp8u)((w) >> (8 * (n)))) + + +/* +// Rijndael's spec +*/ +typedef void (*RijnCipher)(const Ipp8u* pInpBlk, Ipp8u* pOutBlk, int nr, const Ipp8u* pKeys, const void* pTbl); + +struct _cpRijndael128 { + IppCtxId idCtx; /* Rijndael spec identifier */ + int nk; /* security key length (words) */ + int nb; /* data block size (words) */ + int nr; /* number of rounds */ + RijnCipher encoder; /* encoder/decoder */ + RijnCipher decoder; /* entry point */ + Ipp32u* pEncTbl; /* expanded S-boxes for */ + Ipp32u* pDecTbl; /* encryption and decryption */ + Ipp32u enc_keys[64]; /* array of keys for encryprion */ + Ipp32u dec_keys[64]; /* array of keys for decryprion */ + Ipp32u aesNI; /* AES instruction available */ + Ipp32u safeInit; /* SafeInit performed */ +}; + +/* alignment */ +#define RIJ_ALIGNMENT (16) + +#define MBS_RIJ128 (128/8) /* message block size (bytes) */ +#define MBS_RIJ192 (192/8) +#define MBS_RIJ256 (256/8) + +#define SR (4) /* number of rows in STATE data */ + +#define NB(msgBlks) ((msgBlks)/32) /* message block size (words) */ + /* 4-word for 128-bits data block */ + /* 6-word for 192-bits data block */ + /* 8-word for 256-bits data block */ + +#define NK(keybits) ((keybits)/32) /* key length (words): */ +#define NK128 NK(ippRijndaelKey128)/* 4-word for 128-bits security key */ +#define NK192 NK(ippRijndaelKey192)/* 6-word for 192-bits security key */ +#define NK256 NK(ippRijndaelKey256)/* 8-word for 256-bits security key */ + +#define NR128_128 (10) /* number of rounds data: 128 bits key: 128 bits are used */ +#define NR128_192 (12) /* number of rounds data: 128 bits key: 192 bits are used */ +#define NR128_256 (14) /* number of rounds data: 128 bits key: 256 bits are used */ +#define NR192_128 (12) /* number of rounds data: 192 bits key: 128 bits are used */ +#define NR192_192 (12) /* number of rounds data: 192 bits key: 192 bits are used */ +#define NR192_256 (14) /* number of rounds data: 192 bits key: 256 bits are used */ +#define NR256_128 (14) /* number of rounds data: 256 bits key: 128 bits are used */ +#define NR256_192 (14) /* number of rounds data: 256 bits key: 192 bits are used */ +#define NR256_256 (14) /* number of rounds data: 256 bits key: 256 bits are used */ + +/* +// Useful macros +*/ +#define RIJ_ID(ctx) ((ctx)->idCtx) +#define RIJ_NB(ctx) ((ctx)->nb) +#define RIJ_NK(ctx) ((ctx)->nk) +#define RIJ_NR(ctx) ((ctx)->nr) +#define RIJ_ENCODER(ctx) ((ctx)->encoder) +#define RIJ_DECODER(ctx) ((ctx)->decoder) +#define RIJ_ENC_SBOX(ctx) ((ctx)->pEncTbl) +#define RIJ_DEC_SBOX(ctx) ((ctx)->pDecTbl) +#define RIJ_EKEYS(ctx) (Ipp8u*)((ctx)->enc_keys) +#define RIJ_DKEYS(ctx) (Ipp8u*)((ctx)->dec_keys) +#define RIJ_AESNI(ctx) ((ctx)->aesNI) +#define RIJ_SAFE_INIT(ctx) ((ctx)->safeInit) + +#define RIJ_ID_TEST(ctx) (RIJ_ID((ctx))==idCtxRijndael) + +/* +// Internal functions +*/ + +void Safe2Encrypt_RIJ128(const Ipp8u* pInpBlk, Ipp8u* pOutBlk, int nr, const Ipp8u* pKeys, const void* pTbl); +void Safe2Decrypt_RIJ128(const Ipp8u* pInpBlk, Ipp8u* pOutBlk, int nr, const Ipp8u* pKeys, const void* pTbl); + +void ExpandRijndaelKey(const Ipp8u* pKey, int NK, int NB, int NR, int nKeys, + Ipp8u* pEncKeys, Ipp8u* pDecKeys); + +#endif /* _PCP_RIJ_H */ diff --git a/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcprij128safe2.h b/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcprij128safe2.h new file mode 100644 index 0000000000..c407edd470 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcprij128safe2.h @@ -0,0 +1,79 @@ +/* +* Copyright (C) 2016 Intel Corporation. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in +* the documentation and/or other materials provided with the +* distribution. +* * Neither the name of Intel Corporation nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ + +#if !defined(_PCP_RIJ_SAFE2_H) +#define _PCP_RIJ_SAFE2_H + +// transpose 4x4 Ipp8u matrix +#define TRANSPOSE(out, inp) \ + (out)[ 0] = (inp)[ 0]; \ + (out)[ 4] = (inp)[ 1]; \ + (out)[ 8] = (inp)[ 2]; \ + (out)[12] = (inp)[ 3]; \ + \ + (out)[ 1] = (inp)[ 4]; \ + (out)[ 5] = (inp)[ 5]; \ + (out)[ 9] = (inp)[ 6]; \ + (out)[13] = (inp)[ 7]; \ + \ + (out)[ 2] = (inp)[ 8]; \ + (out)[ 6] = (inp)[ 9]; \ + (out)[10] = (inp)[10]; \ + (out)[14] = (inp)[11]; \ + \ + (out)[ 3] = (inp)[12]; \ + (out)[ 7] = (inp)[13]; \ + (out)[11] = (inp)[14]; \ + (out)[15] = (inp)[15] + +__INLINE void XorRoundKey(Ipp32u* state, const Ipp32u* RoundKey) +{ + state[0] ^= RoundKey[0]; + state[1] ^= RoundKey[1]; + state[2] ^= RoundKey[2]; + state[3] ^= RoundKey[3]; +} + +// xtime is a macro that finds the product of {02} and the argument to xtime modulo {1b} +__INLINE Ipp32u mask4(Ipp32u x) +{ + x &= 0x80808080; + return (Ipp32u)((x<<1) - (x>>7)); +} + +__INLINE Ipp32u xtime4(Ipp32u x) +{ + Ipp32u t = (x+x) &0xFEFEFEFE; + t ^= mask4(x) & 0x1B1B1B1B; + return t; +} + +#endif /* _PCP_RIJ_SAFE2_H */ diff --git a/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcprij128safedec2pxca.c b/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcprij128safedec2pxca.c new file mode 100644 index 0000000000..8dbbb21ae4 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcprij128safedec2pxca.c @@ -0,0 +1,133 @@ +/* +* Copyright (C) 2016 Intel Corporation. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in +* the documentation and/or other materials provided with the +* distribution. +* * Neither the name of Intel Corporation nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ + +#include "owndefs.h" +#include "owncp.h" + +#include "pcprij128safe2.h" +#include "pcprijtables.h" + + +__INLINE Ipp8u getInvSboxValue(Ipp32u x) +{ + Ipp32u t[sizeof(RijDecSbox)/CACHE_LINE_SIZE]; + const Ipp8u* SboxEntry = RijDecSbox +x%CACHE_LINE_SIZE; + Ipp32u i; + for(i=0; i0;round--) { + invShiftRows(state); + invSubBytes((Ipp8u*)state); + XorRoundKey(state,(Ipp32u*)(RoundKey+round*16)); + invMixColumns(state); + } + + // last round + invShiftRows(state); + invSubBytes((Ipp8u*)state); + XorRoundKey(state,(Ipp32u*)(RoundKey+0*16)); + + // copy from the state to output + TRANSPOSE(out, (Ipp8u*)state); +} diff --git a/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcprij128safeenc2pxca.c b/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcprij128safeenc2pxca.c new file mode 100644 index 0000000000..c59006df7b --- /dev/null +++ b/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcprij128safeenc2pxca.c @@ -0,0 +1,125 @@ +/* +* Copyright (C) 2016 Intel Corporation. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in +* the documentation and/or other materials provided with the +* distribution. +* * Neither the name of Intel Corporation nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ + +#include "owndefs.h" +#include "owncp.h" + +#include "pcprij128safe2.h" +#include "pcprijtables.h" + + +__INLINE Ipp8u getSboxValue(Ipp32u x) +{ + Ipp32u t[sizeof(RijEncSbox)/CACHE_LINE_SIZE]; + const Ipp8u* SboxEntry = RijEncSbox +x%CACHE_LINE_SIZE; + Ipp32u i; + for(i=0; i>7) & 1) * WPOLY)) +#define gf_m4(x) ((x<<2) ^ (((x>>6) & 1) * WPOLY) ^ (((x>>6) & 2) * WPOLY)) +#define gf_m8(x) ((x<<3) ^ (((x>>5) & 1) * WPOLY) ^ (((x>>5) & 2) * WPOLY) \ + ^ (((x>>5) & 4) * WPOLY)) +#define gf_m1(x) ((x)) +#define gf_m3(x) (gf_m2(x) ^ x) +#define gf_m9(x) (gf_m8(x) ^ x) +#define gf_mB(x) (gf_m8(x) ^ gf_m2(x) ^ x) +#define gf_mD(x) (gf_m8(x) ^ gf_m4(x) ^ x) +#define gf_mE(x) (gf_m8(x) ^ gf_m4(x) ^ gf_m2(x)) + +/* +// The following particular transformations +// are used for create Encryption Tables +*/ +#define fwd_t0(x) BYTES_TO_WORD(gf_m2(x), gf_m1(x), gf_m1(x), gf_m3(x)) +#define fwd_t1(x) BYTES_TO_WORD(gf_m3(x), gf_m2(x), gf_m1(x), gf_m1(x)) +#define fwd_t2(x) BYTES_TO_WORD(gf_m1(x), gf_m3(x), gf_m2(x), gf_m1(x)) +#define fwd_t3(x) BYTES_TO_WORD(gf_m1(x), gf_m1(x), gf_m3(x), gf_m2(x)) + +/* +// The following particular transformations +// are used for create Decryption Tables +*/ +#define inv_t0(x) BYTES_TO_WORD(gf_mE(x), gf_m9(x), gf_mD(x), gf_mB(x)) +#define inv_t1(x) BYTES_TO_WORD(gf_mB(x), gf_mE(x), gf_m9(x), gf_mD(x)) +#define inv_t2(x) BYTES_TO_WORD(gf_mD(x), gf_mB(x), gf_mE(x), gf_m9(x)) +#define inv_t3(x) BYTES_TO_WORD(gf_m9(x), gf_mD(x), gf_mB(x), gf_mE(x)) + +#define exp_b3(x) BYTES_TO_WORD(0, 0, 0, (x)) +#define exp_b2(x) BYTES_TO_WORD(0, 0, (x),0) +#define exp_b1(x) BYTES_TO_WORD(0, (x),0, 0) +#define exp_b0(x) BYTES_TO_WORD((x),0, 0, 0) + +/* +// The following particular transformations +// are used for create pure Encryption/Decryption Sboxes +*/ +#define none_t(x) (x) + + +/* +// Just sequence of byte, beginning 0x00 upto 0xff +// (be parametrized by any transformation 't') +*/ +#define LINE(t) \ + t(0x00), t(0x01), t(0x02), t(0x03), t(0x04), t(0x05), t(0x06), t(0x07),\ + t(0x08), t(0x09), t(0x0a), t(0x0b), t(0x0c), t(0x0d), t(0x0e), t(0x0f),\ + t(0x10), t(0x11), t(0x12), t(0x13), t(0x14), t(0x15), t(0x16), t(0x17),\ + t(0x18), t(0x19), t(0x1a), t(0x1b), t(0x1c), t(0x1d), t(0x1e), t(0x1f),\ + t(0x20), t(0x21), t(0x22), t(0x23), t(0x24), t(0x25), t(0x26), t(0x27),\ + t(0x28), t(0x29), t(0x2a), t(0x2b), t(0x2c), t(0x2d), t(0x2e), t(0x2f),\ + t(0x30), t(0x31), t(0x32), t(0x33), t(0x34), t(0x35), t(0x36), t(0x37),\ + t(0x38), t(0x39), t(0x3a), t(0x3b), t(0x3c), t(0x3d), t(0x3e), t(0x3f),\ + t(0x40), t(0x41), t(0x42), t(0x43), t(0x44), t(0x45), t(0x46), t(0x47),\ + t(0x48), t(0x49), t(0x4a), t(0x4b), t(0x4c), t(0x4d), t(0x4e), t(0x4f),\ + t(0x50), t(0x51), t(0x52), t(0x53), t(0x54), t(0x55), t(0x56), t(0x57),\ + t(0x58), t(0x59), t(0x5a), t(0x5b), t(0x5c), t(0x5d), t(0x5e), t(0x5f),\ + t(0x60), t(0x61), t(0x62), t(0x63), t(0x64), t(0x65), t(0x66), t(0x67),\ + t(0x68), t(0x69), t(0x6a), t(0x6b), t(0x6c), t(0x6d), t(0x6e), t(0x6f),\ + t(0x70), t(0x71), t(0x72), t(0x73), t(0x74), t(0x75), t(0x76), t(0x77),\ + t(0x78), t(0x79), t(0x7a), t(0x7b), t(0x7c), t(0x7d), t(0x7e), t(0x7f),\ + t(0x80), t(0x81), t(0x82), t(0x83), t(0x84), t(0x85), t(0x86), t(0x87),\ + t(0x88), t(0x89), t(0x8a), t(0x8b), t(0x8c), t(0x8d), t(0x8e), t(0x8f),\ + t(0x90), t(0x91), t(0x92), t(0x93), t(0x94), t(0x95), t(0x96), t(0x97),\ + t(0x98), t(0x99), t(0x9a), t(0x9b), t(0x9c), t(0x9d), t(0x9e), t(0x9f),\ + t(0xa0), t(0xa1), t(0xa2), t(0xa3), t(0xa4), t(0xa5), t(0xa6), t(0xa7),\ + t(0xa8), t(0xa9), t(0xaa), t(0xab), t(0xac), t(0xad), t(0xae), t(0xaf),\ + t(0xb0), t(0xb1), t(0xb2), t(0xb3), t(0xb4), t(0xb5), t(0xb6), t(0xb7),\ + t(0xb8), t(0xb9), t(0xba), t(0xbb), t(0xbc), t(0xbd), t(0xbe), t(0xbf),\ + t(0xc0), t(0xc1), t(0xc2), t(0xc3), t(0xc4), t(0xc5), t(0xc6), t(0xc7),\ + t(0xc8), t(0xc9), t(0xca), t(0xcb), t(0xcc), t(0xcd), t(0xce), t(0xcf),\ + t(0xd0), t(0xd1), t(0xd2), t(0xd3), t(0xd4), t(0xd5), t(0xd6), t(0xd7),\ + t(0xd8), t(0xd9), t(0xda), t(0xdb), t(0xdc), t(0xdd), t(0xde), t(0xdf),\ + t(0xe0), t(0xe1), t(0xe2), t(0xe3), t(0xe4), t(0xe5), t(0xe6), t(0xe7),\ + t(0xe8), t(0xe9), t(0xea), t(0xeb), t(0xec), t(0xed), t(0xee), t(0xef),\ + t(0xf0), t(0xf1), t(0xf2), t(0xf3), t(0xf4), t(0xf5), t(0xf6), t(0xf7),\ + t(0xf8), t(0xf9), t(0xfa), t(0xfb), t(0xfc), t(0xfd), t(0xfe), t(0xff) + +/* +// Encrypt/Decrypt S-box data +// (be parametrized by any transformation 't') +*/ +#define ENC_SBOX(t) \ + t(0x63), t(0x7c), t(0x77), t(0x7b), t(0xf2), t(0x6b), t(0x6f), t(0xc5),\ + t(0x30), t(0x01), t(0x67), t(0x2b), t(0xfe), t(0xd7), t(0xab), t(0x76),\ + t(0xca), t(0x82), t(0xc9), t(0x7d), t(0xfa), t(0x59), t(0x47), t(0xf0),\ + t(0xad), t(0xd4), t(0xa2), t(0xaf), t(0x9c), t(0xa4), t(0x72), t(0xc0),\ + t(0xb7), t(0xfd), t(0x93), t(0x26), t(0x36), t(0x3f), t(0xf7), t(0xcc),\ + t(0x34), t(0xa5), t(0xe5), t(0xf1), t(0x71), t(0xd8), t(0x31), t(0x15),\ + t(0x04), t(0xc7), t(0x23), t(0xc3), t(0x18), t(0x96), t(0x05), t(0x9a),\ + t(0x07), t(0x12), t(0x80), t(0xe2), t(0xeb), t(0x27), t(0xb2), t(0x75),\ + t(0x09), t(0x83), t(0x2c), t(0x1a), t(0x1b), t(0x6e), t(0x5a), t(0xa0),\ + t(0x52), t(0x3b), t(0xd6), t(0xb3), t(0x29), t(0xe3), t(0x2f), t(0x84),\ + t(0x53), t(0xd1), t(0x00), t(0xed), t(0x20), t(0xfc), t(0xb1), t(0x5b),\ + t(0x6a), t(0xcb), t(0xbe), t(0x39), t(0x4a), t(0x4c), t(0x58), t(0xcf),\ + t(0xd0), t(0xef), t(0xaa), t(0xfb), t(0x43), t(0x4d), t(0x33), t(0x85),\ + t(0x45), t(0xf9), t(0x02), t(0x7f), t(0x50), t(0x3c), t(0x9f), t(0xa8),\ + t(0x51), t(0xa3), t(0x40), t(0x8f), t(0x92), t(0x9d), t(0x38), t(0xf5),\ + t(0xbc), t(0xb6), t(0xda), t(0x21), t(0x10), t(0xff), t(0xf3), t(0xd2),\ + t(0xcd), t(0x0c), t(0x13), t(0xec), t(0x5f), t(0x97), t(0x44), t(0x17),\ + t(0xc4), t(0xa7), t(0x7e), t(0x3d), t(0x64), t(0x5d), t(0x19), t(0x73),\ + t(0x60), t(0x81), t(0x4f), t(0xdc), t(0x22), t(0x2a), t(0x90), t(0x88),\ + t(0x46), t(0xee), t(0xb8), t(0x14), t(0xde), t(0x5e), t(0x0b), t(0xdb),\ + t(0xe0), t(0x32), t(0x3a), t(0x0a), t(0x49), t(0x06), t(0x24), t(0x5c),\ + t(0xc2), t(0xd3), t(0xac), t(0x62), t(0x91), t(0x95), t(0xe4), t(0x79),\ + t(0xe7), t(0xc8), t(0x37), t(0x6d), t(0x8d), t(0xd5), t(0x4e), t(0xa9),\ + t(0x6c), t(0x56), t(0xf4), t(0xea), t(0x65), t(0x7a), t(0xae), t(0x08),\ + t(0xba), t(0x78), t(0x25), t(0x2e), t(0x1c), t(0xa6), t(0xb4), t(0xc6),\ + t(0xe8), t(0xdd), t(0x74), t(0x1f), t(0x4b), t(0xbd), t(0x8b), t(0x8a),\ + t(0x70), t(0x3e), t(0xb5), t(0x66), t(0x48), t(0x03), t(0xf6), t(0x0e),\ + t(0x61), t(0x35), t(0x57), t(0xb9), t(0x86), t(0xc1), t(0x1d), t(0x9e),\ + t(0xe1), t(0xf8), t(0x98), t(0x11), t(0x69), t(0xd9), t(0x8e), t(0x94),\ + t(0x9b), t(0x1e), t(0x87), t(0xe9), t(0xce), t(0x55), t(0x28), t(0xdf),\ + t(0x8c), t(0xa1), t(0x89), t(0x0d), t(0xbf), t(0xe6), t(0x42), t(0x68),\ + t(0x41), t(0x99), t(0x2d), t(0x0f), t(0xb0), t(0x54), t(0xbb), t(0x16) + +#define DEC_SBOX(t) \ + t(0x52), t(0x09), t(0x6a), t(0xd5), t(0x30), t(0x36), t(0xa5), t(0x38),\ + t(0xbf), t(0x40), t(0xa3), t(0x9e), t(0x81), t(0xf3), t(0xd7), t(0xfb),\ + t(0x7c), t(0xe3), t(0x39), t(0x82), t(0x9b), t(0x2f), t(0xff), t(0x87),\ + t(0x34), t(0x8e), t(0x43), t(0x44), t(0xc4), t(0xde), t(0xe9), t(0xcb),\ + t(0x54), t(0x7b), t(0x94), t(0x32), t(0xa6), t(0xc2), t(0x23), t(0x3d),\ + t(0xee), t(0x4c), t(0x95), t(0x0b), t(0x42), t(0xfa), t(0xc3), t(0x4e),\ + t(0x08), t(0x2e), t(0xa1), t(0x66), t(0x28), t(0xd9), t(0x24), t(0xb2),\ + t(0x76), t(0x5b), t(0xa2), t(0x49), t(0x6d), t(0x8b), t(0xd1), t(0x25),\ + t(0x72), t(0xf8), t(0xf6), t(0x64), t(0x86), t(0x68), t(0x98), t(0x16),\ + t(0xd4), t(0xa4), t(0x5c), t(0xcc), t(0x5d), t(0x65), t(0xb6), t(0x92),\ + t(0x6c), t(0x70), t(0x48), t(0x50), t(0xfd), t(0xed), t(0xb9), t(0xda),\ + t(0x5e), t(0x15), t(0x46), t(0x57), t(0xa7), t(0x8d), t(0x9d), t(0x84),\ + t(0x90), t(0xd8), t(0xab), t(0x00), t(0x8c), t(0xbc), t(0xd3), t(0x0a),\ + t(0xf7), t(0xe4), t(0x58), t(0x05), t(0xb8), t(0xb3), t(0x45), t(0x06),\ + t(0xd0), t(0x2c), t(0x1e), t(0x8f), t(0xca), t(0x3f), t(0x0f), t(0x02),\ + t(0xc1), t(0xaf), t(0xbd), t(0x03), t(0x01), t(0x13), t(0x8a), t(0x6b),\ + t(0x3a), t(0x91), t(0x11), t(0x41), t(0x4f), t(0x67), t(0xdc), t(0xea),\ + t(0x97), t(0xf2), t(0xcf), t(0xce), t(0xf0), t(0xb4), t(0xe6), t(0x73),\ + t(0x96), t(0xac), t(0x74), t(0x22), t(0xe7), t(0xad), t(0x35), t(0x85),\ + t(0xe2), t(0xf9), t(0x37), t(0xe8), t(0x1c), t(0x75), t(0xdf), t(0x6e),\ + t(0x47), t(0xf1), t(0x1a), t(0x71), t(0x1d), t(0x29), t(0xc5), t(0x89),\ + t(0x6f), t(0xb7), t(0x62), t(0x0e), t(0xaa), t(0x18), t(0xbe), t(0x1b),\ + t(0xfc), t(0x56), t(0x3e), t(0x4b), t(0xc6), t(0xd2), t(0x79), t(0x20),\ + t(0x9a), t(0xdb), t(0xc0), t(0xfe), t(0x78), t(0xcd), t(0x5a), t(0xf4),\ + t(0x1f), t(0xdd), t(0xa8), t(0x33), t(0x88), t(0x07), t(0xc7), t(0x31),\ + t(0xb1), t(0x12), t(0x10), t(0x59), t(0x27), t(0x80), t(0xec), t(0x5f),\ + t(0x60), t(0x51), t(0x7f), t(0xa9), t(0x19), t(0xb5), t(0x4a), t(0x0d),\ + t(0x2d), t(0xe5), t(0x7a), t(0x9f), t(0x93), t(0xc9), t(0x9c), t(0xef),\ + t(0xa0), t(0xe0), t(0x3b), t(0x4d), t(0xae), t(0x2a), t(0xf5), t(0xb0),\ + t(0xc8), t(0xeb), t(0xbb), t(0x3c), t(0x83), t(0x53), t(0x99), t(0x61),\ + t(0x17), t(0x2b), t(0x04), t(0x7e), t(0xba), t(0x77), t(0xd6), t(0x26),\ + t(0xe1), t(0x69), t(0x14), t(0x63), t(0x55), t(0x21), t(0x0c), t(0x7d), + +/* +// Internal cipher tables +*/ +extern const __ALIGN64 Ipp8u RijEncSbox[256]; /* pure encryption S-box */ +extern const __ALIGN64 Ipp8u RijDecSbox[256]; /* pure decryption S-box */ + +#endif /* _PCP_RIJTBLES_H */ diff --git a/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpscramble.h b/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpscramble.h new file mode 100644 index 0000000000..9518ef6ada --- /dev/null +++ b/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpscramble.h @@ -0,0 +1,170 @@ +/* +* Copyright (C) 2016 Intel Corporation. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in +* the documentation and/or other materials provided with the +* distribution. +* * Neither the name of Intel Corporation nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ + +#if !defined(_PC_SCRAMBLE_H) +#define _PC_SCRAMBLE_H + +/* +// cpsScramblePut/cpsScrambleGet +// stores to/retrieves from pScrambleEntry position +// pre-computed data if fixed window method is used +*/ +__INLINE void cpScramblePut(Ipp8u* pArray, cpSize colummSize, + const Ipp32u* pData, cpSize dataSize) +{ + int i; + switch(colummSize) { + case 1: + dataSize *= sizeof(Ipp32u); + for(i=0; i=2; dataSize-=2, pArray+=CACHE_LINE_SIZE, pData+=2) { + ((Ipp32u*)pArray)[0] = pData[0]; + ((Ipp32u*)pArray)[1] = pData[1]; + } + if(dataSize) + ((Ipp32u*)pArray)[0] = pData[0]; + break; + case 16: + for(; dataSize>=4; dataSize-=4, pArray+=CACHE_LINE_SIZE, pData+=4) { + ((Ipp32u*)pArray)[0] = pData[0]; + ((Ipp32u*)pArray)[1] = pData[1]; + ((Ipp32u*)pArray)[2] = pData[2]; + ((Ipp32u*)pArray)[3] = pData[3]; + } + for(; dataSize>0; dataSize--, pArray+=sizeof(Ipp32u), pData++) + ((Ipp32u*)pArray)[0] = pData[0]; + break; + case 32: + for(; dataSize>=8; dataSize-=8, pArray+=CACHE_LINE_SIZE, pData+=8) { + ((Ipp32u*)pArray)[0] = pData[0]; + ((Ipp32u*)pArray)[1] = pData[1]; + ((Ipp32u*)pArray)[2] = pData[2]; + ((Ipp32u*)pArray)[3] = pData[3]; + ((Ipp32u*)pArray)[4] = pData[4]; + ((Ipp32u*)pArray)[5] = pData[5]; + ((Ipp32u*)pArray)[6] = pData[6]; + ((Ipp32u*)pArray)[7] = pData[7]; + } + for(; dataSize>0; dataSize--, pArray+=sizeof(Ipp32u), pData++) + ((Ipp32u*)pArray)[0] = pData[0]; + break; + default: + break; + } +} + + +/* +// Retrieve data from pArray +*/ +#define u8_to_u32(b0,b1,b2,b3, x) \ + ((x) = (b0), \ + (x)|=((b1)<<8), \ + (x)|=((b2)<<16), \ + (x)|=((b3)<<24)) +#define u16_to_u32(w0,w1, x) \ + ((x) = (w0), \ + (x)|=((w1)<<16)) +#define u32_to_u64(dw0,dw1, x) \ + ((x) = (Ipp64u)(dw0), \ + (x)|= (((Ipp64u)(dw1))<<32)) + +__INLINE void cpScrambleGet(Ipp32u* pData, cpSize dataSize, + const Ipp8u* pArray, cpSize colummSize) +{ + int i; + switch(colummSize) { + case 1: + for(i=0; i=2; dataSize-=2, pArray+=CACHE_LINE_SIZE, pData+=2) { + pData[0] = ((Ipp32u*)pArray)[0]; + pData[1] = ((Ipp32u*)pArray)[1]; + } + if(dataSize) + pData[0] = ((Ipp32u*)pArray)[0]; + break; + case 16: + for(; dataSize>=4; dataSize-=4, pArray+=CACHE_LINE_SIZE, pData+=4) { + pData[0] = ((Ipp32u*)pArray)[0]; + pData[1] = ((Ipp32u*)pArray)[1]; + pData[2] = ((Ipp32u*)pArray)[2]; + pData[3] = ((Ipp32u*)pArray)[3]; + + } + for(; dataSize>0; dataSize--, pArray+=sizeof(Ipp32u), pData++) + pData[0] = ((Ipp32u*)pArray)[0]; + break; + case 32: + for(; dataSize>=8; dataSize-=8, pArray+=CACHE_LINE_SIZE, pData+=8) { + pData[0] = ((Ipp32u*)pArray)[0]; + pData[1] = ((Ipp32u*)pArray)[1]; + pData[2] = ((Ipp32u*)pArray)[2]; + pData[3] = ((Ipp32u*)pArray)[3]; + pData[4] = ((Ipp32u*)pArray)[4]; + pData[5] = ((Ipp32u*)pArray)[5]; + pData[6] = ((Ipp32u*)pArray)[6]; + pData[7] = ((Ipp32u*)pArray)[7]; + } + for(; dataSize>0; dataSize--, pArray+=sizeof(Ipp32u), pData++) + pData[0] = ((Ipp32u*)pArray)[0]; + break; + default: + break; + } +} + +#endif /* _PC_SCRAMBLE_H */ diff --git a/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpshsmgfca.c b/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpshsmgfca.c new file mode 100644 index 0000000000..544d30eb89 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpshsmgfca.c @@ -0,0 +1,109 @@ +/* +* Copyright (C) 2016 Intel Corporation. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in +* the documentation and/or other materials provided with the +* distribution. +* * Neither the name of Intel Corporation nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ + +#include "owndefs.h" +#include "owncp.h" +#include "pcphash.h" +#include "pcptool.h" + + +/*F* +// Name: ippsMGF_SHA1 +// ippsMGF_SHA224 +// ippsMGF_SHA256 +// ippsMGF_SHA384 +// ippsMGF_SHA512 +// ippsMGF_MD5 +// +// Purpose: Mask Generation Functios. +// +// Returns: Reason: +// ippStsNullPtrErr pMask == NULL +// ippStsLengthErr seedLen <0 +// maskLen <0 +// ippStsNotSupportedModeErr if algID is not match to supported hash alg +// ippStsNoErr no errors +// +// Parameters: +// pSeed pointer to the input stream +// seedLen input stream length (bytes) +// pMaske pointer to the ouput mask +// maskLen desired length of mask (bytes) +// +*F*/ +IPPFUN(IppStatus, ippsMGF,(const Ipp8u* pSeed, int seedLen, Ipp8u* pMask, int maskLen, IppHashAlgId hashAlg)) +{ + /* get algorithm id */ + hashAlg = cpValidHashAlg(hashAlg); + /* test hash alg */ + IPP_BADARG_RET(ippHashAlg_Unknown==hashAlg, ippStsNotSupportedModeErr); + + IPP_BAD_PTR1_RET(pMask); + IPP_BADARG_RET((seedLen<0)||(maskLen<0), ippStsLengthErr); + + { + /* hash specific */ + int hashSize = cpHashSize(hashAlg); + + int i, outLen; + + IppsHashState hashCtx; + ippsHashInit(&hashCtx, hashAlg); + + if(!pSeed) + seedLen = 0; + + for(i=0,outLen=0; outLen>24) & 0xFF); + cnt[1] = (Ipp8u)((i>>16) & 0xFF); + cnt[2] = (Ipp8u)((i>>8) & 0xFF); + cnt[3] = (Ipp8u)(i & 0xFF); + + cpReInitHash(&hashCtx, hashAlg); + ippsHashUpdate(pSeed, seedLen, &hashCtx); + ippsHashUpdate(cnt, 4, &hashCtx); + + if((outLen + hashSize) <= maskLen) { + ippsHashFinal(pMask+outLen, &hashCtx); + outLen += hashSize; + } + else { + Ipp8u md[BITS2WORD8_SIZE(IPP_SHA512_DIGEST_BITSIZE)]; + ippsHashFinal(md, &hashCtx); + CopyBlock(md, pMask+outLen, maskLen-outLen); + outLen = maskLen; + } + } + + return ippStsNoErr; + } +} diff --git a/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcptool.h b/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcptool.h new file mode 100644 index 0000000000..9d6b63e913 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcptool.h @@ -0,0 +1,177 @@ +/* +* Copyright (C) 2016 Intel Corporation. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in +* the documentation and/or other materials provided with the +* distribution. +* * Neither the name of Intel Corporation nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ + +#if !defined(_PC_TOOL_H) +#define _CP_TOOL_H + +/* copy data block */ +__INLINE void CopyBlock(const void* pSrc, void* pDst, cpSize numBytes) +{ + const Ipp8u* s = (Ipp8u*)pSrc; + Ipp8u* d = (Ipp8u*)pDst; + cpSize k; + for(k=0; k> (blkSize-numSize)%8 ); + + /* save crytical byte */ + Ipp8u save = (Ipp8u)( pCounter[maskPosition] & ~mask ); + + int len = BITS2WORD8_SIZE(blkSize); + Ipp32u carry = 1; + for(; (len>maskPosition) && carry; len--) { + Ipp32u x = pCounter[len-1] + carry; + pCounter[len-1] = (Ipp8u)x; + carry = (x>>8) & 0xFF; + } + + /* update crytical byte */ + pCounter[maskPosition] &= mask; + pCounter[maskPosition] |= save; +} + +#endif /* _CP_TOOL_H */ diff --git a/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpver.c b/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpver.c new file mode 100644 index 0000000000..18c70aa883 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpver.c @@ -0,0 +1,41 @@ +/* +* Copyright (C) 2016 Intel Corporation. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in +* the documentation and/or other materials provided with the +* distribution. +* * Neither the name of Intel Corporation nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ + +#include "owndefs.h" + +#ifndef __OWNCP_H__ + #include "owncp.h" +#endif + +#include "pcpname.h" +#include "pcpver.h" + +#include "ippver.gen" diff --git a/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpver.h b/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpver.h new file mode 100644 index 0000000000..30e6dc3a02 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/crypto_px/sources/ippcp/src/pcpver.h @@ -0,0 +1,36 @@ +/* +* Copyright (C) 2016 Intel Corporation. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in +* the documentation and/or other materials provided with the +* distribution. +* * Neither the name of Intel Corporation nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ + +#include "ippver.h" +#define BUILD() 1043 +#define VERSION() BASE_VERSION(),BUILD() + +/* ////////////////////////// End of file "pcpver.h" ///////////////////////// */ diff --git a/sgx-jvm/linux-sgx/external/epid/LICENSE.txt b/sgx-jvm/linux-sgx/external/epid/LICENSE.txt new file mode 100644 index 0000000000..38f89e4ace --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/LICENSE.txt @@ -0,0 +1,249 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + +======================================================================= + +EPID SDK Subcomponents: + +The EPID SDK contains subcomponents with separate copyright notices +and license terms. Your use of the source code for these subcomponents +is subject to the terms and conditions of the following licenses. + + +----------------------------------------------------------------------- +The BSD 3-Clause License +----------------------------------------------------------------------- + +The EPID SDK bundles portions of the following under the BSD 3-Clause +License: + + - Google Test (https://github.com/google/googletest) + Copyright 2008, Google Inc. + +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/sgx-jvm/linux-sgx/external/epid/Makefile b/sgx-jvm/linux-sgx/external/epid/Makefile new file mode 100644 index 0000000000..a542d977a3 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/Makefile @@ -0,0 +1,52 @@ +include ../../buildenv.mk + +EPIDLIB := libepid.a +TOP_DIR := $(LINUX_EXTERNAL_DIR)/epid + +CFLAGS += -fPIC +DEFINES := -DIPPEPID_USE_MERGEDLIB -DASSUME_GETOCTSTRING_POINT_VALID + +ifdef DEBUG + CFLAGS += -O0 + DEFINES += -DDEBUG +else + DEFINES += -DNDEBUG +endif + +ifeq ($(ARCH), x86_64) + DEFINES += -DUSE_Y8_HEADER +else + DEFINES += -DUSE_P8_HEADER +endif + +vpath %.c epid/common epid/common/math epid/member epid/verifier ext/ipp/sources/ippcpepid/src + +INCLUDE += -I$(TOP_DIR)/ext/ipp/include \ + -I$(TOP_DIR)/ext/ipp/sources/include \ + -I$(TOP_DIR)/ext/ipp/sources/ippcp/src \ + -I$(TOP_DIR)/ext/ipp/sources/ippcpepid/src \ + -I$(TOP_DIR) + +SRC := commitment.c epid2params.c errors.c grouppubkey.c memory.c printutils.c sigrlvalid.c stack.c \ + bignum.c ecgroup.c finitefield.c pairing.c \ + context.c nr_prove.c privkey.c signbasic.c get_sigsize.c presig.c request_join.c sign.c \ + check_privrl_entry.c nrverify.c verifybasic.c context.c sigs_linked.c verify.c \ + pcpgfp.c pcpgfpec.c pcpgfpecpoint.c pcpgfpecpointstuff.c pcpgfpstuff.c pcpgfpx.c pcpgfpxstuff.c + +OBJ := $(SRC:.c=.o) + +.PHONY: all +all: $(EPIDLIB) + +$(EPIDLIB): $(OBJ) + $(AR) rcs $@ $^ + +%.o: %.c + $(CC) $(INCLUDE) $(filter-out -Werror, $(CFLAGS)) $(DEFINES) -c $< -o $@ + +.PHONY: clean +clean: + @$(RM) $(OBJ) $(EPIDLIB) + +.PHONY: rebuild +rebuild: clean all diff --git a/sgx-jvm/linux-sgx/external/epid/NOTICE.txt b/sgx-jvm/linux-sgx/external/epid/NOTICE.txt new file mode 100644 index 0000000000..fc0c4208bb --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/NOTICE.txt @@ -0,0 +1,22 @@ +Intel(R) EPID SDK +Copyright 2016 Intel Corporation + +========== + +The Intel(R) EPID SDK contains subcomponents with separate copyright notices +and license terms. + +Your use of the source code for the these subcomponents is subject to +the terms and conditions of their respective licenses. + +See the LICENSE.txt file for a list of subcomponents and dependencies and +their respective licenses. + +---------- + +The source code used for math primitives in the Intel(R) EPID SDK is a +subset of the Intel(R) IPP Cryptography library (v9.0.3) written in +C. For higher performance, you can use the commercial version of the +IPP Cryptography libraries, which are available at +https://software.intel.com/articles/download-ipp-cryptography-libraries. + diff --git a/sgx-jvm/linux-sgx/external/epid/README.md b/sgx-jvm/linux-sgx/external/epid/README.md new file mode 100644 index 0000000000..332f72233e --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/README.md @@ -0,0 +1,57 @@ +# Intel(R) EPID SDK + +The Intel(R) Enhanced Privacy ID Software Development Kit + +Intel(R) EPID SDK enables adding Intel(R) EPID support to applications +and platforms. + +Intel(R) EPID is a cryptographic protocol which enables the remote +authentication of a trusted platform whilst preserving the user's +privacy. + +* For a given public key there are many (e.g., millions) of private + keys. The key holders form a group. + +* Any key holder may sign against the one public key. + +* No one can tell which private key signed the data. This is the + privacy property. + +You can use Intel(R) EPID as a foundational building block for a +multitude of security solutions. + + +## Prerequisites + +* [Python](http://www.python.org) + +* [SCons](http://www.scons.org/) + +* [Parts](https://bitbucket.org/sconsparts/parts) + +* A C/C++ compiler supported by Parts + + +## Release Notes + +See [RELEASE_NOTES.md](RELEASE_NOTES.md). + + +## Documentation + +See [doc/index.html](doc/index.html) to browse the html +documentation. + + +## License + +See [LICENSE.txt](LICENSE.txt). + + +## Math Primitives + +The source code used for math primitives in the Intel(R) EPID SDK is a +subset of the Intel(R) IPP Cryptography library (v9.0.3) written in +C. For higher performance, you can use the commercial version of the +IPP Cryptography libraries, which are available at +https://software.intel.com/articles/download-ipp-cryptography-libraries. diff --git a/sgx-jvm/linux-sgx/external/epid/RELEASE_NOTES.md b/sgx-jvm/linux-sgx/external/epid/RELEASE_NOTES.md new file mode 100644 index 0000000000..3eb9ab3fc5 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/RELEASE_NOTES.md @@ -0,0 +1,41 @@ +# Intel(R) EPID SDK Release Notes {#ChangeLog} + +# 2.0.0 + +## New in This Release + +* Signed binary issuer material support. + + - Binary issuer material validation APIs. + + - Updated sample issuer material. + + - Updated samples that parse signed binary issuer material. + +* Compressed member private key support. + +* Validated on additional IoT platforms. + + - Windows 10 IoT Core + + - WindRiver IDP + + +## Changes + +* The default hash algorithm has changed. It is now SHA-512. + +* Functions that returned `EpidNullPtrErr` now return `EpidBadArgErr` + instead. + + +## Fixes + +* Updated build flags to work around GCC 4.8.5 defect. + + +## Known Issues + +* SHA-512/256 hash algorithm is not supported. + +* Compressed key sample material is not included in the package. diff --git a/sgx-jvm/linux-sgx/external/epid/ReadMe.txt b/sgx-jvm/linux-sgx/external/epid/ReadMe.txt new file mode 100644 index 0000000000..9520110999 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/ReadMe.txt @@ -0,0 +1,29 @@ +======================================================================== + STATIC LIBRARY : epid Project Overview +======================================================================== + +AppWizard has created this epid library project for you. + +No source files were created as part of your project. + + +epid.vcxproj + This is the main project file for VC++ projects generated using an Application Wizard. + It contains information about the version of Visual C++ that generated the file, and + information about the platforms, configurations, and project features selected with the + Application Wizard. + +epid.vcxproj.filters + This is the filters file for VC++ projects generated using an Application Wizard. + It contains information about the association between the files in your project + and the filters. This association is used in the IDE to show grouping of files with + similar extensions under a specific node (for e.g. ".cpp" files are associated with the + "Source Files" filter). + +///////////////////////////////////////////////////////////////////////////// +Other notes: + +AppWizard uses "TODO:" comments to indicate parts of the source code you +should add to or customize. + +///////////////////////////////////////////////////////////////////////////// diff --git a/sgx-jvm/linux-sgx/external/epid/SConstruct b/sgx-jvm/linux-sgx/external/epid/SConstruct new file mode 100644 index 0000000000..296adced51 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/SConstruct @@ -0,0 +1,210 @@ +############################################################################ +# Copyright 2016 Intel Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +############################################################################ + +"""use scons -k to invoke all builds regardless of unit test failures +""" +import string +import sys +import SCons.Script +import os.path +from parts import * + +print "**************** TOOLS ****************" +print '* Python Version:', string.split(sys.version, " ", 1)[0] +print '* SCons Version:', SCons.__version__ +print '* Parts Version:', PartsExtensionVersion() +print "***************************************" + +def PrintCompilerVersion(env): + """ + Function to print version of compilers used for build + Args: + env: Environment to get compilers version + """ + res = '' + if 'INTELC_VERSION' in env: + res += 'ICC ' + env['INTELC_VERSION'] + ';' + if 'MSVC_VERSION' in env: + res += 'MS ' + env['MSVC_VERSION'] + ';' + if 'GXX_VERSION' in env: + res += 'GXX ' + env['GXX_VERSION'] + ';' + if 'GCC_VERSION' in env: + res += 'GCC ' + env['GCC_VERSION'] + ';' + print 'Compiler Version: ', res + +def include_parts(part_list, **kwargs): + for parts_file in part_list: + if os.path.isfile(DefaultEnvironment().subst(parts_file)): + Part(parts_file=parts_file, **kwargs) + +######## Part groups #################################################### +ipp_parts = ['ext/ipp/ippcp.parts', + 'ext/ipp/ippcpepid.parts', + 'ext/ipp/ippcommon.parts'] +utest_parts = ['ext/gtest/gtest.parts', + 'epid/common-testhelper/common-testhelper.parts'] +common_parts = ['epid/common/common.parts'] +member_parts = ['epid/member/member.parts'] +verifier_parts = ['epid/verifier/verifier.parts'] +util_parts = ['example/util/util.parts'] +example_parts = ['example/verifysig/verifysig.parts', + 'example/signmsg/signmsg.parts', + 'example/data/data.parts'] +example_test_parts = ['test/testbot/testbot.parts', + 'test/testbot/signmsg/signmsg_testbot.parts', + 'test/testbot/verifysig/verifysig_testbot.parts', + 'test/testbot/integration/integration_testbot.parts'] +package_parts = ['ext/gtest/gtest.parts', + 'ext/ipp/ippcommon.parts', + 'ext/ipp/ippcp.parts', + 'ext/ipp/ippcpepid.parts', + 'package.parts'] +internal_tools_parts = ['tools/ikgfwrapper/ikgfwrapper.parts', + 'tools/revokegrp/revokegrp.parts', + 'tools/revokekey/revokekey.parts', + 'tools/revokesig/revokesig.parts', + 'tools/extractkeys/extractkeys.parts', + 'tools/extractgrps/extractgrps.parts'] +######## End Part groups ############################################### +######## Commandline option setup ####################################### +product_variants = [ + 'production', + 'internal-test', + 'package-epid-sdk', + 'internal-tools' +] + +default_variant = 'production' + +def is_production(): + return GetOption("product-variant") == 'production' + +def is_internal_test(): + return GetOption("product-variant") == 'internal-test' + +def is_internal_tools(): + return GetOption("product-variant") == 'internal-tools' + +def is_package(): + return GetOption("product-variant") == 'package-epid-sdk' + +def variant_dirname(): + s = GetOption("product-variant") + if s == 'production': + return 'epid-sdk' + elif s == 'package-epid-sdk': + return 'epid-sdk' + else: + return s + +AddOption("--product-variant", "--prod-var", nargs=1, + help=("Select product variant to build. Possible " + "options are: {0}. The default is {1} if no option " + "is specified").format(", ".join(product_variants), + default_variant), + action='store', dest='product-variant', type='choice', + choices=product_variants, default=default_variant) + +SetOptionDefault("PRODUCT_VARIANT", variant_dirname()) + +######## End Commandline option setup ################################### + + +# fix for parts 0.10.8 until we get better logic to extract ${CC} +SetOptionDefault('PARTS_USE_SHORT_TOOL_NAMES', 1) + +def set_default_production_options(): + SetOptionDefault('TARGET_PLATFORM', 'x86_64') + SetOptionDefault('CONFIG', 'release') + + SetOptionDefault('TARGET_VARIANT', '${TARGET_OS}-${TARGET_ARCH}') + + SetOptionDefault('INSTALL_ROOT', + '#_install/${PRODUCT_VARIANT}') + + SetOptionDefault('INSTALL_TOOLS_BIN', + '$INSTALL_ROOT/tools') + + SetOptionDefault('INSTALL_SAMPLE_BIN', + '$INSTALL_ROOT/example') + + SetOptionDefault('INSTALL_EPID_INCLUDE', + '$INSTALL_ROOT/include/epid') + + SetOptionDefault('INSTALL_IPP_INCLUDE', + '$INSTALL_ROOT/include/ext/ipp/include') + + SetOptionDefault('INSTALL_TEST_BIN', + '$INSTALL_ROOT/test') + + SetOptionDefault('INSTALL_LIB', + '$INSTALL_ROOT/lib/${TARGET_VARIANT}') + + SetOptionDefault('INSTALL_SAMPLE_DATA', + '$INSTALL_ROOT/example') + + SetOptionDefault('PACKAGE_DIR', + '#_package') + + SetOptionDefault('PACKAGE_ROOT', + '#_package/${PRODUCT_VARIANT}') + + SetOptionDefault('ROOT', + '#') + + SetOptionDefault('PACKAGE_NAME', + '{PRODUCT_VARIANT}') + +if is_production(): + set_default_production_options() + include_parts(ipp_parts, mode=['install_lib'], + INSTALL_INCLUDE='${INSTALL_IPP_INCLUDE}') + include_parts(utest_parts + common_parts + + member_parts + verifier_parts, + mode=['install_lib'], + INSTALL_INCLUDE='${INSTALL_EPID_INCLUDE}') + include_parts(util_parts + example_parts, + INSTALL_INCLUDE='${INSTALL_EPID_INCLUDE}', + INSTALL_BIN='${INSTALL_SAMPLE_BIN}', + INSTALL_DATA='${INSTALL_SAMPLE_DATA}') + PrintCompilerVersion(DefaultEnvironment()) + Default('all') + Default('run_utest::') + +if is_internal_test(): + set_default_production_options() + include_parts(ipp_parts) + include_parts(utest_parts + common_parts + + member_parts + verifier_parts) + include_parts(util_parts + example_parts, + INSTALL_BIN='${INSTALL_SAMPLE_BIN}', + INSTALL_DATA='${INSTALL_SAMPLE_DATA}') + include_parts(example_test_parts) + Default('all') + +if is_internal_tools(): + set_default_production_options() + include_parts(ipp_parts + utest_parts + common_parts + util_parts) + include_parts(internal_tools_parts, INSTALL_BIN='${INSTALL_TOOLS_BIN}') + Default('ikgfwrapper', 'revokegrp', 'revokekey', 'revokesig', + 'extractkeys', 'extractgrps') + +if is_package(): + set_default_production_options() + include_parts(package_parts, + mode=['install_package'], + INSTALL_TOP_LEVEL='${PACKAGE_ROOT}') + Default('package') diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/BuildingSdk.html b/sgx-jvm/linux-sgx/external/epid/doc/html/BuildingSdk.html new file mode 100644 index 0000000000..715303c04d --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/BuildingSdk.html @@ -0,0 +1,150 @@ + + + + + + + +Intel® Enhanced Privacy ID SDK: Building From Source + + + + + + + + + + + + +

+
+ + + + + + +
+ +
+
+ + +
+
+ +
+
+
+ +
+
+
+
Building From Source
+
+
+ +

To use the SDK in a project, the code from the SDK must be included in that project. The easiest way to do this is to link to static libraries. The SDK comes with build scripts to build static libraries for common environments.

+

+Prerequisites

+

Building SDK code out of the box requires a number of tools. This section lists the tools used to build the SDK.

+ + + + + + + + + + + +
Prerequisite Notes
A C/C++ compiler Core code in C. Unit tests need C++11 support.
Python Validated with v2.7.10
SCons Validated with v2.4.1
Parts 0.10.9.2 or later
+

+Building

+

To use the SDK, you need to build it to generate libraries compatible with your build environment.

+

To build based on the default SConstruct file in the root directory of the SDK, invoke scons with no arguments.

cd <path/to/sdk-root>
+scons
+

By default, this performs a 64 bit release build.

+

Potentially useful command line options:

+ + + + + + + + + + + + + + + + + + + + + + + + + +
Option Action
--cfg=debug Build in debug mode
--cfg=release Build in release mode
--target=x86 Target x86
--target=x86_64 Target x86_64
--tc=cl Use msvc to compile
--tc=gcc Use gcc to compile
--tc=icl,mstools Use intelc to compile
build:: Build the SDK (does not build unit tests)
utest:: Build unit tests
run_utest:: Run unit tests (builds tests if needed)
-c Clean the build
+

Built components appear in the _install directory of the SDK root.

+

+Example Programs

+

The SDK includes several examples that show you different aspects of how the Intel® EPID scheme works. In the SDK build, these examples are located in _install/epid-sdk/example.

+ + + + + + + +
Name Description
signmsg Create Intel® EPID signature of message
verifysig Verify signature is from a group member in good standing
+

+Building with Other Build Systems

+

It is relatively straightforward to port the SDK to your build system of choice. The following dependency diagram shows the relationship between components and the sources used to build them.

+
+basicdoc.png +
+
+
+ + + + + diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/ChangeLog.html b/sgx-jvm/linux-sgx/external/epid/doc/html/ChangeLog.html new file mode 100644 index 0000000000..ed8fc9fb33 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/ChangeLog.html @@ -0,0 +1,106 @@ + + + + + + + +Intel® Enhanced Privacy ID SDK: What's New + + + + + + + + + + + + +
+
+ + + + + + +
+ +
+
+ + +
+
+ +
+
+
+ +
+
+
+
What's New
+
+
+

2.0.0

+

New in This Release

+
    +
  • Signed binary issuer material support.
      +
    • Binary issuer material validation APIs.
    • +
    • Updated sample issuer material.
    • +
    • Updated samples that parse signed binary issuer material.
    • +
    +
  • +
  • Compressed member private key support.
  • +
  • Validated on additional IoT platforms.
      +
    • Windows 10 IoT Core
    • +
    • WindRiver IDP
    • +
    +
  • +
+

Changes

+
    +
  • The default hash algorithm has changed. It is now SHA-512.
  • +
  • Functions that returned EpidNullPtrErr now return EpidBadArgErr instead.
  • +
+

Fixes

+
    +
  • Updated build flags to work around GCC 4.8.5 defect.
  • +
+

Known Issues

+
    +
  • SHA-512/256 hash algorithm is not supported.
  • +
  • Compressed key sample material is not included in the package.
  • +
+
+
+ + + + + diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/EpidOverview.html b/sgx-jvm/linux-sgx/external/epid/doc/html/EpidOverview.html new file mode 100644 index 0000000000..ae20c68102 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/EpidOverview.html @@ -0,0 +1,172 @@ + + + + + + + +Intel® Enhanced Privacy ID SDK: Introduction to the Intel® EPID Scheme + + + + + + + + + + + + +
+
+ + + + + + +
+ +
+
+ + +
+
+ +
+
+
+ +
+
+
+
Introduction to the Intel® EPID Scheme
+
+
+ +

Intel® EPID is a cryptographic protocol which enables the remote authentication of a trusted platform whilst preserving the user's privacy.

+

+Roles

+

In the Intel® EPID scheme, there are three roles: issuers, members, and verifiers.

+

The entities in these roles interact with each other in such a way that a member can prove to a verifier that it is a trusted member of a group without disclosing the identity of the member. Groups are created and managed by the issuer.

+
+epid_diagram_high_level_use_case.png +
+

+Issuers

+

The issuer is responsible for managing group membership.

+

The issuer manages groups by doing the following:

+
    +
  • Creates groups by generating one issuing private key and one group certificate for each group. The group certificate contains the group public key.
  • +
  • Creates group members by generating unique Intel® EPID member private keys through bulk provisioning. Member private keys are created from the issuing private key for the group.
  • +
  • Manages requests from prospective members to join existing groups by using the join protocol.
  • +
  • Creates and maintains signature based revocation lists and private key based revocation lists. These lists of members no longer in good standing allow members to be dropped from a group.
  • +
  • Creates and maintains group revocation lists.
  • +
  • Makes group public keys and revocation lists available to verifiers.
  • +
+
+epid_diagram_issuer_high_level.png +
+

+Members

+

The member is the entity that attempts to anonymously prove its group membership to the verifier.

+
    +
  • Members are authorized by the issuer as part of a group.
  • +
  • Each group member has a unique Intel® EPID private key, which corresponds to the group.
  • +
  • The member uses its member private key to sign a message to prove group membership to the verifier without revealing the identity of the member.
  • +
+
+epid_diagram_member_high_level.png +
+

+Verifiers

+

The verifier checks an Intel(R) EPID signature to establish whether it was signed by an entity or device that is a member in good standing.

+

The verifier acts on behalf of a party that needs to know it is communicating with a trusted device. Verifiers obtain group certificates and revocation lists from issuers and negotiate details of signature protocol with members.

+

A verifier can do the following:

+
    +
  • Confirm a member is in fact a member of a given group in good standing.
  • +
  • Obtain group certificates and revocation lists from issuers.
  • +
  • Negotiate details of signature protocol with members.
  • +
+
+epid_diagram_verifier_high_level.png +
+

+Groups

+

An Intel® EPID group represents a set of trusted entities called members. Issuers create groups and manage group membership. For each group, the issuer creates a group public key simultaneously with the corresponding issuing private key. The issuer uses the issuing private key to create unique member private keys for each group member, and makes the group public key available to verifiers.

+

All groups have the following:

+
    +
  • Group public key, which corresponds to the issuing private key kept by the issuer
  • +
  • Signature based revocation list
  • +
  • Private key based revocation list
  • +
  • Member private keys, generated from the issuing private key
  • +
+

If a signature based revocation list or private key based revocation list does not exist, it is assumed to be empty.

+

+Keys

+

The Intel® EPID scheme works with three types of keys: the group public key, the issuing private key, and the member private key. A group public key corresponds to the unique member private keys that are part of the group. Member private keys are generated from the issuing private key.

+

Additionally, in the Intel® EPID scheme, a private key can be revoked given a signature created by that key, even if the key itself is still unknown. Group membership can be revoked and entire groups can be revoked. For more information on revocation, refer to Revocation.

+

+Group Public Key

+

The group public key is the key used by the verifier to confirm that a member belongs to a group in good standing. Each member private key in a group is associated with the group's public key.

+

When a group is created, the group public key and the issuing private key are simultaneously generated by the issuer. The verifier obtains the group public key from the issuer.

+

+Issuing Private Key

+

The issuing private key is the key used by the issuer to generate unique private keys for each member of a given group. For every group public key, there is a corresponding issuing private key. The issuing private key remains with the issuer and is kept private.

+

+Member Private Key

+

The member private key is the key used by the member to digitally sign a message when attempting to prove to the verifier that the member belongs to the group and is in good standing.

+

Unique member private keys are generated by the issuer for each member of a given group. The same group public key corresponds to each member private key in the group.

+

+Member and Verifier Interaction

+

Each Intel® EPID member uses its Intel® EPID private key to digitally sign a message. The resulting signature is called an Intel® EPID signature.

+

The Intel® EPID verifier uses the group public key to verify the correctness of an Intel® EPID signature, i.e., to verify that the signature was indeed created by a member with a valid Intel® EPID private key.

+

However, the Intel® EPID signature does not convey any information about which unique private key was used to create the signature.

+
+epid_diagram_high_level_interaction.png +
+
+
+ + + + + diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/Glossary.html b/sgx-jvm/linux-sgx/external/epid/doc/html/Glossary.html new file mode 100644 index 0000000000..09a29e6fcb --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/Glossary.html @@ -0,0 +1,170 @@ + + + + + + + +Intel® Enhanced Privacy ID SDK: Glossary + + + + + + + + + + + + +
+
+ + + + + + +
+ +
+
+ + +
+
+ +
+
+
+ +
+
+
+
Glossary
+
+
+ +

+DAA

+

Direct Anonymous Attestation (DAA) is a digital signature algorithm that supports anonymity by providing a group public verification key associated with many unique private signing keys. Intel® EPID enhances DAA by enabling a private key to be revoked given a signature created by that key, even if the key itself is still unknown.

+

+Elliptic curve

+

In elliptic curve cryptography, an elliptic curve is an algebraic structure used to create a function whose output is easy to compute, but whose input is difficult to compute given the output. Elliptic curve cryptography requires smaller keys compared to non-elliptic curve cryptography (based on Galois fields) to provide equivalent security.

+

+Elliptic curve point

+

An elliptic curve point is a point along an elliptic curve. The security of elliptic curve cryptography depends on the ability to compute a point multiplication and the inability to compute the multiplicand given the original and product points.

+

+Group

+

An Intel® EPID group represents a set of trusted entities called members.

+

Issuers create groups and manage group membership. For each group, the issuer creates a group public key simultaneously with the corresponding issuing private key. The issuer uses the issuing private key to create unique member private keys for each group member, and makes the group public key available to verifiers.

+

All groups have the following:

+
    +
  • Group public key, which corresponds to the issuing private key kept by the issuer
  • +
  • Signature based revocation list
  • +
  • Private key based revocation list
  • +
  • Member private keys, generated from the issuing private key
  • +
+

If a signature based revocation list or private key based revocation list does not exist, it is assumed to be empty.

+

+Group certificate

+

The group certificate contains the group public key. The group certificate is created by the issuer and obtained by the verifier. When the issuer creates groups, it generates one issuing private key and one group certificate for each group.

+

+Group public key

+

The group public key is the key used by the verifier to confirm that a member belongs to a group in good standing. Each member private key in a group is associated with the group's public key.

+

When a group is created, the group public key and the issuing private key are simultaneously generated by the issuer. The verifier obtains the group public key from the issuer.

+

+Intel® EPID

+

Enhanced Privacy ID (Intel® EPID) is a cryptographic protocol for attestation of a trusted platform while preserving the user's privacy. Intel® EPID can be used as a foundational building block for a multitude of security solutions.

+

+Intel® EPID signature

+

An Intel® EPID signature is a type of digital signature that preserves anonymity of the signer, while still proving the signer is a member of a trusted group.

+

+Issuer

+

The issuer is the entity in the Intel® EPID scheme that is responsible for managing group membership. An example of an issuer is the Intel Key Generation Facility.

+

The issuer manages groups by doing the following:

+
    +
  • Creates groups by generating one issuing private key and one group certificate for each group. The group certificate contains the group public key.
  • +
  • Creates group members by generating unique Intel® EPID member private keys through bulk provisioning. Member private keys are created from the issuing private key for the group.
  • +
  • Manages requests from prospective members to join existing groups by using the join protocol.
  • +
  • Creates and maintains signature based revocation lists and private key based revocation lists. These lists of members no longer in good standing allow members to be dropped from a group.
  • +
  • Creates and maintains group revocation lists.
  • +
  • Makes group public keys and revocation lists available to verifiers.
  • +
+

+Issuing private key

+

The issuing private key is the key used by the issuer to generate unique private keys for each member of a given group. For every group public key, there is a corresponding issuing private key. The issuing private key remains with the issuer and is kept private.

+

+Member

+

The member is the entity that attempts to prove its group membership to the verifier. Members are authorized by the issuer as part of a group and each group member has a unique Intel® EPID private key. The member uses its member private key to sign a message to prove group membership without revealing its identity. An example of a member is a PC with an embedded Intel® EPID member private key.

+

+Name-based signature

+

A name-based signature is a type of signature that gives the verifier the ability to link Intel® EPID signatures from the same member, reducing the member's privacy.

+

A name-based signature is created using the additional parameter of a basename. If a basename is not specified, a random number is chosen as the basename. If the member uses the same basename, the verifier can mathematically link signatures generated by the member, showing that the signatures are from the same member.

+

+Member private key

+

The member private key is the key used by the member to digitally sign a message when attempting to prove to the verifier that the member belongs to the group and is in good standing.

+

Unique member private keys are generated by the issuer for each member of a given group. The same group public key corresponds to each member private key in the group.

+

+Non-revoked proof

+

A non-revoked proof is part of an Intel® EPID signature that proves that the member is not a specific revoked entity in the signature based revocation list. The member provides the signature with a number of non-revoked proofs, one per revocation list entry, to prove to the verifier that the member does not correspond to any entry in the revocation list.

+

+Pairing

+

Pairing is a mathematical operation that maps two elliptic curve groups to a third multiplicative group.

+

+Revocation, revocation lists

+

Revocation lists are data structures used by the verifier to identify members that are no longer approved members of the group.

+

The verifier obtains the member private key based revocation list (PrivRL), signature based revocation list (SigRL), and group based revocation list (GroupRL) from the issuer. The verifier can also maintain its own verifier blacklist (VerifierRL).

+

+Verifier

+

The verifier is the entity that checks an Intel® EPID signature to establish whether it was signed by an entity or device that is a member in good standing.

+

The verifier acts on behalf of a party that needs to know it is communicating with a trusted device. Verifiers obtain group certificates and revocation lists from issuers and negotiate details of signature protocol with members.

+
+
+ + + + + diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/ImplementationNotes.html b/sgx-jvm/linux-sgx/external/epid/doc/html/ImplementationNotes.html new file mode 100644 index 0000000000..c8a9555422 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/ImplementationNotes.html @@ -0,0 +1,110 @@ + + + + + + + +Intel® Enhanced Privacy ID SDK: Implementation Notes + + + + + + + + + + + + +
+
+ + + + + + +
+ +
+
+ + +
+
+ +
+
+
+ +
+
+
+
Implementation Notes
+
+
+ +

+Random Number Generation

+

Some SDK APIs require a random number data source. A BitSupplier provides a source of random data. This function should be a cryptographically secure random number generator.

+
Warning
The pseudo-random number generator provided with the examples is for sample use only and is not suitable for cryptographically secure applications.
+

+Protecting Secrets

+

Member code works with private keys, so member code must be run in a trusted environment.

+
Warning
If member memory is available to an untrusted source, the member private key could be exposed.
+

The EpidZeroMemory function is used by the memory allocation routines EpidAlloc, EpidRealloc and EpidFree to wipe the memory as memory is freed.

+
Warning
The EpidZeroMemory function may be optimized away by some compilers. If it is, you should consider using a compiler or operating system specific memory sanitization function (e.g. memcpy_s or SecureZeroMemory).
+

+Replacing Math Primitives

+

SDK math primitives are designed to be replaced with your own implementation if you need to rely on custom hardware for performance. The SDK is designed to simplify this process by isolating implementation details behind a clearly defined interface, defined by the non-internal headers the epid/common/math directory. Math functionality has detailed tests to ease validation.

+

+Octstring/Buffer Types

+

Serialized information in the SDK is passed in fixed size buffer types whenever possible. Collectively these fixed size buffer types are called Octstrings.

+

In epid/common/types.h, there are a large number of packed structs that contain other packed structs, which eventually contain OctStr* types. Normally these are named *Str and are refered to as Str types.

+

OctStr* types are buffers that hold N bits, where N is the number at the end of the type name. These types usually represent numbers in a Big Endian format (buffer[0] is the most significant value).

+

Str types generally represent fixed size groups of numbers such as a point or vector.

+

OctStr* and Str types are usually populated by reading a buffer from a file or other storage, or by calling a serialize function. OctStr* and Str types must be packed so that the compiler does not insert padding. In the current code, this is done using pragmas.

+
#pragma pack(1)
// OctStr* type holding 256 bits
typedef struct OctStr256 {
unsigned char data[256 / CHAR_BIT];
// Str type consisting of a single 256 bit number
typedef struct FqElemStr {
// Str type consisting of a two other Str types
typedef struct G1ElemStr {

Many APIs use void* parameters where OctStr* types are expected. If more than one size is allowed, a size parameter is usually also required.

+

+Flexible Arrays

+

A common idiom in the SDK is the use of flexible array types. These types are structs with the last element being an array of size 1 of some type. Flexible array types always have a size value embedded in the struct. The name of the count and array fields differs between flexible array types.

+
typedef struct Sample {
OctStr32 data;
OctStr32 count;
G1ElemStr array[1];
} Sample;

Flexible array types are expected to be in a buffer of size sizeof(FA) + ((N-1) * sizeof(E)) where FA is the flexible array type, N is the number of elements in the array and E is the type of each element. Note that this may be smaller than sizeof(FA) if N is 0, in which case referencing any element is an error.

+
Sample* AllocSample(size_t count) {
return (Sample*)malloc(sizeof(Sample)
+ (count * sizeof(G1ElemStr))
- sizeof(G1ElemStr));
}

In many cases, functions that accept flexible array types will also expect a buffer size that is compared against the computed size of the array as a sanity check.

+
+
+ + + + + diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/IssuerMaterial.html b/sgx-jvm/linux-sgx/external/epid/doc/html/IssuerMaterial.html new file mode 100644 index 0000000000..67d8ab03d0 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/IssuerMaterial.html @@ -0,0 +1,136 @@ + + + + + + + +Intel® Enhanced Privacy ID SDK: Sample Issuer Material + + + + + + + + + + + + +
+
+ + + + + + +
+ +
+
+ + +
+
+ +
+
+
+ +
+
+
+
Sample Issuer Material
+
+
+ +

Because the SDK does not include issuer APIs, pre-generated sample data is included for validation purposes.

+
Note
Sample compressed key material is not included in the package.
+

+Sample Groups

+

Issuers create groups and manage group membership. For each group, the issuer creates a group public key simultaneously with the corresponding issuing private key. The issuer uses the issuing private key to create unique member private keys for each group member, and makes the group public key available to verifiers.

+

All groups have the following:

+
    +
  • Group public key, which corresponds to the issuing private key kept by the issuer
  • +
  • Signature based revocation list
  • +
  • Private key based revocation list
  • +
  • Member private keys, generated from the issuing private key
  • +
+

If a signature based revocation list or private key based revocation list does not exist, it is assumed to be empty.

+

+groupa

+

There are eight members in groupa:

+
    +
  • groupa/member0 - A non-revoked member.
  • +
  • groupa/member1 - Another non-revoked member.
  • +
  • groupa/privrevokedmember0 - A revoked member. Revoked by Private-Key based revocation list (groupa/privrl.bin)
  • +
  • groupa/privrevokedmember1 - A revoked member. Revoked by Private-Key based revocation list (groupa/privrl.bin)
  • +
  • groupa/privrevokedmember2 - A revoked member. Revoked by Private-Key based revocation list (groupa/privrl.bin)
  • +
  • groupa/sigrevokedmember0 - A revoked member. Revoked by Signature based revocation list (groupa/sigrl.bin)
  • +
  • groupa/sigrevokedmember1 - A revoked member. Revoked by Signature based revocation list (groupa/sigrl.bin)
  • +
  • groupa/sigrevokedmember2 - A revoked member. Revoked by Signature based revocation list (groupa/sigrl.bin)
  • +
+

The following are groupa revocation lists:

+
    +
  • groupa/privrl.bin - Private-Key based revocation list. privrevokedmember0, privrevokedmember1 and privrevokedmember2** revoked.
  • +
  • groupa/sigrl.bin - Signature based revocation list. sigrevokedmember0, sigrevokedmember0 and sigrevokedmember0** revoked.
  • +
+

+groupb

+

There are four members in groupb:

+
    +
  • groupb/member0 - A non-revoked member.
  • +
  • groupb/member1 - Another non-revoked member.
  • +
  • groupb/privrevokedmember0 - A revoked member. Revoked by Private-Key based revocation list (groupb/privrl.bin)
  • +
  • groupb/sigrevokedmember0 - A revoked member. Revoked by Signature based revocation list (groupb/sigrl.bin)
  • +
+

The following are groupb revocation lists:

+
    +
  • groupb/privrl.bin - Private-Key based revocation list. privrevokedmember0 revoked.
  • +
  • groupb/sigrl.bin - Signature based revocation list. sigrevokedmember0 revoked.
  • +
+

+Group Based Revocation Lists

+

If an entire group is no longer valid, the issuer can revoke it using the group based revocation list. Two sample group based revocation lists are provided with the SDK.

+
    +
  • grprl_empty.bin - No entries
  • +
  • grprl.bin - One entry in which groupb is revoked.
  • +
+
+
+ + + + + diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/LegalInformation.html b/sgx-jvm/linux-sgx/external/epid/doc/html/LegalInformation.html new file mode 100644 index 0000000000..959bf33c6c --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/LegalInformation.html @@ -0,0 +1,84 @@ + + + + + + + +Intel® Enhanced Privacy ID SDK: Legal Information + + + + + + + + + + + + +
+
+ + + + + + +
+ +
+
+ + +
+
+ +
+
+
+ +
+
+
+
Legal Information
+
+
+

INFORMATION IN THIS DOCUMENT IS PROVIDED IN CONNECTION WITH INTEL® PRODUCTS. NO LICENSE, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, TO ANY INTELLECTUAL PROPERTY RIGHTS IS GRANTED BY THIS DOCUMENT. EXCEPT AS PROVIDED IN INTEL'S TERMS AND CONDITIONS OF SALE FOR SUCH PRODUCTS, INTEL ASSUMES NO LIABILITY WHATSOEVER, AND INTEL DISCLAIMS ANY EXPRESS OR IMPLIED WARRANTY, RELATING TO SALE AND/OR USE OF INTEL PRODUCTS INCLUDING LIABILITY OR WARRANTIES RELATING TO FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABILITY, OR INFRINGEMENT OF ANY PATENT, COPYRIGHT OR OTHER INTELLECTUAL PROPERTY RIGHT.

+

UNLESS OTHERWISE AGREED IN WRITING BY INTEL, THE INTEL PRODUCTS ARE NOT DESIGNED NOR INTENDED FOR ANY APPLICATION IN WHICH THE FAILURE OF THE INTEL PRODUCT COULD CREATE A SITUATION WHERE PERSONAL INJURY OR DEATH MAY OCCUR.

+

Intel may make changes to specifications and product descriptions at any time, without notice. Designers must not rely on the absence or characteristics of any features or instructions marked "reserved" or "undefined." Intel reserves these for future definition and shall have no responsibility whatsoever for conflicts or incompatibilities arising from future changes to them. The information here is subject to change without notice. Do not finalize a design with this information.

+

The products described in this document may contain design defects or errors known as errata which may cause the product to deviate from published specifications. Current characterized errata are available on request.

+

Contact your local Intel sales office or your distributor to obtain the latest specifications and before placing your product order.

+

Copies of documents which have an order number and are referenced in this document, or other Intel literature, may be obtained by calling 1-800-548-4725, or by visiting Intel's web site http://www.intel.com.

+

Intel and the Intel logo are trademarks of Intel Corporation in the U.S. and other countries.

+

*Other names and brands may be claimed as the property of others.

+
+
+ + + + + diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/SdkOverview.html b/sgx-jvm/linux-sgx/external/epid/doc/html/SdkOverview.html new file mode 100644 index 0000000000..b9432dfdda --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/SdkOverview.html @@ -0,0 +1,163 @@ + + + + + + + +Intel® Enhanced Privacy ID SDK: What's Included in the SDK + + + + + + + + + + + + +
+
+ + + + + + +
+ +
+
+ + +
+
+ +
+
+
+ +
+
+
+
What's Included in the SDK
+
+
+ +

+SDK Components

+

The SDK is divided into logical components to separate responsibilities and create interfaces that you can re-implement using custom tools such as hardware accelerators.

+
+sdk_block_diagram.png +
+


+ The Intel® EPID SDK is divided into the following components:

+ + + + + + + + + + + + + + + + + + + + + + + + + +
Component Description
member Library containing APIs needed to implement a member
verifier Library containing APIs needed to implement a verifier
common Library containing common types and functions
math Math primitives used by member and verifier
IPP A C-only non-optimized subset of Intel® IPP
signmsg A sample program showing how to sign messages
verfifysig A sample program showing how to verify signatures
util Common utilities used by samples
gtest gtest unit test framework
Build Scripts Scripts to configure and build the SDK
Sample Issuer Material Sample keys and revocation lists
+

Math primitives are implemented in the math sub-component of common. The reference math primitive implementation is based on a non-optimized Vanilla C subset of the Intel® Performance Primitives. Math is designed so that you can replace its implementation to call custom hardware IP blocks or optimized libraries.

+

+Filesystem Layout

+

The Intel® EPID SDK has two filesystem layouts: the Source Layout and the Install Layout.

+

The Source Layout is what you find when you download the SDK and extract it to disk. This layout contains all of the files that you need to build the libraries, samples, tests, and data generated by the SDK.

+

The Install Layout is the layout of files under the _install folder after you build the SDK.

+

+Source Layout

+

The Source Layout is used by the build scripts in the Intel® EPID SDK to find components and files needed to create libraries and executables.

epid-sdk/
+|__ LICENSE.txt             Distribution license
+|__ NOTICE.txt              Legal notices
+|__ README.md               Readme
+|__ RELEASE_NOTES.md        Release notes
+|__ SConstruct              Main build configuration
+|
+|__ doc/
+|   |__ html/               HTML format documentation
+|   |__ index.html          Entry point for HTML format documentation
+|
+|__ epid/
+|   |__ common/             Source for Common
+|   |__ common-testhelper/  Source for unit test helper common helpers
+|   |__ member/             Source for Member
+|   |__ verifier/           Source for Verifier
+|
+|__ example/
+|   |__ data/               Binary data used for testing and tutorials
+|   |__ signmsg/            Source for message signing example
+|   |__ util/               Common utilities for examples
+|   |__ verifysig/          Source for signature validation signing example
+|
+|__ ext/
+|   |__ gtest/             Third party gtest library
+|   |__ ipp/               IPP library
+|
+|__ parts-site/            Parts platform config scripts
+

+Install Layout

+

The Install Layout contains the data developers need to develop and build their applications using the Intel® EPID SDK. Once built, the Install Layout has no dependency on the Source Layout, allowing developers to build the SDK once and reuse the built files in other locations or on other computers.

_install/
+|__ epid-sdk/
+    |__ include/            C include header files for the SDK
+    |__ lib/
+    |   |__ <platform>      Target specific static libraries for the SDK
+    |
+    |__example/             Sample applications and data
+    |__test/                Unit test executables (if unit tests built)
+
+ + + + + diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/SignVerifyTutorial.html b/sgx-jvm/linux-sgx/external/epid/doc/html/SignVerifyTutorial.html new file mode 100644 index 0000000000..3aca35d6f5 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/SignVerifyTutorial.html @@ -0,0 +1,192 @@ + + + + + + + +Intel® Enhanced Privacy ID SDK: Signing and Verification Tutorial + + + + + + + + + + + + +
+
+ + + + + + +
+ +
+
+ + +
+
+ +
+
+
+ +
+
+
+
Signing and Verification Tutorial
+
+
+ +

The Intel® EPID SDK provides example tools to show you how to use the Intel® EPID SDK APIs. These examples are called signmsg and verifysig.

+

You can build these examples using the instructions in Building From Source. The tutorial assumes _install/epid-sdk/example is the current directory.

+

All command lines in this tutorial use posix command line conventions; for other systems, adjust accordingly.

+

For the code used in this tutorial, refer to Examples.

+
Note
The data for running this tutorial is pre-generated. Once the samples are built, the data is in the _install/epid-sdk/example/data directory. See Sample Issuer Material.
+

+Creating an Intel® EPID Signature of a Given Message

+

The example application signmsg shows you how to create an Intel® EPID Signature of a given message.

$ ./signmsg -h
+Usage: signmsg [OPTION]...
+Create Intel(R) EPID signature of message
+
+Options:
+
+--sig=FILE            write signature to FILE (default: sig.dat)
+--msg=MESSAGE         MESSAGE to sign
+--bsn=BASENAME        BASENAME to sign with (default: random)
+--sigrl=FILE          load signature based revocation list from FILE
+--gpubkey=FILE        load group public key from FILE
+                        (default: pubkey.bin)
+--mprivkey=FILE       load member private key from FILE
+                        (default: mprivkey.dat)
+--mprecmpi=FILE       load pre-computed member data from FILE
+--mprecmpo=FILE       write pre-computed member data to FILE
+--hashalg=NAME        SHA-256 | SHA-384 | SHA-512 (default: SHA-512)
+--capubkey=FILE       load IoT Issuing CA public key from FILE
+                        (default: cacert.bin)
+-h,--help             display this help and exit
+-v,--verbose          print status messages to stdout
+

To sign a message, a group member in good standing uses the following command:

$ ./signmsg --msg="test0"
+

The above command signs a message "test0". signmsg uses default options for the group public key, member private key, and hash algorithm (SHA-512). All other parameters that are not given are ignored. The command produces a signature file: sig.dat

+

+Verifying an Intel® EPID Signature

+

The example application verifysig shows you how to verify that a given Intel® EPID Signature is produced by a member in good standing.

$ ./verifysig -h
+Usage: verifysig [OPTION]...
+Verify signature was created by group member in good standing
+
+Options:
+
+--sig=FILE            load signature from FILE (default: sig.dat)
+--msg=MESSAGE         MESSAGE that was signed (default: empty)
+--bsn=BASENAME        BASENAME used in signature (default: random)
+--privrl=FILE         load private key based revocation list from FILE
+--sigrl=FILE          load signature based revocation list from FILE
+--grprl=FILE          load group revocation list from FILE
+                        (default: grprl.bin)
+--verifierrl=FILE     load verifier revocation list from FILE
+--gpubkey=FILE        load group public key from FILE (default: pubkey.bin)
+--vprecmpi=FILE       load pre-computed verifier data from FILE
+--vprecmpo=FILE       write pre-computed verifier data to FILE
+--hashalg=NAME        SHA-256 | SHA-384 | SHA-512 (default: SHA-512)
+--capubkey=FILE       load IoT Issuing CA public key from FILE
+                        (default: cacert.bin)
+-h,--help             display this help and exit
+-v,--verbose          print status messages to stdout
+

To verify that a signature is from a member in good standing, the verifier uses the following command:

$ ./verifysig --msg="test0"
+signature verified successfully
+

This verifies that the default signature file sig.dat is generated for the message "test0" by a member in good standing. verifysig uses default inputs for group public key and hash algorithm (SHA-512). All other parameters are ignored. The output verifysig: signature verified successfully denotes that the verification is successful.

+

+Linking Intel® EPID Signatures from the Same Member

+

A name-based signature is a type of signature that gives the verifier the ability to link Intel® EPID signatures from the same member, reducing the member's privacy.

+

The verifier can ask the member to sign a message with a basename that the verifier chooses. If the member uses the name-based signature option (i.e., in cases where a basename is specified), then all the signatures created by the member using the same basename are linkable by the verifier.

+
Warning
The use of a name-based signature creates a platform unique pseudonymous identifier. Because it reduces the member's privacy, the user should be notified when it is used and should have control over its use.
+

A name-based signature is created using the additional parameter of a basename. If the member uses the same basename, the verifier can mathematically link signatures generated by the member, showing that the signatures are from the same member.

+

If basename is not provided, then the member uses a random basename and the signature generated by the member is anonymous.

+

To Sign message "test0" with a basename "base0":

$ ./signmsg --msg="test0" --bsn="base0"
+

To verify the signature:

$ ./verifysig --msg="test0" --bsn="base0"
+verifysig: signature verified successfully
+

+Expected Failures

+

The signature verification process fails if there is a parameter mismatch between sign and verify operations. Here are some examples.

+

Verification fails if there is a mismatch in the message:

$ ./signmsg --msg="test0"
+$ ./verifysig --msg="test1"
+verifysig: signature verification failed: invalid signature
+

Verification fails if there is a mismatch in the basename:

$ ./signmsg --msg="test0" --bsn="base0"
+$ ./verifysig --msg="test0" --bsn="base1"
+verifysig: signature verification failed: invalid signature
+

The Intel® EPID SDK supports the following hash algorithms: SHA-256, SHA-384, SHA-512. The selected hash algorithm must be the same for both sign and verify. Mismatch in hash algorithm results in verification failure:

$ ./signmsg --msg="test0" --hashalg=SHA-256
+$ ./verifysig --msg="test0" --hashalg=SHA-384
+verifysig: signature verification failed: invalid signature
+

+Revocation

+

Revocation lists are data structures used by the verifier to identify members that are no longer approved members of the group.

+

The verifier obtains the member private key based revocation list (PrivRL), signature based revocation list (SigRL), and group based revocation list (GroupRL) from the issuer. The verifier can also maintain its own verifier blacklist (VerifierRL).

+

+Detecting Revoked Group from Group Revocation List

+

Verification of a signature fails if it is generated by a member of a group that is revoked in the group revocation list.

+

For example,

$ ./signmsg --msg="test0" --gpubkey=data/groupb/pubkey.bin --mprivkey=data/groupb/member0/mprivkey.dat
+$ ./verifysig --msg="test0" --grprl=data/grprl.bin --gpubkey=data/groupb/pubkey.bin
+verifysig: signature verification failed: signature revoked in GroupRl
+

The verification fails because groupb is revoked and is an entry in the group revocation list (grprl.bin).

+

+Detecting Revoked Member from Private Key Based Revocation List

+

Verification of a signature fails if it is generated by a member whose private key is revoked in a private-key based revocation list.

+

For example,

$ ./signmsg --msg=test0 --gpubkey=data/groupa/pubkey.bin --mprivkey=data/groupa/privrevokedmember0/mprivkey.dat
+$ ./verifysig --msg=test0 --privrl=data/groupa/privrl.bin --gpubkey=data/groupa/pubkey.bin
+verifysig: signature verification failed: signature revoked in PrivRl
+

The verification fails because the private key of privrevokedmember0 is revoked and is an entry in the private key based revocation list of groupa (privrl.bin).

+

+Detecting Revoked Member from Signature Based Revocation List

+

Verification of a signature fails if it is generated by a member whose signature is revoked in a signature based revocation list.

$ ./signmsg --msg="test1" --sigrl=data/groupa/sigrl.bin --gpubkey=data/groupa/pubkey.bin --mprivkey=data/groupa/sigrevokedmember0/mprivkey.dat
+signmsg: signature revoked in SigRL
+$ ./verifysig --msg="test1" --sigrl=data/groupa/sigrl.bin --gpubkey=data/groupa/pubkey.bin
+verifysig: signature verification failed: signature revoked in SigRl
+

The message "test1" is signed by signmsg with a warning signmsg: signature revoked in SigRL. This means that the signature of sigrevokedmember0 is revoked in the signature based revocation list. The verification fails because the signature was generated by sigrevokedmember0, which is revoked and is an entry in the signature based revocation list of groupa (sigrl.bin).

+
+
+ + + + + diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/annotated.html b/sgx-jvm/linux-sgx/external/epid/doc/html/annotated.html new file mode 100644 index 0000000000..3fbd0796d1 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/annotated.html @@ -0,0 +1,136 @@ + + + + + + + +Intel® Enhanced Privacy ID SDK: Data Structures + + + + + + + + + + + + +
+
+ + + + + + +
+ +
+
+ + +
+
+ +
+
+
+ +
+
+
+
Data Structures
+
+
+
Here are the data structures with brief descriptions:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
 CAllowedBasenameInternal implementation of base name
 CBasicSignatureIntel(R) EPID 2.0 basic signature
 CBigNumStrSerialized BigNum
 CCommitValuesStorage for values to create commitment in Sign and Verify algorithms
 CCompressedPrivKeyCompressed private key
 CEcdsaPrivateKeyECDSA Private Key
 CEcdsaPublicKeyECDSA Public Key
 CEcdsaSignatureECDSA Signature using NIST 256-bit curve secp256r1
 CEpid2ParamsIntel(R) EPID 2.0 Parameters
 CEpid2Params_Internal representation of Epid2Params
 CEpidCaCertificateIoT CA Certificate binary format
 CEpidFileHeaderIntel(R) EPID binary file header
 CEpidGroupPubKeyCertificateIntel(R) EPID 2.0 Group Public Key binary format
 CEpidSignatureIntel(R) EPID 2.0 Signature
 CErrorTextEntryRecord mapping status code to string
 CFpElemStrNumber in [0, p-1]
 CFq12ElemDatData for element in Fq2^3^2
 CFq12ElemStrSerialized Fq2^3^2 element
 CFq2ElemDatData for element in Fq2
 CFq2ElemStrSerialized Fq2 element
 CFq6ElemDatData for element in Fq2^3
 CFq6ElemStrSerialized Fq2^3 element
 CFqElemDatData for element in Fq
 CFqElemStrNumber in [0, q-1]
 CG1ElemStrSerialized G1 element
 CG2ElemStrSerialized G2 element
 CGroupPubKeyIntel(R) EPID 2.0 group public key
 CGroupPubKey_Internal representation of GroupPubKey
 CGroupRlGroup revocation list
 CGtElemStrSerialized GT element
 CIPrivKeyIntel(R) EPID 2.0 issuing private key
 CJoinPCommitValuesStorage for values to create commitment in Sign and Verify algorithms
 CJoinRequestJoin request
 CMemberCtxMember context definition
 CMemberPrecompPre-computed member settings
 CMembershipCredentialMembership credential
 CNrProofNon-revoked Proof
 CNrVerifyCommitValuesStorage for values to create commitment in NrProve algorithm
 COctStr128128 bit octet string
 COctStr1616 bit octet string
 COctStr256256 bit octet string
 COctStr3232 bit octet string
 COctStr512512 bit octet string
 COctStr6464 bit octet string
 COctStr88 bit octet string
 CPreComputedSignaturePre-computed signature
 CPrivKeyIntel(R) EPID 2.0 private key
 CPrivKey_Internal implementation of PrivKey
 CPrivRlPrivate-key based revocation list
 CSha256DigestSHA256 digest
 CSigRlSignature based revocation list
 CSigRlEntryEntry in SigRL (B,K)
 CStackInternal representation of a Stack
 CVerifierCtxVerifier context definition
 CVerifierPrecompPre-computed member settings
 CVerifierRl
+
+
+
+ + + + + diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/arrowdown.png b/sgx-jvm/linux-sgx/external/epid/doc/html/arrowdown.png new file mode 100644 index 0000000000..0b63f6d38c Binary files /dev/null and b/sgx-jvm/linux-sgx/external/epid/doc/html/arrowdown.png differ diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/arrowright.png b/sgx-jvm/linux-sgx/external/epid/doc/html/arrowright.png new file mode 100644 index 0000000000..c6ee22f937 Binary files /dev/null and b/sgx-jvm/linux-sgx/external/epid/doc/html/arrowright.png differ diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/basicdoc.png b/sgx-jvm/linux-sgx/external/epid/doc/html/basicdoc.png new file mode 100644 index 0000000000..e092eb64db Binary files /dev/null and b/sgx-jvm/linux-sgx/external/epid/doc/html/basicdoc.png differ diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/bc_s.png b/sgx-jvm/linux-sgx/external/epid/doc/html/bc_s.png new file mode 100644 index 0000000000..224b29aa98 Binary files /dev/null and b/sgx-jvm/linux-sgx/external/epid/doc/html/bc_s.png differ diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/bdwn.png b/sgx-jvm/linux-sgx/external/epid/doc/html/bdwn.png new file mode 100644 index 0000000000..940a0b9504 Binary files /dev/null and b/sgx-jvm/linux-sgx/external/epid/doc/html/bdwn.png differ diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/bignum_8c.html b/sgx-jvm/linux-sgx/external/epid/doc/html/bignum_8c.html new file mode 100644 index 0000000000..4ad4279bec --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/bignum_8c.html @@ -0,0 +1,120 @@ + + + + + + + +Intel® Enhanced Privacy ID SDK: epid/common/math/bignum.c File Reference + + + + + + + + + + + + +
+
+ + + + + + +
+ +
+
+ + +
+
+ +
+
+
+ +
+
+ +
+
bignum.c File Reference
+
+
+ +

Big number implementation. +More...

+
#include "epid/common/math/bignum.h"
+#include "epid/common/math/bignum-internal.h"
+#include "epid/common/memory.h"
+#include "ext/ipp/include/ippcp.h"
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Functions

EpidStatus NewBigNum (size_t data_size_bytes, BigNum **bignum)
 Constructs a new BigNum. More...
 
void DeleteBigNum (BigNum **bignum)
 Deletes a previously allocated BigNum. More...
 
EpidStatus ReadBigNum (void const *bn_str, size_t strlen, BigNum *bn)
 Deserializes a BigNum from a string. More...
 
EpidStatus WriteBigNum (BigNum const *bn, size_t strlen, void const *bn_str)
 Serializes a BigNum to a string. More...
 
+int OctStr2Bnu (uint32_t *bnu_ptr, void const *octstr_ptr, int octstr_len)
 convert octet string into "big number unsigned" representation
 
EpidStatus BigNumAdd (BigNum const *a, BigNum const *b, BigNum *r)
 Adds two BigNum values. More...
 
EpidStatus BigNumSub (BigNum const *a, BigNum const *b, BigNum *r)
 Subtracts two BigNum values. More...
 
EpidStatus BigNumMul (BigNum const *a, BigNum const *b, BigNum *r)
 Multiplies two BigNum values. More...
 
EpidStatus BigNumMod (BigNum const *a, BigNum const *b, BigNum *r)
 Computes modular reduction for BigNum value by specified modulus. More...
 
+

Detailed Description

+

Big number implementation.

+
+
+ + + + + diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/bignum_8h.html b/sgx-jvm/linux-sgx/external/epid/doc/html/bignum_8h.html new file mode 100644 index 0000000000..ac66718f6c --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/bignum_8h.html @@ -0,0 +1,124 @@ + + + + + + + +Intel® Enhanced Privacy ID SDK: epid/common/math/bignum.h File Reference + + + + + + + + + + + + +
+
+ + + + + + +
+ +
+
+ + +
+
+ +
+
+
+ +
+
+ +
+
bignum.h File Reference
+
+
+ +

Big number interface. +More...

+
#include <stddef.h>
+#include <stdint.h>
+#include "epid/common/errors.h"
+#include "epid/common/types.h"
+
+ + + + +

+Typedefs

+typedef struct BigNum BigNum
 Internal representation of large numbers.
 
+ + + + + + + + + + + + + + + + + + + + + + + + + +

+Functions

EpidStatus NewBigNum (size_t data_size_bytes, BigNum **bignum)
 Constructs a new BigNum. More...
 
void DeleteBigNum (BigNum **bignum)
 Deletes a previously allocated BigNum. More...
 
EpidStatus ReadBigNum (void const *bn_str, size_t strlen, BigNum *bn)
 Deserializes a BigNum from a string. More...
 
EpidStatus WriteBigNum (BigNum const *bn, size_t strlen, void const *bn_str)
 Serializes a BigNum to a string. More...
 
EpidStatus BigNumAdd (BigNum const *a, BigNum const *b, BigNum *r)
 Adds two BigNum values. More...
 
EpidStatus BigNumSub (BigNum const *a, BigNum const *b, BigNum *r)
 Subtracts two BigNum values. More...
 
EpidStatus BigNumMul (BigNum const *a, BigNum const *b, BigNum *r)
 Multiplies two BigNum values. More...
 
EpidStatus BigNumMod (BigNum const *a, BigNum const *b, BigNum *r)
 Computes modular reduction for BigNum value by specified modulus. More...
 
+

Detailed Description

+

Big number interface.

+
+
+ + + + + diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/bitsupplier_8h.html b/sgx-jvm/linux-sgx/external/epid/doc/html/bitsupplier_8h.html new file mode 100644 index 0000000000..c89b3b2043 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/bitsupplier_8h.html @@ -0,0 +1,92 @@ + + + + + + + +Intel® Enhanced Privacy ID SDK: epid/common/bitsupplier.h File Reference + + + + + + + + + + + + +
+
+ + + + + + +
+ +
+
+ + +
+
+ +
+
+
+ +
+
+ +
+
bitsupplier.h File Reference
+
+
+ +

Random data supplier interface. +More...

+ + + + + +

+Typedefs

typedef int(__STDCALL * BitSupplier) (unsigned int *rand_data, int num_bits, void *user_data)
 Generates random data. More...
 
+

Detailed Description

+

Random data supplier interface.

+
+
+ + + + + diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/building__sdk_8dox.html b/sgx-jvm/linux-sgx/external/epid/doc/html/building__sdk_8dox.html new file mode 100644 index 0000000000..6e2f6fe4bb --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/building__sdk_8dox.html @@ -0,0 +1,82 @@ + + + + + + + +Intel® Enhanced Privacy ID SDK: doc/docsrc/building_sdk.dox File Reference + + + + + + + + + + + + +
+
+ + + + + + +
+ +
+
+ + +
+
+ +
+
+
+ +
+
+
+
doc/docsrc/building_sdk.dox File Reference
+
+
+ +

This file is used by Doxygen to generate documentation. +More...

+

Detailed Description

+

This file is used by Doxygen to generate documentation.

+
+
+ + + + + diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/check__privrl__entry_8c.html b/sgx-jvm/linux-sgx/external/epid/doc/html/check__privrl__entry_8c.html new file mode 100644 index 0000000000..77506853ea --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/check__privrl__entry_8c.html @@ -0,0 +1,93 @@ + + + + + + + +Intel® Enhanced Privacy ID SDK: epid/verifier/check_privrl_entry.c File Reference + + + + + + + + + + + + +
+
+ + + + + + +
+ +
+
+ + +
+
+ +
+
+
+ +
+
+ +
+
check_privrl_entry.c File Reference
+
+
+ +

EpidCheckPrivRlEntry implementation. +More...

+ + + + + +

+Functions

EpidStatus EpidCheckPrivRlEntry (VerifierCtx const *ctx, BasicSignature const *sig, FpElemStr const *f)
 Verifies a signature has not been revoked in the private key based revocation list. More...
 
+

Detailed Description

+

EpidCheckPrivRlEntry implementation.

+
+
+ + + + + diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/classes.html b/sgx-jvm/linux-sgx/external/epid/doc/html/classes.html new file mode 100644 index 0000000000..1a92e1c897 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/classes.html @@ -0,0 +1,113 @@ + + + + + + + +Intel® Enhanced Privacy ID SDK: Data Structure Index + + + + + + + + + + + + +
+
+ + + + + + +
+ +
+
+ + +
+
+ +
+
+
+ +
+
+
+
Data Structure Index
+
+
+
A | B | C | E | F | G | I | J | M | N | O | P | S | V
+ + + + + + + + + + + + + + + + + + + + +
  A  
+
Epid2Params_   
  G  
+
MemberPrecomp   PrivKey   
EpidCaCertificate   MembershipCredential   PrivKey_   
AllowedBasename   EpidFileHeader   G1ElemStr   
  N  
+
PrivRl   
  B  
+
EpidGroupPubKeyCertificate   G2ElemStr   
  S  
+
EpidSignature   GroupPubKey   NrProof   
BasicSignature   ErrorTextEntry   GroupPubKey_   NrVerifyCommitValues   Sha256Digest   
BigNumStr   
  F  
+
GroupRl   
  O  
+
SigRl   
  C  
+
GtElemStr   SigRlEntry   
FpElemStr   
  I  
+
OctStr128   Stack   
CommitValues   Fq12ElemDat   OctStr16   
  V  
+
CompressedPrivKey   Fq12ElemStr   IPrivKey   OctStr256   
  E  
+
Fq2ElemDat   
  J  
+
OctStr32   VerifierCtx   
Fq2ElemStr   OctStr512   VerifierPrecomp   
EcdsaPrivateKey   Fq6ElemDat   JoinPCommitValues   OctStr64   VerifierRl   
EcdsaPublicKey   Fq6ElemStr   JoinRequest   OctStr8   
EcdsaSignature   FqElemDat   
  M  
+
  P  
+
Epid2Params   FqElemStr   
MemberCtx   PreComputedSignature   
+
A | B | C | E | F | G | I | J | M | N | O | P | S | V
+
+
+ + + + + diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/closed.png b/sgx-jvm/linux-sgx/external/epid/doc/html/closed.png new file mode 100644 index 0000000000..98cc2c909d Binary files /dev/null and b/sgx-jvm/linux-sgx/external/epid/doc/html/closed.png differ diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/commitment_8c.html b/sgx-jvm/linux-sgx/external/epid/doc/html/commitment_8c.html new file mode 100644 index 0000000000..13a543a28d --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/commitment_8c.html @@ -0,0 +1,98 @@ + + + + + + + +Intel® Enhanced Privacy ID SDK: epid/common/commitment.c File Reference + + + + + + + + + + + + +
+
+ + + + + + +
+ +
+
+ + +
+
+ +
+
+
+ +
+
+ +
+
commitment.c File Reference
+
+
+ +

Commitment hash implementation. +More...

+
#include <limits.h>
+#include "epid/common/commitment.h"
+#include "epid/common/memory.h"
+#include "epid/common/epid2params_ate.inc"
+
+ + + + + + + +

+Functions

EpidStatus SetCalculatedCommitValues (G1ElemStr const *B, G1ElemStr const *K, G1ElemStr const *T, EcPoint const *R1, EcGroup *G1, FfElement const *R2, FiniteField *GT, CommitValues *values)
 Set CommitValues structure fields calculated in algorithm. More...
 
EpidStatus CalculateCommitmentHash (CommitValues const *values, FiniteField *Fp, HashAlg hash_alg, void const *msg, size_t msg_len, FfElement *c)
 Calculate Fp.hash(t3 || m) for Sign and Verfiy algorithms. More...
 
+

Detailed Description

+

Commitment hash implementation.

+
+
+ + + + + diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/commitment_8h.html b/sgx-jvm/linux-sgx/external/epid/doc/html/commitment_8h.html new file mode 100644 index 0000000000..fc9e54f8c4 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/commitment_8h.html @@ -0,0 +1,108 @@ + + + + + + + +Intel® Enhanced Privacy ID SDK: epid/common/commitment.h File Reference + + + + + + + + + + + + +
+
+ + + + + + +
+ +
+
+ + +
+
+ +
+
+
+ +
+
+ +
+
commitment.h File Reference
+
+
+ +

Commitment hash interface. +More...

+ + + + + +

+Data Structures

struct  CommitValues
 Storage for values to create commitment in Sign and Verify algorithms. More...
 
+ + + + + + + + + + +

+Functions

EpidStatus SetKeySpecificCommitValues (GroupPubKey const *pub_key, CommitValues *values)
 Set group public key related fields from CommitValues structure. More...
 
EpidStatus SetCalculatedCommitValues (G1ElemStr const *B, G1ElemStr const *K, G1ElemStr const *T, EcPoint const *R1, EcGroup *G1, FfElement const *R2, FiniteField *GT, CommitValues *values)
 Set CommitValues structure fields calculated in algorithm. More...
 
EpidStatus CalculateCommitmentHash (CommitValues const *values, FiniteField *Fp, HashAlg hash_alg, void const *msg, size_t msg_len, FfElement *c)
 Calculate Fp.hash(t3 || m) for Sign and Verfiy algorithms. More...
 
+

Detailed Description

+

Commitment hash interface.

+
+
+ + + + + diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/decompress__privkey_8c.html b/sgx-jvm/linux-sgx/external/epid/doc/html/decompress__privkey_8c.html new file mode 100644 index 0000000000..b34aa82ea7 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/decompress__privkey_8c.html @@ -0,0 +1,124 @@ + + + + + + + +Intel® Enhanced Privacy ID SDK: epid/member/decompress_privkey.c File Reference + + + + + + + + + + + + +
+
+ + + + + + +
+ +
+
+ + +
+
+ +
+
+
+ +
+
+ +
+
decompress_privkey.c File Reference
+
+
+ +

EpidDecompressPrivKey implementation. +More...

+
#include "epid/member/api.h"
+#include "epid/common/memory.h"
+#include "epid/common/epid2params.h"
+#include "epid/common/math/bignum-internal.h"
+#include "epid/common/math/hash.h"
+#include "epid/member/privkey.h"
+
+ + + + +

+Macros

#define BREAK_ON_EPID_ERROR(ret)
 Handle Intel(R) EPID Error with Break. More...
 
+ + + + +

+Functions

EpidStatus EpidDecompressPrivKey (GroupPubKey const *pub_key, CompressedPrivKey const *compressed_privkey, PrivKey *priv_key)
 Decompresses compressed member private key. More...
 
+

Detailed Description

+

EpidDecompressPrivKey implementation.

+

Macro Definition Documentation

+ +
+
+ + + + + + + + +
#define BREAK_ON_EPID_ERROR( ret)
+
+Value:
if (kEpidNoErr != (ret)) { \
break; \
}
no error
Definition: errors.h:41
+
+

Handle Intel(R) EPID Error with Break.

+ +
+
+
+
+ + + + + diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/dir_02c945662023679b89476bd7126bc985.html b/sgx-jvm/linux-sgx/external/epid/doc/html/dir_02c945662023679b89476bd7126bc985.html new file mode 100644 index 0000000000..34c3526226 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/dir_02c945662023679b89476bd7126bc985.html @@ -0,0 +1,111 @@ + + + + + + + +Intel® Enhanced Privacy ID SDK: epid/verifier Directory Reference + + + + + + + + + + + + +
+
+ + + + + + +
+ +
+
+ + +
+
+ +
+
+
+ +
+
+
+
verifier Directory Reference
+
+
+ +

Verifier functionality.

+ +More...

+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+Files

file  api.h
 Intel(R) EPID SDK verifier API.
 
file  check_privrl_entry.c
 EpidCheckPrivRlEntry implementation.
 
file  context.c
 Verifier context implementation.
 
file  context.h
 Verifier context interface.
 
file  nrverify.c
 NrVerfy implementation.
 
file  sigs_linked.c
 AreSigsLinked implementation.
 
file  verify.c
 Verify implementation.
 
file  verifybasic.c
 VerifyBasicSig implementation.
 
+

Detailed Description

+

Verifier functionality.

+
+
+ + + + + diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/dir_12b90d9c027aaf878a834df729679a56.html b/sgx-jvm/linux-sgx/external/epid/doc/html/dir_12b90d9c027aaf878a834df729679a56.html new file mode 100644 index 0000000000..9031b5cc6b --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/dir_12b90d9c027aaf878a834df729679a56.html @@ -0,0 +1,96 @@ + + + + + + + +Intel® Enhanced Privacy ID SDK: epid Directory Reference + + + + + + + + + + + + +
+
+ + + + + + +
+ +
+
+ + +
+
+ +
+
+
+ +
+
+
+
epid Directory Reference
+
+
+ +

Core Intel® EPID functionality.

+ +More...

+ + + + + + + + + + + +

+Directories

directory  common
 Common code shared between core sub-components.
 
directory  member
 Member functionality.
 
directory  verifier
 Verifier functionality.
 
+

Detailed Description

+

Core Intel® EPID functionality.

+
+
+ + + + + diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/dir_512d3e62841a8535b716ec4cf8b9e950.html b/sgx-jvm/linux-sgx/external/epid/doc/html/dir_512d3e62841a8535b716ec4cf8b9e950.html new file mode 100644 index 0000000000..dd82485b94 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/dir_512d3e62841a8535b716ec4cf8b9e950.html @@ -0,0 +1,123 @@ + + + + + + + +Intel® Enhanced Privacy ID SDK: epid/member Directory Reference + + + + + + + + + + + + +
+
+ + + + + + +
+ +
+
+ + +
+
+ +
+
+
+ +
+
+
+
member Directory Reference
+
+
+ +

Member functionality.

+ +More...

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Files

file  api.h
 Intel(R) EPID SDK member API.
 
file  context.c
 Member context implementation.
 
file  context.h
 Member context interface.
 
file  decompress_privkey.c
 EpidDecompressPrivKey implementation.
 
file  get_sigsize.c
 EpidGetSigSize implementation.
 
file  nr_prove.c
 EpidNrProve implementation.
 
file  presig.c
 EpidComputePreSig implementation.
 
file  privkey.c
 Private key implementation.
 
file  privkey.h
 Private key private interface.
 
file  request_join.c
 EpidRequestJoin implementation.
 
file  sign.c
 EpidSign implementation.
 
file  signbasic.c
 EpidSignBasic implementation.
 
+

Detailed Description

+

Member functionality.

+
+
+ + + + + diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/dir_f169ebf8da29290a918fa4b3f7151050.html b/sgx-jvm/linux-sgx/external/epid/doc/html/dir_f169ebf8da29290a918fa4b3f7151050.html new file mode 100644 index 0000000000..7a85522717 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/dir_f169ebf8da29290a918fa4b3f7151050.html @@ -0,0 +1,132 @@ + + + + + + + +Intel® Enhanced Privacy ID SDK: epid/common/math Directory Reference + + + + + + + + + + + + +
+
+ + + + + + +
+ +
+
+ + +
+
+ +
+
+
+ +
+
+
+
math Directory Reference
+
+
+ +

Math primitives.

+ +More...

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Files

file  bignum.c
 Big number implementation.
 
file  bignum.h
 Big number interface.
 
file  ecdsa.h
 Ecdsa interface.
 
file  ecdsa_sign.c
 EcdsaSignBuffer implementation.
 
file  ecdsa_verify.c
 EcdsaVerifyBuffer implementation.
 
file  ecgroup.c
 Elliptic curve group implementation.
 
file  ecgroup.h
 Elliptic curve group interface.
 
file  finitefield.c
 Finite field implementation.
 
file  finitefield.h
 Finite field interface.
 
file  hash.h
 Hash primitives.
 
file  pairing.c
 Pairing implementation.
 
file  pairing.h
 Pairing interface.
 
file  printutils.c
 Print helper implementation.
 
file  printutils.h
 Print helper interface.
 
file  sha256.c
 SHA256 implementation.
 
+

Detailed Description

+

Math primitives.

+
+
+ + + + + diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/dir_f6bef457d5f671b6e774bfccc16651f6.html b/sgx-jvm/linux-sgx/external/epid/doc/html/dir_f6bef457d5f671b6e774bfccc16651f6.html new file mode 100644 index 0000000000..9ce1d0c21e --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/dir_f6bef457d5f671b6e774bfccc16651f6.html @@ -0,0 +1,156 @@ + + + + + + + +Intel® Enhanced Privacy ID SDK: epid/common Directory Reference + + + + + + + + + + + + +
+
+ + + + + + +
+ +
+
+ + +
+
+ +
+
+
+ +
+
+
+
common Directory Reference
+
+
+ +

Common code shared between core sub-components.

+ +More...

+ + + + + +

+Directories

directory  math
 Math primitives.
 
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Files

file  bitsupplier.h
 Random data supplier interface.
 
file  commitment.c
 Commitment hash implementation.
 
file  commitment.h
 Commitment hash interface.
 
file  endian_convert.h
 Endianness conversion interface.
 
file  epid2params.c
 Intel(R) EPID 2.0 constant parameters implementation.
 
file  epid2params.h
 Intel(R) EPID 2.0 constant parameters interface.
 
file  epid2params_ate.inc
 Intel(R) EPID 2.0 constant parameters data.
 
file  errors.c
 Error reporting implementation.
 
file  errors.h
 Error reporting.
 
file  file_parser.c
 Implementation of issuer material file parsing utilities.
 
file  file_parser.h
 Epid issuer material parsing utilities.
 
file  grouppubkey.c
 Group public key implementation.
 
file  grouppubkey.h
 Group public key interface.
 
file  memory.c
 Memory access implementation.
 
file  memory.h
 Memory access interface.
 
file  sigrlvalid.c
 SigRl validity checking implementation.
 
file  sigrlvalid.h
 SigRl validity checking interface.
 
file  stack.c
 Stack container implementation.
 
file  stack.h
 Stack container interface.
 
file  stdtypes.h
 C99 standard data types.
 
file  types.h
 SDK data types.
 
+

Detailed Description

+

Common code shared between core sub-components.

+
+
+ + + + + diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/doc.png b/sgx-jvm/linux-sgx/external/epid/doc/html/doc.png new file mode 100644 index 0000000000..17edabff95 Binary files /dev/null and b/sgx-jvm/linux-sgx/external/epid/doc/html/doc.png differ diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/doxygen.css b/sgx-jvm/linux-sgx/external/epid/doc/html/doxygen.css new file mode 100644 index 0000000000..1425ec530d --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/doxygen.css @@ -0,0 +1,1475 @@ +/* The standard CSS for doxygen 1.8.11 */ + +body, table, div, p, dl { + font: 400 14px/22px Roboto,sans-serif; +} + +/* @group Heading Levels */ + +h1.groupheader { + font-size: 150%; +} + +.title { + font: 400 14px/28px Roboto,sans-serif; + font-size: 150%; + font-weight: bold; + margin: 10px 2px; +} + +h2.groupheader { + border-bottom: 1px solid #879ECB; + color: #354C7B; + font-size: 150%; + font-weight: normal; + margin-top: 1.75em; + padding-top: 8px; + padding-bottom: 4px; + width: 100%; +} + +h3.groupheader { + font-size: 100%; +} + +h1, h2, h3, h4, h5, h6 { + -webkit-transition: text-shadow 0.5s linear; + -moz-transition: text-shadow 0.5s linear; + -ms-transition: text-shadow 0.5s linear; + -o-transition: text-shadow 0.5s linear; + transition: text-shadow 0.5s linear; + margin-right: 15px; +} + +h1.glow, h2.glow, h3.glow, h4.glow, h5.glow, h6.glow { + text-shadow: 0 0 15px cyan; +} + +dt { + font-weight: bold; +} + +div.multicol { + -moz-column-gap: 1em; + -webkit-column-gap: 1em; + -moz-column-count: 3; + -webkit-column-count: 3; +} + +p.startli, p.startdd { + margin-top: 2px; +} + +p.starttd { + margin-top: 0px; +} + +p.endli { + margin-bottom: 0px; +} + +p.enddd { + margin-bottom: 4px; +} + +p.endtd { + margin-bottom: 2px; +} + +/* @end */ + +caption { + font-weight: bold; +} + +span.legend { + font-size: 70%; + text-align: center; +} + +h3.version { + font-size: 90%; + text-align: center; +} + +div.qindex, div.navtab{ + background-color: #EBEFF6; + border: 1px solid #A3B4D7; + text-align: center; +} + +div.qindex, div.navpath { + width: 100%; + line-height: 140%; +} + +div.navtab { + margin-right: 15px; +} + +/* @group Link Styling */ + +a { + color: #3D578C; + font-weight: normal; + text-decoration: none; +} + +.contents a:visited { + color: #4665A2; +} + +a:hover { + text-decoration: underline; +} + +a.qindex { + font-weight: bold; +} + +a.qindexHL { + font-weight: bold; + background-color: #9CAFD4; + color: #ffffff; + border: 1px double #869DCA; +} + +.contents a.qindexHL:visited { + color: #ffffff; +} + +a.el { + font-weight: bold; +} + +a.elRef { +} + +a.code, a.code:visited, a.line, a.line:visited { + color: #4665A2; +} + +a.codeRef, a.codeRef:visited, a.lineRef, a.lineRef:visited { + color: #4665A2; +} + +/* @end */ + +dl.el { + margin-left: -1cm; +} + +pre.fragment { + border: 1px solid #C4CFE5; + background-color: #FBFCFD; + padding: 4px 6px; + margin: 4px 8px 4px 2px; + overflow: auto; + word-wrap: break-word; + font-size: 9pt; + line-height: 125%; + font-family: monospace, fixed; + font-size: 105%; +} + +div.fragment { + padding: 4px 6px; + margin: 4px 8px 4px 2px; + background-color: #FBFCFD; + border: 1px solid #C4CFE5; +} + +div.line { + font-family: monospace, fixed; + font-size: 13px; + min-height: 13px; + line-height: 1.0; + text-wrap: unrestricted; + white-space: -moz-pre-wrap; /* Moz */ + white-space: -pre-wrap; /* Opera 4-6 */ + white-space: -o-pre-wrap; /* Opera 7 */ + white-space: pre-wrap; /* CSS3 */ + word-wrap: break-word; /* IE 5.5+ */ + text-indent: -53px; + padding-left: 53px; + padding-bottom: 0px; + margin: 0px; + -webkit-transition-property: background-color, box-shadow; + -webkit-transition-duration: 0.5s; + -moz-transition-property: background-color, box-shadow; + -moz-transition-duration: 0.5s; + -ms-transition-property: background-color, box-shadow; + -ms-transition-duration: 0.5s; + -o-transition-property: background-color, box-shadow; + -o-transition-duration: 0.5s; + transition-property: background-color, box-shadow; + transition-duration: 0.5s; +} + +div.line:after { + content:"\000A"; + white-space: pre; +} + +div.line.glow { + background-color: cyan; + box-shadow: 0 0 10px cyan; +} + + +span.lineno { + padding-right: 4px; + text-align: right; + border-right: 2px solid #0F0; + background-color: #E8E8E8; + white-space: pre; +} +span.lineno a { + background-color: #D8D8D8; +} + +span.lineno a:hover { + background-color: #C8C8C8; +} + +div.ah, span.ah { + background-color: black; + font-weight: bold; + color: #ffffff; + margin-bottom: 3px; + margin-top: 3px; + padding: 0.2em; + border: solid thin #333; + border-radius: 0.5em; + -webkit-border-radius: .5em; + -moz-border-radius: .5em; + box-shadow: 2px 2px 3px #999; + -webkit-box-shadow: 2px 2px 3px #999; + -moz-box-shadow: rgba(0, 0, 0, 0.15) 2px 2px 2px; + background-image: -webkit-gradient(linear, left top, left bottom, from(#eee), to(#000),color-stop(0.3, #444)); + background-image: -moz-linear-gradient(center top, #eee 0%, #444 40%, #000 110%); +} + +div.classindex ul { + list-style: none; + padding-left: 0; +} + +div.classindex span.ai { + display: inline-block; +} + +div.groupHeader { + margin-left: 16px; + margin-top: 12px; + font-weight: bold; +} + +div.groupText { + margin-left: 16px; + font-style: italic; +} + +body { + background-color: white; + color: black; + margin: 0; +} + +div.contents { + margin-top: 10px; + margin-left: 12px; + margin-right: 8px; +} + +td.indexkey { + background-color: #EBEFF6; + font-weight: bold; + border: 1px solid #C4CFE5; + margin: 2px 0px 2px 0; + padding: 2px 10px; + white-space: nowrap; + vertical-align: top; +} + +td.indexvalue { + background-color: #EBEFF6; + border: 1px solid #C4CFE5; + padding: 2px 10px; + margin: 2px 0px; +} + +tr.memlist { + background-color: #EEF1F7; +} + +p.formulaDsp { + text-align: center; +} + +img.formulaDsp { + +} + +img.formulaInl { + vertical-align: middle; +} + +div.center { + text-align: center; + margin-top: 0px; + margin-bottom: 0px; + padding: 0px; +} + +div.center img { + border: 0px; +} + +address.footer { + text-align: right; + padding-right: 12px; +} + +img.footer { + border: 0px; + vertical-align: middle; +} + +/* @group Code Colorization */ + +span.keyword { + color: #008000 +} + +span.keywordtype { + color: #604020 +} + +span.keywordflow { + color: #e08000 +} + +span.comment { + color: #800000 +} + +span.preprocessor { + color: #806020 +} + +span.stringliteral { + color: #002080 +} + +span.charliteral { + color: #008080 +} + +span.vhdldigit { + color: #ff00ff +} + +span.vhdlchar { + color: #000000 +} + +span.vhdlkeyword { + color: #700070 +} + +span.vhdllogic { + color: #ff0000 +} + +blockquote { + background-color: #F7F8FB; + border-left: 2px solid #9CAFD4; + margin: 0 24px 0 4px; + padding: 0 12px 0 16px; +} + +/* @end */ + +/* +.search { + color: #003399; + font-weight: bold; +} + +form.search { + margin-bottom: 0px; + margin-top: 0px; +} + +input.search { + font-size: 75%; + color: #000080; + font-weight: normal; + background-color: #e8eef2; +} +*/ + +td.tiny { + font-size: 75%; +} + +.dirtab { + padding: 4px; + border-collapse: collapse; + border: 1px solid #A3B4D7; +} + +th.dirtab { + background: #EBEFF6; + font-weight: bold; +} + +hr { + height: 0px; + border: none; + border-top: 1px solid #4A6AAA; +} + +hr.footer { + height: 1px; +} + +/* @group Member Descriptions */ + +table.memberdecls { + border-spacing: 0px; + padding: 0px; +} + +.memberdecls td, .fieldtable tr { + -webkit-transition-property: background-color, box-shadow; + -webkit-transition-duration: 0.5s; + -moz-transition-property: background-color, box-shadow; + -moz-transition-duration: 0.5s; + -ms-transition-property: background-color, box-shadow; + -ms-transition-duration: 0.5s; + -o-transition-property: background-color, box-shadow; + -o-transition-duration: 0.5s; + transition-property: background-color, box-shadow; + transition-duration: 0.5s; +} + +.memberdecls td.glow, .fieldtable tr.glow { + background-color: cyan; + box-shadow: 0 0 15px cyan; +} + +.mdescLeft, .mdescRight, +.memItemLeft, .memItemRight, +.memTemplItemLeft, .memTemplItemRight, .memTemplParams { + background-color: #F9FAFC; + border: none; + margin: 4px; + padding: 1px 0 0 8px; +} + +.mdescLeft, .mdescRight { + padding: 0px 8px 4px 8px; + color: #555; +} + +.memSeparator { + border-bottom: 1px solid #DEE4F0; + line-height: 1px; + margin: 0px; + padding: 0px; +} + +.memItemLeft, .memTemplItemLeft { + white-space: nowrap; +} + +.memItemRight { + width: 100%; +} + +.memTemplParams { + color: #4665A2; + white-space: nowrap; + font-size: 80%; +} + +/* @end */ + +/* @group Member Details */ + +/* Styles for detailed member documentation */ + +.memtemplate { + font-size: 80%; + color: #4665A2; + font-weight: normal; + margin-left: 9px; +} + +.memnav { + background-color: #EBEFF6; + border: 1px solid #A3B4D7; + text-align: center; + margin: 2px; + margin-right: 15px; + padding: 2px; +} + +.mempage { + width: 100%; +} + +.memitem { + padding: 0; + margin-bottom: 10px; + margin-right: 5px; + -webkit-transition: box-shadow 0.5s linear; + -moz-transition: box-shadow 0.5s linear; + -ms-transition: box-shadow 0.5s linear; + -o-transition: box-shadow 0.5s linear; + transition: box-shadow 0.5s linear; + display: table !important; + width: 100%; +} + +.memitem.glow { + box-shadow: 0 0 15px cyan; +} + +.memname { + font-weight: bold; + margin-left: 6px; +} + +.memname td { + vertical-align: bottom; +} + +.memproto, dl.reflist dt { + border-top: 1px solid #A8B8D9; + border-left: 1px solid #A8B8D9; + border-right: 1px solid #A8B8D9; + padding: 6px 0px 6px 0px; + color: #253555; + font-weight: bold; + text-shadow: 0px 1px 1px rgba(255, 255, 255, 0.9); + background-image:url('nav_f.png'); + background-repeat:repeat-x; + background-color: #E2E8F2; + /* opera specific markup */ + box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); + border-top-right-radius: 4px; + border-top-left-radius: 4px; + /* firefox specific markup */ + -moz-box-shadow: rgba(0, 0, 0, 0.15) 5px 5px 5px; + -moz-border-radius-topright: 4px; + -moz-border-radius-topleft: 4px; + /* webkit specific markup */ + -webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); + -webkit-border-top-right-radius: 4px; + -webkit-border-top-left-radius: 4px; + +} + +.memdoc, dl.reflist dd { + border-bottom: 1px solid #A8B8D9; + border-left: 1px solid #A8B8D9; + border-right: 1px solid #A8B8D9; + padding: 6px 10px 2px 10px; + background-color: #FBFCFD; + border-top-width: 0; + background-image:url('nav_g.png'); + background-repeat:repeat-x; + background-color: #FFFFFF; + /* opera specific markup */ + border-bottom-left-radius: 4px; + border-bottom-right-radius: 4px; + box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); + /* firefox specific markup */ + -moz-border-radius-bottomleft: 4px; + -moz-border-radius-bottomright: 4px; + -moz-box-shadow: rgba(0, 0, 0, 0.15) 5px 5px 5px; + /* webkit specific markup */ + -webkit-border-bottom-left-radius: 4px; + -webkit-border-bottom-right-radius: 4px; + -webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); +} + +dl.reflist dt { + padding: 5px; +} + +dl.reflist dd { + margin: 0px 0px 10px 0px; + padding: 5px; +} + +.paramkey { + text-align: right; +} + +.paramtype { + white-space: nowrap; +} + +.paramname { + color: #602020; + white-space: nowrap; +} +.paramname em { + font-style: normal; +} +.paramname code { + line-height: 14px; +} + +.params, .retval, .exception, .tparams { + margin-left: 0px; + padding-left: 0px; +} + +.params .paramname, .retval .paramname { + font-weight: bold; + vertical-align: top; +} + +.params .paramtype { + font-style: italic; + vertical-align: top; +} + +.params .paramdir { + font-family: "courier new",courier,monospace; + vertical-align: top; +} + +table.mlabels { + border-spacing: 0px; +} + +td.mlabels-left { + width: 100%; + padding: 0px; +} + +td.mlabels-right { + vertical-align: bottom; + padding: 0px; + white-space: nowrap; +} + +span.mlabels { + margin-left: 8px; +} + +span.mlabel { + background-color: #728DC1; + border-top:1px solid #5373B4; + border-left:1px solid #5373B4; + border-right:1px solid #C4CFE5; + border-bottom:1px solid #C4CFE5; + text-shadow: none; + color: white; + margin-right: 4px; + padding: 2px 3px; + border-radius: 3px; + font-size: 7pt; + white-space: nowrap; + vertical-align: middle; +} + + + +/* @end */ + +/* these are for tree view inside a (index) page */ + +div.directory { + margin: 10px 0px; + border-top: 1px solid #9CAFD4; + border-bottom: 1px solid #9CAFD4; + width: 100%; +} + +.directory table { + border-collapse:collapse; +} + +.directory td { + margin: 0px; + padding: 0px; + vertical-align: top; +} + +.directory td.entry { + white-space: nowrap; + padding-right: 6px; + padding-top: 3px; +} + +.directory td.entry a { + outline:none; +} + +.directory td.entry a img { + border: none; +} + +.directory td.desc { + width: 100%; + padding-left: 6px; + padding-right: 6px; + padding-top: 3px; + border-left: 1px solid rgba(0,0,0,0.05); +} + +.directory tr.even { + padding-left: 6px; + background-color: #F7F8FB; +} + +.directory img { + vertical-align: -30%; +} + +.directory .levels { + white-space: nowrap; + width: 100%; + text-align: right; + font-size: 9pt; +} + +.directory .levels span { + cursor: pointer; + padding-left: 2px; + padding-right: 2px; + color: #3D578C; +} + +.arrow { + color: #9CAFD4; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + cursor: pointer; + font-size: 80%; + display: inline-block; + width: 16px; + height: 22px; +} + +.icon { + font-family: Arial, Helvetica; + font-weight: bold; + font-size: 12px; + height: 14px; + width: 16px; + display: inline-block; + background-color: #728DC1; + color: white; + text-align: center; + border-radius: 4px; + margin-left: 2px; + margin-right: 2px; +} + +.icona { + width: 24px; + height: 22px; + display: inline-block; +} + +.iconfopen { + width: 24px; + height: 18px; + margin-bottom: 4px; + background-image:url('folderopen.png'); + background-position: 0px -4px; + background-repeat: repeat-y; + vertical-align:top; + display: inline-block; +} + +.iconfclosed { + width: 24px; + height: 18px; + margin-bottom: 4px; + background-image:url('folderclosed.png'); + background-position: 0px -4px; + background-repeat: repeat-y; + vertical-align:top; + display: inline-block; +} + +.icondoc { + width: 24px; + height: 18px; + margin-bottom: 4px; + background-image:url('doc.png'); + background-position: 0px -4px; + background-repeat: repeat-y; + vertical-align:top; + display: inline-block; +} + +table.directory { + font: 400 14px Roboto,sans-serif; +} + +/* @end */ + +div.dynheader { + margin-top: 8px; + -webkit-touch-callout: none; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +address { + font-style: normal; + color: #2A3D61; +} + +table.doxtable caption { + caption-side: top; +} + +table.doxtable { + border-collapse:collapse; + margin-top: 4px; + margin-bottom: 4px; +} + +table.doxtable td, table.doxtable th { + border: 1px solid #2D4068; + padding: 3px 7px 2px; +} + +table.doxtable th { + background-color: #374F7F; + color: #FFFFFF; + font-size: 110%; + padding-bottom: 4px; + padding-top: 5px; +} + +table.fieldtable { + /*width: 100%;*/ + margin-bottom: 10px; + border: 1px solid #A8B8D9; + border-spacing: 0px; + -moz-border-radius: 4px; + -webkit-border-radius: 4px; + border-radius: 4px; + -moz-box-shadow: rgba(0, 0, 0, 0.15) 2px 2px 2px; + -webkit-box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.15); + box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.15); +} + +.fieldtable td, .fieldtable th { + padding: 3px 7px 2px; +} + +.fieldtable td.fieldtype, .fieldtable td.fieldname { + white-space: nowrap; + border-right: 1px solid #A8B8D9; + border-bottom: 1px solid #A8B8D9; + vertical-align: top; +} + +.fieldtable td.fieldname { + padding-top: 3px; +} + +.fieldtable td.fielddoc { + border-bottom: 1px solid #A8B8D9; + /*width: 100%;*/ +} + +.fieldtable td.fielddoc p:first-child { + margin-top: 0px; +} + +.fieldtable td.fielddoc p:last-child { + margin-bottom: 2px; +} + +.fieldtable tr:last-child td { + border-bottom: none; +} + +.fieldtable th { + background-image:url('nav_f.png'); + background-repeat:repeat-x; + background-color: #E2E8F2; + font-size: 90%; + color: #253555; + padding-bottom: 4px; + padding-top: 5px; + text-align:left; + -moz-border-radius-topleft: 4px; + -moz-border-radius-topright: 4px; + -webkit-border-top-left-radius: 4px; + -webkit-border-top-right-radius: 4px; + border-top-left-radius: 4px; + border-top-right-radius: 4px; + border-bottom: 1px solid #A8B8D9; +} + + +.tabsearch { + top: 0px; + left: 10px; + height: 36px; + background-image: url('tab_b.png'); + z-index: 101; + overflow: hidden; + font-size: 13px; +} + +.navpath ul +{ + font-size: 11px; + background-image:url('tab_b.png'); + background-repeat:repeat-x; + background-position: 0 -5px; + height:30px; + line-height:30px; + color:#8AA0CC; + border:solid 1px #C2CDE4; + overflow:hidden; + margin:0px; + padding:0px; +} + +.navpath li +{ + list-style-type:none; + float:left; + padding-left:10px; + padding-right:15px; + background-image:url('bc_s.png'); + background-repeat:no-repeat; + background-position:right; + color:#364D7C; +} + +.navpath li.navelem a +{ + height:32px; + display:block; + text-decoration: none; + outline: none; + color: #283A5D; + font-family: 'Lucida Grande',Geneva,Helvetica,Arial,sans-serif; + text-shadow: 0px 1px 1px rgba(255, 255, 255, 0.9); + text-decoration: none; +} + +.navpath li.navelem a:hover +{ + color:#6884BD; +} + +.navpath li.footer +{ + list-style-type:none; + float:right; + padding-left:10px; + padding-right:15px; + background-image:none; + background-repeat:no-repeat; + background-position:right; + color:#364D7C; + font-size: 8pt; +} + + +div.summary +{ + float: right; + font-size: 8pt; + padding-right: 5px; + width: 50%; + text-align: right; +} + +div.summary a +{ + white-space: nowrap; +} + +table.classindex +{ + margin: 10px; + white-space: nowrap; + margin-left: 3%; + margin-right: 3%; + width: 94%; + border: 0; + border-spacing: 0; + padding: 0; +} + +div.ingroups +{ + font-size: 8pt; + width: 50%; + text-align: left; +} + +div.ingroups a +{ + white-space: nowrap; +} + +div.header +{ + background-image:url('nav_h.png'); + background-repeat:repeat-x; + background-color: #F9FAFC; + margin: 0px; + border-bottom: 1px solid #C4CFE5; +} + +div.headertitle +{ + padding: 5px 5px 5px 10px; +} + +dl +{ + padding: 0 0 0 10px; +} + +/* dl.note, dl.warning, dl.attention, dl.pre, dl.post, dl.invariant, dl.deprecated, dl.todo, dl.test, dl.bug */ +dl.section +{ + margin-left: 0px; + padding-left: 0px; +} + +dl.note +{ + margin-left:-7px; + padding-left: 3px; + border-left:4px solid; + border-color: #D0C000; +} + +dl.warning, dl.attention +{ + margin-left:-7px; + padding-left: 3px; + border-left:4px solid; + border-color: #FF0000; +} + +dl.pre, dl.post, dl.invariant +{ + margin-left:-7px; + padding-left: 3px; + border-left:4px solid; + border-color: #00D000; +} + +dl.deprecated +{ + margin-left:-7px; + padding-left: 3px; + border-left:4px solid; + border-color: #505050; +} + +dl.todo +{ + margin-left:-7px; + padding-left: 3px; + border-left:4px solid; + border-color: #00C0E0; +} + +dl.test +{ + margin-left:-7px; + padding-left: 3px; + border-left:4px solid; + border-color: #3030E0; +} + +dl.bug +{ + margin-left:-7px; + padding-left: 3px; + border-left:4px solid; + border-color: #C08050; +} + +dl.section dd { + margin-bottom: 6px; +} + + +#projectlogo +{ + text-align: center; + vertical-align: bottom; + border-collapse: separate; +} + +#projectlogo img +{ + border: 0px none; +} + +#projectalign +{ + vertical-align: middle; +} + +#projectname +{ + font: 300% Tahoma, Arial,sans-serif; + margin: 0px; + padding: 2px 0px; +} + +#projectbrief +{ + font: 120% Tahoma, Arial,sans-serif; + margin: 0px; + padding: 0px; +} + +#projectnumber +{ + font: 50% Tahoma, Arial,sans-serif; + margin: 0px; + padding: 0px; +} + +#titlearea +{ + padding: 0px; + margin: 0px; + width: 100%; + border-bottom: 1px solid #5373B4; +} + +.image +{ + text-align: center; +} + +.dotgraph +{ + text-align: center; +} + +.mscgraph +{ + text-align: center; +} + +.diagraph +{ + text-align: center; +} + +.caption +{ + font-weight: bold; +} + +div.zoom +{ + border: 1px solid #90A5CE; +} + +dl.citelist { + margin-bottom:50px; +} + +dl.citelist dt { + color:#334975; + float:left; + font-weight:bold; + margin-right:10px; + padding:5px; +} + +dl.citelist dd { + margin:2px 0; + padding:5px 0; +} + +div.toc { + padding: 14px 25px; + background-color: #F4F6FA; + border: 1px solid #D8DFEE; + border-radius: 7px 7px 7px 7px; + float: right; + height: auto; + margin: 0 8px 10px 10px; + width: 200px; +} + +div.toc li { + background: url("bdwn.png") no-repeat scroll 0 5px transparent; + font: 10px/1.2 Verdana,DejaVu Sans,Geneva,sans-serif; + margin-top: 5px; + padding-left: 10px; + padding-top: 2px; +} + +div.toc h3 { + font: bold 12px/1.2 Arial,FreeSans,sans-serif; + color: #4665A2; + border-bottom: 0 none; + margin: 0; +} + +div.toc ul { + list-style: none outside none; + border: medium none; + padding: 0px; +} + +div.toc li.level1 { + margin-left: 0px; +} + +div.toc li.level2 { + margin-left: 15px; +} + +div.toc li.level3 { + margin-left: 30px; +} + +div.toc li.level4 { + margin-left: 45px; +} + +.inherit_header { + font-weight: bold; + color: gray; + cursor: pointer; + -webkit-touch-callout: none; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +.inherit_header td { + padding: 6px 0px 2px 5px; +} + +.inherit { + display: none; +} + +tr.heading h2 { + margin-top: 12px; + margin-bottom: 4px; +} + +/* tooltip related style info */ + +.ttc { + position: absolute; + display: none; +} + +#powerTip { + cursor: default; + white-space: nowrap; + background-color: white; + border: 1px solid gray; + border-radius: 4px 4px 4px 4px; + box-shadow: 1px 1px 7px gray; + display: none; + font-size: smaller; + max-width: 80%; + opacity: 0.9; + padding: 1ex 1em 1em; + position: absolute; + z-index: 2147483647; +} + +#powerTip div.ttdoc { + color: grey; + font-style: italic; +} + +#powerTip div.ttname a { + font-weight: bold; +} + +#powerTip div.ttname { + font-weight: bold; +} + +#powerTip div.ttdeci { + color: #006318; +} + +#powerTip div { + margin: 0px; + padding: 0px; + font: 12px/16px Roboto,sans-serif; +} + +#powerTip:before, #powerTip:after { + content: ""; + position: absolute; + margin: 0px; +} + +#powerTip.n:after, #powerTip.n:before, +#powerTip.s:after, #powerTip.s:before, +#powerTip.w:after, #powerTip.w:before, +#powerTip.e:after, #powerTip.e:before, +#powerTip.ne:after, #powerTip.ne:before, +#powerTip.se:after, #powerTip.se:before, +#powerTip.nw:after, #powerTip.nw:before, +#powerTip.sw:after, #powerTip.sw:before { + border: solid transparent; + content: " "; + height: 0; + width: 0; + position: absolute; +} + +#powerTip.n:after, #powerTip.s:after, +#powerTip.w:after, #powerTip.e:after, +#powerTip.nw:after, #powerTip.ne:after, +#powerTip.sw:after, #powerTip.se:after { + border-color: rgba(255, 255, 255, 0); +} + +#powerTip.n:before, #powerTip.s:before, +#powerTip.w:before, #powerTip.e:before, +#powerTip.nw:before, #powerTip.ne:before, +#powerTip.sw:before, #powerTip.se:before { + border-color: rgba(128, 128, 128, 0); +} + +#powerTip.n:after, #powerTip.n:before, +#powerTip.ne:after, #powerTip.ne:before, +#powerTip.nw:after, #powerTip.nw:before { + top: 100%; +} + +#powerTip.n:after, #powerTip.ne:after, #powerTip.nw:after { + border-top-color: #ffffff; + border-width: 10px; + margin: 0px -10px; +} +#powerTip.n:before { + border-top-color: #808080; + border-width: 11px; + margin: 0px -11px; +} +#powerTip.n:after, #powerTip.n:before { + left: 50%; +} + +#powerTip.nw:after, #powerTip.nw:before { + right: 14px; +} + +#powerTip.ne:after, #powerTip.ne:before { + left: 14px; +} + +#powerTip.s:after, #powerTip.s:before, +#powerTip.se:after, #powerTip.se:before, +#powerTip.sw:after, #powerTip.sw:before { + bottom: 100%; +} + +#powerTip.s:after, #powerTip.se:after, #powerTip.sw:after { + border-bottom-color: #ffffff; + border-width: 10px; + margin: 0px -10px; +} + +#powerTip.s:before, #powerTip.se:before, #powerTip.sw:before { + border-bottom-color: #808080; + border-width: 11px; + margin: 0px -11px; +} + +#powerTip.s:after, #powerTip.s:before { + left: 50%; +} + +#powerTip.sw:after, #powerTip.sw:before { + right: 14px; +} + +#powerTip.se:after, #powerTip.se:before { + left: 14px; +} + +#powerTip.e:after, #powerTip.e:before { + left: 100%; +} +#powerTip.e:after { + border-left-color: #ffffff; + border-width: 10px; + top: 50%; + margin-top: -10px; +} +#powerTip.e:before { + border-left-color: #808080; + border-width: 11px; + top: 50%; + margin-top: -11px; +} + +#powerTip.w:after, #powerTip.w:before { + right: 100%; +} +#powerTip.w:after { + border-right-color: #ffffff; + border-width: 10px; + top: 50%; + margin-top: -10px; +} +#powerTip.w:before { + border-right-color: #808080; + border-width: 11px; + top: 50%; + margin-top: -11px; +} + +@media print +{ + #top { display: none; } + #side-nav { display: none; } + #nav-path { display: none; } + body { overflow:visible; } + h1, h2, h3, h4, h5, h6 { page-break-after: avoid; } + .summary { display: none; } + .memitem { page-break-inside: avoid; } + #doc-content + { + margin-left:0 !important; + height:auto !important; + width:auto !important; + overflow:inherit; + display:inline; + } +} + diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/doxygen.png b/sgx-jvm/linux-sgx/external/epid/doc/html/doxygen.png new file mode 100644 index 0000000000..3ff17d807f Binary files /dev/null and b/sgx-jvm/linux-sgx/external/epid/doc/html/doxygen.png differ diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/dynsections.js b/sgx-jvm/linux-sgx/external/epid/doc/html/dynsections.js new file mode 100644 index 0000000000..85e1836909 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/dynsections.js @@ -0,0 +1,97 @@ +function toggleVisibility(linkObj) +{ + var base = $(linkObj).attr('id'); + var summary = $('#'+base+'-summary'); + var content = $('#'+base+'-content'); + var trigger = $('#'+base+'-trigger'); + var src=$(trigger).attr('src'); + if (content.is(':visible')===true) { + content.hide(); + summary.show(); + $(linkObj).addClass('closed').removeClass('opened'); + $(trigger).attr('src',src.substring(0,src.length-8)+'closed.png'); + } else { + content.show(); + summary.hide(); + $(linkObj).removeClass('closed').addClass('opened'); + $(trigger).attr('src',src.substring(0,src.length-10)+'open.png'); + } + return false; +} + +function updateStripes() +{ + $('table.directory tr'). + removeClass('even').filter(':visible:even').addClass('even'); +} + +function toggleLevel(level) +{ + $('table.directory tr').each(function() { + var l = this.id.split('_').length-1; + var i = $('#img'+this.id.substring(3)); + var a = $('#arr'+this.id.substring(3)); + if (l + + + + + + +Intel® Enhanced Privacy ID SDK: epid/common/math/ecdsa.h File Reference + + + + + + + + + + + + +
+
+ + + + + + +
+ +
+
+ + +
+
+ +
+
+
+ +
+
+ +
+
ecdsa.h File Reference
+
+
+ +

Ecdsa interface. +More...

+
#include <stddef.h>
+#include "epid/common/errors.h"
+#include "epid/common/types.h"
+#include "epid/common/bitsupplier.h"
+
+ + + + + + + +

+Functions

EpidStatus EcdsaVerifyBuffer (void const *buf, size_t buf_len, EcdsaPublicKey const *pubkey, EcdsaSignature const *sig)
 Verifies authenticity of a digital signature over a buffer. More...
 
EpidStatus EcdsaSignBuffer (void const *buf, size_t buf_len, EcdsaPrivateKey const *privkey, BitSupplier rnd_func, void *rnd_param, EcdsaSignature *sig)
 Creates ECDSA signature of buffer. More...
 
+

Detailed Description

+

Ecdsa interface.

+
+
+ + + + + diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/ecdsa__sign_8c.html b/sgx-jvm/linux-sgx/external/epid/doc/html/ecdsa__sign_8c.html new file mode 100644 index 0000000000..a94a4c26c3 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/ecdsa__sign_8c.html @@ -0,0 +1,105 @@ + + + + + + + +Intel® Enhanced Privacy ID SDK: epid/common/math/ecdsa_sign.c File Reference + + + + + + + + + + + + +
+
+ + + + + + +
+ +
+
+ + +
+
+ +
+
+
+ +
+
+ +
+
ecdsa_sign.c File Reference
+
+
+ +

EcdsaSignBuffer implementation. +More...

+
#include "epid/common/math/ecdsa.h"
+#include "epid/common/math/bignum.h"
+#include "epid/common/math/bignum-internal.h"
+#include "epid/common/math/ecgroup.h"
+#include "epid/common/memory.h"
+#include "ext/ipp/include/ippcp.h"
+
+ + + + +

+Macros

+#define EPHKEYGEN_WATCHDOG   (10)
 The number of attempts to generate ephemeral key pair.
 
+ + + + +

+Functions

EpidStatus EcdsaSignBuffer (void const *buf, size_t buf_len, EcdsaPrivateKey const *privkey, BitSupplier rnd_func, void *rnd_param, EcdsaSignature *sig)
 Creates ECDSA signature of buffer. More...
 
+

Detailed Description

+

EcdsaSignBuffer implementation.

+
+
+ + + + + diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/ecdsa__verify_8c.html b/sgx-jvm/linux-sgx/external/epid/doc/html/ecdsa__verify_8c.html new file mode 100644 index 0000000000..bb97f4f4c2 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/ecdsa__verify_8c.html @@ -0,0 +1,133 @@ + + + + + + + +Intel® Enhanced Privacy ID SDK: epid/common/math/ecdsa_verify.c File Reference + + + + + + + + + + + + +
+
+ + + + + + +
+ +
+
+ + +
+
+ +
+
+
+ +
+
+ +
+
ecdsa_verify.c File Reference
+
+
+ +

EcdsaVerifyBuffer implementation. +More...

+
#include "epid/common/math/ecdsa.h"
+#include "epid/common/math/bignum.h"
+#include "epid/common/math/bignum-internal.h"
+#include "epid/common/memory.h"
+#include "ext/ipp/include/ippcp.h"
+
+ + + + +

+Macros

#define BREAK_ON_IPP_ERROR(sts, ret)
 Handle Ipp Errors with Break. More...
 
+ + + + +

+Functions

EpidStatus EcdsaVerifyBuffer (void const *buf, size_t buf_len, EcdsaPublicKey const *pubkey, EcdsaSignature const *sig)
 Verifies authenticity of a digital signature over a buffer. More...
 
+

Detailed Description

+

EcdsaVerifyBuffer implementation.

+

Macro Definition Documentation

+ +
+
+ + + + + + + + + + + + + + + + + + +
#define BREAK_ON_IPP_ERROR( sts,
 ret 
)
+
+Value:
{ \
IppStatus temp_sts = (sts); \
if (ippStsNoErr != temp_sts) { \
(ret) = kEpidMathErr; \
break; \
} \
}
internal math error
Definition: errors.h:53
+
+

Handle Ipp Errors with Break.

+ +
+
+
+
+ + + + + diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/ecgroup_8c.html b/sgx-jvm/linux-sgx/external/epid/doc/html/ecgroup_8c.html new file mode 100644 index 0000000000..a59852ba8f --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/ecgroup_8c.html @@ -0,0 +1,222 @@ + + + + + + + +Intel® Enhanced Privacy ID SDK: epid/common/math/ecgroup.c File Reference + + + + + + + + + + + + +
+
+ + + + + + +
+ +
+
+ + +
+
+ +
+
+
+ +
+
+ +
+
ecgroup.c File Reference
+
+
+ +

Elliptic curve group implementation. +More...

+
#include <string.h>
+#include "epid/common/math/bignum-internal.h"
+#include "epid/common/math/ecgroup-internal.h"
+#include "epid/common/math/ecgroup.h"
+#include "epid/common/math/finitefield-internal.h"
+#include "epid/common/memory.h"
+#include "ext/ipp/include/ippcp.h"
+#include "ext/ipp/include/ippcpepid.h"
+
+ + + + +

+Macros

+#define EPID_ECHASH_WATCHDOG   (50)
 The number of attempts to hash a message to an element.
 
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Functions

EpidStatus NewEcGroup (FiniteField const *ff, FfElement const *a, FfElement const *b, FfElement const *x, FfElement const *y, BigNum const *order, BigNum const *cofactor, EcGroup **g)
 Constructs a new EcGroup. More...
 
void DeleteEcGroup (EcGroup **g)
 Deletes a previously allocated EcGroup. More...
 
EpidStatus NewEcPoint (EcGroup const *g, EcPoint **p)
 Creates a new EcPoint. More...
 
void DeleteEcPoint (EcPoint **p)
 Deletes a previously allocated EcPoint. More...
 
EpidStatus eccontains (EcGroup *g, void const *p_str, size_t strlen, EcPoint *p, bool *in_group)
 Check and initialize element if it is in elliptic curve group. More...
 
EpidStatus ReadEcPoint (EcGroup *g, void const *p_str, size_t strlen, EcPoint *p)
 Deserializes an EcPoint from a string. More...
 
EpidStatus WriteEcPoint (EcGroup *g, EcPoint const *p, void *p_str, size_t strlen)
 Serializes an EcPoint to a string. More...
 
EpidStatus EcMul (EcGroup *g, EcPoint const *a, EcPoint const *b, EcPoint *r)
 Multiplies two elements in an elliptic curve group. More...
 
EpidStatus EcExp (EcGroup *g, EcPoint const *a, BigNumStr const *b, EcPoint *r)
 Raises a point in an elliptic curve group to a power. More...
 
EpidStatus EcSscmExp (EcGroup *g, EcPoint const *a, BigNumStr const *b, EcPoint *r)
 Software side-channel mitigated implementation of EcExp. More...
 
EpidStatus EcMultiExp (EcGroup *g, EcPoint const **a, BigNumStr const **b, size_t m, EcPoint *r)
 Multi-exponentiates elements in elliptic curve group. More...
 
EpidStatus EcSscmMultiExp (EcGroup *g, EcPoint const **a, BigNumStr const **b, size_t m, EcPoint *r)
 Software side-channel mitigated implementation of EcMultiExp. More...
 
EpidStatus EcGetRandom (EcGroup *g, BitSupplier rnd_func, void *rnd_func_param, EcPoint *r)
 Generates a random element from an elliptic curve group. More...
 
EpidStatus EcInGroup (EcGroup *g, void const *p_str, size_t strlen, bool *in_group)
 Checks if a point is in an elliptic curve group. More...
 
EpidStatus EcHash (EcGroup *g, void const *msg, size_t msg_len, HashAlg hash_alg, EcPoint *r)
 Hashes an arbitrary message to an element in an elliptic curve group. More...
 
EpidStatus EcMakePoint (EcGroup *g, FfElement const *x, EcPoint *r)
 Sets an EcPoint variable to a point on a curve. More...
 
EpidStatus EcInverse (EcGroup *g, EcPoint const *p, EcPoint *r)
 Computes the additive inverse of an EcPoint. More...
 
EpidStatus EcIsEqual (EcGroup *g, EcPoint const *a, EcPoint const *b, bool *is_equal)
 Checks if two EcPoints are equal. More...
 
EpidStatus EcIsIdentity (EcGroup *g, EcPoint const *p, bool *is_identity)
 Checks if an EcPoint is the identity element. More...
 
+

Detailed Description

+

Elliptic curve group implementation.

+

Function Documentation

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
EpidStatus eccontains (EcGroupg,
void const * p_str,
size_t strlen,
EcPointp,
boolin_group 
)
+
+ +

Check and initialize element if it is in elliptic curve group.

+

This is internal function. Takes a value p as input. If p is indeed an element of g, it outputs true, otherwise, it outputs false.

+

This is only used to check if input buffer are actually valid elements in group. If p is in g, this fills p and initializes it to internal FfElement format.

+
Parameters
+ + + + + + +
[in]gThe eliptic curve group in which to perform the check
[in]p_strSerialized eliptic curve group element to check
[in]strlenThe size of p_str in bytes.
[out]pDeserialized value of p_str
[out]in_groupResult of the check
+
+
+
Returns
EpidStatus
+
See also
NewEcPoint
+ +
+
+
+
+ + + + + diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/ecgroup_8h.html b/sgx-jvm/linux-sgx/external/epid/doc/html/ecgroup_8h.html new file mode 100644 index 0000000000..ebb7d5d214 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/ecgroup_8h.html @@ -0,0 +1,159 @@ + + + + + + + +Intel® Enhanced Privacy ID SDK: epid/common/math/ecgroup.h File Reference + + + + + + + + + + + + +
+
+ + + + + + +
+ +
+
+ + +
+
+ +
+
+
+ +
+
+ +
+
ecgroup.h File Reference
+
+
+ +

Elliptic curve group interface. +More...

+ + + + + + + + +

+Typedefs

+typedef struct EcGroup EcGroup
 Elliptic curve group over finite field.
 
+typedef struct EcPoint EcPoint
 Point on elliptic curve over finite field.
 
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Functions

EpidStatus NewEcGroup (FiniteField const *ff, FfElement const *a, FfElement const *b, FfElement const *x, FfElement const *y, BigNum const *order, BigNum const *cofactor, EcGroup **g)
 Constructs a new EcGroup. More...
 
void DeleteEcGroup (EcGroup **g)
 Deletes a previously allocated EcGroup. More...
 
EpidStatus NewEcPoint (EcGroup const *g, EcPoint **p)
 Creates a new EcPoint. More...
 
void DeleteEcPoint (EcPoint **p)
 Deletes a previously allocated EcPoint. More...
 
EpidStatus ReadEcPoint (EcGroup *g, void const *p_str, size_t strlen, EcPoint *p)
 Deserializes an EcPoint from a string. More...
 
EpidStatus WriteEcPoint (EcGroup *g, EcPoint const *p, void *p_str, size_t strlen)
 Serializes an EcPoint to a string. More...
 
EpidStatus EcMul (EcGroup *g, EcPoint const *a, EcPoint const *b, EcPoint *r)
 Multiplies two elements in an elliptic curve group. More...
 
EpidStatus EcExp (EcGroup *g, EcPoint const *a, BigNumStr const *b, EcPoint *r)
 Raises a point in an elliptic curve group to a power. More...
 
EpidStatus EcSscmExp (EcGroup *g, EcPoint const *a, BigNumStr const *b, EcPoint *r)
 Software side-channel mitigated implementation of EcExp. More...
 
EpidStatus EcMultiExp (EcGroup *g, EcPoint const **a, BigNumStr const **b, size_t m, EcPoint *r)
 Multi-exponentiates elements in elliptic curve group. More...
 
EpidStatus EcSscmMultiExp (EcGroup *g, EcPoint const **a, BigNumStr const **b, size_t m, EcPoint *r)
 Software side-channel mitigated implementation of EcMultiExp. More...
 
EpidStatus EcGetRandom (EcGroup *g, BitSupplier rnd_func, void *rnd_func_param, EcPoint *r)
 Generates a random element from an elliptic curve group. More...
 
EpidStatus EcInGroup (EcGroup *g, void const *p_str, size_t strlen, bool *in_group)
 Checks if a point is in an elliptic curve group. More...
 
EpidStatus EcHash (EcGroup *g, void const *msg, size_t msg_len, HashAlg hash_alg, EcPoint *r)
 Hashes an arbitrary message to an element in an elliptic curve group. More...
 
EpidStatus EcMakePoint (EcGroup *g, FfElement const *x, EcPoint *r)
 Sets an EcPoint variable to a point on a curve. More...
 
EpidStatus EcInverse (EcGroup *g, EcPoint const *p, EcPoint *r)
 Computes the additive inverse of an EcPoint. More...
 
EpidStatus EcIsEqual (EcGroup *g, EcPoint const *a, EcPoint const *b, bool *is_equal)
 Checks if two EcPoints are equal. More...
 
EpidStatus EcIsIdentity (EcGroup *g, EcPoint const *p, bool *is_identity)
 Checks if an EcPoint is the identity element. More...
 
+

Detailed Description

+

Elliptic curve group interface.

+
+
+ + + + + diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/endian__convert_8h.html b/sgx-jvm/linux-sgx/external/epid/doc/html/endian__convert_8h.html new file mode 100644 index 0000000000..5f089eb45b --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/endian__convert_8h.html @@ -0,0 +1,92 @@ + + + + + + + +Intel® Enhanced Privacy ID SDK: epid/common/endian_convert.h File Reference + + + + + + + + + + + + +
+
+ + + + + + +
+ +
+
+ + +
+
+ +
+
+
+ +
+
+ +
+
endian_convert.h File Reference
+
+
+ +

Endianness conversion interface. +More...

+
#include <stdint.h>
+
+ + + + +

+Macros

#define ntohl(u32)
 Macros to transform oct str 32 into uint_32. More...
 
+

Detailed Description

+

Endianness conversion interface.

+
+
+ + + + + diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/epid2params_8c.html b/sgx-jvm/linux-sgx/external/epid/doc/html/epid2params_8c.html new file mode 100644 index 0000000000..8d24884ccc --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/epid2params_8c.html @@ -0,0 +1,98 @@ + + + + + + + +Intel® Enhanced Privacy ID SDK: epid/common/epid2params.c File Reference + + + + + + + + + + + + +
+
+ + + + + + +
+ +
+
+ + +
+
+ +
+
+
+ +
+
+ +
+
epid2params.c File Reference
+
+
+ +

Intel(R) EPID 2.0 constant parameters implementation. +More...

+ + + + + + + + +

+Functions

+EpidStatus NewFq6 (Epid2Params const *param, FiniteField *Fq2, FfElement *xi, FiniteField **Fq6)
 create a new Finite Field Fq6
 
void DeleteEpid2Params (Epid2Params_ **epid_params)
 Deallocates storage for internal representation of Epid2Params. More...
 
+

Detailed Description

+

Intel(R) EPID 2.0 constant parameters implementation.

+
+
+ + + + + diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/epid2params_8h.html b/sgx-jvm/linux-sgx/external/epid/doc/html/epid2params_8h.html new file mode 100644 index 0000000000..58c8eb3451 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/epid2params_8h.html @@ -0,0 +1,105 @@ + + + + + + + +Intel® Enhanced Privacy ID SDK: epid/common/epid2params.h File Reference + + + + + + + + + + + + +
+
+ + + + + + +
+ +
+
+ + +
+
+ +
+
+
+ +
+
+ +
+
epid2params.h File Reference
+
+
+ +

Intel(R) EPID 2.0 constant parameters interface. +More...

+ + + + + +

+Data Structures

struct  Epid2Params_
 Internal representation of Epid2Params. More...
 
+ + + + + + + +

+Functions

EpidStatus CreateEpid2Params (Epid2Params_ **params)
 Constructs the internal representation of Epid2Params. More...
 
void DeleteEpid2Params (Epid2Params_ **epid_params)
 Deallocates storage for internal representation of Epid2Params. More...
 
+

Detailed Description

+

Intel(R) EPID 2.0 constant parameters interface.

+
+
+ + + + + diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/epid2params__ate_8inc.html b/sgx-jvm/linux-sgx/external/epid/doc/html/epid2params__ate_8inc.html new file mode 100644 index 0000000000..b7168eae1f --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/epid2params__ate_8inc.html @@ -0,0 +1,82 @@ + + + + + + + +Intel® Enhanced Privacy ID SDK: epid/common/epid2params_ate.inc File Reference + + + + + + + + + + + + +
+
+ + + + + + +
+ +
+
+ + +
+
+ +
+
+
+ +
+
+
+
epid2params_ate.inc File Reference
+
+
+ +

Intel(R) EPID 2.0 constant parameters data. +More...

+

Detailed Description

+

Intel(R) EPID 2.0 constant parameters data.

+
+
+ + + + + diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/epid__overview_8dox.html b/sgx-jvm/linux-sgx/external/epid/doc/html/epid__overview_8dox.html new file mode 100644 index 0000000000..eefba2234f --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/epid__overview_8dox.html @@ -0,0 +1,82 @@ + + + + + + + +Intel® Enhanced Privacy ID SDK: doc/docsrc/epid_overview.dox File Reference + + + + + + + + + + + + +
+
+ + + + + + +
+ +
+
+ + +
+
+ +
+
+
+ +
+
+
+
doc/docsrc/epid_overview.dox File Reference
+
+
+ +

This file is used by Doxygen to generate documentation. +More...

+

Detailed Description

+

This file is used by Doxygen to generate documentation.

+
+
+ + + + + diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/epid_diagram_high_level_interaction.png b/sgx-jvm/linux-sgx/external/epid/doc/html/epid_diagram_high_level_interaction.png new file mode 100644 index 0000000000..1013eb05f2 Binary files /dev/null and b/sgx-jvm/linux-sgx/external/epid/doc/html/epid_diagram_high_level_interaction.png differ diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/epid_diagram_high_level_use_case.png b/sgx-jvm/linux-sgx/external/epid/doc/html/epid_diagram_high_level_use_case.png new file mode 100644 index 0000000000..acc6374728 Binary files /dev/null and b/sgx-jvm/linux-sgx/external/epid/doc/html/epid_diagram_high_level_use_case.png differ diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/epid_diagram_issuer_high_level.png b/sgx-jvm/linux-sgx/external/epid/doc/html/epid_diagram_issuer_high_level.png new file mode 100644 index 0000000000..d03d6b9fdb Binary files /dev/null and b/sgx-jvm/linux-sgx/external/epid/doc/html/epid_diagram_issuer_high_level.png differ diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/epid_diagram_member_high_level.png b/sgx-jvm/linux-sgx/external/epid/doc/html/epid_diagram_member_high_level.png new file mode 100644 index 0000000000..58d784f413 Binary files /dev/null and b/sgx-jvm/linux-sgx/external/epid/doc/html/epid_diagram_member_high_level.png differ diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/epid_diagram_verifier_high_level.png b/sgx-jvm/linux-sgx/external/epid/doc/html/epid_diagram_verifier_high_level.png new file mode 100644 index 0000000000..bb92560c91 Binary files /dev/null and b/sgx-jvm/linux-sgx/external/epid/doc/html/epid_diagram_verifier_high_level.png differ diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/epidstyle.css b/sgx-jvm/linux-sgx/external/epid/doc/html/epidstyle.css new file mode 100644 index 0000000000..0ad7ff8689 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/epidstyle.css @@ -0,0 +1,325 @@ +.image { + text-align: left; +} +body { + color: #333333; + background-color: #ffffff; + font-family: Verdana, Arial, sans-serif; + font-size: 10pt; + margin-left: 0px; +} +h1 { + color: #0860a8; + font-size: 15pt; + padding-bottom: 1px; + margin-left: 0pt; + margin-bottom: 0px; + border-bottom: 1px solid #0860A8; + font-weight: normal; +} +h1.title { + border-bottom: 0 none; + margin-left: 0; + font-weight: normal; +} +h2 { + color: #0860a8; + font-weight: lighter; + margin-top: 5pt; + margin-bottom: 0; + font-size: 13pt; +} +h3 { + color: #333333; + font-weight: bold; + margin-top: 5pt; + margin-bottom: 0; + font-size: 11pt; +} +a:link { + color: #0860a8; + text-decoration: none; +} +a:visited { + color: #0860a8; + text-decoration: none; +} +a:active { + color: #0860a8; + text-decoration: underline; +} +a:hover { + color: #0860a8; + text-decoration: underline; +} +p { + font-size: inherit; + line-height: 120%; + margin-top: 0; + margin-bottom: 5pt; + font-family: Verdana, Arial, sans-serif; + font-size: 10pt; +} +blockquote { + margin-top: 0; + margin-bottom: 0; +} +HR { + color: #555555; + border: 0; + background: #555555; + height: 1px; + margin-left: 0; +} +p.Note { + margin-top: 0; + margin-left: 25px; + margin-bottom: 10pt; +} +h3.NoteTipHead { + color: #006699; + margin-top: 11pt; + padding-bottom: 0; + line-height: 18px; + text-transform: uppercase; +} +LI.h3-NoteTipHead { + color: #006699; + line-height: 18px; + text-transform: uppercase; +} +h3.NoteTipHead img { + vertical-align: middle; +} +/* +table { + margin-bottom: 5pt; + border-collapse: collapse; + margin-top: 0.3em; + font-size: 10pt; +} +tr { + vertical-align: top; +} +th { + padding: 4px; + text-align: left; + background-color: #555555; + font-weight: bold; + margin-top: 0; + margin-bottom: 0; + color: #ffffff; + font-size: 11pt; + border: 1px #bababa solid; +} +td { + border: 1px #bababa solid; + vertical-align: top; + font-size: 9pt; + margin-bottom: 0px; + margin-top: 0; + margin-left: 0; + padding: 0px; + text-align: left; +} +P.TableCell { + margin-top: 0; + margin-left: 4px; + padding: 0px; + margin-bottom: 0; + font-size: 9pt; + line-height: 120%; +} +td p { + margin-top: 0; + margin-left: 4; + padding: 0; + margin-bottom: 0; + text-align: left; + font-size: 9pt; + line-height: 120%; +} +td h3 { + margin-top: 0; + margin-left: 0; + padding: 0; + text-align: left; + font-size: inherit; + line-height: 120%; +} +td ul { + font-size: inherit; +} +td ol { + font-size: inherit; +} +td.noBorder { + border: 0px none; +} +h3.TableHead { + padding: 4px; + text-align: left; + background-color: #555555; + font-weight: bold; + margin-top: 0; + margin-bottom: 0; + color: #ffffff; + font-size: 11pt; +} +td table { + margin-left: 0; +} +*/ +ol { + margin-bottom: 1em; + font-size: inherit; + margin-top: 0px; + line-height: 100%; + list-style-type: decimal; +} +ol ol { + list-style: lower-alpha; + margin-bottom: 0em; + font-size: inherit; +} +ol ul { + margin-bottom: 0px; + font-size: inherit; +} +ol p { + margin-bottom: 0.2em; + margin-top: 0.2em; + margin-left: 0; + padding-left: 0; + font-size: inherit; +} +ol.Note { + margin-left: 25px; +} +ul { + margin-bottom: 1em; + font-size: inherit; + margin-top: 0px; + line-height: 100%; +} +ul p { + margin-bottom: 0.2em; + margin-top: 0.2em; + margin-left: 0; + padding-left: 0; + font-size: inherit; +} +ul ol { + margin-bottom: 0em; + font-size: inherit; + list-style-type: decimal; +} +ul ul { + margin-bottom: 0px; + font-size: inherit; +} +ul.Note { + margin-left: 25px; +} +li { + font-size: inherit; + margin-top: 0px; + line-height: 130%; +} +li p { + margin-bottom: 0.2em; + margin-top: 0.2em; + margin-left: 0; + padding-left: 0; + font-size: inherit; +} +p.twoColumnListHead { + color: #000000; + margin-top: 0; + margin-bottom: 0; + font-weight: bold; +} +dl { + margin-bottom: 1em; + font-size: inherit; + margin-top: 0px; +} +dt { + font-weight: bold; + margin-top: 1em; +} +dd { + font-size: inherit; + margin-top: 0; +} +dd p { + margin-bottom: 0.2em; + margin-top: 0.2em; + font-size: inherit; +} +p.pRelatedLink { + margin-top: 0px; + margin-bottom: 0px; +} +SPAN.Code { + font-family: "Courier New", Courier, monospace; +} +span.Variable { + font-family: Courier, monospace; + font-style: italic; +} +SPAN.Superscript { + vertical-align: top; + font-size: 80%; +} +SPAN.Color { + color: #6C9A65; +} +SPAN.Color2 { + color: #0860a8; +} +SPAN.Color3 { + color: #fd0b01; +} +SPAN.Color4 { + color: #f8aa06; +} +.Code { + font-family: "Courier New", Courier, monospace; + background-color: #eeeeee; +} +.link_buttons { + background-color: #EEEEEE; + border-color: #EEEEEE; + border-width: 1px; + padding: 4px; +} +.Color { + color: #6C9A65; +} +.Preformatted { + x-text-tab-stops: repeat 1in; + margin-top: 0; + margin-bottom: 0; + font-size: 10pt; + font-family: "Courier New", Courier, monospace; + background-color: #eeeeee; +} + +/* Hide top level nav-tree node */ +#nav-tree-contents > ul > li > div { + display: none; +} + +/* Shift remaining nav-tree nodes left */ +#nav-tree-contents > ul { + margin: 0; + padding: 0; + margin-left: -16px; + margin-top: -2em; /* nav-tree hack*/ +} + +#projectlink { + color:inherit; + text-decoration:none; +} \ No newline at end of file diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/errors_8c.html b/sgx-jvm/linux-sgx/external/epid/doc/html/errors_8c.html new file mode 100644 index 0000000000..ce82948c36 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/errors_8c.html @@ -0,0 +1,101 @@ + + + + + + + +Intel® Enhanced Privacy ID SDK: epid/common/errors.c File Reference + + + + + + + + + + + + +
+
+ + + + + + +
+ +
+
+ + +
+
+ +
+
+
+ +
+
+ +
+
errors.c File Reference
+
+
+ +

Error reporting implementation. +More...

+
#include <stddef.h>
+#include "epid/common/stdtypes.h"
+#include "epid/common/errors.h"
+
+ + + + +

+Data Structures

struct  ErrorTextEntry
 Record mapping status code to string. More...
 
+ + + + +

+Functions

char const * EpidStatusToString (EpidStatus e)
 Returns string representation of error code. More...
 
+

Detailed Description

+

Error reporting implementation.

+
+
+ + + + + diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/errors_8h.html b/sgx-jvm/linux-sgx/external/epid/doc/html/errors_8h.html new file mode 100644 index 0000000000..7b8a7f8697 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/errors_8h.html @@ -0,0 +1,122 @@ + + + + + + + +Intel® Enhanced Privacy ID SDK: epid/common/errors.h File Reference + + + + + + + + + + + + +
+
+ + + + + + +
+ +
+
+ + +
+
+ +
+
+
+ +
+
+ +
+
errors.h File Reference
+
+
+ +

Error reporting. +More...

+ + + + + +

+Enumerations

enum  EpidStatus {
+  kEpidNoErr = 0, +kEpidSigValid = 0, +kEpidSigInvalid = 1, +kEpidSigRevokedinGroupRl = 2, +
+  kEpidSigRevokedinPrivRl = 3, +kEpidSigRevokedinSigRl = 4, +kEpidSigRevokedinVerifierRl = 5, +kEpidErr = -999, +
+  kEpidNotImpl, +kEpidBadArgErr, +kEpidNoMemErr, +kEpidMemAllocErr, +
+  kEpidMathErr, +kEpidDivByZeroErr, +kEpidUnderflowErr, +kEpidHashAlgorithmNotSupported, +
+  kEpidRandMaxIterErr, +kEpidDuplicateErr +
+ }
 Return status for SDK functions. More...
 
+ + + + +

+Functions

char const * EpidStatusToString (EpidStatus e)
 Returns string representation of error code. More...
 
+

Detailed Description

+

Error reporting.

+
+
+ + + + + diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/examples.html b/sgx-jvm/linux-sgx/external/epid/doc/html/examples.html new file mode 100644 index 0000000000..f2de4e678e --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/examples.html @@ -0,0 +1,82 @@ + + + + + + + +Intel® Enhanced Privacy ID SDK: Examples + + + + + + + + + + + + +
+
+ + + + + + +
+ +
+
+ + +
+
+ +
+
+
+ +
+
+
+
Examples
+
+
+
Here is a list of all examples:
+
+
+ + + + + diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/examples.js b/sgx-jvm/linux-sgx/external/epid/doc/html/examples.js new file mode 100644 index 0000000000..cdfa35393e --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/examples.js @@ -0,0 +1,5 @@ +var examples = +[ + [ "signmsg.c", "signmsg_8c-example.html", null ], + [ "verifysig.c", "verifysig_8c-example.html", null ] +]; \ No newline at end of file diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/examples_8dox.html b/sgx-jvm/linux-sgx/external/epid/doc/html/examples_8dox.html new file mode 100644 index 0000000000..7f8829a3bb --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/examples_8dox.html @@ -0,0 +1,82 @@ + + + + + + + +Intel® Enhanced Privacy ID SDK: doc/docsrc/examples.dox File Reference + + + + + + + + + + + + +
+
+ + + + + + +
+ +
+
+ + +
+
+ +
+
+
+ +
+
+
+
doc/docsrc/examples.dox File Reference
+
+
+ +

This file is used by Doxygen to generate documentation. +More...

+

Detailed Description

+

This file is used by Doxygen to generate documentation.

+
+
+ + + + + diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/file__parser_8c.html b/sgx-jvm/linux-sgx/external/epid/doc/html/file__parser_8c.html new file mode 100644 index 0000000000..befa225f71 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/file__parser_8c.html @@ -0,0 +1,118 @@ + + + + + + + +Intel® Enhanced Privacy ID SDK: epid/common/file_parser.c File Reference + + + + + + + + + + + + +
+
+ + + + + + +
+ +
+
+ + +
+
+ +
+
+
+ +
+
+ +
+
file_parser.c File Reference
+
+
+ +

Implementation of issuer material file parsing utilities. +More...

+
#include "epid/common/file_parser.h"
+#include <string.h>
+#include "epid/common/math/ecdsa.h"
+#include "epid/common/memory.h"
+
+ + + + +

+Data Structures

struct  EpidGroupPubKeyCertificate
 Intel(R) EPID 2.0 Group Public Key binary format. More...
 
+ + + + + + + + + + + + + +

+Functions

EpidStatus EpidParseGroupPubKeyFile (void const *buf, size_t len, EpidCaCertificate const *cert, GroupPubKey *pubkey)
 Extracts group public key from buffer in issuer binary format. More...
 
EpidStatus EpidParsePrivRlFile (void const *buf, size_t len, EpidCaCertificate const *cert, PrivRl *rl, size_t *rl_len)
 Extracts private key revocation list from buffer in issuer binary format. More...
 
EpidStatus EpidParseSigRlFile (void const *buf, size_t len, EpidCaCertificate const *cert, SigRl *rl, size_t *rl_len)
 Extracts signature revocation list from buffer in issuer binary format. More...
 
EpidStatus EpidParseGroupRlFile (void const *buf, size_t len, EpidCaCertificate const *cert, GroupRl *rl, size_t *rl_len)
 Extracts group revocation list from buffer in issuer binary format. More...
 
+ + + + +

+Variables

const OctStr16 kEpidFileTypeCode [kNumFileTypes]
 Encoding of issuer material file types. More...
 
+

Detailed Description

+

Implementation of issuer material file parsing utilities.

+
+
+ + + + + diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/file__parser_8h.html b/sgx-jvm/linux-sgx/external/epid/doc/html/file__parser_8h.html new file mode 100644 index 0000000000..b87ad4cac5 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/file__parser_8h.html @@ -0,0 +1,141 @@ + + + + + + + +Intel® Enhanced Privacy ID SDK: epid/common/file_parser.h File Reference + + + + + + + + + + + + +
+
+ + + + + + +
+ +
+
+ + +
+
+ +
+
+
+ +
+
+ +
+
file_parser.h File Reference
+
+
+ +

Epid issuer material parsing utilities. +More...

+
#include <stddef.h>
+#include "epid/common/types.h"
+#include "epid/common/errors.h"
+
+ + + + + + + +

+Data Structures

struct  EpidFileHeader
 Intel(R) EPID binary file header. More...
 
struct  EpidCaCertificate
 IoT CA Certificate binary format. More...
 
+ + + + +

+Enumerations

enum  EpidFileType {
+  kIssuingCaPubKeyFile, +kGroupPubKeyFile, +kPrivRlFile, +kSigRlFile, +
+  kGroupRlFile, +kPrivRlRequestFile, +kSigRlRequestFile, +kGroupRlRequestFile, +
+  kNumFileTypes +
+ }
 Recognized Intel(R) EPID file types. More...
 
+ + + + + + + + + + + + + +

+Functions

EpidStatus EpidParseGroupPubKeyFile (void const *buf, size_t len, EpidCaCertificate const *cert, GroupPubKey *pubkey)
 Extracts group public key from buffer in issuer binary format. More...
 
EpidStatus EpidParsePrivRlFile (void const *buf, size_t len, EpidCaCertificate const *cert, PrivRl *rl, size_t *rl_len)
 Extracts private key revocation list from buffer in issuer binary format. More...
 
EpidStatus EpidParseSigRlFile (void const *buf, size_t len, EpidCaCertificate const *cert, SigRl *rl, size_t *rl_len)
 Extracts signature revocation list from buffer in issuer binary format. More...
 
EpidStatus EpidParseGroupRlFile (void const *buf, size_t len, EpidCaCertificate const *cert, GroupRl *rl, size_t *rl_len)
 Extracts group revocation list from buffer in issuer binary format. More...
 
+ + + + +

+Variables

+const OctStr16 kEpidFileTypeCode [kNumFileTypes]
 Encoding of issuer material file types.
 
+

Detailed Description

+

Epid issuer material parsing utilities.

+
+
+ + + + + diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/files.html b/sgx-jvm/linux-sgx/external/epid/doc/html/files.html new file mode 100644 index 0000000000..9da5d546e4 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/files.html @@ -0,0 +1,141 @@ + + + + + + + +Intel® Enhanced Privacy ID SDK: File List + + + + + + + + + + + + +
+
+ + + + + + +
+ +
+
+ + +
+
+ +
+
+
+ +
+
+
+
File List
+
+
+
Here is a list of all documented files with brief descriptions:
+
[detail level 1234]
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
  epidCore Intel® EPID functionality
  commonCommon code shared between core sub-components
  mathMath primitives
 bignum.cBig number implementation
 bignum.hBig number interface
 ecdsa.hEcdsa interface
 ecdsa_sign.cEcdsaSignBuffer implementation
 ecdsa_verify.cEcdsaVerifyBuffer implementation
 ecgroup.cElliptic curve group implementation
 ecgroup.hElliptic curve group interface
 finitefield.cFinite field implementation
 finitefield.hFinite field interface
 hash.hHash primitives
 pairing.cPairing implementation
 pairing.hPairing interface
 printutils.cPrint helper implementation
 printutils.hPrint helper interface
 sha256.cSHA256 implementation
 bitsupplier.hRandom data supplier interface
 commitment.cCommitment hash implementation
 commitment.hCommitment hash interface
 endian_convert.hEndianness conversion interface
 epid2params.cIntel(R) EPID 2.0 constant parameters implementation
 epid2params.hIntel(R) EPID 2.0 constant parameters interface
 epid2params_ate.incIntel(R) EPID 2.0 constant parameters data
 errors.cError reporting implementation
 errors.hError reporting
 file_parser.cImplementation of issuer material file parsing utilities
 file_parser.hEpid issuer material parsing utilities
 grouppubkey.cGroup public key implementation
 grouppubkey.hGroup public key interface
 memory.cMemory access implementation
 memory.hMemory access interface
 sigrlvalid.cSigRl validity checking implementation
 sigrlvalid.hSigRl validity checking interface
 stack.cStack container implementation
 stack.hStack container interface
 stdtypes.hC99 standard data types
 types.hSDK data types
  memberMember functionality
 api.hIntel(R) EPID SDK member API
 context.cMember context implementation
 context.hMember context interface
 decompress_privkey.cEpidDecompressPrivKey implementation
 get_sigsize.cEpidGetSigSize implementation
 nr_prove.cEpidNrProve implementation
 presig.cEpidComputePreSig implementation
 privkey.cPrivate key implementation
 privkey.hPrivate key private interface
 request_join.cEpidRequestJoin implementation
 sign.cEpidSign implementation
 signbasic.cEpidSignBasic implementation
  verifierVerifier functionality
 api.hIntel(R) EPID SDK verifier API
 check_privrl_entry.cEpidCheckPrivRlEntry implementation
 context.cVerifier context implementation
 context.hVerifier context interface
 nrverify.cNrVerfy implementation
 sigs_linked.cAreSigsLinked implementation
 verify.cVerify implementation
 verifybasic.cVerifyBasicSig implementation
+
+
+
+ + + + + diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/finitefield_8c.html b/sgx-jvm/linux-sgx/external/epid/doc/html/finitefield_8c.html new file mode 100644 index 0000000000..da6975291f --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/finitefield_8c.html @@ -0,0 +1,162 @@ + + + + + + + +Intel® Enhanced Privacy ID SDK: epid/common/math/finitefield.c File Reference + + + + + + + + + + + + +
+
+ + + + + + +
+ +
+
+ + +
+
+ +
+
+
+ +
+
+ +
+
finitefield.c File Reference
+
+
+ +

Finite field implementation. +More...

+
#include <limits.h>
+#include <string.h>
+#include "epid/common/math/finitefield.h"
+#include "epid/common/math/bignum-internal.h"
+#include "epid/common/math/finitefield-internal.h"
+#include "epid/common/memory.h"
+#include "ext/ipp/include/ippcp.h"
+#include "ext/ipp/include/ippcpepid.h"
+
+ + + + +

+Macros

+#define RNG_WATCHDOG   (10)
 Number of tries for RNG.
 
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Functions

+EpidStatus InitFiniteFieldFromIpp (IppsGFpState *ipp_ff, FiniteField *ff)
 Initializes a FiniteField structure.
 
EpidStatus NewFiniteField (BigNumStr const *prime, FiniteField **ff)
 Creates new finite field. More...
 
EpidStatus NewFiniteFieldViaBinomalExtension (FiniteField const *ground_field, FfElement const *ground_element, int degree, FiniteField **ff)
 Creates a new finite field using binomial extension. More...
 
void DeleteFiniteField (FiniteField **ff)
 Frees a previously allocated FiniteField. More...
 
EpidStatus NewFfElement (FiniteField const *ff, FfElement **new_ff_elem)
 Creates a new finite field element. More...
 
void DeleteFfElement (FfElement **ff_elem)
 Frees a previously allocated FfElement. More...
 
EpidStatus ReadFfElement (FiniteField *ff, void const *ff_elem_str, size_t strlen, FfElement *ff_elem)
 Deserializes a FfElement from a string. More...
 
EpidStatus WriteFfElement (FiniteField *ff, FfElement const *ff_elem, void *ff_elem_str, size_t strlen)
 Serializes a finite field element to a string. More...
 
EpidStatus FfNeg (FiniteField *ff, FfElement const *a, FfElement *r)
 Calculates the additive inverse of a finite field element. More...
 
EpidStatus FfInv (FiniteField *ff, FfElement const *a, FfElement *r)
 Calculates the multiplicative inverse of a finite field element. More...
 
EpidStatus FfAdd (FiniteField *ff, FfElement const *a, FfElement const *b, FfElement *r)
 Adds two finite field elements. More...
 
EpidStatus FfMul (FiniteField *ff, FfElement const *a, FfElement const *b, FfElement *r)
 Multiplies two finite field elements. More...
 
EpidStatus FfIsZero (FiniteField *ff, FfElement const *a, bool *is_zero)
 Checks if given finite field element is the additive identity (zero). More...
 
EpidStatus FfExp (FiniteField *ff, FfElement const *a, BigNum const *b, FfElement *r)
 Raises an element of a finite field to a power. More...
 
EpidStatus FfMultiExp (FiniteField *ff, FfElement const **p, BigNumStr const **b, size_t m, FfElement *r)
 Multi-exponentiates finite field elements. More...
 
EpidStatus FfSscmMultiExp (FiniteField *ff, FfElement const **p, BigNumStr const **b, size_t m, FfElement *r)
 Software side-channel mitigated implementation of FfMultiExp. More...
 
EpidStatus FfIsEqual (FiniteField *ff, FfElement const *a, FfElement const *b, bool *is_equal)
 Checks if two finite field elements are equal. More...
 
EpidStatus FfHash (FiniteField *ff, void const *msg, size_t msg_len, HashAlg hash_alg, FfElement *r)
 Hashes an arbitrary message to an element in a finite field. More...
 
EpidStatus FfGetRandom (FiniteField *ff, BigNumStr const *low_bound, BitSupplier rnd_func, void *rnd_param, FfElement *r)
 Generate random finite field element. More...
 
+

Detailed Description

+

Finite field implementation.

+
+
+ + + + + diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/finitefield_8h.html b/sgx-jvm/linux-sgx/external/epid/doc/html/finitefield_8h.html new file mode 100644 index 0000000000..b966a52228 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/finitefield_8h.html @@ -0,0 +1,159 @@ + + + + + + + +Intel® Enhanced Privacy ID SDK: epid/common/math/finitefield.h File Reference + + + + + + + + + + + + +
+
+ + + + + + +
+ +
+
+ + +
+
+ +
+
+
+ +
+
+ +
+
finitefield.h File Reference
+
+
+ +

Finite field interface. +More...

+ + + + + + + + +

+Typedefs

+typedef struct FiniteField FiniteField
 A finite field.
 
+typedef struct FfElement FfElement
 An element in a finite field.
 
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Functions

EpidStatus NewFiniteField (BigNumStr const *prime, FiniteField **ff)
 Creates new finite field. More...
 
EpidStatus NewFiniteFieldViaBinomalExtension (FiniteField const *ground_field, FfElement const *ground_element, int degree, FiniteField **ff)
 Creates a new finite field using binomial extension. More...
 
void DeleteFiniteField (FiniteField **ff)
 Frees a previously allocated FiniteField. More...
 
EpidStatus NewFfElement (FiniteField const *ff, FfElement **new_ff_elem)
 Creates a new finite field element. More...
 
void DeleteFfElement (FfElement **ff_elem)
 Frees a previously allocated FfElement. More...
 
EpidStatus ReadFfElement (FiniteField *ff, void const *ff_elem_str, size_t strlen, FfElement *ff_elem)
 Deserializes a FfElement from a string. More...
 
EpidStatus WriteFfElement (FiniteField *ff, FfElement const *ff_elem, void *ff_elem_str, size_t strlen)
 Serializes a finite field element to a string. More...
 
EpidStatus FfNeg (FiniteField *ff, FfElement const *a, FfElement *r)
 Calculates the additive inverse of a finite field element. More...
 
EpidStatus FfInv (FiniteField *ff, FfElement const *a, FfElement *r)
 Calculates the multiplicative inverse of a finite field element. More...
 
EpidStatus FfAdd (FiniteField *ff, FfElement const *a, FfElement const *b, FfElement *r)
 Adds two finite field elements. More...
 
EpidStatus FfMul (FiniteField *ff, FfElement const *a, FfElement const *b, FfElement *r)
 Multiplies two finite field elements. More...
 
EpidStatus FfIsZero (FiniteField *ff, FfElement const *a, bool *is_zero)
 Checks if given finite field element is the additive identity (zero). More...
 
EpidStatus FfExp (FiniteField *ff, FfElement const *a, BigNum const *b, FfElement *r)
 Raises an element of a finite field to a power. More...
 
EpidStatus FfMultiExp (FiniteField *ff, FfElement const **a, BigNumStr const **b, size_t m, FfElement *r)
 Multi-exponentiates finite field elements. More...
 
EpidStatus FfSscmMultiExp (FiniteField *ff, FfElement const **a, BigNumStr const **b, size_t m, FfElement *r)
 Software side-channel mitigated implementation of FfMultiExp. More...
 
EpidStatus FfIsEqual (FiniteField *ff, FfElement const *a, FfElement const *b, bool *is_equal)
 Checks if two finite field elements are equal. More...
 
EpidStatus FfHash (FiniteField *ff, void const *msg, size_t msg_len, HashAlg hash_alg, FfElement *r)
 Hashes an arbitrary message to an element in a finite field. More...
 
EpidStatus FfGetRandom (FiniteField *ff, BigNumStr const *low_bound, BitSupplier rnd_func, void *rnd_param, FfElement *r)
 Generate random finite field element. More...
 
+

Detailed Description

+

Finite field interface.

+
+
+ + + + + diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/folderclosed.png b/sgx-jvm/linux-sgx/external/epid/doc/html/folderclosed.png new file mode 100644 index 0000000000..bb8ab35edc Binary files /dev/null and b/sgx-jvm/linux-sgx/external/epid/doc/html/folderclosed.png differ diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/folderopen.png b/sgx-jvm/linux-sgx/external/epid/doc/html/folderopen.png new file mode 100644 index 0000000000..d6c7f676a3 Binary files /dev/null and b/sgx-jvm/linux-sgx/external/epid/doc/html/folderopen.png differ diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/functions.html b/sgx-jvm/linux-sgx/external/epid/doc/html/functions.html new file mode 100644 index 0000000000..e284cced9a --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/functions.html @@ -0,0 +1,98 @@ + + + + + + + +Intel® Enhanced Privacy ID SDK: Data Fields + + + + + + + + + + + + +
+
+ + + + + + +
+ +
+
+ + +
+
+ +
+
+
+ +
+
+
Here is a list of all documented struct and union fields with links to the struct/union documentation for each field:
+ +

- a -

+
+
+ + + + + diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/functions_b.html b/sgx-jvm/linux-sgx/external/epid/doc/html/functions_b.html new file mode 100644 index 0000000000..a2e57488e9 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/functions_b.html @@ -0,0 +1,107 @@ + + + + + + + +Intel® Enhanced Privacy ID SDK: Data Fields + + + + + + + + + + + + +
+
+ + + + + + +
+ +
+
+ + +
+
+ +
+
+
+ +
+
+
Here is a list of all documented struct and union fields with links to the struct/union documentation for each field:
+ +

- b -

+
+
+ + + + + diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/functions_c.html b/sgx-jvm/linux-sgx/external/epid/doc/html/functions_c.html new file mode 100644 index 0000000000..e373d8a1e1 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/functions_c.html @@ -0,0 +1,85 @@ + + + + + + + +Intel® Enhanced Privacy ID SDK: Data Fields + + + + + + + + + + + + +
+
+ + + + + + +
+ +
+
+ + +
+
+ +
+
+
+ +
+
+
Here is a list of all documented struct and union fields with links to the struct/union documentation for each field:
+ +

- c -

+
+
+ + + + + diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/functions_d.html b/sgx-jvm/linux-sgx/external/epid/doc/html/functions_d.html new file mode 100644 index 0000000000..48a9295861 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/functions_d.html @@ -0,0 +1,90 @@ + + + + + + + +Intel® Enhanced Privacy ID SDK: Data Fields + + + + + + + + + + + + +
+
+ + + + + + +
+ +
+
+ + +
+
+ +
+
+
+ +
+
+
Here is a list of all documented struct and union fields with links to the struct/union documentation for each field:
+ +

- d -

+
+
+ + + + + diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/functions_e.html b/sgx-jvm/linux-sgx/external/epid/doc/html/functions_e.html new file mode 100644 index 0000000000..89b95e91a6 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/functions_e.html @@ -0,0 +1,112 @@ + + + + + + + +Intel® Enhanced Privacy ID SDK: Data Fields + + + + + + + + + + + + +
+
+ + + + + + +
+ +
+
+ + +
+
+ +
+
+
+ +
+
+
Here is a list of all documented struct and union fields with links to the struct/union documentation for each field:
+ +

- e -

+
+
+ + + + + diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/functions_f.html b/sgx-jvm/linux-sgx/external/epid/doc/html/functions_f.html new file mode 100644 index 0000000000..72d55950ca --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/functions_f.html @@ -0,0 +1,100 @@ + + + + + + + +Intel® Enhanced Privacy ID SDK: Data Fields + + + + + + + + + + + + +
+
+ + + + + + +
+ +
+
+ + +
+
+ +
+
+
+ +
+
+
Here is a list of all documented struct and union fields with links to the struct/union documentation for each field:
+ +

- f -

+
+
+ + + + + diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/functions_g.html b/sgx-jvm/linux-sgx/external/epid/doc/html/functions_g.html new file mode 100644 index 0000000000..edb3cd466b --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/functions_g.html @@ -0,0 +1,122 @@ + + + + + + + +Intel® Enhanced Privacy ID SDK: Data Fields + + + + + + + + + + + + +
+
+ + + + + + +
+ +
+
+ + +
+
+ +
+
+
+ +
+
+
Here is a list of all documented struct and union fields with links to the struct/union documentation for each field:
+ +

- g -

+
+
+ + + + + diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/functions_h.html b/sgx-jvm/linux-sgx/external/epid/doc/html/functions_h.html new file mode 100644 index 0000000000..dcb325c8ae --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/functions_h.html @@ -0,0 +1,98 @@ + + + + + + + +Intel® Enhanced Privacy ID SDK: Data Fields + + + + + + + + + + + + +
+
+ + + + + + +
+ +
+
+ + +
+
+ +
+
+
+ +
+
+
Here is a list of all documented struct and union fields with links to the struct/union documentation for each field:
+ +

- h -

+
+
+ + + + + diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/functions_k.html b/sgx-jvm/linux-sgx/external/epid/doc/html/functions_k.html new file mode 100644 index 0000000000..fdf2abced7 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/functions_k.html @@ -0,0 +1,95 @@ + + + + + + + +Intel® Enhanced Privacy ID SDK: Data Fields + + + + + + + + + + + + +
+
+ + + + + + +
+ +
+
+ + +
+
+ +
+
+
+ +
+
+
Here is a list of all documented struct and union fields with links to the struct/union documentation for each field:
+ +

- k -

+
+
+ + + + + diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/functions_l.html b/sgx-jvm/linux-sgx/external/epid/doc/html/functions_l.html new file mode 100644 index 0000000000..9c72e634d0 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/functions_l.html @@ -0,0 +1,79 @@ + + + + + + + +Intel® Enhanced Privacy ID SDK: Data Fields + + + + + + + + + + + + +
+
+ + + + + + +
+ +
+
+ + +
+
+ +
+
+
+ +
+
+
Here is a list of all documented struct and union fields with links to the struct/union documentation for each field:
+ +

- l -

+
+
+ + + + + diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/functions_m.html b/sgx-jvm/linux-sgx/external/epid/doc/html/functions_m.html new file mode 100644 index 0000000000..8d86dd4814 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/functions_m.html @@ -0,0 +1,82 @@ + + + + + + + +Intel® Enhanced Privacy ID SDK: Data Fields + + + + + + + + + + + + +
+
+ + + + + + +
+ +
+
+ + +
+
+ +
+
+
+ +
+
+
Here is a list of all documented struct and union fields with links to the struct/union documentation for each field:
+ +

- m -

+
+
+ + + + + diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/functions_n.html b/sgx-jvm/linux-sgx/external/epid/doc/html/functions_n.html new file mode 100644 index 0000000000..23782aac09 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/functions_n.html @@ -0,0 +1,102 @@ + + + + + + + +Intel® Enhanced Privacy ID SDK: Data Fields + + + + + + + + + + + + +
+
+ + + + + + +
+ +
+
+ + +
+
+ +
+
+
+ +
+
+
Here is a list of all documented struct and union fields with links to the struct/union documentation for each field:
+ +

- n -

+
+
+ + + + + diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/functions_p.html b/sgx-jvm/linux-sgx/external/epid/doc/html/functions_p.html new file mode 100644 index 0000000000..8355af16e5 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/functions_p.html @@ -0,0 +1,105 @@ + + + + + + + +Intel® Enhanced Privacy ID SDK: Data Fields + + + + + + + + + + + + +
+
+ + + + + + +
+ +
+
+ + +
+
+ +
+
+
+ +
+
+
Here is a list of all documented struct and union fields with links to the struct/union documentation for each field:
+ +

- p -

+
+
+ + + + + diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/functions_q.html b/sgx-jvm/linux-sgx/external/epid/doc/html/functions_q.html new file mode 100644 index 0000000000..ea64bc38f2 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/functions_q.html @@ -0,0 +1,80 @@ + + + + + + + +Intel® Enhanced Privacy ID SDK: Data Fields + + + + + + + + + + + + +
+
+ + + + + + +
+ +
+
+ + +
+
+ +
+
+
+ +
+
+
Here is a list of all documented struct and union fields with links to the struct/union documentation for each field:
+ +

- q -

+
+
+ + + + + diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/functions_r.html b/sgx-jvm/linux-sgx/external/epid/doc/html/functions_r.html new file mode 100644 index 0000000000..313ae27a04 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/functions_r.html @@ -0,0 +1,121 @@ + + + + + + + +Intel® Enhanced Privacy ID SDK: Data Fields + + + + + + + + + + + + +
+
+ + + + + + +
+ +
+
+ + +
+
+ +
+
+
+ +
+
+
Here is a list of all documented struct and union fields with links to the struct/union documentation for each field:
+ +

- r -

+
+
+ + + + + diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/functions_s.html b/sgx-jvm/linux-sgx/external/epid/doc/html/functions_s.html new file mode 100644 index 0000000000..671de83346 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/functions_s.html @@ -0,0 +1,113 @@ + + + + + + + +Intel® Enhanced Privacy ID SDK: Data Fields + + + + + + + + + + + + +
+
+ + + + + + +
+ +
+
+ + +
+
+ +
+
+
+ +
+
+
Here is a list of all documented struct and union fields with links to the struct/union documentation for each field:
+ +

- s -

+
+
+ + + + + diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/functions_t.html b/sgx-jvm/linux-sgx/external/epid/doc/html/functions_t.html new file mode 100644 index 0000000000..d845079562 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/functions_t.html @@ -0,0 +1,99 @@ + + + + + + + +Intel® Enhanced Privacy ID SDK: Data Fields + + + + + + + + + + + + +
+
+ + + + + + +
+ +
+
+ + +
+
+ +
+
+
+ +
+
+
Here is a list of all documented struct and union fields with links to the struct/union documentation for each field:
+ +

- t -

+
+
+ + + + + diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/functions_v.html b/sgx-jvm/linux-sgx/external/epid/doc/html/functions_v.html new file mode 100644 index 0000000000..590391966a --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/functions_v.html @@ -0,0 +1,88 @@ + + + + + + + +Intel® Enhanced Privacy ID SDK: Data Fields + + + + + + + + + + + + +
+
+ + + + + + +
+ +
+
+ + +
+
+ +
+
+
+ +
+
+
Here is a list of all documented struct and union fields with links to the struct/union documentation for each field:
+ +

- v -

+
+
+ + + + + diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/functions_vars.html b/sgx-jvm/linux-sgx/external/epid/doc/html/functions_vars.html new file mode 100644 index 0000000000..445df8d494 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/functions_vars.html @@ -0,0 +1,98 @@ + + + + + + + +Intel® Enhanced Privacy ID SDK: Data Fields - Variables + + + + + + + + + + + + +
+
+ + + + + + +
+ +
+
+ + +
+
+ +
+
+
+ +
+
+  + +

- a -

+
+
+ + + + + diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/functions_vars_b.html b/sgx-jvm/linux-sgx/external/epid/doc/html/functions_vars_b.html new file mode 100644 index 0000000000..d19d2371e7 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/functions_vars_b.html @@ -0,0 +1,107 @@ + + + + + + + +Intel® Enhanced Privacy ID SDK: Data Fields - Variables + + + + + + + + + + + + +
+
+ + + + + + +
+ +
+
+ + +
+
+ +
+
+
+ +
+
+  + +

- b -

+
+
+ + + + + diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/functions_vars_c.html b/sgx-jvm/linux-sgx/external/epid/doc/html/functions_vars_c.html new file mode 100644 index 0000000000..0225552d3a --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/functions_vars_c.html @@ -0,0 +1,85 @@ + + + + + + + +Intel® Enhanced Privacy ID SDK: Data Fields - Variables + + + + + + + + + + + + +
+
+ + + + + + +
+ +
+
+ + +
+
+ +
+
+
+ +
+
+  + +

- c -

+
+
+ + + + + diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/functions_vars_d.html b/sgx-jvm/linux-sgx/external/epid/doc/html/functions_vars_d.html new file mode 100644 index 0000000000..5887dbfcd7 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/functions_vars_d.html @@ -0,0 +1,90 @@ + + + + + + + +Intel® Enhanced Privacy ID SDK: Data Fields - Variables + + + + + + + + + + + + +
+
+ + + + + + +
+ +
+
+ + +
+
+ +
+
+
+ +
+ +
+ + + + + diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/functions_vars_e.html b/sgx-jvm/linux-sgx/external/epid/doc/html/functions_vars_e.html new file mode 100644 index 0000000000..81b785fd71 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/functions_vars_e.html @@ -0,0 +1,112 @@ + + + + + + + +Intel® Enhanced Privacy ID SDK: Data Fields - Variables + + + + + + + + + + + + +
+
+ + + + + + +
+ +
+
+ + +
+
+ +
+
+
+ +
+
+  + +

- e -

+
+
+ + + + + diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/functions_vars_f.html b/sgx-jvm/linux-sgx/external/epid/doc/html/functions_vars_f.html new file mode 100644 index 0000000000..a9cdb55eb9 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/functions_vars_f.html @@ -0,0 +1,100 @@ + + + + + + + +Intel® Enhanced Privacy ID SDK: Data Fields - Variables + + + + + + + + + + + + +
+
+ + + + + + +
+ +
+
+ + +
+
+ +
+
+
+ +
+
+  + +

- f -

+
+
+ + + + + diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/functions_vars_g.html b/sgx-jvm/linux-sgx/external/epid/doc/html/functions_vars_g.html new file mode 100644 index 0000000000..fc37948c73 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/functions_vars_g.html @@ -0,0 +1,122 @@ + + + + + + + +Intel® Enhanced Privacy ID SDK: Data Fields - Variables + + + + + + + + + + + + +
+
+ + + + + + +
+ +
+
+ + +
+
+ +
+
+
+ + + + + + + diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/functions_vars_h.html b/sgx-jvm/linux-sgx/external/epid/doc/html/functions_vars_h.html new file mode 100644 index 0000000000..53e982ccb1 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/functions_vars_h.html @@ -0,0 +1,98 @@ + + + + + + + +Intel® Enhanced Privacy ID SDK: Data Fields - Variables + + + + + + + + + + + + +
+
+ + + + + + +
+ +
+
+ + +
+
+ +
+
+
+ + + + + + + diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/functions_vars_k.html b/sgx-jvm/linux-sgx/external/epid/doc/html/functions_vars_k.html new file mode 100644 index 0000000000..84e55cd6b7 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/functions_vars_k.html @@ -0,0 +1,95 @@ + + + + + + + +Intel® Enhanced Privacy ID SDK: Data Fields - Variables + + + + + + + + + + + + +
+
+ + + + + + +
+ +
+
+ + +
+
+ +
+
+
+ +
+
+  + +

- k -

+
+
+ + + + + diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/functions_vars_l.html b/sgx-jvm/linux-sgx/external/epid/doc/html/functions_vars_l.html new file mode 100644 index 0000000000..b5eef3e5df --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/functions_vars_l.html @@ -0,0 +1,79 @@ + + + + + + + +Intel® Enhanced Privacy ID SDK: Data Fields - Variables + + + + + + + + + + + + +
+
+ + + + + + +
+ +
+
+ + +
+
+ +
+
+
+ +
+
+  + +

- l -

+
+
+ + + + + diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/functions_vars_m.html b/sgx-jvm/linux-sgx/external/epid/doc/html/functions_vars_m.html new file mode 100644 index 0000000000..58b6aa8a09 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/functions_vars_m.html @@ -0,0 +1,82 @@ + + + + + + + +Intel® Enhanced Privacy ID SDK: Data Fields - Variables + + + + + + + + + + + + +
+
+ + + + + + +
+ +
+
+ + +
+
+ +
+
+
+ +
+
+  + +

- m -

+
+
+ + + + + diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/functions_vars_n.html b/sgx-jvm/linux-sgx/external/epid/doc/html/functions_vars_n.html new file mode 100644 index 0000000000..b154f6685e --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/functions_vars_n.html @@ -0,0 +1,102 @@ + + + + + + + +Intel® Enhanced Privacy ID SDK: Data Fields - Variables + + + + + + + + + + + + +
+
+ + + + + + +
+ +
+
+ + +
+
+ +
+
+
+ +
+
+  + +

- n -

+
+
+ + + + + diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/functions_vars_p.html b/sgx-jvm/linux-sgx/external/epid/doc/html/functions_vars_p.html new file mode 100644 index 0000000000..03f386e990 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/functions_vars_p.html @@ -0,0 +1,105 @@ + + + + + + + +Intel® Enhanced Privacy ID SDK: Data Fields - Variables + + + + + + + + + + + + +
+
+ + + + + + +
+ +
+
+ + +
+
+ +
+
+
+ +
+
+  + +

- p -

+
+
+ + + + + diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/functions_vars_q.html b/sgx-jvm/linux-sgx/external/epid/doc/html/functions_vars_q.html new file mode 100644 index 0000000000..ae5b02c099 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/functions_vars_q.html @@ -0,0 +1,80 @@ + + + + + + + +Intel® Enhanced Privacy ID SDK: Data Fields - Variables + + + + + + + + + + + + +
+
+ + + + + + +
+ +
+
+ + +
+
+ +
+
+
+ +
+
+  + +

- q -

+
+
+ + + + + diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/functions_vars_r.html b/sgx-jvm/linux-sgx/external/epid/doc/html/functions_vars_r.html new file mode 100644 index 0000000000..a9c20fb040 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/functions_vars_r.html @@ -0,0 +1,121 @@ + + + + + + + +Intel® Enhanced Privacy ID SDK: Data Fields - Variables + + + + + + + + + + + + +
+
+ + + + + + +
+ +
+
+ + +
+
+ +
+
+
+ +
+
+  + +

- r -

+
+
+ + + + + diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/functions_vars_s.html b/sgx-jvm/linux-sgx/external/epid/doc/html/functions_vars_s.html new file mode 100644 index 0000000000..e6a4e85a9d --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/functions_vars_s.html @@ -0,0 +1,113 @@ + + + + + + + +Intel® Enhanced Privacy ID SDK: Data Fields - Variables + + + + + + + + + + + + +
+
+ + + + + + +
+ +
+
+ + +
+
+ +
+
+
+ +
+
+  + +

- s -

+
+
+ + + + + diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/functions_vars_t.html b/sgx-jvm/linux-sgx/external/epid/doc/html/functions_vars_t.html new file mode 100644 index 0000000000..6a1d6689e8 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/functions_vars_t.html @@ -0,0 +1,99 @@ + + + + + + + +Intel® Enhanced Privacy ID SDK: Data Fields - Variables + + + + + + + + + + + + +
+
+ + + + + + +
+ +
+
+ + +
+
+ +
+
+
+ +
+
+  + +

- t -

+
+
+ + + + + diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/functions_vars_v.html b/sgx-jvm/linux-sgx/external/epid/doc/html/functions_vars_v.html new file mode 100644 index 0000000000..63566534eb --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/functions_vars_v.html @@ -0,0 +1,88 @@ + + + + + + + +Intel® Enhanced Privacy ID SDK: Data Fields - Variables + + + + + + + + + + + + +
+
+ + + + + + +
+ +
+
+ + +
+
+ +
+
+
+ +
+
+  + +

- v -

+
+
+ + + + + diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/functions_vars_w.html b/sgx-jvm/linux-sgx/external/epid/doc/html/functions_vars_w.html new file mode 100644 index 0000000000..4034b01b6a --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/functions_vars_w.html @@ -0,0 +1,83 @@ + + + + + + + +Intel® Enhanced Privacy ID SDK: Data Fields - Variables + + + + + + + + + + + + +
+
+ + + + + + +
+ +
+
+ + +
+
+ +
+
+
+ + + + + + + diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/functions_vars_x.html b/sgx-jvm/linux-sgx/external/epid/doc/html/functions_vars_x.html new file mode 100644 index 0000000000..17d2cc60bc --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/functions_vars_x.html @@ -0,0 +1,95 @@ + + + + + + + +Intel® Enhanced Privacy ID SDK: Data Fields - Variables + + + + + + + + + + + + +
+
+ + + + + + +
+ +
+
+ + +
+
+ +
+
+
+ + + + + + + diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/functions_vars_y.html b/sgx-jvm/linux-sgx/external/epid/doc/html/functions_vars_y.html new file mode 100644 index 0000000000..96f739bfab --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/functions_vars_y.html @@ -0,0 +1,83 @@ + + + + + + + +Intel® Enhanced Privacy ID SDK: Data Fields - Variables + + + + + + + + + + + + +
+
+ + + + + + +
+ +
+
+ + +
+
+ +
+
+
+ +
+
+  + +

- y -

+
+
+ + + + + diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/functions_w.html b/sgx-jvm/linux-sgx/external/epid/doc/html/functions_w.html new file mode 100644 index 0000000000..8c463abed0 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/functions_w.html @@ -0,0 +1,83 @@ + + + + + + + +Intel® Enhanced Privacy ID SDK: Data Fields + + + + + + + + + + + + +
+
+ + + + + + +
+ +
+
+ + +
+
+ +
+
+
+ +
+
+
Here is a list of all documented struct and union fields with links to the struct/union documentation for each field:
+ +

- w -

+
+
+ + + + + diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/functions_x.html b/sgx-jvm/linux-sgx/external/epid/doc/html/functions_x.html new file mode 100644 index 0000000000..e54c6ebf5f --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/functions_x.html @@ -0,0 +1,95 @@ + + + + + + + +Intel® Enhanced Privacy ID SDK: Data Fields + + + + + + + + + + + + +
+
+ + + + + + +
+ +
+
+ + +
+
+ +
+
+
+ +
+
+
Here is a list of all documented struct and union fields with links to the struct/union documentation for each field:
+ +

- x -

+
+
+ + + + + diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/functions_y.html b/sgx-jvm/linux-sgx/external/epid/doc/html/functions_y.html new file mode 100644 index 0000000000..47cbd2d3d1 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/functions_y.html @@ -0,0 +1,83 @@ + + + + + + + +Intel® Enhanced Privacy ID SDK: Data Fields + + + + + + + + + + + + +
+
+ + + + + + +
+ +
+
+ + +
+
+ +
+
+
+ +
+
+
Here is a list of all documented struct and union fields with links to the struct/union documentation for each field:
+ +

- y -

+
+
+ + + + + diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/get__sigsize_8c.html b/sgx-jvm/linux-sgx/external/epid/doc/html/get__sigsize_8c.html new file mode 100644 index 0000000000..e1196acb68 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/get__sigsize_8c.html @@ -0,0 +1,93 @@ + + + + + + + +Intel® Enhanced Privacy ID SDK: epid/member/get_sigsize.c File Reference + + + + + + + + + + + + +
+
+ + + + + + +
+ +
+
+ + +
+
+ +
+
+
+ +
+
+ +
+
get_sigsize.c File Reference
+
+
+ +

EpidGetSigSize implementation. +More...

+ + + + + +

+Functions

size_t EpidGetSigSize (SigRl const *sig_rl)
 Computes the size in bytes required for a Intel(R) EPID signature. More...
 
+

Detailed Description

+

EpidGetSigSize implementation.

+
+
+ + + + + diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/globals.html b/sgx-jvm/linux-sgx/external/epid/doc/html/globals.html new file mode 100644 index 0000000000..85cb8704c3 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/globals.html @@ -0,0 +1,80 @@ + + + + + + + +Intel® Enhanced Privacy ID SDK: Globals + + + + + + + + + + + + +
+
+ + + + + + +
+ +
+
+ + +
+
+ +
+
+
+ +
+
+
Here is a list of all documented functions, variables, defines, enums, and typedefs with links to the documentation:
+ +

- a -

+
+
+ + + + + diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/globals_b.html b/sgx-jvm/linux-sgx/external/epid/doc/html/globals_b.html new file mode 100644 index 0000000000..82c9bd3dc3 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/globals_b.html @@ -0,0 +1,119 @@ + + + + + + + +Intel® Enhanced Privacy ID SDK: Globals + + + + + + + + + + + + +
+
+ + + + + + +
+ +
+
+ + +
+
+ +
+
+
+ +
+
+
Here is a list of all documented functions, variables, defines, enums, and typedefs with links to the documentation:
+ +

- b -

+
+
+ + + + + diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/globals_c.html b/sgx-jvm/linux-sgx/external/epid/doc/html/globals_c.html new file mode 100644 index 0000000000..a3ef228d2e --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/globals_c.html @@ -0,0 +1,104 @@ + + + + + + + +Intel® Enhanced Privacy ID SDK: Globals + + + + + + + + + + + + +
+
+ + + + + + +
+ +
+
+ + +
+
+ +
+
+
+ +
+
+
Here is a list of all documented functions, variables, defines, enums, and typedefs with links to the documentation:
+ +

- c -

+
+
+ + + + + diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/globals_d.html b/sgx-jvm/linux-sgx/external/epid/doc/html/globals_d.html new file mode 100644 index 0000000000..48bbd7ba26 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/globals_d.html @@ -0,0 +1,120 @@ + + + + + + + +Intel® Enhanced Privacy ID SDK: Globals + + + + + + + + + + + + +
+
+ + + + + + +
+ +
+
+ + +
+
+ +
+
+
+ +
+
+
Here is a list of all documented functions, variables, defines, enums, and typedefs with links to the documentation:
+ +

- d -

+
+
+ + + + + diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/globals_defs.html b/sgx-jvm/linux-sgx/external/epid/doc/html/globals_defs.html new file mode 100644 index 0000000000..63b1b750d1 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/globals_defs.html @@ -0,0 +1,197 @@ + + + + + + + +Intel® Enhanced Privacy ID SDK: Globals + + + + + + + + + + + + +
+
+ + + + + + +
+ +
+
+ + +
+
+ +
+
+
+ +
+
+  + +

- b -

+ + +

- c -

+ + +

- e -

+ + +

- f -

+ + +

- i -

+ + +

- m -

+ + +

- n -

+ + +

- p -

+ + +

- r -

+ + +

- s -

+ + +

- t -

+ + +

- w -

+
+
+ + + + + diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/globals_e.html b/sgx-jvm/linux-sgx/external/epid/doc/html/globals_e.html new file mode 100644 index 0000000000..a2efb894bf --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/globals_e.html @@ -0,0 +1,308 @@ + + + + + + + +Intel® Enhanced Privacy ID SDK: Globals + + + + + + + + + + + + +
+
+ + + + + + +
+ +
+
+ + +
+
+ +
+
+
+ +
+
+
Here is a list of all documented functions, variables, defines, enums, and typedefs with links to the documentation:
+ +

- e -

+
+
+ + + + + diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/globals_enum.html b/sgx-jvm/linux-sgx/external/epid/doc/html/globals_enum.html new file mode 100644 index 0000000000..9054ce7352 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/globals_enum.html @@ -0,0 +1,86 @@ + + + + + + + +Intel® Enhanced Privacy ID SDK: Globals + + + + + + + + + + + + +
+
+ + + + + + +
+ +
+
+ + +
+
+ +
+
+
+ +
+
+
+
+ + + + + diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/globals_eval.html b/sgx-jvm/linux-sgx/external/epid/doc/html/globals_eval.html new file mode 100644 index 0000000000..4e265cb3f6 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/globals_eval.html @@ -0,0 +1,184 @@ + + + + + + + +Intel® Enhanced Privacy ID SDK: Globals + + + + + + + + + + + + +
+
+ + + + + + +
+ +
+
+ + +
+
+ +
+
+
+ +
+
+  + +

- k -

+
+
+ + + + + diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/globals_f.html b/sgx-jvm/linux-sgx/external/epid/doc/html/globals_f.html new file mode 100644 index 0000000000..7b7f7bfb4d --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/globals_f.html @@ -0,0 +1,129 @@ + + + + + + + +Intel® Enhanced Privacy ID SDK: Globals + + + + + + + + + + + + +
+
+ + + + + + +
+ +
+
+ + +
+
+ +
+
+
+ +
+
+
Here is a list of all documented functions, variables, defines, enums, and typedefs with links to the documentation:
+ +

- f -

+
+
+ + + + + diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/globals_func.html b/sgx-jvm/linux-sgx/external/epid/doc/html/globals_func.html new file mode 100644 index 0000000000..786416a46d --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/globals_func.html @@ -0,0 +1,80 @@ + + + + + + + +Intel® Enhanced Privacy ID SDK: Globals + + + + + + + + + + + + +
+
+ + + + + + +
+ +
+
+ + +
+
+ +
+
+
+ +
+
+  + +

- a -

+
+
+ + + + + diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/globals_func_b.html b/sgx-jvm/linux-sgx/external/epid/doc/html/globals_func_b.html new file mode 100644 index 0000000000..452e4ac509 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/globals_func_b.html @@ -0,0 +1,92 @@ + + + + + + + +Intel® Enhanced Privacy ID SDK: Globals + + + + + + + + + + + + +
+
+ + + + + + +
+ +
+
+ + +
+
+ +
+
+
+ +
+
+  + +

- b -

+
+
+ + + + + diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/globals_func_c.html b/sgx-jvm/linux-sgx/external/epid/doc/html/globals_func_c.html new file mode 100644 index 0000000000..032b6eeed2 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/globals_func_c.html @@ -0,0 +1,99 @@ + + + + + + + +Intel® Enhanced Privacy ID SDK: Globals + + + + + + + + + + + + +
+
+ + + + + + +
+ +
+
+ + +
+
+ +
+
+
+ +
+
+  + +

- c -

+
+
+ + + + + diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/globals_func_d.html b/sgx-jvm/linux-sgx/external/epid/doc/html/globals_func_d.html new file mode 100644 index 0000000000..b6f814ed21 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/globals_func_d.html @@ -0,0 +1,120 @@ + + + + + + + +Intel® Enhanced Privacy ID SDK: Globals + + + + + + + + + + + + +
+
+ + + + + + +
+ +
+
+ + +
+
+ +
+
+
+ +
+
+  + +

- d -

+
+
+ + + + + diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/globals_func_e.html b/sgx-jvm/linux-sgx/external/epid/doc/html/globals_func_e.html new file mode 100644 index 0000000000..e0bd93d98c --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/globals_func_e.html @@ -0,0 +1,287 @@ + + + + + + + +Intel® Enhanced Privacy ID SDK: Globals + + + + + + + + + + + + +
+
+ + + + + + +
+ +
+
+ + +
+
+ +
+
+
+ +
+
+  + +

- e -

+
+
+ + + + + diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/globals_func_f.html b/sgx-jvm/linux-sgx/external/epid/doc/html/globals_func_f.html new file mode 100644 index 0000000000..b3b0673c4a --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/globals_func_f.html @@ -0,0 +1,120 @@ + + + + + + + +Intel® Enhanced Privacy ID SDK: Globals + + + + + + + + + + + + +
+
+ + + + + + +
+ +
+
+ + +
+
+ +
+
+
+ +
+
+  + +

- f -

+
+
+ + + + + diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/globals_func_i.html b/sgx-jvm/linux-sgx/external/epid/doc/html/globals_func_i.html new file mode 100644 index 0000000000..26cdb45ccb --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/globals_func_i.html @@ -0,0 +1,83 @@ + + + + + + + +Intel® Enhanced Privacy ID SDK: Globals + + + + + + + + + + + + +
+
+ + + + + + +
+ +
+
+ + +
+
+ +
+
+
+ +
+
+  + +

- i -

+
+
+ + + + + diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/globals_func_m.html b/sgx-jvm/linux-sgx/external/epid/doc/html/globals_func_m.html new file mode 100644 index 0000000000..58fbba2e30 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/globals_func_m.html @@ -0,0 +1,80 @@ + + + + + + + +Intel® Enhanced Privacy ID SDK: Globals + + + + + + + + + + + + +
+
+ + + + + + +
+ +
+
+ + +
+
+ +
+
+
+ +
+
+  + +

- m -

+
+
+ + + + + diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/globals_func_n.html b/sgx-jvm/linux-sgx/external/epid/doc/html/globals_func_n.html new file mode 100644 index 0000000000..e940ff24a1 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/globals_func_n.html @@ -0,0 +1,107 @@ + + + + + + + +Intel® Enhanced Privacy ID SDK: Globals + + + + + + + + + + + + +
+
+ + + + + + +
+ +
+
+ + +
+
+ +
+
+
+ +
+
+  + +

- n -

+
+
+ + + + + diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/globals_func_o.html b/sgx-jvm/linux-sgx/external/epid/doc/html/globals_func_o.html new file mode 100644 index 0000000000..ec740c2fd9 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/globals_func_o.html @@ -0,0 +1,79 @@ + + + + + + + +Intel® Enhanced Privacy ID SDK: Globals + + + + + + + + + + + + +
+
+ + + + + + +
+ +
+
+ + +
+
+ +
+
+
+ +
+
+  + +

- o -

+
+
+ + + + + diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/globals_func_p.html b/sgx-jvm/linux-sgx/external/epid/doc/html/globals_func_p.html new file mode 100644 index 0000000000..61f42fdb0d --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/globals_func_p.html @@ -0,0 +1,128 @@ + + + + + + + +Intel® Enhanced Privacy ID SDK: Globals + + + + + + + + + + + + +
+
+ + + + + + +
+ +
+
+ + +
+
+ +
+
+
+ +
+
+  + +

- p -

+
+
+ + + + + diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/globals_func_r.html b/sgx-jvm/linux-sgx/external/epid/doc/html/globals_func_r.html new file mode 100644 index 0000000000..f4db740eae --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/globals_func_r.html @@ -0,0 +1,88 @@ + + + + + + + +Intel® Enhanced Privacy ID SDK: Globals + + + + + + + + + + + + +
+
+ + + + + + +
+ +
+
+ + +
+
+ +
+
+
+ +
+
+  + +

- r -

+
+
+ + + + + diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/globals_func_s.html b/sgx-jvm/linux-sgx/external/epid/doc/html/globals_func_s.html new file mode 100644 index 0000000000..8dad2c468e --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/globals_func_s.html @@ -0,0 +1,99 @@ + + + + + + + +Intel® Enhanced Privacy ID SDK: Globals + + + + + + + + + + + + +
+
+ + + + + + +
+ +
+
+ + +
+
+ +
+
+
+ +
+
+  + +

- s -

+
+
+ + + + + diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/globals_func_w.html b/sgx-jvm/linux-sgx/external/epid/doc/html/globals_func_w.html new file mode 100644 index 0000000000..378005ea04 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/globals_func_w.html @@ -0,0 +1,88 @@ + + + + + + + +Intel® Enhanced Privacy ID SDK: Globals + + + + + + + + + + + + +
+
+ + + + + + +
+ +
+
+ + +
+
+ +
+
+
+ +
+
+  + +

- w -

+
+
+ + + + + diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/globals_g.html b/sgx-jvm/linux-sgx/external/epid/doc/html/globals_g.html new file mode 100644 index 0000000000..363836c265 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/globals_g.html @@ -0,0 +1,79 @@ + + + + + + + +Intel® Enhanced Privacy ID SDK: Globals + + + + + + + + + + + + +
+
+ + + + + + +
+ +
+
+ + +
+
+ +
+
+
+ +
+
+
Here is a list of all documented functions, variables, defines, enums, and typedefs with links to the documentation:
+ +

- g -

+
+
+ + + + + diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/globals_h.html b/sgx-jvm/linux-sgx/external/epid/doc/html/globals_h.html new file mode 100644 index 0000000000..e45607a9d3 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/globals_h.html @@ -0,0 +1,79 @@ + + + + + + + +Intel® Enhanced Privacy ID SDK: Globals + + + + + + + + + + + + +
+
+ + + + + + +
+ +
+
+ + +
+
+ +
+
+
+ +
+
+
Here is a list of all documented functions, variables, defines, enums, and typedefs with links to the documentation:
+ +

- h -

+
+
+ + + + + diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/globals_i.html b/sgx-jvm/linux-sgx/external/epid/doc/html/globals_i.html new file mode 100644 index 0000000000..6d046c6a48 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/globals_i.html @@ -0,0 +1,89 @@ + + + + + + + +Intel® Enhanced Privacy ID SDK: Globals + + + + + + + + + + + + +
+
+ + + + + + +
+ +
+
+ + +
+
+ +
+
+
+ +
+
+
Here is a list of all documented functions, variables, defines, enums, and typedefs with links to the documentation:
+ +

- i -

+
+
+ + + + + diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/globals_k.html b/sgx-jvm/linux-sgx/external/epid/doc/html/globals_k.html new file mode 100644 index 0000000000..09524383ae --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/globals_k.html @@ -0,0 +1,188 @@ + + + + + + + +Intel® Enhanced Privacy ID SDK: Globals + + + + + + + + + + + + +
+
+ + + + + + +
+ +
+
+ + +
+
+ +
+
+
+ +
+
+
Here is a list of all documented functions, variables, defines, enums, and typedefs with links to the documentation:
+ +

- k -

+
+
+ + + + + diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/globals_m.html b/sgx-jvm/linux-sgx/external/epid/doc/html/globals_m.html new file mode 100644 index 0000000000..b6884640b0 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/globals_m.html @@ -0,0 +1,86 @@ + + + + + + + +Intel® Enhanced Privacy ID SDK: Globals + + + + + + + + + + + + +
+
+ + + + + + +
+ +
+
+ + +
+
+ +
+
+
+ +
+
+
Here is a list of all documented functions, variables, defines, enums, and typedefs with links to the documentation:
+ +

- m -

+
+
+ + + + + diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/globals_n.html b/sgx-jvm/linux-sgx/external/epid/doc/html/globals_n.html new file mode 100644 index 0000000000..1b72d4169b --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/globals_n.html @@ -0,0 +1,110 @@ + + + + + + + +Intel® Enhanced Privacy ID SDK: Globals + + + + + + + + + + + + +
+
+ + + + + + +
+ +
+
+ + +
+
+ +
+
+
+ +
+
+
Here is a list of all documented functions, variables, defines, enums, and typedefs with links to the documentation:
+ +

- n -

+
+
+ + + + + diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/globals_o.html b/sgx-jvm/linux-sgx/external/epid/doc/html/globals_o.html new file mode 100644 index 0000000000..8b0da4a790 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/globals_o.html @@ -0,0 +1,79 @@ + + + + + + + +Intel® Enhanced Privacy ID SDK: Globals + + + + + + + + + + + + +
+
+ + + + + + +
+ +
+
+ + +
+
+ +
+
+
+ +
+
+
Here is a list of all documented functions, variables, defines, enums, and typedefs with links to the documentation:
+ +

- o -

+
+
+ + + + + diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/globals_p.html b/sgx-jvm/linux-sgx/external/epid/doc/html/globals_p.html new file mode 100644 index 0000000000..196ac75dac --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/globals_p.html @@ -0,0 +1,137 @@ + + + + + + + +Intel® Enhanced Privacy ID SDK: Globals + + + + + + + + + + + + +
+
+ + + + + + +
+ +
+
+ + +
+
+ +
+
+
+ +
+
+
Here is a list of all documented functions, variables, defines, enums, and typedefs with links to the documentation:
+ +

- p -

+
+
+ + + + + diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/globals_r.html b/sgx-jvm/linux-sgx/external/epid/doc/html/globals_r.html new file mode 100644 index 0000000000..a3f9836ed2 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/globals_r.html @@ -0,0 +1,100 @@ + + + + + + + +Intel® Enhanced Privacy ID SDK: Globals + + + + + + + + + + + + +
+
+ + + + + + +
+ +
+
+ + +
+
+ +
+
+
+ +
+
+
Here is a list of all documented functions, variables, defines, enums, and typedefs with links to the documentation:
+ +

- r -

+
+
+ + + + + diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/globals_s.html b/sgx-jvm/linux-sgx/external/epid/doc/html/globals_s.html new file mode 100644 index 0000000000..91f6e87aa2 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/globals_s.html @@ -0,0 +1,114 @@ + + + + + + + +Intel® Enhanced Privacy ID SDK: Globals + + + + + + + + + + + + +
+
+ + + + + + +
+ +
+
+ + +
+
+ +
+
+
+ +
+
+
Here is a list of all documented functions, variables, defines, enums, and typedefs with links to the documentation:
+ +

- s -

+
+
+ + + + + diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/globals_t.html b/sgx-jvm/linux-sgx/external/epid/doc/html/globals_t.html new file mode 100644 index 0000000000..a6e1ee10d6 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/globals_t.html @@ -0,0 +1,79 @@ + + + + + + + +Intel® Enhanced Privacy ID SDK: Globals + + + + + + + + + + + + +
+
+ + + + + + +
+ +
+
+ + +
+
+ +
+
+
+ +
+
+
Here is a list of all documented functions, variables, defines, enums, and typedefs with links to the documentation:
+ +

- t -

+
+
+ + + + + diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/globals_type.html b/sgx-jvm/linux-sgx/external/epid/doc/html/globals_type.html new file mode 100644 index 0000000000..8975797ee7 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/globals_type.html @@ -0,0 +1,110 @@ + + + + + + + +Intel® Enhanced Privacy ID SDK: Globals + + + + + + + + + + + + +
+
+ + + + + + +
+ +
+
+ + +
+
+ +
+
+
+ +
+
+
+
+ + + + + diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/globals_vars.html b/sgx-jvm/linux-sgx/external/epid/doc/html/globals_vars.html new file mode 100644 index 0000000000..80dfdade97 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/globals_vars.html @@ -0,0 +1,78 @@ + + + + + + + +Intel® Enhanced Privacy ID SDK: Globals + + + + + + + + + + + + +
+
+ + + + + + +
+ +
+
+ + +
+
+ +
+
+
+ +
+
+
+
+ + + + + diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/globals_w.html b/sgx-jvm/linux-sgx/external/epid/doc/html/globals_w.html new file mode 100644 index 0000000000..6a291796f8 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/globals_w.html @@ -0,0 +1,91 @@ + + + + + + + +Intel® Enhanced Privacy ID SDK: Globals + + + + + + + + + + + + +
+
+ + + + + + +
+ +
+
+ + +
+
+ +
+
+
+ +
+
+
Here is a list of all documented functions, variables, defines, enums, and typedefs with links to the documentation:
+ +

- w -

+
+
+ + + + + diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/glossary_8dox.html b/sgx-jvm/linux-sgx/external/epid/doc/html/glossary_8dox.html new file mode 100644 index 0000000000..268f395b34 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/glossary_8dox.html @@ -0,0 +1,82 @@ + + + + + + + +Intel® Enhanced Privacy ID SDK: doc/docsrc/glossary.dox File Reference + + + + + + + + + + + + +
+
+ + + + + + +
+ +
+
+ + +
+
+ +
+
+
+ +
+
+
+
doc/docsrc/glossary.dox File Reference
+
+
+ +

This file is used by Doxygen to generate documentation. +More...

+

Detailed Description

+

This file is used by Doxygen to generate documentation.

+
+
+ + + + + diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/group___big_num_primitives.html b/sgx-jvm/linux-sgx/external/epid/doc/html/group___big_num_primitives.html new file mode 100644 index 0000000000..c54ac40cb6 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/group___big_num_primitives.html @@ -0,0 +1,445 @@ + + + + + + + +Intel® Enhanced Privacy ID SDK: bignum + + + + + + + + + + + + +
+
+ + + + + + +
+ +
+
+ + +
+
+ +
+
+
+ +
+
+ +
+
bignum
+
+
+ +

Big number operations. +More...

+ + + + + +

+Typedefs

+typedef struct BigNum BigNum
 Internal representation of large numbers.
 
+ + + + + + + + + + + + + + + + + + + + + + + + + +

+Functions

EpidStatus NewBigNum (size_t data_size_bytes, BigNum **bignum)
 Constructs a new BigNum. More...
 
void DeleteBigNum (BigNum **bignum)
 Deletes a previously allocated BigNum. More...
 
EpidStatus ReadBigNum (void const *bn_str, size_t strlen, BigNum *bn)
 Deserializes a BigNum from a string. More...
 
EpidStatus WriteBigNum (BigNum const *bn, size_t strlen, void const *bn_str)
 Serializes a BigNum to a string. More...
 
EpidStatus BigNumAdd (BigNum const *a, BigNum const *b, BigNum *r)
 Adds two BigNum values. More...
 
EpidStatus BigNumSub (BigNum const *a, BigNum const *b, BigNum *r)
 Subtracts two BigNum values. More...
 
EpidStatus BigNumMul (BigNum const *a, BigNum const *b, BigNum *r)
 Multiplies two BigNum values. More...
 
EpidStatus BigNumMod (BigNum const *a, BigNum const *b, BigNum *r)
 Computes modular reduction for BigNum value by specified modulus. More...
 
+

Detailed Description

+

Big number operations.

+

This module provides an API for working with large numbers. BigNums represent non-negative integers.

+

Each BigNum variable represents a number of a byte-size set when the variable was created. BigNum variables cannot be re-sized after they are created.

+

Function Documentation

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
EpidStatus BigNumAdd (BigNum const * a,
BigNum const * b,
BigNumr 
)
+
+ +

Adds two BigNum values.

+
Parameters
+ + + + +
[in]aThe left hand parameter.
[in]bThe right hand parameter.
[out]rThe result of adding a and b.
+
+
+
Returns
EpidStatus
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
EpidStatus BigNumMod (BigNum const * a,
BigNum const * b,
BigNumr 
)
+
+ +

Computes modular reduction for BigNum value by specified modulus.

+
Parameters
+ + + + +
[in]aThe BigNum value.
[in]bThe modulus.
[out]rModular reduction result.
+
+
+
Returns
EpidStatus
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
EpidStatus BigNumMul (BigNum const * a,
BigNum const * b,
BigNumr 
)
+
+ +

Multiplies two BigNum values.

+
Parameters
+ + + + +
[in]aThe left hand parameter.
[in]bThe right hand parameter.
[out]rThe result of multiplying a and b.
+
+
+
Returns
EpidStatus
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
EpidStatus BigNumSub (BigNum const * a,
BigNum const * b,
BigNumr 
)
+
+ +

Subtracts two BigNum values.

+
Parameters
+ + + + +
[in]aThe left hand parameter.
[in]bThe right hand parameter.
[out]rThe result of subtracting a and b.
+
+
+
Returns
EpidStatus
+ +
+
+ +
+
+ + + + + + + + +
void DeleteBigNum (BigNum ** bignum)
+
+ +

Deletes a previously allocated BigNum.

+

Frees memory pointed to by bignum. Nulls the pointer.

+
Parameters
+ + +
[in]bignumThe BigNum. Can be NULL.
+
+
+
See also
NewBigNum
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + +
EpidStatus NewBigNum (size_t data_size_bytes,
BigNum ** bignum 
)
+
+ +

Constructs a new BigNum.

+

Allocates memory and creates a new BigNum.

+

Use DeleteBigNum() to free memory.

+
Parameters
+ + + +
[in]data_size_bytesThe size in bytes of the new number.
[out]bignumThe BigNum.
+
+
+
Returns
EpidStatus
+
See also
DeleteBigNum
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
EpidStatus ReadBigNum (void const * bn_str,
size_t strlen,
BigNumbn 
)
+
+ +

Deserializes a BigNum from a string.

+
Parameters
+ + + + +
[in]bn_strThe serialized value.
[in]strlenThe size of bn_str in bytes.
[out]bnThe target BigNum.
+
+
+
Returns
EpidStatus
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
EpidStatus WriteBigNum (BigNum const * bn,
size_t strlen,
void const * bn_str 
)
+
+ +

Serializes a BigNum to a string.

+
Parameters
+ + + + +
[in]bnThe BigNum to be serialized.
[in]strlenThe size of bn_str in bytes.
[out]bn_strThe target string.
+
+
+
Returns
EpidStatus
+ +
+
+
+
+ + + + + diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/group___big_num_primitives.js b/sgx-jvm/linux-sgx/external/epid/doc/html/group___big_num_primitives.js new file mode 100644 index 0000000000..d4354d5148 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/group___big_num_primitives.js @@ -0,0 +1,12 @@ +var group___big_num_primitives = +[ + [ "BigNum", "group___big_num_primitives.html#ga2bf153e27be2683f0fb26f0f7ff1f718", null ], + [ "BigNumAdd", "group___big_num_primitives.html#gae70fd9b3026f0ab3c7e9601d0a3186b8", null ], + [ "BigNumMod", "group___big_num_primitives.html#ga7dd6038987210d10bf843602fef0c929", null ], + [ "BigNumMul", "group___big_num_primitives.html#ga03c89b8b8dd87de2c0f4b5822145d317", null ], + [ "BigNumSub", "group___big_num_primitives.html#gacbec9669ab0fe768e2be74dcaca397ea", null ], + [ "DeleteBigNum", "group___big_num_primitives.html#ga2d17600068b1d94000635c6644258a03", null ], + [ "NewBigNum", "group___big_num_primitives.html#gad5f6f262bfd780fed3678bcee16f0aed", null ], + [ "ReadBigNum", "group___big_num_primitives.html#ga808cf477b70ed06358b11756bfe36024", null ], + [ "WriteBigNum", "group___big_num_primitives.html#ga47f356d816bcb5742ba6d78000861328", null ] +]; \ No newline at end of file diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/group___ec_group_primitives.html b/sgx-jvm/linux-sgx/external/epid/doc/html/group___ec_group_primitives.html new file mode 100644 index 0000000000..de489f9e26 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/group___ec_group_primitives.html @@ -0,0 +1,1078 @@ + + + + + + + +Intel® Enhanced Privacy ID SDK: ecgroup + + + + + + + + + + + + +
+
+ + + + + + +
+ +
+
+ + +
+
+ +
+
+
+ +
+
+ +
+
ecgroup
+
+
+ +

Elliptic curve group operations. +More...

+ + + + + + + + +

+Typedefs

+typedef struct EcGroup EcGroup
 Elliptic curve group over finite field.
 
+typedef struct EcPoint EcPoint
 Point on elliptic curve over finite field.
 
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Functions

EpidStatus NewEcGroup (FiniteField const *ff, FfElement const *a, FfElement const *b, FfElement const *x, FfElement const *y, BigNum const *order, BigNum const *cofactor, EcGroup **g)
 Constructs a new EcGroup. More...
 
void DeleteEcGroup (EcGroup **g)
 Deletes a previously allocated EcGroup. More...
 
EpidStatus NewEcPoint (EcGroup const *g, EcPoint **p)
 Creates a new EcPoint. More...
 
void DeleteEcPoint (EcPoint **p)
 Deletes a previously allocated EcPoint. More...
 
EpidStatus ReadEcPoint (EcGroup *g, void const *p_str, size_t strlen, EcPoint *p)
 Deserializes an EcPoint from a string. More...
 
EpidStatus WriteEcPoint (EcGroup *g, EcPoint const *p, void *p_str, size_t strlen)
 Serializes an EcPoint to a string. More...
 
EpidStatus EcMul (EcGroup *g, EcPoint const *a, EcPoint const *b, EcPoint *r)
 Multiplies two elements in an elliptic curve group. More...
 
EpidStatus EcExp (EcGroup *g, EcPoint const *a, BigNumStr const *b, EcPoint *r)
 Raises a point in an elliptic curve group to a power. More...
 
EpidStatus EcSscmExp (EcGroup *g, EcPoint const *a, BigNumStr const *b, EcPoint *r)
 Software side-channel mitigated implementation of EcExp. More...
 
EpidStatus EcMultiExp (EcGroup *g, EcPoint const **a, BigNumStr const **b, size_t m, EcPoint *r)
 Multi-exponentiates elements in elliptic curve group. More...
 
EpidStatus EcSscmMultiExp (EcGroup *g, EcPoint const **a, BigNumStr const **b, size_t m, EcPoint *r)
 Software side-channel mitigated implementation of EcMultiExp. More...
 
EpidStatus EcGetRandom (EcGroup *g, BitSupplier rnd_func, void *rnd_func_param, EcPoint *r)
 Generates a random element from an elliptic curve group. More...
 
EpidStatus EcInGroup (EcGroup *g, void const *p_str, size_t strlen, bool *in_group)
 Checks if a point is in an elliptic curve group. More...
 
EpidStatus EcHash (EcGroup *g, void const *msg, size_t msg_len, HashAlg hash_alg, EcPoint *r)
 Hashes an arbitrary message to an element in an elliptic curve group. More...
 
EpidStatus EcMakePoint (EcGroup *g, FfElement const *x, EcPoint *r)
 Sets an EcPoint variable to a point on a curve. More...
 
EpidStatus EcInverse (EcGroup *g, EcPoint const *p, EcPoint *r)
 Computes the additive inverse of an EcPoint. More...
 
EpidStatus EcIsEqual (EcGroup *g, EcPoint const *a, EcPoint const *b, bool *is_equal)
 Checks if two EcPoints are equal. More...
 
EpidStatus EcIsIdentity (EcGroup *g, EcPoint const *p, bool *is_identity)
 Checks if an EcPoint is the identity element. More...
 
+

Detailed Description

+

Elliptic curve group operations.

+

Provides APIs for working with Elliptic curve groups. Elliptic curve groups allow simple mathematical operations based on points that lie on a defined elliptic curve. The results of these operations also lie on the same curve.

+

Curves themselves are defined based on elements (FfElement) of a finite field (FiniteField).

+

Function Documentation

+ +
+
+ + + + + + + + +
void DeleteEcGroup (EcGroup ** g)
+
+ +

Deletes a previously allocated EcGroup.

+

Frees memory pointed to by elliptic curve group. Nulls the pointer.

+
Parameters
+ + +
[in]gThe elliptic curve group. Can be NULL.
+
+
+
See also
NewEcGroup
+ +
+
+ +
+
+ + + + + + + + +
void DeleteEcPoint (EcPoint ** p)
+
+ +

Deletes a previously allocated EcPoint.

+

Frees memory used by a point on elliptic curve group. Nulls the pointer.

+
Parameters
+ + +
[in]pThe EcPoint. Can be NULL.
+
+
+
See also
NewEcPoint
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
EpidStatus EcExp (EcGroupg,
EcPoint const * a,
BigNumStr const * b,
EcPointr 
)
+
+ +

Raises a point in an elliptic curve group to a power.

+

This exponentiation operation is also known as element multiplication for elliptic curve groups.

Parameters
+ + + + + +
[in]gThe elliptic curve group.
[in]aThe base.
[in]bThe power. Power must be less than the order of the elliptic curve group.
[out]rThe result of raising a to the power b.
+
+
+
Returns
EpidStatus
+
See also
NewEcGroup
+
+NewEcPoint
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
EpidStatus EcGetRandom (EcGroupg,
BitSupplier rnd_func,
void * rnd_func_param,
EcPointr 
)
+
+ +

Generates a random element from an elliptic curve group.

+

This function is only available for G1 and GT.

+
Parameters
+ + + + + +
[in]gThe elliptic curve group.
[in]rnd_funcRandom number generator.
[in]rnd_func_paramPass through context data for rnd_func.
[in,out]rOutput random elliptic curve element.
+
+
+
Returns
EpidStatus
+
See also
NewEcPoint
+
+BitSupplier
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
EpidStatus EcHash (EcGroupg,
void const * msg,
size_t msg_len,
HashAlg hash_alg,
EcPointr 
)
+
+ +

Hashes an arbitrary message to an element in an elliptic curve group.

+
Parameters
+ + + + + + +
[in]gThe elliptic curve group.
[in]msgThe message.
[in]msg_lenThe size of msg in bytes.
[in]hash_algThe hash algorithm.
[out]rThe hashed value.
+
+
+
Returns
EpidStatus
+
See also
NewEcGroup
+
+NewEcPoint
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
EpidStatus EcInGroup (EcGroupg,
void const * p_str,
size_t strlen,
boolin_group 
)
+
+ +

Checks if a point is in an elliptic curve group.

+
Parameters
+ + + + + +
[in]gThe elliptic curve group.
[in]p_strA serialized point. Must be a G1ElemStr or G2ElemStr.
[in]strlenThe size of p_str in bytes.
[out]in_groupThe result of the check.
+
+
+
Returns
EpidStatus
+
See also
NewEcPoint
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
EpidStatus EcInverse (EcGroupg,
EcPoint const * p,
EcPointr 
)
+
+ +

Computes the additive inverse of an EcPoint.

+

This inverse operation is also known as element negation for elliptic curve groups.

+
Parameters
+ + + + +
[in]gThe elliptic curve group.
[in]pThe point.
[out]rThe inverted point.
+
+
+
Returns
EpidStatus
+
See also
NewEcGroup
+
+NewEcPoint
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
EpidStatus EcIsEqual (EcGroupg,
EcPoint const * a,
EcPoint const * b,
boolis_equal 
)
+
+ +

Checks if two EcPoints are equal.

+
Parameters
+ + + + + +
[in]gThe elliptic curve group.
[in]aA point to check.
[in]bAnother point to check.
[out]is_equalThe result of the check.
+
+
+
Returns
EpidStatus
+
See also
NewEcGroup
+
+NewEcPoint
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
EpidStatus EcIsIdentity (EcGroupg,
EcPoint const * p,
boolis_identity 
)
+
+ +

Checks if an EcPoint is the identity element.

+

Takes a group element P as input. It outputs true if P is the identity element of G. Otherwise, it outputs false.

+
Parameters
+ + + + +
[in]gThe elliptic curve group.
[in]pThe point to check.
[out]is_identityThe result of the check.
+
+
+
Returns
EpidStatus
+
See also
NewEcGroup
+
+NewEcPoint
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
EpidStatus EcMakePoint (EcGroupg,
FfElement const * x,
EcPointr 
)
+
+ +

Sets an EcPoint variable to a point on a curve.

+

This function is only available for G1.

+
Parameters
+ + + + +
[in]gThe elliptic curve group.
[in]xThe x coordinate.
[out]rThe point.
+
+
+
Returns
EpidStatus
+
See also
NewEcGroup
+
+NewEcPoint
+
+NewFfElement
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
EpidStatus EcMul (EcGroupg,
EcPoint const * a,
EcPoint const * b,
EcPointr 
)
+
+ +

Multiplies two elements in an elliptic curve group.

+

This multiplication operation is also known as element addition for elliptic curve groups.

+
Parameters
+ + + + + +
[in]gThe elliptic curve group.
[in]aThe left hand parameter.
[in]bThe right hand parameter.
[out]rThe result of multiplying a and b.
+
+
+
Returns
EpidStatus
+
See also
NewEcGroup
+
+NewEcPoint
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
EpidStatus EcMultiExp (EcGroupg,
EcPoint const ** a,
BigNumStr const ** b,
size_t m,
EcPointr 
)
+
+ +

Multi-exponentiates elements in elliptic curve group.

+

Takes a group elements a[0], ... , a[m-1] in G and positive integers b[0], ..., b[m-1], where m is a small positive integer. Outputs r (in G) = EcExp(a[0],b[0]) * ... * EcExp(a[m-1],b[m-1]).

+
Parameters
+ + + + + + +
[in]gThe elliptic curve group.
[in]aThe bases.
[in]bThe powers. Power must be less than the order of the elliptic curve group.
[in]mNumber of entries in a and b.
[out]rThe result of raising each a to the corresponding power b and multiplying the results.
+
+
+
Returns
EpidStatus
+
See also
NewEcGroup
+
+NewEcPoint
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
EpidStatus EcSscmExp (EcGroupg,
EcPoint const * a,
BigNumStr const * b,
EcPointr 
)
+
+ +

Software side-channel mitigated implementation of EcExp.

+

This exponentiation operation is also known as element multiplication for elliptic curve groups.

+
Attention
The reference implementation of EcSscmExp calls EcExp directly because the implementation of EcExp is already side channel mitigated. Implementers providing their own versions of this function are responsible for ensuring that EcSscmExp is side channel mitigated per section 8 of the Intel(R) EPID 2.0 spec.
+
Parameters
+ + + + + +
[in]gThe elliptic curve group.
[in]aThe base.
[in]bThe power. Power must be less than the order of the elliptic curve group.
[out]rThe result of raising a to the power b.
+
+
+
Returns
EpidStatus
+
See also
NewEcGroup
+
+NewEcPoint
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
EpidStatus EcSscmMultiExp (EcGroupg,
EcPoint const ** a,
BigNumStr const ** b,
size_t m,
EcPointr 
)
+
+ +

Software side-channel mitigated implementation of EcMultiExp.

+

Takes a group elements a[0], ... , a[m-1] in G and positive integers b[0], ..., b[m-1], where m is a small positive integer. Outputs r (in G) = EcExp(a[0],b[0]) * ... * EcExp(a[m-1],b[m-1]).

+
Attention
The reference implementation of EcSscmMultiExp calls EcMultiExp directly because the implementation of EcMultiExp is already side channel mitigated. Implementers providing their own versions of this function are responsible for ensuring that EcSscmMultiExp is side channel mitigated per section 8 of the Intel(R) EPID 2.0 spec.
+
Parameters
+ + + + + + +
[in]gThe elliptic curve group.
[in]aThe bases.
[in]bThe powers. Power must be less than the order of the elliptic curve group.
[in]mNumber of entries in a and b.
[out]rThe result of raising each a to the corresponding power b and multiplying the results.
+
+
+
Returns
EpidStatus
+
See also
NewEcGroup
+
+NewEcPoint
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
EpidStatus NewEcGroup (FiniteField const * ff,
FfElement const * a,
FfElement const * b,
FfElement const * x,
FfElement const * y,
BigNum const * order,
BigNum const * cofactor,
EcGroup ** g 
)
+
+ +

Constructs a new EcGroup.

+

Allocates memory and creates a new elliptic curve group.

+

Use DeleteFiniteField() to free memory.

+
Parameters
+ + + + + + + + + +
[in]ffThe finite field on which the curve is based.
[in]aThe A value of the elliptic curve.
[in]bThe B value of the elliptic curve.
[in]xThe X co-ordinate of the base point of the elliptic curve.
[in]yThe Y co-ordinate of the base point of the elliptic curve.
[in]orderThe order of the elliptic curve group.
[in]cofactorThe co-factor of the elliptic curve.
[out]gThe newly constructed elliptic curve group.
+
+
+
Returns
EpidStatus
+
See also
DeleteEcGroup
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + +
EpidStatus NewEcPoint (EcGroup const * g,
EcPoint ** p 
)
+
+ +

Creates a new EcPoint.

+

Allocates memory and creates a new point on elliptic curve group.

+

Use DeleteEcPoint() to free memory.

+
Parameters
+ + + +
[in]gElliptic curve group.
[out]pNewly constructed point on the elliptic curve group g.
+
+
+
Returns
EpidStatus
+
See also
NewEcGroup
+
+DeleteEcPoint
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
EpidStatus ReadEcPoint (EcGroupg,
void const * p_str,
size_t strlen,
EcPointp 
)
+
+ +

Deserializes an EcPoint from a string.

+
Parameters
+ + + + + +
[in]gThe elliptic curve group.
[in]p_strThe serialized value.
[in]strlenThe size of p_str in bytes.
[out]pThe target EcPoint.
+
+
+
Returns
EpidStatus
+
See also
NewEcPoint
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
EpidStatus WriteEcPoint (EcGroupg,
EcPoint const * p,
void * p_str,
size_t strlen 
)
+
+ +

Serializes an EcPoint to a string.

+
Parameters
+ + + + + +
[in]gThe elliptic curve group.
[in]pThe EcPoint to be serialized.
[out]p_strThe target string.
[in]strlenthe size of p_str in bytes.
+
+
+
Returns
EpidStatus
+
See also
NewEcPoint
+ +
+
+
+
+ + + + + diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/group___ec_group_primitives.js b/sgx-jvm/linux-sgx/external/epid/doc/html/group___ec_group_primitives.js new file mode 100644 index 0000000000..bf32859b49 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/group___ec_group_primitives.js @@ -0,0 +1,23 @@ +var group___ec_group_primitives = +[ + [ "EcGroup", "group___ec_group_primitives.html#gac91c5a7623c17a868dd15b2e9aaf7159", null ], + [ "EcPoint", "group___ec_group_primitives.html#ga85c1d5e106031b385a6e23e598ac98fa", null ], + [ "DeleteEcGroup", "group___ec_group_primitives.html#gab7af276256c27610eda85ff432b846ea", null ], + [ "DeleteEcPoint", "group___ec_group_primitives.html#ga8cb086d792bffb79b3ca07e6ca4ce0e7", null ], + [ "EcExp", "group___ec_group_primitives.html#ga01bf8d6fa60a2e445490966b3a06c270", null ], + [ "EcGetRandom", "group___ec_group_primitives.html#ga3f96c43d14d24de0f7a5e214aef64196", null ], + [ "EcHash", "group___ec_group_primitives.html#gadc22ee07864a7ee681a881029b69d76a", null ], + [ "EcInGroup", "group___ec_group_primitives.html#ga4d0f32aede3066eae500241b387bd970", null ], + [ "EcInverse", "group___ec_group_primitives.html#ga0b6d7a3398251e9352fb29ef4abef466", null ], + [ "EcIsEqual", "group___ec_group_primitives.html#gad3b3c63c48fa24e8dea07837b05bc061", null ], + [ "EcIsIdentity", "group___ec_group_primitives.html#ga9cf15b34bc4ff12e58b169dd989d8210", null ], + [ "EcMakePoint", "group___ec_group_primitives.html#ga8a6114a48214a327d4ec04fd25e5940e", null ], + [ "EcMul", "group___ec_group_primitives.html#ga25c9013cc76907d73765eb7a96aa8c96", null ], + [ "EcMultiExp", "group___ec_group_primitives.html#gae96c38e004ccd2211290ad6e66415ec4", null ], + [ "EcSscmExp", "group___ec_group_primitives.html#gaf3b6a548aa6f0d4f028a14feca251f57", null ], + [ "EcSscmMultiExp", "group___ec_group_primitives.html#ga40e3431d3dbe8cf7a65ada7b7811cba4", null ], + [ "NewEcGroup", "group___ec_group_primitives.html#gaf4e23677dd378ef2e0cf55df79cbdb62", null ], + [ "NewEcPoint", "group___ec_group_primitives.html#ga6417b0ce72ba96de00c329e322fec7fb", null ], + [ "ReadEcPoint", "group___ec_group_primitives.html#ga2d433f567fa2419465a49604f4da21ad", null ], + [ "WriteEcPoint", "group___ec_group_primitives.html#ga4bb7d6691ffbb6e947c1068453e27fbd", null ] +]; \ No newline at end of file diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/group___ecdsa_primitives.html b/sgx-jvm/linux-sgx/external/epid/doc/html/group___ecdsa_primitives.html new file mode 100644 index 0000000000..e1c37b9239 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/group___ecdsa_primitives.html @@ -0,0 +1,229 @@ + + + + + + + +Intel® Enhanced Privacy ID SDK: ecdsa + + + + + + + + + + + + +
+
+ + + + + + +
+ +
+
+ + +
+
+ +
+
+
+ +
+
+ +
+
ecdsa
+
+
+ +

Elliptic Curve Digital Signature Algorithm Primitives. +More...

+ + + + + + + + +

+Functions

EpidStatus EcdsaVerifyBuffer (void const *buf, size_t buf_len, EcdsaPublicKey const *pubkey, EcdsaSignature const *sig)
 Verifies authenticity of a digital signature over a buffer. More...
 
EpidStatus EcdsaSignBuffer (void const *buf, size_t buf_len, EcdsaPrivateKey const *privkey, BitSupplier rnd_func, void *rnd_param, EcdsaSignature *sig)
 Creates ECDSA signature of buffer. More...
 
+

Detailed Description

+

Elliptic Curve Digital Signature Algorithm Primitives.

+

Provides APIs for computing and checking buffer signatures using the Elliptic Curve Digital Signature Algorithm.

+

Function Documentation

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
EpidStatus EcdsaSignBuffer (void const * buf,
size_t buf_len,
EcdsaPrivateKey const * privkey,
BitSupplier rnd_func,
void * rnd_param,
EcdsaSignaturesig 
)
+
+ +

Creates ECDSA signature of buffer.

+

Uses Elliptic Curve Digital Signature Algorithm (ECDSA) to generate a signature of the SHA256 hash of the input buffer with the provided private key.

+

The operation is over the standard secp256r1 curve.

+
Parameters
+ + + + + + + +
[in]bufPointer to buffer containing message to sign.
[in]buf_lenThe size of buf in bytes.
[in]privkeyThe ECDSA private key on secp256r1 curve.
[in]rnd_funcRandom number generator.
[in]rnd_paramPass through context data for rnd_func.
[out]sigThe resulting ECDSA signature.
+
+
+
Returns
EpidStatus
+
Return values
+ + +
kEpidRandMaxIterErrFailed to sign after maximum number of iterations due to bad luck in random number generation.
+
+
+
See also
EcdsaSignBuffer
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
EpidStatus EcdsaVerifyBuffer (void const * buf,
size_t buf_len,
EcdsaPublicKey const * pubkey,
EcdsaSignature const * sig 
)
+
+ +

Verifies authenticity of a digital signature over a buffer.

+

Uses Elliptic Curve Digital Signature Algorithm (ECDSA) to verify that the SHA256 hash of the input buffer was signed with the private key corresponding to the provided public key.

+

The operation is over the standard secp256r1 curve.

+
Warning
It is the responsibility of the caller to verify the identity of the public key.
+
Parameters
+ + + + + +
[in]bufPointer to buffer containing message to verify.
[in]buf_lenThe size of buf in bytes.
[in]pubkeyThe ECDSA public key on secp256r1 curve.
[in]sigThe ECDSA signature to be verified.
+
+
+
Returns
EpidStatus
+
Return values
+ + + +
kEpidSigValidEcdsaSignature is valid for the given buffer.
kEpidSigInvalidEcdsaSignature is invalid for the given buffer.
+
+
+
See also
EcdsaSignBuffer
+ +
+
+
+
+ + + + + diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/group___ecdsa_primitives.js b/sgx-jvm/linux-sgx/external/epid/doc/html/group___ecdsa_primitives.js new file mode 100644 index 0000000000..37f85bf007 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/group___ecdsa_primitives.js @@ -0,0 +1,5 @@ +var group___ecdsa_primitives = +[ + [ "EcdsaSignBuffer", "group___ecdsa_primitives.html#ga67091ecae643c1b8a0b0a4946eda7afe", null ], + [ "EcdsaVerifyBuffer", "group___ecdsa_primitives.html#gaab68de7291db6e42a01e99c2fa40057f", null ] +]; \ No newline at end of file diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/group___epid_common.html b/sgx-jvm/linux-sgx/external/epid/doc/html/group___epid_common.html new file mode 100644 index 0000000000..e0940043c1 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/group___epid_common.html @@ -0,0 +1,1066 @@ + + + + + + + +Intel® Enhanced Privacy ID SDK: common + + + + + + + + + + + + +
+
+ + + + + + +
+ +
+
+ + +
+
+ +
+
+
+ +
+ +
+ +

Common code shared between core sub-components. +More...

+ + + + + + + + + + + + + + + + + +

+Modules

 math
 Math Primitives and Group Operations.
 
 errors
 Error reporting interface.
 
 fileparser
 Parser for issuer material.
 
 print_utils
 Debug print routines.
 
 types
 SDK data types.
 
+ + + + + + + + + + + + + +

+Data Structures

struct  CommitValues
 Storage for values to create commitment in Sign and Verify algorithms. More...
 
struct  Epid2Params_
 Internal representation of Epid2Params. More...
 
struct  GroupPubKey_
 Internal representation of GroupPubKey. More...
 
struct  PrivKey_
 Internal implementation of PrivKey. More...
 
+ + + + + + + + + + + + + + + + +

+Macros

#define ntohl(u32)
 Macros to transform oct str 32 into uint_32. More...
 
+#define EPID_ENABLE_EPID_ZERO_MEMORY_ON_FREE
 When enabled secrets are wiped out from the memory by EpidFree.
 
+#define SAFE_ALLOC(size)   EpidAlloc(size);
 Allocates zero initalized block of memory.
 
#define SAFE_FREE(ptr)
 Deallocates space allocated by SAFE_ALLOC() and nulls pointer. More...
 
+#define SAFE_REALLOC(ptr, size)   EpidRealloc((ptr), (size))
 Changes the size of the memory block pointed to by ptr.
 
+ + + + +

+Typedefs

typedef int(__STDCALL * BitSupplier) (unsigned int *rand_data, int num_bits, void *user_data)
 Generates random data. More...
 
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Functions

EpidStatus SetKeySpecificCommitValues (GroupPubKey const *pub_key, CommitValues *values)
 Set group public key related fields from CommitValues structure. More...
 
EpidStatus SetCalculatedCommitValues (G1ElemStr const *B, G1ElemStr const *K, G1ElemStr const *T, EcPoint const *R1, EcGroup *G1, FfElement const *R2, FiniteField *GT, CommitValues *values)
 Set CommitValues structure fields calculated in algorithm. More...
 
EpidStatus CalculateCommitmentHash (CommitValues const *values, FiniteField *Fp, HashAlg hash_alg, void const *msg, size_t msg_len, FfElement *c)
 Calculate Fp.hash(t3 || m) for Sign and Verfiy algorithms. More...
 
EpidStatus CreateEpid2Params (Epid2Params_ **params)
 Constructs the internal representation of Epid2Params. More...
 
void DeleteEpid2Params (Epid2Params_ **epid_params)
 Deallocates storage for internal representation of Epid2Params. More...
 
EpidStatus CreateGroupPubKey (GroupPubKey const *pub_key_str, EcGroup *G1, EcGroup *G2, GroupPubKey_ **pub_key)
 Constructs internal representation of GroupPubKey. More...
 
void DeleteGroupPubKey (GroupPubKey_ **pub_key)
 Deallocates storage for internal representation of GroupPubKey. More...
 
void EpidZeroMemory (void *ptr, size_t size)
 Clear information stored in block of memory pointer to by ptr. More...
 
void * EpidAlloc (size_t size)
 Allocates memory of size bytes. More...
 
void * EpidRealloc (void *ptr, size_t new_size)
 Reallocates memory allocated by EpidAlloc. More...
 
void EpidFree (void *ptr)
 Frees memory allocated by EpidAlloc. More...
 
int memcpy_S (void *dest, size_t destsz, void const *src, size_t count)
 Copies bytes between buffers with security ehancements. More...
 
bool IsSigRlValid (GroupId const *gid, SigRl const *sig_rl, size_t sig_rl_size)
 Function to verify if signature based revocation list is valid. More...
 
bool CreateStack (size_t element_size, Stack **stack)
 Create stack. More...
 
void * StackPushN (Stack *stack, size_t n, void *elements)
 Push multiple elements to the stack. More...
 
bool StackPopN (Stack *stack, size_t n, void *elements)
 Pop multiple elements from the stack. More...
 
size_t StackGetSize (Stack const *stack)
 Get number of elements in the stack. More...
 
void DeleteStack (Stack **stack)
 Deallocates memory used for the stack. More...
 
EpidStatus CreatePrivKey (PrivKey const *priv_key_str, EcGroup *G1, FiniteField *Fp, PrivKey_ **priv_key)
 Constructs internal representation of PrivKey. More...
 
void DeletePrivKey (PrivKey_ **priv_key)
 Deallocate storage for internal representation of PrivKey. More...
 
+

Detailed Description

+

Common code shared between core sub-components.

+

Constants, utility functions, and libraries that are used widely in the implementation or definition of APIs and samples.

+

Macro Definition Documentation

+ +
+
+ + + + + + + + +
#define ntohl( u32)
+
+Value:
((uint32_t)(((((unsigned char*)&(u32))[0]) << 24) + \
((((unsigned char*)&(u32))[1]) << 16) + \
((((unsigned char*)&(u32))[2]) << 8) + \
(((unsigned char*)&(u32))[3])))
+

Macros to transform oct str 32 into uint_32.

+ +
+
+ +
+
+ + + + + + + + +
#define SAFE_FREE( ptr)
+
+Value:
{ \
if (NULL != (ptr)) { \
EpidFree(ptr); \
(ptr) = NULL; \
} \
}
+

Deallocates space allocated by SAFE_ALLOC() and nulls pointer.

+ +
+
+

Typedef Documentation

+ +
+
+ + + + +
typedef int(__STDCALL* BitSupplier) (unsigned int *rand_data, int num_bits, void *user_data)
+
+ +

Generates random data.

+

It is the responsibility of the caller of the SDK interfaces to implement a function of this prototype and to then pass a pointer to this function into methods that require it.

+
Parameters
+ + + + +
[out]rand_datadestination buffer
[in]num_bitssize of rand_data in bits
[in]user_datauser data passed through from api call.
+
+
+
Returns
zero on success and non-zero value on error.
+ +
+
+

Function Documentation

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
EpidStatus CalculateCommitmentHash (CommitValues const * values,
FiniteFieldFp,
HashAlg hash_alg,
void const * msg,
size_t msg_len,
FfElementc 
)
+
+ +

Calculate Fp.hash(t3 || m) for Sign and Verfiy algorithms.

+

Calculate c = Fp.hash(t3 || m) where t3 is Fp.hash(p || g1 || g2 || h1 || h2 || w || B || K || T || R1 || R2).

+
Parameters
+ + + + + + + +
[in]valuesCommit values to hash
[in]FpFinite field to perfom hash operation in
[in]hash_algHash algorithm to use
[in]msgMessage to hash
[in]msg_lenSize of msg buffer in bytes
[out]cResult of calculation
+
+
+
Returns
EpidStatus
+
See also
SetKeySpecificCommitValues
+
+SetCalculatedCommitValues
+ +
+
+ +
+
+ + + + + + + + +
EpidStatus CreateEpid2Params (Epid2Params_ ** params)
+
+ +

Constructs the internal representation of Epid2Params.

+

Allocates memory for the internal representation of Epid2Params. Initialize the Epid2Params. Use DeleteEpid2Params() to deallocate memory.

+
Parameters
+ + +
[in,out]paramsInternal Epid2Params
+
+
+
Returns
EpidStatus
+
See also
DeleteEpid2Params
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
EpidStatus CreateGroupPubKey (GroupPubKey const * pub_key_str,
EcGroupG1,
EcGroupG2,
GroupPubKey_ ** pub_key 
)
+
+ +

Constructs internal representation of GroupPubKey.

+

Allocates memory and initializes gid, h1, h2, w parameters. Use DeleteGroupPubKey() to deallocate memory

+
Parameters
+ + + + + +
[in]pub_key_strOct string representation of group public key
[in]G1EcGroup containing elements h1 and h2
[in]G2EcGroup containing element w
[out]pub_keyGroup public key: (gid, h1, h2, w)
+
+
+
Returns
EpidStatus
+
See also
DeleteGroupPubKey
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
EpidStatus CreatePrivKey (PrivKey const * priv_key_str,
EcGroupG1,
FiniteFieldFp,
PrivKey_ ** priv_key 
)
+
+ +

Constructs internal representation of PrivKey.

+

This function allocates memory and initializes gid, A, x, f parameters.

+
Parameters
+ + + + + +
[in]priv_key_strSerialized representation of private key
[in]G1EcGroup containing element A
[in]FpFiniteField containing elements x and f
[out]priv_keyNewly created private key: (gid, A, x, f)
+
+
+
Returns
EpidStatus
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + +
bool CreateStack (size_t element_size,
Stack ** stack 
)
+
+ +

Create stack.

+
Parameters
+ + + +
[in]element_sizeSize of stack element
[out]stackStack context to be created
+
+
+
Returns
true is operation succeed, false if stack were failed to allocate
+
See also
DeleteStack
+ +
+
+ +
+
+ + + + + + + + +
void DeleteEpid2Params (Epid2Params_ ** epid_params)
+
+ +

Deallocates storage for internal representation of Epid2Params.

+

Frees the memory and nulls the pointer.

+
Parameters
+ + +
[in,out]epid_paramsparams to be deallocated
+
+
+
See also
CreateEpid2Params
+ +
+
+ +
+
+ + + + + + + + +
void DeleteGroupPubKey (GroupPubKey_ ** pub_key)
+
+ +

Deallocates storage for internal representation of GroupPubKey.

+

Frees memory pointed to by Group public key. Nulls the pointer.

+
Parameters
+ + +
[in]pub_keyGroup public key to be freed
+
+
+
See also
CreateGroupPubKey
+ +
+
+ +
+
+ + + + + + + + +
void DeletePrivKey (PrivKey_ ** priv_key)
+
+ +

Deallocate storage for internal representation of PrivKey.

+

Frees memory pointed to by Member private key. Nulls the pointer.

+
Parameters
+ + +
[in]priv_keyMember private key to be freed
+
+
+ +
+
+ +
+
+ + + + + + + + +
void DeleteStack (Stack ** stack)
+
+ +

Deallocates memory used for the stack.

+
Parameters
+ + +
[in,out]stackStack context
+
+
+
See also
CreateStack
+ +
+
+ +
+
+ + + + + + + + +
void* EpidAlloc (size_t size)
+
+ +

Allocates memory of size bytes.

+

The content of memory is initialized with zeros. Memory must be freed with EpidFree function.

+
Parameters
+ + +
[in]sizenumber of bytes to allocate
+
+
+
Returns
pointer to allocated memory.
+ +
+
+ +
+
+ + + + + + + + +
void EpidFree (void * ptr)
+
+ +

Frees memory allocated by EpidAlloc.

+

Clears information stored in the block of memory.

+
Parameters
+ + +
[in]ptrpointer to allocated memory block
+
+
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + +
void* EpidRealloc (void * ptr,
size_t new_size 
)
+
+ +

Reallocates memory allocated by EpidAlloc.

+

In case of error NULL pointer is returned and input memory block is not changed. Memory must be freed with EpidFree function.

+
Parameters
+ + + +
[in]ptrpointer to memory block to reallocate
[in]new_sizenumber of bytes to reallocate for
+
+
+
Returns
pointer to allocated memory.
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + +
void EpidZeroMemory (void * ptr,
size_t size 
)
+
+ +

Clear information stored in block of memory pointer to by ptr.

+
Warning
This function may be optimized away by some compilers. If it is, you should consider using a compiler or operating system specific memory sanitization function (e.g. memcpy_s or SecureZeroMemory).
+
Parameters
+ + + +
[in]ptrpointer to memory block
[in]sizenumber of bytes to clear
+
+
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
bool IsSigRlValid (GroupId const * gid,
SigRl const * sig_rl,
size_t sig_rl_size 
)
+
+ +

Function to verify if signature based revocation list is valid.

+
Parameters
+ + + + +
[in]gidGroup id
[in]sig_rlSignature based revocation list
[in]sig_rl_sizeSize of signature based revocation list
+
+
+
Returns
true if revocation list is valid
+
+false if revocation list is invalid
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
int memcpy_S (void * dest,
size_t destsz,
void const * src,
size_t count 
)
+
+ +

Copies bytes between buffers with security ehancements.

+

Copies count bytes from src to dest. If the source and destination overlap, the behavior is undefined.

+
Parameters
+ + + + + +
[out]destpointer to the object to copy to
[in]destszmax number of bytes to modify in the destination (typically the size of the destination object)
[in]srcpointer to the object to copy from
[in]countnumber of bytes to copy
+
+
+
Returns
zero on success and non-zero value on error.
+

Copies bytes between buffers with security ehancements.

+
Note
Implementation follows C11 memcpy_s but with checks always enabled
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
EpidStatus SetCalculatedCommitValues (G1ElemStr const * B,
G1ElemStr const * K,
G1ElemStr const * T,
EcPoint const * R1,
EcGroupG1,
FfElement const * R2,
FiniteFieldGT,
CommitValuesvalues 
)
+
+ +

Set CommitValues structure fields calculated in algorithm.

+

Set B, K, T, R1 and R2 fields of values argument.

+
Parameters
+ + + + + + + + + +
[in]BValue of B to set
[in]KValue of K to set
[in]TValue of T to set
[in]R1Value of R1 to set
[in]G1EcGroup containing element R1
[in]R2Value of R2 to set
[in]GTFiniteField containing element R2
[out]valuesPointer to CommitValues structure to fill.
+
+
+
Returns
EpidStatus
+
See also
CalculateCommitmentHash
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + +
EpidStatus SetKeySpecificCommitValues (GroupPubKey const * pub_key,
CommitValuesvalues 
)
+
+ +

Set group public key related fields from CommitValues structure.

+

Set p, g1, g2, h1, h2 and w fields of values argument.

+
Parameters
+ + + +
[in]pub_keyGroup public key
[out]valuesPointer to CommitValues structure to fill.
+
+
+
Returns
EpidStatus
+
See also
CalculateCommitmentHash
+ +
+
+ +
+
+ + + + + + + + +
size_t StackGetSize (Stack const * stack)
+
+ +

Get number of elements in the stack.

+
Parameters
+ + +
[in]stackStack context
+
+
+
Returns
Number of elements in the stack or 0 if stack is NULL
+
See also
CreateStack
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
bool StackPopN (Stackstack,
size_t n,
void * elements 
)
+
+ +

Pop multiple elements from the stack.

+
Parameters
+ + + + +
[in,out]stackStack context
[in]nNumber of elements to pop from the stack
[out]elementsPointer to a buffer to store elements removed from the stack
+
+
+
Returns
true is operation succeed, false otherwise
+
See also
CreateStack
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
void* StackPushN (Stackstack,
size_t n,
void * elements 
)
+
+ +

Push multiple elements to the stack.

+
Parameters
+ + + + +
[in,out]stackStack context
[in]nNumber of elements to push to the stack
[in]elementsArray of elements to push to the stack. Can be NULL
+
+
+
Returns
A pointer to an array of new elements in the stack or NULL if stack is empty or push operation were failed.
+
See also
CreateStack
+ +
+
+
+
+ + + + + diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/group___epid_common.js b/sgx-jvm/linux-sgx/external/epid/doc/html/group___epid_common.js new file mode 100644 index 0000000000..78783bcfb6 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/group___epid_common.js @@ -0,0 +1,76 @@ +var group___epid_common = +[ + [ "math", "group___epid_math.html", "group___epid_math" ], + [ "errors", "group___error_codes.html", "group___error_codes" ], + [ "fileparser", "group___file_parser.html", "group___file_parser" ], + [ "print_utils", "group___epid_print.html", "group___epid_print" ], + [ "types", "group___epid_types.html", "group___epid_types" ], + [ "CommitValues", "struct_commit_values.html", [ + [ "B", "struct_commit_values.html#abc97167d51a8d0669da9a8d97353db4d", null ], + [ "g1", "struct_commit_values.html#a22512a6efa7b7b0277b211be64f71c30", null ], + [ "g2", "struct_commit_values.html#af7022c18732bbee8c12328923a4a12a1", null ], + [ "h1", "struct_commit_values.html#a42297d157420f0b554bce8a8cbe95c46", null ], + [ "h2", "struct_commit_values.html#a4a93cb984bac3de47bb60511b382a074", null ], + [ "K", "struct_commit_values.html#a49f073d0132a51020c0bfc819ec0d619", null ], + [ "p", "struct_commit_values.html#af5bf0f288e76f28ce54fe2df813881ef", null ], + [ "R1", "struct_commit_values.html#a00f7731d75085be08f171771c8f43d30", null ], + [ "R2", "struct_commit_values.html#acb0d12e761fadb149924cdf21290b9bf", null ], + [ "T", "struct_commit_values.html#ab2da47fe5c28b4202658c5ad3523ea1a", null ], + [ "w", "struct_commit_values.html#ac00af9d3eeb74543808a9e52e692f614", null ] + ] ], + [ "Epid2Params_", "struct_epid2_params__.html", [ + [ "Fp", "struct_epid2_params__.html#a45d742532485af7f34d43606a3f96b5d", null ], + [ "Fq", "struct_epid2_params__.html#a9cd99a40a7427666ff4b940ed69f69a0", null ], + [ "Fq2", "struct_epid2_params__.html#aebda3f9b5ed6f015adc992216bacf29f", null ], + [ "Fq6", "struct_epid2_params__.html#af3e9afc48ec8274f15d10f5f991c0937", null ], + [ "g1", "struct_epid2_params__.html#a337490f043e867b6c8d92180a9120541", null ], + [ "G1", "struct_epid2_params__.html#ade20ba985bc9219832df78ee9d255ee5", null ], + [ "g2", "struct_epid2_params__.html#a20dcfa40dba6679f45f1b90a91791a5c", null ], + [ "G2", "struct_epid2_params__.html#ae15ab066b26bbf1be8772743d604c766", null ], + [ "GT", "struct_epid2_params__.html#ac085cbd970d89fb382b621fb2884e420", null ], + [ "neg", "struct_epid2_params__.html#a1e50604a1739e48e8588d666d33d03ef", null ], + [ "p", "struct_epid2_params__.html#ad90e9f295e28d3f93852e87e97640e76", null ], + [ "pairing_state", "struct_epid2_params__.html#a74aa52f336a194b20627f8a540196dd5", null ], + [ "q", "struct_epid2_params__.html#a6d56c3f4dff7e92a0738e7866208bf4d", null ], + [ "t", "struct_epid2_params__.html#a4bca3d05a46b1325ac2490ebeb460543", null ], + [ "xi", "struct_epid2_params__.html#a51a678f0f26804e0c6f3a4c55fcf6731", null ] + ] ], + [ "GroupPubKey_", "struct_group_pub_key__.html", [ + [ "gid", "struct_group_pub_key__.html#afd2192bfd1e24c09951d9c0200a74f95", null ], + [ "h1", "struct_group_pub_key__.html#a2322bc1b42f85e0d01b50b15d064f840", null ], + [ "h2", "struct_group_pub_key__.html#a4d95b831d9a66071092678547df921ae", null ], + [ "w", "struct_group_pub_key__.html#a4d1537e5bd834b6fc92eb2fd7c826329", null ] + ] ], + [ "PrivKey_", "struct_priv_key__.html", [ + [ "A", "struct_priv_key__.html#aaf02af1379a0801f49a3f8845e7a1b1f", null ], + [ "f", "struct_priv_key__.html#a183eb6658baec9825313ab534608fa10", null ], + [ "gid", "struct_priv_key__.html#a0892f451bb967dd7c99fe1d926d5056f", null ], + [ "x", "struct_priv_key__.html#a327d7192cbb6b5638e3f6f1c3d9d2d5b", null ] + ] ], + [ "EPID_ENABLE_EPID_ZERO_MEMORY_ON_FREE", "group___epid_common.html#gab1587898f15de1b51cd5e799a43465ff", null ], + [ "ntohl", "group___epid_common.html#ga29a7e07cd5181e738f98fc026979efca", null ], + [ "SAFE_ALLOC", "group___epid_common.html#ga38fad13430eba25f9f9b05e35ecd22f8", null ], + [ "SAFE_FREE", "group___epid_common.html#ga2ca3c202ee727774d55890e568621842", null ], + [ "SAFE_REALLOC", "group___epid_common.html#ga41c113e15b695291199c27fac4bd53fa", null ], + [ "BitSupplier", "group___epid_common.html#ga6119a2c0323a3fca9e502b24bc378c2c", null ], + [ "CalculateCommitmentHash", "group___epid_common.html#ga23f8ea0f7529e8e7a81bd88e607dda01", null ], + [ "CreateEpid2Params", "group___epid_common.html#ga5c396a5ac8a0e5ec1e02330c53420dce", null ], + [ "CreateGroupPubKey", "group___epid_common.html#ga20a575d3d538b0bac654fd57f20e2b30", null ], + [ "CreatePrivKey", "group___epid_common.html#gae51985a0e811f4bbb2d70b62e35b881e", null ], + [ "CreateStack", "group___epid_common.html#ga00cb25d52726cef61a9a5266176c2a58", null ], + [ "DeleteEpid2Params", "group___epid_common.html#gac22664b5f7df5cd4da1bd7b1b1e7912f", null ], + [ "DeleteGroupPubKey", "group___epid_common.html#ga07c9b47d326ee784aecb78195adffb8b", null ], + [ "DeletePrivKey", "group___epid_common.html#ga53db100214e65e362fa426508a240d12", null ], + [ "DeleteStack", "group___epid_common.html#ga3335a4754825c54840263aa4b2a9bf67", null ], + [ "EpidAlloc", "group___epid_common.html#gada170fd890504b013139f4a33033ae4b", null ], + [ "EpidFree", "group___epid_common.html#gaeae76709e6bfc80c9d79ec4943ccc1ac", null ], + [ "EpidRealloc", "group___epid_common.html#ga6911838728d546e4a51d7bcb8404525c", null ], + [ "EpidZeroMemory", "group___epid_common.html#gad471f600f6032f432b99432fda97a070", null ], + [ "IsSigRlValid", "group___epid_common.html#ga23ec3f6c8b89eb63e04d2b1ec6fd2696", null ], + [ "memcpy_S", "group___epid_common.html#ga4856121ac4bce4161a015a8a2b4f5b1c", null ], + [ "SetCalculatedCommitValues", "group___epid_common.html#ga3f3c3b965dd714179cbc2f8d96678ee0", null ], + [ "SetKeySpecificCommitValues", "group___epid_common.html#ga2d54f4f222e965222024113c0420602d", null ], + [ "StackGetSize", "group___epid_common.html#gab34066dc882ad63362c43c0790973fdc", null ], + [ "StackPopN", "group___epid_common.html#ga8cdde2b366f4473f0a6965bcfea5b6a6", null ], + [ "StackPushN", "group___epid_common.html#ga0b4dedb867504e0148aa0e1fdf642b2b", null ] +]; \ No newline at end of file diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/group___epid_math.html b/sgx-jvm/linux-sgx/external/epid/doc/html/group___epid_math.html new file mode 100644 index 0000000000..574d7260c3 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/group___epid_math.html @@ -0,0 +1,106 @@ + + + + + + + +Intel® Enhanced Privacy ID SDK: math + + + + + + + + + + + + +
+
+ + + + + + +
+ +
+
+ + +
+
+ +
+
+
+ +
+
+ +
+
math
+
+
+ +

Math Primitives and Group Operations. +More...

+ + + + + + + + + + + + + + + + + + + + +

+Modules

 bignum
 Big number operations.
 
 ecdsa
 Elliptic Curve Digital Signature Algorithm Primitives.
 
 ecgroup
 Elliptic curve group operations.
 
 finitefield
 Finite field operations.
 
 hash
 Hash primitives.
 
 pairing
 Pairing operations.
 
+

Detailed Description

+

Math Primitives and Group Operations.

+

Provides abstracted math primitives that are designed to be overridden by implementers porting to environments with specialized hardware. This module is defined and tested to hide implementation details from users of the API

+
+
+ + + + + diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/group___epid_math.js b/sgx-jvm/linux-sgx/external/epid/doc/html/group___epid_math.js new file mode 100644 index 0000000000..c416f54486 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/group___epid_math.js @@ -0,0 +1,9 @@ +var group___epid_math = +[ + [ "bignum", "group___big_num_primitives.html", "group___big_num_primitives" ], + [ "ecdsa", "group___ecdsa_primitives.html", "group___ecdsa_primitives" ], + [ "ecgroup", "group___ec_group_primitives.html", "group___ec_group_primitives" ], + [ "finitefield", "group___finite_field_primitives.html", "group___finite_field_primitives" ], + [ "hash", "group___hash_primitives.html", "group___hash_primitives" ], + [ "pairing", "group___pairing_primitives.html", "group___pairing_primitives" ] +]; \ No newline at end of file diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/group___epid_member_module.html b/sgx-jvm/linux-sgx/external/epid/doc/html/group___epid_member_module.html new file mode 100644 index 0000000000..898d1c9185 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/group___epid_member_module.html @@ -0,0 +1,933 @@ + + + + + + + +Intel® Enhanced Privacy ID SDK: member + + + + + + + + + + + + +
+
+ + + + + + +
+ +
+
+ + +
+
+ +
+
+
+ +
+
+ +
+
member
+
+
+ +

Member functionality. +More...

+ + + + + + + + +

+Data Structures

struct  MemberPrecomp
 Pre-computed member settings. More...
 
struct  PreComputedSignature
 Pre-computed signature. More...
 
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Functions

EpidStatus EpidMemberCreate (GroupPubKey const *pub_key, PrivKey const *priv_key, MemberPrecomp const *precomp, BitSupplier rnd_func, void *rnd_param, MemberCtx **ctx)
 Creates a new member context. More...
 
void EpidMemberDelete (MemberCtx **ctx)
 Deletes an existing member context. More...
 
EpidStatus EpidMemberWritePrecomp (MemberCtx const *ctx, MemberPrecomp *precomp)
 Serializes the pre-computed member settings. More...
 
EpidStatus EpidMemberSetHashAlg (MemberCtx *ctx, HashAlg hash_alg)
 Sets the hash algorithm to be used by a member. More...
 
size_t EpidGetSigSize (SigRl const *sig_rl)
 Computes the size in bytes required for a Intel(R) EPID signature. More...
 
EpidStatus EpidSign (MemberCtx const *ctx, void const *msg, size_t msg_len, void const *basename, size_t basename_len, SigRl const *sig_rl, size_t sig_rl_size, EpidSignature *sig, size_t sig_len)
 Writes a Intel(R) EPID signature. More...
 
EpidStatus EpidRegisterBaseName (MemberCtx *ctx, void const *basename, size_t basename_len)
 Registers a basename with a member. More...
 
EpidStatus EpidAddPreSigs (MemberCtx *ctx, size_t number_presigs, PreComputedSignature *presigs)
 Extends the member's pool of pre-computed signatures. More...
 
size_t EpidGetNumPreSigs (MemberCtx const *ctx)
 Gets the number of pre-computed signatures in the member's pool. More...
 
EpidStatus EpidWritePreSigs (MemberCtx *ctx, PreComputedSignature *presigs, size_t number_presigs)
 Serializes pre-computed signatures from the member's pool. More...
 
EpidStatus EpidRequestJoin (GroupPubKey const *pub_key, IssuerNonce const *ni, FpElemStr const *f, BitSupplier rnd_func, void *rnd_param, HashAlg hash_alg, JoinRequest *join_request)
 Creates a request to join a group. More...
 
EpidStatus EpidSignBasic (MemberCtx const *ctx, void const *msg, size_t msg_len, void const *basename, size_t basename_len, BasicSignature *sig)
 Creates a basic signature for use in constrained environment. More...
 
EpidStatus EpidNrProve (MemberCtx const *ctx, void const *msg, size_t msg_len, BasicSignature const *sig, SigRlEntry const *sigrl_entry, NrProof *proof)
 Calculates a non-revoked proof for a single signature based revocation list entry. More...
 
bool EpidIsPrivKeyInGroup (GroupPubKey const *pub_key, PrivKey const *priv_key)
 Tests if a member private key is valid without checking revocation. More...
 
EpidStatus EpidDecompressPrivKey (GroupPubKey const *pub_key, CompressedPrivKey const *compressed_privkey, PrivKey *priv_key)
 Decompresses compressed member private key. More...
 
+

Detailed Description

+

Member functionality.

+

Defines the APIs needed by Intel(R) EPID members. Each member context (MemberCtx) represents membership in a single group.

+

Function Documentation

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
EpidStatus EpidAddPreSigs (MemberCtxctx,
size_t number_presigs,
PreComputedSignaturepresigs 
)
+
+ +

Extends the member's pool of pre-computed signatures.

+

Can either generate new pre-computed signatures or import existing ones. EpidWritePreSigs can be used to export pre-computed signatures.

+
Parameters
+ + + + +
[in]ctxThe member context.
[in]number_presigsThe number of pre-computed signatures to add to the internal pool.
[in,out]presigsOptional array of valid pre-computed signatures to import. If presigs is not NULL it most contain at least number_presigs pre-computed signatures.
+
+
+
Returns
EpidStatus
+
Note
presigs buffer is zeroed out before return to prevent pre-computed signatures from being reused.
+
+If the result is not kEpidNoErr the state of the pre-computed signature pool, and of presigs, is undefined.
+
See also
EpidMemberCreate
+
+EpidWritePreSigs
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
EpidStatus EpidDecompressPrivKey (GroupPubKey const * pub_key,
CompressedPrivKey const * compressed_privkey,
PrivKeypriv_key 
)
+
+ +

Decompresses compressed member private key.

+

Converts a compressed member private key into a member private key for use by other member APIs.

+
Parameters
+ + + + +
[in]pub_keyThe public key of the group.
[in]compressed_privkeyThe compressed member private key to be decompressed.
[out]priv_keyThe member private key.
+
+
+
Returns
EpidStatus
+
Examples:
signmsg.c.
+
+
+
+ +
+
+ + + + + + + + +
size_t EpidGetNumPreSigs (MemberCtx const * ctx)
+
+ +

Gets the number of pre-computed signatures in the member's pool.

+
Parameters
+ + +
[in]ctxThe member context.
+
+
+
Returns
Number of remaining pre-computed signatures. Returns 0 if ctx is NULL.
+
See also
EpidMemberCreate
+
+EpidWritePreSigs
+ +
+
+ +
+
+ + + + + + + + +
size_t EpidGetSigSize (SigRl const * sig_rl)
+
+ +

Computes the size in bytes required for a Intel(R) EPID signature.

+
Parameters
+ + +
[in]sig_rlThe signature based revocation list that is used. NULL is treated as a zero length list.
+
+
+
Returns
Size in bytes of an Intel(R) EPID signature including proofs for each entry in the signature based revocation list.
+
See also
SigRl
+
Examples:
signmsg.c.
+
+
+
+ +
+
+ + + + + + + + + + + + + + + + + + +
bool EpidIsPrivKeyInGroup (GroupPubKey const * pub_key,
PrivKey const * priv_key 
)
+
+ +

Tests if a member private key is valid without checking revocation.

+

Used to check that a member private key is a valid key for a group. This is useful as a cross check when creating a new member private key as part of the join process

+
Parameters
+ + + +
[in]pub_keyThe public key of the group.
[in]priv_keyThe private key to check.
+
+
+
Returns
bool
+
Return values
+ + + +
trueif the private key is valid for the group of the public key
falseif the private key is not valid for the group of the public key
+
+
+
See also
EpidRequestJoin
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
EpidStatus EpidMemberCreate (GroupPubKey const * pub_key,
PrivKey const * priv_key,
MemberPrecomp const * precomp,
BitSupplier rnd_func,
void * rnd_param,
MemberCtx ** ctx 
)
+
+ +

Creates a new member context.

+

Must be called to create the member context that is used by other "Member" APIs.

+

Allocates memory for the context, then initializes it.

+

EpidMemberDelete() must be called to safely release the member context.

+
Parameters
+ + + + + + + +
[in]pub_keyThe group certificate.
[in]priv_keyThe member private key.
[in]precompOptional pre-computed data. If NULL the value is computed internally and is readable using EpidMemberWritePrecomp().
[in]rnd_funcRandom number generator.
[in]rnd_paramPass through context data for rnd_func.
[out]ctxNewly constructed member context.
+
+
+
Returns
EpidStatus
+
Warning
For security rnd_func should be a cryptographically secure random number generator.
+
Note
If the result is not kEpidNoErr the content of ctx is undefined.
+
See also
EpidMemberDelete
+
+EpidMemberWritePrecomp
+
Examples:
signmsg.c.
+
+
+
+ +
+
+ + + + + + + + +
void EpidMemberDelete (MemberCtx ** ctx)
+
+ +

Deletes an existing member context.

+

Must be called to safely release a member context created using EpidMemberCreate().

+

De-initializes the context, frees memory used by the context, and sets the context pointer to NULL.

+
Parameters
+ + +
[in,out]ctxThe member context. Can be NULL.
+
+
+
See also
EpidMemberCreate
+
Examples:
signmsg.c.
+
+
+
+ +
+
+ + + + + + + + + + + + + + + + + + +
EpidStatus EpidMemberSetHashAlg (MemberCtxctx,
HashAlg hash_alg 
)
+
+ +

Sets the hash algorithm to be used by a member.

+
Parameters
+ + + +
[in]ctxThe member context.
[in]hash_algThe hash algorithm to use.
+
+
+
Returns
EpidStatus
+
Note
If the result is not kEpidNoErr, the hash algorithm used by the member is undefined.
+
See also
EpidMemberCreate
+
+HashAlg
+
Examples:
signmsg.c.
+
+
+
+ +
+
+ + + + + + + + + + + + + + + + + + +
EpidStatus EpidMemberWritePrecomp (MemberCtx const * ctx,
MemberPrecompprecomp 
)
+
+ +

Serializes the pre-computed member settings.

+
Parameters
+ + + +
[in]ctxThe member context.
[out]precompThe Serialized pre-computed member settings.
+
+
+
Returns
EpidStatus
+
Note
If the result is not kEpidNoErr, the content of precomp is undefined.
+
Examples:
signmsg.c.
+
+
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
EpidStatus EpidNrProve (MemberCtx const * ctx,
void const * msg,
size_t msg_len,
BasicSignature const * sig,
SigRlEntry const * sigrl_entry,
NrProofproof 
)
+
+ +

Calculates a non-revoked proof for a single signature based revocation list entry.

+

Used in constrained environments where, due to limited memory, it may not be possible to process through a large and potentially unbounded revocation list.

+
Parameters
+ + + + + + + +
[in]ctxThe member context.
[in]msgThe message.
[in]msg_lenThe length of message in bytes.
[in]sigThe basic signature.
[in]sigrl_entryThe signature based revocation list entry.
[out]proofThe generated non-revoked proof.
+
+
+
Returns
EpidStatus
+
Note
This function should be used in conjunction with EpidSignBasic().
+
+If the result is not kEpidNoErr, the content of proof is undefined.
+
See also
EpidMemberCreate
+
+EpidSignBasic
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
EpidStatus EpidRegisterBaseName (MemberCtxctx,
void const * basename,
size_t basename_len 
)
+
+ +

Registers a basename with a member.

+

To prevent loss of privacy, the member keeps a list of basenames (corresponding to authorized verifiers). The member signs a message with a basename only if the basename is in the member's basename list.

+
Warning
The use of a name-based signature creates a platform unique pseudonymous identifier. Because it reduces the member's privacy, the user should be notified when it is used and should have control over its use.
+
Parameters
+ + + + +
[in]ctxThe member context.
[in]basenameThe basename.
[in]basename_lenLength of the basename.
+
+
+
Returns
EpidStatus
+
Return values
+ + +
kEpidDuplicateErrThe basename was already registered.
+
+
+
Note
If the result is not kEpidNoErr or kEpidDuplicateErr it is undefined if the basename is registered.
+
Examples:
signmsg.c.
+
+
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
EpidStatus EpidRequestJoin (GroupPubKey const * pub_key,
IssuerNonce const * ni,
FpElemStr const * f,
BitSupplier rnd_func,
void * rnd_param,
HashAlg hash_alg,
JoinRequestjoin_request 
)
+
+ +

Creates a request to join a group.

+

The created request is part of the interaction with an issuer needed to join a group. This interaction with the issuer is outside the scope of this API.

+
Parameters
+ + + + + + + + +
[in]pub_keyThe group certificate of group to join.
[in]niThe nonce chosen by issuer as part of join protocol.
[in]fA randomly selected integer in [1, p-1].
[in]rnd_funcRandom number generator.
[in]rnd_paramPass through context data for rnd_func.
[in]hash_algThe hash algorithm to be used.
[out]join_requestThe join request.
+
+
+
Returns
EpidStatus
+
Warning
For security rnd_func should be a cryptographically secure random number generator.
+
Note
The default hash algorithm in Member is SHA-512. This is the recommended option if you do not override the hash algorithm elsewhere.
+
+If the result is not kEpidNoErr, the content of join_request is undefined.
+
See also
HashAlg
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
EpidStatus EpidSign (MemberCtx const * ctx,
void const * msg,
size_t msg_len,
void const * basename,
size_t basename_len,
SigRl const * sig_rl,
size_t sig_rl_size,
EpidSignaturesig,
size_t sig_len 
)
+
+ +

Writes a Intel(R) EPID signature.

+
Parameters
+ + + + + + + + + + +
[in]ctxThe member context.
[in]msgThe message to sign.
[in]msg_lenThe length in bytes of message.
[in]basenameOptional basename. If basename is NULL a random basename is used. Signatures generated using random basenames are anonymous. Signatures generated using the same basename are linkable by the verifier. If a basename is provided, it must already be registered, or kEpidBadArgErr is returned.
[in]basename_lenThe size of basename in bytes. Must be 0 basename is NULL.
[in]sig_rlThe signature based revocation list.
[in]sig_rl_sizeThe size in bytes of the signature based revocation list.
[out]sigThe generated signature
[in]sig_lenThe size of signature in bytes. Must be equal to value returned by EpidGetSigSize().
+
+
+
Returns
EpidStatus
+
Note
If the result is not kEpidNoErr the content of sig is undefined.
+
See also
EpidMemberCreate
+
+EpidMemberSetHashAlg
+
+EpidGetSigSize
+
Examples:
signmsg.c.
+
+
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
EpidStatus EpidSignBasic (MemberCtx const * ctx,
void const * msg,
size_t msg_len,
void const * basename,
size_t basename_len,
BasicSignaturesig 
)
+
+ +

Creates a basic signature for use in constrained environment.

+

Used in constrained environments where, due to limited memory, it may not be possible to process through a large and potentially unbounded revocation list.

+
Parameters
+ + + + + + + +
[in]ctxThe member context.
[in]msgThe message.
[in]msg_lenThe length of message in bytes.
[in]basenameOptional basename. If basename is NULL a random basename is used. Signatures generated using random basenames are anonymous. Signatures generated using the same basename are linkable by the verifier. If a basename is provided it must already be registered or kEpidBadArgErr is returned.
[in]basename_lenThe size of basename in bytes. Must be 0 basename is NULL.
[out]sigThe generated basic signature
+
+
+
Returns
EpidStatus
+
Note
This function should be used in conjunction with EpidNrProve()
+
+If the result is not kEpidNoErr the content of sig, is undefined.
+
See also
EpidMemberCreate
+
+EpidNrProve
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
EpidStatus EpidWritePreSigs (MemberCtxctx,
PreComputedSignaturepresigs,
size_t number_presigs 
)
+
+ +

Serializes pre-computed signatures from the member's pool.

+

Removes requested number of pre-computed signatures from member's pool and stores them in presigs array. Use EpidAddPreSigs to add pre-computed signatures to the pool.

+
Parameters
+ + + + +
[in]ctxThe member context.
[out]presigsAn existing buffer of pre-computed signatures.
[in]number_presigsNumber of pre-computed signatures to read. Number_presigs must not be greater than the value returned by EpidGetNumPreSigs.
+
+
+
Returns
EpidStatus
+
Note
If the result is not kEpidNoErr the state of the pre-computed signature pool, and of presigs, is undefined.
+
See also
EpidMemberCreate
+
+EpidGetNumPreSigs
+
+EpidAddPreSigs
+ +
+
+
+
+ + + + + diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/group___epid_member_module.js b/sgx-jvm/linux-sgx/external/epid/doc/html/group___epid_member_module.js new file mode 100644 index 0000000000..1a6c7f47ae --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/group___epid_member_module.js @@ -0,0 +1,37 @@ +var group___epid_member_module = +[ + [ "MemberPrecomp", "struct_member_precomp.html", [ + [ "e12", "struct_member_precomp.html#a55e5c4b25c8f0f426969a8d745260fe5", null ], + [ "e22", "struct_member_precomp.html#a4e7412969bed3964f813b093b948e7b4", null ], + [ "e2w", "struct_member_precomp.html#a879d5a7b0c30088b23f6e5c5fc62f834", null ], + [ "ea2", "struct_member_precomp.html#a573551f6494e372f44fd3bdf5b02aeda", null ] + ] ], + [ "PreComputedSignature", "struct_pre_computed_signature.html", [ + [ "a", "struct_pre_computed_signature.html#af23f3f9693857a33fe8564644612ea37", null ], + [ "B", "struct_pre_computed_signature.html#a9cc2eb61572a1aca9e6bc3d5e6f4c1fe", null ], + [ "b", "struct_pre_computed_signature.html#a666710432d9d54ca896647a976892c4f", null ], + [ "K", "struct_pre_computed_signature.html#a2a4eaffe2717bd9c8c360599612adbe6", null ], + [ "R1", "struct_pre_computed_signature.html#a72be597624957e3d668c95ff6f445f94", null ], + [ "R2", "struct_pre_computed_signature.html#a79f06fb57842597372e00dd34c1a804a", null ], + [ "ra", "struct_pre_computed_signature.html#a54462643b8a2b4f2741bf8d2e6909d11", null ], + [ "rb", "struct_pre_computed_signature.html#a6a1db672c609943fe7af84320dc68ba3", null ], + [ "rf", "struct_pre_computed_signature.html#ac244bd559a96812bcee7671abc299b66", null ], + [ "rx", "struct_pre_computed_signature.html#acd0674d5b5e96244645e9abef7bdbddc", null ], + [ "T", "struct_pre_computed_signature.html#a73471643dc757115701833ca2e831a72", null ] + ] ], + [ "EpidAddPreSigs", "group___epid_member_module.html#gad2e3de5c6ce641a318f8a46b61e75236", null ], + [ "EpidDecompressPrivKey", "group___epid_member_module.html#gaf8cd05388f017486f14da2ee48d067ef", null ], + [ "EpidGetNumPreSigs", "group___epid_member_module.html#gad78ca056dfea2565bbacd5734d9dc075", null ], + [ "EpidGetSigSize", "group___epid_member_module.html#ga76e535722467af7c16809b5b521e0000", null ], + [ "EpidIsPrivKeyInGroup", "group___epid_member_module.html#ga8e3f201d1e9dc668659e08a3bdf543b6", null ], + [ "EpidMemberCreate", "group___epid_member_module.html#ga561c4d544a78ee1bf59c3f4f919aa7bb", null ], + [ "EpidMemberDelete", "group___epid_member_module.html#ga3824589c683c5e0e59d483462fce65d6", null ], + [ "EpidMemberSetHashAlg", "group___epid_member_module.html#ga9998eb454838ff5d232ff22ecbab31bf", null ], + [ "EpidMemberWritePrecomp", "group___epid_member_module.html#ga5c35798d62cf81c4ca62b22c38809721", null ], + [ "EpidNrProve", "group___epid_member_module.html#gac8e2c6c1fead8030785a40427905a2cc", null ], + [ "EpidRegisterBaseName", "group___epid_member_module.html#gad92d3c3266ae1833ffb1dba9ad76035d", null ], + [ "EpidRequestJoin", "group___epid_member_module.html#ga13dd0d72be9babf8194d472d7712a361", null ], + [ "EpidSign", "group___epid_member_module.html#ga759155a719254f734157722716dac640", null ], + [ "EpidSignBasic", "group___epid_member_module.html#gae04a250d5981fcf9bd6f9f57e0468faa", null ], + [ "EpidWritePreSigs", "group___epid_member_module.html#ga9e12c7cec8d0c4e07b12c0e26a278c9d", null ] +]; \ No newline at end of file diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/group___epid_module.html b/sgx-jvm/linux-sgx/external/epid/doc/html/group___epid_module.html new file mode 100644 index 0000000000..3b36d18879 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/group___epid_module.html @@ -0,0 +1,97 @@ + + + + + + + +Intel® Enhanced Privacy ID SDK: epid + + + + + + + + + + + + +
+
+ + + + + + +
+ +
+
+ + +
+
+ +
+
+
+ +
+
+ +
+
epid
+
+
+ +

Core Intel® EPID functionality. +More...

+ + + + + + + + + + + +

+Modules

 common
 Common code shared between core sub-components.
 
 member
 Member functionality.
 
 verifier
 Verifier functionality.
 
+

Detailed Description

+

Core Intel® EPID functionality.

+

Contains core functionality used to provide or implement APIs in the Intel(R) EPID SDK.

+
+
+ + + + + diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/group___epid_module.js b/sgx-jvm/linux-sgx/external/epid/doc/html/group___epid_module.js new file mode 100644 index 0000000000..892eddf409 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/group___epid_module.js @@ -0,0 +1,6 @@ +var group___epid_module = +[ + [ "common", "group___epid_common.html", "group___epid_common" ], + [ "member", "group___epid_member_module.html", "group___epid_member_module" ], + [ "verifier", "group___epid_verifier_module.html", "group___epid_verifier_module" ] +]; \ No newline at end of file diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/group___epid_print.html b/sgx-jvm/linux-sgx/external/epid/doc/html/group___epid_print.html new file mode 100644 index 0000000000..f4b0a4d894 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/group___epid_print.html @@ -0,0 +1,660 @@ + + + + + + + +Intel® Enhanced Privacy ID SDK: print_utils + + + + + + + + + + + + +
+
+ + + + + + +
+ +
+
+ + +
+
+ +
+
+
+ +
+
+ +
+
print_utils
+
+
+ +

Debug print routines. +More...

+ + + + + +

+Enumerations

enum  PrintUtilFormat { kPrintUtilUnannotated = 0, +kPrintUtilAnnotated = 1 + }
 Print format. More...
 
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Functions

void PrintBigNum (BigNum const *big_num, char const *var_name)
 Prints BigNum. More...
 
void PrintFfElement (FiniteField const *ff, FfElement const *ff_element, char const *var_name, PrintUtilFormat format)
 Prints finite field element. More...
 
void PrintEcPoint (EcGroup const *g, EcPoint const *ec_point, char const *var_name, PrintUtilFormat format)
 Prints elliptic curve group element. More...
 
void PrintBigNumStr (BigNumStr const *big_num_str, char const *var_name)
 Prints serialized BigNum. More...
 
void PrintFpElemStr (FpElemStr const *fp_elem_str, char const *var_name)
 Prints serialized Fp element. More...
 
void PrintFqElemStr (FqElemStr const *fq_elem_str, char const *var_name)
 Prints serialized Fq element. More...
 
void PrintFq2ElemStr (Fq2ElemStr const *fq2_elem_str, char const *var_name, PrintUtilFormat format)
 Prints serialized Fq2 element. More...
 
void PrintFq6ElemStr (Fq6ElemStr const *fq6_elem_str, char const *var_name, PrintUtilFormat format)
 Prints serialized Fq6 element. More...
 
void PrintFq12ElemStr (Fq12ElemStr const *fq12_elem_str, char const *var_name, PrintUtilFormat format)
 Prints serialized Fq12 element. More...
 
void PrintG1ElemStr (G1ElemStr const *g1_elem_str, char const *var_name, PrintUtilFormat format)
 Prints serialized G1 element. More...
 
void PrintG2ElemStr (G2ElemStr const *g2_elem_str, char const *var_name, PrintUtilFormat format)
 Prints serialized G2 element. More...
 
void PrintGtElemStr (GtElemStr const *gt_elem_str, char const *var_name, PrintUtilFormat format)
 Prints serialized Gt element. More...
 
+

Detailed Description

+

Debug print routines.

+

Defines an API to print formatted versions of the types used for mathematical operations.

+

If the symbol EPID_ENABLE_DEBUG_PRINT is not defined, all calls to the functions in this module are ignored.

+

Enumeration Type Documentation

+ +
+
+ + + + +
enum PrintUtilFormat
+
+ +

Print format.

+ + + +
Enumerator
kPrintUtilUnannotated  +

Unannotated output format.

+
kPrintUtilAnnotated  +

Annotated output format.

+
+ +
+
+

Function Documentation

+ +
+
+ + + + + + + + + + + + + + + + + + +
void PrintBigNum (BigNum const * big_num,
char const * var_name 
)
+
+ +

Prints BigNum.

+

Macro EPID_ENABLE_DEBUG_PRINT needs to be defined in order to activate this routine; otherwise, it prints nothing.

+
Parameters
+ + + +
[in]big_numBigNum to be printed
[in]var_nameResult variable name
+
+
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + +
void PrintBigNumStr (BigNumStr const * big_num_str,
char const * var_name 
)
+
+ +

Prints serialized BigNum.

+

Macro EPID_ENABLE_DEBUG_PRINT needs to be defined in order to activate this routine; otherwise, it prints nothing.

+
Parameters
+ + + +
[in]big_num_strSerialized BigNum to be printed
[in]var_nameResult variable name
+
+
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
void PrintEcPoint (EcGroup const * g,
EcPoint const * ec_point,
char const * var_name,
PrintUtilFormat format 
)
+
+ +

Prints elliptic curve group element.

+

Macro EPID_ENABLE_DEBUG_PRINT needs to be defined in order to activate this routine; otherwise, it prints nothing.

+
Parameters
+ + + + + +
[in]gElliptic curve group that element to be printed belongs to
[in]ec_pointElliptic curve group element to be printed
[in]var_nameResult variable name
[in]formatOutput format
+
+
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
void PrintFfElement (FiniteField const * ff,
FfElement const * ff_element,
char const * var_name,
PrintUtilFormat format 
)
+
+ +

Prints finite field element.

+

Macro EPID_ENABLE_DEBUG_PRINT needs to be defined in order to activate this routine; otherwise, it prints nothing.

+
Parameters
+ + + + + +
[in]ffFinite field that element to be printed belongs to
[in]ff_elementFinite field element to be printed
[in]var_nameResult variable name
[in]formatOutput format
+
+
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + +
void PrintFpElemStr (FpElemStr const * fp_elem_str,
char const * var_name 
)
+
+ +

Prints serialized Fp element.

+

Macro EPID_ENABLE_DEBUG_PRINT needs to be defined in order to activate this routine; otherwise, it prints nothing.

+
Parameters
+ + + +
[in]fp_elem_strSerialized Fp element to be printed
[in]var_nameResult variable name
+
+
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
void PrintFq12ElemStr (Fq12ElemStr const * fq12_elem_str,
char const * var_name,
PrintUtilFormat format 
)
+
+ +

Prints serialized Fq12 element.

+

Macro EPID_ENABLE_DEBUG_PRINT needs to be defined in order to activate this routine; otherwise, it prints nothing.

+
Parameters
+ + + + +
[in]fq12_elem_strSerialized Intel(R) EPID Fq12 element to be printed
[in]var_nameResult variable name
[in]formatOutput format
+
+
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
void PrintFq2ElemStr (Fq2ElemStr const * fq2_elem_str,
char const * var_name,
PrintUtilFormat format 
)
+
+ +

Prints serialized Fq2 element.

+

Macro EPID_ENABLE_DEBUG_PRINT needs to be defined in order to activate this routine; otherwise, it prints nothing.

+
Parameters
+ + + + +
[in]fq2_elem_strSerialized Fq2 element to be printed
[in]var_nameResult variable name
[in]formatOutput format
+
+
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
void PrintFq6ElemStr (Fq6ElemStr const * fq6_elem_str,
char const * var_name,
PrintUtilFormat format 
)
+
+ +

Prints serialized Fq6 element.

+

Macro EPID_ENABLE_DEBUG_PRINT needs to be defined in order to activate this routine; otherwise, it prints nothing.

+
Parameters
+ + + + +
[in]fq6_elem_strSerialized Fq6 element to be printed
[in]var_nameResult variable name
[in]formatOutput format
+
+
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + +
void PrintFqElemStr (FqElemStr const * fq_elem_str,
char const * var_name 
)
+
+ +

Prints serialized Fq element.

+

Macro EPID_ENABLE_DEBUG_PRINT needs to be defined in order to activate this routine; otherwise, it prints nothing.

+
Parameters
+ + + +
[in]fq_elem_strSerialized Fq element to be printed
[in]var_nameResult variable name
+
+
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
void PrintG1ElemStr (G1ElemStr const * g1_elem_str,
char const * var_name,
PrintUtilFormat format 
)
+
+ +

Prints serialized G1 element.

+

Macro EPID_ENABLE_DEBUG_PRINT needs to be defined in order to activate this routine; otherwise, it prints nothing.

+
Parameters
+ + + + +
[in]g1_elem_strSerialized G1 element to be printed
[in]var_nameResult variable name
[in]formatOutput format
+
+
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
void PrintG2ElemStr (G2ElemStr const * g2_elem_str,
char const * var_name,
PrintUtilFormat format 
)
+
+ +

Prints serialized G2 element.

+

Macro EPID_ENABLE_DEBUG_PRINT needs to be defined in order to activate this routine; otherwise, it prints nothing.

+
Parameters
+ + + + +
[in]g2_elem_strSerialized G2 element to be printed
[in]var_nameResult variable name
[in]formatOutput format
+
+
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
void PrintGtElemStr (GtElemStr const * gt_elem_str,
char const * var_name,
PrintUtilFormat format 
)
+
+ +

Prints serialized Gt element.

+

Macro EPID_ENABLE_DEBUG_PRINT needs to be defined in order to activate this routine; otherwise, it prints nothing.

+
Parameters
+ + + + +
[in]gt_elem_strSerialized G2 element to be printed
[in]var_nameResult variable name
[in]formatOutput format
+
+
+ +
+
+
+
+ + + + + diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/group___epid_print.js b/sgx-jvm/linux-sgx/external/epid/doc/html/group___epid_print.js new file mode 100644 index 0000000000..00d8c84e1f --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/group___epid_print.js @@ -0,0 +1,19 @@ +var group___epid_print = +[ + [ "PrintUtilFormat", "group___epid_print.html#ga3e215d157eb205ad596bb84bce694a83", [ + [ "kPrintUtilUnannotated", "group___epid_print.html#gga3e215d157eb205ad596bb84bce694a83aeb475b793d8d357087d7fcc74702ffae", null ], + [ "kPrintUtilAnnotated", "group___epid_print.html#gga3e215d157eb205ad596bb84bce694a83ae2d5345c14f57fc992a613003c3c443d", null ] + ] ], + [ "PrintBigNum", "group___epid_print.html#ga45a933b44fc1dfe926e3af89c198070a", null ], + [ "PrintBigNumStr", "group___epid_print.html#ga5f249c594ed12e4a9b11b7bc101da85d", null ], + [ "PrintEcPoint", "group___epid_print.html#ga0d6377d9c1651d0101ec6b61feaa78ca", null ], + [ "PrintFfElement", "group___epid_print.html#gaa3b1cbbfc6f78562658953113e5798cf", null ], + [ "PrintFpElemStr", "group___epid_print.html#gae553c3a156a0e4968b89635ab0757580", null ], + [ "PrintFq12ElemStr", "group___epid_print.html#gaf185fe3df270cd8b4a2969bf3cfc5d5f", null ], + [ "PrintFq2ElemStr", "group___epid_print.html#ga883a834ab1703365bb0bca4abd3104de", null ], + [ "PrintFq6ElemStr", "group___epid_print.html#ga3f2961ef6b4c44a6205d422d8a293476", null ], + [ "PrintFqElemStr", "group___epid_print.html#ga6c9fea48fa0477f4a98abb50f891a5e4", null ], + [ "PrintG1ElemStr", "group___epid_print.html#ga87168a3ce5306f9839b8e8d6c9a5f84f", null ], + [ "PrintG2ElemStr", "group___epid_print.html#gab76a4cf0385dc4a76bb56ee9f0e3e87a", null ], + [ "PrintGtElemStr", "group___epid_print.html#ga138cd388247a58680d4701d59d6976d2", null ] +]; \ No newline at end of file diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/group___epid_types.html b/sgx-jvm/linux-sgx/external/epid/doc/html/group___epid_types.html new file mode 100644 index 0000000000..efdfd1d41b --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/group___epid_types.html @@ -0,0 +1,266 @@ + + + + + + + +Intel® Enhanced Privacy ID SDK: types + + + + + + + + + + + + +
+
+ + + + + + +
+ +
+
+ + +
+
+ +
+
+
+ +
+ +
+ +

SDK data types. +More...

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Data Structures

struct  OctStr8
 8 bit octet string More...
 
struct  OctStr16
 16 bit octet string More...
 
struct  OctStr32
 32 bit octet string More...
 
struct  OctStr64
 64 bit octet string More...
 
struct  OctStr128
 128 bit octet string More...
 
struct  OctStr256
 256 bit octet string More...
 
struct  OctStr512
 512 bit octet string More...
 
struct  BigNumStr
 Serialized BigNum. More...
 
struct  FpElemStr
 a number in [0, p-1] More...
 
struct  FqElemStr
 a number in [0, q-1] More...
 
struct  G1ElemStr
 Serialized G1 element. More...
 
struct  G2ElemStr
 Serialized G2 element. More...
 
struct  GtElemStr
 Serialized GT element. More...
 
struct  Epid2Params
 Intel(R) EPID 2.0 Parameters. More...
 
struct  GroupPubKey
 Intel(R) EPID 2.0 group public key. More...
 
struct  IPrivKey
 Intel(R) EPID 2.0 issuing private key. More...
 
struct  PrivKey
 Intel(R) EPID 2.0 private key. More...
 
struct  CompressedPrivKey
 Compressed private key. More...
 
struct  MembershipCredential
 Membership credential. More...
 
struct  JoinRequest
 Join request. More...
 
struct  BasicSignature
 Intel(R) EPID 2.0 basic signature. More...
 
struct  NrProof
 non-revoked Proof. More...
 
struct  EpidSignature
 Intel(R) EPID 2.0 Signature. More...
 
struct  PrivRl
 private-key based revocation list. More...
 
struct  SigRlEntry
 entry in SigRL (B,K) More...
 
struct  SigRl
 signature based revocation list More...
 
struct  GroupRl
 group revocation list More...
 
struct  VerifierRl
 
struct  Fq2ElemStr
 Serialized Fq2 element. More...
 
struct  Fq6ElemStr
 Serialized Fq2^3 element. More...
 
struct  Fq12ElemStr
 Serialized Fq2^3^2 element. More...
 
struct  EcdsaSignature
 ECDSA Signature using NIST 256-bit curve secp256r1. More...
 
struct  EcdsaPublicKey
 ECDSA Public Key. More...
 
struct  EcdsaPrivateKey
 ECDSA Private Key. More...
 
+ + + + + + + + + + + + + +

+Typedefs

+typedef OctStr128 GroupId
 group ID
 
+typedef OctStr256 Seed
 256 bit seed derived from fuse key
 
+typedef OctStr256 IssuerNonce
 256 bit nonce chosen by issuer
 
+typedef G1ElemStr ReKeySeed
 element to store seed values for later rekey
 
+ + + + +

+Enumerations

enum  HashAlg {
+  kSha256 = 0, +kSha384 = 1, +kSha512 = 2, +kSha512_256 = 3, +
+  kSha3_256 = 4, +kSha3_384 = 5, +kSha3_512 = 6 +
+ }
 Recognized hash algorithms. More...
 
+

Detailed Description

+

SDK data types.

+

Defines serialized data types used by the SDK.

+

Most of the types defined here are fixed size binary buffers of various sizes that are semantically mapped to the types of various inputs to the EPID APIs.

+

For example GtElemStr is a 384 byte buffer that represents a serialized value that is compatible with a FfElement belonging to the FiniteField GT.

+

Enumeration Type Documentation

+ +
+
+ + + + +
enum HashAlg
+
+ +

Recognized hash algorithms.

+ + + + + + + + +
Enumerator
kSha256  +

SHA-256.

+
kSha384  +

SHA-384.

+
kSha512  +

SHA-512.

+
kSha512_256  +

SHA-512/256.

+
kSha3_256  +

Reserved for SHA3/256.

+
kSha3_384  +

Reserved for SHA3/384.

+
kSha3_512  +

Reserved for SHA3/512.

+
+ +
+
+
+
+ + + + + diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/group___epid_types.js b/sgx-jvm/linux-sgx/external/epid/doc/html/group___epid_types.js new file mode 100644 index 0000000000..f473312478 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/group___epid_types.js @@ -0,0 +1,169 @@ +var group___epid_types = +[ + [ "OctStr8", "struct_oct_str8.html", [ + [ "data", "struct_oct_str8.html#a5e6c56fda48c88b419e621b464b03bef", null ] + ] ], + [ "OctStr16", "struct_oct_str16.html", [ + [ "data", "struct_oct_str16.html#a86ed6671693a3f60ec4ff7de2c1206c3", null ] + ] ], + [ "OctStr32", "struct_oct_str32.html", [ + [ "data", "struct_oct_str32.html#a5588a7e70f3d73f6ce58b567a9f5c5c8", null ] + ] ], + [ "OctStr64", "struct_oct_str64.html", [ + [ "data", "struct_oct_str64.html#a0e107d78192a5ae0b48ed9e5c4eab0fc", null ] + ] ], + [ "OctStr128", "struct_oct_str128.html", [ + [ "data", "struct_oct_str128.html#a7482aa9b0b580fdd50bd65419d52d4b9", null ] + ] ], + [ "OctStr256", "struct_oct_str256.html", [ + [ "data", "struct_oct_str256.html#a359781bb84f5717a16094583a00ef14e", null ] + ] ], + [ "OctStr512", "struct_oct_str512.html", [ + [ "data", "struct_oct_str512.html#abd4d1b97fe49321571da86de1aeac653", null ] + ] ], + [ "BigNumStr", "struct_big_num_str.html", [ + [ "data", "struct_big_num_str.html#a442dcf33889b4f85c5b1228d2c8e6838", null ] + ] ], + [ "FpElemStr", "struct_fp_elem_str.html", [ + [ "data", "struct_fp_elem_str.html#a5ddb96a5567750f2834335851c906c45", null ] + ] ], + [ "FqElemStr", "struct_fq_elem_str.html", [ + [ "data", "struct_fq_elem_str.html#aac1a876b51a8d2c6d1510e4df2fd3f14", null ] + ] ], + [ "G1ElemStr", "struct_g1_elem_str.html", [ + [ "x", "struct_g1_elem_str.html#a3b0e658d6e5697763ad9c633c11d4ec4", null ], + [ "y", "struct_g1_elem_str.html#a8f2455ca314e885ea180dadf84bf27c3", null ] + ] ], + [ "G2ElemStr", "struct_g2_elem_str.html", [ + [ "x", "struct_g2_elem_str.html#a145ec5b20a6f4f00b080e11c8680afc3", null ], + [ "y", "struct_g2_elem_str.html#a43141b2458aecceed8ee2748270f7908", null ] + ] ], + [ "GtElemStr", "struct_gt_elem_str.html", [ + [ "x", "struct_gt_elem_str.html#aeaeb0e9e1c6efd378a475eb9a6c42132", null ] + ] ], + [ "Epid2Params", "struct_epid2_params.html", [ + [ "b", "struct_epid2_params.html#a2f868edb49be49f645101ef5ebbbc551", null ], + [ "beta", "struct_epid2_params.html#ac2d7507c6f58c3451beacacb91b52695", null ], + [ "g1", "struct_epid2_params.html#a4c5195b4fa9393a07a121336202531ad", null ], + [ "g2", "struct_epid2_params.html#a609b0aac17fca34fe39bee29676a9618", null ], + [ "neg", "struct_epid2_params.html#af23f07fb0e1745c0ad14aceeaa946928", null ], + [ "p", "struct_epid2_params.html#ac0e0dad45b10927860cd5fa4f8101f08", null ], + [ "q", "struct_epid2_params.html#a023603228fed2854ddae2e228938940f", null ], + [ "t", "struct_epid2_params.html#a200a0cba1c9e4ad512bece23f2461a5f", null ], + [ "xi", "struct_epid2_params.html#ae1d8f5d6036a82064e91bc137b278e74", null ] + ] ], + [ "GroupPubKey", "struct_group_pub_key.html", [ + [ "gid", "struct_group_pub_key.html#ae8e77ab4d5eb3c8e566c24a64cce56ee", null ], + [ "h1", "struct_group_pub_key.html#a8c22c758ea186f95e3bf4b2ef8451da5", null ], + [ "h2", "struct_group_pub_key.html#a2a4320ec99fd1a15df412fbf2a8d49f1", null ], + [ "w", "struct_group_pub_key.html#a86be439104fb60b324784baf24a943f9", null ] + ] ], + [ "IPrivKey", "struct_i_priv_key.html", [ + [ "gamma", "struct_i_priv_key.html#a6d484175317aef09fb959c3ca55fc70a", null ], + [ "gid", "struct_i_priv_key.html#ad400a4237b6d50855538fd40580eb1bb", null ] + ] ], + [ "PrivKey", "struct_priv_key.html", [ + [ "A", "struct_priv_key.html#a266c7e369b8b868ef5755e9cd3c0c849", null ], + [ "f", "struct_priv_key.html#ad7ee0392a583edd2e287cf8c1f9066ba", null ], + [ "gid", "struct_priv_key.html#ab416dcb4366427c24b44c2a02e4ae7c8", null ], + [ "x", "struct_priv_key.html#aa805f9e124f05bdb733c85cb93614cbd", null ] + ] ], + [ "CompressedPrivKey", "struct_compressed_priv_key.html", [ + [ "ax", "struct_compressed_priv_key.html#a0b0535f0567eb0e48f799d27991d0f66", null ], + [ "gid", "struct_compressed_priv_key.html#ac6689899f1d9a6a8c5e4915563679840", null ], + [ "seed", "struct_compressed_priv_key.html#a54b9af7699f517bbaef3d52d03e3fed8", null ] + ] ], + [ "MembershipCredential", "struct_membership_credential.html", [ + [ "A", "struct_membership_credential.html#a6d38ac3a9c5417833b8adb9b22bc9dc8", null ], + [ "gid", "struct_membership_credential.html#afbff64ec55888c7e2a658eabb5e16671", null ], + [ "x", "struct_membership_credential.html#a2c5c0d22999d6917fea5ad6618883bcf", null ] + ] ], + [ "JoinRequest", "struct_join_request.html", [ + [ "c", "struct_join_request.html#a55e30a274e83b808db6fbab5ae6c6cb8", null ], + [ "F", "struct_join_request.html#a005651506fd4511e8a3537f6c3634532", null ], + [ "s", "struct_join_request.html#a73bf8989df5f90eb3d06e7a42ad74d1d", null ] + ] ], + [ "BasicSignature", "struct_basic_signature.html", [ + [ "B", "struct_basic_signature.html#ae90cb6af66b010ae39913f033c1e65ac", null ], + [ "c", "struct_basic_signature.html#a4daa94db5068db3f10960f3dd178d603", null ], + [ "K", "struct_basic_signature.html#a0078cc83ecf6c7e31f96b7d44aa60e21", null ], + [ "sa", "struct_basic_signature.html#a69115a4776d15b48411dd6c3a76d0f3d", null ], + [ "sb", "struct_basic_signature.html#a91daebc5b577688afeed2a7ee7913245", null ], + [ "sf", "struct_basic_signature.html#a79d8dec8c5da176e497abf22e4c43adb", null ], + [ "sx", "struct_basic_signature.html#a0e8ea6a2cd3af10e9b59d96d7d06bc69", null ], + [ "T", "struct_basic_signature.html#a730f74d85cfb4fa4089d43c87b97a624", null ] + ] ], + [ "NrProof", "struct_nr_proof.html", [ + [ "c", "struct_nr_proof.html#a0de1aa69acf3d93da34cf4a613b359a1", null ], + [ "smu", "struct_nr_proof.html#a717ec36a6c91acd01d9b642bb20fc178", null ], + [ "snu", "struct_nr_proof.html#ae2e9f22089793a4d44a0f7f5cdb78a0c", null ], + [ "T", "struct_nr_proof.html#ace535065bbf96502b893ac677dc8dcd3", null ] + ] ], + [ "EpidSignature", "struct_epid_signature.html", [ + [ "n2", "struct_epid_signature.html#a62a6b0ffcd5f68dd3d2786a58fe43017", null ], + [ "rl_ver", "struct_epid_signature.html#a4155f3f4f1223fc4ae50c94f5305def1", null ], + [ "sigma", "struct_epid_signature.html#a89d2e38223944310b6eeeadf6061a2dd", null ], + [ "sigma0", "struct_epid_signature.html#ab0fe5f98bff737fcfbfe0b4d658e83f2", null ] + ] ], + [ "PrivRl", "struct_priv_rl.html", [ + [ "f", "struct_priv_rl.html#a60d73f9ef5fc81f117b3abadf8c18466", null ], + [ "gid", "struct_priv_rl.html#af7317529b8e55476bd06b66ed8131d64", null ], + [ "n1", "struct_priv_rl.html#a6da9639ec4061689d1c30a58e0befd14", null ], + [ "version", "struct_priv_rl.html#a4c6b51cec760f7e81ca8635422ac6a50", null ] + ] ], + [ "SigRlEntry", "struct_sig_rl_entry.html", [ + [ "b", "struct_sig_rl_entry.html#ac6a47ff0d1b8ea1512e0ff14983ac5ce", null ], + [ "k", "struct_sig_rl_entry.html#a0dfeb058614e81878bfbf86ae3edac3c", null ] + ] ], + [ "SigRl", "struct_sig_rl.html", [ + [ "bk", "struct_sig_rl.html#ac23a919993d99d24a5150302f1778102", null ], + [ "gid", "struct_sig_rl.html#a12757d30fcccd310716433948e0b603e", null ], + [ "n2", "struct_sig_rl.html#a9dfb6b508db9051f4dc480a51d702af2", null ], + [ "version", "struct_sig_rl.html#ac9d4c343c539dba799e1f42eb38b351f", null ] + ] ], + [ "GroupRl", "struct_group_rl.html", [ + [ "gid", "struct_group_rl.html#a51022e172ab8b945efc69f1e63170107", null ], + [ "n3", "struct_group_rl.html#a9067f01c63cdefbc8e23c3cf67a10172", null ], + [ "version", "struct_group_rl.html#a69c41d99cdfc5b6ece7442f466f7ec3f", null ] + ] ], + [ "VerifierRl", "struct_verifier_rl.html", [ + [ "B", "struct_verifier_rl.html#a5d9a9265fffa96fd5f9260543eb08c68", null ], + [ "gid", "struct_verifier_rl.html#ab85c4666d16145ff16443e84468d2d7d", null ], + [ "K", "struct_verifier_rl.html#ac7d3dceab4772096bbbeb3fa735d18a9", null ], + [ "n4", "struct_verifier_rl.html#a1e3f84b873bccc0c882aa6432c42d2f7", null ], + [ "version", "struct_verifier_rl.html#afa44ab69ffff5a3508366aeb2131fdaa", null ] + ] ], + [ "Fq2ElemStr", "struct_fq2_elem_str.html", [ + [ "a", "struct_fq2_elem_str.html#ab1d253eb24ba30eaf516ac429daab915", null ] + ] ], + [ "Fq6ElemStr", "struct_fq6_elem_str.html", [ + [ "a", "struct_fq6_elem_str.html#a89d656e5c815b4a2382d11ef6932a7d2", null ] + ] ], + [ "Fq12ElemStr", "struct_fq12_elem_str.html", [ + [ "a", "struct_fq12_elem_str.html#a0520947335aaf52de90af1dec5bdd112", null ] + ] ], + [ "EcdsaSignature", "struct_ecdsa_signature.html", [ + [ "x", "struct_ecdsa_signature.html#a64b623605a55a267a36df18f29142d0d", null ], + [ "y", "struct_ecdsa_signature.html#a2efd6bf37b12f35135bf325fa491b029", null ] + ] ], + [ "EcdsaPublicKey", "struct_ecdsa_public_key.html", [ + [ "x", "struct_ecdsa_public_key.html#a37c51614faf022eec491b4de8f3a13e1", null ], + [ "y", "struct_ecdsa_public_key.html#a4503c4613386cbc78add1dc245c99284", null ] + ] ], + [ "EcdsaPrivateKey", "struct_ecdsa_private_key.html", [ + [ "data", "struct_ecdsa_private_key.html#a97efee9b4079f95d94a104f9a6d8c96d", null ] + ] ], + [ "GroupId", "group___epid_types.html#gada666b48d0cbc301985405fde896f1de", null ], + [ "IssuerNonce", "group___epid_types.html#ga55eb2193045bde31af3f551565126042", null ], + [ "ReKeySeed", "group___epid_types.html#ga54bd22670f2e348593db7ab631131d10", null ], + [ "Seed", "group___epid_types.html#ga888541b8148df69c634a92c64ed51317", null ], + [ "HashAlg", "group___epid_types.html#ga5e450438f6f9a5eacd0cf5ce354ec890", [ + [ "kSha256", "group___epid_types.html#gga5e450438f6f9a5eacd0cf5ce354ec890aefb89989305b5c34120b0f18ee8e2c5d", null ], + [ "kSha384", "group___epid_types.html#gga5e450438f6f9a5eacd0cf5ce354ec890a0f4dde6e82b84f5769873f6704fcd290", null ], + [ "kSha512", "group___epid_types.html#gga5e450438f6f9a5eacd0cf5ce354ec890afb78d98f37fecc53dd1637d94c5c0055", null ], + [ "kSha512_256", "group___epid_types.html#gga5e450438f6f9a5eacd0cf5ce354ec890a9746b5049a62bca2f7b844925e6136ba", null ], + [ "kSha3_256", "group___epid_types.html#gga5e450438f6f9a5eacd0cf5ce354ec890a4fa16d3867498f5e2f8ae5c94b0fab85", null ], + [ "kSha3_384", "group___epid_types.html#gga5e450438f6f9a5eacd0cf5ce354ec890a90d21c8885ab138f7cf91f253dd6ef86", null ], + [ "kSha3_512", "group___epid_types.html#gga5e450438f6f9a5eacd0cf5ce354ec890ade8e74cf7910b3a71fe902a40abf7eee", null ] + ] ] +]; \ No newline at end of file diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/group___epid_verifier_module.html b/sgx-jvm/linux-sgx/external/epid/doc/html/group___epid_verifier_module.html new file mode 100644 index 0000000000..1e2f5d1f79 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/group___epid_verifier_module.html @@ -0,0 +1,834 @@ + + + + + + + +Intel® Enhanced Privacy ID SDK: verifier + + + + + + + + + + + + +
+
+ + + + + + +
+ +
+
+ + +
+
+ +
+
+
+ +
+
+ +
+
verifier
+
+
+ +

Verifier functionality. +More...

+ + + + + +

+Data Structures

struct  VerifierPrecomp
 Pre-computed member settings. More...
 
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Functions

EpidStatus EpidVerifierCreate (GroupPubKey const *pub_key, VerifierPrecomp const *precomp, VerifierCtx **ctx)
 Creates a new verifier context. More...
 
void EpidVerifierDelete (VerifierCtx **ctx)
 Deletes an existing verifier context. More...
 
EpidStatus EpidVerifierWritePrecomp (VerifierCtx const *ctx, VerifierPrecomp *precomp)
 Serializes the pre-computed verifier settings. More...
 
EpidStatus EpidVerifierSetPrivRl (VerifierCtx *ctx, PrivRl const *priv_rl, size_t priv_rl_size)
 Sets the private key based revocation list. More...
 
EpidStatus EpidVerifierSetSigRl (VerifierCtx *ctx, SigRl const *sig_rl, size_t sig_rl_size)
 Sets the signature based revocation list. More...
 
EpidStatus EpidVerifierSetGroupRl (VerifierCtx *ctx, GroupRl const *grp_rl, size_t grp_rl_size)
 Sets the group based revocation list. More...
 
EpidStatus EpidVerifierSetVerifierRl (VerifierCtx *ctx, VerifierRl const *ver_rl, size_t ver_rl_size)
 Sets the verifier revocation list. More...
 
EpidStatus EpidVerifierSetHashAlg (VerifierCtx *ctx, HashAlg hash_alg)
 Sets the hash algorithm to be used by a verifier. More...
 
EpidStatus EpidVerify (VerifierCtx const *ctx, EpidSignature const *sig, size_t sig_len, void const *msg, size_t msg_len, void const *basename, size_t basename_len)
 Verifies a signature and checks revocation status. More...
 
bool EpidAreSigsLinked (BasicSignature const *sig1, BasicSignature const *sig2)
 Determines if two signatures are linked. More...
 
EpidStatus EpidVerifyBasicSig (VerifierCtx const *ctx, BasicSignature const *sig, void const *msg, size_t msg_len, void const *basename, size_t basename_len)
 Verifies a member signature without revocation checks. More...
 
EpidStatus EpidNrVerify (VerifierCtx const *ctx, BasicSignature const *sig, void const *msg, size_t msg_len, SigRlEntry const *sigrl_entry, NrProof const *proof)
 Verifies the non-revoked proof for a single signature based revocation list entry. More...
 
EpidStatus EpidCheckPrivRlEntry (VerifierCtx const *ctx, BasicSignature const *sig, FpElemStr const *f)
 Verifies a signature has not been revoked in the private key based revocation list. More...
 
+

Detailed Description

+

Verifier functionality.

+

Defines the APIs needed by Intel(R) EPID verifiers. Each verifier context (VerifierCtx) represents a verifier for a single group.

+

Function Documentation

+ +
+
+ + + + + + + + + + + + + + + + + + +
bool EpidAreSigsLinked (BasicSignature const * sig1,
BasicSignature const * sig2 
)
+
+ +

Determines if two signatures are linked.

+

The Intel(R) EPID scheme allows signatures to be linked. If basename option is specified when signing, signatures with the same basename are linkable. This linking capability allows the verifier, or anyone, to know whether two Intel(R) EPID signatures are generated by the same member.

+
Parameters
+ + + +
[in]sig1A basic signature.
[in]sig2A basic signature.
+
+
+
Returns
bool
+
Return values
+ + + +
trueif the signatures were generated by the same member
falseif it couldn't be determined if the signatures were generated by the same member
+
+
+
Note
The input signatures should be verified using EpidVerifyBasicSig() before invocation. Behavior is undefined if either of the signatures cannot be verified.
+
See also
EpidVerifyBasicSig
+
+EpidSignBasic
+
+EpidSign
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
EpidStatus EpidCheckPrivRlEntry (VerifierCtx const * ctx,
BasicSignature const * sig,
FpElemStr const * f 
)
+
+ +

Verifies a signature has not been revoked in the private key based revocation list.

+

Used in constrained environments where, due to limited memory, it may not be possible to process through a large and potentially unbounded revocation list.

+
Parameters
+ + + + +
[in]ctxThe verifier context.
[in]sigThe basic signature.
[in]fThe private key based revocation list entry.
+
+
+
Note
Sig should be verified using EpidVerifyBasicSig() before invocation. Behavior is undefined if sig cannot be verified.
+
+This function should be used in conjunction with EpidNrVerify() and EpidVerifyBasicSig().
+
+If the result is not kEpidNoErr the verify should be considered to have failed.
+
Returns
EpidStatus
+
See also
EpidVerifierCreate
+
+EpidNrVerify
+
+EpidVerifyBasicSig
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
EpidStatus EpidNrVerify (VerifierCtx const * ctx,
BasicSignature const * sig,
void const * msg,
size_t msg_len,
SigRlEntry const * sigrl_entry,
NrProof const * proof 
)
+
+ +

Verifies the non-revoked proof for a single signature based revocation list entry.

+

Used in constrained environments where, due to limited memory, it may not be possible to process through a large and potentially unbounded revocation list.

+
Parameters
+ + + + + + + +
[in]ctxThe verifier context.
[in]sigThe basic signature.
[in]msgThe message that was signed.
[in]msg_lenThe size of msg in bytes.
[in]sigrl_entryThe signature based revocation list entry.
[in]proofThe non-revoked proof.
+
+
+
Returns
EpidStatus
+
Note
Sig should be verified using EpidVerifyBasicSig() before invocation. Behavior is undefined if sig cannot be verified.
+
+This function should be used in conjunction with EpidVerifyBasicSig() and EpidCheckPrivRlEntry().
+
+If the result is not kEpidNoErr, the verification should be considered to have failed.
+
See also
EpidVerifierCreate
+
+EpidVerifyBasicSig
+
+EpidCheckPrivRlEntry
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
EpidStatus EpidVerifierCreate (GroupPubKey const * pub_key,
VerifierPrecomp const * precomp,
VerifierCtx ** ctx 
)
+
+ +

Creates a new verifier context.

+

Must be called to create the verifier context that is used by other "Verifier" APIs.

+

Allocates memory for the context, then initializes it.

+

EpidVerifierDelete() must be called to safely release the member context.

+
Parameters
+ + + + +
[in]pub_keyThe group certificate.
[in]precompOptional pre-computed data. If NULL the value is computed internally and is readable using EpidVerifierWritePrecomp().
[out]ctxNewly constructed verifier context.
+
+
+
Returns
EpidStatus
+
Note
If the result is not kEpidNoErr the content of ctx is undefined.
+
See also
EpidVerifierDelete
+
+EpidVerifierWritePrecomp
+
Examples:
verifysig.c.
+
+
+
+ +
+
+ + + + + + + + +
void EpidVerifierDelete (VerifierCtx ** ctx)
+
+ +

Deletes an existing verifier context.

+

Must be called to safely release a verifier context created using EpidVerifierCreate().

+

De-initializes the context, frees memory used by the context, and sets the context pointer to NULL.

+
Parameters
+ + +
[in,out]ctxThe verifier context. Can be NULL.
+
+
+
See also
EpidVerifierCreate
+
Examples:
verifysig.c.
+
+
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
EpidStatus EpidVerifierSetGroupRl (VerifierCtxctx,
GroupRl const * grp_rl,
size_t grp_rl_size 
)
+
+ +

Sets the group based revocation list.

+

The caller is responsible for insuring the revocation list is authorized, e.g signed by the issuer. The caller is also responsible checking the version of the revocation list. The call fails if trying to set an older version of the revocation list than was last set.

+
Attention
The memory pointed to by grp_rl is accessed directly by the verifier until a new list is set or the verifier is destroyed. Do not modify the contents of this memory. The behavior of subsequent operations that rely on the revocation list is undefined if the memory is modified.
+
+It is the responsibility of the caller to free the memory pointed to by grp_rl after the verifier is no longer using it.
+
Parameters
+ + + + +
[in,out]ctxThe verifier context.
[in]grp_rlThe group based revocation list.
[in]grp_rl_sizeThe size of the group based revocation list in bytes.
+
+
+
Returns
EpidStatus
+
Note
If the result is not kEpidNoErr the group based revocation list pointed to by the verifier is undefined.
+
See also
EpidVerifierCreate
+
Examples:
verifysig.c.
+
+
+
+ +
+
+ + + + + + + + + + + + + + + + + + +
EpidStatus EpidVerifierSetHashAlg (VerifierCtxctx,
HashAlg hash_alg 
)
+
+ +

Sets the hash algorithm to be used by a verifier.

+
Parameters
+ + + +
[in]ctxThe verifier context.
[in]hash_algThe hash algorithm to use.
+
+
+
Returns
EpidStatus
+
Note
If the result is not kEpidNoErr, the hash algorithm used by the verifier is undefined.
+
See also
EpidVerifierCreate
+
+HashAlg
+
Examples:
verifysig.c.
+
+
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
EpidStatus EpidVerifierSetPrivRl (VerifierCtxctx,
PrivRl const * priv_rl,
size_t priv_rl_size 
)
+
+ +

Sets the private key based revocation list.

+

The caller is responsible for insuring the revocation list is authorized, e.g signed by the issuer. The caller is also responsible checking the version of the revocation list. The call fails if trying to set an older version of the revocation list than was last set.

+
Attention
The memory pointed to by priv_rl is accessed directly by the verifier until a new list is set or the verifier is destroyed. Do not modify the contents of this memory. The behavior of subsequent operations that rely on the revocation list is undefined if the memory is modified.
+
+It is the responsibility of the caller to free the memory pointed to by priv_rl after the verifier is no longer using it.
+
Parameters
+ + + + +
[in,out]ctxThe verifier context.
[in]priv_rlThe private key based revocation list.
[in]priv_rl_sizeThe size of the private key based revocation list in bytes.
+
+
+
Returns
EpidStatus
+
Note
If the result is not kEpidNoErr the private key based revocation list pointed to by the verifier is undefined.
+
See also
EpidVerifierCreate
+
Examples:
verifysig.c.
+
+
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
EpidStatus EpidVerifierSetSigRl (VerifierCtxctx,
SigRl const * sig_rl,
size_t sig_rl_size 
)
+
+ +

Sets the signature based revocation list.

+

The caller is responsible for insuring the revocation list is authorized, e.g signed by the issuer. The caller is also responsible checking the version of the revocation list. The call fails if trying to set an older version of the revocation list than was last set.

+
Attention
The memory pointed to by sig_rl is accessed directly by the verifier until a new list is set or the verifier is destroyed. Do not modify the contents of this memory. The behavior of subsequent operations that rely on the revocation list is undefined if the memory is modified.
+
+It is the responsibility of the caller to free the memory pointed to by sig_rl after the verifier is no longer using it.
+
Parameters
+ + + + +
[in,out]ctxThe verifier context.
[in]sig_rlThe signature based revocation list.
[in]sig_rl_sizeThe size of the signature based revocation list in bytes.
+
+
+
Returns
EpidStatus
+
Note
If the result is not kEpidNoErr the signature based revocation list pointed to by the verifier is undefined.
+
See also
EpidVerifierCreate
+
Examples:
verifysig.c.
+
+
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
EpidStatus EpidVerifierSetVerifierRl (VerifierCtxctx,
VerifierRl const * ver_rl,
size_t ver_rl_size 
)
+
+ +

Sets the verifier revocation list.

+

The caller is responsible for insuring the revocation list is authorized, e.g signed by the issuer. The caller is also responsible checking the version of the revocation list. The call fails if trying to set an older version of the revocation list than was last set.

+
Attention
The memory pointed to by ver_rl is accessed directly by the verifier until a new list is set or the verifier is destroyed. Do not modify the contents of this memory. The behavior of subsequent operations that rely on the revocation list is undefined if the memory is modified.
+
+It is the responsibility of the caller to free the memory pointed to by ver_rl after the verifier is no longer using it.
+
Parameters
+ + + + +
[in,out]ctxThe verifier context.
[in]ver_rlThe verifier revocation list.
[in]ver_rl_sizeThe size of the verifier revocation list in bytes.
+
+
+
Returns
EpidStatus
+
Note
If the result is not kEpidNoErr the verifier revocation list pointed to by the verifier is undefined.
+
See also
EpidVerifierCreate
+
Examples:
verifysig.c.
+
+
+
+ +
+
+ + + + + + + + + + + + + + + + + + +
EpidStatus EpidVerifierWritePrecomp (VerifierCtx const * ctx,
VerifierPrecompprecomp 
)
+
+ +

Serializes the pre-computed verifier settings.

+
Parameters
+ + + +
[in]ctxThe verifier context.
[out]precompThe Serialized pre-computed verifier settings.
+
+
+
Returns
EpidStatus
+
Note
If the result is not kEpidNoErr the content of precomp is undefined.
+
Examples:
verifysig.c.
+
+
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
EpidStatus EpidVerify (VerifierCtx const * ctx,
EpidSignature const * sig,
size_t sig_len,
void const * msg,
size_t msg_len,
void const * basename,
size_t basename_len 
)
+
+ +

Verifies a signature and checks revocation status.

+
Parameters
+ + + + + + + + +
[in]ctxThe verifier context.
[in]sigThe signature.
[in]sig_lenThe size of sig in bytes.
[in]msgThe message that was signed.
[in]msg_lenThe size of msg in bytes.
[in]basenameThe basename. Pass NULL if not specified
[in]basename_lenNumber of bytes in basename buffer. Must be 0 if basename is NULL.
+
+
+
Returns
EpidStatus
+
Return values
+ + + + + + + +
kEpidSigValidSignature validated successfully
kEpidSigInvalidSignature is invalid
kEpidSigRevokedinGroupRlSignature revoked in GroupRl
kEpidSigRevokedinPrivRlSignature revoked in PrivRl
kEpidSigRevokedinSigRlSignature revoked in SigRl
kEpidSigRevokedinVerifierRlSignature revoked in VerifierRl
+
+
+
Note
If the result is not kEpidNoErr or one of the values listed above the verify should be considered to have failed.
+
See also
EpidVerifierCreate
+
+EpidSignBasic
+
+EpidSign
+
Examples:
verifysig.c.
+
+
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
EpidStatus EpidVerifyBasicSig (VerifierCtx const * ctx,
BasicSignature const * sig,
void const * msg,
size_t msg_len,
void const * basename,
size_t basename_len 
)
+
+ +

Verifies a member signature without revocation checks.

+

Used in constrained environments where, due to limited memory, it may not be possible to process through a large and potentially unbounded revocation list.

+
Parameters
+ + + + + + + +
[in]ctxThe verifier context.
[in]sigThe basic signature.
[in]msgThe message that was signed.
[in]msg_lenThe size of msg in bytes.
[in]basenameThe basename. Pass NULL if not specified
[in]basename_lenNumber of bytes in basename buffer. Must be 0 if basename is NULL.
+
+
+
Returns
EpidStatus
+
Note
This function should be used in conjunction with EpidNrVerify() and EpidCheckPrivRlEntry().
+
+If the result is not kEpidNoErr the verify should be considered to have failed.
+
See also
EpidVerifierCreate
+
+EpidSignBasic
+
+EpidSign
+ +
+
+
+
+ + + + + diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/group___epid_verifier_module.js b/sgx-jvm/linux-sgx/external/epid/doc/html/group___epid_verifier_module.js new file mode 100644 index 0000000000..cabf2b5c64 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/group___epid_verifier_module.js @@ -0,0 +1,22 @@ +var group___epid_verifier_module = +[ + [ "VerifierPrecomp", "struct_verifier_precomp.html", [ + [ "e12", "struct_verifier_precomp.html#ad1106376f12772942af0331eb74de6e5", null ], + [ "e22", "struct_verifier_precomp.html#af8fd90f3a5a2be932a97dcd86099d5b2", null ], + [ "e2w", "struct_verifier_precomp.html#a8caf79578e3c0baf91921460391103ca", null ], + [ "eg12", "struct_verifier_precomp.html#ab061d6cc07d1467eeb5bf25f3ea7e306", null ] + ] ], + [ "EpidAreSigsLinked", "group___epid_verifier_module.html#gae44bd8acbc1e7205aeedff0c7e2632a8", null ], + [ "EpidCheckPrivRlEntry", "group___epid_verifier_module.html#gaeb05e6faea6f09c0665b13adc6e7ddea", null ], + [ "EpidNrVerify", "group___epid_verifier_module.html#gac6e2fab59e3af8a33a74a5b201642700", null ], + [ "EpidVerifierCreate", "group___epid_verifier_module.html#ga1d116daaee5466a1485d26ebc4e3ab70", null ], + [ "EpidVerifierDelete", "group___epid_verifier_module.html#ga6707e691f4b3916f9c684d5bbd463d12", null ], + [ "EpidVerifierSetGroupRl", "group___epid_verifier_module.html#ga1d41d6ef4dabbc30ec28452edd6baffb", null ], + [ "EpidVerifierSetHashAlg", "group___epid_verifier_module.html#ga97b58b2382f24756b66a357f1e825c92", null ], + [ "EpidVerifierSetPrivRl", "group___epid_verifier_module.html#gafab08180a43b58ce2e1d56c4b070bb0e", null ], + [ "EpidVerifierSetSigRl", "group___epid_verifier_module.html#ga4c7c9820409ee06f30bb8dc75fdd5dcf", null ], + [ "EpidVerifierSetVerifierRl", "group___epid_verifier_module.html#ga0909703a0a4dfe080374d0d99077465a", null ], + [ "EpidVerifierWritePrecomp", "group___epid_verifier_module.html#ga92df4d00ea4ee59d7bfd35b23da03392", null ], + [ "EpidVerify", "group___epid_verifier_module.html#ga39b240a17f310894e9f5946c9a731798", null ], + [ "EpidVerifyBasicSig", "group___epid_verifier_module.html#ga974b92a62e8b65ea75cf802e8cc6bb6a", null ] +]; \ No newline at end of file diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/group___error_codes.html b/sgx-jvm/linux-sgx/external/epid/doc/html/group___error_codes.html new file mode 100644 index 0000000000..557e3e73fc --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/group___error_codes.html @@ -0,0 +1,225 @@ + + + + + + + +Intel® Enhanced Privacy ID SDK: errors + + + + + + + + + + + + +
+
+ + + + + + +
+ +
+
+ + +
+
+ +
+
+
+ +
+
+ +
+
errors
+
+
+ +

Error reporting interface. +More...

+ + + + + +

+Enumerations

enum  EpidStatus {
+  kEpidNoErr = 0, +kEpidSigValid = 0, +kEpidSigInvalid = 1, +kEpidSigRevokedinGroupRl = 2, +
+  kEpidSigRevokedinPrivRl = 3, +kEpidSigRevokedinSigRl = 4, +kEpidSigRevokedinVerifierRl = 5, +kEpidErr = -999, +
+  kEpidNotImpl, +kEpidBadArgErr, +kEpidNoMemErr, +kEpidMemAllocErr, +
+  kEpidMathErr, +kEpidDivByZeroErr, +kEpidUnderflowErr, +kEpidHashAlgorithmNotSupported, +
+  kEpidRandMaxIterErr, +kEpidDuplicateErr +
+ }
 Return status for SDK functions. More...
 
+ + + + +

+Functions

char const * EpidStatusToString (EpidStatus e)
 Returns string representation of error code. More...
 
+

Detailed Description

+

Error reporting interface.

+

This module defines the return status type. It also provides tools for interactions with status values, such as converting them to a string.

+

Enumeration Type Documentation

+ +
+
+ + + + +
enum EpidStatus
+
+ +

Return status for SDK functions.

+

Convention for status values is as follows:

    +
  • Zero indicates "success"
  • +
  • Any positive number indicates "success with status"
  • +
  • Any negative number indicates "failure"
  • +
+ + + + + + + + + + + + + + + + + + + +
Enumerator
kEpidNoErr  +

no error

+
kEpidSigValid  +

Signature is valid.

+
kEpidSigInvalid  +

Signature is invalid.

+
kEpidSigRevokedinGroupRl  +

Signature revoked in GroupRl.

+
kEpidSigRevokedinPrivRl  +

Signature revoked in PrivRl.

+
kEpidSigRevokedinSigRl  +

Signature revoked in SigRl.

+
kEpidSigRevokedinVerifierRl  +

Signature revoked in VerifierRl.

+
kEpidErr  +

unspecified error

+
kEpidNotImpl  +

not implemented error

+
kEpidBadArgErr  +

incorrect arg to function

+
kEpidNoMemErr  +

not enough memory for the operation

+
kEpidMemAllocErr  +

insufficient memory allocated for operation

+
kEpidMathErr  +

internal math error

+
kEpidDivByZeroErr  +

an attempt to divide by zero

+
kEpidUnderflowErr  +

a value became less than minimum supported level

+
kEpidHashAlgorithmNotSupported  +

unsupported hash algorithm type

+
kEpidRandMaxIterErr  +

reached max iteration for random number generation

+
kEpidDuplicateErr  +

argument would add duplicate entry

+
+
Examples:
verifysig.c.
+
+
+
+

Function Documentation

+ +
+
+ + + + + + + + +
char const* EpidStatusToString (EpidStatus e)
+
+ +

Returns string representation of error code.

+
Parameters
+ + +
eThe status value.
+
+
+
Returns
The string describing the status.
+ +
+
+
+
+ + + + + diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/group___error_codes.js b/sgx-jvm/linux-sgx/external/epid/doc/html/group___error_codes.js new file mode 100644 index 0000000000..6121a1ddb8 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/group___error_codes.js @@ -0,0 +1,24 @@ +var group___error_codes = +[ + [ "EpidStatus", "group___error_codes.html#gafdb27c77c2c4b32c807e326a8a0da360", [ + [ "kEpidNoErr", "group___error_codes.html#ggafdb27c77c2c4b32c807e326a8a0da360a8a6861e14322ca9193498ffc955537f9", null ], + [ "kEpidSigValid", "group___error_codes.html#ggafdb27c77c2c4b32c807e326a8a0da360ab45ad60085d03c03ea30b40a0519897e", null ], + [ "kEpidSigInvalid", "group___error_codes.html#ggafdb27c77c2c4b32c807e326a8a0da360aeedd19b8a1cbdecf963f90b4860e02b8", null ], + [ "kEpidSigRevokedinGroupRl", "group___error_codes.html#ggafdb27c77c2c4b32c807e326a8a0da360a2b38f44424cecd7b432194a2012dc9c7", null ], + [ "kEpidSigRevokedinPrivRl", "group___error_codes.html#ggafdb27c77c2c4b32c807e326a8a0da360a780a20821863553b88ca617a6fc0f718", null ], + [ "kEpidSigRevokedinSigRl", "group___error_codes.html#ggafdb27c77c2c4b32c807e326a8a0da360aff83186b61d48f9fee5f691c5b219bc1", null ], + [ "kEpidSigRevokedinVerifierRl", "group___error_codes.html#ggafdb27c77c2c4b32c807e326a8a0da360addbba767bb884b4459a567056b4d3f86", null ], + [ "kEpidErr", "group___error_codes.html#ggafdb27c77c2c4b32c807e326a8a0da360aa08f0d2e394b37694117a6a32bc71e6e", null ], + [ "kEpidNotImpl", "group___error_codes.html#ggafdb27c77c2c4b32c807e326a8a0da360a5252da1ff519a098446723e9edd30cc7", null ], + [ "kEpidBadArgErr", "group___error_codes.html#ggafdb27c77c2c4b32c807e326a8a0da360ad134d6cc95a9dcb1b1a9f9c358047cbf", null ], + [ "kEpidNoMemErr", "group___error_codes.html#ggafdb27c77c2c4b32c807e326a8a0da360ab7dfec784192a827a91a4b8a6054d01c", null ], + [ "kEpidMemAllocErr", "group___error_codes.html#ggafdb27c77c2c4b32c807e326a8a0da360a11a4d2f1c37064eb663de08dc57bcda8", null ], + [ "kEpidMathErr", "group___error_codes.html#ggafdb27c77c2c4b32c807e326a8a0da360a1739ecb620f4bede2e1b84e52a96cee6", null ], + [ "kEpidDivByZeroErr", "group___error_codes.html#ggafdb27c77c2c4b32c807e326a8a0da360a893cd0d417b139bb376d09c93695c3f3", null ], + [ "kEpidUnderflowErr", "group___error_codes.html#ggafdb27c77c2c4b32c807e326a8a0da360a83a867b4f71ee13edbfca2f1b72abbec", null ], + [ "kEpidHashAlgorithmNotSupported", "group___error_codes.html#ggafdb27c77c2c4b32c807e326a8a0da360ad4d4ff24a7ef2cd7a50b8082265e9ff4", null ], + [ "kEpidRandMaxIterErr", "group___error_codes.html#ggafdb27c77c2c4b32c807e326a8a0da360a61234ad9610406da6bf7977afd72a357", null ], + [ "kEpidDuplicateErr", "group___error_codes.html#ggafdb27c77c2c4b32c807e326a8a0da360a3706f895a660260033b5b91890516c0f", null ] + ] ], + [ "EpidStatusToString", "group___error_codes.html#ga59e8680ce52509302fd58a987e45004d", null ] +]; \ No newline at end of file diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/group___file_parser.html b/sgx-jvm/linux-sgx/external/epid/doc/html/group___file_parser.html new file mode 100644 index 0000000000..70cd3af34e --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/group___file_parser.html @@ -0,0 +1,439 @@ + + + + + + + +Intel® Enhanced Privacy ID SDK: fileparser + + + + + + + + + + + + +
+
+ + + + + + +
+ +
+
+ + +
+
+ +
+
+
+ +
+ +
+ +

Parser for issuer material. +More...

+ + + + + + + + +

+Data Structures

struct  EpidFileHeader
 Intel(R) EPID binary file header. More...
 
struct  EpidCaCertificate
 IoT CA Certificate binary format. More...
 
+ + + + +

+Enumerations

enum  EpidFileType {
+  kIssuingCaPubKeyFile, +kGroupPubKeyFile, +kPrivRlFile, +kSigRlFile, +
+  kGroupRlFile, +kPrivRlRequestFile, +kSigRlRequestFile, +kGroupRlRequestFile, +
+  kNumFileTypes +
+ }
 Recognized Intel(R) EPID file types. More...
 
+ + + + + + + + + + + + + +

+Functions

EpidStatus EpidParseGroupPubKeyFile (void const *buf, size_t len, EpidCaCertificate const *cert, GroupPubKey *pubkey)
 Extracts group public key from buffer in issuer binary format. More...
 
EpidStatus EpidParsePrivRlFile (void const *buf, size_t len, EpidCaCertificate const *cert, PrivRl *rl, size_t *rl_len)
 Extracts private key revocation list from buffer in issuer binary format. More...
 
EpidStatus EpidParseSigRlFile (void const *buf, size_t len, EpidCaCertificate const *cert, SigRl *rl, size_t *rl_len)
 Extracts signature revocation list from buffer in issuer binary format. More...
 
EpidStatus EpidParseGroupRlFile (void const *buf, size_t len, EpidCaCertificate const *cert, GroupRl *rl, size_t *rl_len)
 Extracts group revocation list from buffer in issuer binary format. More...
 
+ + + + +

+Variables

+const OctStr16 kEpidFileTypeCode [kNumFileTypes]
 Encoding of issuer material file types.
 
+

Detailed Description

+

Parser for issuer material.

+

Provides an API for parsing buffers formatted according to the various IoT Intel(R) EPID binary file formats.

+

Enumeration Type Documentation

+ +
+
+ + + + +
enum EpidFileType
+
+ +

Recognized Intel(R) EPID file types.

+ + + + + + + + + + +
Enumerator
kIssuingCaPubKeyFile  +

IoT Issuing CA public key file.

+
kGroupPubKeyFile  +

Group Public Key Output File Format.

+
kPrivRlFile  +

Binary Private Key Revocation List.

+
kSigRlFile  +

Binary Signature Revocation List.

+
kGroupRlFile  +

Binary Group Revocation List.

+
kPrivRlRequestFile  +

Binary Private Key Revocation Request.

+
kSigRlRequestFile  +

Binary Signature Revocation Request.

+
kGroupRlRequestFile  +

Binary Group Revocation Request.

+
kNumFileTypes  +

Maximum number of file types.

+
+ +
+
+

Function Documentation

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
EpidStatus EpidParseGroupPubKeyFile (void const * buf,
size_t len,
EpidCaCertificate const * cert,
GroupPubKeypubkey 
)
+
+ +

Extracts group public key from buffer in issuer binary format.

+

Extracts the first group public key from a buffer with format of Intel(R) EPID 2.0 Group Public Key Certificate Binary File. The function validates that the first public key was signed by the private key corresponding to the provided CA certificate and the size of the input buffer is correct.

+
Warning
It is the responsibility of the caller to authenticate the EpidCaCertificate.
+
Parameters
+ + + + + +
[in]bufPointer to buffer containing public key to extract.
[in]lenThe size of buf in bytes.
[in]certThe issuing CA public key certificate.
[out]pubkeyThe extracted group public key.
+
+
+
Returns
EpidStatus
+
Return values
+ + +
kEpidSigInvalidParsing failed due to data authentication failure.
+
+
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
EpidStatus EpidParseGroupRlFile (void const * buf,
size_t len,
EpidCaCertificate const * cert,
GroupRlrl,
size_t * rl_len 
)
+
+ +

Extracts group revocation list from buffer in issuer binary format.

+

Extracts the group revocation list from a buffer with format of Binary Group Certificate Revocation List File. The function validates that the revocation list was signed by the private key corresponding to the provided CA certificate and the size of the input buffer is correct.

+

To determine the required size of the revocation list output buffer, provide a null pointer for the output buffer.

+
Warning
It is the responsibility of the caller to authenticate the EpidCaCertificate.
+
Parameters
+ + + + + + +
[in]bufPointer to buffer containing the revocation list to extract.
[in]lenThe size of buf in bytes.
[in]certThe issuing CA public key certificate.
[out]rlThe extracted revocation list. If Null, rl_len is filled with the required output buffer size.
[in,out]rl_lenThe size of rl in bytes.
+
+
+
Returns
EpidStatus
+
Return values
+ + +
kEpidSigInvalidParsing failed due to data authentication failure.
+
+
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
EpidStatus EpidParsePrivRlFile (void const * buf,
size_t len,
EpidCaCertificate const * cert,
PrivRlrl,
size_t * rl_len 
)
+
+ +

Extracts private key revocation list from buffer in issuer binary format.

+

Extracts the private key revocation list from a buffer with format of Binary Private Key Revocation List File. The function validates that the revocation list was signed by the private key corresponding to the provided CA certificate and the size of the input buffer is correct.

+

To determine the required size of the revocation list output buffer, provide a null pointer for the output buffer.

+
Warning
It is the responsibility of the caller to authenticate the EpidCaCertificate.
+
Parameters
+ + + + + + +
[in]bufPointer to buffer containing the revocation list to extract.
[in]lenThe size of buf in bytes.
[in]certThe issuing CA public key certificate.
[out]rlThe extracted revocation list. If Null, rl_len is filled with the required output buffer size.
[in,out]rl_lenThe size of rl in bytes.
+
+
+
Returns
EpidStatus
+
Return values
+ + +
kEpidSigInvalidParsing failed due to data authentication failure.
+
+
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
EpidStatus EpidParseSigRlFile (void const * buf,
size_t len,
EpidCaCertificate const * cert,
SigRlrl,
size_t * rl_len 
)
+
+ +

Extracts signature revocation list from buffer in issuer binary format.

+

Extracts the signature based revocation list from a buffer with format of Binary Signature Revocation List File. The function validates that the revocation list was signed by the private key corresponding to the provided CA certificate and the size of the input buffer is correct.

+

To determine the required size of the revocation list output buffer, provide a null pointer for the output buffer.

+
Warning
It is the responsibility of the caller to authenticate the EpidCaCertificate.
+
Parameters
+ + + + + + +
[in]bufPointer to buffer containing the revocation list to extract.
[in]lenThe size of buf in bytes.
[in]certThe issuing CA public key certificate.
[out]rlThe extracted revocation list. If Null, rl_len is filled with the required output buffer size.
[in,out]rl_lenThe size of rl in bytes.
+
+
+
Returns
EpidStatus
+
Return values
+ + +
kEpidSigInvalidParsing failed due to data authentication failure.
+
+
+ +
+
+
+
+ + + + + diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/group___file_parser.js b/sgx-jvm/linux-sgx/external/epid/doc/html/group___file_parser.js new file mode 100644 index 0000000000..0d7346c603 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/group___file_parser.js @@ -0,0 +1,34 @@ +var group___file_parser = +[ + [ "EpidFileHeader", "struct_epid_file_header.html", [ + [ "epid_version", "struct_epid_file_header.html#a35d43c51c1739940381e4898ca87b824", null ], + [ "file_type", "struct_epid_file_header.html#af5d48c739cc6c00c6e1ce35abf4f1473", null ] + ] ], + [ "EpidCaCertificate", "struct_epid_ca_certificate.html", [ + [ "a", "struct_epid_ca_certificate.html#a2811c1914ffae913820f13da914c8f01", null ], + [ "b", "struct_epid_ca_certificate.html#a280e0b0238cf45834c21849ab8a7e124", null ], + [ "header", "struct_epid_ca_certificate.html#ac03cf7257c52ad14e3dd3201b930dd50", null ], + [ "prime", "struct_epid_ca_certificate.html#a3a44e8050ca2f5085652b2b4e15b779c", null ], + [ "pubkey", "struct_epid_ca_certificate.html#a9d2fc21f46cf9fc96e2ea557b70e5356", null ], + [ "r", "struct_epid_ca_certificate.html#ab9d4c318b1fc8d38d3ce53b29f2dfee2", null ], + [ "signature", "struct_epid_ca_certificate.html#a2f8f09ae02919c379c38386668b47418", null ], + [ "x", "struct_epid_ca_certificate.html#a4f77996f90ed7da1d0503c4236b2c9d1", null ], + [ "y", "struct_epid_ca_certificate.html#abd69cce8d5e3940787ee0d17f72184ab", null ] + ] ], + [ "EpidFileType", "group___file_parser.html#ga9a33be7edc6b4c7a867fb07bd2bddecb", [ + [ "kIssuingCaPubKeyFile", "group___file_parser.html#gga9a33be7edc6b4c7a867fb07bd2bddecbac24554caafe2db01e2daed413188cd92", null ], + [ "kGroupPubKeyFile", "group___file_parser.html#gga9a33be7edc6b4c7a867fb07bd2bddecba1f8d8c4b253403a35c51e05d34a7ca1e", null ], + [ "kPrivRlFile", "group___file_parser.html#gga9a33be7edc6b4c7a867fb07bd2bddecba692b4141bff8225bee6000750b0da322", null ], + [ "kSigRlFile", "group___file_parser.html#gga9a33be7edc6b4c7a867fb07bd2bddecba8aead4b6aab87a1efb2d7e8c77a9b710", null ], + [ "kGroupRlFile", "group___file_parser.html#gga9a33be7edc6b4c7a867fb07bd2bddecba8e5247daee3999540e6cb24d4c2b3770", null ], + [ "kPrivRlRequestFile", "group___file_parser.html#gga9a33be7edc6b4c7a867fb07bd2bddecbac708ba9e56eaeac0f1256457cbd45911", null ], + [ "kSigRlRequestFile", "group___file_parser.html#gga9a33be7edc6b4c7a867fb07bd2bddecbac52e5fe24a12424316f655b9b7c62600", null ], + [ "kGroupRlRequestFile", "group___file_parser.html#gga9a33be7edc6b4c7a867fb07bd2bddecbab772fa1e3f221af125ffb34b86b3f24c", null ], + [ "kNumFileTypes", "group___file_parser.html#gga9a33be7edc6b4c7a867fb07bd2bddecbac6d742ea3dd3b17f6d763970ac84b811", null ] + ] ], + [ "EpidParseGroupPubKeyFile", "group___file_parser.html#ga43fdbc1bf2edd3695d21cb457365afbb", null ], + [ "EpidParseGroupRlFile", "group___file_parser.html#gad767f72dc55307b872a8b5600da3fd6f", null ], + [ "EpidParsePrivRlFile", "group___file_parser.html#gadc033fb23e3cbda56aa7e3d412060b7e", null ], + [ "EpidParseSigRlFile", "group___file_parser.html#ga237ef5a43076aa6fc6eb18829a93da3f", null ], + [ "kEpidFileTypeCode", "group___file_parser.html#ga3770c39a0546c79447c9d4159d794c33", null ] +]; \ No newline at end of file diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/group___finite_field_primitives.html b/sgx-jvm/linux-sgx/external/epid/doc/html/group___finite_field_primitives.html new file mode 100644 index 0000000000..1c40c12d63 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/group___finite_field_primitives.html @@ -0,0 +1,1048 @@ + + + + + + + +Intel® Enhanced Privacy ID SDK: finitefield + + + + + + + + + + + + +
+
+ + + + + + +
+ +
+
+ + +
+
+ +
+
+
+ +
+
+ +
+
finitefield
+
+
+ +

Finite field operations. +More...

+ + + + + + + + +

+Typedefs

+typedef struct FiniteField FiniteField
 A finite field.
 
+typedef struct FfElement FfElement
 An element in a finite field.
 
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Functions

EpidStatus NewFiniteField (BigNumStr const *prime, FiniteField **ff)
 Creates new finite field. More...
 
EpidStatus NewFiniteFieldViaBinomalExtension (FiniteField const *ground_field, FfElement const *ground_element, int degree, FiniteField **ff)
 Creates a new finite field using binomial extension. More...
 
void DeleteFiniteField (FiniteField **ff)
 Frees a previously allocated FiniteField. More...
 
EpidStatus NewFfElement (FiniteField const *ff, FfElement **new_ff_elem)
 Creates a new finite field element. More...
 
void DeleteFfElement (FfElement **ff_elem)
 Frees a previously allocated FfElement. More...
 
EpidStatus ReadFfElement (FiniteField *ff, void const *ff_elem_str, size_t strlen, FfElement *ff_elem)
 Deserializes a FfElement from a string. More...
 
EpidStatus WriteFfElement (FiniteField *ff, FfElement const *ff_elem, void *ff_elem_str, size_t strlen)
 Serializes a finite field element to a string. More...
 
EpidStatus FfNeg (FiniteField *ff, FfElement const *a, FfElement *r)
 Calculates the additive inverse of a finite field element. More...
 
EpidStatus FfInv (FiniteField *ff, FfElement const *a, FfElement *r)
 Calculates the multiplicative inverse of a finite field element. More...
 
EpidStatus FfAdd (FiniteField *ff, FfElement const *a, FfElement const *b, FfElement *r)
 Adds two finite field elements. More...
 
EpidStatus FfMul (FiniteField *ff, FfElement const *a, FfElement const *b, FfElement *r)
 Multiplies two finite field elements. More...
 
EpidStatus FfIsZero (FiniteField *ff, FfElement const *a, bool *is_zero)
 Checks if given finite field element is the additive identity (zero). More...
 
EpidStatus FfExp (FiniteField *ff, FfElement const *a, BigNum const *b, FfElement *r)
 Raises an element of a finite field to a power. More...
 
EpidStatus FfMultiExp (FiniteField *ff, FfElement const **a, BigNumStr const **b, size_t m, FfElement *r)
 Multi-exponentiates finite field elements. More...
 
EpidStatus FfSscmMultiExp (FiniteField *ff, FfElement const **a, BigNumStr const **b, size_t m, FfElement *r)
 Software side-channel mitigated implementation of FfMultiExp. More...
 
EpidStatus FfIsEqual (FiniteField *ff, FfElement const *a, FfElement const *b, bool *is_equal)
 Checks if two finite field elements are equal. More...
 
EpidStatus FfHash (FiniteField *ff, void const *msg, size_t msg_len, HashAlg hash_alg, FfElement *r)
 Hashes an arbitrary message to an element in a finite field. More...
 
EpidStatus FfGetRandom (FiniteField *ff, BigNumStr const *low_bound, BitSupplier rnd_func, void *rnd_param, FfElement *r)
 Generate random finite field element. More...
 
+

Detailed Description

+

Finite field operations.

+

provides APIs for working with finite fields. Finite fields allow simple mathematical operations based on a finite set of discrete values. the results of these operations are also contained in the same set.

+

A simple example of a finite field is all integers from zero that are less than a given value.

+

The elements (FfElement) of a finite field can be used in a variety of simple mathematical operations that result in elements of the same field.

+

Function Documentation

+ +
+
+ + + + + + + + +
void DeleteFfElement (FfElement ** ff_elem)
+
+ +

Frees a previously allocated FfElement.

+

Frees memory pointed to by ff_elem. Nulls the pointer.

+
Parameters
+ + +
[in]ff_elemThe finite field element. Can be NULL.
+
+
+
See also
NewFfElement
+ +
+
+ +
+
+ + + + + + + + +
void DeleteFiniteField (FiniteField ** ff)
+
+ +

Frees a previously allocated FiniteField.

+

Frees memory pointed to by finite field. Nulls the pointer.

+
Parameters
+ + +
[in]ffThe Finite field. Can be NULL.
+
+
+
See also
NewFiniteField
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
EpidStatus FfAdd (FiniteFieldff,
FfElement const * a,
FfElement const * b,
FfElementr 
)
+
+ +

Adds two finite field elements.

+
Parameters
+ + + + + +
[in]ffThe finite field.
[out]aThe left hand parameter.
[out]bThe right hand parameter.
[out]rThe result of adding a and b.
+
+
+
Returns
EpidStatus
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
EpidStatus FfExp (FiniteFieldff,
FfElement const * a,
BigNum const * b,
FfElementr 
)
+
+ +

Raises an element of a finite field to a power.

+
Parameters
+ + + + + +
[in]ffThe finite field in which to perform the operation
[in]aThe base.
[in]bThe power.
[out]rThe result of raising a to the power b.
+
+
+
Returns
EpidStatus
+
See also
NewFiniteField
+
+NewFfElement
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
EpidStatus FfGetRandom (FiniteFieldff,
BigNumStr const * low_bound,
BitSupplier rnd_func,
void * rnd_param,
FfElementr 
)
+
+ +

Generate random finite field element.

+
Parameters
+ + + + + + +
[in]ffThe finite field associated with the random finite field element.
[in]low_boundLower bound of the random finite field to be generated.
[in]rnd_funcRandom number generator.
[in]rnd_paramPass through context data for rnd_func.
[in,out]rThe random finite field element.
+
+
+
Returns
EpidStatus
+
Return values
+ + +
kEpidRandMaxIterErrthe function should be called again with different random data.
+
+
+
See also
NewFfElement
+
+BitSupplier
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
EpidStatus FfHash (FiniteFieldff,
void const * msg,
size_t msg_len,
HashAlg hash_alg,
FfElementr 
)
+
+ +

Hashes an arbitrary message to an element in a finite field.

+
Parameters
+ + + + + + +
[in]ffThe finite field.
[in]msgThe message.
[in]msg_lenThe size of msg in bytes.
[in]hash_algThe hash algorithm.
[out]rThe hashed value.
+
+
+
Returns
EpidStatus
+
See also
NewFiniteField
+
+NewFfElement
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
EpidStatus FfInv (FiniteFieldff,
FfElement const * a,
FfElementr 
)
+
+ +

Calculates the multiplicative inverse of a finite field element.

+
Parameters
+ + + + +
[in]ffThe finite field.
[in]aThe element.
[out]rThe inverted element.
+
+
+
Returns
EpidStatus
+
See also
NewFiniteField
+
+NewFfElement
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
EpidStatus FfIsEqual (FiniteFieldff,
FfElement const * a,
FfElement const * b,
boolis_equal 
)
+
+ +

Checks if two finite field elements are equal.

+
Parameters
+ + + + + +
[in]ffThe finite field.
[in]aAn element to check.
[in]bAnother element to check.
[out]is_equalThe result of the check.
+
+
+
Returns
EpidStatus
+
See also
NewEcGroup
+
+NewEcPoint
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
EpidStatus FfIsZero (FiniteFieldff,
FfElement const * a,
boolis_zero 
)
+
+ +

Checks if given finite field element is the additive identity (zero).

+
Parameters
+ + + + +
[in]ffThe finite field.
[out]aThe element.
[out]is_zeroThe result of the check.
+
+
+
Returns
EpidStatus
+
See also
NewFiniteField
+
+NewFfElement
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
EpidStatus FfMul (FiniteFieldff,
FfElement const * a,
FfElement const * b,
FfElementr 
)
+
+ +

Multiplies two finite field elements.

+
Parameters
+ + + + + +
[in]ffThe finite field.
[out]aThe left hand parameter.
[out]bThe right hand parameter. If ff is an extension field of a field F then this parameter may be an element of either ff or F.
[out]rThe result of multiplying a and b.
+
+
+
Returns
EpidStatus
+
See also
NewFiniteField
+
+NewFfElement
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
EpidStatus FfMultiExp (FiniteFieldff,
FfElement const ** a,
BigNumStr const ** b,
size_t m,
FfElementr 
)
+
+ +

Multi-exponentiates finite field elements.

+

Calculates FfExp(p[0],b[0]) * ... * FfExp(p[m-1],b[m-1]) for m > 1

+
Parameters
+ + + + + + +
[in]ffThe finite field in which to perform the operation
[in]aThe bases.
[in]bThe powers.
[in]mNumber of entries in a and b.
[out]rThe result of raising each a to the corresponding power b and multiplying the results.
+
+
+
Returns
EpidStatus
+
See also
NewFiniteField
+
+NewFfElement
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
EpidStatus FfNeg (FiniteFieldff,
FfElement const * a,
FfElementr 
)
+
+ +

Calculates the additive inverse of a finite field element.

+
Parameters
+ + + + +
[in]ffThe finite field.
[in]aThe element.
[out]rThe inverted element.
+
+
+
Returns
EpidStatus
+
See also
NewFiniteField
+
+NewFfElement
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
EpidStatus FfSscmMultiExp (FiniteFieldff,
FfElement const ** a,
BigNumStr const ** b,
size_t m,
FfElementr 
)
+
+ +

Software side-channel mitigated implementation of FfMultiExp.

+

Calculates FfExp(p[0],b[0]) * ... * FfExp(p[m-1],b[m-1]) for m > 1

+
Attention
The reference implementation of FfSscmMultiExp calls FfMultiExp directly because the implementation of FfMultiExp is already side channel mitigated. Implementers providing their own versions of this function are responsible for ensuring that FfSscmMultiExp is side channel mitigated per section 8 of the Intel(R) EPID 2.0 spec.
+
Parameters
+ + + + + + +
[in]ffThe finite field in which to perform the operation.
[in]aThe bases.
[in]bThe powers.
[in]mNumber of entries in a and b.
[out]rThe result of raising each a to the corresponding power b and multiplying the results.
+
+
+
Returns
EpidStatus
+
See also
NewFiniteField
+
+NewFfElement
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + +
EpidStatus NewFfElement (FiniteField const * ff,
FfElement ** new_ff_elem 
)
+
+ +

Creates a new finite field element.

+

Allocates memory and creates a new finite field element.

+

Use DeleteFfElement() to free memory.

+
Parameters
+ + + +
[in]ffThe finite field.
[out]new_ff_elemThe Newly constructed finite field element.
+
+
+
Returns
EpidStatus
+
See also
NewFiniteField
+
+DeleteFfElement
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + +
EpidStatus NewFiniteField (BigNumStr const * prime,
FiniteField ** ff 
)
+
+ +

Creates new finite field.

+

Allocates memory and creates a new finite field GF(prime).

+

Use DeleteFiniteField() to free memory.

+
Parameters
+ + + +
[in]primeThe order of finite field.
[out]ffThe Newly constructed finite field.
+
+
+
Returns
EpidStatus
+
See also
DeleteFiniteField
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
EpidStatus NewFiniteFieldViaBinomalExtension (FiniteField const * ground_field,
FfElement const * ground_element,
int degree,
FiniteField ** ff 
)
+
+ +

Creates a new finite field using binomial extension.

+

Allocates memory and creates a finite field using binomial extension.

+

Use DeleteFiniteField() to free memory.

+
Parameters
+ + + + + +
[in]ground_fieldThe ground field.
[in]ground_elementThe low-order term of the extension.
[in]degreeThe degree of the extension.
[out]ffThe Newly constructed finite field.
+
+
+
Returns
EpidStatus
+
See also
DeleteFiniteField
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
EpidStatus ReadFfElement (FiniteFieldff,
void const * ff_elem_str,
size_t strlen,
FfElementff_elem 
)
+
+ +

Deserializes a FfElement from a string.

+
Parameters
+ + + + + +
[in]ffThe the finite field.
[in]ff_elem_strThe serialized value.
[in]strlenThe size of ff_elem_str in bytes.
[out]ff_elemthe target FfElement.
+
+
+
Returns
EpidStatus
+
See also
NewFfElement
+
+WriteFfElement
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
EpidStatus WriteFfElement (FiniteFieldff,
FfElement const * ff_elem,
void * ff_elem_str,
size_t strlen 
)
+
+ +

Serializes a finite field element to a string.

+
Parameters
+ + + + + +
[in]ffThe finite field.
[in]ff_elemThe FfElement to be serialized.
[out]ff_elem_strThe target string.
[in]strlenThe size of ff_elem_str in bytes.
+
+
+
Returns
EpidStatus
+
See also
NewFfElement
+
+FpElemStr
+
+FqElemStr
+
+GtElemStr
+ +
+
+
+
+ + + + + diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/group___finite_field_primitives.js b/sgx-jvm/linux-sgx/external/epid/doc/html/group___finite_field_primitives.js new file mode 100644 index 0000000000..462a90c1c5 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/group___finite_field_primitives.js @@ -0,0 +1,23 @@ +var group___finite_field_primitives = +[ + [ "FfElement", "group___finite_field_primitives.html#ga6cff5c7c06b07a87442b810ccc0a86fa", null ], + [ "FiniteField", "group___finite_field_primitives.html#gab281b24e336a8b3d7d90079d862d969e", null ], + [ "DeleteFfElement", "group___finite_field_primitives.html#ga1bad3c6945d1d709fceb07a1dd03000e", null ], + [ "DeleteFiniteField", "group___finite_field_primitives.html#gacbdd2871ecf93dadaac9d2c5b16e1e5f", null ], + [ "FfAdd", "group___finite_field_primitives.html#ga1a6e6d3c2319bb24eae8670b021e223b", null ], + [ "FfExp", "group___finite_field_primitives.html#gaf0ddbc1bad048d67771cba119eb44a6c", null ], + [ "FfGetRandom", "group___finite_field_primitives.html#ga6622db072782fd9e53b4d59dd3dbd8e8", null ], + [ "FfHash", "group___finite_field_primitives.html#ga18a952cebb4a1274c73e6cb0c19e8aea", null ], + [ "FfInv", "group___finite_field_primitives.html#ga26069d035d0f6ade33af2b5d5c14949a", null ], + [ "FfIsEqual", "group___finite_field_primitives.html#gaed2acb8583e9c9f6b49fdb660c672625", null ], + [ "FfIsZero", "group___finite_field_primitives.html#ga20d9140e5670d679ef8183d9b5115f53", null ], + [ "FfMul", "group___finite_field_primitives.html#ga4613a75bd001a974b3e3e494c3a112a5", null ], + [ "FfMultiExp", "group___finite_field_primitives.html#ga84d21decc1c957bcf6e98e1492eb2ac3", null ], + [ "FfNeg", "group___finite_field_primitives.html#gae7a8c7503b6fc7a41bcaab4d45ca37b2", null ], + [ "FfSscmMultiExp", "group___finite_field_primitives.html#ga0d0c31a22bbfb665a16b2d25b0cd2634", null ], + [ "NewFfElement", "group___finite_field_primitives.html#gacc54f315ede2dbeb8c5990c024a0de6c", null ], + [ "NewFiniteField", "group___finite_field_primitives.html#ga7d99fdc5e4573668a5744e49df7ab67c", null ], + [ "NewFiniteFieldViaBinomalExtension", "group___finite_field_primitives.html#ga83041e3be9984a4bd8f1021934bfa3a2", null ], + [ "ReadFfElement", "group___finite_field_primitives.html#ga884d9e1baadf29a410244a735853e3c7", null ], + [ "WriteFfElement", "group___finite_field_primitives.html#ga678694636708463b078d842d5c58a900", null ] +]; \ No newline at end of file diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/group___hash_primitives.html b/sgx-jvm/linux-sgx/external/epid/doc/html/group___hash_primitives.html new file mode 100644 index 0000000000..3125c01dc9 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/group___hash_primitives.html @@ -0,0 +1,142 @@ + + + + + + + +Intel® Enhanced Privacy ID SDK: hash + + + + + + + + + + + + +
+
+ + + + + + +
+ +
+
+ + +
+
+ +
+
+
+ +
+
+ +
+
hash
+
+
+ +

Hash primitives. +More...

+ + + + + +

+Data Structures

struct  Sha256Digest
 SHA256 digest. More...
 
+ + + + +

+Functions

EpidStatus Sha256MessageDigest (void const *msg, size_t len, Sha256Digest *digest)
 Computes SHA256 digest of a message. More...
 
+

Detailed Description

+

Hash primitives.

+

Provides APIs for computing digests of messages.

+

Function Documentation

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
EpidStatus Sha256MessageDigest (void const * msg,
size_t len,
Sha256Digestdigest 
)
+
+ +

Computes SHA256 digest of a message.

+
Parameters
+ + + + +
[in]msgMessage to compute digest for.
[in]lenThe size of msg in bytes.
[out]digestThe resulting message digest.
+
+
+
Returns
EpidStatus
+ +
+
+
+
+ + + + + diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/group___hash_primitives.js b/sgx-jvm/linux-sgx/external/epid/doc/html/group___hash_primitives.js new file mode 100644 index 0000000000..14b92829cf --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/group___hash_primitives.js @@ -0,0 +1,7 @@ +var group___hash_primitives = +[ + [ "Sha256Digest", "struct_sha256_digest.html", [ + [ "data", "struct_sha256_digest.html#a4b6462ddd3f89e4c40220ceb6b1c7f28", null ] + ] ], + [ "Sha256MessageDigest", "group___hash_primitives.html#ga86d62aac9efd7445acee311b41846c6c", null ] +]; \ No newline at end of file diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/group___pairing_primitives.html b/sgx-jvm/linux-sgx/external/epid/doc/html/group___pairing_primitives.html new file mode 100644 index 0000000000..6b31f6182c --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/group___pairing_primitives.html @@ -0,0 +1,249 @@ + + + + + + + +Intel® Enhanced Privacy ID SDK: pairing + + + + + + + + + + + + +
+
+ + + + + + +
+ +
+
+ + +
+
+ +
+
+
+ +
+
+ +
+
pairing
+
+
+ +

Pairing operations. +More...

+ + + + + +

+Typedefs

+typedef struct PairingState PairingState
 A pairing.
 
+ + + + + + + + + + +

+Functions

EpidStatus NewPairingState (EcGroup const *ga, EcGroup const *gb, FiniteField *ff, BigNumStr const *t, bool neg, PairingState **ps)
 Constructs a new Pairing State. More...
 
void DeletePairingState (PairingState **ps)
 Frees a previously allocated by PairingState. More...
 
EpidStatus Pairing (PairingState *ps, FfElement *d, EcPoint const *a, EcPoint const *b)
 Computes an Optimal Ate Pairing for two parameters. More...
 
+

Detailed Description

+

Pairing operations.

+

Provides APIs for defining and using a pairing relationship between two Elliptic Curve Groups.

+

Function Documentation

+ +
+
+ + + + + + + + +
void DeletePairingState (PairingState ** ps)
+
+ +

Frees a previously allocated by PairingState.

+

Frees memory pointed to by pairing state. Nulls the pointer.

+
Parameters
+ + +
[in]psThe Pairing state. Can be NULL.
+
+
+
See also
NewPairingState
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
EpidStatus NewPairingState (EcGroup const * ga,
EcGroup const * gb,
FiniteFieldff,
BigNumStr const * t,
bool neg,
PairingState ** ps 
)
+
+ +

Constructs a new Pairing State.

+

Allocates memory and creates a new Pairing State for Optimal Ate Pairing.

+

Use DeletePairingState() to free memory.

+
Parameters
+ + + + + + + +
[in]gaThe EcGroup from which the first parameter of the pairing is taken.
[in]gbThe EcGroup from which the second parameter of the pairing is taken.
[in]ffThe result finite field. Must be a Fq12 field.
[in]tA positive integer such that 6(t^2) == q - p, where p and q are parameters of G1.
[in]negSelect the alternate "negate" processing path for Optimal Ate Pairing.
[out]psNewly constructed Pairing State.
+
+
+
Returns
EpidStatus
+
See also
DeletePairingState
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
EpidStatus Pairing (PairingStateps,
FfElementd,
EcPoint const * a,
EcPoint const * b 
)
+
+ +

Computes an Optimal Ate Pairing for two parameters.

+
Parameters
+ + + + + +
[in]psThe pairing state.
[out]dThe result of the pairing. Will be in ff used to create the pairing state.
[in]aThe first value to pair. Must be in ga used to create ps.
[in]bThe second value to pair. Must be in gb used to create ps
+
+
+
Returns
EpidStatus
+ +
+
+
+
+ + + + + diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/group___pairing_primitives.js b/sgx-jvm/linux-sgx/external/epid/doc/html/group___pairing_primitives.js new file mode 100644 index 0000000000..4f7612011c --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/group___pairing_primitives.js @@ -0,0 +1,7 @@ +var group___pairing_primitives = +[ + [ "PairingState", "group___pairing_primitives.html#ga3f1fa61d25487f96dfb0ffef4ad35607", null ], + [ "DeletePairingState", "group___pairing_primitives.html#gad54aebdc331d39b73000fdca9e04f94d", null ], + [ "NewPairingState", "group___pairing_primitives.html#ga29f79a645871830754d396b9b4a2a0cc", null ], + [ "Pairing", "group___pairing_primitives.html#ga5dd07d13536e27c37eaeee285297066c", null ] +]; \ No newline at end of file diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/grouppubkey_8c.html b/sgx-jvm/linux-sgx/external/epid/doc/html/grouppubkey_8c.html new file mode 100644 index 0000000000..009cf4253e --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/grouppubkey_8c.html @@ -0,0 +1,96 @@ + + + + + + + +Intel® Enhanced Privacy ID SDK: epid/common/grouppubkey.c File Reference + + + + + + + + + + + + +
+
+ + + + + + +
+ +
+
+ + +
+
+ +
+
+
+ +
+
+ +
+
grouppubkey.c File Reference
+
+
+ +

Group public key implementation. +More...

+ + + + + + + + +

+Functions

EpidStatus CreateGroupPubKey (GroupPubKey const *pub_key_str, EcGroup *G1, EcGroup *G2, GroupPubKey_ **pub_key)
 Constructs internal representation of GroupPubKey. More...
 
void DeleteGroupPubKey (GroupPubKey_ **pub_key)
 Deallocates storage for internal representation of GroupPubKey. More...
 
+

Detailed Description

+

Group public key implementation.

+
+
+ + + + + diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/grouppubkey_8h.html b/sgx-jvm/linux-sgx/external/epid/doc/html/grouppubkey_8h.html new file mode 100644 index 0000000000..a179e826a0 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/grouppubkey_8h.html @@ -0,0 +1,104 @@ + + + + + + + +Intel® Enhanced Privacy ID SDK: epid/common/grouppubkey.h File Reference + + + + + + + + + + + + +
+
+ + + + + + +
+ +
+
+ + +
+
+ +
+
+
+ +
+
+ +
+
grouppubkey.h File Reference
+
+
+ +

Group public key interface. +More...

+ + + + + +

+Data Structures

struct  GroupPubKey_
 Internal representation of GroupPubKey. More...
 
+ + + + + + + +

+Functions

EpidStatus CreateGroupPubKey (GroupPubKey const *pub_key_str, EcGroup *G1, EcGroup *G2, GroupPubKey_ **pub_key)
 Constructs internal representation of GroupPubKey. More...
 
void DeleteGroupPubKey (GroupPubKey_ **pub_key)
 Deallocates storage for internal representation of GroupPubKey. More...
 
+

Detailed Description

+

Group public key interface.

+
+
+ + + + + diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/hash_8h.html b/sgx-jvm/linux-sgx/external/epid/doc/html/hash_8h.html new file mode 100644 index 0000000000..fb3b6f669a --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/hash_8h.html @@ -0,0 +1,102 @@ + + + + + + + +Intel® Enhanced Privacy ID SDK: epid/common/math/hash.h File Reference + + + + + + + + + + + + +
+
+ + + + + + +
+ +
+
+ + +
+
+ +
+
+
+ +
+
+ +
+
hash.h File Reference
+
+
+ +

Hash primitives. +More...

+
#include <stddef.h>
+#include <stdint.h>
+#include <limits.h>
+#include "epid/common/errors.h"
+
+ + + + +

+Data Structures

struct  Sha256Digest
 SHA256 digest. More...
 
+ + + + +

+Functions

EpidStatus Sha256MessageDigest (void const *msg, size_t len, Sha256Digest *digest)
 Computes SHA256 digest of a message. More...
 
+

Detailed Description

+

Hash primitives.

+
+
+ + + + + diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/implementation__notes_8dox.html b/sgx-jvm/linux-sgx/external/epid/doc/html/implementation__notes_8dox.html new file mode 100644 index 0000000000..be407ab5bb --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/implementation__notes_8dox.html @@ -0,0 +1,82 @@ + + + + + + + +Intel® Enhanced Privacy ID SDK: doc/docsrc/implementation_notes.dox File Reference + + + + + + + + + + + + +
+
+ + + + + + +
+ +
+
+ + +
+
+ +
+
+
+ +
+
+
+
doc/docsrc/implementation_notes.dox File Reference
+
+
+ +

This file is used by Doxygen to generate documentation. +More...

+

Detailed Description

+

This file is used by Doxygen to generate documentation.

+
+
+ + + + + diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/index.html b/sgx-jvm/linux-sgx/external/epid/doc/html/index.html new file mode 100644 index 0000000000..3a81885cd2 --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/index.html @@ -0,0 +1,78 @@ + + + + + + + +Intel® Enhanced Privacy ID SDK: Introducing the Intel® EPID SDK + + + + + + + + + + + + +
+
+ + + + + + +
+ +
+
+ + +
+
+ +
+
+
+ +
+
+
+
Introducing the Intel® EPID SDK
+
+
+

Intel® EPID is a cryptographic protocol which enables the remote authentication of a trusted platform whilst preserving the user's privacy.

+

The Intel® EPID Software Development Kit provides an implementation of the Intel® EPID specification that developers can use when developing their own applications using Intel® EPID technology.

+
+
+ + + + + diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/issuer__material_8dox.html b/sgx-jvm/linux-sgx/external/epid/doc/html/issuer__material_8dox.html new file mode 100644 index 0000000000..b8c991864e --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/issuer__material_8dox.html @@ -0,0 +1,82 @@ + + + + + + + +Intel® Enhanced Privacy ID SDK: doc/docsrc/issuer_material.dox File Reference + + + + + + + + + + + + +
+
+ + + + + + +
+ +
+
+ + +
+
+ +
+
+
+ +
+
+
+
doc/docsrc/issuer_material.dox File Reference
+
+
+ +

This file is used by Doxygen to generate documentation. +More...

+

Detailed Description

+

This file is used by Doxygen to generate documentation.

+
+
+ + + + + diff --git a/sgx-jvm/linux-sgx/external/epid/doc/html/jquery.js b/sgx-jvm/linux-sgx/external/epid/doc/html/jquery.js new file mode 100644 index 0000000000..1f4d0b47ce --- /dev/null +++ b/sgx-jvm/linux-sgx/external/epid/doc/html/jquery.js @@ -0,0 +1,68 @@ +/*! + * jQuery JavaScript Library v1.7.1 + * http://jquery.com/ + * + * Copyright 2011, John Resig + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * Includes Sizzle.js + * http://sizzlejs.com/ + * Copyright 2011, The Dojo Foundation + * Released under the MIT, BSD, and GPL Licenses. + * + * Date: Mon Nov 21 21:11:03 2011 -0500 + */ +(function(bb,L){var av=bb.document,bu=bb.navigator,bl=bb.location;var b=(function(){var bF=function(b0,b1){return new bF.fn.init(b0,b1,bD)},bU=bb.jQuery,bH=bb.$,bD,bY=/^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,bM=/\S/,bI=/^\s+/,bE=/\s+$/,bA=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,bN=/^[\],:{}\s]*$/,bW=/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,bP=/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,bJ=/(?:^|:|,)(?:\s*\[)+/g,by=/(webkit)[ \/]([\w.]+)/,bR=/(opera)(?:.*version)?[ \/]([\w.]+)/,bQ=/(msie) ([\w.]+)/,bS=/(mozilla)(?:.*? rv:([\w.]+))?/,bB=/-([a-z]|[0-9])/ig,bZ=/^-ms-/,bT=function(b0,b1){return(b1+"").toUpperCase()},bX=bu.userAgent,bV,bC,e,bL=Object.prototype.toString,bG=Object.prototype.hasOwnProperty,bz=Array.prototype.push,bK=Array.prototype.slice,bO=String.prototype.trim,bv=Array.prototype.indexOf,bx={};bF.fn=bF.prototype={constructor:bF,init:function(b0,b4,b3){var b2,b5,b1,b6;if(!b0){return this}if(b0.nodeType){this.context=this[0]=b0;this.length=1;return this}if(b0==="body"&&!b4&&av.body){this.context=av;this[0]=av.body;this.selector=b0;this.length=1;return this}if(typeof b0==="string"){if(b0.charAt(0)==="<"&&b0.charAt(b0.length-1)===">"&&b0.length>=3){b2=[null,b0,null]}else{b2=bY.exec(b0)}if(b2&&(b2[1]||!b4)){if(b2[1]){b4=b4 instanceof bF?b4[0]:b4;b6=(b4?b4.ownerDocument||b4:av);b1=bA.exec(b0);if(b1){if(bF.isPlainObject(b4)){b0=[av.createElement(b1[1])];bF.fn.attr.call(b0,b4,true)}else{b0=[b6.createElement(b1[1])]}}else{b1=bF.buildFragment([b2[1]],[b6]);b0=(b1.cacheable?bF.clone(b1.fragment):b1.fragment).childNodes}return bF.merge(this,b0)}else{b5=av.getElementById(b2[2]);if(b5&&b5.parentNode){if(b5.id!==b2[2]){return b3.find(b0)}this.length=1;this[0]=b5}this.context=av;this.selector=b0;return this}}else{if(!b4||b4.jquery){return(b4||b3).find(b0)}else{return this.constructor(b4).find(b0)}}}else{if(bF.isFunction(b0)){return b3.ready(b0)}}if(b0.selector!==L){this.selector=b0.selector;this.context=b0.context}return bF.makeArray(b0,this)},selector:"",jquery:"1.7.1",length:0,size:function(){return this.length},toArray:function(){return bK.call(this,0)},get:function(b0){return b0==null?this.toArray():(b0<0?this[this.length+b0]:this[b0])},pushStack:function(b1,b3,b0){var b2=this.constructor();if(bF.isArray(b1)){bz.apply(b2,b1)}else{bF.merge(b2,b1)}b2.prevObject=this;b2.context=this.context;if(b3==="find"){b2.selector=this.selector+(this.selector?" ":"")+b0}else{if(b3){b2.selector=this.selector+"."+b3+"("+b0+")"}}return b2},each:function(b1,b0){return bF.each(this,b1,b0)},ready:function(b0){bF.bindReady();bC.add(b0);return this},eq:function(b0){b0=+b0;return b0===-1?this.slice(b0):this.slice(b0,b0+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(bK.apply(this,arguments),"slice",bK.call(arguments).join(","))},map:function(b0){return this.pushStack(bF.map(this,function(b2,b1){return b0.call(b2,b1,b2)}))},end:function(){return this.prevObject||this.constructor(null)},push:bz,sort:[].sort,splice:[].splice};bF.fn.init.prototype=bF.fn;bF.extend=bF.fn.extend=function(){var b9,b2,b0,b1,b6,b7,b5=arguments[0]||{},b4=1,b3=arguments.length,b8=false;if(typeof b5==="boolean"){b8=b5;b5=arguments[1]||{};b4=2}if(typeof b5!=="object"&&!bF.isFunction(b5)){b5={}}if(b3===b4){b5=this;--b4}for(;b40){return}bC.fireWith(av,[bF]);if(bF.fn.trigger){bF(av).trigger("ready").off("ready")}}},bindReady:function(){if(bC){return}bC=bF.Callbacks("once memory");if(av.readyState==="complete"){return setTimeout(bF.ready,1)}if(av.addEventListener){av.addEventListener("DOMContentLoaded",e,false);bb.addEventListener("load",bF.ready,false)}else{if(av.attachEvent){av.attachEvent("onreadystatechange",e);bb.attachEvent("onload",bF.ready);var b0=false;try{b0=bb.frameElement==null}catch(b1){}if(av.documentElement.doScroll&&b0){bw()}}}},isFunction:function(b0){return bF.type(b0)==="function"},isArray:Array.isArray||function(b0){return bF.type(b0)==="array"},isWindow:function(b0){return b0&&typeof b0==="object"&&"setInterval" in b0},isNumeric:function(b0){return !isNaN(parseFloat(b0))&&isFinite(b0)},type:function(b0){return b0==null?String(b0):bx[bL.call(b0)]||"object"},isPlainObject:function(b2){if(!b2||bF.type(b2)!=="object"||b2.nodeType||bF.isWindow(b2)){return false}try{if(b2.constructor&&!bG.call(b2,"constructor")&&!bG.call(b2.constructor.prototype,"isPrototypeOf")){return false}}catch(b1){return false}var b0;for(b0 in b2){}return b0===L||bG.call(b2,b0)},isEmptyObject:function(b1){for(var b0 in b1){return false}return true},error:function(b0){throw new Error(b0)},parseJSON:function(b0){if(typeof b0!=="string"||!b0){return null}b0=bF.trim(b0);if(bb.JSON&&bb.JSON.parse){return bb.JSON.parse(b0)}if(bN.test(b0.replace(bW,"@").replace(bP,"]").replace(bJ,""))){return(new Function("return "+b0))()}bF.error("Invalid JSON: "+b0)},parseXML:function(b2){var b0,b1;try{if(bb.DOMParser){b1=new DOMParser();b0=b1.parseFromString(b2,"text/xml")}else{b0=new ActiveXObject("Microsoft.XMLDOM");b0.async="false";b0.loadXML(b2)}}catch(b3){b0=L}if(!b0||!b0.documentElement||b0.getElementsByTagName("parsererror").length){bF.error("Invalid XML: "+b2)}return b0},noop:function(){},globalEval:function(b0){if(b0&&bM.test(b0)){(bb.execScript||function(b1){bb["eval"].call(bb,b1)})(b0)}},camelCase:function(b0){return b0.replace(bZ,"ms-").replace(bB,bT)},nodeName:function(b1,b0){return b1.nodeName&&b1.nodeName.toUpperCase()===b0.toUpperCase()},each:function(b3,b6,b2){var b1,b4=0,b5=b3.length,b0=b5===L||bF.isFunction(b3);if(b2){if(b0){for(b1 in b3){if(b6.apply(b3[b1],b2)===false){break}}}else{for(;b40&&b0[0]&&b0[b1-1])||b1===0||bF.isArray(b0));if(b3){for(;b21?aJ.call(arguments,0):bG;if(!(--bw)){bC.resolveWith(bC,bx)}}}function bz(bF){return function(bG){bB[bF]=arguments.length>1?aJ.call(arguments,0):bG;bC.notifyWith(bE,bB)}}if(e>1){for(;bv
a";bI=bv.getElementsByTagName("*");bF=bv.getElementsByTagName("a")[0];if(!bI||!bI.length||!bF){return{}}bG=av.createElement("select");bx=bG.appendChild(av.createElement("option"));bE=bv.getElementsByTagName("input")[0];bJ={leadingWhitespace:(bv.firstChild.nodeType===3),tbody:!bv.getElementsByTagName("tbody").length,htmlSerialize:!!bv.getElementsByTagName("link").length,style:/top/.test(bF.getAttribute("style")),hrefNormalized:(bF.getAttribute("href")==="/a"),opacity:/^0.55/.test(bF.style.opacity),cssFloat:!!bF.style.cssFloat,checkOn:(bE.value==="on"),optSelected:bx.selected,getSetAttribute:bv.className!=="t",enctype:!!av.createElement("form").enctype,html5Clone:av.createElement("nav").cloneNode(true).outerHTML!=="<:nav>",submitBubbles:true,changeBubbles:true,focusinBubbles:false,deleteExpando:true,noCloneEvent:true,inlineBlockNeedsLayout:false,shrinkWrapBlocks:false,reliableMarginRight:true};bE.checked=true;bJ.noCloneChecked=bE.cloneNode(true).checked;bG.disabled=true;bJ.optDisabled=!bx.disabled;try{delete bv.test}catch(bC){bJ.deleteExpando=false}if(!bv.addEventListener&&bv.attachEvent&&bv.fireEvent){bv.attachEvent("onclick",function(){bJ.noCloneEvent=false});bv.cloneNode(true).fireEvent("onclick")}bE=av.createElement("input");bE.value="t";bE.setAttribute("type","radio");bJ.radioValue=bE.value==="t";bE.setAttribute("checked","checked");bv.appendChild(bE);bD=av.createDocumentFragment();bD.appendChild(bv.lastChild);bJ.checkClone=bD.cloneNode(true).cloneNode(true).lastChild.checked;bJ.appendChecked=bE.checked;bD.removeChild(bE);bD.appendChild(bv);bv.innerHTML="";if(bb.getComputedStyle){bA=av.createElement("div");bA.style.width="0";bA.style.marginRight="0";bv.style.width="2px";bv.appendChild(bA);bJ.reliableMarginRight=(parseInt((bb.getComputedStyle(bA,null)||{marginRight:0}).marginRight,10)||0)===0}if(bv.attachEvent){for(by in {submit:1,change:1,focusin:1}){bB="on"+by;bw=(bB in bv);if(!bw){bv.setAttribute(bB,"return;");bw=(typeof bv[bB]==="function")}bJ[by+"Bubbles"]=bw}}bD.removeChild(bv);bD=bG=bx=bA=bv=bE=null;b(function(){var bM,bU,bV,bT,bN,bO,bL,bS,bR,e,bP,bQ=av.getElementsByTagName("body")[0];if(!bQ){return}bL=1;bS="position:absolute;top:0;left:0;width:1px;height:1px;margin:0;";bR="visibility:hidden;border:0;";e="style='"+bS+"border:5px solid #000;padding:0;'";bP="
";bM=av.createElement("div");bM.style.cssText=bR+"width:0;height:0;position:static;top:0;margin-top:"+bL+"px";bQ.insertBefore(bM,bQ.firstChild);bv=av.createElement("div");bM.appendChild(bv);bv.innerHTML="
t
";bz=bv.getElementsByTagName("td");bw=(bz[0].offsetHeight===0);bz[0].style.display="";bz[1].style.display="none";bJ.reliableHiddenOffsets=bw&&(bz[0].offsetHeight===0);bv.innerHTML="";bv.style.width=bv.style.paddingLeft="1px";b.boxModel=bJ.boxModel=bv.offsetWidth===2;if(typeof bv.style.zoom!=="undefined"){bv.style.display="inline";bv.style.zoom=1;bJ.inlineBlockNeedsLayout=(bv.offsetWidth===2);bv.style.display="";bv.innerHTML="
";bJ.shrinkWrapBlocks=(bv.offsetWidth!==2)}bv.style.cssText=bS+bR;bv.innerHTML=bP;bU=bv.firstChild;bV=bU.firstChild;bN=bU.nextSibling.firstChild.firstChild;bO={doesNotAddBorder:(bV.offsetTop!==5),doesAddBorderForTableAndCells:(bN.offsetTop===5)};bV.style.position="fixed";bV.style.top="20px";bO.fixedPosition=(bV.offsetTop===20||bV.offsetTop===15);bV.style.position=bV.style.top="";bU.style.overflow="hidden";bU.style.position="relative";bO.subtractsBorderForOverflowNotVisible=(bV.offsetTop===-5);bO.doesNotIncludeMarginInBodyOffset=(bQ.offsetTop!==bL);bQ.removeChild(bM);bv=bM=null;b.extend(bJ,bO)});return bJ})();var aS=/^(?:\{.*\}|\[.*\])$/,aA=/([A-Z])/g;b.extend({cache:{},uuid:0,expando:"jQuery"+(b.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:true,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:true},hasData:function(e){e=e.nodeType?b.cache[e[b.expando]]:e[b.expando];return !!e&&!S(e)},data:function(bx,bv,bz,by){if(!b.acceptData(bx)){return}var bG,bA,bD,bE=b.expando,bC=typeof bv==="string",bF=bx.nodeType,e=bF?b.cache:bx,bw=bF?bx[bE]:bx[bE]&&bE,bB=bv==="events";if((!bw||!e[bw]||(!bB&&!by&&!e[bw].data))&&bC&&bz===L){return}if(!bw){if(bF){bx[bE]=bw=++b.uuid}else{bw=bE}}if(!e[bw]){e[bw]={};if(!bF){e[bw].toJSON=b.noop}}if(typeof bv==="object"||typeof bv==="function"){if(by){e[bw]=b.extend(e[bw],bv)}else{e[bw].data=b.extend(e[bw].data,bv)}}bG=bA=e[bw];if(!by){if(!bA.data){bA.data={}}bA=bA.data}if(bz!==L){bA[b.camelCase(bv)]=bz}if(bB&&!bA[bv]){return bG.events}if(bC){bD=bA[bv];if(bD==null){bD=bA[b.camelCase(bv)]}}else{bD=bA}return bD},removeData:function(bx,bv,by){if(!b.acceptData(bx)){return}var bB,bA,bz,bC=b.expando,bD=bx.nodeType,e=bD?b.cache:bx,bw=bD?bx[bC]:bC;if(!e[bw]){return}if(bv){bB=by?e[bw]:e[bw].data;if(bB){if(!b.isArray(bv)){if(bv in bB){bv=[bv]}else{bv=b.camelCase(bv);if(bv in bB){bv=[bv]}else{bv=bv.split(" ")}}}for(bA=0,bz=bv.length;bA-1){return true}}return false},val:function(bx){var e,bv,by,bw=this[0];if(!arguments.length){if(bw){e=b.valHooks[bw.nodeName.toLowerCase()]||b.valHooks[bw.type];if(e&&"get" in e&&(bv=e.get(bw,"value"))!==L){return bv}bv=bw.value;return typeof bv==="string"?bv.replace(aU,""):bv==null?"":bv}return}by=b.isFunction(bx);return this.each(function(bA){var bz=b(this),bB;if(this.nodeType!==1){return}if(by){bB=bx.call(this,bA,bz.val())}else{bB=bx}if(bB==null){bB=""}else{if(typeof bB==="number"){bB+=""}else{if(b.isArray(bB)){bB=b.map(bB,function(bC){return bC==null?"":bC+""})}}}e=b.valHooks[this.nodeName.toLowerCase()]||b.valHooks[this.type];if(!e||!("set" in e)||e.set(this,bB,"value")===L){this.value=bB}})}});b.extend({valHooks:{option:{get:function(e){var bv=e.attributes.value;return !bv||bv.specified?e.value:e.text}},select:{get:function(e){var bA,bv,bz,bx,by=e.selectedIndex,bB=[],bC=e.options,bw=e.type==="select-one";if(by<0){return null}bv=bw?by:0;bz=bw?by+1:bC.length;for(;bv=0});if(!e.length){bv.selectedIndex=-1}return e}}},attrFn:{val:true,css:true,html:true,text:true,data:true,width:true,height:true,offset:true},attr:function(bA,bx,bB,bz){var bw,e,by,bv=bA.nodeType;if(!bA||bv===3||bv===8||bv===2){return}if(bz&&bx in b.attrFn){return b(bA)[bx](bB)}if(typeof bA.getAttribute==="undefined"){return b.prop(bA,bx,bB)}by=bv!==1||!b.isXMLDoc(bA);if(by){bx=bx.toLowerCase();e=b.attrHooks[bx]||(ao.test(bx)?aY:be)}if(bB!==L){if(bB===null){b.removeAttr(bA,bx);return}else{if(e&&"set" in e&&by&&(bw=e.set(bA,bB,bx))!==L){return bw}else{bA.setAttribute(bx,""+bB);return bB}}}else{if(e&&"get" in e&&by&&(bw=e.get(bA,bx))!==null){return bw}else{bw=bA.getAttribute(bx);return bw===null?L:bw}}},removeAttr:function(bx,bz){var by,bA,bv,e,bw=0;if(bz&&bx.nodeType===1){bA=bz.toLowerCase().split(af);e=bA.length;for(;bw=0)}}})});var bd=/^(?:textarea|input|select)$/i,n=/^([^\.]*)?(?:\.(.+))?$/,J=/\bhover(\.\S+)?\b/,aO=/^key/,bf=/^(?:mouse|contextmenu)|click/,T=/^(?:focusinfocus|focusoutblur)$/,U=/^(\w*)(?:#([\w\-]+))?(?:\.([\w\-]+))?$/,Y=function(e){var bv=U.exec(e);if(bv){bv[1]=(bv[1]||"").toLowerCase();bv[3]=bv[3]&&new RegExp("(?:^|\\s)"+bv[3]+"(?:\\s|$)")}return bv},j=function(bw,e){var bv=bw.attributes||{};return((!e[1]||bw.nodeName.toLowerCase()===e[1])&&(!e[2]||(bv.id||{}).value===e[2])&&(!e[3]||e[3].test((bv["class"]||{}).value)))},bt=function(e){return b.event.special.hover?e:e.replace(J,"mouseenter$1 mouseleave$1")};b.event={add:function(bx,bC,bJ,bA,by){var bD,bB,bK,bI,bH,bF,e,bG,bv,bz,bw,bE;if(bx.nodeType===3||bx.nodeType===8||!bC||!bJ||!(bD=b._data(bx))){return}if(bJ.handler){bv=bJ;bJ=bv.handler}if(!bJ.guid){bJ.guid=b.guid++}bK=bD.events;if(!bK){bD.events=bK={}}bB=bD.handle;if(!bB){bD.handle=bB=function(bL){return typeof b!=="undefined"&&(!bL||b.event.triggered!==bL.type)?b.event.dispatch.apply(bB.elem,arguments):L};bB.elem=bx}bC=b.trim(bt(bC)).split(" ");for(bI=0;bI=0){bG=bG.slice(0,-1);bw=true}if(bG.indexOf(".")>=0){bx=bG.split(".");bG=bx.shift();bx.sort()}if((!bA||b.event.customEvent[bG])&&!b.event.global[bG]){return}bv=typeof bv==="object"?bv[b.expando]?bv:new b.Event(bG,bv):new b.Event(bG);bv.type=bG;bv.isTrigger=true;bv.exclusive=bw;bv.namespace=bx.join(".");bv.namespace_re=bv.namespace?new RegExp("(^|\\.)"+bx.join("\\.(?:.*\\.)?")+"(\\.|$)"):null;by=bG.indexOf(":")<0?"on"+bG:"";if(!bA){e=b.cache;for(bC in e){if(e[bC].events&&e[bC].events[bG]){b.event.trigger(bv,bD,e[bC].handle.elem,true)}}return}bv.result=L;if(!bv.target){bv.target=bA}bD=bD!=null?b.makeArray(bD):[];bD.unshift(bv);bF=b.event.special[bG]||{};if(bF.trigger&&bF.trigger.apply(bA,bD)===false){return}bB=[[bA,bF.bindType||bG]];if(!bJ&&!bF.noBubble&&!b.isWindow(bA)){bI=bF.delegateType||bG;bH=T.test(bI+bG)?bA:bA.parentNode;bz=null;for(;bH;bH=bH.parentNode){bB.push([bH,bI]);bz=bH}if(bz&&bz===bA.ownerDocument){bB.push([bz.defaultView||bz.parentWindow||bb,bI])}}for(bC=0;bCbA){bH.push({elem:this,matches:bz.slice(bA)})}for(bC=0;bC0?this.on(e,null,bx,bw):this.trigger(e)};if(b.attrFn){b.attrFn[e]=true}if(aO.test(e)){b.event.fixHooks[e]=b.event.keyHooks}if(bf.test(e)){b.event.fixHooks[e]=b.event.mouseHooks}}); +/*! + * Sizzle CSS Selector Engine + * Copyright 2011, The Dojo Foundation + * Released under the MIT, BSD, and GPL Licenses. + * More information: http://sizzlejs.com/ + */ +(function(){var bH=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,bC="sizcache"+(Math.random()+"").replace(".",""),bI=0,bL=Object.prototype.toString,bB=false,bA=true,bK=/\\/g,bO=/\r\n/g,bQ=/\W/;[0,0].sort(function(){bA=false;return 0});var by=function(bV,e,bY,bZ){bY=bY||[];e=e||av;var b1=e;if(e.nodeType!==1&&e.nodeType!==9){return[]}if(!bV||typeof bV!=="string"){return bY}var bS,b3,b6,bR,b2,b5,b4,bX,bU=true,bT=by.isXML(e),bW=[],b0=bV;do{bH.exec("");bS=bH.exec(b0);if(bS){b0=bS[3];bW.push(bS[1]);if(bS[2]){bR=bS[3];break}}}while(bS);if(bW.length>1&&bD.exec(bV)){if(bW.length===2&&bE.relative[bW[0]]){b3=bM(bW[0]+bW[1],e,bZ)}else{b3=bE.relative[bW[0]]?[e]:by(bW.shift(),e);while(bW.length){bV=bW.shift();if(bE.relative[bV]){bV+=bW.shift()}b3=bM(bV,b3,bZ)}}}else{if(!bZ&&bW.length>1&&e.nodeType===9&&!bT&&bE.match.ID.test(bW[0])&&!bE.match.ID.test(bW[bW.length-1])){b2=by.find(bW.shift(),e,bT);e=b2.expr?by.filter(b2.expr,b2.set)[0]:b2.set[0]}if(e){b2=bZ?{expr:bW.pop(),set:bF(bZ)}:by.find(bW.pop(),bW.length===1&&(bW[0]==="~"||bW[0]==="+")&&e.parentNode?e.parentNode:e,bT);b3=b2.expr?by.filter(b2.expr,b2.set):b2.set;if(bW.length>0){b6=bF(b3)}else{bU=false}while(bW.length){b5=bW.pop();b4=b5;if(!bE.relative[b5]){b5=""}else{b4=bW.pop()}if(b4==null){b4=e}bE.relative[b5](b6,b4,bT)}}else{b6=bW=[]}}if(!b6){b6=b3}if(!b6){by.error(b5||bV)}if(bL.call(b6)==="[object Array]"){if(!bU){bY.push.apply(bY,b6)}else{if(e&&e.nodeType===1){for(bX=0;b6[bX]!=null;bX++){if(b6[bX]&&(b6[bX]===true||b6[bX].nodeType===1&&by.contains(e,b6[bX]))){bY.push(b3[bX])}}}else{for(bX=0;b6[bX]!=null;bX++){if(b6[bX]&&b6[bX].nodeType===1){bY.push(b3[bX])}}}}}else{bF(b6,bY)}if(bR){by(bR,b1,bY,bZ);by.uniqueSort(bY)}return bY};by.uniqueSort=function(bR){if(bJ){bB=bA;bR.sort(bJ);if(bB){for(var e=1;e0};by.find=function(bX,e,bY){var bW,bS,bU,bT,bV,bR;if(!bX){return[]}for(bS=0,bU=bE.order.length;bS":function(bW,bR){var bV,bU=typeof bR==="string",bS=0,e=bW.length;if(bU&&!bQ.test(bR)){bR=bR.toLowerCase();for(;bS=0)){if(!bS){e.push(bV)}}else{if(bS){bR[bU]=false}}}}return false},ID:function(e){return e[1].replace(bK,"")},TAG:function(bR,e){return bR[1].replace(bK,"").toLowerCase()},CHILD:function(e){if(e[1]==="nth"){if(!e[2]){by.error(e[0])}e[2]=e[2].replace(/^\+|\s*/g,"");var bR=/(-?)(\d*)(?:n([+\-]?\d*))?/.exec(e[2]==="even"&&"2n"||e[2]==="odd"&&"2n+1"||!/\D/.test(e[2])&&"0n+"+e[2]||e[2]);e[2]=(bR[1]+(bR[2]||1))-0;e[3]=bR[3]-0}else{if(e[2]){by.error(e[0])}}e[0]=bI++;return e},ATTR:function(bU,bR,bS,e,bV,bW){var bT=bU[1]=bU[1].replace(bK,"");if(!bW&&bE.attrMap[bT]){bU[1]=bE.attrMap[bT]}bU[4]=(bU[4]||bU[5]||"").replace(bK,"");if(bU[2]==="~="){bU[4]=" "+bU[4]+" "}return bU},PSEUDO:function(bU,bR,bS,e,bV){if(bU[1]==="not"){if((bH.exec(bU[3])||"").length>1||/^\w/.test(bU[3])){bU[3]=by(bU[3],null,null,bR)}else{var bT=by.filter(bU[3],bR,bS,true^bV);if(!bS){e.push.apply(e,bT)}return false}}else{if(bE.match.POS.test(bU[0])||bE.match.CHILD.test(bU[0])){return true}}return bU},POS:function(e){e.unshift(true);return e}},filters:{enabled:function(e){return e.disabled===false&&e.type!=="hidden"},disabled:function(e){return e.disabled===true},checked:function(e){return e.checked===true},selected:function(e){if(e.parentNode){e.parentNode.selectedIndex}return e.selected===true},parent:function(e){return !!e.firstChild},empty:function(e){return !e.firstChild},has:function(bS,bR,e){return !!by(e[3],bS).length},header:function(e){return(/h\d/i).test(e.nodeName)},text:function(bS){var e=bS.getAttribute("type"),bR=bS.type;return bS.nodeName.toLowerCase()==="input"&&"text"===bR&&(e===bR||e===null)},radio:function(e){return e.nodeName.toLowerCase()==="input"&&"radio"===e.type},checkbox:function(e){return e.nodeName.toLowerCase()==="input"&&"checkbox"===e.type},file:function(e){return e.nodeName.toLowerCase()==="input"&&"file"===e.type},password:function(e){return e.nodeName.toLowerCase()==="input"&&"password"===e.type},submit:function(bR){var e=bR.nodeName.toLowerCase();return(e==="input"||e==="button")&&"submit"===bR.type},image:function(e){return e.nodeName.toLowerCase()==="input"&&"image"===e.type},reset:function(bR){var e=bR.nodeName.toLowerCase();return(e==="input"||e==="button")&&"reset"===bR.type},button:function(bR){var e=bR.nodeName.toLowerCase();return e==="input"&&"button"===bR.type||e==="button"},input:function(e){return(/input|select|textarea|button/i).test(e.nodeName)},focus:function(e){return e===e.ownerDocument.activeElement}},setFilters:{first:function(bR,e){return e===0},last:function(bS,bR,e,bT){return bR===bT.length-1},even:function(bR,e){return e%2===0},odd:function(bR,e){return e%2===1},lt:function(bS,bR,e){return bRe[3]-0},nth:function(bS,bR,e){return e[3]-0===bR},eq:function(bS,bR,e){return e[3]-0===bR}},filter:{PSEUDO:function(bS,bX,bW,bY){var e=bX[1],bR=bE.filters[e];if(bR){return bR(bS,bW,bX,bY)}else{if(e==="contains"){return(bS.textContent||bS.innerText||bw([bS])||"").indexOf(bX[3])>=0}else{if(e==="not"){var bT=bX[3];for(var bV=0,bU=bT.length;bV=0)}}},ID:function(bR,e){return bR.nodeType===1&&bR.getAttribute("id")===e},TAG:function(bR,e){return(e==="*"&&bR.nodeType===1)||!!bR.nodeName&&bR.nodeName.toLowerCase()===e},CLASS:function(bR,e){return(" "+(bR.className||bR.getAttribute("class"))+" ").indexOf(e)>-1},ATTR:function(bV,bT){var bS=bT[1],e=by.attr?by.attr(bV,bS):bE.attrHandle[bS]?bE.attrHandle[bS](bV):bV[bS]!=null?bV[bS]:bV.getAttribute(bS),bW=e+"",bU=bT[2],bR=bT[4];return e==null?bU==="!=":!bU&&by.attr?e!=null:bU==="="?bW===bR:bU==="*="?bW.indexOf(bR)>=0:bU==="~="?(" "+bW+" ").indexOf(bR)>=0:!bR?bW&&e!==false:bU==="!="?bW!==bR:bU==="^="?bW.indexOf(bR)===0:bU==="$="?bW.substr(bW.length-bR.length)===bR:bU==="|="?bW===bR||bW.substr(0,bR.length+1)===bR+"-":false},POS:function(bU,bR,bS,bV){var e=bR[2],bT=bE.setFilters[e];if(bT){return bT(bU,bS,bR,bV)}}}};var bD=bE.match.POS,bx=function(bR,e){return"\\"+(e-0+1)};for(var bz in bE.match){bE.match[bz]=new RegExp(bE.match[bz].source+(/(?![^\[]*\])(?![^\(]*\))/.source));bE.leftMatch[bz]=new RegExp(/(^(?:.|\r|\n)*?)/.source+bE.match[bz].source.replace(/\\(\d+)/g,bx))}var bF=function(bR,e){bR=Array.prototype.slice.call(bR,0);if(e){e.push.apply(e,bR);return e}return bR};try{Array.prototype.slice.call(av.documentElement.childNodes,0)[0].nodeType}catch(bP){bF=function(bU,bT){var bS=0,bR=bT||[];if(bL.call(bU)==="[object Array]"){Array.prototype.push.apply(bR,bU)}else{if(typeof bU.length==="number"){for(var e=bU.length;bS";e.insertBefore(bR,e.firstChild);if(av.getElementById(bS)){bE.find.ID=function(bU,bV,bW){if(typeof bV.getElementById!=="undefined"&&!bW){var bT=bV.getElementById(bU[1]);return bT?bT.id===bU[1]||typeof bT.getAttributeNode!=="undefined"&&bT.getAttributeNode("id").nodeValue===bU[1]?[bT]:L:[]}};bE.filter.ID=function(bV,bT){var bU=typeof bV.getAttributeNode!=="undefined"&&bV.getAttributeNode("id");return bV.nodeType===1&&bU&&bU.nodeValue===bT}}e.removeChild(bR);e=bR=null})();(function(){var e=av.createElement("div");e.appendChild(av.createComment(""));if(e.getElementsByTagName("*").length>0){bE.find.TAG=function(bR,bV){var bU=bV.getElementsByTagName(bR[1]);if(bR[1]==="*"){var bT=[];for(var bS=0;bU[bS];bS++){if(bU[bS].nodeType===1){bT.push(bU[bS])}}bU=bT}return bU}}e.innerHTML="";if(e.firstChild&&typeof e.firstChild.getAttribute!=="undefined"&&e.firstChild.getAttribute("href")!=="#"){bE.attrHandle.href=function(bR){return bR.getAttribute("href",2)}}e=null})();if(av.querySelectorAll){(function(){var e=by,bT=av.createElement("div"),bS="__sizzle__";bT.innerHTML="

";if(bT.querySelectorAll&&bT.querySelectorAll(".TEST").length===0){return}by=function(b4,bV,bZ,b3){bV=bV||av;if(!b3&&!by.isXML(bV)){var b2=/^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec(b4);if(b2&&(bV.nodeType===1||bV.nodeType===9)){if(b2[1]){return bF(bV.getElementsByTagName(b4),bZ)}else{if(b2[2]&&bE.find.CLASS&&bV.getElementsByClassName){return bF(bV.getElementsByClassName(b2[2]),bZ)}}}if(bV.nodeType===9){if(b4==="body"&&bV.body){return bF([bV.body],bZ)}else{if(b2&&b2[3]){var bY=bV.getElementById(b2[3]);if(bY&&bY.parentNode){if(bY.id===b2[3]){return bF([bY],bZ)}}else{return bF([],bZ)}}}try{return bF(bV.querySelectorAll(b4),bZ)}catch(b0){}}else{if(bV.nodeType===1&&bV.nodeName.toLowerCase()!=="object"){var bW=bV,bX=bV.getAttribute("id"),bU=bX||bS,b6=bV.parentNode,b5=/^\s*[+~]/.test(b4);if(!bX){bV.setAttribute("id",bU)}else{bU=bU.replace(/'/g,"\\$&")}if(b5&&b6){bV=bV.parentNode}try{if(!b5||b6){return bF(bV.querySelectorAll("[id='"+bU+"'] "+b4),bZ)}}catch(b1){}finally{if(!bX){bW.removeAttribute("id")}}}}}return e(b4,bV,bZ,b3)};for(var bR in e){by[bR]=e[bR]}bT=null})()}(function(){var e=av.documentElement,bS=e.matchesSelector||e.mozMatchesSelector||e.webkitMatchesSelector||e.msMatchesSelector;if(bS){var bU=!bS.call(av.createElement("div"),"div"),bR=false;try{bS.call(av.documentElement,"[test!='']:sizzle")}catch(bT){bR=true}by.matchesSelector=function(bW,bY){bY=bY.replace(/\=\s*([^'"\]]*)\s*\]/g,"='$1']");if(!by.isXML(bW)){try{if(bR||!bE.match.PSEUDO.test(bY)&&!/!=/.test(bY)){var bV=bS.call(bW,bY);if(bV||!bU||bW.document&&bW.document.nodeType!==11){return bV}}}catch(bX){}}return by(bY,null,null,[bW]).length>0}}})();(function(){var e=av.createElement("div");e.innerHTML="
";if(!e.getElementsByClassName||e.getElementsByClassName("e").length===0){return}e.lastChild.className="e";if(e.getElementsByClassName("e").length===1){return}bE.order.splice(1,0,"CLASS");bE.find.CLASS=function(bR,bS,bT){if(typeof bS.getElementsByClassName!=="undefined"&&!bT){return bS.getElementsByClassName(bR[1])}};e=null})();function bv(bR,bW,bV,bZ,bX,bY){for(var bT=0,bS=bZ.length;bT0){bU=e;break}}}e=e[bR]}bZ[bT]=bU}}}if(av.documentElement.contains){by.contains=function(bR,e){return bR!==e&&(bR.contains?bR.contains(e):true)}}else{if(av.documentElement.compareDocumentPosition){by.contains=function(bR,e){return !!(bR.compareDocumentPosition(e)&16)}}else{by.contains=function(){return false}}}by.isXML=function(e){var bR=(e?e.ownerDocument||e:0).documentElement;return bR?bR.nodeName!=="HTML":false};var bM=function(bS,e,bW){var bV,bX=[],bU="",bY=e.nodeType?[e]:e;while((bV=bE.match.PSEUDO.exec(bS))){bU+=bV[0];bS=bS.replace(bE.match.PSEUDO,"")}bS=bE.relative[bS]?bS+"*":bS;for(var bT=0,bR=bY.length;bT0){for(bB=bA;bB=0:b.filter(e,this).length>0:this.filter(e).length>0)},closest:function(by,bx){var bv=[],bw,e,bz=this[0];if(b.isArray(by)){var bB=1;while(bz&&bz.ownerDocument&&bz!==bx){for(bw=0;bw-1:b.find.matchesSelector(bz,by)){bv.push(bz);break}else{bz=bz.parentNode;if(!bz||!bz.ownerDocument||bz===bx||bz.nodeType===11){break}}}}bv=bv.length>1?b.unique(bv):bv;return this.pushStack(bv,"closest",by)},index:function(e){if(!e){return(this[0]&&this[0].parentNode)?this.prevAll().length:-1}if(typeof e==="string"){return b.inArray(this[0],b(e))}return b.inArray(e.jquery?e[0]:e,this)},add:function(e,bv){var bx=typeof e==="string"?b(e,bv):b.makeArray(e&&e.nodeType?[e]:e),bw=b.merge(this.get(),bx);return this.pushStack(C(bx[0])||C(bw[0])?bw:b.unique(bw))},andSelf:function(){return this.add(this.prevObject)}});function C(e){return !e||!e.parentNode||e.parentNode.nodeType===11}b.each({parent:function(bv){var e=bv.parentNode;return e&&e.nodeType!==11?e:null},parents:function(e){return b.dir(e,"parentNode")},parentsUntil:function(bv,e,bw){return b.dir(bv,"parentNode",bw)},next:function(e){return b.nth(e,2,"nextSibling")},prev:function(e){return b.nth(e,2,"previousSibling")},nextAll:function(e){return b.dir(e,"nextSibling")},prevAll:function(e){return b.dir(e,"previousSibling")},nextUntil:function(bv,e,bw){return b.dir(bv,"nextSibling",bw)},prevUntil:function(bv,e,bw){return b.dir(bv,"previousSibling",bw)},siblings:function(e){return b.sibling(e.parentNode.firstChild,e)},children:function(e){return b.sibling(e.firstChild)},contents:function(e){return b.nodeName(e,"iframe")?e.contentDocument||e.contentWindow.document:b.makeArray(e.childNodes)}},function(e,bv){b.fn[e]=function(by,bw){var bx=b.map(this,bv,by);if(!ab.test(e)){bw=by}if(bw&&typeof bw==="string"){bx=b.filter(bw,bx)}bx=this.length>1&&!ay[e]?b.unique(bx):bx;if((this.length>1||a9.test(bw))&&aq.test(e)){bx=bx.reverse()}return this.pushStack(bx,e,P.call(arguments).join(","))}});b.extend({filter:function(bw,e,bv){if(bv){bw=":not("+bw+")"}return e.length===1?b.find.matchesSelector(e[0],bw)?[e[0]]:[]:b.find.matches(bw,e)},dir:function(bw,bv,by){var e=[],bx=bw[bv];while(bx&&bx.nodeType!==9&&(by===L||bx.nodeType!==1||!b(bx).is(by))){if(bx.nodeType===1){e.push(bx)}bx=bx[bv]}return e},nth:function(by,e,bw,bx){e=e||1;var bv=0;for(;by;by=by[bw]){if(by.nodeType===1&&++bv===e){break}}return by},sibling:function(bw,bv){var e=[];for(;bw;bw=bw.nextSibling){if(bw.nodeType===1&&bw!==bv){e.push(bw)}}return e}});function aG(bx,bw,e){bw=bw||0;if(b.isFunction(bw)){return b.grep(bx,function(bz,by){var bA=!!bw.call(bz,by,bz);return bA===e})}else{if(bw.nodeType){return b.grep(bx,function(bz,by){return(bz===bw)===e})}else{if(typeof bw==="string"){var bv=b.grep(bx,function(by){return by.nodeType===1});if(bp.test(bw)){return b.filter(bw,bv,!e)}else{bw=b.filter(bw,bv)}}}}return b.grep(bx,function(bz,by){return(b.inArray(bz,bw)>=0)===e})}function a(e){var bw=aR.split("|"),bv=e.createDocumentFragment();if(bv.createElement){while(bw.length){bv.createElement(bw.pop())}}return bv}var aR="abbr|article|aside|audio|canvas|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",ag=/ jQuery\d+="(?:\d+|null)"/g,ar=/^\s+/,R=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,d=/<([\w:]+)/,w=/",""],legend:[1,"
","
"],thead:[1,"","
"],tr:[2,"","
"],td:[3,"","
"],col:[2,"","
"],area:[1,"",""],_default:[0,"",""]},ac=a(av);ax.optgroup=ax.option;ax.tbody=ax.tfoot=ax.colgroup=ax.caption=ax.thead;ax.th=ax.td;if(!b.support.htmlSerialize){ax._default=[1,"div
","
"]}b.fn.extend({text:function(e){if(b.isFunction(e)){return this.each(function(bw){var bv=b(this);bv.text(e.call(this,bw,bv.text()))})}if(typeof e!=="object"&&e!==L){return this.empty().append((this[0]&&this[0].ownerDocument||av).createTextNode(e))}return b.text(this)},wrapAll:function(e){if(b.isFunction(e)){return this.each(function(bw){b(this).wrapAll(e.call(this,bw))})}if(this[0]){var bv=b(e,this[0].ownerDocument).eq(0).clone(true);if(this[0].parentNode){bv.insertBefore(this[0])}bv.map(function(){var bw=this;while(bw.firstChild&&bw.firstChild.nodeType===1){bw=bw.firstChild}return bw}).append(this)}return this},wrapInner:function(e){if(b.isFunction(e)){return this.each(function(bv){b(this).wrapInner(e.call(this,bv))})}return this.each(function(){var bv=b(this),bw=bv.contents();if(bw.length){bw.wrapAll(e)}else{bv.append(e)}})},wrap:function(e){var bv=b.isFunction(e);return this.each(function(bw){b(this).wrapAll(bv?e.call(this,bw):e)})},unwrap:function(){return this.parent().each(function(){if(!b.nodeName(this,"body")){b(this).replaceWith(this.childNodes)}}).end()},append:function(){return this.domManip(arguments,true,function(e){if(this.nodeType===1){this.appendChild(e)}})},prepend:function(){return this.domManip(arguments,true,function(e){if(this.nodeType===1){this.insertBefore(e,this.firstChild)}})},before:function(){if(this[0]&&this[0].parentNode){return this.domManip(arguments,false,function(bv){this.parentNode.insertBefore(bv,this)})}else{if(arguments.length){var e=b.clean(arguments);e.push.apply(e,this.toArray());return this.pushStack(e,"before",arguments)}}},after:function(){if(this[0]&&this[0].parentNode){return this.domManip(arguments,false,function(bv){this.parentNode.insertBefore(bv,this.nextSibling)})}else{if(arguments.length){var e=this.pushStack(this,"after",arguments);e.push.apply(e,b.clean(arguments));return e}}},remove:function(e,bx){for(var bv=0,bw;(bw=this[bv])!=null;bv++){if(!e||b.filter(e,[bw]).length){if(!bx&&bw.nodeType===1){b.cleanData(bw.getElementsByTagName("*"));b.cleanData([bw])}if(bw.parentNode){bw.parentNode.removeChild(bw)}}}return this},empty:function(){for(var e=0,bv;(bv=this[e])!=null;e++){if(bv.nodeType===1){b.cleanData(bv.getElementsByTagName("*"))}while(bv.firstChild){bv.removeChild(bv.firstChild)}}return this},clone:function(bv,e){bv=bv==null?false:bv;e=e==null?bv:e;return this.map(function(){return b.clone(this,bv,e)})},html:function(bx){if(bx===L){return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(ag,""):null}else{if(typeof bx==="string"&&!ae.test(bx)&&(b.support.leadingWhitespace||!ar.test(bx))&&!ax[(d.exec(bx)||["",""])[1].toLowerCase()]){bx=bx.replace(R,"<$1>");try{for(var bw=0,bv=this.length;bw1&&bw0?this.clone(true):this).get();b(bC[bA])[bv](by);bz=bz.concat(by)}return this.pushStack(bz,e,bC.selector)}}});function bg(e){if(typeof e.getElementsByTagName!=="undefined"){return e.getElementsByTagName("*")}else{if(typeof e.querySelectorAll!=="undefined"){return e.querySelectorAll("*")}else{return[]}}}function az(e){if(e.type==="checkbox"||e.type==="radio"){e.defaultChecked=e.checked}}function E(e){var bv=(e.nodeName||"").toLowerCase();if(bv==="input"){az(e)}else{if(bv!=="script"&&typeof e.getElementsByTagName!=="undefined"){b.grep(e.getElementsByTagName("input"),az)}}}function al(e){var bv=av.createElement("div");ac.appendChild(bv);bv.innerHTML=e.outerHTML;return bv.firstChild}b.extend({clone:function(by,bA,bw){var e,bv,bx,bz=b.support.html5Clone||!ah.test("<"+by.nodeName)?by.cloneNode(true):al(by);if((!b.support.noCloneEvent||!b.support.noCloneChecked)&&(by.nodeType===1||by.nodeType===11)&&!b.isXMLDoc(by)){ai(by,bz);e=bg(by);bv=bg(bz);for(bx=0;e[bx];++bx){if(bv[bx]){ai(e[bx],bv[bx])}}}if(bA){t(by,bz);if(bw){e=bg(by);bv=bg(bz);for(bx=0;e[bx];++bx){t(e[bx],bv[bx])}}}e=bv=null;return bz},clean:function(bw,by,bH,bA){var bF;by=by||av;if(typeof by.createElement==="undefined"){by=by.ownerDocument||by[0]&&by[0].ownerDocument||av}var bI=[],bB;for(var bE=0,bz;(bz=bw[bE])!=null;bE++){if(typeof bz==="number"){bz+=""}if(!bz){continue}if(typeof bz==="string"){if(!W.test(bz)){bz=by.createTextNode(bz)}else{bz=bz.replace(R,"<$1>");var bK=(d.exec(bz)||["",""])[1].toLowerCase(),bx=ax[bK]||ax._default,bD=bx[0],bv=by.createElement("div");if(by===av){ac.appendChild(bv)}else{a(by).appendChild(bv)}bv.innerHTML=bx[1]+bz+bx[2];while(bD--){bv=bv.lastChild}if(!b.support.tbody){var e=w.test(bz),bC=bK==="table"&&!e?bv.firstChild&&bv.firstChild.childNodes:bx[1]===""&&!e?bv.childNodes:[];for(bB=bC.length-1;bB>=0;--bB){if(b.nodeName(bC[bB],"tbody")&&!bC[bB].childNodes.length){bC[bB].parentNode.removeChild(bC[bB])}}}if(!b.support.leadingWhitespace&&ar.test(bz)){bv.insertBefore(by.createTextNode(ar.exec(bz)[0]),bv.firstChild)}bz=bv.childNodes}}var bG;if(!b.support.appendChecked){if(bz[0]&&typeof(bG=bz.length)==="number"){for(bB=0;bB=0){return bx+"px"}}else{return bx}}}});if(!b.support.opacity){b.cssHooks.opacity={get:function(bv,e){return au.test((e&&bv.currentStyle?bv.currentStyle.filter:bv.style.filter)||"")?(parseFloat(RegExp.$1)/100)+"":e?"1":""},set:function(by,bz){var bx=by.style,bv=by.currentStyle,e=b.isNumeric(bz)?"alpha(opacity="+bz*100+")":"",bw=bv&&bv.filter||bx.filter||"";bx.zoom=1;if(bz>=1&&b.trim(bw.replace(ak,""))===""){bx.removeAttribute("filter");if(bv&&!bv.filter){return}}bx.filter=ak.test(bw)?bw.replace(ak,e):bw+" "+e}}}b(function(){if(!b.support.reliableMarginRight){b.cssHooks.marginRight={get:function(bw,bv){var e;b.swap(bw,{display:"inline-block"},function(){if(bv){e=Z(bw,"margin-right","marginRight")}else{e=bw.style.marginRight}});return e}}}});if(av.defaultView&&av.defaultView.getComputedStyle){aI=function(by,bw){var bv,bx,e;bw=bw.replace(z,"-$1").toLowerCase();if((bx=by.ownerDocument.defaultView)&&(e=bx.getComputedStyle(by,null))){bv=e.getPropertyValue(bw);if(bv===""&&!b.contains(by.ownerDocument.documentElement,by)){bv=b.style(by,bw)}}return bv}}if(av.documentElement.currentStyle){aX=function(bz,bw){var bA,e,by,bv=bz.currentStyle&&bz.currentStyle[bw],bx=bz.style;if(bv===null&&bx&&(by=bx[bw])){bv=by}if(!bc.test(bv)&&bn.test(bv)){bA=bx.left;e=bz.runtimeStyle&&bz.runtimeStyle.left;if(e){bz.runtimeStyle.left=bz.currentStyle.left}bx.left=bw==="fontSize"?"1em":(bv||0);bv=bx.pixelLeft+"px";bx.left=bA;if(e){bz.runtimeStyle.left=e}}return bv===""?"auto":bv}}Z=aI||aX;function p(by,bw,bv){var bA=bw==="width"?by.offsetWidth:by.offsetHeight,bz=bw==="width"?an:a1,bx=0,e=bz.length;if(bA>0){if(bv!=="border"){for(;bx)<[^<]*)*<\/script>/gi,q=/^(?:select|textarea)/i,h=/\s+/,br=/([?&])_=[^&]*/,K=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+))?)?/,A=b.fn.load,aa={},r={},aE,s,aV=["*/"]+["*"];try{aE=bl.href}catch(aw){aE=av.createElement("a");aE.href="";aE=aE.href}s=K.exec(aE.toLowerCase())||[];function f(e){return function(by,bA){if(typeof by!=="string"){bA=by;by="*"}if(b.isFunction(bA)){var bx=by.toLowerCase().split(h),bw=0,bz=bx.length,bv,bB,bC;for(;bw=0){var e=bw.slice(by,bw.length);bw=bw.slice(0,by)}var bx="GET";if(bz){if(b.isFunction(bz)){bA=bz;bz=L}else{if(typeof bz==="object"){bz=b.param(bz,b.ajaxSettings.traditional);bx="POST"}}}var bv=this;b.ajax({url:bw,type:bx,dataType:"html",data:bz,complete:function(bC,bB,bD){bD=bC.responseText;if(bC.isResolved()){bC.done(function(bE){bD=bE});bv.html(e?b("
").append(bD.replace(a6,"")).find(e):bD)}if(bA){bv.each(bA,[bD,bB,bC])}}});return this},serialize:function(){return b.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?b.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||q.test(this.nodeName)||aZ.test(this.type))}).map(function(e,bv){var bw=b(this).val();return bw==null?null:b.isArray(bw)?b.map(bw,function(by,bx){return{name:bv.name,value:by.replace(bs,"\r\n")}}):{name:bv.name,value:bw.replace(bs,"\r\n")}}).get()}});b.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(e,bv){b.fn[bv]=function(bw){return this.on(bv,bw)}});b.each(["get","post"],function(e,bv){b[bv]=function(bw,by,bz,bx){if(b.isFunction(by)){bx=bx||bz;bz=by;by=L}return b.ajax({type:bv,url:bw,data:by,success:bz,dataType:bx})}});b.extend({getScript:function(e,bv){return b.get(e,L,bv,"script")},getJSON:function(e,bv,bw){return b.get(e,bv,bw,"json")},ajaxSetup:function(bv,e){if(e){am(bv,b.ajaxSettings)}else{e=bv;bv=b.ajaxSettings}am(bv,e);return bv},ajaxSettings:{url:aE,isLocal:aM.test(s[1]),global:true,type:"GET",contentType:"application/x-www-form-urlencoded",processData:true,async:true,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":aV},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":bb.String,"text html":true,"text json":b.parseJSON,"text xml":b.parseXML},flatOptions:{context:true,url:true}},ajaxPrefilter:f(aa),ajaxTransport:f(r),ajax:function(bz,bx){if(typeof bz==="object"){bx=bz;bz=L}bx=bx||{};var bD=b.ajaxSetup({},bx),bS=bD.context||bD,bG=bS!==bD&&(bS.nodeType||bS instanceof b)?b(bS):b.event,bR=b.Deferred(),bN=b.Callbacks("once memory"),bB=bD.statusCode||{},bC,bH={},bO={},bQ,by,bL,bE,bI,bA=0,bw,bK,bJ={readyState:0,setRequestHeader:function(bT,bU){if(!bA){var e=bT.toLowerCase();bT=bO[e]=bO[e]||bT;bH[bT]=bU}return this},getAllResponseHeaders:function(){return bA===2?bQ:null},getResponseHeader:function(bT){var e;if(bA===2){if(!by){by={};while((e=aD.exec(bQ))){by[e[1].toLowerCase()]=e[2]}}e=by[bT.toLowerCase()]}return e===L?null:e},overrideMimeType:function(e){if(!bA){bD.mimeType=e}return this},abort:function(e){e=e||"abort";if(bL){bL.abort(e)}bF(0,e);return this}};function bF(bZ,bU,b0,bW){if(bA===2){return}bA=2;if(bE){clearTimeout(bE)}bL=L;bQ=bW||"";bJ.readyState=bZ>0?4:0;var bT,b4,b3,bX=bU,bY=b0?bj(bD,bJ,b0):L,bV,b2;if(bZ>=200&&bZ<300||bZ===304){if(bD.ifModified){if((bV=bJ.getResponseHeader("Last-Modified"))){b.lastModified[bC]=bV}if((b2=bJ.getResponseHeader("Etag"))){b.etag[bC]=b2}}if(bZ===304){bX="notmodified";bT=true}else{try{b4=G(bD,bY);bX="success";bT=true}catch(b1){bX="parsererror";b3=b1}}}else{b3=bX;if(!bX||bZ){bX="error";if(bZ<0){bZ=0}}}bJ.status=bZ;bJ.statusText=""+(bU||bX);if(bT){bR.resolveWith(bS,[b4,bX,bJ])}else{bR.rejectWith(bS,[bJ,bX,b3])}bJ.statusCode(bB);bB=L;if(bw){bG.trigger("ajax"+(bT?"Success":"Error"),[bJ,bD,bT?b4:b3])}bN.fireWith(bS,[bJ,bX]);if(bw){bG.trigger("ajaxComplete",[bJ,bD]);if(!(--b.active)){b.event.trigger("ajaxStop")}}}bR.promise(bJ);bJ.success=bJ.done;bJ.error=bJ.fail;bJ.complete=bN.add;bJ.statusCode=function(bT){if(bT){var e;if(bA<2){for(e in bT){bB[e]=[bB[e],bT[e]]}}else{e=bT[bJ.status];bJ.then(e,e)}}return this};bD.url=((bz||bD.url)+"").replace(bq,"").replace(c,s[1]+"//");bD.dataTypes=b.trim(bD.dataType||"*").toLowerCase().split(h);if(bD.crossDomain==null){bI=K.exec(bD.url.toLowerCase());bD.crossDomain=!!(bI&&(bI[1]!=s[1]||bI[2]!=s[2]||(bI[3]||(bI[1]==="http:"?80:443))!=(s[3]||(s[1]==="http:"?80:443))))}if(bD.data&&bD.processData&&typeof bD.data!=="string"){bD.data=b.param(bD.data,bD.traditional)}aW(aa,bD,bx,bJ);if(bA===2){return false}bw=bD.global;bD.type=bD.type.toUpperCase();bD.hasContent=!aQ.test(bD.type);if(bw&&b.active++===0){b.event.trigger("ajaxStart")}if(!bD.hasContent){if(bD.data){bD.url+=(M.test(bD.url)?"&":"?")+bD.data;delete bD.data}bC=bD.url;if(bD.cache===false){var bv=b.now(),bP=bD.url.replace(br,"$1_="+bv);bD.url=bP+((bP===bD.url)?(M.test(bD.url)?"&":"?")+"_="+bv:"")}}if(bD.data&&bD.hasContent&&bD.contentType!==false||bx.contentType){bJ.setRequestHeader("Content-Type",bD.contentType)}if(bD.ifModified){bC=bC||bD.url;if(b.lastModified[bC]){bJ.setRequestHeader("If-Modified-Since",b.lastModified[bC])}if(b.etag[bC]){bJ.setRequestHeader("If-None-Match",b.etag[bC])}}bJ.setRequestHeader("Accept",bD.dataTypes[0]&&bD.accepts[bD.dataTypes[0]]?bD.accepts[bD.dataTypes[0]]+(bD.dataTypes[0]!=="*"?", "+aV+"; q=0.01":""):bD.accepts["*"]);for(bK in bD.headers){bJ.setRequestHeader(bK,bD.headers[bK])}if(bD.beforeSend&&(bD.beforeSend.call(bS,bJ,bD)===false||bA===2)){bJ.abort();return false}for(bK in {success:1,error:1,complete:1}){bJ[bK](bD[bK])}bL=aW(r,bD,bx,bJ);if(!bL){bF(-1,"No Transport")}else{bJ.readyState=1;if(bw){bG.trigger("ajaxSend",[bJ,bD])}if(bD.async&&bD.timeout>0){bE=setTimeout(function(){bJ.abort("timeout")},bD.timeout)}try{bA=1;bL.send(bH,bF)}catch(bM){if(bA<2){bF(-1,bM)}else{throw bM}}}return bJ},param:function(e,bw){var bv=[],by=function(bz,bA){bA=b.isFunction(bA)?bA():bA;bv[bv.length]=encodeURIComponent(bz)+"="+encodeURIComponent(bA)};if(bw===L){bw=b.ajaxSettings.traditional}if(b.isArray(e)||(e.jquery&&!b.isPlainObject(e))){b.each(e,function(){by(this.name,this.value)})}else{for(var bx in e){v(bx,e[bx],bw,by)}}return bv.join("&").replace(k,"+")}});function v(bw,by,bv,bx){if(b.isArray(by)){b.each(by,function(bA,bz){if(bv||ap.test(bw)){bx(bw,bz)}else{v(bw+"["+(typeof bz==="object"||b.isArray(bz)?bA:"")+"]",bz,bv,bx)}})}else{if(!bv&&by!=null&&typeof by==="object"){for(var e in by){v(bw+"["+e+"]",by[e],bv,bx)}}else{bx(bw,by)}}}b.extend({active:0,lastModified:{},etag:{}});function bj(bD,bC,bz){var bv=bD.contents,bB=bD.dataTypes,bw=bD.responseFields,by,bA,bx,e;for(bA in bw){if(bA in bz){bC[bw[bA]]=bz[bA]}}while(bB[0]==="*"){bB.shift();if(by===L){by=bD.mimeType||bC.getResponseHeader("content-type")}}if(by){for(bA in bv){if(bv[bA]&&bv[bA].test(by)){bB.unshift(bA);break}}}if(bB[0] in bz){bx=bB[0]}else{for(bA in bz){if(!bB[0]||bD.converters[bA+" "+bB[0]]){bx=bA;break}if(!e){e=bA}}bx=bx||e}if(bx){if(bx!==bB[0]){bB.unshift(bx)}return bz[bx]}}function G(bH,bz){if(bH.dataFilter){bz=bH.dataFilter(bz,bH.dataType)}var bD=bH.dataTypes,bG={},bA,bE,bw=bD.length,bB,bC=bD[0],bx,by,bF,bv,e;for(bA=1;bA=bw.duration+this.startTime){this.now=this.end;this.pos=this.state=1;this.update();bw.animatedProperties[this.prop]=true;for(bA in bw.animatedProperties){if(bw.animatedProperties[bA]!==true){e=false}}if(e){if(bw.overflow!=null&&!b.support.shrinkWrapBlocks){b.each(["","X","Y"],function(bC,bD){bz.style["overflow"+bD]=bw.overflow[bC]})}if(bw.hide){b(bz).hide()}if(bw.hide||bw.show){for(bA in bw.animatedProperties){b.style(bz,bA,bw.orig[bA]);b.removeData(bz,"fxshow"+bA,true);b.removeData(bz,"toggle"+bA,true)}}bv=bw.complete;if(bv){bw.complete=false;bv.call(bz)}}return false}else{if(bw.duration==Infinity){this.now=bx}else{bB=bx-this.startTime;this.state=bB/bw.duration;this.pos=b.easing[bw.animatedProperties[this.prop]](this.state,bB,0,1,bw.duration);this.now=this.start+((this.end-this.start)*this.pos)}this.update()}return true}};b.extend(b.fx,{tick:function(){var bw,bv=b.timers,e=0;for(;e").appendTo(e),bw=bv.css("display");bv.remove();if(bw==="none"||bw===""){if(!a8){a8=av.createElement("iframe");a8.frameBorder=a8.width=a8.height=0}e.appendChild(a8);if(!m||!a8.createElement){m=(a8.contentWindow||a8.contentDocument).document;m.write((av.compatMode==="CSS1Compat"?"":"")+"");m.close()}bv=m.createElement(bx);m.body.appendChild(bv);bw=b.css(bv,"display");e.removeChild(a8)}Q[bx]=bw}return Q[bx]}var V=/^t(?:able|d|h)$/i,ad=/^(?:body|html)$/i;if("getBoundingClientRect" in av.documentElement){b.fn.offset=function(bI){var by=this[0],bB;if(bI){return this.each(function(e){b.offset.setOffset(this,bI,e)})}if(!by||!by.ownerDocument){return null}if(by===by.ownerDocument.body){return b.offset.bodyOffset(by)}try{bB=by.getBoundingClientRect()}catch(bF){}var bH=by.ownerDocument,bw=bH.documentElement;if(!bB||!b.contains(bw,by)){return bB?{top:bB.top,left:bB.left}:{top:0,left:0}}var bC=bH.body,bD=aK(bH),bA=bw.clientTop||bC.clientTop||0,bE=bw.clientLeft||bC.clientLeft||0,bv=bD.pageYOffset||b.support.boxModel&&bw.scrollTop||bC.scrollTop,bz=bD.pageXOffset||b.support.boxModel&&bw.scrollLeft||bC.scrollLeft,bG=bB.top+bv-bA,bx=bB.left+bz-bE;return{top:bG,left:bx}}}else{b.fn.offset=function(bF){var bz=this[0];if(bF){return this.each(function(bG){b.offset.setOffset(this,bF,bG)})}if(!bz||!bz.ownerDocument){return null}if(bz===bz.ownerDocument.body){return b.offset.bodyOffset(bz)}var bC,bw=bz.offsetParent,bv=bz,bE=bz.ownerDocument,bx=bE.documentElement,bA=bE.body,bB=bE.defaultView,e=bB?bB.getComputedStyle(bz,null):bz.currentStyle,bD=bz.offsetTop,by=bz.offsetLeft;while((bz=bz.parentNode)&&bz!==bA&&bz!==bx){if(b.support.fixedPosition&&e.position==="fixed"){break}bC=bB?bB.getComputedStyle(bz,null):bz.currentStyle;bD-=bz.scrollTop;by-=bz.scrollLeft;if(bz===bw){bD+=bz.offsetTop;by+=bz.offsetLeft;if(b.support.doesNotAddBorder&&!(b.support.doesAddBorderForTableAndCells&&V.test(bz.nodeName))){bD+=parseFloat(bC.borderTopWidth)||0;by+=parseFloat(bC.borderLeftWidth)||0}bv=bw;bw=bz.offsetParent}if(b.support.subtractsBorderForOverflowNotVisible&&bC.overflow!=="visible"){bD+=parseFloat(bC.borderTopWidth)||0;by+=parseFloat(bC.borderLeftWidth)||0}e=bC}if(e.position==="relative"||e.position==="static"){bD+=bA.offsetTop;by+=bA.offsetLeft}if(b.support.fixedPosition&&e.position==="fixed"){bD+=Math.max(bx.scrollTop,bA.scrollTop);by+=Math.max(bx.scrollLeft,bA.scrollLeft)}return{top:bD,left:by}}}b.offset={bodyOffset:function(e){var bw=e.offsetTop,bv=e.offsetLeft;if(b.support.doesNotIncludeMarginInBodyOffset){bw+=parseFloat(b.css(e,"marginTop"))||0;bv+=parseFloat(b.css(e,"marginLeft"))||0}return{top:bw,left:bv}},setOffset:function(bx,bG,bA){var bB=b.css(bx,"position");if(bB==="static"){bx.style.position="relative"}var bz=b(bx),bv=bz.offset(),e=b.css(bx,"top"),bE=b.css(bx,"left"),bF=(bB==="absolute"||bB==="fixed")&&b.inArray("auto",[e,bE])>-1,bD={},bC={},bw,by;if(bF){bC=bz.position();bw=bC.top;by=bC.left}else{bw=parseFloat(e)||0;by=parseFloat(bE)||0}if(b.isFunction(bG)){bG=bG.call(bx,bA,bv)}if(bG.top!=null){bD.top=(bG.top-bv.top)+bw}if(bG.left!=null){bD.left=(bG.left-bv.left)+by}if("using" in bG){bG.using.call(bx,bD)}else{bz.css(bD)}}};b.fn.extend({position:function(){if(!this[0]){return null}var bw=this[0],bv=this.offsetParent(),bx=this.offset(),e=ad.test(bv[0].nodeName)?{top:0,left:0}:bv.offset();bx.top-=parseFloat(b.css(bw,"marginTop"))||0;bx.left-=parseFloat(b.css(bw,"marginLeft"))||0;e.top+=parseFloat(b.css(bv[0],"borderTopWidth"))||0;e.left+=parseFloat(b.css(bv[0],"borderLeftWidth"))||0;return{top:bx.top-e.top,left:bx.left-e.left}},offsetParent:function(){return this.map(function(){var e=this.offsetParent||av.body;while(e&&(!ad.test(e.nodeName)&&b.css(e,"position")==="static")){e=e.offsetParent}return e})}});b.each(["Left","Top"],function(bv,e){var bw="scroll"+e;b.fn[bw]=function(bz){var bx,by;if(bz===L){bx=this[0];if(!bx){return null}by=aK(bx);return by?("pageXOffset" in by)?by[bv?"pageYOffset":"pageXOffset"]:b.support.boxModel&&by.document.documentElement[bw]||by.document.body[bw]:bx[bw]}return this.each(function(){by=aK(this);if(by){by.scrollTo(!bv?bz:b(by).scrollLeft(),bv?bz:b(by).scrollTop())}else{this[bw]=bz}})}});function aK(e){return b.isWindow(e)?e:e.nodeType===9?e.defaultView||e.parentWindow:false}b.each(["Height","Width"],function(bv,e){var bw=e.toLowerCase();b.fn["inner"+e]=function(){var bx=this[0];return bx?bx.style?parseFloat(b.css(bx,bw,"padding")):this[bw]():null};b.fn["outer"+e]=function(by){var bx=this[0];return bx?bx.style?parseFloat(b.css(bx,bw,by?"margin":"border")):this[bw]():null};b.fn[bw]=function(bz){var bA=this[0];if(!bA){return bz==null?null:this}if(b.isFunction(bz)){return this.each(function(bE){var bD=b(this);bD[bw](bz.call(this,bE,bD[bw]()))})}if(b.isWindow(bA)){var bB=bA.document.documentElement["client"+e],bx=bA.document.body;return bA.document.compatMode==="CSS1Compat"&&bB||bx&&bx["client"+e]||bB}else{if(bA.nodeType===9){return Math.max(bA.documentElement["client"+e],bA.body["scroll"+e],bA.documentElement["scroll"+e],bA.body["offset"+e],bA.documentElement["offset"+e])}else{if(bz===L){var bC=b.css(bA,bw),by=parseFloat(bC);return b.isNumeric(by)?by:bC}else{return this.css(bw,typeof bz==="string"?bz:bz+"px")}}}}});bb.jQuery=bb.$=b;if(typeof define==="function"&&define.amd&&define.amd.jQuery){define("jquery",[],function(){return b})}})(window);/*! + * jQuery UI 1.8.18 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI + */ +(function(a,d){a.ui=a.ui||{};if(a.ui.version){return}a.extend(a.ui,{version:"1.8.18",keyCode:{ALT:18,BACKSPACE:8,CAPS_LOCK:20,COMMA:188,COMMAND:91,COMMAND_LEFT:91,COMMAND_RIGHT:93,CONTROL:17,DELETE:46,DOWN:40,END:35,ENTER:13,ESCAPE:27,HOME:36,INSERT:45,LEFT:37,MENU:93,NUMPAD_ADD:107,NUMPAD_DECIMAL:110,NUMPAD_DIVIDE:111,NUMPAD_ENTER:108,NUMPAD_MULTIPLY:106,NUMPAD_SUBTRACT:109,PAGE_DOWN:34,PAGE_UP:33,PERIOD:190,RIGHT:39,SHIFT:16,SPACE:32,TAB:9,UP:38,WINDOWS:91}});a.fn.extend({propAttr:a.fn.prop||a.fn.attr,_focus:a.fn.focus,focus:function(e,f){return typeof e==="number"?this.each(function(){var g=this;setTimeout(function(){a(g).focus();if(f){f.call(g)}},e)}):this._focus.apply(this,arguments)},scrollParent:function(){var e;if((a.browser.msie&&(/(static|relative)/).test(this.css("position")))||(/absolute/).test(this.css("position"))){e=this.parents().filter(function(){return(/(relative|absolute|fixed)/).test(a.curCSS(this,"position",1))&&(/(auto|scroll)/).test(a.curCSS(this,"overflow",1)+a.curCSS(this,"overflow-y",1)+a.curCSS(this,"overflow-x",1))}).eq(0)}else{e=this.parents().filter(function(){return(/(auto|scroll)/).test(a.curCSS(this,"overflow",1)+a.curCSS(this,"overflow-y",1)+a.curCSS(this,"overflow-x",1))}).eq(0)}return(/fixed/).test(this.css("position"))||!e.length?a(document):e},zIndex:function(h){if(h!==d){return this.css("zIndex",h)}if(this.length){var f=a(this[0]),e,g;while(f.length&&f[0]!==document){e=f.css("position");if(e==="absolute"||e==="relative"||e==="fixed"){g=parseInt(f.css("zIndex"),10);if(!isNaN(g)&&g!==0){return g}}f=f.parent()}}return 0},disableSelection:function(){return this.bind((a.support.selectstart?"selectstart":"mousedown")+".ui-disableSelection",function(e){e.preventDefault()})},enableSelection:function(){return this.unbind(".ui-disableSelection")}});a.each(["Width","Height"],function(g,e){var f=e==="Width"?["Left","Right"]:["Top","Bottom"],h=e.toLowerCase(),k={innerWidth:a.fn.innerWidth,innerHeight:a.fn.innerHeight,outerWidth:a.fn.outerWidth,outerHeight:a.fn.outerHeight};function j(m,l,i,n){a.each(f,function(){l-=parseFloat(a.curCSS(m,"padding"+this,true))||0;if(i){l-=parseFloat(a.curCSS(m,"border"+this+"Width",true))||0}if(n){l-=parseFloat(a.curCSS(m,"margin"+this,true))||0}});return l}a.fn["inner"+e]=function(i){if(i===d){return k["inner"+e].call(this)}return this.each(function(){a(this).css(h,j(this,i)+"px")})};a.fn["outer"+e]=function(i,l){if(typeof i!=="number"){return k["outer"+e].call(this,i)}return this.each(function(){a(this).css(h,j(this,i,true,l)+"px")})}});function c(g,e){var j=g.nodeName.toLowerCase();if("area"===j){var i=g.parentNode,h=i.name,f;if(!g.href||!h||i.nodeName.toLowerCase()!=="map"){return false}f=a("img[usemap=#"+h+"]")[0];return !!f&&b(f)}return(/input|select|textarea|button|object/.test(j)?!g.disabled:"a"==j?g.href||e:e)&&b(g)}function b(e){return !a(e).parents().andSelf().filter(function(){return a.curCSS(this,"visibility")==="hidden"||a.expr.filters.hidden(this)}).length}a.extend(a.expr[":"],{data:function(g,f,e){return !!a.data(g,e[3])},focusable:function(e){return c(e,!isNaN(a.attr(e,"tabindex")))},tabbable:function(g){var e=a.attr(g,"tabindex"),f=isNaN(e);return(f||e>=0)&&c(g,!f)}});a(function(){var e=document.body,f=e.appendChild(f=document.createElement("div"));f.offsetHeight;a.extend(f.style,{minHeight:"100px",height:"auto",padding:0,borderWidth:0});a.support.minHeight=f.offsetHeight===100;a.support.selectstart="onselectstart" in f;e.removeChild(f).style.display="none"});a.extend(a.ui,{plugin:{add:function(f,g,j){var h=a.ui[f].prototype;for(var e in j){h.plugins[e]=h.plugins[e]||[];h.plugins[e].push([g,j[e]])}},call:function(e,g,f){var j=e.plugins[g];if(!j||!e.element[0].parentNode){return}for(var h=0;h0){return true}h[e]=1;g=(h[e]>0);h[e]=0;return g},isOverAxis:function(f,e,g){return(f>e)&&(f<(e+g))},isOver:function(j,f,i,h,e,g){return a.ui.isOverAxis(j,i,e)&&a.ui.isOverAxis(f,h,g)}})})(jQuery);/*! + * jQuery UI Widget 1.8.18 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Widget + */ +(function(b,d){if(b.cleanData){var c=b.cleanData;b.cleanData=function(f){for(var g=0,h;(h=f[g])!=null;g++){try{b(h).triggerHandler("remove")}catch(j){}}c(f)}}else{var a=b.fn.remove;b.fn.remove=function(e,f){return this.each(function(){if(!f){if(!e||b.filter(e,[this]).length){b("*",this).add([this]).each(function(){try{b(this).triggerHandler("remove")}catch(g){}})}}return a.call(b(this),e,f)})}}b.widget=function(f,h,e){var g=f.split(".")[0],j;f=f.split(".")[1];j=g+"-"+f;if(!e){e=h;h=b.Widget}b.expr[":"][j]=function(k){return !!b.data(k,f)};b[g]=b[g]||{};b[g][f]=function(k,l){if(arguments.length){this._createWidget(k,l)}};var i=new h();i.options=b.extend(true,{},i.options);b[g][f].prototype=b.extend(true,i,{namespace:g,widgetName:f,widgetEventPrefix:b[g][f].prototype.widgetEventPrefix||f,widgetBaseClass:j},e);b.widget.bridge(f,b[g][f])};b.widget.bridge=function(f,e){b.fn[f]=function(i){var g=typeof i==="string",h=Array.prototype.slice.call(arguments,1),j=this;i=!g&&h.length?b.extend.apply(null,[true,i].concat(h)):i;if(g&&i.charAt(0)==="_"){return j}if(g){this.each(function(){var k=b.data(this,f),l=k&&b.isFunction(k[i])?k[i].apply(k,h):k;if(l!==k&&l!==d){j=l;return false}})}else{this.each(function(){var k=b.data(this,f);if(k){k.option(i||{})._init()}else{b.data(this,f,new e(i,this))}})}return j}};b.Widget=function(e,f){if(arguments.length){this._createWidget(e,f)}};b.Widget.prototype={widgetName:"widget",widgetEventPrefix:"",options:{disabled:false},_createWidget:function(f,g){b.data(g,this.widgetName,this);this.element=b(g);this.options=b.extend(true,{},this.options,this._getCreateOptions(),f);var e=this;this.element.bind("remove."+this.widgetName,function(){e.destroy()});this._create();this._trigger("create");this._init()},_getCreateOptions:function(){return b.metadata&&b.metadata.get(this.element[0])[this.widgetName]},_create:function(){},_init:function(){},destroy:function(){this.element.unbind("."+this.widgetName).removeData(this.widgetName);this.widget().unbind("."+this.widgetName).removeAttr("aria-disabled").removeClass(this.widgetBaseClass+"-disabled ui-state-disabled")},widget:function(){return this.element},option:function(f,g){var e=f;if(arguments.length===0){return b.extend({},this.options)}if(typeof f==="string"){if(g===d){return this.options[f]}e={};e[f]=g}this._setOptions(e);return this},_setOptions:function(f){var e=this;b.each(f,function(g,h){e._setOption(g,h)});return this},_setOption:function(e,f){this.options[e]=f;if(e==="disabled"){this.widget()[f?"addClass":"removeClass"](this.widgetBaseClass+"-disabled ui-state-disabled").attr("aria-disabled",f)}return this},enable:function(){return this._setOption("disabled",false)},disable:function(){return this._setOption("disabled",true)},_trigger:function(e,f,g){var j,i,h=this.options[e];g=g||{};f=b.Event(f);f.type=(e===this.widgetEventPrefix?e:this.widgetEventPrefix+e).toLowerCase();f.target=this.element[0];i=f.originalEvent;if(i){for(j in i){if(!(j in f)){f[j]=i[j]}}}this.element.trigger(f,g);return !(b.isFunction(h)&&h.call(this.element[0],f,g)===false||f.isDefaultPrevented())}}})(jQuery);/*! + * jQuery UI Mouse 1.8.18 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Mouse + * + * Depends: + * jquery.ui.widget.js + */ +(function(b,c){var a=false;b(document).mouseup(function(d){a=false});b.widget("ui.mouse",{options:{cancel:":input,option",distance:1,delay:0},_mouseInit:function(){var d=this;this.element.bind("mousedown."+this.widgetName,function(e){return d._mouseDown(e)}).bind("click."+this.widgetName,function(e){if(true===b.data(e.target,d.widgetName+".preventClickEvent")){b.removeData(e.target,d.widgetName+".preventClickEvent");e.stopImmediatePropagation();return false}});this.started=false},_mouseDestroy:function(){this.element.unbind("."+this.widgetName)},_mouseDown:function(f){if(a){return}(this._mouseStarted&&this._mouseUp(f));this._mouseDownEvent=f;var e=this,g=(f.which==1),d=(typeof this.options.cancel=="string"&&f.target.nodeName?b(f.target).closest(this.options.cancel).length:false);if(!g||d||!this._mouseCapture(f)){return true}this.mouseDelayMet=!this.options.delay;if(!this.mouseDelayMet){this._mouseDelayTimer=setTimeout(function(){e.mouseDelayMet=true},this.options.delay)}if(this._mouseDistanceMet(f)&&this._mouseDelayMet(f)){this._mouseStarted=(this._mouseStart(f)!==false);if(!this._mouseStarted){f.preventDefault();return true}}if(true===b.data(f.target,this.widgetName+".preventClickEvent")){b.removeData(f.target,this.widgetName+".preventClickEvent")}this._mouseMoveDelegate=function(h){return e._mouseMove(h)};this._mouseUpDelegate=function(h){return e._mouseUp(h)};b(document).bind("mousemove."+this.widgetName,this._mouseMoveDelegate).bind("mouseup."+this.widgetName,this._mouseUpDelegate);f.preventDefault();a=true;return true},_mouseMove:function(d){if(b.browser.msie&&!(document.documentMode>=9)&&!d.button){return this._mouseUp(d)}if(this._mouseStarted){this._mouseDrag(d);return d.preventDefault()}if(this._mouseDistanceMet(d)&&this._mouseDelayMet(d)){this._mouseStarted=(this._mouseStart(this._mouseDownEvent,d)!==false);(this._mouseStarted?this._mouseDrag(d):this._mouseUp(d))}return !this._mouseStarted},_mouseUp:function(d){b(document).unbind("mousemove."+this.widgetName,this._mouseMoveDelegate).unbind("mouseup."+this.widgetName,this._mouseUpDelegate);if(this._mouseStarted){this._mouseStarted=false;if(d.target==this._mouseDownEvent.target){b.data(d.target,this.widgetName+".preventClickEvent",true)}this._mouseStop(d)}return false},_mouseDistanceMet:function(d){return(Math.max(Math.abs(this._mouseDownEvent.pageX-d.pageX),Math.abs(this._mouseDownEvent.pageY-d.pageY))>=this.options.distance)},_mouseDelayMet:function(d){return this.mouseDelayMet},_mouseStart:function(d){},_mouseDrag:function(d){},_mouseStop:function(d){},_mouseCapture:function(d){return true}})})(jQuery);(function(c,d){c.widget("ui.resizable",c.ui.mouse,{widgetEventPrefix:"resize",options:{alsoResize:false,animate:false,animateDuration:"slow",animateEasing:"swing",aspectRatio:false,autoHide:false,containment:false,ghost:false,grid:false,handles:"e,s,se",helper:false,maxHeight:null,maxWidth:null,minHeight:10,minWidth:10,zIndex:1000},_create:function(){var f=this,k=this.options;this.element.addClass("ui-resizable");c.extend(this,{_aspectRatio:!!(k.aspectRatio),aspectRatio:k.aspectRatio,originalElement:this.element,_proportionallyResizeElements:[],_helper:k.helper||k.ghost||k.animate?k.helper||"ui-resizable-helper":null});if(this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i)){this.element.wrap(c('
').css({position:this.element.css("position"),width:this.element.outerWidth(),height:this.element.outerHeight(),top:this.element.css("top"),left:this.element.css("left")}));this.element=this.element.parent().data("resizable",this.element.data("resizable"));this.elementIsWrapper=true;this.element.css({marginLeft:this.originalElement.css("marginLeft"),marginTop:this.originalElement.css("marginTop"),marginRight:this.originalElement.css("marginRight"),marginBottom:this.originalElement.css("marginBottom")});this.originalElement.css({marginLeft:0,marginTop:0,marginRight:0,marginBottom:0});this.originalResizeStyle=this.originalElement.css("resize");this.originalElement.css("resize","none");this._proportionallyResizeElements.push(this.originalElement.css({position:"static",zoom:1,display:"block"}));this.originalElement.css({margin:this.originalElement.css("margin")});this._proportionallyResize()}this.handles=k.handles||(!c(".ui-resizable-handle",this.element).length?"e,s,se":{n:".ui-resizable-n",e:".ui-resizable-e",s:".ui-resizable-s",w:".ui-resizable-w",se:".ui-resizable-se",sw:".ui-resizable-sw",ne:".ui-resizable-ne",nw:".ui-resizable-nw"});if(this.handles.constructor==String){if(this.handles=="all"){this.handles="n,e,s,w,se,sw,ne,nw"}var l=this.handles.split(",");this.handles={};for(var g=0;g
');if(/sw|se|ne|nw/.test(j)){h.css({zIndex:++k.zIndex})}if("se"==j){h.addClass("ui-icon ui-icon-gripsmall-diagonal-se")}this.handles[j]=".ui-resizable-"+j;this.element.append(h)}}this._renderAxis=function(q){q=q||this.element;for(var n in this.handles){if(this.handles[n].constructor==String){this.handles[n]=c(this.handles[n],this.element).show()}if(this.elementIsWrapper&&this.originalElement[0].nodeName.match(/textarea|input|select|button/i)){var o=c(this.handles[n],this.element),p=0;p=/sw|ne|nw|se|n|s/.test(n)?o.outerHeight():o.outerWidth();var m=["padding",/ne|nw|n/.test(n)?"Top":/se|sw|s/.test(n)?"Bottom":/^e$/.test(n)?"Right":"Left"].join("");q.css(m,p);this._proportionallyResize()}if(!c(this.handles[n]).length){continue}}};this._renderAxis(this.element);this._handles=c(".ui-resizable-handle",this.element).disableSelection();this._handles.mouseover(function(){if(!f.resizing){if(this.className){var i=this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i)}f.axis=i&&i[1]?i[1]:"se"}});if(k.autoHide){this._handles.hide();c(this.element).addClass("ui-resizable-autohide").hover(function(){if(k.disabled){return}c(this).removeClass("ui-resizable-autohide");f._handles.show()},function(){if(k.disabled){return}if(!f.resizing){c(this).addClass("ui-resizable-autohide");f._handles.hide()}})}this._mouseInit()},destroy:function(){this._mouseDestroy();var e=function(g){c(g).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing").removeData("resizable").unbind(".resizable").find(".ui-resizable-handle").remove()};if(this.elementIsWrapper){e(this.element);var f=this.element;f.after(this.originalElement.css({position:f.css("position"),width:f.outerWidth(),height:f.outerHeight(),top:f.css("top"),left:f.css("left")})).remove()}this.originalElement.css("resize",this.originalResizeStyle);e(this.originalElement);return this},_mouseCapture:function(f){var g=false;for(var e in this.handles){if(c(this.handles[e])[0]==f.target){g=true}}return !this.options.disabled&&g},_mouseStart:function(g){var j=this.options,f=this.element.position(),e=this.element;this.resizing=true;this.documentScroll={top:c(document).scrollTop(),left:c(document).scrollLeft()};if(e.is(".ui-draggable")||(/absolute/).test(e.css("position"))){e.css({position:"absolute",top:f.top,left:f.left})}this._renderProxy();var k=b(this.helper.css("left")),h=b(this.helper.css("top"));if(j.containment){k+=c(j.containment).scrollLeft()||0;h+=c(j.containment).scrollTop()||0}this.offset=this.helper.offset();this.position={left:k,top:h};this.size=this._helper?{width:e.outerWidth(),height:e.outerHeight()}:{width:e.width(),height:e.height()};this.originalSize=this._helper?{width:e.outerWidth(),height:e.outerHeight()}:{width:e.width(),height:e.height()};this.originalPosition={left:k,top:h};this.sizeDiff={width:e.outerWidth()-e.width(),height:e.outerHeight()-e.height()};this.originalMousePosition={left:g.pageX,top:g.pageY};this.aspectRatio=(typeof j.aspectRatio=="number")?j.aspectRatio:((this.originalSize.width/this.originalSize.height)||1);var i=c(".ui-resizable-"+this.axis).css("cursor");c("body").css("cursor",i=="auto"?this.axis+"-resize":i);e.addClass("ui-resizable-resizing");this._propagate("start",g);return true},_mouseDrag:function(e){var h=this.helper,g=this.options,m={},q=this,j=this.originalMousePosition,n=this.axis;var r=(e.pageX-j.left)||0,p=(e.pageY-j.top)||0;var i=this._change[n];if(!i){return false}var l=i.apply(this,[e,r,p]),k=c.browser.msie&&c.browser.version<7,f=this.sizeDiff;this._updateVirtualBoundaries(e.shiftKey);if(this._aspectRatio||e.shiftKey){l=this._updateRatio(l,e)}l=this._respectSize(l,e);this._propagate("resize",e);h.css({top:this.position.top+"px",left:this.position.left+"px",width:this.size.width+"px",height:this.size.height+"px"});if(!this._helper&&this._proportionallyResizeElements.length){this._proportionallyResize()}this._updateCache(l);this._trigger("resize",e,this.ui());return false},_mouseStop:function(h){this.resizing=false;var i=this.options,m=this;if(this._helper){var g=this._proportionallyResizeElements,e=g.length&&(/textarea/i).test(g[0].nodeName),f=e&&c.ui.hasScroll(g[0],"left")?0:m.sizeDiff.height,k=e?0:m.sizeDiff.width;var n={width:(m.helper.width()-k),height:(m.helper.height()-f)},j=(parseInt(m.element.css("left"),10)+(m.position.left-m.originalPosition.left))||null,l=(parseInt(m.element.css("top"),10)+(m.position.top-m.originalPosition.top))||null;if(!i.animate){this.element.css(c.extend(n,{top:l,left:j}))}m.helper.height(m.size.height);m.helper.width(m.size.width);if(this._helper&&!i.animate){this._proportionallyResize()}}c("body").css("cursor","auto");this.element.removeClass("ui-resizable-resizing");this._propagate("stop",h);if(this._helper){this.helper.remove()}return false},_updateVirtualBoundaries:function(g){var j=this.options,i,h,f,k,e;e={minWidth:a(j.minWidth)?j.minWidth:0,maxWidth:a(j.maxWidth)?j.maxWidth:Infinity,minHeight:a(j.minHeight)?j.minHeight:0,maxHeight:a(j.maxHeight)?j.maxHeight:Infinity};if(this._aspectRatio||g){i=e.minHeight*this.aspectRatio;f=e.minWidth/this.aspectRatio;h=e.maxHeight*this.aspectRatio;k=e.maxWidth/this.aspectRatio;if(i>e.minWidth){e.minWidth=i}if(f>e.minHeight){e.minHeight=f}if(hl.width),s=a(l.height)&&i.minHeight&&(i.minHeight>l.height);if(h){l.width=i.minWidth}if(s){l.height=i.minHeight}if(t){l.width=i.maxWidth}if(m){l.height=i.maxHeight}var f=this.originalPosition.left+this.originalSize.width,p=this.position.top+this.size.height;var k=/sw|nw|w/.test(q),e=/nw|ne|n/.test(q);if(h&&k){l.left=f-i.minWidth}if(t&&k){l.left=f-i.maxWidth}if(s&&e){l.top=p-i.minHeight}if(m&&e){l.top=p-i.maxHeight}var n=!l.width&&!l.height;if(n&&!l.left&&l.top){l.top=null}else{if(n&&!l.top&&l.left){l.left=null}}return l},_proportionallyResize:function(){var k=this.options;if(!this._proportionallyResizeElements.length){return}var g=this.helper||this.element;for(var f=0;f');var e=c.browser.msie&&c.browser.version<7,g=(e?1:0),h=(e?2:-1);this.helper.addClass(this._helper).css({width:this.element.outerWidth()+h,height:this.element.outerHeight()+h,position:"absolute",left:this.elementOffset.left-g+"px",top:this.elementOffset.top-g+"px",zIndex:++i.zIndex});this.helper.appendTo("body").disableSelection()}else{this.helper=this.element}},_change:{e:function(g,f,e){return{width:this.originalSize.width+f}},w:function(h,f,e){var j=this.options,g=this.originalSize,i=this.originalPosition;return{left:i.left+f,width:g.width-f}},n:function(h,f,e){var j=this.options,g=this.originalSize,i=this.originalPosition;return{top:i.top+e,height:g.height-e}},s:function(g,f,e){return{height:this.originalSize.height+e}},se:function(g,f,e){return c.extend(this._change.s.apply(this,arguments),this._change.e.apply(this,[g,f,e]))},sw:function(g,f,e){return c.extend(this._change.s.apply(this,arguments),this._change.w.apply(this,[g,f,e]))},ne:function(g,f,e){return c.extend(this._change.n.apply(this,arguments),this._change.e.apply(this,[g,f,e]))},nw:function(g,f,e){return c.extend(this._change.n.apply(this,arguments),this._change.w.apply(this,[g,f,e]))}},_propagate:function(f,e){c.ui.plugin.call(this,f,[e,this.ui()]);(f!="resize"&&this._trigger(f,e,this.ui()))},plugins:{},ui:function(){return{originalElement:this.originalElement,element:this.element,helper:this.helper,position:this.position,size:this.size,originalSize:this.originalSize,originalPosition:this.originalPosition}}});c.extend(c.ui.resizable,{version:"1.8.18"});c.ui.plugin.add("resizable","alsoResize",{start:function(f,g){var e=c(this).data("resizable"),i=e.options;var h=function(j){c(j).each(function(){var k=c(this);k.data("resizable-alsoresize",{width:parseInt(k.width(),10),height:parseInt(k.height(),10),left:parseInt(k.css("left"),10),top:parseInt(k.css("top"),10)})})};if(typeof(i.alsoResize)=="object"&&!i.alsoResize.parentNode){if(i.alsoResize.length){i.alsoResize=i.alsoResize[0];h(i.alsoResize)}else{c.each(i.alsoResize,function(j){h(j)})}}else{h(i.alsoResize)}},resize:function(g,i){var f=c(this).data("resizable"),j=f.options,h=f.originalSize,l=f.originalPosition;var k={height:(f.size.height-h.height)||0,width:(f.size.width-h.width)||0,top:(f.position.top-l.top)||0,left:(f.position.left-l.left)||0},e=function(m,n){c(m).each(function(){var q=c(this),r=c(this).data("resizable-alsoresize"),p={},o=n&&n.length?n:q.parents(i.originalElement[0]).length?["width","height"]:["width","height","top","left"];c.each(o,function(s,u){var t=(r[u]||0)+(k[u]||0);if(t&&t>=0){p[u]=t||null}});q.css(p)})};if(typeof(j.alsoResize)=="object"&&!j.alsoResize.nodeType){c.each(j.alsoResize,function(m,n){e(m,n)})}else{e(j.alsoResize)}},stop:function(e,f){c(this).removeData("resizable-alsoresize")}});c.ui.plugin.add("resizable","animate",{stop:function(i,n){var p=c(this).data("resizable"),j=p.options;var h=p._proportionallyResizeElements,e=h.length&&(/textarea/i).test(h[0].nodeName),f=e&&c.ui.hasScroll(h[0],"left")?0:p.sizeDiff.height,l=e?0:p.sizeDiff.width;var g={width:(p.size.width-l),height:(p.size.height-f)},k=(parseInt(p.element.css("left"),10)+(p.position.left-p.originalPosition.left))||null,m=(parseInt(p.element.css("top"),10)+(p.position.top-p.originalPosition.top))||null;p.element.animate(c.extend(g,m&&k?{top:m,left:k}:{}),{duration:j.animateDuration,easing:j.animateEasing,step:function(){var o={width:parseInt(p.element.css("width"),10),height:parseInt(p.element.css("height"),10),top:parseInt(p.element.css("top"),10),left:parseInt(p.element.css("left"),10)};if(h&&h.length){c(h[0]).css({width:o.width,height:o.height})}p._updateCache(o);p._propagate("resize",i)}})}});c.ui.plugin.add("resizable","containment",{start:function(f,r){var t=c(this).data("resizable"),j=t.options,l=t.element;var g=j.containment,k=(g instanceof c)?g.get(0):(/parent/.test(g))?l.parent().get(0):g;if(!k){return}t.containerElement=c(k);if(/document/.test(g)||g==document){t.containerOffset={left:0,top:0};t.containerPosition={left:0,top:0};t.parentData={element:c(document),left:0,top:0,width:c(document).width(),height:c(document).height()||document.body.parentNode.scrollHeight}}else{var n=c(k),i=[];c(["Top","Right","Left","Bottom"]).each(function(p,o){i[p]=b(n.css("padding"+o))});t.containerOffset=n.offset();t.containerPosition=n.position();t.containerSize={height:(n.innerHeight()-i[3]),width:(n.innerWidth()-i[1])};var q=t.containerOffset,e=t.containerSize.height,m=t.containerSize.width,h=(c.ui.hasScroll(k,"left")?k.scrollWidth:m),s=(c.ui.hasScroll(k)?k.scrollHeight:e);t.parentData={element:k,left:q.left,top:q.top,width:h,height:s}}},resize:function(g,q){var t=c(this).data("resizable"),i=t.options,f=t.containerSize,p=t.containerOffset,m=t.size,n=t.position,r=t._aspectRatio||g.shiftKey,e={top:0,left:0},h=t.containerElement;if(h[0]!=document&&(/static/).test(h.css("position"))){e=p}if(n.left<(t._helper?p.left:0)){t.size.width=t.size.width+(t._helper?(t.position.left-p.left):(t.position.left-e.left));if(r){t.size.height=t.size.width/i.aspectRatio}t.position.left=i.helper?p.left:0}if(n.top<(t._helper?p.top:0)){t.size.height=t.size.height+(t._helper?(t.position.top-p.top):t.position.top);if(r){t.size.width=t.size.height*i.aspectRatio}t.position.top=t._helper?p.top:0}t.offset.left=t.parentData.left+t.position.left;t.offset.top=t.parentData.top+t.position.top;var l=Math.abs((t._helper?t.offset.left-e.left:(t.offset.left-e.left))+t.sizeDiff.width),s=Math.abs((t._helper?t.offset.top-e.top:(t.offset.top-p.top))+t.sizeDiff.height);var k=t.containerElement.get(0)==t.element.parent().get(0),j=/relative|absolute/.test(t.containerElement.css("position"));if(k&&j){l-=t.parentData.left}if(l+t.size.width>=t.parentData.width){t.size.width=t.parentData.width-l;if(r){t.size.height=t.size.width/t.aspectRatio}}if(s+t.size.height>=t.parentData.height){t.size.height=t.parentData.height-s;if(r){t.size.width=t.size.height*t.aspectRatio}}},stop:function(f,n){var q=c(this).data("resizable"),g=q.options,l=q.position,m=q.containerOffset,e=q.containerPosition,i=q.containerElement;var j=c(q.helper),r=j.offset(),p=j.outerWidth()-q.sizeDiff.width,k=j.outerHeight()-q.sizeDiff.height;if(q._helper&&!g.animate&&(/relative/).test(i.css("position"))){c(this).css({left:r.left-e.left-m.left,width:p,height:k})}if(q._helper&&!g.animate&&(/static/).test(i.css("position"))){c(this).css({left:r.left-e.left-m.left,width:p,height:k})}}});c.ui.plugin.add("resizable","ghost",{start:function(g,h){var e=c(this).data("resizable"),i=e.options,f=e.size;e.ghost=e.originalElement.clone();e.ghost.css({opacity:0.25,display:"block",position:"relative",height:f.height,width:f.width,margin:0,left:0,top:0}).addClass("ui-resizable-ghost").addClass(typeof i.ghost=="string"?i.ghost:"");e.ghost.appendTo(e.helper)},resize:function(f,g){var e=c(this).data("resizable"),h=e.options;if(e.ghost){e.ghost.css({position:"relative",height:e.size.height,width:e.size.width})}},stop:function(f,g){var e=c(this).data("resizable"),h=e.options;if(e.ghost&&e.helper){e.helper.get(0).removeChild(e.ghost.get(0))}}});c.ui.plugin.add("resizable","grid",{resize:function(e,m){var p=c(this).data("resizable"),h=p.options,k=p.size,i=p.originalSize,j=p.originalPosition,n=p.axis,l=h._aspectRatio||e.shiftKey;h.grid=typeof h.grid=="number"?[h.grid,h.grid]:h.grid;var g=Math.round((k.width-i.width)/(h.grid[0]||1))*(h.grid[0]||1),f=Math.round((k.height-i.height)/(h.grid[1]||1))*(h.grid[1]||1);if(/^(se|s|e)$/.test(n)){p.size.width=i.width+g;p.size.height=i.height+f}else{if(/^(ne)$/.test(n)){p.size.width=i.width+g;p.size.height=i.height+f;p.position.top=j.top-f}else{if(/^(sw)$/.test(n)){p.size.width=i.width+g;p.size.height=i.height+f;p.position.left=j.left-g}else{p.size.width=i.width+g;p.size.height=i.height+f;p.position.top=j.top-f;p.position.left=j.left-g}}}}});var b=function(e){return parseInt(e,10)||0};var a=function(e){return !isNaN(parseInt(e,10))}})(jQuery);/*! + * jQuery hashchange event - v1.3 - 7/21/2010 + * http://benalman.com/projects/jquery-hashchange-plugin/ + * + * Copyright (c) 2010 "Cowboy" Ben Alman + * Dual licensed under the MIT and GPL licenses. + * http://benalman.com/about/license/ + */ +(function($,e,b){var c="hashchange",h=document,f,g=$.event.special,i=h.documentMode,d="on"+c in e&&(i===b||i>7);function a(j){j=j||location.href;return"#"+j.replace(/^[^#]*#?(.*)$/,"$1")}$.fn[c]=function(j){return j?this.bind(c,j):this.trigger(c)};$.fn[c].delay=50;g[c]=$.extend(g[c],{setup:function(){if(d){return false}$(f.start)},teardown:function(){if(d){return false}$(f.stop)}});f=(function(){var j={},p,m=a(),k=function(q){return q},l=k,o=k;j.start=function(){p||n()};j.stop=function(){p&&clearTimeout(p);p=b};function n(){var r=a(),q=o(m);if(r!==m){l(m=r,q);$(e).trigger(c)}else{if(q!==m){location.href=location.href.replace(/#.*/,"")+q}}p=setTimeout(n,$.fn[c].delay)}$.browser.msie&&!d&&(function(){var q,r;j.start=function(){if(!q){r=$.fn[c].src;r=r&&r+a();q=$('