diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 000000000000..f06c382dcef0 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,28 @@ +# see http://editorconfig.org/ for docs on this file + +root = true + +[*] +end_of_line = lf +trim_trailing_whitespace = false +insert_final_newline = false +indent_style = tab +indent_size = 4 + +# this VS-specific stuff is based on experiments to see how VS will modify a file after it has been manually edited. +# the settings are meant to closely match what VS does to minimize unnecessary diffs. this duplicates some settings in * +# but let's be explicit here to be safe (in case someone wants to copy-paste this out to another .editorconfig). +[*.{vcxproj,vcxproj.filters,csproj,props,targets}] +indent_style = space +indent_size = 2 +end_of_line = crlf +charset = utf-8-bom +trim_trailing_whitespace = true +insert_final_newline = false +[*.{sln,sln.template}] +indent_style = tab +indent_size = 4 +end_of_line = crlf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = false diff --git a/.gitmodules b/.gitmodules index 4e968d7a0663..04b5228b6bef 100644 --- a/.gitmodules +++ b/.gitmodules @@ -58,3 +58,6 @@ [submodule "external/api-snapshot"] path = external/api-snapshot url = git://github.com/mono/api-snapshot.git +[submodule "external/bdwgc"] + path = external/bdwgc + url = git://github.com/Unity-Technologies/bdwgc.git diff --git a/Makefile.am b/Makefile.am index f9dd1784c836..024324e3fc7f 100644 --- a/Makefile.am +++ b/Makefile.am @@ -17,9 +17,9 @@ else support_dir = endif -SUBDIRS = po $(libgc_dir) mono $(ikvm_native_dir) $(support_dir) data runtime scripts man samples $(tools_dir) msvc $(docs_dir) acceptance-tests llvm +SUBDIRS = po $(libgc_dir) $(bdwgc_dir) mono $(ikvm_native_dir) $(support_dir) data runtime scripts man samples $(tools_dir) msvc $(docs_dir) acceptance-tests llvm # Keep in sync with SUBDIRS -DIST_SUBDIRS = m4 po $(libgc_dir) mono ikvm-native $(support_dir) data runtime scripts man samples tools msvc docs acceptance-tests llvm +DIST_SUBDIRS = m4 po $(libgc_dir) $(bdwgc_dir) mono ikvm-native $(support_dir) data runtime scripts man samples tools msvc docs acceptance-tests llvm all: update_submodules diff --git a/README.md b/README.md index ce96d99aa059..917e18a22345 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,47 @@ +Unity +============================ +This is Unity Technologies fork of the open source mono project. + +### Versions +Each Unity release contains two versions of Mono. One older version (Mono) is embedded into the Editor and Players. Another newer version (MonoBleedingEdge) is used to run tools and tests. + +In newer Unity versions (2017.1+) this MonoBleedingEdge version can be used in the Editor and Players via enabling an Experimental player setting. + +### Branch Naming Convention +Branches for released Unity versions are of the form unity-\\[-mbe\][-staging\]. The '-staging' suffix is used as a branch for PRs to target with potential changes. The '-mbe' suffix indicates the branch is for the MonoBleedingEdge version of Mono mentioned above. + +### Branches + +#### Trunk +* [unity-trunk (PR to this branch for Mono)](https://github.com/Unity-Technologies/mono/tree/unity-trunk) +* [unity-master (PR to this branch for MonoBleedingEdge)](https://github.com/Unity-Technologies/mono/tree/unity-master) + +#### 2018.1 +* [unity-2018.1](https://github.com/Unity-Technologies/mono/tree/unity-2018.1) +* [unity-2018.1-mbe](https://github.com/Unity-Technologies/mono/tree/unity-2018.1-mbe) + +#### 2017.3 +* [unity-2017.3](https://github.com/Unity-Technologies/mono/tree/unity-2017.3) +* [unity-2017.3-mbe](https://github.com/Unity-Technologies/mono/tree/unity-2017.3-mbe) + +#### 2017.2 +* [unity-2017.2](https://github.com/Unity-Technologies/mono/tree/unity-2017.2) +* [unity-2017.2-mbe](https://github.com/Unity-Technologies/mono/tree/unity-2017.2-mbe) + +#### 2017.1 +* [unity-2017.1](https://github.com/Unity-Technologies/mono/tree/unity-2017.1) +* [unity-2017.1-mbe](https://github.com/Unity-Technologies/mono/tree/unity-2017.1-mbe) + +#### 5.6 +* [unity-5.6](https://github.com/Unity-Technologies/mono/tree/unity-5.6) +* [unity-5.6-mbe](https://github.com/Unity-Technologies/mono/tree/unity-5.6-mbe) + + + + +Mono +============================ + Mono is a software platform designed to allow developers to easily create cross platform applications. It is an open source implementation of Microsoft's .NET Framework based on the ECMA diff --git a/autogen.sh b/autogen.sh index 7c58e0921502..88c2eded6c6f 100755 --- a/autogen.sh +++ b/autogen.sh @@ -148,6 +148,18 @@ automake --add-missing --gnu -Wno-portability -Wno-obsolete $am_opt || echo "Running autoconf ..." autoconf || { echo "**Error**: autoconf failed."; exit 1; } +# if test -d $srcdir/external/bdwgc/libatomic_ops; then +# echo Running external/bdwgc/libatomic_ops/autogen.sh ... +# (cd $srcdir/external/bdwgc/libatomic_ops ; ./autogen.sh) +# echo Done running external/bdwgc/libatomic_ops/autogen.sh ... +# fi + +if test -d $srcdir/external/bdwgc; then + echo Running external/bdwgc/autogen.sh ... + (cd $srcdir/external/bdwgc ; ./autogen.sh) + echo Done running external/bdwgc/autogen.sh ... +fi + if test -d $srcdir/libgc; then echo Running libgc/autogen.sh ... (cd $srcdir/libgc ; NOCONFIGURE=1 ./autogen.sh "$@") diff --git a/configure.ac b/configure.ac index ec5b8e7ac675..53c48fdf65b3 100644 --- a/configure.ac +++ b/configure.ac @@ -927,6 +927,8 @@ AC_ARG_WITH(xammac, [ --with-xammac=yes,no If you w AC_ARG_WITH(testing_aot_hybrid, [ --with-testing_aot_hybrid=yes,no If you want to build the testing_aot_hybrid assemblies (defaults to no)], [], [with_testing_aot_hybrid=default]) AC_ARG_WITH(testing_aot_full, [ --with-testing_aot_full=yes,no If you want to build the testing_aot_full assemblies (defaults to no)], [], [with_testing_aot_full=default]) AC_ARG_WITH(winaot, [ --with-winaot=yes,no If you want to build the Windows friendly AOT assemblies (defaults to no)], [], [with_winaot=default]) +AC_ARG_WITH(unityjit, [ --with-unityjit=yes,no If you want to build the Unity JIT friendly assemblies (defaults to no)], [], [with_unityjit=default]) +AC_ARG_WITH(unityaot, [ --with-unityaot=yes,no If you want to build the Unity AOT friendly assemblies (defaults to no)], [], [with_unityaot=default]) AC_ARG_WITH(orbis, [ --with-orbis=yes,no If you want to build the Orbis assemblies (defaults to no)], [], [with_orbis=default]) AC_ARG_WITH(unreal, [ --with-unreal=yes,no If you want to build the Unreal assemblies (defaults to no)], [], [with_unreal=default]) AC_ARG_WITH(wasm, [ --with-wasm=yes,no If you want to build the WebAssembly (defaults to no)], [], [with_wasm=default]) @@ -949,12 +951,15 @@ with_xammac_default=no with_testing_aot_hybrid_default=no with_testing_aot_full_default=no with_winaot_default=no +with_unityjit_default=no +with_unityaot_default=no with_orbis_default=no with_unreal_default=no with_wasm_default=no with_bitcode_default=no with_cooperative_gc_default=no +mono_feature_disable_com=yes INVARIANT_AOT_OPTIONS=nimt-trampolines=2000,ntrampolines=9000,nrgctx-fetch-trampolines=256,ngsharedvt-trampolines=4000 @@ -972,6 +977,8 @@ elif test x$with_runtime_preset = xall; then with_monotouch_tv_default=yes with_xammac_default=yes with_winaot_default=yes + with_unityjit_default=yes + with_unityaot_default=yes with_orbis_default=yes with_unreal_default=yes with_wasm_default=yes @@ -1034,6 +1041,25 @@ elif test x$with_runtime_preset = xwinaot; then AOT_BUILD_FLAGS="--runtime=mobile --aot=full,$INVARIANT_AOT_OPTIONS" AOT_RUN_FLAGS="--runtime=mobile --full-aot" AOT_MODE="llvmonly" +elif test x$with_runtime_preset = xunityjit; then + DISABLE_MCS_DOCS_default=yes + with_unityjit_default=yes + TEST_PROFILE=unityjit + + mono_feature_disable_remoting='yes' +elif test x$with_runtime_preset = xunityaot; then + DISABLE_MCS_DOCS_default=yes + with_unityaot_default=yes + TEST_PROFILE=unityaot + + #mono_feature_disable_com='yes' + mono_feature_disable_remoting='yes' + mono_feature_disable_reflection_emit_save='yes' + mono_feature_disable_reflection_emit='yes' + mono_feature_disable_appdomains='yes' + + AOT_BUILD_FLAGS="--aot=full,$INVARIANT_AOT_OPTIONS" + AOT_RUN_FLAGS="--full-aot" elif test x$with_runtime_preset = xorbis; then DISABLE_MCS_DOCS_default=yes with_orbis_default=yes @@ -1115,6 +1141,12 @@ fi if test "x$with_winaot" = "xdefault"; then with_winaot=$with_winaot_default fi +if test "x$with_unityjit = "xdefault"; then + with_unityjit=$with_unityjit_default +fi +if test "x$with_unityaot = "xdefault"; then + with_unityaot=$with_unityaot_default +fi if test "x$with_orbis" = "xdefault"; then with_orbis=$with_orbis_default fi @@ -1136,6 +1168,8 @@ AM_CONDITIONAL(INSTALL_XAMMAC, [test "x$with_xammac" != "xno"]) AM_CONDITIONAL(INSTALL_TESTING_AOT_HYBRID, [test "x$with_testing_aot_hybrid" != "xno"]) AM_CONDITIONAL(INSTALL_TESTING_AOT_FULL, [test "x$with_testing_aot_full" != "xno"]) AM_CONDITIONAL(INSTALL_WINAOT, [test "x$with_winaot" != "xno"]) +AM_CONDITIONAL(INSTALL_UNITYJIT, [test "x$with_unityjit" != "xno"]) +AM_CONDITIONAL(INSTALL_UNITYAOT, [test "x$with_unityaot" != "xno"]) AM_CONDITIONAL(INSTALL_ORBIS, [test "x$with_orbis" != "xno"]) AM_CONDITIONAL(INSTALL_UNREAL, [test "x$with_unreal" != "xno"]) AM_CONDITIONAL(INSTALL_WASM, [test "x$with_wasm" != "xno"]) @@ -1161,6 +1195,12 @@ fi if test -z "$INSTALL_WINAOT_TRUE"; then : default_profile=winaot fi +if test -z "$INSTALL_UNITYJIT_TRUE"; then : + default_profile=unityjit +fi +if test -z "$INSTALL_UNITYAOT_TRUE"; then : + default_profile=unityaot +fi if test -z "$INSTALL_ORBIS_TRUE"; then : default_profile=orbis fi @@ -1429,6 +1469,20 @@ AC_COMPILE_IFELSE([ AC_MSG_RESULT(no) ]) +dnl BDWGC GC configuration +dnl + +AC_ARG_ENABLE(bdwgc, [ --disable-bdwgc Disable the Bdwgc GC.], upport_bdwgc=$enableval,support_bdwgc=${support_bdwgc:-yes}) +AM_CONDITIONAL(SUPPORT_BDWGC, test x$support_bdwgc = xyes) +bdwgc_dir=external/bdwgc +BDWGC_DEFINES='-DHAVE_BOEHM_GC -DHAVE_BDWGC_GC' +LIBGCBDWGC_CPPFLAGS='-I$(top_srcdir)/external/bdwgc/include -I$(top_srcdir)/external/bdwgc/libatomic_ops/src' +AC_SUBST(bdwgc_dir) +AC_SUBST(BDWGC_DEFINES) +AC_SUBST(LIBGCBDWGC_CPPFLAGS) + +dnl + dnl dnl Boehm GC configuration dnl @@ -1505,7 +1559,10 @@ if test "x$support_boehm" = "xyes"; then AC_SUBST(LIBGC_STATIC_LIBS) AC_SUBST(libgc_dir) AC_SUBST(BOEHM_DEFINES) - +else + if test "x$support_bdwgc" = "xyes"; then + AC_DEFINE_UNQUOTED(DEFAULT_GC_NAME, "External BDWGC (with typed GC)", [GC description]) + fi fi AM_CONDITIONAL(SUPPORT_NULLGC, test "x$libgc" = "xnone") @@ -4250,6 +4307,11 @@ case "x$libgc" in if test "x$support_boehm" = "xyes"; then AC_CONFIG_SUBDIRS(libgc) fi + if test "x$support_bdwgc" = "xyes"; then + AC_CONFIG_SUBDIRS([external/bdwgc/libatomic_ops]) + ac_configure_args="$ac_configure_args --enable-thread-local-alloc=no --enable-parallel-mark=no --enable-verify-defines=yes --enable-gc-threads=yes --with-libatomic-ops=no --enable-no-threads-discovery=yes --enable-single-obj-compilation=yes --enable-gcj-support=yes --enable-threads=$libgc_threads --enable-munmap=yes --enable-mmap=yes --enable-ignore-dynamic-loading=yes --enable-dont-register-main-static-data=yes" + AC_CONFIG_SUBDIRS([external/bdwgc]) + fi ;; esac @@ -4925,6 +4987,8 @@ echo " Xamarin.TVOS: $with_monotouch_tv Xamarin.Mac: $with_xammac Windows AOT: $with_winaot + Unity JIT: $with_unityjit + Unity AOT: $with_unityaot Orbis: $with_orbis Unreal: $with_unreal WebAssembly: $with_wasm diff --git a/data/net_2_0/machine.config b/data/net_2_0/machine.config index 2f8090f02884..9da7be987191 100644 --- a/data/net_2_0/machine.config +++ b/data/net_2_0/machine.config @@ -118,6 +118,9 @@ + + + diff --git a/data/net_4_0/machine.config b/data/net_4_0/machine.config index 30bc2105f3af..12839c1f6a3c 100644 --- a/data/net_4_0/machine.config +++ b/data/net_4_0/machine.config @@ -135,6 +135,9 @@ + + + diff --git a/data/net_4_5/machine.config b/data/net_4_5/machine.config index d17369394e31..61f7889871f8 100644 --- a/data/net_4_5/machine.config +++ b/data/net_4_5/machine.config @@ -138,6 +138,9 @@ + + + diff --git a/external/bdwgc b/external/bdwgc new file mode 160000 index 000000000000..8440aa8cdffd --- /dev/null +++ b/external/bdwgc @@ -0,0 +1 @@ +Subproject commit 8440aa8cdffda0b9aa324a0e63f950f05551ab27 diff --git a/external/binary-reference-assemblies b/external/binary-reference-assemblies index 9f07d0746d94..e048fe4a88d2 160000 --- a/external/binary-reference-assemblies +++ b/external/binary-reference-assemblies @@ -1 +1 @@ -Subproject commit 9f07d0746d94d2c2b055e3e689814ca07431e5fd +Subproject commit e048fe4a88d237d105ae02fe0363a68296099362 diff --git a/external/buildscripts/add_to_build_results/monodistribution/bin/cli b/external/buildscripts/add_to_build_results/monodistribution/bin/cli new file mode 100755 index 000000000000..a8360f862951 --- /dev/null +++ b/external/buildscripts/add_to_build_results/monodistribution/bin/cli @@ -0,0 +1,5 @@ +#!/bin/bash +. $(dirname $0)/mono-env + +$MONO "$@" + diff --git a/external/buildscripts/add_to_build_results/monodistribution/bin/cli.bat b/external/buildscripts/add_to_build_results/monodistribution/bin/cli.bat new file mode 100644 index 000000000000..685963d34fc1 --- /dev/null +++ b/external/buildscripts/add_to_build_results/monodistribution/bin/cli.bat @@ -0,0 +1,7 @@ +@echo off +SETLOCAL +set MONO_PREFIX=%~dp0.. +set MONO=%MONO_PREFIX%\bin\mono +"%MONO%" %* +exit /b %ERRORLEVEL% +ENDLOCAL diff --git a/external/buildscripts/add_to_build_results/monodistribution/bin/cli_x86 b/external/buildscripts/add_to_build_results/monodistribution/bin/cli_x86 new file mode 100755 index 000000000000..de796470ff8b --- /dev/null +++ b/external/buildscripts/add_to_build_results/monodistribution/bin/cli_x86 @@ -0,0 +1,4 @@ +#!/bin/bash +. $(dirname $0)/mono-env + +arch -i386 $MONO "$@" diff --git a/external/buildscripts/add_to_build_results/monodistribution/bin/ilasm b/external/buildscripts/add_to_build_results/monodistribution/bin/ilasm new file mode 100755 index 000000000000..c7e0afc7f7c8 --- /dev/null +++ b/external/buildscripts/add_to_build_results/monodistribution/bin/ilasm @@ -0,0 +1,3 @@ +#!/bin/bash +. $(dirname $0)/mono-env +exec $MONO $MONO_OPTIONS $MONO_PREFIX/lib/mono/4.5/ilasm.exe "$@" diff --git a/external/buildscripts/add_to_build_results/monodistribution/bin/ilasm.bat b/external/buildscripts/add_to_build_results/monodistribution/bin/ilasm.bat new file mode 100644 index 000000000000..3b3e4635ee56 --- /dev/null +++ b/external/buildscripts/add_to_build_results/monodistribution/bin/ilasm.bat @@ -0,0 +1,2 @@ +@"%~dp0cli.bat" %MONO_OPTIONS% "%~dp0..\lib\mono\4.5\ilasm.exe" %* +exit /b %ERRORLEVEL% diff --git a/external/buildscripts/add_to_build_results/monodistribution/bin/mcs b/external/buildscripts/add_to_build_results/monodistribution/bin/mcs new file mode 100755 index 000000000000..7a48ace18cea --- /dev/null +++ b/external/buildscripts/add_to_build_results/monodistribution/bin/mcs @@ -0,0 +1,3 @@ +#!/bin/bash +. $(dirname $0)/mono-env +exec $MONO $MONO_OPTIONS $MONO_PREFIX/lib/mono/4.5/mcs.exe "$@" diff --git a/external/buildscripts/add_to_build_results/monodistribution/bin/mcs.bat b/external/buildscripts/add_to_build_results/monodistribution/bin/mcs.bat new file mode 100644 index 000000000000..3ef693d443d3 --- /dev/null +++ b/external/buildscripts/add_to_build_results/monodistribution/bin/mcs.bat @@ -0,0 +1,2 @@ +@"%~dp0cli.bat" %MONO_OPTIONS% "%~dp0..\lib\mono\4.5\mcs.exe" %* +exit /b %ERRORLEVEL% diff --git a/external/buildscripts/add_to_build_results/monodistribution/bin/mono-env b/external/buildscripts/add_to_build_results/monodistribution/bin/mono-env new file mode 100755 index 000000000000..46c41b4744ff --- /dev/null +++ b/external/buildscripts/add_to_build_results/monodistribution/bin/mono-env @@ -0,0 +1,7 @@ +. $(dirname $0)/monobin-env + +export MONO_PREFIX=$(dirname $0)/.. +MONO=$MONO_PREFIX/$MONOBINDIR/mono +# remove //.. pattern as it causes problem on OSX High Sierra +MONO=${MONO/\/\/\./\/\.} +export LD_LIBRARY_PATH=$MONO_PREFIX/lib diff --git a/external/buildscripts/add_to_build_results/monodistribution/bin/monobin-env b/external/buildscripts/add_to_build_results/monodistribution/bin/monobin-env new file mode 100644 index 000000000000..9b85997c3927 --- /dev/null +++ b/external/buildscripts/add_to_build_results/monodistribution/bin/monobin-env @@ -0,0 +1,14 @@ +MONOBINDIR=bin + +os=$(uname -a) +variant=$(uname -m) + +case "$os" in + *GNU/Linux* ) + if [ "$variant" = "x86_64" ]; then + MONOBINDIR=bin-linux64 + else + MONOBINDIR=bin-linux32 + fi + ;; +esac diff --git a/external/buildscripts/add_to_build_results/monodistribution/bin/monolinker b/external/buildscripts/add_to_build_results/monodistribution/bin/monolinker new file mode 100755 index 000000000000..4da80a1bc55b --- /dev/null +++ b/external/buildscripts/add_to_build_results/monodistribution/bin/monolinker @@ -0,0 +1,5 @@ +#!/bin/bash +. $(dirname $0)/mono-env + +$MONO $MONO_PATH/monolinker.exe "$@" + diff --git a/external/buildscripts/add_to_build_results/monodistribution/bin/monolinker.bat b/external/buildscripts/add_to_build_results/monodistribution/bin/monolinker.bat new file mode 100644 index 000000000000..013920349f82 --- /dev/null +++ b/external/buildscripts/add_to_build_results/monodistribution/bin/monolinker.bat @@ -0,0 +1,2 @@ +@"%~dp0cli.bat" %MONO_OPTIONS% "%~dp0..\lib\mono\2.0\monolinker.exe" %* +exit /b %ERRORLEVEL% diff --git a/external/buildscripts/add_to_build_results/monodistribution/bin/nunit-console b/external/buildscripts/add_to_build_results/monodistribution/bin/nunit-console new file mode 100755 index 000000000000..1a72b09096ed --- /dev/null +++ b/external/buildscripts/add_to_build_results/monodistribution/bin/nunit-console @@ -0,0 +1,5 @@ +#!/bin/bash +. $(dirname $0)/mono-env + +$MONO --debug $MONO_PREFIX/lib/mono/4.0/nunit-console.exe "$@" + diff --git a/external/buildscripts/add_to_build_results/monodistribution/bin/nunit-console.bat b/external/buildscripts/add_to_build_results/monodistribution/bin/nunit-console.bat new file mode 100644 index 000000000000..c21335b65c09 --- /dev/null +++ b/external/buildscripts/add_to_build_results/monodistribution/bin/nunit-console.bat @@ -0,0 +1,2 @@ +@"%~dp0cli.bat" %MONO_OPTIONS% --debug "%~dp0..\lib\mono\4.0\nunit-console.exe" %* +exit /b %ERRORLEVEL% diff --git a/external/buildscripts/add_to_build_results/monodistribution/bin/nunit-console2 b/external/buildscripts/add_to_build_results/monodistribution/bin/nunit-console2 new file mode 100755 index 000000000000..17db31ffd0b8 --- /dev/null +++ b/external/buildscripts/add_to_build_results/monodistribution/bin/nunit-console2 @@ -0,0 +1,5 @@ +#!/bin/bash +. $(dirname $0)/mono-env + +$MONO --debug $MONO_PREFIX/lib/mono/2.0/nunit-console.exe "$@" + diff --git a/external/buildscripts/add_to_build_results/monodistribution/bin/resgen2 b/external/buildscripts/add_to_build_results/monodistribution/bin/resgen2 new file mode 100755 index 000000000000..20d79ca7d3bd --- /dev/null +++ b/external/buildscripts/add_to_build_results/monodistribution/bin/resgen2 @@ -0,0 +1,5 @@ +#!/bin/bash +. $(dirname $0)/mono-env + +$MONO $MONO_PREFIX/lib/mono/4.5/resgen.exe "$@" + diff --git a/external/buildscripts/add_to_build_results/monodistribution/bin/resgen2.bat b/external/buildscripts/add_to_build_results/monodistribution/bin/resgen2.bat new file mode 100644 index 000000000000..c3ec2fbb896a --- /dev/null +++ b/external/buildscripts/add_to_build_results/monodistribution/bin/resgen2.bat @@ -0,0 +1,2 @@ +@"%~dp0cli.bat" %MONO_OPTIONS% "%~dp0..\lib\mono\4.5\resgen.exe" %* +exit /b %ERRORLEVEL% diff --git a/external/buildscripts/add_to_build_results/monodistribution/bin/xbuild b/external/buildscripts/add_to_build_results/monodistribution/bin/xbuild new file mode 100755 index 000000000000..60ba18fe8bec --- /dev/null +++ b/external/buildscripts/add_to_build_results/monodistribution/bin/xbuild @@ -0,0 +1,5 @@ +#!/bin/bash +. $(dirname $0)/mono-env + +$MONO $MONO_PREFIX/lib/mono/4.5/xbuild.exe "$@" + diff --git a/external/buildscripts/add_to_build_results/monodistribution/bin/xbuild.bat b/external/buildscripts/add_to_build_results/monodistribution/bin/xbuild.bat new file mode 100644 index 000000000000..50b3a8e44997 --- /dev/null +++ b/external/buildscripts/add_to_build_results/monodistribution/bin/xbuild.bat @@ -0,0 +1,2 @@ +@"%~dp0cli.bat" %MONO_OPTIONS% "%~dp0..\lib\mono\4.5\xbuild.exe" %* +exit /b %ERRORLEVEL% diff --git a/external/buildscripts/build.pl b/external/buildscripts/build.pl new file mode 100644 index 000000000000..7b05e3d2ecae --- /dev/null +++ b/external/buildscripts/build.pl @@ -0,0 +1,1781 @@ +use Cwd; +use Cwd 'abs_path'; +use Getopt::Long; +use File::Basename; +use File::Path; +use lib ('external/buildscripts', "../../Tools/perl_lib","perl_lib", 'external/buildscripts/perl_lib'); +use Tools qw(InstallNameTool); + +print ">>> PATH in Build All = $ENV{PATH}\n\n"; + +my $currentdir = getcwd(); + +my $monoroot = File::Spec->rel2abs(dirname(__FILE__) . "/../.."); +my $monoroot = abs_path($monoroot); + +my $buildscriptsdir = "$monoroot/external/buildscripts"; +my $addtoresultsdistdir = "$buildscriptsdir/add_to_build_results/monodistribution"; +my $buildsroot = "$monoroot/builds"; +my $includesroot = "$buildsroot/include"; +my $sourcesroot = "$buildsroot/source"; +my $distdir = "$buildsroot/monodistribution"; +my $buildMachine = $ENV{UNITY_THISISABUILDMACHINE}; + +# This script should not be ran on windows, if it is, kindly call the wrapper +# to switch over to cygwin +if ($^O eq "MSWin32") +{ + print(">>> build.pl called from Windows. Switching over to cygwin\n"); + system("perl", "$buildscriptsdir/build_win_wrapper.pl", @ARGV) eq 0 or die("\n"); + exit 0; +} + +system("source","~/.profile"); + +my $build=0; +my $clean=0; +my $jobs=8; +my $test=0; +my $artifact=0; +my $debug=0; +my $disableMcs=0; +my $mcsOnly=0; +my $buildUsAndBoo=0; +my $artifactsCommon=0; +my $artifactsRuntime=1; +my $runRuntimeTests=1; +my $runClasslibTests=1; +my $checkoutOnTheFly=0; +my $forceDefaultBuildDeps=0; +my $existingMonoRootPath = ''; +my $sdk = ''; +my $arch32 = 0; +my $winPerl = ""; +my $winMonoRoot = ""; +my $msBuildVersion = "14.0"; +my $buildDeps = ""; +my $android=0; +my $androidArch = ""; +my $iphone=0; +my $iphoneArch = ""; +my $iphoneCross=0; +my $iphoneSimulator=0; +my $iphoneSimulatorArch=""; +my $tizen=0; +my $tizenEmulator=0; +my $windowsSubsystemForLinux=0; + +# Handy troubleshooting/niche options +my $skipMonoMake=0; + +# The prefix hack probably isn't needed anymore. Let's disable it by default and see how things go +my $shortPrefix=1; + +# Disabled by default for now. causes more problems than it's worth when actively making changes to the build scripts. +# Would be okay to turn on once the build scripts stabilize and you just want to rebuild code changes +my $enableCacheFile=0; + +# Linux toolchain setup needs this +my @commandPrefix = (); + +print(">>> Build All Args = @ARGV\n"); + +GetOptions( + 'build=i'=>\$build, + 'clean=i'=>\$clean, + 'test=i'=>\$test, + 'artifact=i'=>\$artifact, + 'artifactscommon=i'=>\$artifactsCommon, + 'artifactsruntime=i'=>\$artifactsRuntime, + 'debug=i'=>\$debug, + 'disablemcs=i'=>\$disableMcs, + 'mcsonly=i'=>\$mcsOnly, + 'buildusandboo=i'=>\$buildUsAndBoo, + 'runtimetests=i'=>\$runRuntimeTests, + 'classlibtests=i'=>\$runClasslibTests, + 'arch32=i'=>\$arch32, + 'jobs=i'=>\$jobs, + 'sdk=s'=>\$sdk, + 'existingmono=s'=>\$existingMonoRootPath, + 'skipmonomake=i'=>\$skipMonoMake, + 'shortprefix=i'=>\$shortPrefix, + 'winperl=s'=>\$winPerl, + 'winmonoroot=s'=>\$winMonoRoot, + 'msbuildversion=s'=>\$msBuildVersion, + 'checkoutonthefly=i'=>\$checkoutOnTheFly, + 'builddeps=s'=>\$buildDeps, + 'forcedefaultbuilddeps=i'=>\$forceDefaultBuildDeps, + 'android=i'=>\$android, + 'androidarch=s'=>\$androidArch, + 'iphone=i'=>\$iphone, + 'iphonearch=s'=>\$iphoneArch, + 'iphonecross=i'=>\$iphoneCross, + 'iphonesimulator=i'=>\$iphoneSimulator, + 'tizen=i'=>\$tizen, + 'tizenemulator=i'=>\$tizenEmulator, + 'windowssubsystemforlinux=i'=>\$windowsSubsystemForLinux, + 'enablecachefile=i'=>\$enableCacheFile, +) or die ("illegal cmdline options"); + +print ">>> Mono checkout = $monoroot\n"; + +print(">> System Info : \n"); +system("uname", "-a"); + +my $monoRevision = `git rev-parse HEAD`; +chdir("$buildscriptsdir") eq 1 or die ("failed to chdir : $buildscriptsdir\n"); +my $buildScriptsRevision = `git rev-parse HEAD`; +chdir("$monoroot") eq 1 or die ("failed to chdir : $monoroot\n"); + +print(">>> Mono Revision = $monoRevision\n"); +print(">>> Build Scripts Revision = $buildScriptsRevision\n"); + +if ($androidArch ne "") +{ + $android = 1; +} + +if ($iphoneArch ne "") +{ + $iphone = 1; +} + +if($iphoneSimulator) +{ + if ($arch32) + { + $iphoneSimulatorArch = "i386"; + } + else + { + $iphoneSimulatorArch = "x86_64"; + } +} + +my $isDesktopBuild = 1; +if ($android || $iphone || $iphoneCross || $iphoneSimulator || $tizen || $tizenEmulator) +{ + $isDesktopBuild = 0; + + # Disable building of the class libraries by default when building the android runtime + # since we don't care about a class library build in this situation (as of writing this at least) + # but only if the test flag is not set. If the test flag was set, we'd need to build the classlibs + # in order to run the tests + $disableMcs = 1 if(!($test)); +} + +# Do any settings agnostic per-platform stuff +my $externalBuildDeps = ""; + +if ($buildDeps ne "" && not $forceDefaultBuildDeps) +{ + $externalBuildDeps = $buildDeps; +} +else +{ + $externalBuildDeps = "$monoroot/../../mono-build-deps/build"; +} + +# Only clean up the path if the directory exists, if it doesn't exist, +# abs_path ends up returning an empty string +$externalBuildDeps = abs_path($externalBuildDeps) if (-d $externalBuildDeps); + +my $existingExternalMonoRoot = "$externalBuildDeps/MonoBleedingEdge"; +my $existingExternalMono = ""; +my $existingExternalMonoBinDir = ""; +my $monoHostArch = ""; +my $monoprefix = "$monoroot/tmp"; +my $runningOnWindows=0; +if($^O eq "linux") +{ + $monoHostArch = $arch32 ? "i686" : "x86_64"; + $existingExternalMono = "$existingExternalMonoRoot"; + $existingExternalMonoBinDir = "bin-linux64"; +} +elsif($^O eq 'darwin') +{ + $monoHostArch = $arch32 ? "i386" : "x86_64"; + $existingExternalMono = "$existingExternalMonoRoot"; + $existingExternalMonoBinDir = "bin"; + + # From Massi: I was getting failures in install_name_tool about space + # for the commands being too small, and adding here things like + # $ENV{LDFLAGS} = '-headerpad_max_install_names' and + # $ENV{LDFLAGS} = '-headerpad=0x40000' did not help at all (and also + # adding them to our final gcc invocation to make the bundle). + # Lucas noticed that I was lacking a Mono prefix, and having a long + # one would give us space, so here is this silly looong prefix. + if (not $shortPrefix) + { + $monoprefix = "$monoroot/tmp/scripting/scripting/scripting/scripting/scripting/scripting/scripting/scripting/scripting/scripting/scripting/scripting/scripting/scripting/scripting/scripting/scripting/scripting/scripting/scripting"; + } +} +else +{ + $monoHostArch = "i686"; + $existingExternalMono = "$existingExternalMonoRoot"; + $existingExternalMonoBinDir = "bin-x64"; + $runningOnWindows = 1; + + # We only care about an existing mono if we need to build. + # So only do this path clean up if we are building. + if ($build) + { + if ($existingMonoRootPath ne "" && not $existingMonoRootPath =~ /^\/cygdrive/) + { + $existingMonoRootPath = `cygpath -u $existingMonoRootPath`; + chomp($existingMonoRootPath); + } + + $existingMonoRootPath =~ tr/\\//d; + } +} + +if ($runningOnWindows) +{ + # Fixes a line ending issue that happens on windows when we try to run autogen.sh + $ENV{'SHELLOPTS'} = "igncr"; +} + +print(">>> Existing Mono = $existingMonoRootPath\n"); +print(">>> Mono Arch = $monoHostArch\n"); + +if ($build) +{ + my $platformflags = ''; + my $host = ''; + my $mcs = ''; + + my $iphoneCrossAbi = "arm-apple-darwin10"; + my $iphoneCrossMonoBinToUse = "$monoroot/builds/monodistribution/bin"; + + my @configureparams = (); + + push @configureparams, "--disable-mcs-build" if($disableMcs); + push @configureparams, "--with-glib=embedded"; + push @configureparams, "--disable-nls"; #this removes the dependency on gettext package + push @configureparams, "--disable-btls"; #this removes the dependency on cmake to build btls for now + push @configureparams, "--with-mcs-docs=no"; + push @configureparams, "--prefix=$monoprefix"; + + if(!($disableMcs)) + { + push @configureparams, "--with-unityjit=yes"; + push @configureparams, "--with-unityaot=yes"; + } + + if ($isDesktopBuild) + { + push @configureparams, "--with-monotouch=no"; + } + + if ($existingMonoRootPath eq "") + { + print(">>> No existing mono supplied. Checking for external...\n"); + + if (!(-d "$externalBuildDeps")) + { + if (not $checkoutonthefly) + { + print(">>> No external build deps found. Might as well try to check them out. If it fails, we'll continue and trust mono is in your PATH\n"); + } + + # Check out on the fly + print(">>> Checking out mono build dependencies to : $externalBuildDeps\n"); + my $repo = "https://ono.unity3d.com/unity-extra/mono-build-deps"; + print(">>> Cloning $repo at $externalBuildDeps\n"); + my $checkoutResult = system("hg", "clone", $repo, "$externalBuildDeps"); + + if ($checkoutOnTheFly && $checkoutResult ne 0) + { + die("failed to checkout mono build dependencies\n"); + } + + # Only clean up if the dir exists. Otherwise abs_path will return empty string + $externalBuildDeps = abs_path($externalBuildDeps) if (-d $externalBuildDeps); + } + + if (-d "$existingExternalMono") + { + print(">>> External mono found at : $existingExternalMono\n"); + + if (-d "$existingExternalMono/builds") + { + print(">>> Mono already extracted at : $existingExternalMono/builds\n"); + } + + if (!(-d "$existingExternalMono/builds")) + { + # We need to extract builds.zip + print(">>> Extracting mono builds.zip...\n"); + system("unzip", "$existingExternalMono/builds.zip", "-d", "$existingExternalMono/builds") eq 0 or die("failed to extract mono builds.zip\n"); + } + + $existingMonoRootPath = "$existingExternalMono/builds/monodistribution"; + } + else + { + print(">>> No external mono found. Trusting a new enough mono is in your PATH.\n"); + } + } + + if ($existingMonoRootPath ne "" && !(-d $existingMonoRootPath)) + { + die("Existing mono not found at : $existingMonoRootPath\n"); + } + + if ($externalBuildDeps ne "") + { + print "\n"; + print ">>> Building autoconf, texinfo, automake, and libtool if needed...\n"; + my $autoconfVersion = "2.69"; + my $texinfoVersion = "4.8"; + my $automakeVersion = "1.15"; + my $libtoolVersion = "2.4.6"; + my $autoconfDir = "$externalBuildDeps/autoconf-$autoconfVersion"; + my $texinfoDir = "$externalBuildDeps/texinfo-$texinfoVersion"; + my $automakeDir = "$externalBuildDeps/automake-$automakeVersion"; + my $libtoolDir = "$externalBuildDeps/libtool-$libtoolVersion"; + my $builtToolsDir = "$externalBuildDeps/built-tools"; + + $ENV{PATH} = "$builtToolsDir/bin:$ENV{PATH}"; + + if (!(-d "$autoconfDir")) + { + chdir("$externalBuildDeps") eq 1 or die ("failed to chdir to external directory\n"); + system("tar xzf autoconf-$autoconfVersion.tar.gz") eq 0 or die ("failed to extract autoconf\n"); + + chdir("$autoconfDir") eq 1 or die ("failed to chdir to autoconf directory\n"); + system("./configure --prefix=$builtToolsDir") eq 0 or die ("failed to configure autoconf\n"); + system("make") eq 0 or die ("failed to make autoconf\n"); + system("make install") eq 0 or die ("failed to make install autoconf\n"); + + chdir("$monoroot") eq 1 or die ("failed to chdir to $monoroot\n"); + } + + if (!(-d "$texinfoDir") and $windowsSubsystemForLinux) + { + chdir("$externalBuildDeps") eq 1 or die ("failed to chdir to external directory\n"); + system("tar xzf texinfo-$texinfoVersion.tar.gz") eq 0 or die ("failed to extract texinfo\n"); + + chdir($texinfoDir) eq 1 or die ("failed to chdir to texinfo directory\n"); + system("./configure --prefix=$builtToolsDir") eq 0 or die ("failed to configure texinfo\n"); + system("make") eq 0 or die ("failed to make texinfo\n"); + system("make install") eq 0 or die ("failed to make install texinfo\n"); + + chdir("$monoroot") eq 1 or die ("failed to chdir to $monoroot\n"); + } + + if (!(-d "$automakeDir")) + { + my $automakeMakeFlags = ""; + chdir("$externalBuildDeps") eq 1 or die ("failed to chdir to external directory\n"); + system("tar xzf automake-$automakeVersion.tar.gz") eq 0 or die ("failed to extract automake\n"); + + chdir("$automakeDir") eq 1 or die ("failed to chdir to automake directory\n"); + if($windowsSubsystemForLinux) + { + #Windows subsystem needs to run bootstrap, and make needs to be run with -i due to one doc failing to build + system("./bootstrap.sh") eq 0 or die ("failed to bootstrap automake\n"); + $automakeMakeFlags = "-i"; + } + system("./configure --prefix=$builtToolsDir") eq 0 or die ("failed to configure automake\n"); + system("make $automakeMakeFlags") eq 0 or die ("failed to make automake\n"); + system("make install"); + chdir("$monoroot") eq 1 or die ("failed to chdir to $monoroot\n"); + } + + if (!(-d "$libtoolDir")) + { + chdir("$externalBuildDeps") eq 1 or die ("failed to chdir to external directory\n"); + system("tar xzf libtool-$libtoolVersion.tar.gz") eq 0 or die ("failed to extract libtool\n"); + + chdir("$libtoolDir") eq 1 or die ("failed to chdir to libtool directory\n"); + system("./configure --prefix=$builtToolsDir") eq 0 or die ("failed to configure libtool\n"); + system("make") eq 0 or die ("failed to make libtool\n"); + system("make install") eq 0 or die ("failed to make install libtool\n"); + + chdir("$monoroot") eq 1 or die ("failed to chdir to $monoroot\n"); + } + + $ENV{'LIBTOOLIZE'} = "$builtToolsDir/bin/libtoolize"; + $ENV{'LIBTOOL'} = "$builtToolsDir/bin/libtool"; + } + + my $macSdkPath = ""; + my $macversion = '10.8'; + my $darwinVersion = "10"; + if ($^O eq 'darwin') + { + if ($sdk eq '') + { + $sdk='10.11'; + } + + my $macBuildEnvDir = "$externalBuildDeps/MacBuildEnvironment"; + $macSdkPath = "$macBuildEnvDir/builds/MacOSX$sdk.sdk"; + if (! -d $macSdkPath) + { + print(">>> Unzipping mac build toolchain\n"); + system("$externalBuildDeps/unzip", '-qd', "$macBuildEnvDir", "$macBuildEnvDir/builds.zip") eq 0 or die ("failed unzipping mac build toolchain\n"); + } + } + + if ($iphone || $iphoneSimulator) + { + if ($runningOnWindows) + { + die("This build is not supported on Windows\n"); + } + + my $iosBuildEnvDir = "$externalBuildDeps/iOSBuildEnvironment"; + my $iosXcodeDefaultToolchainRoot = "$iosBuildEnvDir/builds/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain"; + + if (! -d "$iosBuildEnvDir/builds") + { + print(">>> Unzipping ios build toolchain\n"); + system("$externalBuildDeps/unzip", '-qd', "$iosBuildEnvDir/builds", "$iosBuildEnvDir/builds.zip") eq 0 or die ("failed unzipping ios build toolchain\n"); + } + + $ENV{PATH} = "$iosXcodeDefaultToolchainRoot/usr/bin:$iosBuildEnvDir/builds/Xcode.app/Contents/Developer/usr/bin:$ENV{PATH}"; + # Need to keep our libtool in front + $ENV{PATH} = "$externalBuildDeps/built-tools/bin:$ENV{PATH}"; + + push @configureparams, "--cache-file=iphone-$iphoneArch.cache" if ($enableCacheFile); + + my $iosMinimalCommon = "com,remoting,shared_perfcounters,appdomains"; + my $iosCFlagsCommon = "-DMONOTOUCH -DHOST_IOS -DDISABLE_POLICY_EVIDENCE=1 -DDISABLE_PROCESS_HANDLING=1"; + + push @configureparams, "--with-tls=pthread"; + push @configureparams, "--without-ikvm-native"; + push @configureparams, "--disable-executables"; + push @configureparams, "--disable-visibility-hidden"; + + if ($iphone) + { + my $iosSdkVersion = "9.3"; + my $iphoneOsMinVersion = "3.0"; + my $iosSdkRoot = "$iosBuildEnvDir/builds/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS$iosSdkVersion.sdk"; + + print(">>> iOS Build Environment = $iosBuildEnvDir\n"); + print(">>> iOS SDK Version = $iosSdkVersion\n"); + print(">>> iOS SDK Root = $iosSdkRoot\n"); + print(">>> iPhone Arch = $iphoneArch\n"); + + $ENV{PATH} = "$iosSdkRoot/usr/bin:$ENV{PATH}"; + + $ENV{C_INCLUDE_PATH} = "$iosSdkRoot/usr/include"; + $ENV{CPLUS_INCLUDE_PATH} = "$iosSdkRoot/usr/include"; + + $ENV{CC} = "$iosBuildEnvDir/builds/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang -arch $iphoneArch"; + $ENV{CXX} = "$iosBuildEnvDir/builds/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang++ -arch $iphoneArch"; + $ENV{LD} = "$iosBuildEnvDir/builds/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/ld"; + + $ENV{CFLAGS} = "$iosCFlagsCommon -gdwarf-2 -DSMALL_CONFIG -DHAVE_LARGE_FILE_SUPPORT=1 -DHAVE_ARMV6=1 -DARM_FPU_VFP=1 -Wl,-application_extension -miphoneos-version-min=$iphoneOsMinVersion -mno-thumb -Os -isysroot $iosSdkRoot"; + + # Unity defines + $ENV{CFLAGS} = "-DPLATFORM_IPHONE $ENV{CFLAGS}"; + + $ENV{CXXFLAGS} = "$ENV{CFLAGS} -U__powerpc__ -U__i386__ -D__arm__"; + $ENV{CPPFLAGS} = $ENV{CXXFLAGS}; + + $ENV{LDFLAGS} = "-arch $iphoneArch -liconv -lobjc -lc++ -Wl,-syslibroot,$iosSdkRoot"; + + print "\n"; + print ">>> Environment:\n"; + print ">>> \tCC = $ENV{CC}\n"; + print ">>> \tCXX = $ENV{CXX}\n"; + print ">>> \tLD = $ENV{LD}\n"; + print ">>> \tCFLAGS = $ENV{CFLAGS}\n"; + print ">>> \tCXXFLAGS = $ENV{CXXFLAGS}\n"; + print ">>> \tCPPFLAGS = $ENV{CPPFLAGS}\n"; + print ">>> \tLDFLAGS = $ENV{LDFLAGS}\n"; + print ">>> \tCPLUS_INCLUDE_PATH = $ENV{CPLUS_INCLUDE_PATH}\n"; + print ">>> \tC_INCLUDE_PATH = $ENV{C_INCLUDE_PATH}\n"; + + push @configureparams, "--host=arm-apple-darwin$darwinVersion"; + + push @configureparams, "--with-sigaltstack=no"; + push @configureparams, "--disable-shared-handles"; + push @configureparams, "--with-monotouch"; + + push @configureparams, "--enable-llvm-runtime"; + push @configureparams, "--with-bitcode=yes"; + + push @configureparams, "--with-lazy-gc-thread-creation=yes"; + push @configureparams, "--enable-icall-export"; + push @configureparams, "--enable-dtrace=no"; + + push @configureparams, "--enable-minimal=$iosMinimalCommon,ssa,jit,reflection_emit_save,reflection_emit,portability,assembly_remapping,attach,verifier,full_messages,security,sgen_remset,sgen_marksweep_par,sgen_marksweep_fixed,sgen_marksweep_fixed_par,sgen_copying,logging"; + + push @configureparams, "mono_cv_uscore=yes"; + push @configureparams, "cv_mono_sizeof_sunpath=104"; + push @configureparams, "ac_cv_func_posix_getpwuid_r=yes"; + push @configureparams, "ac_cv_func_backtrace_symbols=no"; + push @configureparams, "ac_cv_func_finite=no"; + push @configureparams, "ac_cv_header_curses_h=no"; + } + elsif ($iphoneSimulator) + { + my $iosSdkVersion = "9.3"; + my $iosSimMinVersion = "4.3"; + my $iosSdkRoot = "$iosBuildEnvDir/builds/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator$iosSdkVersion.sdk"; + + print(">>> iOS Sim Build Environment = $iosBuildEnvDir\n"); + print(">>> iOS Sim SDK Version = $iosSdkVersion\n"); + print(">>> iOS Sim SDK Root = $iosSdkRoot\n"); + print(">>> iOS Sim Arch = $iphoneSimulatorArch\n"); + + $ENV{PATH} = "$iosSdkRoot/usr/bin:$ENV{PATH}"; + + $ENV{MACSDKOPTIONS} = "$iosCFlagsCommon -D_XOPEN_SOURCE=1 -g -O0 -DTARGET_IPHONE_SIMULATOR -mios-simulator-version-min=$iosSimMinVersion -isysroot $iosSdkRoot"; + $ENV{CFLAGS} = "-arch $iphoneSimulatorArch $ENV{MACSDKOPTIONS}"; + $ENV{CXXFLAGS} = "$ENV{CFLAGS}"; + $ENV{CPPFLAGS} = "$ENV{CFLAGS}"; + $ENV{CC} = "$iosBuildEnvDir/builds/Xcode.app/Contents/Developer/usr/bin/gcc"; + $ENV{CXX} = "$iosBuildEnvDir/builds/Xcode.app/Contents/Developer/usr/bin/g++"; + + print "\n"; + print ">>> Environment:\n"; + print ">>> \tCC = $ENV{CC}\n"; + print ">>> \tCXX = $ENV{CXX}\n"; + print ">>> \tLD = $ENV{LD}\n"; + print ">>> \tCFLAGS = $ENV{CFLAGS}\n"; + print ">>> \tCXXFLAGS = $ENV{CXXFLAGS}\n"; + print ">>> \tCPPFLAGS = $ENV{CPPFLAGS}\n"; + print ">>> \tMACSDKOPTIONS = $ENV{MACSDKOPTIONS}\n"; + + push @configureparams, "--host=$iphoneSimulatorArch-apple-darwin$darwinVersion"; + push @configureparams, "--enable-minimal=$iosMinimalCommon"; + + push @configureparams, "mono_cv_uscore=yes"; + push @configureparams, "ac_cv_func_clock_nanosleep=no"; + } + else + { + die("This should not be hit\n"); + } + } + elsif ($iphoneCross) + { + if ($runningOnWindows) + { + die("Not implemented\n"); + } + else + { + $ENV{CFLAGS} = "-DMONOTOUCH -DARM_FPU_VFP=1 -DUSE_MUNMAP -DPLATFORM_IPHONE_XCOMP -mmacosx-version-min=$macversion"; + $ENV{CXXFLAGS} = "-mmacosx-version-min=$macversion -stdlib=libc++"; + $ENV{CPPFLAGS} = "$ENV{CFLAGS} -mmacosx-version-min=$macversion"; + + $ENV{CC} = "$macSdkPath/../usr/bin/clang -arch i386"; + $ENV{CXX} = "$macSdkPath/../usr/bin/clang++ -arch i386"; + $ENV{CPP} = "$ENV{CC} -E"; + $ENV{LD} = $ENV{CC}; + $ENV{LDFLAGS} = "-stdlib=libc++"; + $ENV{MACSDKOPTIONS} = "-mmacosx-version-min=$macversion -isysroot $macSdkPath"; + + print "\n"; + print ">>> Environment:\n"; + print ">>> \tCC = $ENV{CC}\n"; + print ">>> \tCXX = $ENV{CXX}\n"; + print ">>> \tLD = $ENV{LD}\n"; + print ">>> \tCFLAGS = $ENV{CFLAGS}\n"; + print ">>> \tCXXFLAGS = $ENV{CXXFLAGS}\n"; + print ">>> \tCPPFLAGS = $ENV{CPPFLAGS}\n"; + print ">>> \tLDFLAGS = $ENV{LDFLAGS}\n"; + print ">>> \tMACSDKOPTIONS = $ENV{MACSDKOPTIONS}\n"; + + push @configureparams, "--cache-file=iphone-cross.cache" if ($enableCacheFile); + + push @configureparams, "--with-sigaltstack=no"; + push @configureparams, "--disable-shared-handles"; + push @configureparams, "--with-tls=pthread"; + + push @configureparams, "--target=arm-darwin"; + push @configureparams, "--with-macversion=$macversion"; + push @configureparams, "--with-cross-offsets=$iphoneCrossAbi.h"; + + push @configureparams, "--build=i386-apple-darwin10"; + push @configureparams, "--disable-libraries"; + push @configureparams, "--enable-icall-symbol-map"; + push @configureparams, "--enable-minimal=com,remoting"; + + #push @configureparams, "--enable-llvm"; + #push @configureparams, "--with-llvm=llvm/usr"; + + my @mcsArgs = (); + push @mcsArgs, "$monoroot/tools/offsets-tool/MonoAotOffsetsDumper.cs"; + push @mcsArgs, "$monoroot/mcs/class/Mono.Options/Mono.Options/Options.cs"; + push @mcsArgs, "/r:$externalBuildDeps/CppSharpBinaries/CppSharp.AST.dll"; + push @mcsArgs, "/r:$externalBuildDeps/CppSharpBinaries/CppSharp.Generator.dll"; + push @mcsArgs, "/r:$externalBuildDeps/CppSharpBinaries/CppSharp.Parser.CSharp.dll"; + push @mcsArgs, "/r:$externalBuildDeps/CppSharpBinaries/CppSharp.Parser.dll"; + push @mcsArgs, "/r:$externalBuildDeps/CppSharpBinaries/CppSharp.dll"; + push @mcsArgs, "/debug"; + push @mcsArgs, "/nowarn:0436"; + push @mcsArgs, "/out:$monoroot/tools/offsets-tool/MonoAotOffsetsDumper.exe"; + + print ">>> Compiling MonoAotOffsetDumper : $iphoneCrossMonoBinToUse/mcs @mcsArgs\n"; + system("$iphoneCrossMonoBinToUse/mcs", @mcsArgs) eq 0 or die("failed to compile MonoAotOffsetsDumper\n"); + + # clean up any pre-existing offset header just in case + if (-f "$monoroot/$iphoneCrossAbi.h") + { + system("rm", "-rf", "$iphoneCrossAbi.h"); + } + } + } + elsif ($android) + { + if (!(-d $externalBuildDeps)) + { + die("mono build deps are required and the directory was not found : $externalBuildDeps\n"); + } + + my $ndkVersion = "r13b"; + my $isArmArch = 1; + my $toolchainName = ""; + my $platformRootPostfix = ""; + my $useKraitPatch = 1; + my $kraitPatchPath = "$monoroot/../../android_krait_signal_handler/build"; + my $toolChainExtension = ""; + + $isArmArch = 0 if ($androidArch eq "x86"); + + $ENV{ANDROID_PLATFORM} = "android-9"; + $ENV{GCC_VERSION} = "4.9"; + + if ($isArmArch) + { + $ENV{GCC_PREFIX} = "arm-linux-androideabi-"; + $toolchainName = "$ENV{GCC_PREFIX}$ENV{GCC_VERSION}"; + $platformRootPostfix = "arm"; + } + else + { + $ENV{GCC_PREFIX} = "i686-linux-android-"; + $toolchainName = "x86-$ENV{GCC_VERSION}"; + $platformRootPostfix = "x86"; + $useKraitPatch = 0; + } + + if ($^O eq "linux") + { + $ENV{HOST_ENV} = "linux"; + } + elsif ($^O eq 'darwin') + { + $ENV{HOST_ENV} = "darwin"; + } + else + { + $ENV{HOST_ENV} = "windows"; + } + + print "\n"; + print(">>> Android Platform = $ENV{ANDROID_PLATFORM}\n"); + print(">>> Android NDK Version = $ndkVersion\n"); + print(">>> Android GCC Prefix = $ENV{GCC_PREFIX}\n"); + print(">>> Android GCC Version = $ENV{GCC_VERSION}\n"); + + my $ndkName = ""; + if($^O eq "linux") + { + $ndkName = "android-ndk-$ndkVersion-linux-x86_64.zip"; + } + elsif($^O eq "darwin") + { + $ndkName = "android-ndk-$ndkVersion-darwin-x86_64.zip"; + } + else + { + $ndkName = "android-ndk-$ndkVersion-windows-x86.zip"; + } + + my $depsNdkArchive = "$externalBuildDeps/$ndkName"; + my $depsNdkFinal = "$externalBuildDeps/android-ndk-$ndkVersion"; + + print(">>> Android NDK Archive = $depsNdkArchive\n"); + print(">>> Android NDK Extraction Destination = $depsNdkFinal\n"); + print("\n"); + + $ENV{ANDROID_NDK_ROOT} = "$depsNdkFinal"; + + if (-d $depsNdkFinal) + { + print(">>> Android NDK already extracted\n"); + } + else + { + print(">>> Android NDK needs to be extracted\n"); + + if ($runningOnWindows) + { + my $sevenZip = "$externalBuildDeps/7z/win64/7za.exe"; + my $winDepsNdkArchive = `cygpath -w $depsNdkArchive`; + my $winDepsNdkExtract = `cygpath -w $externalBuildDeps`; + + # clean up trailing new lines that end up in the output from cygpath. If left, they cause problems down the line + # for 7zip + $winDepsNdkArchive =~ s/\n+$//; + $winDepsNdkExtract =~ s/\n+$//; + + system($sevenZip, "x", "$winDepsNdkArchive", "-o$winDepsNdkExtract"); + } + else + { + my ($name,$path,$suffix) = fileparse($depsNdkArchive, qr/\.[^.]*/); + + print(">>> Android NDK Extension = $suffix\n"); + + # Versions after r11 use .zip extension. Currently we use r10e, but let's support the .zip extension in case + # we upgrade down the road + if (lc $suffix eq '.zip') + { + system("unzip", "-q", $depsNdkArchive, "-d", $externalBuildDeps); + } + elsif (lc $suffix eq '.bin') + { chmod(0755, $depsNdkArchive); + system($depsNdkArchive, "-o$externalBuildDeps"); + } + else + { + die "Unknown file extension '" . $suffix . "'\n"; + } + } + } + + if (!(-f "$ENV{ANDROID_NDK_ROOT}/ndk-build")) + { + die("Something went wrong with the NDK extraction\n"); + } + + my $androidNdkRoot = $ENV{ANDROID_NDK_ROOT}; + my $androidPlatformRoot = "$androidNdkRoot/platforms/$ENV{ANDROID_PLATFORM}/arch-$platformRootPostfix"; + my $androidToolchain = "$androidNdkRoot/toolchains/$toolchainName/prebuilt/$ENV{HOST_ENV}"; + + if (!(-d "$androidToolchain")) + { + if (-d "$androidToolchain-x86") + { + $androidToolchain = "$androidToolchain-x86"; + } + else + { + $androidToolchain = "$androidToolchain-x86_64"; + } + } + + if ($runningOnWindows) + { + $toolChainExtension = ".exe"; + + $androidPlatformRoot = `cygpath -w $androidPlatformRoot`; + # clean up trailing new lines that end up in the output from cygpath. + $androidPlatformRoot =~ s/\n+$//; + # Switch over to forward slashes. They propagate down the toolchain correctly + $androidPlatformRoot =~ s/\\/\//g; + + # this will get passed as a path to the linker, so we need to windows-ify the path + $kraitPatchPath = `cygpath -w $kraitPatchPath`; + $kraitPatchPath =~ s/\n+$//; + $kraitPatchPath =~ s/\\/\//g; + } + + print(">>> Android Arch = $androidArch\n"); + print(">>> Android NDK Root = $androidNdkRoot\n"); + print(">>> Android Platform Root = $androidPlatformRoot\n"); + print(">>> Android Toolchain = $androidToolchain\n"); + + if (!(-d "$androidToolchain")) + { + die("Failed to locate android toolchain\n"); + } + + if (!(-d "$androidPlatformRoot")) + { + die("Failed to locate android platform root\n"); + } + + if ("$androidArch" eq 'armv5') + { + $ENV{CFLAGS} = "-DARM_FPU_NONE=1 -march=armv5te -mtune=xscale -msoft-float"; + } + elsif ("$androidArch" eq 'armv6_vfp') + { + $ENV{CFLAGS} = "-DARM_FPU_VFP=1 -march=armv6 -mtune=xscale -msoft-float -mfloat-abi=softfp -mfpu=vfp -DHAVE_ARMV6=1"; + } + elsif ("$androidArch" eq 'armv7a') + { + $ENV{CFLAGS} = "-DARM_FPU_VFP=1 -march=armv7-a -mfloat-abi=softfp -mfpu=vfp -DHAVE_ARMV6=1"; + $ENV{LDFLAGS} = "-Wl,--fix-cortex-a8"; + } + elsif ("$androidArch" eq 'x86') + { + $ENV{LDFLAGS} = "-lgcc" + } + else + { + die("Unsupported android arch : $androidArch\n"); + } + + if ($isArmArch) + { + $ENV{CFLAGS} = "-funwind-tables $ENV{CFLAGS}"; + $ENV{LDFLAGS} = "-Wl,-rpath-link=$androidPlatformRoot/usr/lib $ENV{LDFLAGS}"; + } + + $ENV{PATH} = "$androidToolchain/bin:$ENV{PATH}"; + $ENV{CC} = "$androidToolchain/bin/$ENV{GCC_PREFIX}gcc$toolChainExtension --sysroot=$androidPlatformRoot"; + $ENV{CXX} = "$androidToolchain/bin/$ENV{GCC_PREFIX}g++$toolChainExtension --sysroot=$androidPlatformRoot"; + $ENV{CPP} = "$androidToolchain/bin/$ENV{GCC_PREFIX}cpp$toolChainExtension"; + $ENV{CXXCPP} = "$androidToolchain/bin/$ENV{GCC_PREFIX}cpp$toolChainExtension"; + $ENV{CPATH} = "$androidPlatformRoot/usr/include"; + $ENV{LD} = "$androidToolchain/bin/$ENV{GCC_PREFIX}ld$toolChainExtension"; + $ENV{AS} = "$androidToolchain/bin/$ENV{GCC_PREFIX}as$toolChainExtension"; + $ENV{AR} = "$androidToolchain/bin/$ENV{GCC_PREFIX}ar$toolChainExtension"; + $ENV{RANLIB} = "$androidToolchain/bin/$ENV{GCC_PREFIX}ranlib$toolChainExtension"; + $ENV{STRIP} = "$androidToolchain/bin/$ENV{GCC_PREFIX}strip$toolChainExtension"; + + $ENV{CFLAGS} = "-DANDROID -DPLATFORM_ANDROID -DLINUX -D__linux__ -DHAVE_USR_INCLUDE_MALLOC_H -DPAGE_SIZE=0x1000 -D_POSIX_PATH_MAX=256 -DS_IWRITE=S_IWUSR -DHAVE_PTHREAD_MUTEX_TIMEDLOCK -fpic -g -ffunction-sections -fdata-sections $ENV{CFLAGS}"; + $ENV{CXXFLAGS} = $ENV{CFLAGS}; + $ENV{CPPFLAGS} = $ENV{CFLAGS}; + + if ($useKraitPatch) + { + $ENV{LDFLAGS} = "-Wl,--wrap,sigaction -L$kraitPatchPath/obj/local/armeabi -lkrait-signal-handler $ENV{LDFLAGS}"; + } + + $ENV{LDFLAGS} = "-Wl,--no-undefined -Wl,--gc-sections -ldl -lm -llog -lc $ENV{LDFLAGS}"; + + print "\n"; + print ">>> Environment:\n"; + print ">>> \tCC = $ENV{CC}\n"; + print ">>> \tCXX = $ENV{CXX}\n"; + print ">>> \tCPP = $ENV{CPP}\n"; + print ">>> \tCXXCPP = $ENV{CXXCPP}\n"; + print ">>> \tCPATH = $ENV{CPATH}\n"; + print ">>> \tLD = $ENV{LD}\n"; + print ">>> \tAS = $ENV{AS}\n"; + print ">>> \tAR = $ENV{AR}\n"; + print ">>> \tRANLIB = $ENV{RANLIB}\n"; + print ">>> \tSTRIP = $ENV{STRIP}\n"; + print ">>> \tCFLAGS = $ENV{CFLAGS}\n"; + print ">>> \tCXXFLAGS = $ENV{CXXFLAGS}\n"; + print ">>> \tCPPFLAGS = $ENV{CPPFLAGS}\n"; + print ">>> \tLDFLAGS = $ENV{LDFLAGS}\n"; + + if ($useKraitPatch) + { + my $kraitPatchRepo = "git://github.com/Unity-Technologies/krait-signal-handler.git"; + if (-d "$kraitPatchPath") + { + print ">>> Krait patch repository already cloned\n"; + } + else + { + system("git", "clone", "--branch", "master", "$kraitPatchRepo", "$kraitPatchPath") eq 0 or die ('failing cloning Krait patch'); + } + + chdir("$kraitPatchPath") eq 1 or die ("failed to chdir to krait patch directory\n"); + system('$ANDROID_NDK_ROOT/ndk-build clean') eq 0 or die ('failing to clean Krait patch'); + system('$ANDROID_NDK_ROOT/ndk-build') eq 0 or die ('failing to build Krait patch'); + chdir("$monoroot") eq 1 or die ("failed to chdir to $monoroot\n"); + } + + if ($isArmArch) + { + push @configureparams, "--host=armv5-linux-androideabi"; + } + elsif ("$androidArch" eq 'x86') + { + push @configureparams, "--host=i686-linux-android"; + } + else + { + die("Unsupported android arch : $androidArch\n"); + } + + push @configureparams, "--cache-file=android-$androidArch.cache" if ($enableCacheFile); + + push @configureparams, "--disable-parallel-mark"; + push @configureparams, "--disable-shared-handles"; + push @configureparams, "--with-sigaltstack=no"; + push @configureparams, "--with-tls=pthread"; + push @configureparams, "--disable-visibility-hidden"; + push @configureparams, "mono_cv_uscore=yes"; + push @configureparams, "ac_cv_header_zlib_h=no" if($runningOnWindows); + } + elsif ($tizen) + { + if (!(-d $externalBuildDeps)) + { + die("mono build deps are required and the directory was not found : $externalBuildDeps\n"); + } + + my $sdkVersion = "2.4.0r1"; + my $isArmArch = 1; + + $isArmArch = 0 if ($tizenEmulator); + + $ENV{TIZEN_PLATFORM} = "tizen-2.4"; + + if ($tizenEmulator) + { + $ENV{TIZEN_ROOTSTRAP} = "mobile-2.4-emulator.core"; + } + else + { + $ENV{TIZEN_ROOTSTRAP} = "mobile-2.4-device.core"; + } + + if ($^O eq "linux") + { + $ENV{HOST_ENV} = "linux"; + } + elsif ($^O eq 'darwin') + { + $ENV{HOST_ENV} = "darwin"; + } + else + { + $ENV{HOST_ENV} = "windows"; + } + + print "\n"; + print(">>> Tizen Platform = $ENV{TIZEN_PLATFORM}\n"); + print(">>> Tizen SDK Version = $sdkVersion\n"); + + my $sdkName = "tizen-$sdkVersion-$ENV{HOST_ENV}.tar.bz2"; + my $depsSdkArchive = "$externalBuildDeps/$sdkName"; + my $depsSdkFinal = "$externalBuildDeps/tizen-$sdkVersion-$ENV{HOST_ENV}"; + + print(">>> Tizen SDK Archive = $depsSdkArchive\n"); + print(">>> Tizen SDK Extraction Destination = $depsSdkFinal\n"); + print("\n"); + + $ENV{TIZEN_SDK_ROOT} = "$depsSdkFinal"; + + if (-d $depsSdkFinal) + { + print(">>> Tizen SDK already extracted\n"); + } + else + { + print(">>> Tizen SDK needs to be extracted\n"); + + if ($runningOnWindows) + { + my $sevenZip = "$externalBuildDeps/7z/win64/7za.exe"; + my $winDepsSdkArchive = `cygpath -w $depsSdkArchive`; + my $winDepsSdkExtract = `cygpath -w $externalBuildDeps`; + + # clean up trailing new lines that end up in the output from cygpath. If left, they cause problems down the line + # for 7zip + $winDepsSdkArchive =~ s/\n+$//; + $winDepsSdkExtract =~ s/\n+$//; + + system($sevenZip, "x", "$winDepsSdkArchive", "-o$winDepsSdkExtract"); + } + else + { + my ($name,$path,$suffix) = fileparse($depsSdkArchive, qr/\.[^.]*/); + + print(">>> Tizen SDK Extension = $suffix\n"); + + if (lc $suffix eq '.bz2') + { chmod(0755, $depsSdkArchive); + system("tar xjf $depsSdkArchive -C $externalBuildDeps") eq 0 or die ("failed to extract Tizen SDK\n"); + } + else + { + die "Unknown file extension '" . $suffix . "'\n"; + } + } + } + + if (!(-f "$ENV{TIZEN_SDK_ROOT}/tools/sdb")) + { + die("Something went wrong with the SDK extraction\n"); + } + + my $tizenSdkRoot = $ENV{TIZEN_SDK_ROOT}; + my $tizenPlatformRoot = "$tizenSdkRoot/platforms/$ENV{TIZEN_PLATFORM}/mobile/rootstraps/$ENV{TIZEN_ROOTSTRAP}"; + my $tizenToolchain = "$tizenSdkRoot/tools/llvm-3.6/bin"; + + if ($runningOnWindows) + { + $toolChainExtension = ".exe"; + + $tizenPlatformRoot = `cygpath -w $tizenPlatformRoot`; + # clean up trailing new lines that end up in the output from cygpath. + $tizenPlatformRoot =~ s/\n+$//; + # Switch over to forward slashes. They propagate down the toolchain correctly + $tizenPlatformRoot =~ s/\\/\//g; + } + + if ($tizenEmulator) + { + $tizenToolchain = "$tizenSdkRoot/tools/i386-linux-gnueabi-gcc-4.9/bin/i386"; + $ENV{CFLAGS} = "-Os -g -march=i686 -msse2 -mfpmath=sse"; + } + else + { + $tizenToolchain = "$tizenSdkRoot/tools/arm-linux-gnueabi-gcc-4.9/bin/arm"; + $ENV{CFLAGS} = "-Os -g -march=armv7-a -mfpu=vfp -mfloat-abi=softfp -DARM_FPU_VFP=1 -DHAVE_ARMV6=1"; + $ENV{LDFLAGS} = "-Wl,-rpath-link=$tizenPlatformRoot/usr/lib -L$tizenPlatformRoot/usr/lib $ENV{LDFLAGS}"; + } + + print(">>> Tizen SDK Root = $tizenSdkRoot\n"); + print(">>> Tizen Platform Root = $tizenPlatformRoot\n"); + print(">>> Tizen Toolchain Prefix = $tizenToolchain\n"); + + if (!(-d "$tizenPlatformRoot")) + { + die("Failed to locate Tizen platform root\n"); + } + + $ENV{PATH} = "$tizenToolchain/bin:$ENV{PATH}"; + $ENV{CC} = "$tizenToolchain-linux-gnueabi-gcc --sysroot=$tizenPlatformRoot"; + $ENV{CXX} = "$tizenToolchain-linux-gnueabi-g++ --sysroot=$tizenPlatformRoot"; + $ENV{CPP} = "$tizenToolchain-linux-gnueabi-cpp"; + $ENV{CXXCPP} = "$tizenToolchain-linux-gnueabi-cpp"; + $ENV{CPATH} = "$tizenPlatformRoot/usr/include"; + $ENV{LD} = "$tizenToolchain-linux-gnueabi-ld --sysroot=$tizenPlatformRoot"; + $ENV{AS} = "$tizenToolchain-linux-gnueabi-as"; + $ENV{STRIP} = "$tizenToolchain-linux-gnueabi-strip"; + + if ($tizenEmulator) + { + $ENV{AR} = "$ENV{TIZEN_SDK_ROOT}/tools/i386-linux-gnueabi-gcc-4.9/bin/i386-linux-gnueabi-ar"; + $ENV{RANLIB} = "$ENV{TIZEN_SDK_ROOT}/tools/i386-linux-gnueabi-gcc-4.9/bin/i386-linux-gnueabi-ranlib"; + } + else + { + $ENV{AR} = "$ENV{TIZEN_SDK_ROOT}/tools/arm-linux-gnueabi-gcc-4.9/bin/arm-linux-gnueabi-ar"; + $ENV{RANLIB} = "$ENV{TIZEN_SDK_ROOT}/tools/arm-linux-gnueabi-gcc-4.9/bin/arm-linux-gnueabi-ranlib"; + } + + $ENV{CFLAGS} = "-DTIZEN -DLINUX -D__linux__ -DHAVE_USR_INCLUDE_MALLOC_H -DPAGE_SIZE=0x1000 -D_POSIX_PATH_MAX=256 -DS_IWRITE=S_IWUSR -DHAVE_PTHREAD_MUTEX_TIMEDLOCK -fpic -g -ffunction-sections -fdata-sections $ENV{CFLAGS}"; + $ENV{CXXFLAGS} = $ENV{CFLAGS}; + $ENV{CPPFLAGS} = $ENV{CFLAGS}; + $ENV{LDFLAGS} = "-Wl,--no-undefined -ldlog -shared -Xlinker --as-needed $ENV{LDFLAGS}"; + + print "\n"; + print ">>> Environment:\n"; + print ">>> \tCC = $ENV{CC}\n"; + print ">>> \tCXX = $ENV{CXX}\n"; + print ">>> \tCPP = $ENV{CPP}\n"; + print ">>> \tCXXCPP = $ENV{CXXCPP}\n"; + print ">>> \tCPATH = $ENV{CPATH}\n"; + print ">>> \tLD = $ENV{LD}\n"; + print ">>> \tAS = $ENV{AS}\n"; + print ">>> \tAR = $ENV{AR}\n"; + print ">>> \tRANLIB = $ENV{RANLIB}\n"; + print ">>> \tSTRIP = $ENV{STRIP}\n"; + print ">>> \tCFLAGS = $ENV{CFLAGS}\n"; + print ">>> \tCXXFLAGS = $ENV{CXXFLAGS}\n"; + print ">>> \tCPPFLAGS = $ENV{CPPFLAGS}\n"; + print ">>> \tLDFLAGS = $ENV{LDFLAGS}\n"; + + if ($tizenEmulator) + { + push @configureparams, "--host=i386-tizen-linux-gnueabi"; + } + else + { + push @configureparams, "--host=arm-tizen-linux-gnueabi"; + } + + push @configureparams, "--cache-file=tizen-cross.cache" if ($enableCacheFile); + push @configureparams, "--disable-parallel-mark"; + push @configureparams, "--disable-shared-handles"; + push @configureparams, "--with-sigaltstack=no"; + push @configureparams, "--with-tls=pthread"; + push @configureparams, "--disable-visibility-hidden"; + push @configureparams, "--disable-executables"; + push @configureparams, "--with-gnu-ld=yes"; + push @configureparams, "mono_cv_uscore=yes"; + push @configureparams, "ac_cv_header_zlib_h=no" if($runningOnWindows); + } + elsif($^O eq "linux") + { + if (!(-d $externalBuildDeps)) + { + die("mono build deps are required and the directory was not found : $externalBuildDeps\n"); + } + + if($ENV{UNITY_THISISABUILDMACHINE} || $ENV{UNITY_USE_LINUX_SDK}) + { + my $sdkVersion = '20170609'; + my $schroot = "LinuxBuildEnvironment-$sdkVersion"; + my @linuxToolchain = ('schroot', '-c', $schroot, '--'); + + print "\n"; + print(">>> Linux SDK Version = $sdkVersion\n"); + + my $sdkName = "linux-sdk-$sdkVersion.tar.bz2"; + my $depsSdkArchive = "$externalBuildDeps/$sdkName"; + my $depsSdkFinal = "$externalBuildDeps/linux-sdk-$sdkVersion"; + + print(">>> Linux SDK Archive = $depsSdkArchive\n"); + print(">>> Linux SDK Extraction Destination = $depsSdkFinal\n"); + print("\n"); + + my $linuxSdkRoot = $depsSdkFinal; + + if (-d $depsSdkFinal) + { + print(">>> Linux SDK already extracted\n"); + } + else + { + print(">>> Linux SDK needs to be extracted\n"); + system('mkdir', '-p', $depsSdkFinal); + system('tar', 'xaf', $depsSdkArchive, '-C', $depsSdkFinal) eq 0 or die ("failed to extract Linux SDK\n"); + system('sudo', 'cp', '-R', "$depsSdkFinal/linux-sdk-$sdkVersion", '/etc/schroot'); + system("sed 's,^directory=.*,directory=$depsSdkFinal/$schroot,' \"$depsSdkFinal/$schroot.conf\" | sudo tee /etc/schroot/chroot.d/$schroot.conf") eq 0 or die ("failed to deploy Linux SDK\n"); + } + + @commandPrefix = @linuxToolchain; + print(">>> Linux SDK Root = $linuxSdkRoot\n"); + print(">>> Linux Toolchain Command Prefix = " . join(' ', @commandPrefix) . "\n"); + } + + push @configureparams, "--host=$monoHostArch-pc-linux-gnu"; + + push @configureparams, "--disable-parallel-mark"; #this causes crashes + + my $archflags = ''; + if ($arch32) + { + $archflags = '-m32'; + } + else + { + $archflags = '-fPIC'; + } + + if ($debug) + { + $ENV{CFLAGS} = "$archflags -g -O0"; + } + else + { + $ENV{CFLAGS} = "$archflags -Os"; #optimize for size + } + } + elsif($^O eq 'darwin') + { + # Set up mono for bootstrapping + if ($existingMonoRootPath eq "") + { + # Find the latest mono version and use that for boostrapping + my $monoInstalls = '/Library/Frameworks/Mono.framework/Versions'; + my @monoVersions = (); + + opendir( my $DIR, $monoInstalls ); + while ( my $entry = readdir $DIR ) + { + next unless -d $monoInstalls . '/' . $entry; + next if $entry eq '.' or $entry eq '..' or $entry eq 'Current'; + push @monoVersions, $entry; + } + closedir $DIR; + @monoVersions = sort @monoVersions; + my $monoVersionToUse = pop @monoVersions; + $existingMonoRootPath = "$monoInstalls/$monoVersionToUse"; + } + + $mcs = "EXTERNAL_MCS=$existingMonoRootPath/bin/mcs"; + + $ENV{'CC'} = "$macSdkPath/../usr/bin/clang"; + $ENV{'CXX'} = "$macSdkPath/../usr/bin/clang++"; + $ENV{'CFLAGS'} = $ENV{MACSDKOPTIONS} = "-D_XOPEN_SOURCE -I$macBuildEnvDir/builds/usr/include -mmacosx-version-min=$macversion -isysroot $macSdkPath"; + + $ENV{CFLAGS} = "$ENV{CFLAGS} -g -O0" if $debug; + $ENV{CFLAGS} = "$ENV{CFLAGS} -Os" if not $debug; #optimize for size + + $ENV{CC} = "$ENV{CC} -arch $monoHostArch"; + $ENV{CXX} = "$ENV{CXX} -arch $monoHostArch"; + + # Add OSX specific autogen args + push @configureparams, "--host=$monoHostArch-apple-darwin12.2.0"; + + # Need to define because Apple's SIP gets in the way of us telling mono where to find this + push @configureparams, "--with-libgdiplus=$addtoresultsdistdir/lib/libgdiplus.dylib"; + + print "\n"; + print ">>> Setting environment:\n"; + print ">>> PATH = ".$ENV{PATH}."\n"; + print ">>> C_INCLUDE_PATH = ".$ENV{C_INCLUDE_PATH}."\n"; + print ">>> CPLUS_INCLUDE_PATH = ".$ENV{CPLUS_INCLUDE_PATH}."\n"; + print ">>> CFLAGS = ".$ENV{CFLAGS}."\n"; + print ">>> CXXFLAGS = ".$ENV{CXXFLAGS}."\n"; + print ">>> CC = ".$ENV{CC}."\n"; + print ">>> CXX = ".$ENV{CXX}."\n"; + print ">>> CPP = ".$ENV{CPP}."\n"; + print ">>> CXXPP = ".$ENV{CXXPP}."\n"; + print ">>> LD = ".$ENV{LD}."\n"; + print ">>> LDFLAGS = ".$ENV{LDFLAGS}."\n"; + print "\n"; + } + else + { + push @configureparams, "--host=$monoHostArch-pc-mingw32"; + } + + if ($isDesktopBuild) + { + my $cacheArch = $arch32 ? "i386" : "x86_64"; + push @configureparams, "--cache-file=desktop-$cacheArch.cache" if ($enableCacheFile); + } + + print ">>> Existing Mono : $existingMonoRootPath\n\n"; + $ENV{'PATH'} = "$existingMonoRootPath/$existingExternalMonoBinDir:$ENV{'PATH'}"; + + print ">>> PATH before Build = $ENV{PATH}\n\n"; + + print(">>> mcs Information : \n"); + system(@commandPrefix, ("which", "mcs")); + system(@commandPrefix, ("mcs", "--version")); + print("\n"); + + print ">>> Checking on some tools...\n"; + system(@commandPrefix, ("which", "autoconf")); + system(@commandPrefix, ("autoconf", "--version")); + + system(@commandPrefix, ("which", "texi2dvi")); + system(@commandPrefix, ("texi2dvi", "--version")); + + system(@commandPrefix, ("which", "automake")); + system(@commandPrefix, ("automake", "--version")); + + system(@commandPrefix, ("which", "libtool")); + system(@commandPrefix, ("libtool", "--version")); + + system(@commandPrefix, ("which", "libtoolize")); + system(@commandPrefix, ("libtoolize", "--version")); + print("\n"); + + print ">>> LIBTOOLIZE before Build = $ENV{LIBTOOLIZE}\n"; + print ">>> LIBTOOL before Build = $ENV{LIBTOOL}\n"; + + chdir("$monoroot") eq 1 or die ("failed to chdir 2\n"); + + if (not $skipMonoMake) + { + if ($clean) + { + if (!($mcsOnly)) + { + print(">>> Cleaning $monoprefix\n"); + rmtree($monoprefix); + } + + # Avoid "source directory already configured" ... + system(@commandPrefix, ('rm', '-f', 'config.status', 'eglib/config.status', 'libgc/config.status')); + + print("\n>>> Calling autogen in mono\n"); + print("\n"); + print("\n>>> Configure parameters are : @configureparams\n"); + print("\n"); + + system(@commandPrefix, ('./autogen.sh', @configureparams)) eq 0 or die ('failing autogenning mono'); + + if ($mcsOnly) + { + print("\n>>> Calling make clean in mcs\n"); + chdir("$monoroot/mcs"); + system(@commandPrefix, ("make","clean")) eq 0 or die ("failed to make clean\n"); + chdir("$monoroot"); + } + else + { + print("\n>>> Calling make clean in mono\n"); + system(@commandPrefix, ("make","clean")) eq 0 or die ("failed to make clean\n"); + } + } + + # this step needs to run after configure + if ($iphoneCross || $iphone || $android || $tizen) + { + # This step generates the arm_dpimacros.h file, which is needed by the offset dumper + chdir("$monoroot/mono/arch/arm"); + system("make") eq 0 or die("failed to make in $monoroot/mono/arch/arm\n"); + chdir("$monoroot"); + } + + if ($iphoneCross) + { + my @monoArgs = (); + push @monoArgs, "$monoroot/tools/offsets-tool/MonoAotOffsetsDumper.exe"; + push @monoArgs, "--abi"; + push @monoArgs, "$iphoneCrossAbi"; + push @monoArgs, "--out"; + push @monoArgs, "$monoroot"; + push @monoArgs, "--mono"; + push @monoArgs, "$monoroot"; + push @monoArgs, "--maccore"; + push @monoArgs, "$monoroot"; + + $ENV{MONO_PATH} = "$externalBuildDeps/CppSharpBinaries"; + # Need to use 32bit mono because there is a native CppSharp dylib that will be used and there's only a 32bit version of it + print ">>> Running MonoAotOffsetDumper : arch -i386 $iphoneCrossMonoBinToUse/mono @monoArgs\n"; + system("arch", "-i386", "$iphoneCrossMonoBinToUse/mono", @monoArgs) eq 0 or die("failed to run MonoAotOffsetsDumper\n"); + } + + if ($mcsOnly) + { + print("\n>>> Calling make in mcs\n"); + chdir("$monoroot/mcs"); + my @makeCommand = (@commandPrefix, ('make', "-j$jobs")); + if($mcs ne '') + { + push(@makeCommand, $mcs); + } + system(@makeCommand) eq 0 or die ("Failed to make\n"); + chdir("$monoroot"); + } + else + { + print("\n>>> Calling make\n"); + my @makeCommand = (@commandPrefix, ('make', "-j$jobs")); + if($mcs ne '') + { + push(@makeCommand, $mcs); + } + system(@makeCommand) eq 0 or die ("Failed to make\n"); + } + + if ($isDesktopBuild) + { + print("\n>>> Calling make install\n"); + system(@commandPrefix, ('make', 'install')) eq 0 or die ("Failed to make install\n"); + } + else + { + if ($disableMcs) + { + print(">>> Skipping make install. We don't need to run this step when building the runtime on non-desktop platforms.\n"); + } + else + { + # Note by Mike : make install on Windows for android runtime runs into more cygwin path issues. The one I hit was related to ranlib.exe being passed cygwin linux paths + # and as a result not being able to find stuff. The previous build scripts didn't run make install for android or iOS, so I think we are fine to skip this step. + # However, if we were to build the class libs for these cases, then we probably would need to run make install. If that day comes, we'll have to figure out what to do here. + print(">>> Attempting to build class libs for a non-desktop platform. The `make install` step is probably needed, but it has cygwin path related problems on Windows for android\n"); + die("Blocking this code path until we need it. It probably should be looked at more closely before letting it proceed\n"); + } + } + } + + if ($isDesktopBuild) + { + if ($^O eq "cygwin") + { + system("$winPerl", "$winMonoRoot/external/buildscripts/build_runtime_vs.pl", "--build=$build", "--arch32=$arch32", "--msbuildversion=$msBuildVersion", "--clean=$clean", "--debug=$debug") eq 0 or die ('failed building mono with VS\n'); + + # Copy over the VS built stuff that we want to use instead into the prefix directory + my $archNameForBuild = $arch32 ? 'Win32' : 'x64'; + my $config = $debug ? "Debug" : "Release"; + system("cp $monoroot/msvc/$archNameForBuild/bin/$config/mono.exe $monoprefix/bin/.") eq 0 or die ("failed copying mono.exe\n"); + system("cp $monoroot/msvc/$archNameForBuild/bin/$config/mono-2.0.dll $monoprefix/bin/.") eq 0 or die ("failed copying mono-2.0.dll\n"); + system("cp $monoroot/msvc/$archNameForBuild/bin/$config/mono-2.0.pdb $monoprefix/bin/.") eq 0 or die ("failed copying mono-2.0.pdb\n"); + } + + system("cp -R $addtoresultsdistdir/bin/. $monoprefix/bin/") eq 0 or die ("Failed copying $addtoresultsdistdir/bin to $monoprefix/bin\n"); + } + + if(!($disableMcs)) + { + my @additionalProfiles = (); + push @additionalProfiles, "unityjit"; + push @additionalProfiles, "unityaot"; + + chdir("$monoroot/mcs"); + foreach my $profileName(@additionalProfiles) + { + print(">>> Making profile : $profileName\n"); + system("make", "PROFILE=$profileName") eq 0 or die ("Failed to make $profileName profile in mcs\n"); + + my $profileDestDir = "$monoprefix/lib/mono/$profileName"; + print(">>> Copying $profileName to $profileDestDir directory\n"); + + print(">>> Cleaning $profileDestDir\n"); + system("rm -rf $profileDestDir"); + + system("mkdir -p $profileDestDir") eq 0 or die("failed to make directory $profileDestDir\n"); + system("mkdir -p $profileDestDir/Facades") eq 0 or die("failed to make directory $profileDestDir/Facades\n"); + + system("cp $monoroot/mcs/class/lib/$profileName/*.dll $profileDestDir") eq 0 or die("Failed copying dlls from $monoroot/mcs/class/lib/$profileName to $profileDestDir\n"); + system("cp $monoroot/mcs/class/lib/$profileName/Facades/*.dll $profileDestDir/Facades") eq 0 or die("Failed copying dlls from $monoroot/mcs/class/lib/$profileName/Facades to $profileDestDir/Facades\n"); + } + + chdir("$monoroot"); + } +} +else +{ + print(">>> Skipping build\n"); +} + +if ($buildUsAndBoo) +{ + print(">>> Building Unity Script and Boo...\n"); + if($windowsSubsystemForLinux) + { + #boo scripts expect a bin-platform folder, but we haven't built them that way + system("ln -s $monoprefix/bin $monoprefix/bin-linux64"); + system("ln -s $monoprefix/bin $monoprefix/bin-linux32"); + } + + system(@commandPrefix, ("perl", "$buildscriptsdir/build_us_and_boo.pl", "--monoprefix=$monoprefix")) eq 0 or die ("Failed building Unity Script and Boo\n"); + + print(">>> Copying Unity Script and Boo *.Lang.dll's from 4.5 profile to unityjit profile...\n"); + system("cp $monoprefix/lib/mono/4.5/Boo*.dll $monoprefix/lib/mono/unityjit/.") eq 0 or die("Failed copying Boo*.dll\n"); + system("cp $monoprefix/lib/mono/4.5/UnityScript*.dll $monoprefix/lib/mono/unityjit/.") eq 0 or die("Failed copying UnityScript*.dll\n"); + system("cp $monoprefix/lib/mono/4.5/booc.exe $monoprefix/lib/mono/unityjit/.") eq 0 or die("Failed copying booc.exe\n"); + system("cp $monoprefix/lib/mono/4.5/us.exe $monoprefix/lib/mono/unityjit/.") eq 0 or die("Failed copying us.exe\n"); +} +else +{ + print(">>> Skipping build Unity Script and Boo\n"); +} + +if ($artifact) +{ + print(">>> Creating artifact...\n"); + + if ($artifactsCommon) + { + print(">>> Creating common artifacts...\n"); + print(">>> distribution directory = $distdir\n"); + + if (!(-d "$distdir")) + { + system("mkdir -p $distdir") eq 0 or die("failed to make directory $distdir\n"); + } + + $File::Copy::Recursive::CopyLink = 0; #make sure we copy files as files and not as symlinks, as TC unfortunately doesn't pick up symlinks. + + my $distdirlibmono = "$distdir/lib/mono"; + + print(">>> Cleaning $distdir/lib\n"); + system("rm -rf $distdir/lib"); + system("mkdir -p $distdir/lib"); + + print(">>> Creating normal profile artifacts...\n"); + system("cp -R $addtoresultsdistdir/. $distdir/") eq 0 or die ("Failed copying $addtoresultsdistdir to $distdir\n"); + + system("cp -r $monoprefix/lib/mono $distdir/lib"); + + if($^O ne 'darwin') + { + # On OSX we build a universal binary for 32-bit and 64-bit in the mono executable. The class library build + # only creates the 64-bit slice, so we don't want to end up with a single slice binary in the output. + # If we do, it will step on the universal binary produced but the OSX runtime build. + system("cp -r $monoprefix/bin $distdir/") eq 0 or die ("failed copying bin folder\n"); + } + system("cp -r $monoprefix/etc $distdir/") eq 0 or die("failed copying etc folder\n"); + + system("cp -R $externalBuildDeps/reference-assemblies/unity $distdirlibmono/unity"); + system("cp -R $externalBuildDeps/reference-assemblies/unity_web $distdirlibmono/unity_web"); + + system("cp -R $externalBuildDeps/reference-assemblies/unity/Boo*.dll $distdirlibmono/2.0-api"); + system("cp -R $externalBuildDeps/reference-assemblies/unity/UnityScript*.dll $distdirlibmono/2.0-api"); + + system("cp -R $externalBuildDeps/reference-assemblies/unity/Boo*.dll $distdirlibmono/4.0-api"); + system("cp -R $externalBuildDeps/reference-assemblies/unity/UnityScript*.dll $distdirlibmono/4.0-api"); + + system("cp -R $externalBuildDeps/reference-assemblies/unity/Boo*.dll $distdirlibmono/4.5-api"); + system("cp -R $externalBuildDeps/reference-assemblies/unity/UnityScript*.dll $distdirlibmono/4.5-api"); + + # now remove nunit from a couple places (but not all, we need some of them) + # linux tar is not happy these are removed(at least on wsl), so don't remove them for now + if(not $windowsSubsystemForLinux) + { + system("rm -rf $distdirlibmono/2.0/nunit*"); + system("rm -rf $distdirlibmono/gac/nunit*"); + } + + # Remove a self referencing sym link that causes problems + system("rm -rf $monoprefix/bin/bin"); + + if (-f "$monoroot/ZippedClasslibs.tar.gz") + { + system("rm -f $monoroot/ZippedClasslibs.tar.gz") eq 0 or die("Failed to clean existing ZippedClasslibs.tar.gz\n"); + } + + print(">>> Creating ZippedClasslibs.tar.gz\n"); + print(">>> Changing directory to : $buildsroot\n"); + chdir("$buildsroot"); + system("tar -hpczf ../ZippedClasslibs.tar.gz *") eq 0 or die("Failed to zip up classlibs\n"); + print(">>> Changing directory back to : $currentdir\n"); + chdir("$currentdir"); + } + + # Do the platform specific logic to create the builds output structure that we want + + my $embedDirRoot = "$buildsroot/embedruntimes"; + my $embedDirArchDestination = ""; + my $distDirArchBin = ""; + my $versionsOutputFile = ""; + my $crossCompilerRoot = "$buildsroot/crosscompiler"; + my $crossCompilerDestination = ""; + + if ($iphone) + { + $embedDirArchDestination = "$embedDirRoot/iphone/$iphoneArch"; + $versionsOutputFile = "$buildsroot/versions-iphone-$iphoneArch.txt"; + } + elsif ($iphoneCross) + { + $crossCompilerDestination = "$buildsroot/crosscompiler/iphone"; + $versionsOutputFile = "$buildsroot/versions-iphone-xcompiler.txt"; + } + elsif ($iphoneSimulator) + { + $embedDirArchDestination = "$embedDirRoot/iphone/$iphoneSimulatorArch"; + $versionsOutputFile = "$buildsroot/versions-iphone-$iphoneSimulatorArch.txt"; + } + elsif ($android) + { + $embedDirArchDestination = "$embedDirRoot/android/$androidArch"; + $versionsOutputFile = "$buildsroot/versions-android-$androidArch.txt"; + } + elsif ($tizenEmulator) + { + $embedDirArchDestination = "$embedDirRoot/tizenemulator/"; + $versionsOutputFile = "$buildsroot/versions-tizenemulator.txt"; + } + elsif ($tizen) + { + $embedDirArchDestination = "$embedDirRoot/tizen/"; + $versionsOutputFile = "$buildsroot/versions-tizen.txt"; + } + elsif($^O eq "linux") + { + $embedDirArchDestination = $arch32 ? "$embedDirRoot/linux32" : "$embedDirRoot/linux64"; + $distDirArchBin = $arch32 ? "$distdir/bin-linux32" : "$distdir/bin-linux64"; + $versionsOutputFile = $arch32 ? "$buildsroot/versions-linux32.txt" : "$buildsroot/versions-linux64.txt"; + } + elsif($^O eq 'darwin') + { + # Note these tmp directories will get merged into a single 'osx' directory later by a parent script + $embedDirArchDestination = "$embedDirRoot/osx-tmp-$monoHostArch"; + $distDirArchBin = "$distdir/bin-osx-tmp-$monoHostArch"; + $versionsOutputFile = $arch32 ? "$buildsroot/versions-osx32.txt" : "$buildsroot/versions-osx64.txt"; + } + else + { + $embedDirArchDestination = $arch32 ? "$embedDirRoot/win32" : "$embedDirRoot/win64"; + $distDirArchBin = $arch32 ? "$distdir/bin" : "$distdir/bin-x64"; + $versionsOutputFile = $arch32 ? "$buildsroot/versions-win32.txt" : "$buildsroot/versions-win64.txt"; + } + + # Make sure the directory for our architecture is clean before we copy stuff into it + if (-d "$embedDirArchDestination") + { + print(">>> Cleaning $embedDirArchDestination\n"); + rmtree($embedDirArchDestination); + } + + if (-d "$distDirArchBin") + { + print(">>> Cleaning $distDirArchBin\n"); + rmtree($distDirArchBin); + } + + if ($artifactsRuntime) + { + system("mkdir -p $embedDirArchDestination") if ($embedDirArchDestination ne ""); + system("mkdir -p $distDirArchBin") if ($distDirArchBin ne ""); + system("mkdir -p $crossCompilerDestination") if ($crossCompilerDestination ne ""); + + # embedruntimes directory setup + print(">>> Creating embedruntimes directory : $embedDirArchDestination\n"); + if ($iphone || $iphoneSimulator) + { + for my $file ('libmonosgen-2.0.a','libmonobdwgc-2.0.a') + { + print ">>> Copying $file\n"; + system("cp", "$monoroot/mono/mini/.libs/$file","$embedDirArchDestination/$file") eq 0 or die ("failed copying $file\n"); + } + } + elsif ($iphoneCross) + { + # Nothing to do + } + elsif ($android) + { + for my $file ('libmonosgen-2.0.so','libmonosgen-2.0.a','libmonobdwgc-2.0.so','libmonobdwgc-2.0.a') + { + print ">>> Copying $file\n"; + system("cp", "$monoroot/mono/mini/.libs/$file","$embedDirArchDestination/$file") eq 0 or die ("failed copying $file\n"); + } + } + elsif ($tizen || $tizenEmulator) + { + for my $file ('libmonosgen-2.0.so','libmonobdwgc-2.0.so') + { + print ">>> Copying $file\n"; + system("cp", "$monoroot/mono/mini/.libs/$file","$embedDirArchDestination/$file") eq 0 or die ("failed copying $file\n"); + } + } + elsif($^O eq "linux") + { + print ">>> Copying libmonosgen-2.0\n"; + system("cp", "$monoroot/mono/mini/.libs/libmonobdwgc-2.0.so","$embedDirArchDestination/libmonobdwgc-2.0.so") eq 0 or die ("failed copying libmonobdwgc-2.0.so\n"); + system("cp", "$monoroot/mono/mini/.libs/libmonosgen-2.0.so","$embedDirArchDestination/libmonosgen-2.0.so") eq 0 or die ("failed copying libmonosgen-2.0.so\n"); + + print ">>> Copying libMonoPosixHelper.so\n"; + system("cp", "$monoroot/support/.libs/libMonoPosixHelper.so","$embedDirArchDestination/libMonoPosixHelper.so") eq 0 or die ("failed copying libMonoPosixHelper.so\n"); + + if ($buildMachine) + { + system("strip $embedDirArchDestination/libmonobdwgc-2.0.so") eq 0 or die("failed to strip libmonobdwgc-2.0.so (shared)\n"); + system("strip $embedDirArchDestination/libmonosgen-2.0.so") eq 0 or die("failed to strip libmonosgen-2.0.so (shared)\n"); + system("strip $embedDirArchDestination/libMonoPosixHelper.so") eq 0 or die("failed to strip libMonoPosixHelper (shared)\n"); + } + } + elsif($^O eq 'darwin') + { + # embedruntimes directory setup + print ">>> Hardlinking libmonosgen-2.0\n"; + + system("ln","-f", "$monoroot/mono/mini/.libs/libmonobdwgc-2.0.dylib","$embedDirArchDestination/libmonobdwgc-2.0.dylib") eq 0 or die ("failed symlinking libmonobdwgc-2.0.dylib\n"); + system("ln","-f", "$monoroot/mono/mini/.libs/libmonosgen-2.0.dylib","$embedDirArchDestination/libmonosgen-2.0.dylib") eq 0 or die ("failed symlinking libmonosgen-2.0.dylib\n"); + + print "Hardlinking libMonoPosixHelper.dylib\n"; + system("ln","-f", "$monoroot/support/.libs/libMonoPosixHelper.dylib","$embedDirArchDestination/libMonoPosixHelper.dylib") eq 0 or die ("failed symlinking $libtarget/libMonoPosixHelper.dylib\n"); + + InstallNameTool("$embedDirArchDestination/libmonobdwgc-2.0.dylib", "\@executable_path/../Frameworks/MonoEmbedRuntime/osx/libmonobdwgc-2.0.dylib"); + InstallNameTool("$embedDirArchDestination/libmonosgen-2.0.dylib", "\@executable_path/../Frameworks/MonoEmbedRuntime/osx/libmonosgen-2.0.dylib"); + InstallNameTool("$embedDirArchDestination/libMonoPosixHelper.dylib", "\@executable_path/../Frameworks/MonoEmbedRuntime/osx/libMonoPosixHelper.dylib"); + + print ">>> Copying mono public headers\n"; + system("mkdir -p $includesroot/mono"); + system("cp -R $monoprefix/include/mono-2.0/mono $includesroot/mono"); + } + else + { + # embedruntimes directory setup + system("cp", "$monoprefix/bin/mono-2.0-bdwgc.dll", "$embedDirArchDestination/mono-2.0-bdwgc.dll") eq 0 or die ("failed copying mono-2.0-bdwgc.dll\n"); + system("cp", "$monoprefix/bin/mono-2.0-bdwgc.pdb", "$embedDirArchDestination/mono-2.0-bdwgc.pdb") eq 0 or die ("failed copying mono-2.0-bdwgc.pdb\n"); + + system("cp", "$monoprefix/bin/mono-2.0-sgen.dll", "$embedDirArchDestination/mono-2.0-sgen.dll") eq 0 or die ("failed copying mono-2.0-sgen.dll\n"); + system("cp", "$monoprefix/bin/mono-2.0-sgen.pdb", "$embedDirArchDestination/mono-2.0-sgen.pdb") eq 0 or die ("failed copying mono-2.0-sgen.pdb\n"); + } + + # monodistribution directory setup + print(">>> Creating monodistribution directory\n"); + if ($android || $iphone || $iphoneCross || $iphoneSimulator || $tizen || $tizenEmulator) + { + # Nothing to do + } + elsif($^O eq "linux") + { + my $distDirArchEtc = $arch32 ? "$distdir/etc-linux32" : "$distdir/etc-linux64"; + + if (-d "$distDirArchEtc") + { + print(">>> Cleaning $distDirArchEtc\n"); + rmtree($distDirArchEtc); + } + + system("mkdir -p $distDirArchBin"); + system("mkdir -p $distDirArchEtc"); + system("mkdir -p $distDirArchEtc/mono"); + + system("ln", "-f", "$monoroot/mono/mini/mono-sgen","$distDirArchBin/mono") eq 0 or die("failed symlinking mono executable\n"); + system("ln", "-f", "$monoroot/tools/pedump/pedump","$distDirArchBin/pedump") eq 0 or die("failed symlinking pedump executable\n"); + system('cp', "$monoroot/data/config","$distDirArchEtc/mono/config") eq 0 or die("failed to copy config\n"); + } + elsif($^O eq 'darwin') + { + system("ln", "-f", "$monoroot/mono/mini/mono","$distDirArchBin/mono") eq 0 or die("failed hardlinking mono executable\n"); + system("ln", "-f", "$monoroot/tools/pedump/pedump","$distDirArchBin/pedump") eq 0 or die("failed hardlinking pedump executable\n"); + } + else + { + system("cp", "$monoprefix/bin/mono-2.0.dll", "$distDirArchBin/mono-2.0.dll") eq 0 or die ("failed copying mono-2.0.dll\n"); + system("cp", "$monoprefix/bin/mono-2.0.pdb", "$distDirArchBin/mono-2.0.pdb") eq 0 or die ("failed copying mono-2.0.pdb\n"); + system("cp", "$monoprefix/bin/mono.exe", "$distDirArchBin/mono.exe") eq 0 or die ("failed copying mono.exe\n"); + } + } + + # cross compiler directory setup + if ($iphoneCross) + { + print ">>> Copying mono-xcompiler\n"; + if($runningOnWindows) + { + die("Not implemented\n"); + } + else + { + system("cp", "$monoroot/mono/mini/mono","$crossCompilerDestination/mono-xcompiler") eq 0 or die ("failed copying mono-xcompiler\n"); + } + } + + # Not all build configurations output to the distro dir, so only chmod it if it exists + system("chmod", "-R", "755", $distDirArchBin) if (-d "$distDirArchBin"); + + # Output version information + print(">>> Creating version file : $versionsOutputFile\n"); + system("echo \"mono-version =\" > $versionsOutputFile"); + + # Not all build configurations output to the distro dir, only try to output version info if there is a distro dir + system("$distDirArchBin/mono --version >> $versionsOutputFile") if (-d "$distDirArchBin"); + + system("echo \"unity-mono-revision = $monoRevision\" >> $versionsOutputFile"); + system("echo \"unity-mono-build-scripts-revision = $buildScriptsRevision\" >> $versionsOutputFile"); + my $tmp = `date`; + system("echo \"build-date = $tmp\" >> $versionsOutputFile"); +} +else +{ + print(">>> Skipping artifact creation\n"); +} + +if ($test) +{ + if ($runRuntimeTests) + { + my $runtimeTestsDir = "$monoroot/mono/mini"; + chdir("$runtimeTestsDir") eq 1 or die ("failed to chdir"); + print("\n>>> Calling make check in $runtimeTestsDir\n\n"); + system("make","check") eq 0 or die ("runtime tests failed\n"); + } + else + { + print(">>> Skipping runtime unit tests\n"); + } + + if ($runClasslibTests) + { + if ($disableMcs) + { + print(">>> Skipping classlib unit tests because building the class libs was disabled\n"); + } + else + { + my $classlibTestsDir = "$monoroot/mcs/class"; + chdir("$classlibTestsDir") eq 1 or die ("failed to chdir"); + print("\n>>> Calling make run-test in $runtimeTestsDir\n\n"); + system("make","run-test") eq 0 or die ("classlib tests failed\n"); + } + } + else + { + print(">>> Skipping classlib unit tests\n"); + } +} +else +{ + print(">>> Skipping unit tests\n"); +} + +chdir ($currentdir); diff --git a/external/buildscripts/build_all_linux.pl b/external/buildscripts/build_all_linux.pl new file mode 100644 index 000000000000..d124f2b19cce --- /dev/null +++ b/external/buildscripts/build_all_linux.pl @@ -0,0 +1,27 @@ +use Cwd; +use Cwd 'abs_path'; +use Getopt::Long; +use File::Basename; +use File::Path; + +my $currentdir = getcwd(); + +my $monoroot = File::Spec->rel2abs(dirname(__FILE__) . "/../.."); +my $monoroot = abs_path($monoroot); +my $buildscriptsdir = "$monoroot/external/buildscripts"; + +my @passAlongArgs = (); +foreach my $arg (@ARGV) +{ + # Filter out --clean if someone uses it. We have to clean since we are doing two builds + if (not $arg =~ /^--clean=/) + { + push @passAlongArgs, $arg; + } +} + +print(">>> Building i386\n"); +system("perl", "$buildscriptsdir/build.pl", "--arch32=1", "--clean=1", "--classlibtests=0", @passAlongArgs) eq 0 or die ('failing building i386'); + +print(">>> Building x86_64\n"); +system("perl", "$buildscriptsdir/build.pl", "--clean=1", "--classlibtests=0", @passAlongArgs) eq 0 or die ('failing building x86_64'); \ No newline at end of file diff --git a/external/buildscripts/build_all_osx.pl b/external/buildscripts/build_all_osx.pl new file mode 100644 index 000000000000..0f0eb42d6aa3 --- /dev/null +++ b/external/buildscripts/build_all_osx.pl @@ -0,0 +1,165 @@ +use Cwd; +use Cwd 'abs_path'; +use Getopt::Long; +use File::Basename; +use File::Path; + +my $currentdir = getcwd(); + +my $monoroot = File::Spec->rel2abs(dirname(__FILE__) . "/../.."); +my $monoroot = abs_path($monoroot); +my $buildscriptsdir = "$monoroot/external/buildscripts"; +my $buildMachine = $ENV{UNITY_THISISABUILDMACHINE}; +my $buildsroot = "$monoroot/builds"; + +my $artifact=0; +my $artifactsCommon=0; +my $buildUsAndBoo=0; + +my @thisScriptArgs = (); +my @passAlongArgs = (); +foreach my $arg (@ARGV) +{ + # Filter out --clean if someone uses it. We have to clean since we are doing two builds + if (not $arg =~ /^--clean=/) + { + # We don't need common artifacts, us, and boo, from both, so filter out temporarily and we'll + # only pass it to the second build + if ($arg =~ /^--artifactscommon=/ || $arg =~ /^--buildusandboo=/) + { + push @thisScriptArgs, $arg; + } + else + { + push @passAlongArgs, $arg; + } + } + + if ($arg =~ /^--artifact=/) + { + push @thisScriptArgs, $arg; + } +} + +print(">>> This Script Args = @thisScriptArgs\n"); +print(">>> Pass Along Args = @passAlongArgs\n"); + +@ARGV = @thisScriptArgs; +GetOptions( + 'artifact=i'=>\$artifact, + 'artifactscommon=i'=>\$artifactsCommon, + 'buildusandboo=i'=>\$buildUsAndBoo, +); + +my $monoArch32Target = "i386"; + +print(">>> Building $monoArch32Target\n"); +system("perl", "$buildscriptsdir/build.pl", "--arch32=1", "--clean=1", "--classlibtests=0", @passAlongArgs) eq 0 or die ("failing building $monoArch32Target"); + +if ($artifactsCommon) +{ + push @passAlongArgs, "--artifactscommon=1"; +} + +if ($buildUsAndBoo) +{ + push @passAlongArgs, "--buildusandboo=1"; +} + +print(">>> Building x86_64\n"); +system("perl", "$buildscriptsdir/build.pl", "--clean=1", "--classlibtests=0", @passAlongArgs) eq 0 or die ('failing building x86_64'); + +if ($artifact) +{ + print(">>> Creating universal binaries\n"); + # Merge stuff in the embedruntimes directory + my $embedDirRoot = "$buildsroot/embedruntimes"; + my $embedDirDestination = "$embedDirRoot/osx"; + my $embedDirSource32 = "$embedDirRoot/osx-tmp-$monoArch32Target"; + my $embedDirSource64 = "$embedDirRoot/osx-tmp-x86_64"; + + system("mkdir -p $embedDirDestination"); + + if (!(-d $embedDirSource32)) + { + die("Expected source directory not found : $embedDirSource32\n"); + } + + if (!(-d $embedDirSource64)) + { + die("Expected source directory not found : $embedDirSource64\n"); + } + + # Create universal binaries + for my $file ('libmonobdwgc-2.0.dylib','libmonosgen-2.0.dylib','libMonoPosixHelper.dylib') + { + print(">>> lipo $embedDirSource32/$file $embedDirSource64/$file -create -output $embedDirDestination/$file\n\n"); + system ('lipo', "$embedDirSource32/$file", "$embedDirSource64/$file", '-create', '-output', "$embedDirDestination/$file"); + } + + if (not $buildMachine) + { + print(">>> Doing non-build machine stuff...\n"); + for my $file ('libmonobdwgc-2.0.dylib','libmonosgen-2.0.dylib','libMonoPosixHelper.dylib') + { + print(">>> Removing $embedDirDestination/$file.dSYM\n"); + rmtree ("$embedDirDestination/$file.dSYM"); + print(">>> 'dsymutil $embedDirDestination/$file\n"); + system ('dsymutil', "$embedDirDestination/$file") eq 0 or warn ("Failed creating $embedDirDestination/$file.dSYM"); + } + + print(">>> Done with non-build machine stuff\n"); + } + + # Merge stuff in the monodistribution directory + my $distDirRoot = "$buildsroot/monodistribution"; + my $distDirDestinationBin = "$buildsroot/monodistribution/bin"; + my $distDirDestinationLib = "$buildsroot/monodistribution/lib"; + my $distDirSourceBin32 = "$distDirRoot/bin-osx-tmp-$monoArch32Target"; + my $distDirSourceBin64 = "$distDirRoot/bin-osx-tmp-x86_64"; + + # Should always exist because build_all would have put stuff in it, but in some situations + # depending on the options it may not. So create it if it does not exist + if (!(-d $distDirDestinationBin)) + { + system("mkdir -p $distDirDestinationBin"); + } + + if (!(-d $distDirDestinationLib)) + { + system("mkdir -p $distDirDestinationLib"); + } + + if (!(-d $distDirSourceBin32)) + { + die("Expected source directory not found : $distDirSourceBin32\n"); + } + + if (!(-d $distDirSourceBin64)) + { + die("Expected source directory not found : $distDirSourceBin64\n"); + } + + for my $file ('mono','pedump') + { + print(">>> lipo $distDirSourceBin32/$file $distDirSourceBin64/$file -create -output $distDirDestinationBin/$file\n\n"); + system ('lipo', "$distDirSourceBin32/$file", "$distDirSourceBin64/$file", '-create', '-output', "$distDirDestinationBin/$file"); + } + + #Create universal binaries for stuff is in the embed dir but will end up in the dist dir + for my $file ('libMonoPosixHelper.dylib') + { + print(">>> lipo $embedDirSource32/$file $embedDirSource64/$file -create -output $distDirDestinationLib/$file\n\n"); + system ('lipo', "$embedDirSource32/$file", "$embedDirSource64/$file", '-create', '-output', "$distDirDestinationLib/$file"); + } + + if ($buildMachine) + { + print(">>> Clean up temporary arch specific build directories\n"); + + rmtree("$distDirSourceBin32"); + rmtree("$distDirSourceBin64"); + rmtree("$embedDirSource32"); + rmtree("$embedDirSource64"); + } +} diff --git a/external/buildscripts/build_all_win.pl b/external/buildscripts/build_all_win.pl new file mode 100644 index 000000000000..3c282f5f9993 --- /dev/null +++ b/external/buildscripts/build_all_win.pl @@ -0,0 +1,27 @@ +use Cwd; +use Cwd 'abs_path'; +use Getopt::Long; +use File::Basename; +use File::Path; + +my $currentdir = getcwd(); + +my $monoroot = File::Spec->rel2abs(dirname(__FILE__) . "/../.."); +my $monoroot = abs_path($monoroot); +my $buildscriptsdir = "$monoroot/external/buildscripts"; + +my @passAlongArgs = (); +foreach my $arg (@ARGV) +{ + # Filter out --clean if someone uses it. We have to clean since we are doing two builds + if (not $arg =~ /^--clean=/) + { + push @passAlongArgs, $arg; + } +} + +print(">>> Building i686\n"); +system("perl", "$buildscriptsdir/build_win_wrapper.pl", "--arch32=1", "--clean=1", "--classlibtests=0", @passAlongArgs) eq 0 or die ('failing building win32'); + +print(">>> Building x86_64\n"); +system("perl", "$buildscriptsdir/build_win_wrapper.pl", "--clean=1", "--classlibtests=0", @passAlongArgs) eq 0 or die ('failing building x64'); \ No newline at end of file diff --git a/external/buildscripts/build_classlibs_osx.pl b/external/buildscripts/build_classlibs_osx.pl new file mode 100644 index 000000000000..b1a47d9fef8d --- /dev/null +++ b/external/buildscripts/build_classlibs_osx.pl @@ -0,0 +1,40 @@ +use Cwd; +use Cwd 'abs_path'; +use Getopt::Long; +use File::Basename; +use File::Path; + +my $monoroot = File::Spec->rel2abs(dirname(__FILE__) . "/../.."); +my $monoroot = abs_path($monoroot); +my $buildScriptsRoot = "$monoroot/external/buildscripts"; + +my $build = 1; +my $clean = 1; +my $mcsOnly = 0; +my $skipMonoMake = 0; + +# Handy troubleshooting/niche options + +# The prefix hack probably isn't needed anymore. Let's disable it by default and see how things go +my $shortPrefix = 1; + +GetOptions( + "build=i"=>\$build, + "clean=i"=>\$clean, + "mcsOnly=i"=>\$mcsOnly, + 'skipmonomake=i'=>\$skipMonoMake, + 'shortprefix=i'=>\$shortPrefix, +) or die ("illegal cmdline options"); + +system( + "perl", + "$buildScriptsRoot/build.pl", + "--build=$build", + "--clean=$clean", + "--mcsonly=$mcsOnly", + "--skipmonomake=$skipMonoMake", + "--artifact=1", + "--artifactscommon=1", + "--buildusandboo=1", + "--forcedefaultbuilddeps=1", + "--shortprefix=$shortPrefix") eq 0 or die ("Failed building mono\n"); diff --git a/external/buildscripts/build_classlibs_wsl.pl b/external/buildscripts/build_classlibs_wsl.pl new file mode 100644 index 000000000000..750b21d646f6 --- /dev/null +++ b/external/buildscripts/build_classlibs_wsl.pl @@ -0,0 +1,53 @@ +use Cwd; +use Cwd 'abs_path'; +use Getopt::Long; +use File::Basename; +use File::Path; + +my $monoroot = File::Spec->rel2abs(dirname(__FILE__) . "/../.."); +my $monoroot = abs_path($monoroot); +my $buildScriptsRoot = "$monoroot/external/buildscripts"; + +my $build = 1; +my $clean = 1; +my $mcsOnly = 0; +my $skipMonoMake = 0; + +# Handy troubleshooting/niche options + +# The prefix hack probably isn't needed anymore. Let's disable it by default and see how things go +my $shortPrefix = 1; + +# This script should not be ran on windows, if it is, kindly switch over to wsl +if ($^O eq "MSWin32") +{ + print(">>> Called from Windows. Switching over to wsl\n"); + my $monoRootInBash = `bash -c pwd`; + chomp $monoRootInBash; + print(">>> monoRootInBash = $monoRootInBash\n"); + my $cmdForBash = "$monoRootInBash/external/buildscripts/build_classlibs_wsl.pl @ARGV"; + system("bash", "-c", "\"perl $cmdForBash\"") eq 0 or die("\n"); + exit 0; +} + +GetOptions( + "build=i"=>\$build, + "clean=i"=>\$clean, + "mcsOnly=i"=>\$mcsOnly, + 'skipmonomake=i'=>\$skipMonoMake, + 'shortprefix=i'=>\$shortPrefix, +) or die ("illegal cmdline options"); + +system( + "perl", + "$buildScriptsRoot/build.pl", + "--build=$build", + "--clean=$clean", + "--mcsonly=$mcsOnly", + "--skipmonomake=$skipMonoMake", + "--artifact=1", + "--artifactscommon=1", + "--buildusandboo=1", + "--forcedefaultbuilddeps=1", + "--windowssubsystemforlinux=1", + "--shortprefix=$shortPrefix") eq 0 or die ("Failed building mono\n"); diff --git a/external/buildscripts/build_ios_xwin.pl b/external/buildscripts/build_ios_xwin.pl new file mode 100644 index 000000000000..d20844d1ef25 --- /dev/null +++ b/external/buildscripts/build_ios_xwin.pl @@ -0,0 +1,18 @@ +use Cwd; +use Cwd 'abs_path'; +use Getopt::Long; +use File::Basename; +use File::Path; + +my $monoroot = File::Spec->rel2abs(dirname(__FILE__) . "/../.."); +my $monoroot = abs_path($monoroot); +my $buildScriptsRoot = "$monoroot/external/buildscripts"; + +my $clean = 1; + +GetOptions( + "clean=i"=>\$clean, +) or die ("illegal cmdline options"); + + +system("perl", "$buildScriptsRoot/build.pl", "--build=1", "--clean=$clean", "--artifact=1", "--arch32=1", "--iphonecross=1", "--forcedefaultbuilddeps=1") eq 0 or die ("Failed building iphone cross compiler\n"); diff --git a/external/buildscripts/build_ios_xwin.sh b/external/buildscripts/build_ios_xwin.sh new file mode 100644 index 000000000000..8095de7d7146 --- /dev/null +++ b/external/buildscripts/build_ios_xwin.sh @@ -0,0 +1,19 @@ +#!/bin/sh + +# The build configs are looking for this file rather than the perl script. +# easier to add this + +BASEDIR=$(dirname $0) + +# Note : Not Implemented yet. Script is here to make the katana build pass so that the mono build artifact is created +# Uncomment the line below when ready to implement. Remove the mkdir +if [ -d builds ]; then + echo "Skip making builds directory. Already exists" +else + mkdir builds +fi + +touch builds/dummy_ios_win.txt + + +#perl "$BASEDIR/build_ios_xwin.pl" "$@" || exit 1 diff --git a/external/buildscripts/build_runtime_android.pl b/external/buildscripts/build_runtime_android.pl new file mode 100644 index 000000000000..b827b191968e --- /dev/null +++ b/external/buildscripts/build_runtime_android.pl @@ -0,0 +1,32 @@ +use Cwd; +use Cwd 'abs_path'; +use Getopt::Long; +use File::Basename; +use File::Path; + +my $monoroot = File::Spec->rel2abs(dirname(__FILE__) . "/../.."); +my $monoroot = abs_path($monoroot); +my $buildScriptsRoot = "$monoroot/external/buildscripts"; + +my $androidArch = ""; +my $clean = 1; +my $windowsSubsystemForLinux = 0; + +GetOptions( + "androidarch=s"=>\$androidArch, + "clean=i"=>\$clean, + "windowssubsystemforlinux=i"=>\$windowsSubsystemForLinux, +) or die ("illegal cmdline options"); + +# By default, build runtime for all the variants we need. But allow something to specify an individual variation to build +if ($androidArch eq "") +{ + system("perl", "$buildScriptsRoot/build.pl", "--build=1", "--clean=1", "--artifact=1", "--arch32=1", "--androidarch=armv5", "--forcedefaultbuilddeps=1", "--windowssubsystemforlinux=$windowsSubsystemForLinux") eq 0 or die ("Failed building mono for armv5\n"); + system("perl", "$buildScriptsRoot/build.pl", "--build=1", "--clean=1", "--artifact=1", "--arch32=1", "--androidarch=armv6_vfp", "--forcedefaultbuilddeps=1", "--windowssubsystemforlinux=$windowsSubsystemForLinux") eq 0 or die ("Failed building mono for armv6_vfp\n"); + system("perl", "$buildScriptsRoot/build.pl", "--build=1", "--clean=1", "--artifact=1", "--arch32=1", "--androidarch=armv7a", "--forcedefaultbuilddeps=1", "--windowssubsystemforlinux=$windowsSubsystemForLinux") eq 0 or die ("Failed building mono for armv7a\n"); + system("perl", "$buildScriptsRoot/build.pl", "--build=1", "--clean=1", "--artifact=1", "--arch32=1", "--androidarch=x86", "--forcedefaultbuilddeps=1", "--windowssubsystemforlinux=$windowsSubsystemForLinux") eq 0 or die ("Failed building mono for x86\n"); +} +else +{ + system("perl", "$buildScriptsRoot/build.pl", "--build=1", "--clean=$clean", "--artifact=1", "--arch32=1", "--androidarch=$androidArch", "--forcedefaultbuilddeps=1", "--windowssubsystemforlinux=$windowsSubsystemForLinux") eq 0 or die ("Failed building mono for $androidArch\n"); +} diff --git a/external/buildscripts/build_runtime_android.sh b/external/buildscripts/build_runtime_android.sh new file mode 100644 index 000000000000..2916d73d5e65 --- /dev/null +++ b/external/buildscripts/build_runtime_android.sh @@ -0,0 +1,8 @@ +#!/bin/sh + +# The build configs are looking for this file rather than the perl script. +# easier to add this + +BASEDIR=$(dirname $0) + +perl "$BASEDIR/build_runtime_android.pl" "$@" diff --git a/external/buildscripts/build_runtime_iphone.pl b/external/buildscripts/build_runtime_iphone.pl new file mode 100644 index 000000000000..7c0b93e9df2e --- /dev/null +++ b/external/buildscripts/build_runtime_iphone.pl @@ -0,0 +1,67 @@ +use Cwd; +use Cwd 'abs_path'; +use Getopt::Long; +use File::Basename; +use File::Path; + +my $monoroot = File::Spec->rel2abs(dirname(__FILE__) . "/../.."); +my $monoroot = abs_path($monoroot); +my $buildScriptsRoot = "$monoroot/external/buildscripts"; + +my $clean = 1; +my $runtime = 0; +my $xcomp = 0; +my $simulator = 0; + +GetOptions( + "clean=i"=>\$clean, + "runtime=i"=>\$runtime, + "xcomp=i"=>\$xcomp, + "simulator=i"=>\$simulator, +) or die ("illegal cmdline options"); + +# Build everything by default +if ($runtime == 0 && $xcomp == 0 && $simulator == 0) +{ + print ">>> All iphone related builds will be ran\n"; + $runtime = 1; + $xcomp = 1; + $simulator = 1; +} + +if ($runtime) +{ + print ">>> Building iphone runtime\n"; + system("perl", "$buildScriptsRoot/build.pl", "--build=1", "--clean=$clean", "--artifact=1", "--arch32=1", "--iphoneArch=armv7", "--forcedefaultbuilddeps=1") eq 0 or die ("Failed building mono for iphone\n"); +} + +if ($xcomp) +{ + # TODO : This is a horrible waste of time, and we should fix it, but for now it gets things working. + # The mono we have in the build deps for bootstrapping doesn't have a 32bit slice, which we need in order to run the MonoAotOffsetsDumper. + # To get around this for the moment, we'll build the runtime & classlibs first, and then use that to run the MonoAotOffsetsDumper. + # Once we update the mono in the build deps, we can remove this. + if(!(-f "$monoroot/builds/monodistribution/bin/mono")) + { + print ">>> Building mono to use for bootstrapping. The version in mono build deps is missing the 32bit slice and we need a 32bit version to run the MonoAotOffsetsDumper\n"; + #system("perl", "$buildScriptsRoot/build.pl", "--build=1", "--arch32=1", "--clean=$clean", "--classlibtests=0", "--artifact=1", "--artifactscommon=1", "--forcedefaultbuilddeps=1") eq 0 or die ("failing building mono 32bit for bootstrapping\n"); + #system("perl", "$buildScriptsRoot/build_all_osx.pl", "--build=1", "--artifact=1", "--forcedefaultbuilddeps=1") eq 0 or die ("Failed building mono\n"); + system("perl", "$buildScriptsRoot/build.pl", "--build=1", "--clean=1", "--artifact=1", "--arch32=1", "--artifactscommon=1", "--forcedefaultbuilddeps=1") eq 0 or die ("Failed building mono\n"); + + system("cp", "$monoroot/builds/monodistribution/bin-osx-tmp-i386/mono", "$monoroot/builds/monodistribution/bin/.") eq 0 or die ("failed to copy mono over from bin-osx-tmp-i386 to bin\n"); + system("chmod", "+x", "$monoroot/builds/monodistribution/bin/mono") eq 0 or die("Failed to chmod mono\n"); + + # Need to clean up the tmp build folder so that we don't pollute the final artifact + rmtree("$monoroot/builds/monodistribution/bin-osx-tmp-i386"); + rmtree("$monoroot/builds/embedruntimes/osx-tmp-i386"); + } + + print ">>> Building iphone cross compiler\n"; + system("perl", "$buildScriptsRoot/build.pl", "--build=1", "--clean=$clean", "--artifact=1", "--arch32=1", "--iphonecross=1", "--forcedefaultbuilddeps=1") eq 0 or die ("Failed building iphone cross compiler\n"); +} + +if ($simulator) +{ + print ">>> Building iphone simulator\n"; + system("perl", "$buildScriptsRoot/build.pl", "--build=1", "--clean=$clean", "--artifact=1", "--arch32=1", "--iphonesimulator=1", "--forcedefaultbuilddeps=1") eq 0 or die ("Failed building iphone simulator\n"); +} diff --git a/external/buildscripts/build_runtime_iphone.sh b/external/buildscripts/build_runtime_iphone.sh new file mode 100644 index 000000000000..21452053675b --- /dev/null +++ b/external/buildscripts/build_runtime_iphone.sh @@ -0,0 +1,20 @@ +#!/bin/sh + +# The build configs are looking for this file rather than the perl script. +# easier to add this + +BASEDIR=$(dirname $0) + +if [ -d builds ]; then + echo "Skip making builds directory. Already exists" +else + mkdir builds +fi + +if [ "x$1" == "x--runtime-only" ]; then + touch builds/dummy_iphone_runtime.txt +elif [ "x$1" == "x--xcomp-only" ]; then + touch builds/dummy_iphone_xcomp.txt +elif [ "x$1" == "x--simulator-only" ]; then + touch builds/dummy_iphone_sim.txt +fi diff --git a/external/buildscripts/build_runtime_linux.pl b/external/buildscripts/build_runtime_linux.pl new file mode 100644 index 000000000000..073b6fb5ea76 --- /dev/null +++ b/external/buildscripts/build_runtime_linux.pl @@ -0,0 +1,23 @@ +use Cwd; +use Cwd 'abs_path'; +use Getopt::Long; +use File::Basename; +use File::Path; + +my $monoroot = File::Spec->rel2abs(dirname(__FILE__) . "/../.."); +my $monoroot = abs_path($monoroot); +my $buildScriptsRoot = "$monoroot/external/buildscripts"; + +my $build64 = 0; + +GetOptions( + "build64=i"=>\$build64, +) or die ("illegal cmdline options"); + +my $arch32 = 1; +if ($build64) +{ + $arch32 = 0; +} + +system("perl", "$buildScriptsRoot/build.pl", "--build=1", "--clean=1", "--test=1", "--artifact=1", "--arch32=$arch32", "--classlibtests=0", "--forcedefaultbuilddeps=1") eq 0 or die ("Failed building mono\n"); diff --git a/external/buildscripts/build_runtime_osx.pl b/external/buildscripts/build_runtime_osx.pl new file mode 100644 index 000000000000..42009e295b51 --- /dev/null +++ b/external/buildscripts/build_runtime_osx.pl @@ -0,0 +1,11 @@ +use Cwd; +use Cwd 'abs_path'; +use Getopt::Long; +use File::Basename; +use File::Path; + +my $monoroot = File::Spec->rel2abs(dirname(__FILE__) . "/../.."); +my $monoroot = abs_path($monoroot); +my $buildScriptsRoot = "$monoroot/external/buildscripts"; + +system("perl", "$buildScriptsRoot/build_all_osx.pl", "--build=1", "--artifact=1", "--test=1", "--forcedefaultbuilddeps=1") eq 0 or die ("Failed building mono\n"); diff --git a/external/buildscripts/build_runtime_qnx.sh b/external/buildscripts/build_runtime_qnx.sh new file mode 100644 index 000000000000..b2eaaf63a0a8 --- /dev/null +++ b/external/buildscripts/build_runtime_qnx.sh @@ -0,0 +1,13 @@ +#!/bin/sh + +# The build configs are looking for this file rather than the perl script. +# easier to add this + +# Note : Not Implemented yet. Script is here to make the katana build pass so that the mono build artifact is created +if [ -d builds ]; then + echo "Skip making builds directory. Already exists" +else + mkdir builds +fi + +touch builds/dummy_qnx.txt diff --git a/external/buildscripts/build_runtime_stv.sh b/external/buildscripts/build_runtime_stv.sh new file mode 100644 index 000000000000..4d8fb005059c --- /dev/null +++ b/external/buildscripts/build_runtime_stv.sh @@ -0,0 +1,14 @@ +#!/bin/sh + +# The build configs are looking for this file rather than the perl script. +# easier to add this + +# Note : Not Implemented yet. Script is here to make the katana build pass so that the mono build artifact is created +if [ -d builds ]; then + echo "Skip making builds directory. Already exists" +else + mkdir builds +fi + +touch builds/dummy_stv.txt + diff --git a/external/buildscripts/build_runtime_tizen.pl b/external/buildscripts/build_runtime_tizen.pl new file mode 100644 index 000000000000..039e26c8ef9f --- /dev/null +++ b/external/buildscripts/build_runtime_tizen.pl @@ -0,0 +1,18 @@ +use Cwd; +use Cwd 'abs_path'; +use Getopt::Long; +use File::Basename; +use File::Path; + +my $monoroot = File::Spec->rel2abs(dirname(__FILE__) . "/../.."); +my $monoroot = abs_path($monoroot); +my $buildScriptsRoot = "$monoroot/external/buildscripts"; + +my $clean = 1; + +GetOptions( + "clean=i"=>\$clean, +) or die ("illegal cmdline options"); + +system("perl", "$buildScriptsRoot/build.pl", "--build=1", "--clean=1", "--artifact=1", "--arch32=1", "--tizen=1", "--forcedefaultbuilddeps=1") eq 0 or die ("Failed building mono for tizen\n"); +system("perl", "$buildScriptsRoot/build.pl", "--build=1", "--clean=1", "--artifact=1", "--arch32=1", "--tizen=1", "--tizenemulator=1", "--forcedefaultbuilddeps=1") eq 0 or die ("Failed building mono for tizen emulator\n"); diff --git a/external/buildscripts/build_runtime_tizen.sh b/external/buildscripts/build_runtime_tizen.sh new file mode 100644 index 000000000000..b7a4b24bc699 --- /dev/null +++ b/external/buildscripts/build_runtime_tizen.sh @@ -0,0 +1,8 @@ +#!/bin/sh + +# The build configs are looking for this file rather than the perl script. +# easier to add this + +BASEDIR=$(dirname $0) + +perl "$BASEDIR/build_runtime_tizen.pl" "$@" diff --git a/external/buildscripts/build_runtime_vs.pl b/external/buildscripts/build_runtime_vs.pl new file mode 100644 index 000000000000..ee41343ede20 --- /dev/null +++ b/external/buildscripts/build_runtime_vs.pl @@ -0,0 +1,52 @@ +sub CompileVCProj; +use Cwd 'abs_path'; +use Getopt::Long; +use File::Spec; +use File::Basename; +use File::Copy; +use File::Path; + +print ">>> PATH in Build VS = $ENV{PATH}\n\n"; + +my $monoroot = File::Spec->rel2abs(dirname(__FILE__) . "/../.."); +my $monoroot = abs_path($monoroot); +my $buildsroot = "$monoroot/builds"; +my $buildMachine = $ENV{UNITY_THISISABUILDMACHINE}; + +my $build = 0; +my $clean = 0; +my $arch32 = 0; +my $debug = 0; +my $gc = "bdwgc"; +my $msBuildVersion = ""; + +GetOptions( + 'build=i'=>\$build, + 'clean=i'=>\$clean, + 'arch32=i'=>\$arch32, + 'debug=i'=>\$debug, + 'msbuildversion=s'=>\$msBuildVersion, + 'gc=s'=>\$gc, +) or die ("illegal cmdline options"); + +if ($build) +{ + CompileVCProj("$monoroot/msvc/mono.sln"); +} + +sub CompileVCProj +{ + my $sln = shift; + my $config; + + my $msbuild = $ENV{"ProgramFiles(x86)"}."/MSBuild/$msBuildVersion/Bin/MSBuild.exe"; + + $config = $debug ? "Debug" : "Release"; + my $arch = $arch32 ? "Win32" : "x64"; + my $target = $clean ? "/t:Clean,Build" :"/t:Build"; + my $properties = "/p:Configuration=$config;Platform=$arch;MONO_TARGET_GC=$gc"; + + print ">>> $msbuild $properties $target $sln\n\n"; + system($msbuild, $properties, $target, $sln) eq 0 + or die("MSBuild failed to build $sln\n"); +} diff --git a/external/buildscripts/build_runtime_win.pl b/external/buildscripts/build_runtime_win.pl new file mode 100644 index 000000000000..f8dda725c262 --- /dev/null +++ b/external/buildscripts/build_runtime_win.pl @@ -0,0 +1,14 @@ +use Cwd; +use Cwd 'abs_path'; +use Getopt::Long; +use File::Basename; +use File::Path; + +my $monoroot = File::Spec->rel2abs(dirname(__FILE__) . "/../.."); +my $monoroot = abs_path($monoroot); +my $buildScriptsRoot = "$monoroot/external/buildscripts"; + +# Note : Ideally we can switch back to this build approach once the random cygwin hangs on the build machines are sorted out +#system("perl", "$buildScriptsRoot/build.pl", "--build=1", "--clean=1", "--test=1", "--artifact=1", "--arch32=1", "--classlibtests=0", "--forcedefaultbuilddeps=1") eq 0 or die ("Failed building mono\n"); + +system("perl", "$buildScriptsRoot/build_win_no_cygwin.pl", "--build=1", "--clean=1", "--artifact=1", "--arch32=1", "--forcedefaultbuilddeps=1") eq 0 or die ("Failed building mono\n"); diff --git a/external/buildscripts/build_runtime_win64.pl b/external/buildscripts/build_runtime_win64.pl new file mode 100644 index 000000000000..fd36d86bfd35 --- /dev/null +++ b/external/buildscripts/build_runtime_win64.pl @@ -0,0 +1,14 @@ +use Cwd; +use Cwd 'abs_path'; +use Getopt::Long; +use File::Basename; +use File::Path; + +my $monoroot = File::Spec->rel2abs(dirname(__FILE__) . "/../.."); +my $monoroot = abs_path($monoroot); +my $buildScriptsRoot = "$monoroot/external/buildscripts"; + +# Note : Ideally we can switch back to this build approach once the random cygwin hangs on the build machines are sorted out +#system("perl", "$buildScriptsRoot/build.pl", "--build=1", "--clean=1", "--test=1", "--artifact=1", "--classlibtests=0", "--forcedefaultbuilddeps=1") eq 0 or die ("Failed building mono\n"); + +system("perl", "$buildScriptsRoot/build_win_no_cygwin.pl", "--build=1", "--clean=1", "--artifact=1", "--arch32=0", "--forcedefaultbuilddeps=1") eq 0 or die ("Failed building mono\n"); diff --git a/external/buildscripts/build_runtime_wsl.pl b/external/buildscripts/build_runtime_wsl.pl new file mode 100644 index 000000000000..fabedcff1774 --- /dev/null +++ b/external/buildscripts/build_runtime_wsl.pl @@ -0,0 +1,13 @@ +use Cwd; +use Cwd 'abs_path'; +use Getopt::Long; +use File::Basename; +use File::Path; + +my $monoroot = File::Spec->rel2abs(dirname(__FILE__) . "/../.."); +my $monoroot = abs_path($monoroot); +my $buildScriptsRoot = "$monoroot/external/buildscripts"; + +#Windows Subsystem for Linux currently does not support 32-bit, so the option is 64-bit only + +system("perl", "$buildScriptsRoot/build.pl", "--build=1", "--clean=1", "--test=1", "--artifact=1", "--arch32=0", "--classlibtests=0", "--forcedefaultbuilddeps=1", "--windowssubsystemforlinux=1") eq 0 or die ("Failed building mono\n"); diff --git a/external/buildscripts/build_unityscript_bareminimum_win.pl b/external/buildscripts/build_unityscript_bareminimum_win.pl new file mode 100644 index 000000000000..753cf408dd62 --- /dev/null +++ b/external/buildscripts/build_unityscript_bareminimum_win.pl @@ -0,0 +1,159 @@ +use lib ('.', 'perl_lib', 'external/buildscripts/perl_lib'); +use Cwd; +use File::Path; + +use File::Copy::Recursive qw(dircopy); +use Getopt::Long; +use File::Basename; + +my $root = getcwd(); + +my $monodistro = "$root/builds/monodistribution"; +my $libmono = "$monodistro/lib/mono"; + +sub AddDotNetFolderToPath() { + + my @netFrameworkLocations = ( + $ENV{"SYSTEMROOT"}."/Microsoft.NET/Framework/v4.0.30319", + $ENV{"SYSTEMROOT"}."/Microsoft.NET/Framework/v3.5" + ); + + my $netFrameworkLocation = ""; + my $checkedLocations = ""; + + find_framework: + foreach my $current (@netFrameworkLocations) + { + if (-e $current) { + $netFrameworkLocation = $current; + last find_framework; + } + + $checkedLocations = $checkedLocations . ", " . $current; + } + + if ($netFrameworkLocation eq '') { + die("Could not find dotnet framework folder. Checked: $checkedLocations"); + } + + print("Using .Net framework: $netFrameworkLocation"); + $ENV{PATH} = "$netFrameworkLocation;$ENV{PATH}"; +} + +AddDotNetFolderToPath(); + +my $output = Win32::GetLongPathName("$ENV{TEMP}") . "/output/BareMinimum"; + +print("\nEnvironment Path: $ENV{PATH}\n"); + +my $booCheckout = "$root/../../boo/build"; +my $usCheckout = "$root/../../unityscript/build"; + +my $skipbuild=0; +GetOptions( + "skipbuild=i"=>\$skipbuild, +) or die ("illegal cmdline options"); + +my $monodistroLibMono = "$monodistro/lib/mono"; +my $monodistroUnity = "$monodistroLibMono/unity"; + +sub UnityBooc +{ + my $commandLine = shift; + system("$output/wsa/booc -debug- $commandLine") eq 0 or die("booc failed to execute: $commandLine"); +} + +sub BuildUnityScriptForUnity +{ + # Build system is handling this + if (!$ENV{UNITY_THISISABUILDMACHINE}) { + GitClone("git://github.com/Unity-Technologies/boo.git", $booCheckout); + } + + my $commonDefines = "NO_SERIALIZATION_INFO,NO_SYSTEM_PROCESS,NO_ICLONEABLE,MSBUILD,IGNOREKEYFILE"; + + Build("$booCheckout/src/booc/Booc.csproj", undef, "/property:TargetFrameworkVersion=4.0 /property:DefineConstants=\"" . $commonDefines . "\" /property:OutputPath=$output/wp8"); + Build("$booCheckout/src/booc/Booc.csproj", undef, "/property:TargetFrameworkVersion=4.0 /property:DefineConstants=\"" . $commonDefines . ",NO_SYSTEM_REFLECTION_EMIT\" /property:OutputPath=$output/wsa"); + + if (!$ENV{UNITY_THISISABUILDMACHINE}) { + GitClone("git://github.com/Unity-Technologies/unityscript.git", $usCheckout); + } + + UnityBooc("-out:$output/wsa/Boo.Lang.Extensions.dll -srcdir:$booCheckout/src/Boo.Lang.Extensions -r:$output/wsa/Boo.Lang.dll -r:$output/wsa/Boo.Lang.Compiler.dll"); + UnityBooc("-out:$output/wsa/Boo.Lang.Useful.dll -srcdir:$booCheckout/src/Boo.Lang.Useful -r:$output/wsa/Boo.Lang.Parser"); + UnityBooc("-out:$output/wsa/Boo.Lang.PatternMatching.dll -srcdir:$booCheckout/src/Boo.Lang.PatternMatching"); + + my $UnityScriptLangDLL = "$output/UnityScript.Lang.dll"; + UnityBooc("-out:$UnityScriptLangDLL -srcdir:$usCheckout/src/UnityScript.Lang -r:$output/wsa/Boo.Lang.Extensions.dll"); +} + +sub Build +{ + my $projectFile = shift; + + my $optionalConfiguration = shift; + my $configuration = defined($optionalConfiguration) ? $optionalConfiguration : "Release"; + + my $optionalCustomArguments = shift; + my $customArguments = defined($optionalCustomArguments) ? $optionalCustomArguments : ""; + + my $target = "Rebuild"; + my $commandLine = "MSBuild $projectFile /p:AssemblyOriginatorKeyFile= /p:SignAssembly=false /p:MonoTouch=True /t:$target /p:Configuration=$configuration $customArguments"; + + system($commandLine) eq 0 or die("Failed to xbuild '$projectFile' for unity"); +} + +sub GitClone +{ + my $repo = shift; + my $localFolder = shift; + my $branch = shift; + $branch = defined($branch)?$branch:master; + + if (-d $localFolder) { + return; + } + system("git clone --branch $branch $repo $localFolder") eq 0 or die("git clone $repo $localFolder failed!"); +} + +sub NormalizePath { + my $path = shift; + $path =~ s/\//\\/g; + + return $path; +} + +sub cp +{ + my $cmdLine = shift; + $cmdLine = NormalizePath($cmdLine); + + system("xcopy $cmdLine /s /y") eq 0 or die("failed to copy '$cmdLine'"); + print "Copied: $cmdLine\n"; +} + +rmtree("$root/builds"); +rmtree("$output"); + +BuildUnityScriptForUnity(); + +cp("$output/wsa/Boo.Lang.dll $libmono/bare-minimum/wsa/Boo.Lang.dll*"); +cp("$output/wsa/Boo.Lang.pdb $libmono/bare-minimum/wsa/Boo.Lang.pdb*"); +cp("$output/wp8/Boo.Lang.dll $libmono/bare-minimum/wp8/Boo.Lang.dll*"); +cp("$output/wp8/Boo.Lang.pdb $libmono/bare-minimum/wp8/Boo.Lang.pdb*"); +cp("$output/UnityScript.Lang.* $libmono/bare-minimum/UnityScript.Lang.*"); + +if($ENV{UNITY_THISISABUILDMACHINE}) +{ + my %checkouts = ( + 'mono-classlibs' => 'BUILD_VCS_NUMBER_Mono____Mono2_6_x_Unity3_x', + 'boo' => 'BUILD_VCS_NUMBER_Boo', + 'unityscript' => 'BUILD_VCS_NUMBER_UnityScript', + 'cecil' => 'BUILD_VCS_NUMBER_Cecil' + ); + + system("echo '' > $root/builds/versions.txt"); + for my $key (keys %checkouts) { + system("echo \"$key = $ENV{$checkouts{$key}}\" >> $root/builds/versions.txt"); + } +} diff --git a/external/buildscripts/build_us_and_boo.pl b/external/buildscripts/build_us_and_boo.pl new file mode 100644 index 000000000000..ecbbd0da07e9 --- /dev/null +++ b/external/buildscripts/build_us_and_boo.pl @@ -0,0 +1,158 @@ +use Cwd; +use Cwd 'abs_path'; +use Getopt::Long; +use File::Basename; +use File::Path; +use File::Copy; +use lib ('.', 'perl_lib', 'external/buildscripts/perl_lib'); +use Tools qw(GitClone); + +system("source","~/.profile"); +print ">>> My Path: $ENV{PATH}\n"; + +my $monoroot = File::Spec->rel2abs(dirname(__FILE__) . "/../.."); +my $monoroot = abs_path($monoroot); +my $buildscriptsdir = "$monoroot/external/buildscripts"; +my $monoprefix = "$monoroot/tmp/monoprefix"; +my $buildsroot = "$monoroot/builds"; +my $buildMachine = $ENV{UNITY_THISISABUILDMACHINE}; + +GetOptions( + 'monoprefix=s'=>\$monoprefix, +) or die ("illegal cmdline options"); + +my $xbuildPath = "$monoprefix/bin/xbuild"; +my $monoprefix45 = "$monoprefix/lib/mono/4.5"; + +if (!(-f "$xbuildPath")) +{ + die("Unable to locate xbuild at : $xbuildPath\n"); +} + +BuildUnityScriptFor45(); + +sub XBuild +{ + print(">>> Running : $monoprefix/bin/xbuild @_\n"); + system("$monoprefix/bin/xbuild", @_) eq 0 or die("Failed to xbuild @_\n"); +} + +sub Booc45 +{ + my $commandLine = shift; + + system("$monoprefix/bin/mono $monoprefix45/booc.exe -debug- $commandLine") eq 0 or die("booc failed to execute: $monoprefix/bin/booc -debug- $commandLine\n"); +} + +sub BuildUnityScriptFor45 +{ + my $booCheckout = "$monoroot/../../boo/build"; + print(">>> Using mono prefix $monoprefix45\n"); + + # Build host is handling this + if (!$buildMachine) + { + if (!(-d "$booCheckout")) + { + print(">>> Checking out boo\n"); + GitClone("git://github.com/Unity-Technologies/boo.git", $booCheckout, "unity-trunk"); + } + } + + my $usCheckout = "$monoroot/../../unityscript/build"; + if (!$buildMachine) + { + if (!(-d "$usCheckout")) + { + print(">>> Checking out unity script\n"); + GitClone("git://github.com/Unity-Technologies/unityscript.git", $usCheckout, "unity-trunk"); + } + } + + my $boocCsproj = "$booCheckout/src/booc/booc.csproj"; + if (!(-f "$boocCsproj")) + { + die("Unable to locate : $boocCsproj\n"); + } + + XBuild("$boocCsproj", "/t:Rebuild"); + + print(">>> Mono Prefix 4.5 = $monoprefix45\n"); + foreach my $file (glob "$booCheckout/ide-build/Boo.Lang*.dll") + { + print(">>> Copying $file to $monoprefix45\n"); + copy($file, "$monoprefix45/."); + } + + copy("$booCheckout/ide-build/booc.exe", "$monoprefix45/."); + + foreach my $file (glob "$buildscriptsdir/add_to_build_results/monodistribution/lib/mono/4.5/*") + { + print(">>> Copying $file to $monoprefix45\n"); + copy($file, "$monoprefix45/."); + my $nameOnly = basename($file); + system("chmod", "755", "$monoprefix45/$nameOnly"); + } + + Booc45("-out:$monoprefix45/Boo.Lang.Extensions.dll -noconfig -nostdlib -srcdir:$booCheckout/src/Boo.Lang.Extensions -r:System.dll -r:System.Core.dll -r:mscorlib.dll -r:Boo.Lang.dll -r:Boo.Lang.Compiler.dll"); + Booc45("-out:$monoprefix45/Boo.Lang.Useful.dll -srcdir:$booCheckout/src/Boo.Lang.Useful -r:Boo.Lang.Parser"); + Booc45("-out:$monoprefix45/Boo.Lang.PatternMatching.dll -srcdir:$booCheckout/src/Boo.Lang.PatternMatching"); + + my $UnityScriptLangDLL = "$monoprefix45/UnityScript.Lang.dll"; + Booc45("-out:$UnityScriptLangDLL -srcdir:$usCheckout/src/UnityScript.Lang"); + + my $UnityScriptDLL = "$monoprefix45/UnityScript.dll"; + Booc45("-out:$UnityScriptDLL -srcdir:$usCheckout/src/UnityScript -r:$UnityScriptLangDLL -r:Boo.Lang.Parser.dll -r:Boo.Lang.PatternMatching.dll"); + Booc45("-out:$monoprefix45/us.exe -srcdir:$usCheckout/src/us -r:$UnityScriptLangDLL -r:$UnityScriptDLL -r:Boo.Lang.Useful.dll"); + + # # unityscript test suite + # my $UnityScriptTestsCSharpDLL = "$usCheckout/src/UnityScript.Tests.CSharp/bin/Debug/UnityScript.Tests.CSharp.dll"; + # XBuild("$usCheckout/src/UnityScript.Tests.CSharp/UnityScript.Tests.CSharp.csproj", "/t:Rebuild"); + + my $usBuildDir = "$usCheckout/build"; + + if (!(-d "$usBuildDir")) + { + rmtree($usBuildDir); + } + + mkdir($usBuildDir); + + # my $UnityScriptTestsDLL = <$usBuildDir/UnityScript.Tests.dll>; + # Booc("-out:$UnityScriptTestsDLL -srcdir:$usCheckout/src/UnityScript.Tests -r:$UnityScriptLangDLL -r:$UnityScriptDLL -r:$UnityScriptTestsCSharpDLL -r:Boo.Lang.Compiler.dll -r:Boo.Lang.Useful.dll"); + + # cp("$UnityScriptTestsCSharpDLL $usBuildDir/"); + print(">>> Populating Unity Script Build Directory : $usBuildDir\n"); + foreach my $file (glob "$monoprefix45/Boo.*") + { + print(">>> Copying $file to $usBuildDir\n"); + copy($file, "$usBuildDir/."); + } + + foreach my $file (glob "$monoprefix45/UnityScript.*") + { + print(">>> Copying $file to $usBuildDir\n"); + copy($file, "$usBuildDir/."); + } + + print(">>> Copying $monoprefix45/us.exe to $usBuildDir\n"); + copy("$monoprefix45/us.exe", "$usBuildDir/."); + print(">>> Copying $monoprefix45/booc.exe to $usBuildDir\n"); + copy("$monoprefix45/booc.exe", "$usBuildDir/."); + # put unityscript and boo into their own directories that we can reference for compilation only in Unity + my $usLibDir = "$monoprefix/lib/mono/unityscript"; + + if (!(-d "$usLibDir")) + { + print(">>> Removing directory $usLibDir\n"); + rmtree($usLibDir); + } + + mkdir($usLibDir); + + foreach my $file (glob "$usBuildDir/*") + { + print(">>> Copying $file to $usLibDir\n"); + copy($file, "$usLibDir/."); + } +} diff --git a/external/buildscripts/build_win_no_cygwin.pl b/external/buildscripts/build_win_no_cygwin.pl new file mode 100644 index 000000000000..17c0d6927a92 --- /dev/null +++ b/external/buildscripts/build_win_no_cygwin.pl @@ -0,0 +1,281 @@ +use Cwd; +use Cwd 'abs_path'; +use Getopt::Long; +use File::Basename; +use File::Path; +use File::Copy; +use lib ('external/buildscripts', "../../Tools/perl_lib","perl_lib", 'external/buildscripts/perl_lib'); +use Tools qw(InstallNameTool); + +print ">>> PATH in Build All = $ENV{PATH}\n\n"; + +my $currentdir = getcwd(); + +my $monoroot = File::Spec->rel2abs(dirname(__FILE__) . "/../.."); +my $monoroot = abs_path($monoroot); + +$monoroot =~ tr{/}{\\}; + +print ">>> monoroot = $monoroot\n"; + +my $buildscriptsdir = "$monoroot\\external\\buildscripts"; +my $addtoresultsdistdir = "$buildscriptsdir\\add_to_build_results\\monodistribution"; +my $monoprefix = "$monoroot\\tmp\\monoprefix"; +my $buildsroot = "$monoroot\\builds"; +my $distdir = "$buildsroot\\monodistribution"; +my $buildMachine = $ENV{UNITY_THISISABUILDMACHINE}; + +my $build=0; +my $clean=0; +my $artifact=0; +my $debug=0; +my $checkoutOnTheFly=0; +my $forceDefaultBuildDeps=0; +my $existingMonoRootPath = ''; +my $arch32 = 0; +my $winPerl = "perl"; +my $winMonoRoot = $monoroot; +my $msBuildVersion = "14.0"; +my $buildDeps = ""; + +print(">>> Build All Args = @ARGV\n"); + +GetOptions( + 'build=i'=>\$build, + 'clean=i'=>\$clean, + 'artifact=i'=>\$artifact, + 'debug=i'=>\$debug, + 'arch32=i'=>\$arch32, + 'existingmono=s'=>\$existingMonoRootPath, + 'winperl=s'=>\$winPerl, + 'winmonoroot=s'=>\$winMonoRoot, + 'msbuildversion=s'=>\$msBuildVersion, + 'checkoutonthefly=i'=>\$checkoutOnTheFly, + 'builddeps=s'=>\$buildDeps, + 'forcedefaultbuilddeps=i'=>\$forceDefaultBuildDeps, +) or die ("illegal cmdline options"); + +my $monoRevision = `git rev-parse HEAD`; +chdir("$buildscriptsdir") eq 1 or die ("failed to chdir : $buildscriptsdir\n"); +my $buildScriptsRevision = `git rev-parse HEAD`; +chdir("$monoroot") eq 1 or die ("failed to chdir : $monoroot\n"); + +print(">>> Mono Revision = $monoRevision\n"); +print(">>> Build Scripts Revision = $buildScriptsRevision\n"); + +# Do any settings agnostic per-platform stuff +my $externalBuildDeps = ""; + +if ($buildDeps ne "" && not $forceDefaultBuildDeps) +{ + $externalBuildDeps = $buildDeps; +} +else +{ + $externalBuildDeps = "$monoroot/../../mono-build-deps/build"; +} + +my $existingExternalMonoRoot = "$externalBuildDeps\\mono"; +my $existingExternalMono = "$existingExternalMonoRoot\\win"; + +if ($clean) +{ + print(">>> Cleaning $monoprefix\n"); + rmtree($monoprefix); +} + +# ******************* Build Stage ************************** + +if ($build) +{ + if ($existingMonoRootPath eq "") + { + print(">>> No existing mono supplied. Checking for external...\n"); + + if (!(-d "$externalBuildDeps")) + { + if (not $checkoutonthefly) + { + print(">>> No external build deps found. Might as well try to check them out. If it fails, we'll continue and trust mono is in your PATH\n"); + } + + # Check out on the fly + print(">>> Checking out mono build dependencies to : $externalBuildDeps\n"); + my $repo = "https://ono.unity3d.com/unity-extra/mono-build-deps"; + print(">>> Cloning $repo at $externalBuildDeps\n"); + my $checkoutResult = system("hg", "clone", $repo, "$externalBuildDeps"); + + if ($checkoutOnTheFly && $checkoutResult ne 0) + { + die("failed to checkout mono build dependencies\n"); + } + } + + if (-d "$existingExternalMono") + { + print(">>> External mono found at : $existingExternalMono\n"); + + if (-d "$existingExternalMono/builds") + { + print(">>> Mono already extracted at : $existingExternalMono/builds\n"); + } + + if (!(-d "$existingExternalMono/builds")) + { + # We need to extract builds.zip + print(">>> Extracting mono builds.zip...\n"); + my $SevenZip = "$externalBuildDeps/7z/win64/7za.exe"; + print(">>> Using 7z : $SevenZip\n"); + system("$SevenZip", "x", "$existingExternalMono/builds.zip", "-o$existingExternalMono") eq 0 or die("Failed extracting mono builds.zip\n"); + } + + $existingMonoRootPath = "$existingExternalMono/builds"; + } + else + { + print(">>> No external mono found. Trusting a new enough mono is in your PATH.\n"); + } + } + + if ($existingMonoRootPath ne "" && !(-d $existingMonoRootPath)) + { + die("Existing mono not found at : $existingMonoRootPath\n"); + } + + system("$winPerl", "$winMonoRoot/external/buildscripts/build_runtime_vs.pl", "--build=$build", "--arch32=$arch32", "--msbuildversion=$msBuildVersion", "--clean=$clean", "--debug=$debug", "--gc=bdwgc") eq 0 or die ('failed building mono bdwgc with VS\n'); + system("$winPerl", "$winMonoRoot/external/buildscripts/build_runtime_vs.pl", "--build=$build", "--arch32=$arch32", "--msbuildversion=$msBuildVersion", "--clean=$clean", "--debug=$debug", "--gc=sgen") eq 0 or die ('failed building mono sgen with VS\n'); + + if (!(-d "$monoroot\\tmp")) + { + print(">>> Creating directory $monoroot\\tmp\n"); + system("mkdir $monoroot\\tmp") eq 0 or die ("failing creating $monoroot\\tmp\n");; + } + + if (!(-d "$monoprefix")) + { + print(">>> Creating directory $monoprefix\n"); + system("mkdir $monoprefix") eq 0 or die ("failing creating $monoprefix\n");; + } + + if (!(-d "$monoprefix\\bin")) + { + print(">>> Creating directory $monoprefix\\bin\n"); + system("mkdir $monoprefix\\bin") eq 0 or die ("failing creating $monoprefix\\bin\n");; + } + + # Copy over the VS built stuff that we want to use instead into the prefix directory + my $archNameForBuild = $arch32 ? 'Win32' : 'x64'; + my $configDirName = $debug ? "Debug" : "Release"; + + copy("$monoroot/msvc/build/bdwgc/$archNameForBuild/bin/$configDirName/mono-bdwgc.exe", "$monoprefix/bin/.") or die ("failed copying mono-bdwgc.exe\n"); + copy("$monoroot/msvc/build/bdwgc/$archNameForBuild/bin/$configDirName/mono-2.0-bdwgc.dll", "$monoprefix/bin/.") or die ("failed copying mono-2.0-bdwgc.dll\n"); + copy("$monoroot/msvc/build/bdwgc/$archNameForBuild/bin/$configDirName/mono-2.0-bdwgc.pdb", "$monoprefix/bin/.") or die ("failed copying mono-2.0-bdwgc.pdb\n"); + + copy("$monoroot/msvc/build/sgen/$archNameForBuild/bin/$configDirName/mono-sgen.exe", "$monoprefix/bin/.") or die ("failed copying mono-sgen.exe\n"); + copy("$monoroot/msvc/build/sgen/$archNameForBuild/bin/$configDirName/mono-2.0-sgen.dll", "$monoprefix/bin/.") or die ("failed copying mono-2.0-sgen.dll\n"); + copy("$monoroot/msvc/build/sgen/$archNameForBuild/bin/$configDirName/mono-2.0-sgen.pdb", "$monoprefix/bin/.") or die ("failed copying mono-2.0-sgen.pdb\n"); + + # sgen as default exe + copy("$monoroot/msvc/build/sgen/$archNameForBuild/bin/$configDirName/mono-sgen.exe", "$monoprefix/bin/mono.exe") or die ("failed copying mono-sgen.exe to mono.exe\n"); + + copy("$monoroot/msvc/build/bdwgc/$archNameForBuild/bin/$configDirName/MonoPosixHelper.dll", "$monoprefix/bin/.") or die ("failed copying MonoPosixHelper.dll\n"); + copy("$monoroot/msvc/build/bdwgc/$archNameForBuild/bin/$configDirName/MonoPosixHelper.pdb", "$monoprefix/bin/.") or die ("failed copying MonoPosixHelper.pdb\n"); + + system("xcopy /y /f $addtoresultsdistdir\\bin\\*.* $monoprefix\\bin\\") eq 0 or die ("Failed copying $addtoresultsdistdir/bin to $monoprefix/bin\n"); +} + +# ******************* Artifact Stage ************************** + +if ($artifact) +{ + print(">>> Creating artifact...\n"); + + # Do the platform specific logic to create the builds output structure that we want + + my $embedDirRoot = "$buildsroot\\embedruntimes"; + + my $embedDirArchDestination = $arch32 ? "$embedDirRoot\\win32" : "$embedDirRoot\\win64"; + my $distDirArchBin = $arch32 ? "$distdir\\bin" : "$distdir\\bin-x64"; + my $versionsOutputFile = $arch32 ? "$buildsroot\\versions-win32.txt" : "$buildsroot\\versions-win64.txt"; + + # Make sure the directory for our architecture is clean before we copy stuff into it + if (-d "$embedDirArchDestination") + { + print(">>> Cleaning $embedDirArchDestination\n"); + rmtree($embedDirArchDestination); + } + + if (-d "$distDirArchBin") + { + print(">>> Cleaning $distDirArchBin\n"); + rmtree($distDirArchBin); + } + + if (!(-d "$buildsroot")) + { + print(">>> Creating directory $buildsroot\n"); + system("mkdir $buildsroot") eq 0 or die("failed to create directory $buildsroot\n"); + } + + if (!(-d "$embedDirRoot")) + { + print(">>> Creating directory $embedDirRoot\n"); + system("mkdir $embedDirRoot") eq 0 or die("failed to create directory $embedDirRoot\n"); + } + + if (!(-d "$distdir")) + { + print(">>> Creating directory $distdir\n"); + system("mkdir $distdir") eq 0 or die("failed to create directory $distdir\n"); + } + + print(">>> Creating directory $embedDirArchDestination\n"); + system("mkdir $embedDirArchDestination") eq 0 or die("failed to create directory $embedDirArchDestination\n"); + + print(">>> Creating directory $distDirArchBin\n"); + system("mkdir $distDirArchBin") eq 0 or die("failed to create directory $distDirArchBin\n"); + + # embedruntimes directory setup + print(">>> Creating embedruntimes directory : $embedDirArchDestination\n"); + + copy("$monoprefix/bin/mono-2.0-bdwgc.dll", "$embedDirArchDestination/.") or die ("failed copying mono-2.0-bdwgc.dll\n"); + copy("$monoprefix/bin/mono-2.0-bdwgc.pdb", "$embedDirArchDestination/.") or die ("failed copying mono-2.0-bdwgc.pdb\n"); + + copy("$monoprefix/bin/mono-2.0-sgen.dll", "$embedDirArchDestination/.") or die ("failed copying mono-2.0-sgen.dll\n"); + copy("$monoprefix/bin/mono-2.0-sgen.pdb", "$embedDirArchDestination/.") or die ("failed copying mono-2.0-sgen.pdb\n"); + + copy("$monoprefix/bin/MonoPosixHelper.dll", "$embedDirArchDestination/.") or die ("failed copying MonoPosixHelper.dll\n"); + copy("$monoprefix/bin/MonoPosixHelper.pdb", "$embedDirArchDestination/.") or die ("failed copying MonoPosixHelper.pdb\n"); + + # monodistribution directory setup + print(">>> Creating monodistribution directory\n"); + copy("$monoprefix/bin/mono-2.0-bdwgc.dll", "$distDirArchBin/.") or die ("failed copying mono-2.0-bdwgc.dll\n"); + copy("$monoprefix/bin/mono-2.0-bdwgc.pdb", "$distDirArchBin/.") or die ("failed copying mono-2.0-bdwgc.pdb\n"); + + copy("$monoprefix/bin/mono-2.0-sgen.dll", "$distDirArchBin/.") or die ("failed copying mono-2.0-sgen.dll\n"); + copy("$monoprefix/bin/mono-2.0-sgen.pdb", "$distDirArchBin/.") or die ("failed copying mono-2.0-sgen.pdb\n"); + + copy("$monoprefix/bin/mono-sgen.exe", "$distDirArchBin/.") or die ("failed copying mono-sgen.exe\n"); + copy("$monoprefix/bin/mono-bdwgc.exe", "$distDirArchBin/.") or die ("failed copying mono-bdwgc.exe\n"); + copy("$monoprefix/bin/mono.exe", "$distDirArchBin/.") or die ("failed copying mono.exe\n"); + + copy("$monoprefix/bin/MonoPosixHelper.dll", "$distDirArchBin/.") or die ("failed copying MonoPosixHelper.dll\n"); + copy("$monoprefix/bin/MonoPosixHelper.pdb", "$distDirArchBin/.") or die ("failed copying MonoPosixHelper.pdb\n"); + + + # Output version information + print(">>> Creating version file : $versionsOutputFile\n"); + open(my $fh, '>', $versionsOutputFile) or die "Could not open file '$versionsOutputFile' $!"; + say $fh "mono-version ="; + my $monoVersionInfo = `$distDirArchBin\\mono --version`; + say $fh "$monoVersionInfo"; + say $fh "unity-mono-revision = $monoRevision"; + say $fh "unity-mono-build-scripts-revision = $buildScriptsRevision"; + my $tmp = `date /T`; + say $fh "$tmp"; + close $fh; +} +else +{ + print(">>> Skipping artifact creation\n"); +} diff --git a/external/buildscripts/build_win_wrapper.pl b/external/buildscripts/build_win_wrapper.pl new file mode 100644 index 000000000000..bbe16f80b94b --- /dev/null +++ b/external/buildscripts/build_win_wrapper.pl @@ -0,0 +1,218 @@ +use Cwd; +use Cwd 'abs_path'; +use Getopt::Long; +use File::Basename; +use File::Path; +use Config; + +print ">>> My Path: $ENV{PATH}\n\n"; + +my $monoroot = File::Spec->rel2abs(dirname(__FILE__) . "/../.."); +my $monoroot = abs_path($monoroot); +my $buildScriptsRoot = "$monoroot/external/buildscripts"; +print ">>> Mono checkout found in $monoroot\n\n"; + +my $cygwinRootWindows = ""; +my $monoInstallLinux = ""; +my $checkoutOnTheFly=0; +my $buildDeps = ""; +my $forceDefaultBuildDeps = 0; + +my @thisScriptArgs = (); +my @passAlongArgs = (); +foreach my $arg (@ARGV) +{ + push @backupArgs, $arg; + + if ($arg =~ /^--cygwin=/) + { + push @thisScriptArgs, $arg; + } + elsif ($arg =~ /^--existingmono=/) + { + push @thisScriptArgs, $arg; + } + elsif ($arg =~ /^--checkoutonthefly=/) + { + push @thisScriptArgs, $arg; + push @passAlongArgs, $arg; + } + elsif ($arg =~ /^--builddeps=/) + { + push @thisScriptArgs, $arg; + push @passAlongArgs, $arg; + } + elsif ($arg =~ /^--forcedefaultbuilddeps=/) + { + push @thisScriptArgs, $arg; + push @passAlongArgs, $arg; + } + else + { + push @passAlongArgs, $arg; + } +} + +print(">>> This Script Args = @thisScriptArgs\n"); +print(">>> Pass Along Args = @passAlongArgs\n"); + +@ARGV = @thisScriptArgs; +GetOptions( + 'cygwin=s'=>\$cygwinRootWindows, + 'existingmono=s'=>\$monoInstallLinux, + 'checkoutonthefly=i'=>\$checkoutOnTheFly, + 'builddeps=s'=>\$buildDeps, + 'forcedefaultbuilddeps=i'=>\$forceDefaultBuildDeps, +); + +my $externalBuildDeps = ""; + +if ($buildDeps ne "") +{ + $externalBuildDeps = $buildDeps; +} +else +{ + if (-d "$monoroot/../../mono-build-deps/build" || $forceDefaultBuildDeps) + { + $externalBuildDeps = "$monoroot/../../mono-build-deps/build"; + } + + if (!(-d "$externalBuildDeps")) + { + if (not $checkoutonthefly && $cygwinRootWindows eq "") + { + print(">>> No external build deps found and --cygwin not used. Might as well try to check them out. If the checkout fails, we'll continue, but the build will probably fail\n"); + } + + # Check out on the fly + print(">>> Checking out mono build dependencies to : $externalBuildDeps\n"); + my $repo = "https://ono.unity3d.com/unity-extra/mono-build-deps"; + print(">>> Cloning $repo at $externalBuildDeps\n"); + my $checkoutResult = system("hg", "clone", $repo, "$externalBuildDeps"); + + if ($checkoutOnTheFly && $checkoutResult ne 0) + { + die("failed to checkout mono build dependencies\n"); + } + } +} + +print(">>> externalBuildDeps = $externalBuildDeps\n"); + +my $SevenZip = "$externalBuildDeps/7z/win64/7za.exe"; + +# Attempt to find common default cygwin install locations +if ($cygwinRootWindows eq "") +{ + print(">>> No cygwin install specified. Looking for defaults...\n"); + + my $externalCygwin = "$externalBuildDeps/cygwin64/builds"; + my $externalCygwinZip = "$externalBuildDeps/cygwin64/builds.zip"; + + if (-d "$externalCygwin") + { + $cygwinRootWindows = $externalCygwin; + print(">>> Found Cygwin at : $cygwinRootWindows\n"); + } + elsif(-f "$externalCygwinZip") + { + print(">>> Found unextracted cygwin builds.zip : $externalCygwinZip\n"); + print(">>> Using 7z : $SevenZip\n"); + print(">>> Extracting...\n"); + system("$SevenZip", "x", "$externalCygwinZip", "-o$externalBuildDeps/cygwin64") eq 0 or die("Failed extracting cygwin\n"); + $cygwinRootWindows = $externalCygwin; + } + else + { + if ($forceDefaultBuildDeps) + { + die("\nCould not fined Cygwin in default external build deps location : $externalBuildDeps\n") + } + else + { + if (-d "C:\\Cygwin64") + { + $cygwinRootWindows = "C:\\Cygwin64"; + print(">>> Found Cygwin at : $cygwinRootWindows\n"); + } + elsif (-d "C:\\Cygwin") + { + $cygwinRootWindows = "C:\\Cygwin"; + print(">>> Found Cygwin at : $cygwinRootWindows\n"); + } + else + { + die("\nCould not fined Cygwin. Define path using --cygwin=\n") + } + } + } +} +else +{ + print(">>> Cygwin Path = $cygwinRootWindows\n"); +} + +if ($monoInstallLinux eq "") +{ + print(">>> No mono install specified. Looking for defaults...\n"); + + my $externalMono = "$externalBuildDeps/mono/win/builds"; + my $externalMonoZip = "$externalBuildDeps/mono/win/builds.zip"; + + if (-d "$externalMono") + { + $monoInstallLinux = $externalMono; + $monoInstallLinux =~ s/\\/\//g; + print(">>> Found Mono at : $monoInstallLinux\n"); + } + elsif(-f "$externalMonoZip") + { + print(">>> Found unextracted mono builds.zip : $externalMonoZip\n"); + print(">>> Using 7z : $SevenZip\n"); + print(">>> Extracting...\n"); + system("$SevenZip", "x", "$externalMonoZip", "-o$externalBuildDeps/mono/win") eq 0 or die("Failed extracting mono\n"); + $monoInstallLinux = $externalMono; + $monoInstallLinux =~ s/\\/\//g; + print(">>> Found Mono at : $monoInstallLinux\n"); + } + else + { + if ($forceDefaultBuildDeps) + { + die("\nCould not fined mono in default external build deps location : $externalBuildDeps\n") + } + else + { + if (-d "C:\\Program Files (x86)\\Mono") + { + # Pass over the cygwin format since I already have it escaped correctly to survive + # crossing over the shell + $monoInstallLinux = "/cygdrive/c/Program\\ Files\\ \\(x86\\)/Mono"; + print(">>> Found Mono at : $monoInstallLinux\n"); + } + else + { + die("\n--existingmono= is required and should be in the cygwin path format\n"); + } + } + } +} +else +{ + $monoInstallLinux =~ s/\\/\//g; + print(">>> Linux Mono Path = $monoInstallLinux\n"); +} + +push @passAlongArgs, "--existingmono=$monoInstallLinux" if $monoInstallLinux ne ""; + +my $windowsPerl = $Config{perlpath}; +print ">>> Perl Exe = $windowsPerl\n"; +push @passAlongArgs, "--winperl=$windowsPerl"; +push @passAlongArgs, "--winmonoroot=$monoroot"; + +# In some cases the file gets windowsified, use SHELLOPTS to avoid issues instead of dos2unixing the file, which will cause it to show up as modified by source control +$ENV{'SHELLOPTS'} = "igncr"; + +print ">>> Calling $cygwinRootWindows\\bin\\sh.exe with @passAlongArgs"; +system("$cygwinRootWindows\\bin\\sh.exe", "$monoroot/external/buildscripts/build_win_wrapper.sh", @passAlongArgs) eq 0 or die("failed building mono\n"); diff --git a/external/buildscripts/build_win_wrapper.sh b/external/buildscripts/build_win_wrapper.sh new file mode 100644 index 000000000000..c71964f87986 --- /dev/null +++ b/external/buildscripts/build_win_wrapper.sh @@ -0,0 +1,12 @@ +#!/bin/sh + +# Need to put the cygwin stuff into our PATH +export PATH=/usr/bin:$PATH +BUILD_SCRIPT_ROOT=$(dirname $0) + +echo ">>> Build Script Root = $BUILD_SCRIPT_ROOT" +echo +echo ">>> PATH in Win Shell Script = $PATH" +echo + +perl "$BUILD_SCRIPT_ROOT/build.pl" "$@" \ No newline at end of file diff --git a/external/buildscripts/collect_allbuilds.pl b/external/buildscripts/collect_allbuilds.pl new file mode 100644 index 000000000000..71ba0b01e2de --- /dev/null +++ b/external/buildscripts/collect_allbuilds.pl @@ -0,0 +1,46 @@ +use lib ('external/buildscripts/perl_lib'); +use File::Copy::Recursive qw(dircopy rmove); +use File::Path; +use Tools qw(InstallNameTool); + +my $path = "incomingbuilds/"; + +rmtree("collectedbuilds"); +mkpath("collectedbuilds"); + +my @folders = (); +opendir(DIR, $path) or die "cant find $path: $!"; +# Sort the directories alphabetically so that classlibs comes before the +# OSX universal runtime (in the osx-i386 directory). Both builds produce the same +# files in some cases (notably libMonoPosixHelper.dylib), and we need the +# universal runtime build to be second, since it produces a universal binary +# and the classlibs build produces a 32-bit binary only. +my @files = sort readdir(DIR); +while (defined(my $file = shift @files)) { + + next if $file =~ /^\.\.?$/; + if (-d "$path$file"){ + if (-f "$path$file/versions.txt") { + system("cat $path$file/versions.txt >> collectedbuilds/versions-aggregated.txt"); + } + dircopy("$path$file","collectedbuilds/") or die ("failed copying $path$file"); + push @folders,"$path$file"; + } +} +closedir(DIR); + +system("find collectedbuilds -type f -name mono -exec chmod +x {} \\;") eq 0 or die("Failed chmodding"); +system("find collectedbuilds -type f -name mono-sgen -exec chmod +x {} \\;") eq 0 or die("Failed chmodding"); +system("find collectedbuilds -type f -name pedump -exec chmod +x {} \\;") eq 0 or die("Failed chmodding"); + +chdir("collectedbuilds"); + +rmove('versions-aggregated.txt', 'versions.txt'); + +open(MYFILE,">built_by_teamcity.txt"); +print MYFILE "These builds were created by teamcity from svn revision $ENV{BUILD_VCS_NUMBER}\n"; +print MYFILE "TC projectname was: $ENV{TEAMCITY_PROJECT_NAME}\n"; +print MYFILE "TC buildconfigname was: $ENV{TEAMCITY_BUILDCONF_NAME}\n"; +close(MYFILE); + +system("zip -r builds.zip *") eq 0 or die("failed zipping up builds"); diff --git a/external/buildscripts/perl_lib/File/Copy/Recursive.pm b/external/buildscripts/perl_lib/File/Copy/Recursive.pm new file mode 100644 index 000000000000..c5fb2576f8df --- /dev/null +++ b/external/buildscripts/perl_lib/File/Copy/Recursive.pm @@ -0,0 +1,696 @@ +package File::Copy::Recursive; + +use strict; +BEGIN { + # Keep older versions of Perl from trying to use lexical warnings + $INC{'warnings.pm'} = "fake warnings entry for < 5.6 perl ($])" if $] < 5.006; +} +use warnings; + +use Carp; +use File::Copy; +use File::Spec; #not really needed because File::Copy already gets it, but for good measure :) + +use vars qw( + @ISA @EXPORT_OK $VERSION $MaxDepth $KeepMode $CPRFComp $CopyLink + $PFSCheck $RemvBase $NoFtlPth $ForcePth $CopyLoop $RMTrgFil $RMTrgDir + $CondCopy $BdTrgWrn $SkipFlop $DirPerms +); + +require Exporter; +@ISA = qw(Exporter); +@EXPORT_OK = qw(fcopy rcopy dircopy fmove rmove dirmove pathmk pathrm pathempty pathrmdir); +$VERSION = '0.38'; + +$MaxDepth = 0; +$KeepMode = 1; +$CPRFComp = 0; +$CopyLink = eval { local $SIG{'__DIE__'};symlink '',''; 1 } || 0; +$PFSCheck = 1; +$RemvBase = 0; +$NoFtlPth = 0; +$ForcePth = 0; +$CopyLoop = 0; +$RMTrgFil = 0; +$RMTrgDir = 0; +$CondCopy = {}; +$BdTrgWrn = 0; +$SkipFlop = 0; +$DirPerms = 0777; + +my $samecheck = sub { + return 1 if $^O eq 'MSWin32'; # need better way to check for this on winders... + return if @_ != 2 || !defined $_[0] || !defined $_[1]; + return if $_[0] eq $_[1]; + + my $one = ''; + if($PFSCheck) { + $one = join( '-', ( stat $_[0] )[0,1] ) || ''; + my $two = join( '-', ( stat $_[1] )[0,1] ) || ''; + if ( $one eq $two && $one ) { + carp "$_[0] and $_[1] are identical"; + return; + } + } + + if(-d $_[0] && !$CopyLoop) { + $one = join( '-', ( stat $_[0] )[0,1] ) if !$one; + my $abs = File::Spec->rel2abs($_[1]); + my @pth = File::Spec->splitdir( $abs ); + while(@pth) { + my $cur = File::Spec->catdir(@pth); + last if !$cur; # probably not necessary, but nice to have just in case :) + my $two = join( '-', ( stat $cur )[0,1] ) || ''; + if ( $one eq $two && $one ) { + # $! = 62; # Too many levels of symbolic links + carp "Caught Deep Recursion Condition: $_[0] contains $_[1]"; + return; + } + + pop @pth; + } + } + + return 1; +}; + +my $glob = sub { + my ($do, $src_glob, @args) = @_; + + local $CPRFComp = 1; + + my @rt; + for my $path ( glob($src_glob) ) { + my @call = [$do->($path, @args)] or return; + push @rt, \@call; + } + + return @rt; +}; + +my $move = sub { + my $fl = shift; + my @x; + if($fl) { + @x = fcopy(@_) or return; + } else { + @x = dircopy(@_) or return; + } + if(@x) { + if($fl) { + unlink $_[0] or return; + } else { + pathrmdir($_[0]) or return; + } + if($RemvBase) { + my ($volm, $path) = File::Spec->splitpath($_[0]); + pathrm(File::Spec->catpath($volm,$path,''), $ForcePth, $NoFtlPth) or return; + } + } + return wantarray ? @x : $x[0]; +}; + +my $ok_todo_asper_condcopy = sub { + my $org = shift; + my $copy = 1; + if(exists $CondCopy->{$org}) { + if($CondCopy->{$org}{'md5'}) { + + } + if($copy) { + + } + } + return $copy; +}; + +sub fcopy { + $samecheck->(@_) or return; + if($RMTrgFil && (-d $_[1] || -e $_[1]) ) { + my $trg = $_[1]; + if( -d $trg ) { + my @trgx = File::Spec->splitpath( $_[0] ); + $trg = File::Spec->catfile( $_[1], $trgx[ $#trgx ] ); + } + $samecheck->($_[0], $trg) or return; + if(-e $trg) { + if($RMTrgFil == 1) { + unlink $trg or carp "\$RMTrgFil failed: $!"; + } else { + unlink $trg or return; + } + } + } + my ($volm, $path) = File::Spec->splitpath($_[1]); + if($path && !-d $path) { + pathmk(File::Spec->catpath($volm,$path,''), $NoFtlPth); + } + if( -l $_[0] && $CopyLink ) { + carp "Copying a symlink ($_[0]) whose target does not exist" + if !-e readlink($_[0]) && $BdTrgWrn; + symlink readlink(shift()), shift() or return; + } else { + copy(@_) or return; + + my @base_file = File::Spec->splitpath($_[0]); + my $mode_trg = -d $_[1] ? File::Spec->catfile($_[1], $base_file[ $#base_file ]) : $_[1]; + + chmod scalar((stat($_[0]))[2]), $mode_trg if $KeepMode; + } + return wantarray ? (1,0,0) : 1; # use 0's incase they do math on them and in case rcopy() is called in list context = no uninit val warnings +} + +sub rcopy { + if (-l $_[0] && $CopyLink) { + goto &fcopy; + } + + goto &dircopy if -d $_[0] || substr( $_[0], ( 1 * -1), 1) eq '*'; + goto &fcopy; +} + +sub rcopy_glob { + $glob->(\&rcopy, @_); +} + +sub dircopy { + if($RMTrgDir && -d $_[1]) { + if($RMTrgDir == 1) { + pathrmdir($_[1]) or carp "\$RMTrgDir failed: $!"; + } else { + pathrmdir($_[1]) or return; + } + } + my $globstar = 0; + my $_zero = $_[0]; + my $_one = $_[1]; + if ( substr( $_zero, ( 1 * -1 ), 1 ) eq '*') { + $globstar = 1; + $_zero = substr( $_zero, 0, ( length( $_zero ) - 1 ) ); + } + + $samecheck->( $_zero, $_[1] ) or return; + if ( !-d $_zero || ( -e $_[1] && !-d $_[1] ) ) { + $! = 20; + return; + } + + if(!-d $_[1]) { + pathmk($_[1], $NoFtlPth) or return; + } else { + if($CPRFComp && !$globstar) { + my @parts = File::Spec->splitdir($_zero); + while($parts[ $#parts ] eq '') { pop @parts; } + $_one = File::Spec->catdir($_[1], $parts[$#parts]); + } + } + my $baseend = $_one; + my $level = 0; + my $filen = 0; + my $dirn = 0; + + my $recurs; #must be my()ed before sub {} since it calls itself + $recurs = sub { + my ($str,$end,$buf) = @_; + $filen++ if $end eq $baseend; + $dirn++ if $end eq $baseend; + + $DirPerms = oct($DirPerms) if substr($DirPerms,0,1) eq '0'; + mkdir($end,$DirPerms) or return if !-d $end; + chmod scalar((stat($str))[2]), $end if $KeepMode; + if($MaxDepth && $MaxDepth =~ m/^\d+$/ && $level >= $MaxDepth) { + return ($filen,$dirn,$level) if wantarray; + return $filen; + } + $level++; + + + my @files; + if ( $] < 5.006 ) { + opendir(STR_DH, $str) or return; + @files = grep( $_ ne '.' && $_ ne '..', readdir(STR_DH)); + closedir STR_DH; + } + else { + opendir(my $str_dh, $str) or return; + @files = grep( $_ ne '.' && $_ ne '..', readdir($str_dh)); + closedir $str_dh; + } + + for my $file (@files) { + my ($file_ut) = $file =~ m{ (.*) }xms; + my $org = File::Spec->catfile($str, $file_ut); + my $new = File::Spec->catfile($end, $file_ut); + if( -l $org && $CopyLink ) { + carp "Copying a symlink ($org) whose target does not exist" + if !-e readlink($org) && $BdTrgWrn; + symlink readlink($org), $new or return; + } + elsif(-d $org) { + $recurs->($org,$new,$buf) if defined $buf; + $recurs->($org,$new) if !defined $buf; + $filen++; + $dirn++; + } + else { + if($ok_todo_asper_condcopy->($org)) { + if($SkipFlop) { + fcopy($org,$new,$buf) or next if defined $buf; + fcopy($org,$new) or next if !defined $buf; + } + else { + fcopy($org,$new,$buf) or return if defined $buf; + fcopy($org,$new) or return if !defined $buf; + } + chmod scalar((stat($org))[2]), $new if $KeepMode; + $filen++; + } + } + } + 1; + }; + + $recurs->($_zero, $_one, $_[2]) or return; + return wantarray ? ($filen,$dirn,$level) : $filen; +} + +sub fmove { $move->(1, @_) } + +sub rmove { + if (-l $_[0] && $CopyLink) { + goto &fmove; + } + + goto &dirmove if -d $_[0] || substr( $_[0], ( 1 * -1), 1) eq '*'; + goto &fmove; +} + +sub rmove_glob { + $glob->(\&rmove, @_); +} + +sub dirmove { $move->(0, @_) } + +sub pathmk { + my @parts = File::Spec->splitdir( shift() ); + my $nofatal = shift; + my $pth = $parts[0]; + my $zer = 0; + if(!$pth) { + $pth = File::Spec->catdir($parts[0],$parts[1]); + $zer = 1; + } + for($zer..$#parts) { + $DirPerms = oct($DirPerms) if substr($DirPerms,0,1) eq '0'; + mkdir($pth,$DirPerms) or return if !-d $pth && !$nofatal; + mkdir($pth,$DirPerms) if !-d $pth && $nofatal; + $pth = File::Spec->catdir($pth, $parts[$_ + 1]) unless $_ == $#parts; + } + 1; +} + +sub pathempty { + my $pth = shift; + + return 2 if !-d $pth; + + my @names; + my $pth_dh; + if ( $] < 5.006 ) { + opendir(PTH_DH, $pth) or return; + @names = grep !/^\.+$/, readdir(PTH_DH); + } + else { + opendir($pth_dh, $pth) or return; + @names = grep !/^\.+$/, readdir($pth_dh); + } + + for my $name (@names) { + my ($name_ut) = $name =~ m{ (.*) }xms; + my $flpth = File::Spec->catdir($pth, $name_ut); + + if( -l $flpth ) { + unlink $flpth or return; + } + elsif(-d $flpth) { + pathrmdir($flpth) or return; + } + else { + unlink $flpth or return; + } + } + + if ( $] < 5.006 ) { + closedir PTH_DH; + } + else { + closedir $pth_dh; + } + + 1; +} + +sub pathrm { + my $path = shift; + return 2 if !-d $path; + my @pth = File::Spec->splitdir( $path ); + my $force = shift; + + while(@pth) { + my $cur = File::Spec->catdir(@pth); + last if !$cur; # necessary ??? + if(!shift()) { + pathempty($cur) or return if $force; + rmdir $cur or return; + } + else { + pathempty($cur) if $force; + rmdir $cur; + } + pop @pth; + } + 1; +} + +sub pathrmdir { + my $dir = shift; + if( -e $dir ) { + return if !-d $dir; + } + else { + return 2; + } + + pathempty($dir) or return; + + rmdir $dir or return; +} + +1; + +__END__ + +=head1 NAME + +File::Copy::Recursive - Perl extension for recursively copying files and directories + +=head1 SYNOPSIS + + use File::Copy::Recursive qw(fcopy rcopy dircopy fmove rmove dirmove); + + fcopy($orig,$new[,$buf]) or die $!; + rcopy($orig,$new[,$buf]) or die $!; + dircopy($orig,$new[,$buf]) or die $!; + + fmove($orig,$new[,$buf]) or die $!; + rmove($orig,$new[,$buf]) or die $!; + dirmove($orig,$new[,$buf]) or die $!; + + rcopy_glob("orig/stuff-*", $trg [, $buf]) or die $!; + rmove_glob("orig/stuff-*", $trg [,$buf]) or die $!; + +=head1 DESCRIPTION + +This module copies and moves directories recursively (or single files, well... singley) to an optional depth and attempts to preserve each file or directory's mode. + +=head1 EXPORT + +None by default. But you can export all the functions as in the example above and the path* functions if you wish. + +=head2 fcopy() + +This function uses File::Copy's copy() function to copy a file but not a directory. Any directories are recursively created if need be. +One difference to File::Copy::copy() is that fcopy attempts to preserve the mode (see Preserving Mode below) +The optional $buf in the synopsis if the same as File::Copy::copy()'s 3rd argument +returns the same as File::Copy::copy() in scalar context and 1,0,0 in list context to accomidate rcopy()'s list context on regular files. (See below for more info) + +=head2 dircopy() + +This function recursively traverses the $orig directory's structure and recursively copies it to the $new directory. +$new is created if necessary (multiple non existant directories is ok (IE foo/bar/baz). The script logically and portably creates all of them if necessary). +It attempts to preserve the mode (see Preserving Mode below) and +by default it copies all the way down into the directory, (see Managing Depth) below. +If a directory is not specified it croaks just like fcopy croaks if its not a file that is specified. + +returns true or false, for true in scalar context it returns the number of files and directories copied, +In list context it returns the number of files and directories, number of directories only, depth level traversed. + + my $num_of_files_and_dirs = dircopy($orig,$new); + my($num_of_files_and_dirs,$num_of_dirs,$depth_traversed) = dircopy($orig,$new); + +Normally it stops and return's if a copy fails, to continue on regardless set $File::Copy::Recursive::SkipFlop to true. + + local $File::Copy::Recursive::SkipFlop = 1; + +That way it will copy everythgingit can ina directory and won't stop because of permissions, etc... + +=head2 rcopy() + +This function will allow you to specify a file *or* directory. It calls fcopy() if its a file and dircopy() if its a directory. +If you call rcopy() (or fcopy() for that matter) on a file in list context, the values will be 1,0,0 since no directories and no depth are used. +This is important becasue if its a directory in list context and there is only the initial directory the return value is 1,1,1. + +=head2 rcopy_glob() + +This function lets you specify a pattern suitable for perl's glob() as the first argument. Subsequently each path returned by perl's glob() gets rcopy()ied. + +It returns and array whose items are array refs that contain the return value of each rcopy() call. + +It forces behavior as if $File::Copy::Recursive::CPRFComp is true. + +=head2 fmove() + +Copies the file then removes the original. You can manage the path the original file is in according to $RemvBase. + +=head2 dirmove() + +Uses dircopy() to copy the directory then removes the original. You can manage the path the original directory is in according to $RemvBase. + +=head2 rmove() + +Like rcopy() but calls fmove() or dirmove() instead. + +=head2 rmove_glob() + +Like rcopy_glob() but calls rmove() instead of rcopy() + +=head3 $RemvBase + +Default is false. When set to true the *move() functions will not only attempt to remove the original file or directory but will remove the given path it is in. + +So if you: + + rmove('foo/bar/baz', '/etc/'); + # "baz" is removed from foo/bar after it is successfully copied to /etc/ + + local $File::Copy::Recursive::Remvbase = 1; + rmove('foo/bar/baz','/etc/'); + # if baz is successfully copied to /etc/ : + # first "baz" is removed from foo/bar + # then "foo/bar is removed via pathrm() + +=head4 $ForcePth + +Default is false. When set to true it calls pathempty() before any directories are removed to empty the directory so it can be rmdir()'ed when $RemvBase is in effect. + +=head2 Creating and Removing Paths + +=head3 $NoFtlPth + +Default is false. If set to true rmdir(), mkdir(), and pathempty() calls in pathrm() and pathmk() do not return() on failure. + +If its set to true they just silently go about their business regardless. This isn't a good idea but its there if you want it. + +=head3 $DirPerms + +Mode to pass to any mkdir() calls. Defaults to 0777 as per umask()'s POD. Explicitly having this allows older perls to be able to use FCR and might add a bit of flexibility for you. + +Any value you set it to should be suitable for oct() + +=head3 Path functions + +These functions exist soley because they were necessary for the move and copy functions to have the features they do and not because they are of themselves the purpose of this module. That being said, here is how they work so you can understand how the copy and move funtions work and use them by themselves if you wish. + +=head4 pathrm() + +Removes a given path recursively. It removes the *entire* path so be carefull!!! + +Returns 2 if the given path is not a directory. + + File::Copy::Recursive::pathrm('foo/bar/baz') or die $!; + # foo no longer exists + +Same as: + + rmdir 'foo/bar/baz' or die $!; + rmdir 'foo/bar' or die $!; + rmdir 'foo' or die $!; + +An optional second argument makes it call pathempty() before any rmdir()'s when set to true. + + File::Copy::Recursive::pathrm('foo/bar/baz', 1) or die $!; + # foo no longer exists + +Same as:PFSCheck + + File::Copy::Recursive::pathempty('foo/bar/baz') or die $!; + rmdir 'foo/bar/baz' or die $!; + File::Copy::Recursive::pathempty('foo/bar/') or die $!; + rmdir 'foo/bar' or die $!; + File::Copy::Recursive::pathempty('foo/') or die $!; + rmdir 'foo' or die $!; + +An optional third argument acts like $File::Copy::Recursive::NoFtlPth, again probably not a good idea. + +=head4 pathempty() + +Recursively removes the given directory's contents so it is empty. returns 2 if argument is not a directory, 1 on successfully emptying the directory. + + File::Copy::Recursive::pathempty($pth) or die $!; + # $pth is now an empty directory + +=head4 pathmk() + +Creates a given path recursively. Creates foo/bar/baz even if foo does not exist. + + File::Copy::Recursive::pathmk('foo/bar/baz') or die $!; + +An optional second argument if true acts just like $File::Copy::Recursive::NoFtlPth, which means you'd never get your die() if something went wrong. Again, probably a *bad* idea. + +=head4 pathrmdir() + +Same as rmdir() but it calls pathempty() first to recursively empty it first since rmdir can not remove a directory with contents. +Just removes the top directory the path given instead of the entire path like pathrm(). Return 2 if given argument does not exist (IE its already gone). Return false if it exists but is not a directory. + +=head2 Preserving Mode + +By default a quiet attempt is made to change the new file or directory to the mode of the old one. +To turn this behavior off set + $File::Copy::Recursive::KeepMode +to false; + +=head2 Managing Depth + +You can set the maximum depth a directory structure is recursed by setting: + $File::Copy::Recursive::MaxDepth +to a whole number greater than 0. + +=head2 SymLinks + +If your system supports symlinks then symlinks will be copied as symlinks instead of as the target file. +Perl's symlink() is used instead of File::Copy's copy() +You can customize this behavior by setting $File::Copy::Recursive::CopyLink to a true or false value. +It is already set to true or false dending on your system's support of symlinks so you can check it with an if statement to see how it will behave: + + if($File::Copy::Recursive::CopyLink) { + print "Symlinks will be preserved\n"; + } else { + print "Symlinks will not be preserved because your system does not support it\n"; + } + +If symlinks are being copied you can set $File::Copy::Recursive::BdTrgWrn to true to make it carp when it copies a link whose target does not exist. Its false by default. + + local $File::Copy::Recursive::BdTrgWrn = 1; + +=head2 Removing existing target file or directory before copying. + +This can be done by setting $File::Copy::Recursive::RMTrgFil or $File::Copy::Recursive::RMTrgDir for file or directory behavior respectively. + +0 = off (This is the default) + +1 = carp() $! if removal fails + +2 = return if removal fails + + local $File::Copy::Recursive::RMTrgFil = 1; + fcopy($orig, $target) or die $!; + # if it fails it does warn() and keeps going + + local $File::Copy::Recursive::RMTrgDir = 2; + dircopy($orig, $target) or die $!; + # if it fails it does your "or die" + +This should be unnecessary most of the time but its there if you need it :) + +=head2 Turning off stat() check + +By default the files or directories are checked to see if they are the same (IE linked, or two paths (absolute/relative or different relative paths) to the same file) by comparing the file's stat() info. +It's a very efficient check that croaks if they are and shouldn't be turned off but if you must for some weird reason just set $File::Copy::Recursive::PFSCheck to a false value. ("PFS" stands for "Physical File System") + +=head2 Emulating cp -rf dir1/ dir2/ + +By default dircopy($dir1,$dir2) will put $dir1's contents right into $dir2 whether $dir2 exists or not. + +You can make dircopy() emulate cp -rf by setting $File::Copy::Recursive::CPRFComp to true. + +NOTE: This only emulates -f in the sense that it does not prompt. It does not remove the target file or directory if it exists. +If you need to do that then use the variables $RMTrgFil and $RMTrgDir described in "Removing existing target file or directory before copying" above. + +That means that if $dir2 exists it puts the contents into $dir2/$dir1 instead of $dir2 just like cp -rf. +If $dir2 does not exist then the contents go into $dir2 like normal (also like cp -rf) + +So assuming 'foo/file': + + dircopy('foo', 'bar') or die $!; + # if bar does not exist the result is bar/file + # if bar does exist the result is bar/file + + $File::Copy::Recursive::CPRFComp = 1; + dircopy('foo', 'bar') or die $!; + # if bar does not exist the result is bar/file + # if bar does exist the result is bar/foo/file + +You can also specify a star for cp -rf glob type behavior: + + dircopy('foo/*', 'bar') or die $!; + # if bar does not exist the result is bar/file + # if bar does exist the result is bar/file + + $File::Copy::Recursive::CPRFComp = 1; + dircopy('foo/*', 'bar') or die $!; + # if bar does not exist the result is bar/file + # if bar does exist the result is bar/file + +NOTE: The '*' is only like cp -rf foo/* and *DOES NOT EXPAND PARTIAL DIRECTORY NAMES LIKE YOUR SHELL DOES* (IE not like cp -rf fo* to copy foo/*) + +=head2 Allowing Copy Loops + +If you want to allow: + + cp -rf . foo/ + +type behavior set $File::Copy::Recursive::CopyLoop to true. + +This is false by default so that a check is done to see if the source directory will contain the target directory and croaks to avoid this problem. + +If you ever find a situation where $CopyLoop = 1 is desirable let me know (IE its a bad bad idea but is there if you want it) + +(Note: On Windows this was necessary since it uses stat() to detemine samedness and stat() is essencially useless for this on Windows. +The test is now simply skipped on Windows but I'd rather have an actual reliable check if anyone in Microsoft land would care to share) + +=head1 SEE ALSO + +L L + +=head1 TO DO + +I am currently working on and reviewing some other modules to use in the new interface so we can lose the horrid globals as well as some other undesirable traits and also more easily make available some long standing requests. + +Tests will be easier to do with the new interface and hence the testing focus will shift to the new interface and aim to be comprehensive. + +The old interface will work, it just won't be brought in until it is used, so it will add no overhead for users of the new interface. + +I'll add this after the latest verision has been out for a while with no new features or issues found :) + +=head1 AUTHOR + +Daniel Muey, L + +=head1 COPYRIGHT AND LICENSE + +Copyright 2004 by Daniel Muey + +This library is free software; you can redistribute it and/or modify +it under the same terms as Perl itself. + +=cut diff --git a/external/buildscripts/perl_lib/Tools.pm b/external/buildscripts/perl_lib/Tools.pm new file mode 100644 index 000000000000..8b2d7a6a7e2f --- /dev/null +++ b/external/buildscripts/perl_lib/Tools.pm @@ -0,0 +1,40 @@ +package Tools; + +use warnings; +use strict; +use File::Basename qw(dirname basename ); +use File::Spec; +use Cwd qw(realpath); +use Carp qw(croak carp); +use File::stat; + +require Exporter; +our @ISA = qw(Exporter); +our @EXPORT_OK = qw(InstallNameTool GitClone); + + +sub InstallNameTool +{ + my ($target,$pathtoburnin) = @_; + print "running otool before:\n"; + system("otool","-L",$target); + print "running install_name_tool\n"; + system("install_name_tool -id $pathtoburnin $target") eq 0 or die("Failed running install_name_tool"); + print "running otool after:\n"; + system("otool","-L",$target); +} + +sub GitClone +{ + my $repo = shift; + my $localFolder = shift; + my $branch = shift; + $branch = defined($branch)?$branch:"master"; + + if (-d $localFolder) { + return; + } + print "running git clone --branch $branch $repo $localFolder\n"; + system("git clone --branch $branch $repo $localFolder") eq 0 or die("git clone $repo $localFolder failed!"); +} + diff --git a/external/buildscripts/test-driver b/external/buildscripts/test-driver new file mode 100644 index 000000000000..8a05be09ec4b --- /dev/null +++ b/external/buildscripts/test-driver @@ -0,0 +1,100 @@ +#!/usr/bin/env perl + +my $interpreter = shift; +my $test = shift; +my $disabled_tests = shift; +my $output = $test; +my $stdout = $test.'.stdout'; +my $stderr = $test.'.stderr'; + +my $teamcity = $ENV{UNITY_THISISABUILDMACHINE}; +$output =~ s/\.exe$/.output/; + +$| = 0; +if ($teamcity) { + print "##teamcity[testStarted name='$test']\n"; +} +else { + print "Testing $test... "; +} + +foreach $disabled (split (/ /, $disabled_tests)) { + if ($disabled eq $test) { + print "disabled.\n"; + exit (0); + } +} + +my $res; +my $cpid = fork (); +if (!defined ($cpid)) { + $res = system("$interpreter @ARGV $test 2>$stderr 1>$stdout"); +} elsif ($cpid == 0) { + exec ("$interpreter @ARGV $test 2>$stderr 1>$stdout") || die "Cannot exec: $!"; +} else { + # in the parent, setup the alarm + # test must complete in 30 seconds or it is considered buggy + my $timeout = 30; + alarm ($timeout); + $SIG{ALRM} = sub { + print "failed after $timeout seconds timeout.\n"; + if ($teamcity) { + print "##teamcity[testFailed name='$test' message='failed after $timeout seconds timeout.' details='message and stack trace']\n"; + print "##teamcity[testFinished name='$test']\n"; + } + # process group kill + kill (-9, $cpid); + exit (3); + }; + $res = wait (); + $SIG{ALRM} = sub {}; + $res = $? >> 8; +} + +if ($teamcity && -f $stdout) { + $text = read_file ($stdout); + print "##teamcity[testStdOut name='$test' out='$text']\n"; +} + +if ($teamcity && -f $stderr) { + $text = read_file ($stderr); + print "##teamcity[testStdErr name='$test' out='$text']\n"; +} + +if ($res) { + $failedText = sprintf ("failed $? (%d) signal (%d).", $? >> 8, $? & 127); + if ($teamcity) { + print "##teamcity[testFailed name='$test' message='$failedText' details='message and stack trace']\n"; + print "##teamcity[testFinished name='$test']\n"; + } else { + print "$failedText\n"; + } + + if (($? & 127) == 2) { + exit (2); + } else { + exit (1); + } +} +if (-f $output && (read_file ($output) ne read_file ($stdout))) { + print "failed output.\n"; + exit (1); +} + +if ($teamcity) { + print "##teamcity[testFinished name='$test']\n"; +} +else { + print "pass.\n"; +} +unlink ($stderr); +exit (0); + +sub read_file { + local ($/); + my $out = shift; + open (F, "<$out") || die $!; + $out = ; + close(F); + return $out; +} diff --git a/mcs/Makefile b/mcs/Makefile index 59db5e77267f..87e5ace2c96a 100644 --- a/mcs/Makefile +++ b/mcs/Makefile @@ -23,6 +23,8 @@ xammac_net_4_5_SUBDIRS := build class xbuild_12_SUBDIRS := build class tools/xbuild xbuild_14_SUBDIRS := build class tools/xbuild winaot_SUBDIRS := build class +unityjit_SUBDIRS := build class +unityaot_SUBDIRS := build class orbis_SUBDIRS := build class unreal_SUBDIRS := build class wasm_SUBDIRS := build class @@ -80,6 +82,8 @@ $(_boot_:%=profile-do--xammac_net_4_5--%): profile-do--xammac_net_4_5--%: $(_boot_:%=profile-do--testing_aot_hybrid--%): profile-do--testing_aot_hybrid--%: profile-do--build--% $(_boot_:%=profile-do--testing_aot_full--%): profile-do--testing_aot_full--%: profile-do--build--% $(_boot_:%=profile-do--winaot--%): profile-do--winaot--%: profile-do--build--% +$(_boot_:%=profile-do--unityjit--%): profile-do--unityjit--%: profile-do--build--% +$(_boot_:%=profile-do--unityaot--%): profile-do--unityaot--%: profile-do--build--% $(_boot_:%=profile-do--orbis--%): profile-do--orbis--%: profile-do--build--% $(_boot_:%=profile-do--unreal--%): profile-do--unreal--%: profile-do--build--% $(_boot_:%=profile-do--wasm--%): profile-do--wasm--%: profile-do--build--% diff --git a/mcs/build/common/Consts.cs.in b/mcs/build/common/Consts.cs.in index 8bb64bc43a70..a6cdfdd19611 100644 --- a/mcs/build/common/Consts.cs.in +++ b/mcs/build/common/Consts.cs.in @@ -40,7 +40,7 @@ static class Consts public const string MonoCopyright = "(c) Various Mono authors"; public const int MonoCorlibVersion = @MONO_CORLIB_VERSION@; -#if MOBILE +#if MOBILE && !UNITY_AOT // Versions of .NET Framework for Silverlight 4.0 public const string FxVersion = "2.0.5.0"; public const string VsVersion = "9.0.0.0"; // unused, but needed for compilation @@ -78,7 +78,7 @@ static class Consts #error No profile symbols defined. #endif -#if MOBILE +#if MOBILE && !UNITY_AOT const string PublicKeyToken = "7cec85d7bea7798e"; #else const string PublicKeyToken = "b77a5c561934e089"; diff --git a/mcs/build/profiles/net_4_x.make b/mcs/build/profiles/net_4_x.make index 5463812acc6e..a7cc2e81dc1f 100644 --- a/mcs/build/profiles/net_4_x.make +++ b/mcs/build/profiles/net_4_x.make @@ -13,7 +13,7 @@ profile-check: @: DEFAULT_REFERENCES = -r:$(topdir)/class/lib/$(PROFILE_DIRECTORY)/mscorlib.dll -PROFILE_MCS_FLAGS = -d:NET_4_0 -d:NET_4_5 -d:NET_4_6 -d:MONO -d:WIN_PLATFORM -d:MULTIPLEX_OS -nowarn:1699 -nostdlib $(DEFAULT_REFERENCES) $(PLATFORM_DEBUG_FLAGS) +PROFILE_MCS_FLAGS = -d:NET_4_0 -d:NET_4_5 -d:NET_4_6 -d:MONO -d:UNITY_AOT -d:UNITY -d:WIN_PLATFORM -d:MULTIPLEX_OS -nowarn:1699 -nostdlib $(DEFAULT_REFERENCES) $(PLATFORM_DEBUG_FLAGS) API_BIN_PROFILE = v4.7.1 FRAMEWORK_VERSION = 4.5 diff --git a/mcs/build/profiles/unityaot.make b/mcs/build/profiles/unityaot.make new file mode 100644 index 000000000000..9b69620953c1 --- /dev/null +++ b/mcs/build/profiles/unityaot.make @@ -0,0 +1,41 @@ +#! -*- makefile -*- + +BOOTSTRAP_PROFILE = build + +BOOTSTRAP_MCS = MONO_PATH="$(topdir)/class/lib/$(BOOTSTRAP_PROFILE)$(PLATFORM_PATH_SEPARATOR)$$MONO_PATH" $(INTERNAL_CSC) +MCS = $(BOOTSTRAP_MCS) + +profile-check: + @: + +DEFAULT_REFERENCES = -r:$(topdir)/class/lib/$(PROFILE)/mscorlib.dll + +PROFILE_MCS_FLAGS = \ + -d:NET_1_1 \ + -d:NET_2_0 \ + -d:NET_2_1 \ + -d:NET_3_5 \ + -d:NET_4_0 \ + -d:NET_4_5 \ + -d:MONO \ + -d:UNITY \ + -d:UNITY_AOT \ + -d:MOBILE,MOBILE_LEGACY \ + -d:FULL_AOT_DESKTOP \ + -d:FULL_AOT_RUNTIME \ + -d:DISABLE_REMOTING \ + -d:WIN_PLATFORM \ + -nowarn:1699 \ + -nostdlib \ + $(DEFAULT_REFERENCES) \ + $(PLATFORM_DEBUG_FLAGS) +API_BIN_PROFILE = v4.7.1 + +FRAMEWORK_VERSION = 2.1 + +NO_INSTALL = yes +AOT_FRIENDLY_PROFILE = yes +#ALWAYS_AOT = yes +MOBILE_PROFILE = yes +NO_TEST = yes +#NO_SIGN_ASSEMBLY = yes diff --git a/mcs/build/profiles/unityjit.make b/mcs/build/profiles/unityjit.make new file mode 100644 index 000000000000..b943ecf40f99 --- /dev/null +++ b/mcs/build/profiles/unityjit.make @@ -0,0 +1,18 @@ +# -*- makefile -*- + +BOOTSTRAP_PROFILE = build + +BOOTSTRAP_MCS = MONO_PATH="$(topdir)/class/lib/$(BOOTSTRAP_PROFILE)$(PLATFORM_PATH_SEPARATOR)$$MONO_PATH" $(INTERNAL_CSC) +MCS = $(BOOTSTRAP_MCS) + + +profile-check: + @: + +DEFAULT_REFERENCES = -r:$(topdir)/class/lib/$(PROFILE)/mscorlib.dll +PROFILE_MCS_FLAGS = -d:NET_4_0 -d:NET_4_5 -d:NET_4_6 -d:MONO -d:UNITY_JIT -d:UNITY -d:WIN_PLATFORM -nowarn:1699 -nostdlib $(DEFAULT_REFERENCES) $(PLATFORM_DEBUG_FLAGS) +API_BIN_PROFILE = v4.7.1 + +FRAMEWORK_VERSION = 4.5 +XBUILD_VERSION = 4.0 +MONO_FEATURE_APPLETLS=1 diff --git a/mcs/class/Facades/System.Drawing.Primitives/Makefile b/mcs/class/Facades/System.Drawing.Primitives/Makefile index 036ec852fa5e..174df4af8ee8 100644 --- a/mcs/class/Facades/System.Drawing.Primitives/Makefile +++ b/mcs/class/Facades/System.Drawing.Primitives/Makefile @@ -23,7 +23,7 @@ EMBEDDED_DRAWING_DEP := $(filter xammac_net_4_5 testing_aot_full testing_aot_hyb ifndef EMBEDDED_DRAWING_DEP # profiles which build a System.Drawing.dll in the repo -REPO_DRAWING_DEP := $(filter net_4_x orbis winaot unreal wasm, $(PROFILE)) +REPO_DRAWING_DEP := $(filter net_4_x orbis winaot unityaot unityjit unreal wasm, $(PROFILE)) ifdef REPO_DRAWING_DEP LIB_REFS += System.Drawing diff --git a/mcs/class/Facades/System.Net.Http.Rtc/AssemblyInfo.cs b/mcs/class/Facades/System.Net.Http.Rtc/AssemblyInfo.cs new file mode 100644 index 000000000000..19cd3907a866 --- /dev/null +++ b/mcs/class/Facades/System.Net.Http.Rtc/AssemblyInfo.cs @@ -0,0 +1,35 @@ +// +// Copyright (c) 2013 Xamarin Inc. (http://www.xamarin.com) +// +// 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. +// + +using System; +using System.Reflection; +using System.Runtime.CompilerServices; + +[assembly: AssemblyTitle ("System.Net.Http.Rtc")] +[assembly: AssemblyDescription ("System.Net.Http.Rtc")] +[assembly: AssemblyDefaultAlias ("System.Net.Http.Rtc")] +[assembly: AssemblyCompany ("Mono development team")] +[assembly: AssemblyProduct ("Mono Common Language Infrastructure")] +[assembly: AssemblyCopyright ("(c) Various Mono authors")] +[assembly: AssemblyVersion ("4.0.0.0")] +[assembly: AssemblyInformationalVersion ("4.0.0.0")] +[assembly: AssemblyFileVersion ("4.0.0.0")] diff --git a/mcs/class/Facades/System.Net.Http.Rtc/Makefile b/mcs/class/Facades/System.Net.Http.Rtc/Makefile new file mode 100644 index 000000000000..f730763a925e --- /dev/null +++ b/mcs/class/Facades/System.Net.Http.Rtc/Makefile @@ -0,0 +1,21 @@ +MCS_BUILD_DIR = ../../../build + +thisdir = class/Facades/System.Net.Http.Rtc +SUBDIRS = +include $(MCS_BUILD_DIR)/rules.make + +LIBRARY_SUBDIR = Facades +LIBRARY_INSTALL_DIR = $(mono_libdir)/mono/$(FRAMEWORK_VERSION)/Facades + +LIBRARY = System.Net.Http.Rtc.dll + +KEYFILE = ../../msfinal.pub +SIGN_FLAGS = /delaysign /nowarn:1616,1699 +LIB_REFS = System +LIB_MCS_FLAGS = $(SIGN_FLAGS) + +PLATFORM_DEBUG_FLAGS = + +NO_TEST = yes + +include $(MCS_BUILD_DIR)/library.make diff --git a/mcs/class/Facades/System.Net.Http.Rtc/System.Net.Http.Rtc.dll.sources b/mcs/class/Facades/System.Net.Http.Rtc/System.Net.Http.Rtc.dll.sources new file mode 100644 index 000000000000..719628dc7c61 --- /dev/null +++ b/mcs/class/Facades/System.Net.Http.Rtc/System.Net.Http.Rtc.dll.sources @@ -0,0 +1,2 @@ +TypeForwarders.cs +AssemblyInfo.cs diff --git a/mcs/class/Facades/System.Net.Http.Rtc/TypeForwarders.cs b/mcs/class/Facades/System.Net.Http.Rtc/TypeForwarders.cs new file mode 100644 index 000000000000..b8c87d21f333 --- /dev/null +++ b/mcs/class/Facades/System.Net.Http.Rtc/TypeForwarders.cs @@ -0,0 +1,25 @@ +// +// Copyright (c) 2016 Xamarin Inc. (http://www.xamarin.com) +// +// 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. +// + +#if false // it is forwarded to System.Net.Http.WebRequest.dll but doesn't actually exist there in the .NET 4.7.1 reference assemblies ... +[assembly:System.Runtime.CompilerServices.TypeForwardedToAttribute(typeof(System.Net.Http.RtcRequestFactory))] +#endif diff --git a/mcs/class/Facades/System.Resources.Reader/AssemblyInfo.cs b/mcs/class/Facades/System.Resources.Reader/AssemblyInfo.cs new file mode 100644 index 000000000000..fe58b174b957 --- /dev/null +++ b/mcs/class/Facades/System.Resources.Reader/AssemblyInfo.cs @@ -0,0 +1,35 @@ +// +// Copyright (c) 2015 Xamarin Inc. (http://www.xamarin.com) +// +// 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. +// + +using System; +using System.Reflection; +using System.Runtime.CompilerServices; + +[assembly: AssemblyTitle ("System.Resources.Reader")] +[assembly: AssemblyDescription ("System.Resources.Reader")] +[assembly: AssemblyDefaultAlias ("System.Resources.Reader")] +[assembly: AssemblyCompany ("Mono development team")] +[assembly: AssemblyProduct ("Mono Common Language Infrastructure")] +[assembly: AssemblyCopyright ("(c) Various Mono authors")] +[assembly: AssemblyVersion ("4.0.2.0")] +[assembly: AssemblyInformationalVersion ("4.0.0.0")] +[assembly: AssemblyFileVersion ("4.0.0.0")] diff --git a/mcs/class/Facades/System.Resources.Reader/Makefile b/mcs/class/Facades/System.Resources.Reader/Makefile new file mode 100644 index 000000000000..b16ae43ee303 --- /dev/null +++ b/mcs/class/Facades/System.Resources.Reader/Makefile @@ -0,0 +1,23 @@ +MCS_BUILD_DIR = ../../../build + +thisdir = class/Facades/System.Resources.Reader +SUBDIRS = +include $(MCS_BUILD_DIR)/rules.make + +LIBRARY_SUBDIR = Facades +LIBRARY_INSTALL_DIR = $(mono_libdir)/mono/$(FRAMEWORK_VERSION)/Facades + +LIBRARY = System.Resources.Reader.dll + +KEYFILE = ../../msfinal.pub +SIGN_FLAGS = /delaysign /nowarn:1616,1699 +LIB_REFS = System +LIB_MCS_FLAGS = $(SIGN_FLAGS) + +PLATFORM_DEBUG_FLAGS = + +NO_TEST = yes + +include $(MCS_BUILD_DIR)/library.make + + diff --git a/mcs/class/Facades/System.Resources.Reader/System.Resources.Reader.dll.sources b/mcs/class/Facades/System.Resources.Reader/System.Resources.Reader.dll.sources new file mode 100644 index 000000000000..8e33d4ddeae9 --- /dev/null +++ b/mcs/class/Facades/System.Resources.Reader/System.Resources.Reader.dll.sources @@ -0,0 +1,3 @@ +TypeForwarders.cs +AssemblyInfo.cs + diff --git a/mcs/class/Facades/System.Resources.Reader/TypeForwarders.cs b/mcs/class/Facades/System.Resources.Reader/TypeForwarders.cs new file mode 100644 index 000000000000..310362270c75 --- /dev/null +++ b/mcs/class/Facades/System.Resources.Reader/TypeForwarders.cs @@ -0,0 +1,25 @@ +// +// Copyright (c) 2015 Xamarin Inc. (http://www.xamarin.com) +// +// 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. +// + +[assembly: System.Runtime.CompilerServices.TypeForwardedToAttribute(typeof(System.Resources.ResourceReader))] + + diff --git a/mcs/class/Facades/System.Resources.Writer/AssemblyInfo.cs b/mcs/class/Facades/System.Resources.Writer/AssemblyInfo.cs new file mode 100644 index 000000000000..71222db9e31e --- /dev/null +++ b/mcs/class/Facades/System.Resources.Writer/AssemblyInfo.cs @@ -0,0 +1,35 @@ +// +// Copyright (c) 2015 Xamarin Inc. (http://www.xamarin.com) +// +// 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. +// + +using System; +using System.Reflection; +using System.Runtime.CompilerServices; + +[assembly: AssemblyTitle ("System.Resources.Writer")] +[assembly: AssemblyDescription ("System.Resources.Writer")] +[assembly: AssemblyDefaultAlias ("System.Resources.Writer")] +[assembly: AssemblyCompany ("Mono development team")] +[assembly: AssemblyProduct ("Mono Common Language Infrastructure")] +[assembly: AssemblyCopyright ("(c) Various Mono authors")] +[assembly: AssemblyVersion ("4.0.2.0")] +[assembly: AssemblyInformationalVersion ("4.0.0.0")] +[assembly: AssemblyFileVersion ("4.0.0.0")] diff --git a/mcs/class/Facades/System.Resources.Writer/Makefile b/mcs/class/Facades/System.Resources.Writer/Makefile new file mode 100644 index 000000000000..f2f622eb1bf0 --- /dev/null +++ b/mcs/class/Facades/System.Resources.Writer/Makefile @@ -0,0 +1,23 @@ +MCS_BUILD_DIR = ../../../build + +thisdir = class/Facades/System.Resources.Writer +SUBDIRS = +include $(MCS_BUILD_DIR)/rules.make + +LIBRARY_SUBDIR = Facades +LIBRARY_INSTALL_DIR = $(mono_libdir)/mono/$(FRAMEWORK_VERSION)/Facades + +LIBRARY = System.Resources.Writer.dll + +KEYFILE = ../../msfinal.pub +SIGN_FLAGS = /delaysign /nowarn:1616,1699 +LIB_REFS = System +LIB_MCS_FLAGS = $(SIGN_FLAGS) + +PLATFORM_DEBUG_FLAGS = + +NO_TEST = yes + +include $(MCS_BUILD_DIR)/library.make + + diff --git a/mcs/class/Facades/System.Resources.Writer/System.Resources.Writer.dll.sources b/mcs/class/Facades/System.Resources.Writer/System.Resources.Writer.dll.sources new file mode 100644 index 000000000000..8e33d4ddeae9 --- /dev/null +++ b/mcs/class/Facades/System.Resources.Writer/System.Resources.Writer.dll.sources @@ -0,0 +1,3 @@ +TypeForwarders.cs +AssemblyInfo.cs + diff --git a/mcs/class/Facades/System.Resources.Writer/TypeForwarders.cs b/mcs/class/Facades/System.Resources.Writer/TypeForwarders.cs new file mode 100644 index 000000000000..e82cdb0ad509 --- /dev/null +++ b/mcs/class/Facades/System.Resources.Writer/TypeForwarders.cs @@ -0,0 +1,25 @@ +// +// Copyright (c) 2015 Xamarin Inc. (http://www.xamarin.com) +// +// 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. +// + +[assembly: System.Runtime.CompilerServices.TypeForwardedToAttribute(typeof(System.Resources.ResourceWriter))] + + diff --git a/mcs/class/Facades/netstandard/Makefile b/mcs/class/Facades/netstandard/Makefile index b9974695d6d1..e6487dc44d16 100644 --- a/mcs/class/Facades/netstandard/Makefile +++ b/mcs/class/Facades/netstandard/Makefile @@ -23,13 +23,15 @@ LIB_MCS_FLAGS = $(SIGN_FLAGS) $(EXTRA_LIB_MCS_FLAGS) ifeq ($(PROFILE),xammac_net_4_5) LIB_REFS += System.Web.Services else ifeq (2.1, $(FRAMEWORK_VERSION)) +ifneq ($(PROFILE),unityaot) LIB_REFS += System.Web.Services +endif else LIB_REFS += System.Web endif # profiles which build a System.Drawing.dll in the repo -REPO_DRAWING_DEP := $(filter net_4_x orbis winaot unreal wasm, $(PROFILE)) +REPO_DRAWING_DEP := $(filter net_4_x orbis winaot unityaot unityjit unreal wasm, $(PROFILE)) ifdef REPO_DRAWING_DEP LIB_REFS += System.Drawing diff --git a/mcs/class/Facades/subdirs.make b/mcs/class/Facades/subdirs.make index 992516931274..3901ea16eeb2 100644 --- a/mcs/class/Facades/subdirs.make +++ b/mcs/class/Facades/subdirs.make @@ -27,7 +27,8 @@ System.Xml.XPath System.Xml.XmlDocument System.Xml.Xsl.Primitives Microsoft.Win3 System.IO.FileSystem.AccessControl System.Reflection.TypeExtensions System.Reflection.Emit.Lightweight System.Reflection.Emit.ILGeneration System.Reflection.Emit \ System.Threading.AccessControl System.ValueTuple \ System.Security.Cryptography.Primitives System.Text.Encoding.CodePages System.IO.FileSystem.Watcher \ -System.Security.Cryptography.ProtectedData System.ServiceProcess.ServiceController System.IO.Pipes +System.Security.Cryptography.ProtectedData System.ServiceProcess.ServiceController System.IO.Pipes \ +System.Net.Http.Rtc System.Net.Ping System.Resources.Reader System.Resources.Writer System.Runtime.Serialization.Formatters System.Security.Cryptography.Csp # common_SUBDIRS dependencies common_DEPS_SUBDIRS = System.Security.Cryptography.X509Certificates System.ServiceModel.Primitives System.Runtime.Serialization.Primitives \ @@ -80,6 +81,12 @@ monotouch_tv_PARALLEL_SUBDIRS = $(monotouch_PARALLEL_SUBDIRS) winaot_SUBDIRS = $(common_DEPS_SUBDIRS) $(netstandard_drawing_SUBDIRS) $(mobile_only_DEPS_SUBDIRS) winaot_PARALLEL_SUBDIRS = $(common_SUBDIRS) $(mobile_only_SUBDIRS) +unityjit_SUBDIRS = $(common_DEPS_SUBDIRS) $(netstandard_drawing_SUBDIRS) +unityjit_PARALLEL_SUBDIRS = $(common_SUBDIRS) + +unityaot_SUBDIRS = $(filter-out System.ServiceModel.Primitives,$(common_DEPS_SUBDIRS)) $(netstandard_drawing_SUBDIRS) $(mobile_only_DEPS_SUBDIRS) +unityaot_PARALLEL_SUBDIRS = $(filter-out System.ServiceModel.Http System.ServiceModel.Security System.ServiceModel.Duplex System.ServiceModel.NetTcp ,$(common_SUBDIRS)) $(mobile_only_SUBDIRS) + orbis_SUBDIRS = $(common_DEPS_SUBDIRS) $(netstandard_drawing_SUBDIRS) $(mobile_only_DEPS_SUBDIRS) orbis_PARALLEL_SUBDIRS = $(common_SUBDIRS) $(mobile_only_SUBDIRS) @@ -89,7 +96,7 @@ unreal_PARALLEL_SUBDIRS = $(common_SUBDIRS) $(mobile_only_SUBDIRS) wasm_SUBDIRS = $(common_DEPS_SUBDIRS) $(netstandard_drawing_SUBDIRS) $(mobile_only_DEPS_SUBDIRS) wasm_PARALLEL_SUBDIRS = $(common_SUBDIRS) $(mobile_only_SUBDIRS) -mobile_only_SUBDIRS = System.Net.Ping System.Runtime.Serialization.Formatters System.Security.Cryptography.Csp System.Security.Cryptography.Pkcs \ +mobile_only_SUBDIRS = System.Security.Cryptography.Pkcs \ System.Security.Cryptography.Cng System.Runtime.Loader System.Xml.XPath.XmlDocument System.Reflection.DispatchProxy mobile_only_DEPS_SUBDIRS = System.Security.Cryptography.OpenSsl diff --git a/mcs/class/Makefile b/mcs/class/Makefile index 13d7aae28738..64beb024a76b 100644 --- a/mcs/class/Makefile +++ b/mcs/class/Makefile @@ -342,6 +342,27 @@ net_4_x_parallel_dirs := \ legacy/Mono.Cecil \ $(pcl_facade_dirs) +unityjit_dirs := \ + $(net_4_x_dirs) \ + System.ComponentModel.Composition.4.5 \ + I18N \ + $(pcl_facade_dirs) + +unityaot_dirs := \ + $(filter-out \ + Mono.CSharp \ + System.Data.Services.Client \ + System.Net.Http.WinHttpHandler \ + System.ServiceModel.Web \ + System.ServiceModel \ + System.Web.Services \ + System.Reflection.Context \ + System.Windows \ + System.Xml.Serialization \ + System.Runtime.CompilerServices.Unsafe, $(mobile_common_dirs)) \ + System.Drawing \ + $(pcl_facade_dirs) + xbuild_2_0_dirs := \ Microsoft.Build.Framework \ Microsoft.Build.Utilities \ @@ -376,13 +397,15 @@ net_4_x_PARALLEL_SUBDIRS := $(net_4_x_parallel_dirs) xbuild_12_SUBDIRS := $(xbuild_4_0_dirs) xbuild_14_SUBDIRS := $(xbuild_4_0_dirs) Microsoft.NuGet.Build.Tasks winaot_SUBDIRS := $(winaot_dirs) +unityjit_SUBDIRS := $(unityjit_dirs) +unityaot_SUBDIRS := $(unityaot_dirs) orbis_SUBDIRS := $(orbis_dirs) unreal_SUBDIRS := $(unreal_dirs) wasm_SUBDIRS := $(wasm_dirs) include ../build/rules.make -SUBDIRS = $(testing_aot_full_dirs) $(testing_aot_hybrid_dirs) $(monotouch_dirs) $(monodroid_dirs) $(monodroid_tools_dirs) $(xammac_dirs) $(net_4_x_dirs) $(net_4_x_parallel_dirs) $(xammac_net_4_5_SUBDIRS) $(unreal_dirs) +SUBDIRS = $(testing_aot_full_dirs) $(testing_aot_hybrid_dirs) $(monotouch_dirs) $(monodroid_dirs) $(monodroid_tools_dirs) $(xammac_dirs) $(net_4_x_dirs) $(net_4_x_parallel_dirs) $(xammac_net_4_5_SUBDIRS) $(unityjit_dirs) $(unityaot_dirs) $(unreal_dirs) DIST_ONLY_SUBDIRS = dlr aot-compiler reference-assemblies $(xbuild_4_0_dirs) Microsoft.NuGet.Build.Tasks diff --git a/mcs/class/Mono.Debugger.Soft/Mono.Debugger.Soft/Connection.cs b/mcs/class/Mono.Debugger.Soft/Mono.Debugger.Soft/Connection.cs index 602c827091de..e480555252ed 100644 --- a/mcs/class/Mono.Debugger.Soft/Mono.Debugger.Soft/Connection.cs +++ b/mcs/class/Mono.Debugger.Soft/Mono.Debugger.Soft/Connection.cs @@ -420,7 +420,7 @@ public abstract class Connection * with newer runtimes, and vice versa. */ internal const int MAJOR_VERSION = 2; - internal const int MINOR_VERSION = 45; + internal const int MINOR_VERSION = 46; enum WPSuspendPolicy { NONE = 0, @@ -442,7 +442,8 @@ enum CommandSet { TYPE = 23, MODULE = 24, FIELD = 25, - EVENT = 64 + EVENT = 64, + POINTER = 65 } enum EventKind { @@ -574,7 +575,8 @@ enum CmdType { GET_INTERFACES = 16, GET_INTERFACE_MAP = 17, IS_INITIALIZED = 18, - CREATE_INSTANCE = 19 + CREATE_INSTANCE = 19, + GET_VALUE_SIZE = 20 } enum CmdField { @@ -606,6 +608,10 @@ enum CmdStringRef { GET_CHARS = 3 } + enum CmdPointer { + GET_VALUE = 1 + } + enum CmdObjectRef { GET_TYPE = 1, GET_VALUES = 2, @@ -730,10 +736,12 @@ internal static byte[] EncodePacket (int id, int commandSet, int command, byte[] } class PacketReader { + Connection connection; byte[] packet; int offset; - public PacketReader (byte[] packet) { + public PacketReader (Connection connection, byte[] packet) { + this.connection = connection; this.packet = packet; // For event packets @@ -845,9 +853,16 @@ public ValueImpl ReadValue () { return new ValueImpl { Type = etype, Value = ReadDouble () }; case ElementType.I: case ElementType.U: - case ElementType.Ptr: // FIXME: The client and the debuggee might have different word sizes return new ValueImpl { Type = etype, Value = ReadLong () }; + case ElementType.Ptr: + long value = ReadLong (); + if (connection.Version.AtLeast (2, 46)) { + long pointerClass = ReadId (); + return new ValueImpl { Type = etype, Klass = pointerClass, Value = value }; + } else { + return new ValueImpl { Type = etype, Value = value }; + } case ElementType.String: case ElementType.SzArray: case ElementType.Class: @@ -1283,7 +1298,7 @@ bool ReceivePacket () { if (cb != null) cb.Invoke (id, packet); } else { - PacketReader r = new PacketReader (packet); + PacketReader r = new PacketReader (this, packet); if (r.CommandSet == CommandSet.EVENT && r.Command == (int)CmdEvent.COMPOSITE) { int spolicy = r.ReadByte (); @@ -1502,7 +1517,7 @@ int Send (CommandSet command_set, int command, PacketWriter packet, Action parent_vtypes) { - if (v.Value != null) + if (v.Value != null) { + if (Version.AtLeast (2, 46) && v.Type == ElementType.Ptr) + return new PointerValue(this, GetType(v.Klass), (long)v.Value); return new PrimitiveValue (this, v.Value); + } switch (v.Type) { case ElementType.Void: @@ -682,8 +685,11 @@ internal ValueImpl EncodeValue (Value v, List duplicates = null) { duplicates.Add (v); return new ValueImpl { Type = ElementType.ValueType, Klass = (v as StructMirror).Type.Id, Fields = EncodeValues ((v as StructMirror).Fields, duplicates) }; + } else if (v is PointerValue) { + PointerValue val = (PointerValue)v; + return new ValueImpl { Type = ElementType.Ptr, Klass = val.Type.Id, Value = val.Address }; } else { - throw new NotSupportedException (); + throw new NotSupportedException ("Value of type " + v.GetType()); } } diff --git a/mcs/class/Mono.Debugger.Soft/Test/dtest-app.cs b/mcs/class/Mono.Debugger.Soft/Test/dtest-app.cs index 82efc79e51d8..20df95287288 100644 --- a/mcs/class/Mono.Debugger.Soft/Test/dtest-app.cs +++ b/mcs/class/Mono.Debugger.Soft/Test/dtest-app.cs @@ -145,6 +145,12 @@ public override string ToString () { } } + +public struct BlittableStruct { + public int i; + public double d; +} + public class GClass { public T field; public static T static_field; @@ -343,6 +349,7 @@ public static int Main (String[] args) { gc_suspend (); set_ip (); step_filters (); + pointers (); if (args.Length > 0 && args [0] == "local-reflect") local_reflect (); if (args.Length > 0 && args [0] == "domain-test") @@ -1720,6 +1727,18 @@ public void attach () { attach_break (); } } + + public static unsafe void pointer_arguments (int* a, BlittableStruct* s) { + *a = 0; + } + + [MethodImplAttribute (MethodImplOptions.NoInlining)] + public static unsafe void pointers () { + int[] a = new [] {1,2,3}; + BlittableStruct s = new BlittableStruct () { i = 2, d = 3.0 }; + fixed (int* pa = a) + pointer_arguments (pa, &s); + } } public class SentinelClass : MarshalByRefObject { diff --git a/mcs/class/Mono.Debugger.Soft/Test/dtest.cs b/mcs/class/Mono.Debugger.Soft/Test/dtest.cs index ccd3b6b7602e..7d5c0fdbe660 100644 --- a/mcs/class/Mono.Debugger.Soft/Test/dtest.cs +++ b/mcs/class/Mono.Debugger.Soft/Test/dtest.cs @@ -324,6 +324,8 @@ void AssertValue (object expected, object val) { Assert.AreEqual (expected, (val as StringMirror).Value); } else if (val is StructMirror && (val as StructMirror).Type.Name == "IntPtr") { AssertValue (expected, (val as StructMirror).Fields [0]); + } else if (val is PointerValue) { + Assert.AreEqual (expected, (val as PointerValue).Address); } else { Assert.IsTrue (val is PrimitiveValue); Assert.AreEqual (expected, (val as PrimitiveValue).Value); @@ -4361,6 +4363,38 @@ public void Hash () } } -} + [Test] + public void Pointer_GetValue () { + var e = run_until ("pointer_arguments"); + var frame = e.Thread.GetFrames () [0]; + + var param = frame.Method.GetParameters()[0]; + Assert.AreEqual("Int32*", param.ParameterType.Name); + + var pointerValue = frame.GetValue(param) as PointerValue; + Assert.AreEqual("Int32*", pointerValue.Type.Name); + + AssertValue(1, pointerValue.Value); + + var pointerValue2 = new PointerValue (pointerValue.VirtualMachine, pointerValue.Type, pointerValue.Address + pointerValue.Type.GetElementType().GetValueSize()); + + AssertValue(2, pointerValue2.Value); -} + + param = frame.Method.GetParameters()[1]; + Assert.AreEqual("BlittableStruct*", param.ParameterType.Name); + + pointerValue = frame.GetValue(param) as PointerValue; + Assert.AreEqual("BlittableStruct*", pointerValue.Type.Name); + + var structValue = pointerValue.Value as StructMirror; + Assert.AreEqual("BlittableStruct", structValue.Type.Name); + + object f = structValue.Fields[0]; + AssertValue (2, f); + f = structValue.Fields[1]; + AssertValue (3.0, f); + + } +} // class DebuggerTests +} // namespace diff --git a/mcs/class/System.Core/System.IO.Pipes/PipeStream.cs b/mcs/class/System.Core/System.IO.Pipes/PipeStream.cs index d60b71b1f5b7..738342c76e88 100644 --- a/mcs/class/System.Core/System.IO.Pipes/PipeStream.cs +++ b/mcs/class/System.Core/System.IO.Pipes/PipeStream.cs @@ -137,7 +137,7 @@ internal Stream Stream { #pragma warning disable 618 stream = new FileStream (handle.DangerousGetHandle (), CanRead ? (CanWrite ? FileAccess.ReadWrite : FileAccess.Read) - : FileAccess.Write, true, buffer_size, IsAsync); + : FileAccess.Write, false, buffer_size, IsAsync); #pragma warning restore 618 } return stream; diff --git a/mcs/class/System.Core/unityaot_System.Core.dll.exclude.sources b/mcs/class/System.Core/unityaot_System.Core.dll.exclude.sources new file mode 100644 index 000000000000..7953f1b8f0ef --- /dev/null +++ b/mcs/class/System.Core/unityaot_System.Core.dll.exclude.sources @@ -0,0 +1 @@ +../../../external/corefx/src/System.Linq/src/System/Linq/*.cs diff --git a/mcs/class/System.Core/unityaot_System.Core.dll.sources b/mcs/class/System.Core/unityaot_System.Core.dll.sources new file mode 100644 index 000000000000..5ec6fe909185 --- /dev/null +++ b/mcs/class/System.Core/unityaot_System.Core.dll.sources @@ -0,0 +1,3 @@ +#include winaot_System.Core.dll.sources +../referencesource/System.Core/System/Linq/Enumerable.cs +corefx/SR.cs diff --git a/mcs/class/System.Core/unityjit_System.Core.dll.sources b/mcs/class/System.Core/unityjit_System.Core.dll.sources new file mode 100644 index 000000000000..e5681ff8ff5b --- /dev/null +++ b/mcs/class/System.Core/unityjit_System.Core.dll.sources @@ -0,0 +1 @@ +#include net_4_x_System.Core.dll.sources diff --git a/mcs/class/System.Data/unityjit_System.Data.dll.sources b/mcs/class/System.Data/unityjit_System.Data.dll.sources new file mode 100644 index 000000000000..87d9b19fbf8c --- /dev/null +++ b/mcs/class/System.Data/unityjit_System.Data.dll.sources @@ -0,0 +1,4 @@ +#include corefx.unix.sources +#include net_4_x_System.Data.dll.sources + +../../../external/corefx/src/System.Data.Odbc/src/Common/System/Data/Common/ExternDll.Osx.cs diff --git a/mcs/class/System.Drawing/unityaot_System.Drawing.dll.sources b/mcs/class/System.Drawing/unityaot_System.Drawing.dll.sources new file mode 100644 index 000000000000..0403fdc41fcc --- /dev/null +++ b/mcs/class/System.Drawing/unityaot_System.Drawing.dll.sources @@ -0,0 +1 @@ +#include winaot_System.Drawing.dll.sources diff --git a/mcs/class/System.IdentityModel/unityaot_System.IdentityModel.dll.sources b/mcs/class/System.IdentityModel/unityaot_System.IdentityModel.dll.sources new file mode 100644 index 000000000000..429636751c2e --- /dev/null +++ b/mcs/class/System.IdentityModel/unityaot_System.IdentityModel.dll.sources @@ -0,0 +1 @@ +#include mobile_System.IdentityModel.dll.sources diff --git a/mcs/class/System.IdentityModel/unityjit_System.IdentityModel.dll.sources b/mcs/class/System.IdentityModel/unityjit_System.IdentityModel.dll.sources new file mode 100644 index 000000000000..7d312678c9ce --- /dev/null +++ b/mcs/class/System.IdentityModel/unityjit_System.IdentityModel.dll.sources @@ -0,0 +1 @@ +#include net_4_x_System.IdentityModel.dll.sources diff --git a/mcs/class/System.Runtime.Serialization/unityaot_System.Runtime.Serialization.dll.sources b/mcs/class/System.Runtime.Serialization/unityaot_System.Runtime.Serialization.dll.sources new file mode 100644 index 000000000000..6caafd411987 --- /dev/null +++ b/mcs/class/System.Runtime.Serialization/unityaot_System.Runtime.Serialization.dll.sources @@ -0,0 +1 @@ +#include mobile_System.Runtime.Serialization.dll.sources diff --git a/mcs/class/System.Runtime.Serialization/unityjit_System.Runtime.Serialization.dll.sources b/mcs/class/System.Runtime.Serialization/unityjit_System.Runtime.Serialization.dll.sources new file mode 100644 index 000000000000..5feabf388ccf --- /dev/null +++ b/mcs/class/System.Runtime.Serialization/unityjit_System.Runtime.Serialization.dll.sources @@ -0,0 +1 @@ +#include net_4_x_System.Runtime.Serialization.dll.sources diff --git a/mcs/class/System.ServiceModel.Internals/EventLogEntryType.cs b/mcs/class/System.ServiceModel.Internals/EventLogEntryType.cs index 74811394aa85..601f4574a999 100644 --- a/mcs/class/System.ServiceModel.Internals/EventLogEntryType.cs +++ b/mcs/class/System.ServiceModel.Internals/EventLogEntryType.cs @@ -41,7 +41,12 @@ build without adding this public API in System.dll. IF we brought this using System.Diagnostics; namespace System.Diagnostics { - public enum EventLogEntryType { +#if UNITY_AOT + internal +#else + public +#endif + enum EventLogEntryType { Error = 0x01, Warning = 0x02, Information = 0x04, diff --git a/mcs/class/System.ServiceModel.Web/unityaot_System.ServiceModel.Web.dll.sources b/mcs/class/System.ServiceModel.Web/unityaot_System.ServiceModel.Web.dll.sources new file mode 100644 index 000000000000..cbea0fae7b4f --- /dev/null +++ b/mcs/class/System.ServiceModel.Web/unityaot_System.ServiceModel.Web.dll.sources @@ -0,0 +1 @@ +#include mobile_System.ServiceModel.Web.dll.sources diff --git a/mcs/class/System.ServiceModel/Dummy_XM_4_5.cs b/mcs/class/System.ServiceModel/Dummy_XM_4_5.cs index 989c4dddc527..588ada68ccf6 100644 --- a/mcs/class/System.ServiceModel/Dummy_XM_4_5.cs +++ b/mcs/class/System.ServiceModel/Dummy_XM_4_5.cs @@ -126,7 +126,11 @@ internal EndpointDispatcher () namespace System.ServiceModel.Channels { +#if UNITY + static class UrlUtility { +#else public static class UrlUtility { +#endif public static string UrlEncode (string s, Encoding e) { return System.Runtime.UrlUtility.UrlEncode (s, e); diff --git a/mcs/class/System.ServiceModel/unityaot_System.ServiceModel.dll.sources b/mcs/class/System.ServiceModel/unityaot_System.ServiceModel.dll.sources new file mode 100644 index 000000000000..22ece5ce8cec --- /dev/null +++ b/mcs/class/System.ServiceModel/unityaot_System.ServiceModel.dll.sources @@ -0,0 +1 @@ +#include mobile_System.ServiceModel.dll.sources diff --git a/mcs/class/System.Web.Services/unityaot_System.Web.Services.dll.sources b/mcs/class/System.Web.Services/unityaot_System.Web.Services.dll.sources new file mode 100644 index 000000000000..9e39dcc73b13 --- /dev/null +++ b/mcs/class/System.Web.Services/unityaot_System.Web.Services.dll.sources @@ -0,0 +1 @@ +#include mobile_System.Web.Services.dll.sources diff --git a/mcs/class/System.XML/unityaot_System.Xml.dll.sources b/mcs/class/System.XML/unityaot_System.Xml.dll.sources new file mode 100644 index 000000000000..b6630930f75f --- /dev/null +++ b/mcs/class/System.XML/unityaot_System.Xml.dll.sources @@ -0,0 +1 @@ +#include mobile_System.Xml.dll.sources diff --git a/mcs/class/System/Mono.Net.Security/MonoTlsProviderFactory.cs b/mcs/class/System/Mono.Net.Security/MonoTlsProviderFactory.cs index dcc640ad30fe..7e2135f49c55 100644 --- a/mcs/class/System/Mono.Net.Security/MonoTlsProviderFactory.cs +++ b/mcs/class/System/Mono.Net.Security/MonoTlsProviderFactory.cs @@ -211,6 +211,7 @@ internal static void Debug (string message, params object[] args) #endregion + internal static readonly Guid UnityTlsId = new Guid("06414A97-74F6-488F-877B-A6CA9BBEB82E"); internal static readonly Guid AppleTlsId = new Guid ("981af8af-a3a3-419a-9f01-a518e3a17c1c"); internal static readonly Guid BtlsId = new Guid ("432d18c9-9348-4b90-bfbf-9f2a10e1f15b"); internal static readonly Guid LegacyId = new Guid ("809e77d5-56cc-4da8-b9f0-45e65ba9cceb"); @@ -226,6 +227,16 @@ static void InitializeProviderRegistration () providerRegistration = new Dictionary> (); providerCache = new Dictionary (); +#if UNITY + if (Mono.Unity.UnityTls.IsSupported) + { + var unityTlsEntry = new Tuple (UnityTlsId, "Mono.Unity.UnityTlsProvider"); + providerRegistration.Add ("default", unityTlsEntry); + providerRegistration.Add ("unitytls", unityTlsEntry); + return; + } +#endif + var appleTlsEntry = new Tuple (AppleTlsId, "Mono.AppleTls.AppleTlsProvider"); #if ONLY_APPLETLS || MONOTOUCH || XAMMAC diff --git a/mcs/class/System/Mono.UnityTls/CertHelper.cs b/mcs/class/System/Mono.UnityTls/CertHelper.cs new file mode 100644 index 000000000000..d669ca3cdafa --- /dev/null +++ b/mcs/class/System/Mono.UnityTls/CertHelper.cs @@ -0,0 +1,53 @@ +#if SECURITY_DEP +using System.Security.Cryptography.X509Certificates; + +namespace Mono.Unity +{ + internal unsafe static class CertHelper + { + public static void AddCertificatesToNativeChain (UnityTls.unitytls_x509list* nativeCertificateChain, X509CertificateCollection certificates, UnityTls.unitytls_errorstate* errorState) + { + foreach (var certificate in certificates) { + AddCertificateToNativeChain (nativeCertificateChain, certificate, errorState); + } + } + + public static void AddCertificateToNativeChain (UnityTls.unitytls_x509list* nativeCertificateChain, X509Certificate certificate, UnityTls.unitytls_errorstate* errorState) + { + byte[] certDer = certificate.GetRawCertData (); + fixed(byte* certDerPtr = certDer) { + UnityTls.NativeInterface.unitytls_x509list_append_der (nativeCertificateChain, certDerPtr, certDer.Length, errorState); + } + + var certificateImpl2 = certificate.Impl as X509Certificate2Impl; + if (certificateImpl2 != null) { + var intermediates = certificateImpl2.IntermediateCertificates; + if (intermediates != null && intermediates.Count > 0) { + for (int i=0; i NativeInterface != null; + + public static unitytls_interface_struct NativeInterface + { + get + { + if (marshalledInterface == null) { + IntPtr rawInterface = GetUnityTlsInterface (); + if (rawInterface == IntPtr.Zero) + return null; + marshalledInterface = Marshal.PtrToStructure (rawInterface); + } + return marshalledInterface; + } + } + } +} \ No newline at end of file diff --git a/mcs/class/System/Mono.UnityTls/UnityTlsContext.cs b/mcs/class/System/Mono.UnityTls/UnityTlsContext.cs new file mode 100644 index 000000000000..f54c82cac81a --- /dev/null +++ b/mcs/class/System/Mono.UnityTls/UnityTlsContext.cs @@ -0,0 +1,465 @@ +#if SECURITY_DEP +#if MONO_SECURITY_ALIAS +extern alias MonoSecurity; +#endif + +using System; +using System.IO; +using System.Text; +using System.Runtime.InteropServices; +using System.Security.Cryptography; +using System.Security.Cryptography.X509Certificates; +using System.Security.Authentication; + +#if MONO_SECURITY_ALIAS +using MonoSecurity::Mono.Security.Interface; +using MonoSecurity::Mono.Security.Cryptography; +#else +using Mono.Security.Interface; +using Mono.Security.Cryptography; +#endif + +using Mono.Net.Security; +using Mono.Util; + +using Int8 = System.Byte; + +namespace Mono.Unity +{ + unsafe internal class UnityTlsContext : MobileTlsContext + { + private const bool ActivateTracing = false; + + // Native UnityTls objects + UnityTls.unitytls_tlsctx* tlsContext = null; + UnityTls.unitytls_x509list* requestedClientCertChain = null; + UnityTls.unitytls_key* requestedClientKey = null; + + // States and certificates + X509Certificate localClientCertificate; + X509Certificate remoteCertificate; + MonoTlsConnectionInfo connectioninfo; + bool isAuthenticated = false; + bool hasContext = false; + + // Memory-buffer + byte [] writeBuffer; + byte [] readBuffer; + + GCHandle handle; + Exception lastException; + + public UnityTlsContext ( + MobileAuthenticatedStream parent, + bool serverMode, string targetHost, + SslProtocols enabledProtocols, X509Certificate serverCertificate, + X509CertificateCollection clientCertificates, bool askForClientCert) + : base (parent, serverMode, targetHost, enabledProtocols, serverCertificate, clientCertificates, askForClientCert) + { + // Need GCHandle to get a consistent pointer to this instance + handle = GCHandle.Alloc (this); + + var errorState = UnityTls.NativeInterface.unitytls_errorstate_create (); + + // Map selected protocols as best as we can. + UnityTls.unitytls_tlsctx_protocolrange protocolRange = new UnityTls.unitytls_tlsctx_protocolrange { + min = UnityTlsConversions.GetMinProtocol (enabledProtocols), + max = UnityTlsConversions.GetMaxProtocol (enabledProtocols), + }; + + UnityTls.unitytls_tlsctx_callbacks callbacks = new UnityTls.unitytls_tlsctx_callbacks { + write = WriteCallback, + read = ReadCallback, + data = (void*)(IntPtr)handle, + }; + + if (serverMode) { + ExtractNativeKeyAndChainFromManagedCertificate(serverCertificate, &errorState, out var serverCerts, out var serverPrivateKey); + try { + var serverCertsRef = UnityTls.NativeInterface.unitytls_x509list_get_ref (serverCerts, &errorState); + var serverKeyRef = UnityTls.NativeInterface.unitytls_key_get_ref (serverPrivateKey, &errorState); + Mono.Unity.Debug.CheckAndThrow (errorState, "Failed to parse server key/certificate"); + + tlsContext = UnityTls.NativeInterface.unitytls_tlsctx_create_server (protocolRange, callbacks, serverCertsRef.handle, serverKeyRef.handle, &errorState); + + if (askForClientCert) { + UnityTls.unitytls_x509list* clientAuthCAList = null; + try { + clientAuthCAList = UnityTls.NativeInterface.unitytls_x509list_create (&errorState); + var clientAuthCAListRef = UnityTls.NativeInterface.unitytls_x509list_get_ref (clientAuthCAList, &errorState); + UnityTls.NativeInterface.unitytls_tlsctx_server_require_client_authentication (tlsContext, clientAuthCAListRef, &errorState); + } finally { + UnityTls.NativeInterface.unitytls_x509list_free (clientAuthCAList); + } + } + } finally { + UnityTls.NativeInterface.unitytls_x509list_free (serverCerts); + UnityTls.NativeInterface.unitytls_key_free (serverPrivateKey); + } + } + else { + byte [] targetHostUtf8 = Encoding.UTF8.GetBytes (targetHost); + fixed (byte* targetHostUtf8Ptr = targetHostUtf8) { + tlsContext = UnityTls.NativeInterface.unitytls_tlsctx_create_client (protocolRange, callbacks, targetHostUtf8Ptr, targetHostUtf8.Length, &errorState); + } + + UnityTls.NativeInterface.unitytls_tlsctx_set_certificate_callback (tlsContext, CertificateCallback, (void*)(IntPtr)handle, &errorState); + } + + UnityTls.NativeInterface.unitytls_tlsctx_set_x509verify_callback (tlsContext, VerifyCallback, (void*)(IntPtr)handle, &errorState); + + Mono.Unity.Debug.CheckAndThrow (errorState, "Failed to create UnityTls context"); + + if (ActivateTracing) { + UnityTls.NativeInterface.unitytls_tlsctx_set_trace_callback (tlsContext, TraceCallback, null, &errorState); + Mono.Unity.Debug.CheckAndThrow (errorState, "Failed to set trace callback"); + } + + hasContext = true; + } + + static private void ExtractNativeKeyAndChainFromManagedCertificate(X509Certificate cert, UnityTls.unitytls_errorstate* errorState, out UnityTls.unitytls_x509list* nativeCertChain, out UnityTls.unitytls_key* nativeKey) + { + if (cert == null) + throw new ArgumentNullException ("cert"); + X509Certificate2 cert2 = cert as X509Certificate2; + if (cert2 == null || cert2.PrivateKey == null) + throw new ArgumentException ("Certificate does not have a private key", "cert"); + + nativeCertChain = null; + nativeKey = null; + try { + nativeCertChain = UnityTls.NativeInterface.unitytls_x509list_create (errorState); + CertHelper.AddCertificateToNativeChain (nativeCertChain, cert, errorState); + + byte[] privateKeyDer = PKCS8.PrivateKeyInfo.Encode (cert2.PrivateKey); + fixed(byte* privateKeyDerPtr = privateKeyDer) { + nativeKey = UnityTls.NativeInterface.unitytls_key_parse_der (privateKeyDerPtr, privateKeyDer.Length, null, 0, errorState); + } + } catch { + UnityTls.NativeInterface.unitytls_x509list_free (nativeCertChain); + UnityTls.NativeInterface.unitytls_key_free (nativeKey); + throw; + } + } + + public override bool HasContext { + get { return hasContext; } + } + public override bool IsAuthenticated { + get { return isAuthenticated; } + } + public override MonoTlsConnectionInfo ConnectionInfo { + get { return connectioninfo; } + } + internal override bool IsRemoteCertificateAvailable { + get { return remoteCertificate != null; } + } + internal override X509Certificate LocalClientCertificate { + get { return localClientCertificate; } + } + public override X509Certificate RemoteCertificate { + get { return remoteCertificate; } + } + public override TlsProtocols NegotiatedProtocol { + get { return ConnectionInfo.ProtocolVersion; } + } + + public override void Flush () + { + // NO-OP + } + + public override (int ret, bool wantMore) Read (byte[] buffer, int offset, int count) + { + bool wouldBlock = false; + int numBytesRead = 0; + + lastException = null; + var errorState = UnityTls.NativeInterface.unitytls_errorstate_create (); + fixed (byte* bufferPtr = buffer) { + numBytesRead = UnityTls.NativeInterface.unitytls_tlsctx_read (tlsContext, bufferPtr + offset, count, &errorState); + } + if (lastException != null) + throw lastException; + + if (errorState.code == UnityTls.unitytls_error_code.UNITYTLS_USER_WOULD_BLOCK) + wouldBlock = true; + else if (errorState.code == UnityTls.unitytls_error_code.UNITYTLS_STREAM_CLOSED) + return (0, false); // According to Apple and Btls implementation this is how we should handle gracefully closed connections. + else + Mono.Unity.Debug.CheckAndThrow (errorState, "Failed to read data from TLS context"); + + return (numBytesRead, wouldBlock); + } + + public override (int ret, bool wantMore) Write (byte[] buffer, int offset, int count) + { + bool wouldBlock = false; + int numBytesWritten = 0; + + lastException = null; + var errorState = UnityTls.NativeInterface.unitytls_errorstate_create (); + fixed (byte* bufferPtr = buffer) { + numBytesWritten = UnityTls.NativeInterface.unitytls_tlsctx_write (tlsContext, bufferPtr + offset, count, &errorState); + } + if (lastException != null) + throw lastException; + + if (errorState.code == UnityTls.unitytls_error_code.UNITYTLS_USER_WOULD_BLOCK) + wouldBlock = true; + else if (errorState.code == UnityTls.unitytls_error_code.UNITYTLS_STREAM_CLOSED) + return (0, false); // According to Apple and Btls implementation this is how we should handle gracefully closed connections. + else + Mono.Unity.Debug.CheckAndThrow (errorState, "Failed to write data to TLS context"); + + return (numBytesWritten, wouldBlock); + } + + public override void Shutdown () + { + if(Settings != null && Settings.SendCloseNotify) { + var err = UnityTls.NativeInterface.unitytls_errorstate_create (); + UnityTls.NativeInterface.unitytls_tlsctx_notify_close (tlsContext, &err); + } + + // Destroy native UnityTls objects + UnityTls.NativeInterface.unitytls_x509list_free (requestedClientCertChain); + UnityTls.NativeInterface.unitytls_key_free (requestedClientKey); + UnityTls.NativeInterface.unitytls_tlsctx_free (tlsContext); + tlsContext = null; + + hasContext = false; + } + + protected override void Dispose (bool disposing) + { + try { + if (disposing) + { + Shutdown(); + + // reset states + localClientCertificate = null; + remoteCertificate = null; + + if (localClientCertificate != null) { + localClientCertificate.Dispose (); + localClientCertificate = null; + } + if (remoteCertificate != null) { + remoteCertificate.Dispose (); + remoteCertificate = null; + } + + connectioninfo = null; + isAuthenticated = false; + hasContext = false; + } + + handle.Free(); + + } finally { + base.Dispose (disposing); + } + } + + public override void StartHandshake () + { + if (Settings != null && Settings.EnabledCiphers != null) { + var ciphers = new UnityTls.unitytls_ciphersuite [Settings.EnabledCiphers.Length]; + for (int i = 0; i < ciphers.Length; i++) + ciphers [i] = (UnityTls.unitytls_ciphersuite)Settings.EnabledCiphers [i]; + + var errorState = UnityTls.NativeInterface.unitytls_errorstate_create (); + fixed (UnityTls.unitytls_ciphersuite* ciphersPtr = ciphers) + UnityTls.NativeInterface.unitytls_tlsctx_set_supported_ciphersuites (tlsContext, ciphersPtr, ciphers.Length, &errorState); + Unity.Debug.CheckAndThrow (errorState, "Failed to set list of supported ciphers", AlertDescription.HandshakeFailure); + } + } + + public override bool ProcessHandshake () + { + lastException = null; + var errorState = UnityTls.NativeInterface.unitytls_errorstate_create (); + var result = UnityTls.NativeInterface.unitytls_tlsctx_process_handshake (tlsContext, &errorState); + if (errorState.code == UnityTls.unitytls_error_code.UNITYTLS_USER_WOULD_BLOCK) + return false; + if (lastException != null) + throw lastException; + + // Not done is not an error if we are server and don't ask for ClientCertificate + if (result == UnityTls.unitytls_x509verify_result.UNITYTLS_X509VERIFY_NOT_DONE && IsServer && !AskForClientCertificate) + Unity.Debug.CheckAndThrow (errorState, "Handshake failed", AlertDescription.HandshakeFailure); + else + Unity.Debug.CheckAndThrow (errorState, result, "Handshake failed", AlertDescription.HandshakeFailure); + + // .Net implementation gives the server a verification callback (with null cert) even if AskForClientCertificate is false. + // We stick to this behavior here. + if (IsServer && !AskForClientCertificate) { + if (!ValidateCertificate (null, null)) + throw new TlsException (AlertDescription.HandshakeFailure, "Verification failure during handshake"); + } + + return true; + } + + public override void FinishHandshake () + { + // Query some data. Ignore errors on the way since failure is not crucial. + var errorState = UnityTls.NativeInterface.unitytls_errorstate_create (); + var cipherSuite = UnityTls.NativeInterface.unitytls_tlsctx_get_ciphersuite(tlsContext, &errorState); + var protocolVersion = UnityTls.NativeInterface.unitytls_tlsctx_get_protocol(tlsContext, &errorState); + + connectioninfo = new MonoTlsConnectionInfo () { + CipherSuiteCode = (CipherSuiteCode)cipherSuite, + ProtocolVersion = UnityTlsConversions.ConvertProtocolVersion(protocolVersion), + PeerDomainName = ServerName + + // TODO: + // The following properties can be deducted from CipherSuiteCode. + // It looks though like as of writing no Mono implemention fills it out and there is also no mechanism that does that automatically + // + //CipherAlgorithmType + //HashAlgorithmType + //ExchangeAlgorithmType + }; + isAuthenticated = true; + } + + [MonoPInvokeCallback (typeof (UnityTls.unitytls_tlsctx_write_callback))] + static private size_t WriteCallback (void* userData, byte* data, size_t bufferLen, UnityTls.unitytls_errorstate* errorState) + { + var handle = (GCHandle)(IntPtr)userData; + var context = (UnityTlsContext)handle.Target; + return context.WriteCallback (data, bufferLen, errorState); + } + + private size_t WriteCallback (byte* data, size_t bufferLen, UnityTls.unitytls_errorstate* errorState) + { + try { + if (writeBuffer == null || writeBuffer.Length < bufferLen) + writeBuffer = new byte[bufferLen]; + Marshal.Copy ((IntPtr)data, writeBuffer, 0, bufferLen); + + if (!Parent.InternalWrite (writeBuffer, 0, bufferLen)) { + UnityTls.NativeInterface.unitytls_errorstate_raise_error (errorState, UnityTls.unitytls_error_code.UNITYTLS_USER_WRITE_FAILED); + return 0; + } + + return bufferLen; + } catch (Exception ex) { // handle all exceptions and store them for later since we don't want to let them go through native code. + UnityTls.NativeInterface.unitytls_errorstate_raise_error (errorState, UnityTls.unitytls_error_code.UNITYTLS_USER_UNKNOWN_ERROR); + if (lastException == null) + lastException = ex; + return 0; + } + } + + [MonoPInvokeCallback (typeof (UnityTls.unitytls_tlsctx_read_callback))] + static private size_t ReadCallback (void* userData, byte* buffer, size_t bufferLen, UnityTls.unitytls_errorstate* errorState) + { + var handle = (GCHandle)(IntPtr)userData; + var context = (UnityTlsContext)handle.Target; + return context.ReadCallback (buffer, bufferLen, errorState); + } + + private size_t ReadCallback (byte* buffer, size_t bufferLen, UnityTls.unitytls_errorstate* errorState) + { + try { + if (readBuffer == null || readBuffer.Length < bufferLen) + readBuffer = new byte [bufferLen]; + + bool wouldBlock; + int numBytesRead = Parent.InternalRead (readBuffer, 0, bufferLen, out wouldBlock); + if (wouldBlock) { + UnityTls.NativeInterface.unitytls_errorstate_raise_error (errorState, UnityTls.unitytls_error_code.UNITYTLS_USER_WOULD_BLOCK); + return 0; + } + if (numBytesRead < 0) { + UnityTls.NativeInterface.unitytls_errorstate_raise_error (errorState, UnityTls.unitytls_error_code.UNITYTLS_USER_READ_FAILED); + return 0; + } + + Marshal.Copy (readBuffer, 0, (IntPtr)buffer, bufferLen); + return numBytesRead; + } catch (Exception ex) { // handle all exceptions and store them for later since we don't want to let them go through native code. + UnityTls.NativeInterface.unitytls_errorstate_raise_error (errorState, UnityTls.unitytls_error_code.UNITYTLS_USER_UNKNOWN_ERROR); + if (lastException == null) + lastException = ex; + return 0; + } + } + + [MonoPInvokeCallback (typeof (UnityTls.unitytls_tlsctx_x509verify_callback))] + static private UnityTls.unitytls_x509verify_result VerifyCallback (void* userData, UnityTls.unitytls_x509list_ref chain, UnityTls.unitytls_errorstate* errorState) + { + var handle = (GCHandle)(IntPtr)userData; + var context = (UnityTlsContext)handle.Target; + return context.VerifyCallback (chain, errorState); + } + + private UnityTls.unitytls_x509verify_result VerifyCallback (UnityTls.unitytls_x509list_ref chain, UnityTls.unitytls_errorstate* errorState) + { + try { + X509CertificateCollection certificates = CertHelper.NativeChainToManagedCollection (chain, errorState); + remoteCertificate = new X509Certificate (certificates [0]); + + if (ValidateCertificate (certificates)) + return UnityTls.unitytls_x509verify_result.UNITYTLS_X509VERIFY_SUCCESS; + else + return UnityTls.unitytls_x509verify_result.UNITYTLS_X509VERIFY_FLAG_NOT_TRUSTED; + } catch (Exception ex) { // handle all exceptions and store them for later since we don't want to let them go through native code. + if (lastException == null) + lastException = ex; + return UnityTls.unitytls_x509verify_result.UNITYTLS_X509VERIFY_FATAL_ERROR; + } + } + + [MonoPInvokeCallback (typeof (UnityTls.unitytls_tlsctx_certificate_callback))] + static private void CertificateCallback (void* userData, UnityTls.unitytls_tlsctx* ctx, Int8* cn, size_t cnLen, UnityTls.unitytls_x509name* caList, size_t caListLen, UnityTls.unitytls_x509list_ref* chain, UnityTls.unitytls_key_ref* key, UnityTls.unitytls_errorstate* errorState) + { + var handle = (GCHandle)(IntPtr)userData; + var context = (UnityTlsContext)handle.Target; + context.CertificateCallback (ctx, cn, cnLen, caList, caListLen, chain, key, errorState); + } + + private void CertificateCallback (UnityTls.unitytls_tlsctx* ctx, Int8* cn, size_t cnLen, UnityTls.unitytls_x509name* caList, size_t caListLen, UnityTls.unitytls_x509list_ref* chain, UnityTls.unitytls_key_ref* key, UnityTls.unitytls_errorstate* errorState) + { + try { + if (remoteCertificate == null) + throw new TlsException (AlertDescription.InternalError, "Cannot request client certificate before receiving one from the server."); + + localClientCertificate = SelectClientCertificate (remoteCertificate, null); + + if (localClientCertificate == null) { + *chain = new UnityTls.unitytls_x509list_ref { handle = UnityTls.NativeInterface.UNITYTLS_INVALID_HANDLE }; + *key = new UnityTls.unitytls_key_ref { handle = UnityTls.NativeInterface.UNITYTLS_INVALID_HANDLE }; + } else { + // Need to create native objects for client chain/key. Need to keep them cached. + // Make sure we don't have old native objects still around. + UnityTls.NativeInterface.unitytls_x509list_free (requestedClientCertChain); + UnityTls.NativeInterface.unitytls_key_free (requestedClientKey); + + ExtractNativeKeyAndChainFromManagedCertificate(localClientCertificate, errorState, out requestedClientCertChain, out requestedClientKey); + *chain = UnityTls.NativeInterface.unitytls_x509list_get_ref (requestedClientCertChain, errorState); + *key = UnityTls.NativeInterface.unitytls_key_get_ref (requestedClientKey, errorState); + } + + Unity.Debug.CheckAndThrow (*errorState, "Failed to retrieve certificates on request.", AlertDescription.HandshakeFailure); + } catch (Exception ex) { // handle all exceptions and store them for later since we don't want to let them go through native code. + UnityTls.NativeInterface.unitytls_errorstate_raise_error (errorState, UnityTls.unitytls_error_code.UNITYTLS_USER_UNKNOWN_ERROR); + if (lastException == null) + lastException = ex; + } + } + + [MonoPInvokeCallback (typeof (UnityTls.unitytls_tlsctx_trace_callback))] + static private void TraceCallback (void* userData, UnityTls.unitytls_tlsctx* ctx, byte* traceMessage, size_t traceMessageLen) + { + string message = Encoding.UTF8.GetString (traceMessage, traceMessageLen); + System.Console.Write (message); + } + } +} +#endif \ No newline at end of file diff --git a/mcs/class/System/Mono.UnityTls/UnityTlsConversions.cs b/mcs/class/System/Mono.UnityTls/UnityTlsConversions.cs new file mode 100644 index 000000000000..e72f8e623c29 --- /dev/null +++ b/mcs/class/System/Mono.UnityTls/UnityTlsConversions.cs @@ -0,0 +1,107 @@ +#if SECURITY_DEP + +#if MONO_SECURITY_ALIAS +extern alias MonoSecurity; +using MonoSecurity::Mono.Security.Interface; +#else +using Mono.Security.Interface; +#endif + +using System.Security.Authentication; + +namespace Mono.Unity +{ + internal static class UnityTlsConversions + { + public static UnityTls.unitytls_protocol GetMinProtocol (SslProtocols protocols) + { + if (protocols.HasFlag (SslProtocols.Tls)) + return UnityTls.unitytls_protocol.UNITYTLS_PROTOCOL_TLS_1_0; + if (protocols.HasFlag (SslProtocols.Tls11)) + return UnityTls.unitytls_protocol.UNITYTLS_PROTOCOL_TLS_1_1; + if (protocols.HasFlag (SslProtocols.Tls12)) + return UnityTls.unitytls_protocol.UNITYTLS_PROTOCOL_TLS_1_2; + return UnityTls.unitytls_protocol.UNITYTLS_PROTOCOL_TLS_1_2; // Behavior as in AppleTlsContext + } + + public static UnityTls.unitytls_protocol GetMaxProtocol (SslProtocols protocols) + { + if (protocols.HasFlag (SslProtocols.Tls12)) + return UnityTls.unitytls_protocol.UNITYTLS_PROTOCOL_TLS_1_2; + if (protocols.HasFlag (SslProtocols.Tls11)) + return UnityTls.unitytls_protocol.UNITYTLS_PROTOCOL_TLS_1_1; + if (protocols.HasFlag (SslProtocols.Tls)) + return UnityTls.unitytls_protocol.UNITYTLS_PROTOCOL_TLS_1_0; + return UnityTls.unitytls_protocol.UNITYTLS_PROTOCOL_TLS_1_0; // Behavior as in AppleTlsContext + } + + public static TlsProtocols ConvertProtocolVersion(UnityTls.unitytls_protocol protocol) + { + switch (protocol) + { + case UnityTls.unitytls_protocol.UNITYTLS_PROTOCOL_TLS_1_0: + return TlsProtocols.Tls10; + case UnityTls.unitytls_protocol.UNITYTLS_PROTOCOL_TLS_1_1: + return TlsProtocols.Tls11; + case UnityTls.unitytls_protocol.UNITYTLS_PROTOCOL_TLS_1_2: + return TlsProtocols.Tls12; + case UnityTls.unitytls_protocol.UNITYTLS_PROTOCOL_INVALID: + return TlsProtocols.Zero; + } + return TlsProtocols.Zero; + } + + public static AlertDescription VerifyResultToAlertDescription (UnityTls.unitytls_x509verify_result verifyResult, AlertDescription defaultAlert = AlertDescription.InternalError) + { + if (verifyResult == UnityTls.unitytls_x509verify_result.UNITYTLS_X509VERIFY_FATAL_ERROR) + return AlertDescription.CertificateUnknown; + else if (verifyResult.HasFlag (UnityTls.unitytls_x509verify_result.UNITYTLS_X509VERIFY_FLAG_EXPIRED)) + return AlertDescription.CertificateExpired; + else if (verifyResult.HasFlag (UnityTls.unitytls_x509verify_result.UNITYTLS_X509VERIFY_FLAG_REVOKED)) + return AlertDescription.CertificateRevoked; + else if (verifyResult.HasFlag (UnityTls.unitytls_x509verify_result.UNITYTLS_X509VERIFY_FLAG_CN_MISMATCH)) + return AlertDescription.UnknownCA; + else if (verifyResult.HasFlag (UnityTls.unitytls_x509verify_result.UNITYTLS_X509VERIFY_FLAG_NOT_TRUSTED)) + return AlertDescription.CertificateUnknown; + + else if (verifyResult.HasFlag (UnityTls.unitytls_x509verify_result.UNITYTLS_X509VERIFY_FLAG_USER_ERROR1)) + return AlertDescription.UserCancelled; + else if (verifyResult.HasFlag (UnityTls.unitytls_x509verify_result.UNITYTLS_X509VERIFY_FLAG_USER_ERROR2)) + return AlertDescription.UserCancelled; + else if (verifyResult.HasFlag (UnityTls.unitytls_x509verify_result.UNITYTLS_X509VERIFY_FLAG_USER_ERROR2)) + return AlertDescription.UserCancelled; + else if (verifyResult.HasFlag (UnityTls.unitytls_x509verify_result.UNITYTLS_X509VERIFY_FLAG_USER_ERROR3)) + return AlertDescription.UserCancelled; + else if (verifyResult.HasFlag (UnityTls.unitytls_x509verify_result.UNITYTLS_X509VERIFY_FLAG_USER_ERROR4)) + return AlertDescription.UserCancelled; + else if (verifyResult.HasFlag (UnityTls.unitytls_x509verify_result.UNITYTLS_X509VERIFY_FLAG_USER_ERROR5)) + return AlertDescription.UserCancelled; + else if (verifyResult.HasFlag (UnityTls.unitytls_x509verify_result.UNITYTLS_X509VERIFY_FLAG_USER_ERROR6)) + return AlertDescription.UserCancelled; + else if (verifyResult.HasFlag (UnityTls.unitytls_x509verify_result.UNITYTLS_X509VERIFY_FLAG_USER_ERROR7)) + return AlertDescription.UserCancelled; + else if (verifyResult.HasFlag (UnityTls.unitytls_x509verify_result.UNITYTLS_X509VERIFY_FLAG_USER_ERROR8)) + return AlertDescription.UserCancelled; + + return defaultAlert; + } + + public static MonoSslPolicyErrors VerifyResultToPolicyErrror (UnityTls.unitytls_x509verify_result verifyResult) + { + // First, check "non-flags" + if (verifyResult == UnityTls.unitytls_x509verify_result.UNITYTLS_X509VERIFY_SUCCESS) + return MonoSslPolicyErrors.None; + else if (verifyResult == UnityTls.unitytls_x509verify_result.UNITYTLS_X509VERIFY_FATAL_ERROR) + return MonoSslPolicyErrors.RemoteCertificateChainErrors; + + MonoSslPolicyErrors error = MonoSslPolicyErrors.None; + if (verifyResult.HasFlag (UnityTls.unitytls_x509verify_result.UNITYTLS_X509VERIFY_FLAG_CN_MISMATCH)) + error |= MonoSslPolicyErrors.RemoteCertificateNameMismatch; + // Anything else translates to MonoSslPolicyErrors.RemoteCertificateChainErrors. So if it is not the only flag, add it. + if (verifyResult != UnityTls.unitytls_x509verify_result.UNITYTLS_X509VERIFY_FLAG_CN_MISMATCH) + error |= MonoSslPolicyErrors.RemoteCertificateChainErrors; + return error; + } + } +} +#endif \ No newline at end of file diff --git a/mcs/class/System/Mono.UnityTls/UnityTlsProvider.cs b/mcs/class/System/Mono.UnityTls/UnityTlsProvider.cs new file mode 100644 index 000000000000..78c637c86803 --- /dev/null +++ b/mcs/class/System/Mono.UnityTls/UnityTlsProvider.cs @@ -0,0 +1,117 @@ +#if SECURITY_DEP +#if MONO_SECURITY_ALIAS +extern alias MonoSecurity; +#endif + +using System; +using System.Text; +using System.IO; +using System.Net.Security; +using System.Security.Authentication; +using System.Security.Cryptography.X509Certificates; + +using MNS = Mono.Net.Security; +#if MONO_SECURITY_ALIAS +using MonoSecurity::Mono.Security.Interface; +#else +using Mono.Security.Interface; +#endif + +namespace Mono.Unity +{ + unsafe internal class UnityTlsProvider : MonoTlsProvider + { + public override string Name { + get { return "unitytls"; } + } + + public override Guid ID => MNS.MonoTlsProviderFactory.UnityTlsId; + public override bool SupportsSslStream => true; + public override bool SupportsMonoExtensions => true; + public override bool SupportsConnectionInfo => true; + internal override bool SupportsCleanShutdown => true; + public override SslProtocols SupportedProtocols => SslProtocols.Tls12 | SslProtocols.Tls11 | SslProtocols.Tls; + + public override IMonoSslStream CreateSslStream ( + Stream innerStream, bool leaveInnerStreamOpen, + MonoTlsSettings settings = null) + { + return SslStream.CreateMonoSslStream (innerStream, leaveInnerStreamOpen, this, settings); + } + + internal override IMonoSslStream CreateSslStreamInternal ( + SslStream sslStream, Stream innerStream, bool leaveInnerStreamOpen, + MonoTlsSettings settings) + { + return new UnityTlsStream (innerStream, leaveInnerStreamOpen, sslStream, settings, this); + } + + internal override bool ValidateCertificate ( + ICertificateValidator2 validator, string targetHost, bool serverMode, + X509CertificateCollection certificates, bool wantsChain, ref X509Chain chain, + ref MonoSslPolicyErrors errors, ref int status11) + { + if (certificates == null) { + errors |= MonoSslPolicyErrors.RemoteCertificateNotAvailable; + return false; + } + + if (wantsChain) + chain = MNS.SystemCertificateValidator.CreateX509Chain (certificates); + + if (certificates == null || certificates.Count == 0) { + errors |= MonoSslPolicyErrors.RemoteCertificateNotAvailable; + return false; + } + + // fixup targetHost name by removing port + if (!string.IsNullOrEmpty (targetHost)) { + var pos = targetHost.IndexOf (':'); + if (pos > 0) + targetHost = targetHost.Substring (0, pos); + } + + // convert cert to native + var errorState = UnityTls.NativeInterface.unitytls_errorstate_create (); + var certificatesNative = UnityTls.NativeInterface.unitytls_x509list_create (&errorState); + var result = UnityTls.unitytls_x509verify_result.UNITYTLS_X509VERIFY_NOT_DONE; + try + { + // Things the validator provides that we might want to make use of here: + //validator.Settings.CheckCertificateName // not used by mono? + //validator.Settings.CheckCertificateRevocationStatus // not used by mono? + //validator.Settings.CertificateValidationTime + //validator.Settings.CertificateSearchPaths // currently only used by MonoBtlsProvider + + CertHelper.AddCertificatesToNativeChain (certificatesNative, certificates, &errorState); + var certificatesNativeRef = UnityTls.NativeInterface.unitytls_x509list_get_ref (certificatesNative, &errorState); + var targetHostUtf8 = Encoding.UTF8.GetBytes (targetHost); + + if (validator.Settings.TrustAnchors != null) { + var trustCAnative = UnityTls.NativeInterface.unitytls_x509list_create (&errorState); + CertHelper.AddCertificatesToNativeChain (trustCAnative, validator.Settings.TrustAnchors, &errorState); + var trustCAnativeRef = UnityTls.NativeInterface.unitytls_x509list_get_ref (certificatesNative, &errorState); + + fixed (byte* targetHostUtf8Ptr = targetHostUtf8) { + result = UnityTls.NativeInterface.unitytls_x509verify_explicit_ca (certificatesNativeRef, trustCAnativeRef, targetHostUtf8Ptr, targetHostUtf8.Length, null, null, &errorState); + } + + UnityTls.NativeInterface.unitytls_x509list_free (trustCAnative); + } else { + fixed (byte* targetHostUtf8Ptr = targetHostUtf8) { + result = UnityTls.NativeInterface.unitytls_x509verify_default_ca (certificatesNativeRef, targetHostUtf8Ptr, targetHostUtf8.Length, null, null, &errorState); + } + } + } + finally + { + UnityTls.NativeInterface.unitytls_x509list_free (certificatesNative); + } + + errors = UnityTlsConversions.VerifyResultToPolicyErrror(result); + return result == UnityTls.unitytls_x509verify_result.UNITYTLS_X509VERIFY_SUCCESS && + errorState.code == UnityTls.unitytls_error_code.UNITYTLS_SUCCESS; + } + } +} +#endif diff --git a/mcs/class/System/Mono.UnityTls/UnityTlsStream.cs b/mcs/class/System/Mono.UnityTls/UnityTlsStream.cs new file mode 100644 index 000000000000..9f99ae8e6a2d --- /dev/null +++ b/mcs/class/System/Mono.UnityTls/UnityTlsStream.cs @@ -0,0 +1,41 @@ +#if SECURITY_DEP +#if MONO_SECURITY_ALIAS +extern alias MonoSecurity; +#endif + +using System.IO; +using System.Net.Security; +using System.Security.Cryptography.X509Certificates; +using System.Security.Authentication; + +#if MONO_SECURITY_ALIAS +using MonoSecurity::Mono.Security.Interface; +#else +using Mono.Security.Interface; +#endif + +using MNS = Mono.Net.Security; + +namespace Mono.Unity +{ + class UnityTlsStream : MNS.MobileAuthenticatedStream + { + public UnityTlsStream (Stream innerStream, bool leaveInnerStreamOpen, SslStream owner, + MonoTlsSettings settings, MonoTlsProvider provider) + : base (innerStream, leaveInnerStreamOpen, owner, settings, provider) + { + } + + protected override MNS.MobileTlsContext CreateContext ( + bool serverMode, string targetHost, SslProtocols enabledProtocols, + X509Certificate serverCertificate, X509CertificateCollection clientCertificates, + bool askForClientCert) + { + return new UnityTlsContext ( + this, serverMode, targetHost, + enabledProtocols, serverCertificate, + clientCertificates, askForClientCert); + } + } +} +#endif \ No newline at end of file diff --git a/mcs/class/System/Mono.Util/MonoPInvokeCallbackAttribute.cs b/mcs/class/System/Mono.Util/MonoPInvokeCallbackAttribute.cs index 72acfed3d502..1e7130f58f8f 100644 --- a/mcs/class/System/Mono.Util/MonoPInvokeCallbackAttribute.cs +++ b/mcs/class/System/Mono.Util/MonoPInvokeCallbackAttribute.cs @@ -28,6 +28,7 @@ namespace Mono.Util { [Conditional("MONOTOUCH")] [Conditional("FULL_AOT_RUNTIME")] + [Conditional("UNITY")] [AttributeUsage (AttributeTargets.Method)] sealed class MonoPInvokeCallbackAttribute : Attribute { diff --git a/mcs/class/System/ReferenceSources/AutoWebProxyScriptEngine.cs b/mcs/class/System/ReferenceSources/AutoWebProxyScriptEngine.cs index f3b840e8f7f5..b667bdc9792b 100644 --- a/mcs/class/System/ReferenceSources/AutoWebProxyScriptEngine.cs +++ b/mcs/class/System/ReferenceSources/AutoWebProxyScriptEngine.cs @@ -46,14 +46,22 @@ public WebProxyData GetWebProxyData () WebProxyData data; // TODO: Could re-use some pieces from _AutoWebProxyScriptEngine.cs - if (IsWindows ()) { - data = InitializeRegistryGlobalProxy (); + try { + if (IsWindows ()) { + data = InitializeRegistryGlobalProxy (); + if (data != null) + return data; + } + + data = ReadEnvVariables (); if (data != null) return data; } + catch (DllNotFoundException) { + // This path will be hit on UWP since we're not allowed to read from registry + } - data = ReadEnvVariables (); - return data ?? new WebProxyData (); + return new WebProxyData (); } WebProxyData ReadEnvVariables () diff --git a/mcs/class/System/ReferenceSources/SecureStringHelper.cs b/mcs/class/System/ReferenceSources/SecureStringHelper.cs index 31372e2cc6cc..de5ac5809fa1 100644 --- a/mcs/class/System/ReferenceSources/SecureStringHelper.cs +++ b/mcs/class/System/ReferenceSources/SecureStringHelper.cs @@ -14,7 +14,18 @@ internal static string CreateString(SecureString secureString) if (secureString == null || secureString.Length == 0) return String.Empty; - +#if MONO + try + { + bstr = Marshal.SecureStringToGlobalAllocUnicode(secureString); + plainString = Marshal.PtrToStringUni(bstr); + } + finally + { + if (bstr != IntPtr.Zero) + Marshal.ZeroFreeGlobalAllocUnicode(bstr); + } +#else try { bstr = Marshal.SecureStringToBSTR(secureString); @@ -25,6 +36,7 @@ internal static string CreateString(SecureString secureString) if (bstr != IntPtr.Zero) Marshal.ZeroFreeBSTR(bstr); } +#endif return plainString; } diff --git a/mcs/class/System/ReferenceSources/SettingsSectionInternal.cs b/mcs/class/System/ReferenceSources/SettingsSectionInternal.cs index e7719c1afaad..c3bda137bfa7 100644 --- a/mcs/class/System/ReferenceSources/SettingsSectionInternal.cs +++ b/mcs/class/System/ReferenceSources/SettingsSectionInternal.cs @@ -30,6 +30,7 @@ internal static SettingsSectionInternal Section { internal bool Ipv6Enabled { get { +#if !UNITY #if CONFIGURATION_DEP && !MOBILE try { var config = (SettingsSection) System.Configuration.ConfigurationManager.GetSection ("system.net/settings"); @@ -37,6 +38,7 @@ internal bool Ipv6Enabled { return config.Ipv6.Enabled; } catch { } +#endif #endif return true; diff --git a/mcs/class/System/ReferenceSources/Win32Exception.cs b/mcs/class/System/ReferenceSources/Win32Exception.cs index a18b9fba8f69..c4ee090e8ef7 100644 --- a/mcs/class/System/ReferenceSources/Win32Exception.cs +++ b/mcs/class/System/ReferenceSources/Win32Exception.cs @@ -3,6 +3,9 @@ using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Text; +#if UNITY +using System.Collections.Generic; +#endif namespace System.ComponentModel { @@ -14,6 +17,11 @@ static extern int FormatMessage(int dwFlags, IntPtr lpSource, uint dwMessageId, [Out] StringBuilder lpBuffer, int nSize, IntPtr[] arguments); #endif +#if UNITY + static bool s_ErrorMessagesInitialized = false; + static Dictionary s_ErrorMessage = new Dictionary(); +#endif + internal static string GetErrorMessage (int error) { #if !MOBILE @@ -29,7 +37,14 @@ internal static string GetErrorMessage (int error) return sb.ToString (); } #endif - +#if UNITY + if (!s_ErrorMessagesInitialized) + InitializeErrorMessages(); + string message; + if (s_ErrorMessage.TryGetValue(error, out message)) + return message; + return string.Format ("mono-io-layer-error ({0})", error); +#else switch (error) { case 0: /* ERROR_SUCCESS */ return "Success"; case 2: /* ERROR_FILE_NOT_FOUND */ return "Cannot find the specified file"; @@ -1738,6 +1753,1728 @@ internal static string GetErrorMessage (int error) default: return string.Format ("mono-io-layer-error ({0})", error); } +#endif // UNITY + } + +#if UNITY + static void InitializeErrorMessages() + { + if (s_ErrorMessagesInitialized) + return; + + lock (s_ErrorMessage) + { + if (s_ErrorMessagesInitialized) + return; + + s_ErrorMessage.Add(0, "Success"); /* ERROR_SUCCESS */ + s_ErrorMessage.Add(2, "Cannot find the specified file"); /* ERROR_FILE_NOT_FOUND */ + s_ErrorMessage.Add(3, "Cannot find the specified file"); /* ERROR_PATH_NOT_FOUND */ + s_ErrorMessage.Add(4, "Too many open files"); /* ERROR_TOO_MANY_OPEN_FILES */ + s_ErrorMessage.Add(5, "Access denied"); /* ERROR_ACCESS_DENIED */ + s_ErrorMessage.Add(6, "Invalid handle"); /* ERROR_INVALID_HANDLE */ + s_ErrorMessage.Add(13, "Invalid data"); /* ERROR_INVALID_DATA */ + s_ErrorMessage.Add(14, "Out of memory"); /* ERROR_OUTOFMEMORY */ + s_ErrorMessage.Add(17, "Not same device"); /* ERROR_NOT_SAME_DEVICE */ + s_ErrorMessage.Add(18, "No more files"); /* ERROR_NO_MORE_FILES */ + s_ErrorMessage.Add(24, "Bad length"); /* ERROR_BAD_LENGTH */ + s_ErrorMessage.Add(31, "General failure"); /* ERROR_GEN_FAILURE */ + s_ErrorMessage.Add(32, "Sharing violation"); /* ERROR_SHARING_VIOLATION */ + s_ErrorMessage.Add(33, "Lock violation"); /* ERROR_LOCK_VIOLATION */ + s_ErrorMessage.Add(50, "Operation not supported"); /* ERROR_NOT_SUPPORTED */ + s_ErrorMessage.Add(55, "Device does not exist"); /* ERROR_DEV_NOT_EXIST */ + s_ErrorMessage.Add(87, "Invalid parameter"); /* ERROR_INVALID_PARAMETER */ + s_ErrorMessage.Add(120, "Call not implemented"); /* ERROR_CALL_NOT_IMPLEMENTED */ + s_ErrorMessage.Add(123, "Invalid name"); /* ERROR_INVALID_NAME */ + s_ErrorMessage.Add(127, "Process not found"); /* ERROR_PROC_NOT_FOUND */ + s_ErrorMessage.Add(183, "Already exists"); /* ERROR_ALREADY_EXISTS */ + s_ErrorMessage.Add(267, "Is a directory"); /* ERROR_DIRECTORY */ + s_ErrorMessage.Add(995, "Operation aborted"); /* ERROR_OPERATION_ABORTED */ + s_ErrorMessage.Add(6000, "Encryption failed"); /* ERROR_ENCRYPTION_FAILED */ + s_ErrorMessage.Add(10004, "interrupted"); /* WSAEINTR */ + s_ErrorMessage.Add(10009, "Bad file number"); /* WSAEBADF */ + s_ErrorMessage.Add(10013, "Access denied"); /* WSAEACCES */ + s_ErrorMessage.Add(10014, "Bad address"); /* WSAEFAULT */ + s_ErrorMessage.Add(10022, "Invalid arguments"); /* WSAEINVAL */ + s_ErrorMessage.Add(10024, "Too many open files"); /* WSAEMFILE */ + s_ErrorMessage.Add(10035, "Operation on non-blocking socket would block"); /* WSAEWOULDBLOCK */ + s_ErrorMessage.Add(10036, "Operation in progress"); /* WSAEINPROGRESS */ + s_ErrorMessage.Add(10037, "Operation already in progress"); /* WSAEALREADY */ + s_ErrorMessage.Add(10038, "The descriptor is not a socket"); /* WSAENOTSOCK */ + s_ErrorMessage.Add(10039, "Destination address required"); /* WSAEDESTADDRREQ */ + s_ErrorMessage.Add(10040, "Message too long"); /* WSAEMSGSIZE */ + s_ErrorMessage.Add(10041, "Protocol wrong type for socket"); /* WSAEPROTOTYPE */ + s_ErrorMessage.Add(10042, "Protocol option not supported"); /* WSAENOPROTOOPT */ + s_ErrorMessage.Add(10043, "Protocol not supported"); /* WSAEPROTONOSUPPORT */ + s_ErrorMessage.Add(10044, "Socket not supported"); /* WSAESOCKTNOSUPPORT */ + s_ErrorMessage.Add(10045, "Operation not supported"); /* WSAEOPNOTSUPP */ + s_ErrorMessage.Add(10046, "Protocol family not supported"); /* WSAEPFNOSUPPORT */ + s_ErrorMessage.Add(10047, "An address incompatible with the requested protocol was used"); /* WSAEAFNOSUPPORT */ + s_ErrorMessage.Add(10048, "Address already in use"); /* WSAEADDRINUSE */ + s_ErrorMessage.Add(10049, "The requested address is not valid in this context"); /* WSAEADDRNOTAVAIL */ + s_ErrorMessage.Add(10050, "Network subsystem is down"); /* WSAENETDOWN */ + s_ErrorMessage.Add(10051, "Network is unreachable"); /* WSAENETUNREACH */ + s_ErrorMessage.Add(10052, "Connection broken, keep-alive detected a problem"); /* WSAENETRESET */ + s_ErrorMessage.Add(10053, "An established connection was aborted in your host machine."); /* WSAECONNABORTED */ + s_ErrorMessage.Add(10054, "Connection reset by peer"); /* WSAECONNRESET */ + s_ErrorMessage.Add(10055, "Not enough buffer space is available"); /* WSAENOBUFS */ + s_ErrorMessage.Add(10056, "Socket is already connected"); /* WSAEISCONN */ + s_ErrorMessage.Add(10057, "The socket is not connected"); /* WSAENOTCONN */ + s_ErrorMessage.Add(10058, "The socket has been shut down"); /* WSAESHUTDOWN */ + s_ErrorMessage.Add(10059, "Too many references: cannot splice"); /* WSAETOOMANYREFS */ + s_ErrorMessage.Add(10060, "Connection timed out"); /* WSAETIMEDOUT */ + s_ErrorMessage.Add(10061, "Connection refused"); /* WSAECONNREFUSED */ + s_ErrorMessage.Add(10062, "Too many symbolic links encountered"); /* WSAELOOP */ + s_ErrorMessage.Add(10063, "File name too long"); /* WSAENAMETOOLONG */ + s_ErrorMessage.Add(10064, "Host is down"); /* WSAEHOSTDOWN */ + s_ErrorMessage.Add(10065, "No route to host"); /* WSAEHOSTUNREACH */ + s_ErrorMessage.Add(10066, "Directory not empty"); /* WSAENOTEMPTY */ + s_ErrorMessage.Add(10067, "EPROCLIM"); /* WSAEPROCLIM */ + s_ErrorMessage.Add(10068, "Too many users"); /* WSAEUSERS */ + s_ErrorMessage.Add(10069, "Quota exceeded"); /* WSAEDQUOT */ + s_ErrorMessage.Add(10070, "Stale NFS file handle"); /* WSAESTALE */ + s_ErrorMessage.Add(10071, "Object is remote"); /* WSAEREMOTE */ + s_ErrorMessage.Add(10091, "SYSNOTREADY"); /* WSASYSNOTREADY */ + s_ErrorMessage.Add(10092, "VERNOTSUPPORTED"); /* WSAVERNOTSUPPORTED */ + s_ErrorMessage.Add(10093, "Winsock not initialised"); /* WSANOTINITIALISED */ + s_ErrorMessage.Add(10101, "EDISCON"); /* WSAEDISCON */ + s_ErrorMessage.Add(10102, "ENOMORE"); /* WSAENOMORE */ + s_ErrorMessage.Add(10103, "Operation canceled"); /* WSAECANCELLED */ + s_ErrorMessage.Add(10104, "EINVALIDPROCTABLE"); /* WSAEINVALIDPROCTABLE */ + s_ErrorMessage.Add(10105, "EINVALIDPROVIDER"); /* WSAEINVALIDPROVIDER */ + s_ErrorMessage.Add(10106, "EPROVIDERFAILEDINIT"); /* WSAEPROVIDERFAILEDINIT */ + s_ErrorMessage.Add(10107, "System call failed"); /* WSASYSCALLFAILURE */ + s_ErrorMessage.Add(10108, "SERVICE_NOT_FOUND"); /* WSASERVICE_NOT_FOUND */ + s_ErrorMessage.Add(10109, "TYPE_NOT_FOUND"); /* WSATYPE_NOT_FOUND */ + s_ErrorMessage.Add(10112, "EREFUSED"); /* WSAEREFUSED */ + s_ErrorMessage.Add(11001, "No such host is known"); /* WSAHOST_NOT_FOUND */ + s_ErrorMessage.Add(11002, "A temporary error occurred on an authoritative name server. Try again later."); /* WSATRY_AGAIN */ + s_ErrorMessage.Add(11003, "No recovery"); /* WSANO_RECOVERY */ + s_ErrorMessage.Add(11004, "No data"); /* WSANO_DATA */ +#if !MOBILE + s_ErrorMessage.Add(1, "Invalid function"); /* ERROR_INVALID_FUNCTION */ + s_ErrorMessage.Add(7, "Arena trashed"); /* ERROR_ARENA_TRASHED */ + s_ErrorMessage.Add(8, "Not enough memory"); /* ERROR_NOT_ENOUGH_MEMORY */ + s_ErrorMessage.Add(9, "Invalid block"); /* ERROR_INVALID_BLOCK */ + s_ErrorMessage.Add(10, "Bad environment"); /* ERROR_BAD_ENVIRONMENT */ + s_ErrorMessage.Add(11, "Bad format"); /* ERROR_BAD_FORMAT */ + s_ErrorMessage.Add(12, "Invalid access"); /* ERROR_INVALID_ACCESS */ + s_ErrorMessage.Add(15, "Invalid drive"); /* ERROR_INVALID_DRIVE */ + s_ErrorMessage.Add(16, "Current directory"); /* ERROR_CURRENT_DIRECTORY */ + s_ErrorMessage.Add(19, "Write protect"); /* ERROR_WRITE_PROTECT */ + s_ErrorMessage.Add(20, "Bad unit"); /* ERROR_BAD_UNIT */ + s_ErrorMessage.Add(21, "Not ready"); /* ERROR_NOT_READY */ + s_ErrorMessage.Add(22, "Bad command"); /* ERROR_BAD_COMMAND */ + s_ErrorMessage.Add(23, "CRC"); /* ERROR_CRC */ + s_ErrorMessage.Add(25, "Seek"); /* ERROR_SEEK */ + s_ErrorMessage.Add(26, "Not DOS disk"); /* ERROR_NOT_DOS_DISK */ + s_ErrorMessage.Add(27, "Sector not found"); /* ERROR_SECTOR_NOT_FOUND */ + s_ErrorMessage.Add(28, "Out of paper"); /* ERROR_OUT_OF_PAPER */ + s_ErrorMessage.Add(29, "Write fault"); /* ERROR_WRITE_FAULT */ + s_ErrorMessage.Add(30, "Read fault"); /* ERROR_READ_FAULT */ + s_ErrorMessage.Add(34, "Wrong disk"); /* ERROR_WRONG_DISK */ + s_ErrorMessage.Add(36, "Sharing buffer exceeded"); /* ERROR_SHARING_BUFFER_EXCEEDED */ + s_ErrorMessage.Add(38, "Handle EOF"); /* ERROR_HANDLE_EOF */ + s_ErrorMessage.Add(39, "Handle disk full"); /* ERROR_HANDLE_DISK_FULL */ + s_ErrorMessage.Add(51, "Rem not list"); /* ERROR_REM_NOT_LIST */ + s_ErrorMessage.Add(52, "Duplicate name"); /* ERROR_DUP_NAME */ + s_ErrorMessage.Add(53, "Bad netpath"); /* ERROR_BAD_NETPATH */ + s_ErrorMessage.Add(54, "Network busy"); /* ERROR_NETWORK_BUSY */ + s_ErrorMessage.Add(56, "Too many commands"); /* ERROR_TOO_MANY_CMDS */ + s_ErrorMessage.Add(57, "ADAP HDW error"); /* ERROR_ADAP_HDW_ERR */ + s_ErrorMessage.Add(58, "Bad net response"); /* ERROR_BAD_NET_RESP */ + s_ErrorMessage.Add(59, "Unexpected net error"); /* ERROR_UNEXP_NET_ERR */ + s_ErrorMessage.Add(60, "Bad rem adap"); /* ERROR_BAD_REM_ADAP */ + s_ErrorMessage.Add(61, "Print queue full"); /* ERROR_PRINTQ_FULL */ + s_ErrorMessage.Add(62, "No spool space"); /* ERROR_NO_SPOOL_SPACE */ + s_ErrorMessage.Add(63, "Print cancelled"); /* ERROR_PRINT_CANCELLED */ + s_ErrorMessage.Add(64, "Netname deleted"); /* ERROR_NETNAME_DELETED */ + s_ErrorMessage.Add(65, "Network access denied"); /* ERROR_NETWORK_ACCESS_DENIED */ + s_ErrorMessage.Add(66, "Bad device type"); /* ERROR_BAD_DEV_TYPE */ + s_ErrorMessage.Add(67, "Bad net name"); /* ERROR_BAD_NET_NAME */ + s_ErrorMessage.Add(68, "Too many names"); /* ERROR_TOO_MANY_NAMES */ + s_ErrorMessage.Add(69, "Too many sessions"); /* ERROR_TOO_MANY_SESS */ + s_ErrorMessage.Add(70, "Sharing paused"); /* ERROR_SHARING_PAUSED */ + s_ErrorMessage.Add(71, "Req not accep"); /* ERROR_REQ_NOT_ACCEP */ + s_ErrorMessage.Add(72, "Redir paused"); /* ERROR_REDIR_PAUSED */ + s_ErrorMessage.Add(80, "File exists"); /* ERROR_FILE_EXISTS */ + s_ErrorMessage.Add(82, "Cannot make"); /* ERROR_CANNOT_MAKE */ + s_ErrorMessage.Add(83, "Fail i24"); /* ERROR_FAIL_I24 */ + s_ErrorMessage.Add(84, "Out of structures"); /* ERROR_OUT_OF_STRUCTURES */ + s_ErrorMessage.Add(85, "Already assigned"); /* ERROR_ALREADY_ASSIGNED */ + s_ErrorMessage.Add(86, "Invalid password"); /* ERROR_INVALID_PASSWORD */ + s_ErrorMessage.Add(88, "Net write fault"); /* ERROR_NET_WRITE_FAULT */ + s_ErrorMessage.Add(89, "No proc slots"); /* ERROR_NO_PROC_SLOTS */ + s_ErrorMessage.Add(100, "Too many semaphores"); /* ERROR_TOO_MANY_SEMAPHORES */ + s_ErrorMessage.Add(101, "Exclusive semaphore already owned"); /* ERROR_EXCL_SEM_ALREADY_OWNED */ + s_ErrorMessage.Add(102, "Semaphore is set"); /* ERROR_SEM_IS_SET */ + s_ErrorMessage.Add(103, "Too many semaphore requests"); /* ERROR_TOO_MANY_SEM_REQUESTS */ + s_ErrorMessage.Add(104, "Invalid at interrupt time"); /* ERROR_INVALID_AT_INTERRUPT_TIME */ + s_ErrorMessage.Add(105, "Semaphore owner died"); /* ERROR_SEM_OWNER_DIED */ + s_ErrorMessage.Add(106, "Semaphore user limit"); /* ERROR_SEM_USER_LIMIT */ + s_ErrorMessage.Add(107, "Disk change"); /* ERROR_DISK_CHANGE */ + s_ErrorMessage.Add(108, "Drive locked"); /* ERROR_DRIVE_LOCKED */ + s_ErrorMessage.Add(109, "Broken pipe"); /* ERROR_BROKEN_PIPE */ + s_ErrorMessage.Add(110, "Open failed"); /* ERROR_OPEN_FAILED */ + s_ErrorMessage.Add(111, "Buffer overflow"); /* ERROR_BUFFER_OVERFLOW */ + s_ErrorMessage.Add(112, "Disk full"); /* ERROR_DISK_FULL */ + s_ErrorMessage.Add(113, "No more search handles"); /* ERROR_NO_MORE_SEARCH_HANDLES */ + s_ErrorMessage.Add(114, "Invalid target handle"); /* ERROR_INVALID_TARGET_HANDLE */ + s_ErrorMessage.Add(117, "Invalid category"); /* ERROR_INVALID_CATEGORY */ + s_ErrorMessage.Add(118, "Invalid verify switch"); /* ERROR_INVALID_VERIFY_SWITCH */ + s_ErrorMessage.Add(119, "Bad driver level"); /* ERROR_BAD_DRIVER_LEVEL */ + s_ErrorMessage.Add(121, "Semaphore timeout"); /* ERROR_SEM_TIMEOUT */ + s_ErrorMessage.Add(122, "Insufficient buffer"); /* ERROR_INSUFFICIENT_BUFFER */ + s_ErrorMessage.Add(124, "Invalid level"); /* ERROR_INVALID_LEVEL */ + s_ErrorMessage.Add(125, "No volume label"); /* ERROR_NO_VOLUME_LABEL */ + s_ErrorMessage.Add(126, "Module not found"); /* ERROR_MOD_NOT_FOUND */ + s_ErrorMessage.Add(128, "Wait no children"); /* ERROR_WAIT_NO_CHILDREN */ + s_ErrorMessage.Add(129, "Child not complete"); /* ERROR_CHILD_NOT_COMPLETE */ + s_ErrorMessage.Add(130, "Direct access handle"); /* ERROR_DIRECT_ACCESS_HANDLE */ + s_ErrorMessage.Add(131, "Negative seek"); /* ERROR_NEGATIVE_SEEK */ + s_ErrorMessage.Add(132, "Seek on device"); /* ERROR_SEEK_ON_DEVICE */ + s_ErrorMessage.Add(133, "Is join target"); /* ERROR_IS_JOIN_TARGET */ + s_ErrorMessage.Add(134, "Is joined"); /* ERROR_IS_JOINED */ + s_ErrorMessage.Add(135, "Is substed"); /* ERROR_IS_SUBSTED */ + s_ErrorMessage.Add(136, "Not joined"); /* ERROR_NOT_JOINED */ + s_ErrorMessage.Add(137, "Not substed"); /* ERROR_NOT_SUBSTED */ + s_ErrorMessage.Add(138, "Join to join"); /* ERROR_JOIN_TO_JOIN */ + s_ErrorMessage.Add(139, "Subst to subst"); /* ERROR_SUBST_TO_SUBST */ + s_ErrorMessage.Add(140, "Join to subst"); /* ERROR_JOIN_TO_SUBST */ + s_ErrorMessage.Add(141, "Subst to join"); /* ERROR_SUBST_TO_JOIN */ + s_ErrorMessage.Add(142, "Busy drive"); /* ERROR_BUSY_DRIVE */ + s_ErrorMessage.Add(143, "Same drive"); /* ERROR_SAME_DRIVE */ + s_ErrorMessage.Add(144, "Directory not root"); /* ERROR_DIR_NOT_ROOT */ + s_ErrorMessage.Add(145, "Directory not empty"); /* ERROR_DIR_NOT_EMPTY */ + s_ErrorMessage.Add(146, "Is subst path"); /* ERROR_IS_SUBST_PATH */ + s_ErrorMessage.Add(147, "Is join path"); /* ERROR_IS_JOIN_PATH */ + s_ErrorMessage.Add(148, "Path busy"); /* ERROR_PATH_BUSY */ + s_ErrorMessage.Add(149, "Is subst target"); /* ERROR_IS_SUBST_TARGET */ + s_ErrorMessage.Add(150, "System trace"); /* ERROR_SYSTEM_TRACE */ + s_ErrorMessage.Add(151, "Invalid event count"); /* ERROR_INVALID_EVENT_COUNT */ + s_ErrorMessage.Add(152, "Too many muxwaiters"); /* ERROR_TOO_MANY_MUXWAITERS */ + s_ErrorMessage.Add(153, "Invalid list format"); /* ERROR_INVALID_LIST_FORMAT */ + s_ErrorMessage.Add(154, "Label too long"); /* ERROR_LABEL_TOO_LONG */ + s_ErrorMessage.Add(155, "Too many TCBs"); /* ERROR_TOO_MANY_TCBS */ + s_ErrorMessage.Add(156, "Signal refused"); /* ERROR_SIGNAL_REFUSED */ + s_ErrorMessage.Add(157, "Discarded"); /* ERROR_DISCARDED */ + s_ErrorMessage.Add(158, "Not locked"); /* ERROR_NOT_LOCKED */ + s_ErrorMessage.Add(159, "Bad thread ID addr"); /* ERROR_BAD_THREADID_ADDR */ + s_ErrorMessage.Add(160, "Bad arguments"); /* ERROR_BAD_ARGUMENTS */ + s_ErrorMessage.Add(161, "Bad pathname"); /* ERROR_BAD_PATHNAME */ + s_ErrorMessage.Add(162, "Signal pending"); /* ERROR_SIGNAL_PENDING */ + s_ErrorMessage.Add(164, "Max thrds reached"); /* ERROR_MAX_THRDS_REACHED */ + s_ErrorMessage.Add(167, "Lock failed"); /* ERROR_LOCK_FAILED */ + s_ErrorMessage.Add(170, "Busy"); /* ERROR_BUSY */ + s_ErrorMessage.Add(173, "Cancel violation"); /* ERROR_CANCEL_VIOLATION */ + s_ErrorMessage.Add(174, "Atomic locks not supported"); /* ERROR_ATOMIC_LOCKS_NOT_SUPPORTED */ + s_ErrorMessage.Add(180, "Invalid segment number"); /* ERROR_INVALID_SEGMENT_NUMBER */ + s_ErrorMessage.Add(182, "Invalid ordinal"); /* ERROR_INVALID_ORDINAL */ + s_ErrorMessage.Add(186, "Invalid flag number"); /* ERROR_INVALID_FLAG_NUMBER */ + s_ErrorMessage.Add(187, "Sem not found"); /* ERROR_SEM_NOT_FOUND */ + s_ErrorMessage.Add(188, "Invalid starting codeseg"); /* ERROR_INVALID_STARTING_CODESEG */ + s_ErrorMessage.Add(189, "Invalid stackseg"); /* ERROR_INVALID_STACKSEG */ + s_ErrorMessage.Add(190, "Invalid moduletype"); /* ERROR_INVALID_MODULETYPE */ + s_ErrorMessage.Add(191, "Invalid exe signature"); /* ERROR_INVALID_EXE_SIGNATURE */ + s_ErrorMessage.Add(192, "Exe marked invalid"); /* ERROR_EXE_MARKED_INVALID */ + s_ErrorMessage.Add(193, "Bad exe format"); /* ERROR_BAD_EXE_FORMAT */ + s_ErrorMessage.Add(194, "Iterated data exceeds 64k (and that should be enough for anybody!)"); /* ERROR_ITERATED_DATA_EXCEEDS_64k */ + s_ErrorMessage.Add(195, "Invalid minallocsize"); /* ERROR_INVALID_MINALLOCSIZE */ + s_ErrorMessage.Add(196, "Dynlink from invalid ring"); /* ERROR_DYNLINK_FROM_INVALID_RING */ + s_ErrorMessage.Add(197, "IOPL not enabled"); /* ERROR_IOPL_NOT_ENABLED */ + s_ErrorMessage.Add(198, "Invalid segdpl"); /* ERROR_INVALID_SEGDPL */ + s_ErrorMessage.Add(199, "Autodataseg exceeds 64k"); /* ERROR_AUTODATASEG_EXCEEDS_64k */ + s_ErrorMessage.Add(200, "Ring2seg must be movable"); /* ERROR_RING2SEG_MUST_BE_MOVABLE */ + s_ErrorMessage.Add(201, "Reloc chain exceeds seglim"); /* ERROR_RELOC_CHAIN_XEEDS_SEGLIM */ + s_ErrorMessage.Add(202, "Infloop in reloc chain"); /* ERROR_INFLOOP_IN_RELOC_CHAIN */ + s_ErrorMessage.Add(203, "Env var not found"); /* ERROR_ENVVAR_NOT_FOUND */ + s_ErrorMessage.Add(205, "No signal sent"); /* ERROR_NO_SIGNAL_SENT */ + s_ErrorMessage.Add(206, "Filename exceeds range"); /* ERROR_FILENAME_EXCED_RANGE */ + s_ErrorMessage.Add(207, "Ring2 stack in use"); /* ERROR_RING2_STACK_IN_USE */ + s_ErrorMessage.Add(208, "Meta expansion too long"); /* ERROR_META_EXPANSION_TOO_LONG */ + s_ErrorMessage.Add(209, "Invalid signal number"); /* ERROR_INVALID_SIGNAL_NUMBER */ + s_ErrorMessage.Add(210, "Thread 1 inactive"); /* ERROR_THREAD_1_INACTIVE */ + s_ErrorMessage.Add(212, "Locked"); /* ERROR_LOCKED */ + s_ErrorMessage.Add(214, "Too many modules"); /* ERROR_TOO_MANY_MODULES */ + s_ErrorMessage.Add(215, "Nesting not allowed"); /* ERROR_NESTING_NOT_ALLOWED */ + s_ErrorMessage.Add(216, "Exe machine type mismatch"); /* ERROR_EXE_MACHINE_TYPE_MISMATCH */ + s_ErrorMessage.Add(230, "Bad pipe"); /* ERROR_BAD_PIPE */ + s_ErrorMessage.Add(231, "Pipe busy"); /* ERROR_PIPE_BUSY */ + s_ErrorMessage.Add(232, "No data"); /* ERROR_NO_DATA */ + s_ErrorMessage.Add(233, "Pipe not connected"); /* ERROR_PIPE_NOT_CONNECTED */ + s_ErrorMessage.Add(234, "More data"); /* ERROR_MORE_DATA */ + s_ErrorMessage.Add(240, "VC disconnected"); /* ERROR_VC_DISCONNECTED */ + s_ErrorMessage.Add(254, "Invalid EA name"); /* ERROR_INVALID_EA_NAME */ + s_ErrorMessage.Add(255, "EA list inconsistent"); /* ERROR_EA_LIST_INCONSISTENT */ + s_ErrorMessage.Add(258, "Wait timeout"); /* WAIT_TIMEOUT */ + s_ErrorMessage.Add(259, "No more items"); /* ERROR_NO_MORE_ITEMS */ + s_ErrorMessage.Add(266, "Cannot copy"); /* ERROR_CANNOT_COPY */ + s_ErrorMessage.Add(275, "EAS didnt fit"); /* ERROR_EAS_DIDNT_FIT */ + s_ErrorMessage.Add(276, "EA file corrupt"); /* ERROR_EA_FILE_CORRUPT */ + s_ErrorMessage.Add(277, "EA table full"); /* ERROR_EA_TABLE_FULL */ + s_ErrorMessage.Add(278, "Invalid EA handle"); /* ERROR_INVALID_EA_HANDLE */ + s_ErrorMessage.Add(282, "EAs not supported"); /* ERROR_EAS_NOT_SUPPORTED */ + s_ErrorMessage.Add(288, "Not owner"); /* ERROR_NOT_OWNER */ + s_ErrorMessage.Add(298, "Too many posts"); /* ERROR_TOO_MANY_POSTS */ + s_ErrorMessage.Add(299, "Partial copy"); /* ERROR_PARTIAL_COPY */ + s_ErrorMessage.Add(300, "Oplock not granted"); /* ERROR_OPLOCK_NOT_GRANTED */ + s_ErrorMessage.Add(301, "Invalid oplock protocol"); /* ERROR_INVALID_OPLOCK_PROTOCOL */ + s_ErrorMessage.Add(302, "Disk too fragmented"); /* ERROR_DISK_TOO_FRAGMENTED */ + s_ErrorMessage.Add(303, "Delete pending"); /* ERROR_DELETE_PENDING */ + s_ErrorMessage.Add(317, "Mr Mid not found"); /* ERROR_MR_MID_NOT_FOUND */ + s_ErrorMessage.Add(487, "Invalid address"); /* ERROR_INVALID_ADDRESS */ + s_ErrorMessage.Add(534, "Arithmetic overflow"); /* ERROR_ARITHMETIC_OVERFLOW */ + s_ErrorMessage.Add(535, "Pipe connected"); /* ERROR_PIPE_CONNECTED */ + s_ErrorMessage.Add(536, "Pipe listening"); /* ERROR_PIPE_LISTENING */ + s_ErrorMessage.Add(994, "EA access denied"); /* ERROR_EA_ACCESS_DENIED */ + s_ErrorMessage.Add(996, "IO incomplete"); /* ERROR_IO_INCOMPLETE */ + s_ErrorMessage.Add(997, "IO pending"); /* ERROR_IO_PENDING */ + s_ErrorMessage.Add(998, "No access"); /* ERROR_NOACCESS */ + s_ErrorMessage.Add(999, "Swap error"); /* ERROR_SWAPERROR */ + s_ErrorMessage.Add(1001, "Stack overflow"); /* ERROR_STACK_OVERFLOW */ + s_ErrorMessage.Add(1002, "Invalid message"); /* ERROR_INVALID_MESSAGE */ + s_ErrorMessage.Add(1003, "Can not complete"); /* ERROR_CAN_NOT_COMPLETE */ + s_ErrorMessage.Add(1004, "Invalid flags"); /* ERROR_INVALID_FLAGS */ + s_ErrorMessage.Add(1005, "Unrecognised volume"); /* ERROR_UNRECOGNIZED_VOLUME */ + s_ErrorMessage.Add(1006, "File invalid"); /* ERROR_FILE_INVALID */ + s_ErrorMessage.Add(1007, "Full screen mode"); /* ERROR_FULLSCREEN_MODE */ + s_ErrorMessage.Add(1008, "No token"); /* ERROR_NO_TOKEN */ + s_ErrorMessage.Add(1009, "Bad DB"); /* ERROR_BADDB */ + s_ErrorMessage.Add(1010, "Bad key"); /* ERROR_BADKEY */ + s_ErrorMessage.Add(1011, "Can't open"); /* ERROR_CANTOPEN */ + s_ErrorMessage.Add(1012, "Can't read"); /* ERROR_CANTREAD */ + s_ErrorMessage.Add(1013, "Can't write"); /* ERROR_CANTWRITE */ + s_ErrorMessage.Add(1014, "Registry recovered"); /* ERROR_REGISTRY_RECOVERED */ + s_ErrorMessage.Add(1015, "Registry corrupt"); /* ERROR_REGISTRY_CORRUPT */ + s_ErrorMessage.Add(1016, "Registry IO failed"); /* ERROR_REGISTRY_IO_FAILED */ + s_ErrorMessage.Add(1017, "Not registry file"); /* ERROR_NOT_REGISTRY_FILE */ + s_ErrorMessage.Add(1018, "Key deleted"); /* ERROR_KEY_DELETED */ + s_ErrorMessage.Add(1019, "No log space"); /* ERROR_NO_LOG_SPACE */ + s_ErrorMessage.Add(1020, "Key has children"); /* ERROR_KEY_HAS_CHILDREN */ + s_ErrorMessage.Add(1021, "Child must be volatile"); /* ERROR_CHILD_MUST_BE_VOLATILE */ + s_ErrorMessage.Add(1022, "Notify enum dir"); /* ERROR_NOTIFY_ENUM_DIR */ + s_ErrorMessage.Add(1051, "Dependent services running"); /* ERROR_DEPENDENT_SERVICES_RUNNING */ + s_ErrorMessage.Add(1052, "Invalid service control"); /* ERROR_INVALID_SERVICE_CONTROL */ + s_ErrorMessage.Add(1053, "Service request timeout"); /* ERROR_SERVICE_REQUEST_TIMEOUT */ + s_ErrorMessage.Add(1054, "Service no thread"); /* ERROR_SERVICE_NO_THREAD */ + s_ErrorMessage.Add(1055, "Service database locked"); /* ERROR_SERVICE_DATABASE_LOCKED */ + s_ErrorMessage.Add(1056, "Service already running"); /* ERROR_SERVICE_ALREADY_RUNNING */ + s_ErrorMessage.Add(1057, "Invalid service account"); /* ERROR_INVALID_SERVICE_ACCOUNT */ + s_ErrorMessage.Add(1058, "Service disabled"); /* ERROR_SERVICE_DISABLED */ + s_ErrorMessage.Add(1059, "Circular dependency"); /* ERROR_CIRCULAR_DEPENDENCY */ + s_ErrorMessage.Add(1060, "Service does not exist"); /* ERROR_SERVICE_DOES_NOT_EXIST */ + s_ErrorMessage.Add(1061, "Service cannot accept ctrl"); /* ERROR_SERVICE_CANNOT_ACCEPT_CTRL */ + s_ErrorMessage.Add(1062, "Service not active"); /* ERROR_SERVICE_NOT_ACTIVE */ + s_ErrorMessage.Add(1063, "Failed service controller connect"); /* ERROR_FAILED_SERVICE_CONTROLLER_CONNECT */ + s_ErrorMessage.Add(1064, "Exception in service"); /* ERROR_EXCEPTION_IN_SERVICE */ + s_ErrorMessage.Add(1065, "Database does not exist"); /* ERROR_DATABASE_DOES_NOT_EXIST */ + s_ErrorMessage.Add(1066, "Service specific error"); /* ERROR_SERVICE_SPECIFIC_ERROR */ + s_ErrorMessage.Add(1067, "Process aborted"); /* ERROR_PROCESS_ABORTED */ + s_ErrorMessage.Add(1068, "Service dependency fail"); /* ERROR_SERVICE_DEPENDENCY_FAIL */ + s_ErrorMessage.Add(1069, "Service logon failed"); /* ERROR_SERVICE_LOGON_FAILED */ + s_ErrorMessage.Add(1070, "Service start hang"); /* ERROR_SERVICE_START_HANG */ + s_ErrorMessage.Add(1071, "Invalid service lock"); /* ERROR_INVALID_SERVICE_LOCK */ + s_ErrorMessage.Add(1072, "Service marked for delete"); /* ERROR_SERVICE_MARKED_FOR_DELETE */ + s_ErrorMessage.Add(1073, "Service exists"); /* ERROR_SERVICE_EXISTS */ + s_ErrorMessage.Add(1074, "Already running lkg"); /* ERROR_ALREADY_RUNNING_LKG */ + s_ErrorMessage.Add(1075, "Service dependency deleted"); /* ERROR_SERVICE_DEPENDENCY_DELETED */ + s_ErrorMessage.Add(1076, "Boot already accepted"); /* ERROR_BOOT_ALREADY_ACCEPTED */ + s_ErrorMessage.Add(1077, "Service never started"); /* ERROR_SERVICE_NEVER_STARTED */ + s_ErrorMessage.Add(1078, "Duplicate service name"); /* ERROR_DUPLICATE_SERVICE_NAME */ + s_ErrorMessage.Add(1079, "Different service account"); /* ERROR_DIFFERENT_SERVICE_ACCOUNT */ + s_ErrorMessage.Add(1080, "Cannot detect driver failure"); /* ERROR_CANNOT_DETECT_DRIVER_FAILURE */ + s_ErrorMessage.Add(1081, "Cannot detect process abort"); /* ERROR_CANNOT_DETECT_PROCESS_ABORT */ + s_ErrorMessage.Add(1082, "No recovery program"); /* ERROR_NO_RECOVERY_PROGRAM */ + s_ErrorMessage.Add(1083, "Service not in exe"); /* ERROR_SERVICE_NOT_IN_EXE */ + s_ErrorMessage.Add(1084, "Not safeboot service"); /* ERROR_NOT_SAFEBOOT_SERVICE */ + s_ErrorMessage.Add(1100, "End of media"); /* ERROR_END_OF_MEDIA */ + s_ErrorMessage.Add(1101, "Filemark detected"); /* ERROR_FILEMARK_DETECTED */ + s_ErrorMessage.Add(1102, "Beginning of media"); /* ERROR_BEGINNING_OF_MEDIA */ + s_ErrorMessage.Add(1103, "Setmark detected"); /* ERROR_SETMARK_DETECTED */ + s_ErrorMessage.Add(1104, "No data detected"); /* ERROR_NO_DATA_DETECTED */ + s_ErrorMessage.Add(1105, "Partition failure"); /* ERROR_PARTITION_FAILURE */ + s_ErrorMessage.Add(1106, "Invalid block length"); /* ERROR_INVALID_BLOCK_LENGTH */ + s_ErrorMessage.Add(1107, "Device not partitioned"); /* ERROR_DEVICE_NOT_PARTITIONED */ + s_ErrorMessage.Add(1108, "Unable to lock media"); /* ERROR_UNABLE_TO_LOCK_MEDIA */ + s_ErrorMessage.Add(1109, "Unable to unload media"); /* ERROR_UNABLE_TO_UNLOAD_MEDIA */ + s_ErrorMessage.Add(1110, "Media changed"); /* ERROR_MEDIA_CHANGED */ + s_ErrorMessage.Add(1111, "Bus reset"); /* ERROR_BUS_RESET */ + s_ErrorMessage.Add(1112, "No media in drive"); /* ERROR_NO_MEDIA_IN_DRIVE */ + s_ErrorMessage.Add(1113, "No unicode translation"); /* ERROR_NO_UNICODE_TRANSLATION */ + s_ErrorMessage.Add(1114, "DLL init failed"); /* ERROR_DLL_INIT_FAILED */ + s_ErrorMessage.Add(1115, "Shutdown in progress"); /* ERROR_SHUTDOWN_IN_PROGRESS */ + s_ErrorMessage.Add(1116, "No shutdown in progress"); /* ERROR_NO_SHUTDOWN_IN_PROGRESS */ + s_ErrorMessage.Add(1117, "IO device"); /* ERROR_IO_DEVICE */ + s_ErrorMessage.Add(1118, "Serial IO device"); /* ERROR_SERIAL_NO_DEVICE */ + s_ErrorMessage.Add(1119, "IRQ busy"); /* ERROR_IRQ_BUSY */ + s_ErrorMessage.Add(1120, "More writes"); /* ERROR_MORE_WRITES */ + s_ErrorMessage.Add(1121, "Counter timeout"); /* ERROR_COUNTER_TIMEOUT */ + s_ErrorMessage.Add(1122, "Floppy ID mark not found"); /* ERROR_FLOPPY_ID_MARK_NOT_FOUND */ + s_ErrorMessage.Add(1123, "Floppy wrong cylinder"); /* ERROR_FLOPPY_WRONG_CYLINDER */ + s_ErrorMessage.Add(1124, "Floppy unknown error"); /* ERROR_FLOPPY_UNKNOWN_ERROR */ + s_ErrorMessage.Add(1125, "Floppy bad registers"); /* ERROR_FLOPPY_BAD_REGISTERS */ + s_ErrorMessage.Add(1126, "Disk recalibrate failed"); /* ERROR_DISK_RECALIBRATE_FAILED */ + s_ErrorMessage.Add(1127, "Disk operation failed"); /* ERROR_DISK_OPERATION_FAILED */ + s_ErrorMessage.Add(1128, "Disk reset failed"); /* ERROR_DISK_RESET_FAILED */ + s_ErrorMessage.Add(1129, "EOM overflow"); /* ERROR_EOM_OVERFLOW */ + s_ErrorMessage.Add(1130, "Not enough server memory"); /* ERROR_NOT_ENOUGH_SERVER_MEMORY */ + s_ErrorMessage.Add(1131, "Possible deadlock"); /* ERROR_POSSIBLE_DEADLOCK */ + s_ErrorMessage.Add(1132, "Mapped alignment"); /* ERROR_MAPPED_ALIGNMENT */ + s_ErrorMessage.Add(1140, "Set power state vetoed"); /* ERROR_SET_POWER_STATE_VETOED */ + s_ErrorMessage.Add(1141, "Set power state failed"); /* ERROR_SET_POWER_STATE_FAILED */ + s_ErrorMessage.Add(1142, "Too many links"); /* ERROR_TOO_MANY_LINKS */ + s_ErrorMessage.Add(1150, "Old win version"); /* ERROR_OLD_WIN_VERSION */ + s_ErrorMessage.Add(1151, "App wrong OS"); /* ERROR_APP_WRONG_OS */ + s_ErrorMessage.Add(1152, "Single instance app"); /* ERROR_SINGLE_INSTANCE_APP */ + s_ErrorMessage.Add(1153, "Rmode app"); /* ERROR_RMODE_APP */ + s_ErrorMessage.Add(1154, "Invalid DLL"); /* ERROR_INVALID_DLL */ + s_ErrorMessage.Add(1155, "No association"); /* ERROR_NO_ASSOCIATION */ + s_ErrorMessage.Add(1156, "DDE fail"); /* ERROR_DDE_FAIL */ + s_ErrorMessage.Add(1157, "DLL not found"); /* ERROR_DLL_NOT_FOUND */ + s_ErrorMessage.Add(1158, "No more user handles"); /* ERROR_NO_MORE_USER_HANDLES */ + s_ErrorMessage.Add(1159, "Message sync only"); /* ERROR_MESSAGE_SYNC_ONLY */ + s_ErrorMessage.Add(1160, "Source element empty"); /* ERROR_SOURCE_ELEMENT_EMPTY */ + s_ErrorMessage.Add(1161, "Destination element full"); /* ERROR_DESTINATION_ELEMENT_FULL */ + s_ErrorMessage.Add(1162, "Illegal element address"); /* ERROR_ILLEGAL_ELEMENT_ADDRESS */ + s_ErrorMessage.Add(1163, "Magazine not present"); /* ERROR_MAGAZINE_NOT_PRESENT */ + s_ErrorMessage.Add(1164, "Device reinitialization needed"); /* ERROR_DEVICE_REINITIALIZATION_NEEDED */ + s_ErrorMessage.Add(1165, "Device requires cleaning"); /* ERROR_DEVICE_REQUIRES_CLEANING */ + s_ErrorMessage.Add(1166, "Device door open"); /* ERROR_DEVICE_DOOR_OPEN */ + s_ErrorMessage.Add(1167, "Device not connected"); /* ERROR_DEVICE_NOT_CONNECTED */ + s_ErrorMessage.Add(1168, "Not found"); /* ERROR_NOT_FOUND */ + s_ErrorMessage.Add(1169, "No match"); /* ERROR_NO_MATCH */ + s_ErrorMessage.Add(1170, "Set not found"); /* ERROR_SET_NOT_FOUND */ + s_ErrorMessage.Add(1171, "Point not found"); /* ERROR_POINT_NOT_FOUND */ + s_ErrorMessage.Add(1172, "No tracking service"); /* ERROR_NO_TRACKING_SERVICE */ + s_ErrorMessage.Add(1173, "No volume ID"); /* ERROR_NO_VOLUME_ID */ + s_ErrorMessage.Add(1175, "Unable to remove replaced"); /* ERROR_UNABLE_TO_REMOVE_REPLACED */ + s_ErrorMessage.Add(1176, "Unable to move replacement"); /* ERROR_UNABLE_TO_MOVE_REPLACEMENT */ + s_ErrorMessage.Add(1177, "Unable to move replacement 2"); /* ERROR_UNABLE_TO_MOVE_REPLACEMENT_2 */ + s_ErrorMessage.Add(1178, "Journal delete in progress"); /* ERROR_JOURNAL_DELETE_IN_PROGRESS */ + s_ErrorMessage.Add(1179, "Journal not active"); /* ERROR_JOURNAL_NOT_ACTIVE */ + s_ErrorMessage.Add(1180, "Potential file found"); /* ERROR_POTENTIAL_FILE_FOUND */ + s_ErrorMessage.Add(1181, "Journal entry deleted"); /* ERROR_JOURNAL_ENTRY_DELETED */ + s_ErrorMessage.Add(1200, "Bad device"); /* ERROR_BAD_DEVICE */ + s_ErrorMessage.Add(1201, "Connection unavail"); /* ERROR_CONNECTION_UNAVAIL */ + s_ErrorMessage.Add(1202, "Device already remembered"); /* ERROR_DEVICE_ALREADY_REMEMBERED */ + s_ErrorMessage.Add(1203, "No net or bad path"); /* ERROR_NO_NET_OR_BAD_PATH */ + s_ErrorMessage.Add(1204, "Bad provider"); /* ERROR_BAD_PROVIDER */ + s_ErrorMessage.Add(1205, "Cannot open profile"); /* ERROR_CANNOT_OPEN_PROFILE */ + s_ErrorMessage.Add(1206, "Bad profile"); /* ERROR_BAD_PROFILE */ + s_ErrorMessage.Add(1207, "Not container"); /* ERROR_NOT_CONTAINER */ + s_ErrorMessage.Add(1208, "Extended error"); /* ERROR_EXTENDED_ERROR */ + s_ErrorMessage.Add(1209, "Invalid group name"); /* ERROR_INVALID_GROUPNAME */ + s_ErrorMessage.Add(1210, "Invalid computer name"); /* ERROR_INVALID_COMPUTERNAME */ + s_ErrorMessage.Add(1211, "Invalid event name"); /* ERROR_INVALID_EVENTNAME */ + s_ErrorMessage.Add(1212, "Invalid domain name"); /* ERROR_INVALID_DOMAINNAME */ + s_ErrorMessage.Add(1213, "Invalid service name"); /* ERROR_INVALID_SERVICENAME */ + s_ErrorMessage.Add(1214, "Invalid net name"); /* ERROR_INVALID_NETNAME */ + s_ErrorMessage.Add(1215, "Invalid share name"); /* ERROR_INVALID_SHARENAME */ + s_ErrorMessage.Add(1216, "Invalid password name"); /* ERROR_INVALID_PASSWORDNAME */ + s_ErrorMessage.Add(1217, "Invalid message name"); /* ERROR_INVALID_MESSAGENAME */ + s_ErrorMessage.Add(1218, "Invalid message dest"); /* ERROR_INVALID_MESSAGEDEST */ + s_ErrorMessage.Add(1219, "Session credential conflict"); /* ERROR_SESSION_CREDENTIAL_CONFLICT */ + s_ErrorMessage.Add(1220, "Remote session limit exceeded"); /* ERROR_REMOTE_SESSION_LIMIT_EXCEEDED */ + s_ErrorMessage.Add(1221, "Dup domain name"); /* ERROR_DUP_DOMAINNAME */ + s_ErrorMessage.Add(1222, "No network"); /* ERROR_NO_NETWORK */ + s_ErrorMessage.Add(1223, "Cancelled"); /* ERROR_CANCELLED */ + s_ErrorMessage.Add(1224, "User mapped file"); /* ERROR_USER_MAPPED_FILE */ + s_ErrorMessage.Add(1225, "Connection refused"); /* ERROR_CONNECTION_REFUSED */ + s_ErrorMessage.Add(1226, "Graceful disconnect"); /* ERROR_GRACEFUL_DISCONNECT */ + s_ErrorMessage.Add(1227, "Address already associated"); /* ERROR_ADDRESS_ALREADY_ASSOCIATED */ + s_ErrorMessage.Add(1228, "Address not associated"); /* ERROR_ADDRESS_NOT_ASSOCIATED */ + s_ErrorMessage.Add(1229, "Connected invalid"); /* ERROR_CONNECTION_INVALID */ + s_ErrorMessage.Add(1230, "Connection active"); /* ERROR_CONNECTION_ACTIVE */ + s_ErrorMessage.Add(1231, "Network unreachable"); /* ERROR_NETWORK_UNREACHABLE */ + s_ErrorMessage.Add(1232, "Host unreachable"); /* ERROR_HOST_UNREACHABLE */ + s_ErrorMessage.Add(1233, "Protocol unreachable"); /* ERROR_PROTOCOL_UNREACHABLE */ + s_ErrorMessage.Add(1234, "Port unreachable"); /* ERROR_PORT_UNREACHABLE */ + s_ErrorMessage.Add(1235, "Request aborted"); /* ERROR_REQUEST_ABORTED */ + s_ErrorMessage.Add(1236, "Connection aborted"); /* ERROR_CONNECTION_ABORTED */ + s_ErrorMessage.Add(1237, "Retry"); /* ERROR_RETRY */ + s_ErrorMessage.Add(1238, "Connection count limit"); /* ERROR_CONNECTION_COUNT_LIMIT */ + s_ErrorMessage.Add(1239, "Login time restriction"); /* ERROR_LOGIN_TIME_RESTRICTION */ + s_ErrorMessage.Add(1240, "Login wksta restriction"); /* ERROR_LOGIN_WKSTA_RESTRICTION */ + s_ErrorMessage.Add(1241, "Incorrect address"); /* ERROR_INCORRECT_ADDRESS */ + s_ErrorMessage.Add(1242, "Already registered"); /* ERROR_ALREADY_REGISTERED */ + s_ErrorMessage.Add(1243, "Service not found"); /* ERROR_SERVICE_NOT_FOUND */ + s_ErrorMessage.Add(1244, "Not authenticated"); /* ERROR_NOT_AUTHENTICATED */ + s_ErrorMessage.Add(1245, "Not logged on"); /* ERROR_NOT_LOGGED_ON */ + s_ErrorMessage.Add(1246, "Continue"); /* ERROR_CONTINUE */ + s_ErrorMessage.Add(1247, "Already initialised"); /* ERROR_ALREADY_INITIALIZED */ + s_ErrorMessage.Add(1248, "No more devices"); /* ERROR_NO_MORE_DEVICES */ + s_ErrorMessage.Add(1249, "No such site"); /* ERROR_NO_SUCH_SITE */ + s_ErrorMessage.Add(1250, "Domain controller exists"); /* ERROR_DOMAIN_CONTROLLER_EXISTS */ + s_ErrorMessage.Add(1251, "Only if connected"); /* ERROR_ONLY_IF_CONNECTED */ + s_ErrorMessage.Add(1252, "Override no changes"); /* ERROR_OVERRIDE_NOCHANGES */ + s_ErrorMessage.Add(1253, "Bad user profile"); /* ERROR_BAD_USER_PROFILE */ + s_ErrorMessage.Add(1254, "Not supported on SBS"); /* ERROR_NOT_SUPPORTED_ON_SBS */ + s_ErrorMessage.Add(1255, "Server shutdown in progress"); /* ERROR_SERVER_SHUTDOWN_IN_PROGRESS */ + s_ErrorMessage.Add(1256, "Host down"); /* ERROR_HOST_DOWN */ + s_ErrorMessage.Add(1257, "Non account sid"); /* ERROR_NON_ACCOUNT_SID */ + s_ErrorMessage.Add(1258, "Non domain sid"); /* ERROR_NON_DOMAIN_SID */ + s_ErrorMessage.Add(1259, "Apphelp block"); /* ERROR_APPHELP_BLOCK */ + s_ErrorMessage.Add(1260, "Access disabled by policy"); /* ERROR_ACCESS_DISABLED_BY_POLICY */ + s_ErrorMessage.Add(1261, "Reg nat consumption"); /* ERROR_REG_NAT_CONSUMPTION */ + s_ErrorMessage.Add(1262, "CSC share offline"); /* ERROR_CSCSHARE_OFFLINE */ + s_ErrorMessage.Add(1263, "PK init failure"); /* ERROR_PKINIT_FAILURE */ + s_ErrorMessage.Add(1264, "Smartcard subsystem failure"); /* ERROR_SMARTCARD_SUBSYSTEM_FAILURE */ + s_ErrorMessage.Add(1265, "Downgrade detected"); /* ERROR_DOWNGRADE_DETECTED */ + s_ErrorMessage.Add(1266, "Smartcard cert revoked"); /* SEC_E_SMARTCARD_CERT_REVOKED */ + s_ErrorMessage.Add(1267, "Issuing CA untrusted"); /* SEC_E_ISSUING_CA_UNTRUSTED */ + s_ErrorMessage.Add(1268, "Revocation offline"); /* SEC_E_REVOCATION_OFFLINE_C */ + s_ErrorMessage.Add(1269, "PK init client failure"); /* SEC_E_PKINIT_CLIENT_FAILUR */ + s_ErrorMessage.Add(1270, "Smartcard cert expired"); /* SEC_E_SMARTCARD_CERT_EXPIRED */ + s_ErrorMessage.Add(1271, "Machine locked"); /* ERROR_MACHINE_LOCKED */ + s_ErrorMessage.Add(1273, "Callback supplied invalid data"); /* ERROR_CALLBACK_SUPPLIED_INVALID_DATA */ + s_ErrorMessage.Add(1274, "Sync foreground refresh required"); /* ERROR_SYNC_FOREGROUND_REFRESH_REQUIRED */ + s_ErrorMessage.Add(1275, "Driver blocked"); /* ERROR_DRIVER_BLOCKED */ + s_ErrorMessage.Add(1276, "Invalid import of non DLL"); /* ERROR_INVALID_IMPORT_OF_NON_DLL */ + s_ErrorMessage.Add(1300, "Not all assigned"); /* ERROR_NOT_ALL_ASSIGNED */ + s_ErrorMessage.Add(1301, "Some not mapped"); /* ERROR_SOME_NOT_MAPPED */ + s_ErrorMessage.Add(1302, "No quotas for account"); /* ERROR_NO_QUOTAS_FOR_ACCOUNT */ + s_ErrorMessage.Add(1303, "Local user session key"); /* ERROR_LOCAL_USER_SESSION_KEY */ + s_ErrorMessage.Add(1304, "Null LM password"); /* ERROR_NULL_LM_PASSWORD */ + s_ErrorMessage.Add(1305, "Unknown revision"); /* ERROR_UNKNOWN_REVISION */ + s_ErrorMessage.Add(1306, "Revision mismatch"); /* ERROR_REVISION_MISMATCH */ + s_ErrorMessage.Add(1307, "Invalid owner"); /* ERROR_INVALID_OWNER */ + s_ErrorMessage.Add(1308, "Invalid primary group"); /* ERROR_INVALID_PRIMARY_GROUP */ + s_ErrorMessage.Add(1309, "No impersonation token"); /* ERROR_NO_IMPERSONATION_TOKEN */ + s_ErrorMessage.Add(1310, "Can't disable mandatory"); /* ERROR_CANT_DISABLE_MANDATORY */ + s_ErrorMessage.Add(1311, "No logon servers"); /* ERROR_NO_LOGON_SERVERS */ + s_ErrorMessage.Add(1312, "No such logon session"); /* ERROR_NO_SUCH_LOGON_SESSION */ + s_ErrorMessage.Add(1313, "No such privilege"); /* ERROR_NO_SUCH_PRIVILEGE */ + s_ErrorMessage.Add(1314, "Privilege not held"); /* ERROR_PRIVILEGE_NOT_HELD */ + s_ErrorMessage.Add(1315, "Invalid account name"); /* ERROR_INVALID_ACCOUNT_NAME */ + s_ErrorMessage.Add(1316, "User exists"); /* ERROR_USER_EXISTS */ + s_ErrorMessage.Add(1317, "No such user"); /* ERROR_NO_SUCH_USER */ + s_ErrorMessage.Add(1318, "Group exists"); /* ERROR_GROUP_EXISTS */ + s_ErrorMessage.Add(1319, "No such group"); /* ERROR_NO_SUCH_GROUP */ + s_ErrorMessage.Add(1320, "Member in group"); /* ERROR_MEMBER_IN_GROUP */ + s_ErrorMessage.Add(1321, "Member not in group"); /* ERROR_MEMBER_NOT_IN_GROUP */ + s_ErrorMessage.Add(1322, "Last admin"); /* ERROR_LAST_ADMIN */ + s_ErrorMessage.Add(1323, "Wrong password"); /* ERROR_WRONG_PASSWORD */ + s_ErrorMessage.Add(1324, "Ill formed password"); /* ERROR_ILL_FORMED_PASSWORD */ + s_ErrorMessage.Add(1325, "Password restriction"); /* ERROR_PASSWORD_RESTRICTION */ + s_ErrorMessage.Add(1326, "Logon failure"); /* ERROR_LOGON_FAILURE */ + s_ErrorMessage.Add(1327, "Account restriction"); /* ERROR_ACCOUNT_RESTRICTION */ + s_ErrorMessage.Add(1328, "Invalid logon hours"); /* ERROR_INVALID_LOGON_HOURS */ + s_ErrorMessage.Add(1329, "Invalid workstation"); /* ERROR_INVALID_WORKSTATION */ + s_ErrorMessage.Add(1330, "Password expired"); /* ERROR_PASSWORD_EXPIRED */ + s_ErrorMessage.Add(1331, "Account disabled"); /* ERROR_ACCOUNT_DISABLED */ + s_ErrorMessage.Add(1332, "None mapped"); /* ERROR_NONE_MAPPED */ + s_ErrorMessage.Add(1333, "Too many LUIDs requested"); /* ERROR_TOO_MANY_LUIDS_REQUESTED */ + s_ErrorMessage.Add(1334, "LUIDs exhausted"); /* ERROR_LUIDS_EXHAUSTED */ + s_ErrorMessage.Add(1335, "Invalid sub authority"); /* ERROR_INVALID_SUB_AUTHORITY */ + s_ErrorMessage.Add(1336, "Invalid ACL"); /* ERROR_INVALID_ACL */ + s_ErrorMessage.Add(1337, "Invalid SID"); /* ERROR_INVALID_SID */ + s_ErrorMessage.Add(1338, "Invalid security descr"); /* ERROR_INVALID_SECURITY_DESCR */ + s_ErrorMessage.Add(1340, "Bad inheritance ACL"); /* ERROR_BAD_INHERITANCE_ACL */ + s_ErrorMessage.Add(1341, "Server disabled"); /* ERROR_SERVER_DISABLED */ + s_ErrorMessage.Add(1342, "Server not disabled"); /* ERROR_SERVER_NOT_DISABLED */ + s_ErrorMessage.Add(1343, "Invalid ID authority"); /* ERROR_INVALID_ID_AUTHORITY */ + s_ErrorMessage.Add(1344, "Allotted space exceeded"); /* ERROR_ALLOTTED_SPACE_EXCEEDED */ + s_ErrorMessage.Add(1345, "Invalid group attributes"); /* ERROR_INVALID_GROUP_ATTRIBUTES */ + s_ErrorMessage.Add(1346, "Bad impersonation level"); /* ERROR_BAD_IMPERSONATION_LEVEL */ + s_ErrorMessage.Add(1347, "Can't open anonymous"); /* ERROR_CANT_OPEN_ANONYMOUS */ + s_ErrorMessage.Add(1348, "Bad validation class"); /* ERROR_BAD_VALIDATION_CLASS */ + s_ErrorMessage.Add(1349, "Bad token type"); /* ERROR_BAD_TOKEN_TYPE */ + s_ErrorMessage.Add(1350, "No security on object"); /* ERROR_NO_SECURITY_ON_OBJECT */ + s_ErrorMessage.Add(1351, "Can't access domain info"); /* ERROR_CANT_ACCESS_DOMAIN_INFO */ + s_ErrorMessage.Add(1352, "Invalid server state"); /* ERROR_INVALID_SERVER_STATE */ + s_ErrorMessage.Add(1353, "Invalid domain state"); /* ERROR_INVALID_DOMAIN_STATE */ + s_ErrorMessage.Add(1354, "Invalid domain role"); /* ERROR_INVALID_DOMAIN_ROLE */ + s_ErrorMessage.Add(1355, "No such domain"); /* ERROR_NO_SUCH_DOMAIN */ + s_ErrorMessage.Add(1356, "Domain exists"); /* ERROR_DOMAIN_EXISTS */ + s_ErrorMessage.Add(1357, "Domain limit exceeded"); /* ERROR_DOMAIN_LIMIT_EXCEEDED */ + s_ErrorMessage.Add(1358, "Internal DB corruption"); /* ERROR_INTERNAL_DB_CORRUPTION */ + s_ErrorMessage.Add(1359, "Internal error"); /* ERROR_INTERNAL_ERROR */ + s_ErrorMessage.Add(1360, "Generic not mapped"); /* ERROR_GENERIC_NOT_MAPPED */ + s_ErrorMessage.Add(1361, "Bad descriptor format"); /* ERROR_BAD_DESCRIPTOR_FORMAT */ + s_ErrorMessage.Add(1362, "Not logon process"); /* ERROR_NOT_LOGON_PROCESS */ + s_ErrorMessage.Add(1363, "Logon session exists"); /* ERROR_LOGON_SESSION_EXISTS */ + s_ErrorMessage.Add(1364, "No such package"); /* ERROR_NO_SUCH_PACKAGE */ + s_ErrorMessage.Add(1365, "Bad logon session state"); /* ERROR_BAD_LOGON_SESSION_STATE */ + s_ErrorMessage.Add(1366, "Logon session collision"); /* ERROR_LOGON_SESSION_COLLISION */ + s_ErrorMessage.Add(1367, "Invalid logon type"); /* ERROR_INVALID_LOGON_TYPE */ + s_ErrorMessage.Add(1368, "Cannot impersonate"); /* ERROR_CANNOT_IMPERSONATE */ + s_ErrorMessage.Add(1369, "Rxact invalid state"); /* ERROR_RXACT_INVALID_STATE */ + s_ErrorMessage.Add(1370, "Rxact commit failure"); /* ERROR_RXACT_COMMIT_FAILURE */ + s_ErrorMessage.Add(1371, "Special account"); /* ERROR_SPECIAL_ACCOUNT */ + s_ErrorMessage.Add(1372, "Special group"); /* ERROR_SPECIAL_GROUP */ + s_ErrorMessage.Add(1373, "Special user"); /* ERROR_SPECIAL_USER */ + s_ErrorMessage.Add(1374, "Members primary group"); /* ERROR_MEMBERS_PRIMARY_GROUP */ + s_ErrorMessage.Add(1375, "Token already in use"); /* ERROR_TOKEN_ALREADY_IN_USE */ + s_ErrorMessage.Add(1376, "No such alias"); /* ERROR_NO_SUCH_ALIAS */ + s_ErrorMessage.Add(1377, "Member not in alias"); /* ERROR_MEMBER_NOT_IN_ALIAS */ + s_ErrorMessage.Add(1378, "Member in alias"); /* ERROR_MEMBER_IN_ALIAS */ + s_ErrorMessage.Add(1379, "Alias exists"); /* ERROR_ALIAS_EXISTS */ + s_ErrorMessage.Add(1380, "Logon not granted"); /* ERROR_LOGON_NOT_GRANTED */ + s_ErrorMessage.Add(1381, "Too many secrets"); /* ERROR_TOO_MANY_SECRETS */ + s_ErrorMessage.Add(1382, "Secret too long"); /* ERROR_SECRET_TOO_LONG */ + s_ErrorMessage.Add(1383, "Internal DB error"); /* ERROR_INTERNAL_DB_ERROR */ + s_ErrorMessage.Add(1384, "Too many context IDs"); /* ERROR_TOO_MANY_CONTEXT_IDS */ + s_ErrorMessage.Add(1385, "Logon type not granted"); /* ERROR_LOGON_TYPE_NOT_GRANTED */ + s_ErrorMessage.Add(1386, "NT cross encryption required"); /* ERROR_NT_CROSS_ENCRYPTION_REQUIRED */ + s_ErrorMessage.Add(1387, "No such member"); /* ERROR_NO_SUCH_MEMBER */ + s_ErrorMessage.Add(1388, "Invalid member"); /* ERROR_INVALID_MEMBER */ + s_ErrorMessage.Add(1389, "Too many SIDs"); /* ERROR_TOO_MANY_SIDS */ + s_ErrorMessage.Add(1390, "LM cross encryption required"); /* ERROR_LM_CROSS_ENCRYPTION_REQUIRED */ + s_ErrorMessage.Add(1391, "No inheritance"); /* ERROR_NO_INHERITANCE */ + s_ErrorMessage.Add(1392, "File corrupt"); /* ERROR_FILE_CORRUPT */ + s_ErrorMessage.Add(1393, "Disk corrupt"); /* ERROR_DISK_CORRUPT */ + s_ErrorMessage.Add(1394, "No user session key"); /* ERROR_NO_USER_SESSION_KEY */ + s_ErrorMessage.Add(1395, "Licence quota exceeded"); /* ERROR_LICENSE_QUOTA_EXCEEDED */ + s_ErrorMessage.Add(1396, "Wrong target name"); /* ERROR_WRONG_TARGET_NAME */ + s_ErrorMessage.Add(1397, "Mutual auth failed"); /* ERROR_MUTUAL_AUTH_FAILED */ + s_ErrorMessage.Add(1398, "Time skew"); /* ERROR_TIME_SKEW */ + s_ErrorMessage.Add(1399, "Current domain not allowed"); /* ERROR_CURRENT_DOMAIN_NOT_ALLOWED */ + s_ErrorMessage.Add(1400, "Invalid window handle"); /* ERROR_INVALID_WINDOW_HANDLE */ + s_ErrorMessage.Add(1401, "Invalid menu handle"); /* ERROR_INVALID_MENU_HANDLE */ + s_ErrorMessage.Add(1402, "Invalid cursor handle"); /* ERROR_INVALID_CURSOR_HANDLE */ + s_ErrorMessage.Add(1403, "Invalid accel handle"); /* ERROR_INVALID_ACCEL_HANDLE */ + s_ErrorMessage.Add(1404, "Invalid hook handle"); /* ERROR_INVALID_HOOK_HANDLE */ + s_ErrorMessage.Add(1405, "Invalid DWP handle"); /* ERROR_INVALID_DWP_HANDLE */ + s_ErrorMessage.Add(1406, "TLW with wschild"); /* ERROR_TLW_WITH_WSCHILD */ + s_ErrorMessage.Add(1407, "Cannot find WND class"); /* ERROR_CANNOT_FIND_WND_CLASS */ + s_ErrorMessage.Add(1408, "Window of other thread"); /* ERROR_WINDOW_OF_OTHER_THREAD */ + s_ErrorMessage.Add(1409, "Hotkey already registered"); /* ERROR_HOTKEY_ALREADY_REGISTERED */ + s_ErrorMessage.Add(1410, "Class already exists"); /* ERROR_CLASS_ALREADY_EXISTS */ + s_ErrorMessage.Add(1411, "Class does not exist"); /* ERROR_CLASS_DOES_NOT_EXIST */ + s_ErrorMessage.Add(1412, "Class has windows"); /* ERROR_CLASS_HAS_WINDOWS */ + s_ErrorMessage.Add(1413, "Invalid index"); /* ERROR_INVALID_INDEX */ + s_ErrorMessage.Add(1414, "Invalid icon handle"); /* ERROR_INVALID_ICON_HANDLE */ + s_ErrorMessage.Add(1415, "Private dialog index"); /* ERROR_PRIVATE_DIALOG_INDEX */ + s_ErrorMessage.Add(1416, "Listbox ID not found"); /* ERROR_LISTBOX_ID_NOT_FOUND */ + s_ErrorMessage.Add(1417, "No wildcard characters"); /* ERROR_NO_WILDCARD_CHARACTERS */ + s_ErrorMessage.Add(1418, "Clipboard not open"); /* ERROR_CLIPBOARD_NOT_OPEN */ + s_ErrorMessage.Add(1419, "Hotkey not registered"); /* ERROR_HOTKEY_NOT_REGISTERED */ + s_ErrorMessage.Add(1420, "Window not dialog"); /* ERROR_WINDOW_NOT_DIALOG */ + s_ErrorMessage.Add(1421, "Control ID not found"); /* ERROR_CONTROL_ID_NOT_FOUND */ + s_ErrorMessage.Add(1422, "Invalid combobox message"); /* ERROR_INVALID_COMBOBOX_MESSAGE */ + s_ErrorMessage.Add(1423, "Window not combobox"); /* ERROR_WINDOW_NOT_COMBOBOX */ + s_ErrorMessage.Add(1424, "Invalid edit height"); /* ERROR_INVALID_EDIT_HEIGHT */ + s_ErrorMessage.Add(1425, "DC not found"); /* ERROR_DC_NOT_FOUND */ + s_ErrorMessage.Add(1426, "Invalid hook filter"); /* ERROR_INVALID_HOOK_FILTER */ + s_ErrorMessage.Add(1427, "Invalid filter proc"); /* ERROR_INVALID_FILTER_PROC */ + s_ErrorMessage.Add(1428, "Hook needs HMOD"); /* ERROR_HOOK_NEEDS_HMOD */ + s_ErrorMessage.Add(1429, "Global only hook"); /* ERROR_GLOBAL_ONLY_HOOK */ + s_ErrorMessage.Add(1430, "Journal hook set"); /* ERROR_JOURNAL_HOOK_SET */ + s_ErrorMessage.Add(1431, "Hook not installed"); /* ERROR_HOOK_NOT_INSTALLED */ + s_ErrorMessage.Add(1432, "Invalid LB message"); /* ERROR_INVALID_LB_MESSAGE */ + s_ErrorMessage.Add(1433, "Setcount on bad LB"); /* ERROR_SETCOUNT_ON_BAD_LB */ + s_ErrorMessage.Add(1434, "LB without tabstops"); /* ERROR_LB_WITHOUT_TABSTOPS */ + s_ErrorMessage.Add(1435, "Destroy object of other thread"); /* ERROR_DESTROY_OBJECT_OF_OTHER_THREAD */ + s_ErrorMessage.Add(1436, "Child window menu"); /* ERROR_CHILD_WINDOW_MENU */ + s_ErrorMessage.Add(1437, "No system menu"); /* ERROR_NO_SYSTEM_MENU */ + s_ErrorMessage.Add(1438, "Invalid msgbox style"); /* ERROR_INVALID_MSGBOX_STYLE */ + s_ErrorMessage.Add(1439, "Invalid SPI value"); /* ERROR_INVALID_SPI_VALUE */ + s_ErrorMessage.Add(1440, "Screen already locked"); /* ERROR_SCREEN_ALREADY_LOCKED */ + s_ErrorMessage.Add(1441, "HWNDs have different parent"); /* ERROR_HWNDS_HAVE_DIFF_PARENT */ + s_ErrorMessage.Add(1442, "Not child window"); /* ERROR_NOT_CHILD_WINDOW */ + s_ErrorMessage.Add(1443, "Invalid GW command"); /* ERROR_INVALID_GW_COMMAND */ + s_ErrorMessage.Add(1444, "Invalid thread ID"); /* ERROR_INVALID_THREAD_ID */ + s_ErrorMessage.Add(1445, "Non MDI child window"); /* ERROR_NON_MDICHILD_WINDOW */ + s_ErrorMessage.Add(1446, "Popup already active"); /* ERROR_POPUP_ALREADY_ACTIVE */ + s_ErrorMessage.Add(1447, "No scrollbars"); /* ERROR_NO_SCROLLBARS */ + s_ErrorMessage.Add(1448, "Invalid scrollbar range"); /* ERROR_INVALID_SCROLLBAR_RANGE */ + s_ErrorMessage.Add(1449, "Invalid showwin command"); /* ERROR_INVALID_SHOWWIN_COMMAND */ + s_ErrorMessage.Add(1450, "No system resources"); /* ERROR_NO_SYSTEM_RESOURCES */ + s_ErrorMessage.Add(1451, "Nonpaged system resources"); /* ERROR_NONPAGED_SYSTEM_RESOURCES */ + s_ErrorMessage.Add(1452, "Paged system resources"); /* ERROR_PAGED_SYSTEM_RESOURCES */ + s_ErrorMessage.Add(1453, "Working set quota"); /* ERROR_WORKING_SET_QUOTA */ + s_ErrorMessage.Add(1454, "Pagefile quota"); /* ERROR_PAGEFILE_QUOTA */ + s_ErrorMessage.Add(1455, "Commitment limit"); /* ERROR_COMMITMENT_LIMIT */ + s_ErrorMessage.Add(1456, "Menu item not found"); /* ERROR_MENU_ITEM_NOT_FOUND */ + s_ErrorMessage.Add(1457, "Invalid keyboard handle"); /* ERROR_INVALID_KEYBOARD_HANDLE */ + s_ErrorMessage.Add(1458, "Hook type not allowed"); /* ERROR_HOOK_TYPE_NOT_ALLOWED */ + s_ErrorMessage.Add(1459, "Requires interactive windowstation"); /* ERROR_REQUIRES_INTERACTIVE_WINDOWSTATION */ + s_ErrorMessage.Add(1460, "Timeout"); /* ERROR_TIMEOUT */ + s_ErrorMessage.Add(1461, "Invalid monitor handle"); /* ERROR_INVALID_MONITOR_HANDLE */ + s_ErrorMessage.Add(1500, "Eventlog file corrupt"); /* ERROR_EVENTLOG_FILE_CORRUPT */ + s_ErrorMessage.Add(1501, "Eventlog can't start"); /* ERROR_EVENTLOG_CANT_START */ + s_ErrorMessage.Add(1502, "Log file full"); /* ERROR_LOG_FILE_FULL */ + s_ErrorMessage.Add(1503, "Eventlog file changed"); /* ERROR_EVENTLOG_FILE_CHANGED */ + s_ErrorMessage.Add(1601, "Install service failure"); /* ERROR_INSTALL_SERVICE_FAILURE */ + s_ErrorMessage.Add(1602, "Install userexit"); /* ERROR_INSTALL_USEREXIT */ + s_ErrorMessage.Add(1603, "Install failure"); /* ERROR_INSTALL_FAILURE */ + s_ErrorMessage.Add(1604, "Install suspend"); /* ERROR_INSTALL_SUSPEND */ + s_ErrorMessage.Add(1605, "Unknown product"); /* ERROR_UNKNOWN_PRODUCT */ + s_ErrorMessage.Add(1606, "Unknown feature"); /* ERROR_UNKNOWN_FEATURE */ + s_ErrorMessage.Add(1607, "Unknown component"); /* ERROR_UNKNOWN_COMPONENT */ + s_ErrorMessage.Add(1608, "Unknown property"); /* ERROR_UNKNOWN_PROPERTY */ + s_ErrorMessage.Add(1609, "Invalid handle state"); /* ERROR_INVALID_HANDLE_STATE */ + s_ErrorMessage.Add(1610, "Bad configuration"); /* ERROR_BAD_CONFIGURATION */ + s_ErrorMessage.Add(1611, "Index absent"); /* ERROR_INDEX_ABSENT */ + s_ErrorMessage.Add(1612, "Install source absent"); /* ERROR_INSTALL_SOURCE_ABSENT */ + s_ErrorMessage.Add(1613, "Install package version"); /* ERROR_INSTALL_PACKAGE_VERSION */ + s_ErrorMessage.Add(1614, "Product uninstalled"); /* ERROR_PRODUCT_UNINSTALLED */ + s_ErrorMessage.Add(1615, "Bad query syntax"); /* ERROR_BAD_QUERY_SYNTAX */ + s_ErrorMessage.Add(1616, "Invalid field"); /* ERROR_INVALID_FIELD */ + s_ErrorMessage.Add(1617, "Device removed"); /* ERROR_DEVICE_REMOVED */ + s_ErrorMessage.Add(1618, "Install already running"); /* ERROR_INSTALL_ALREADY_RUNNING */ + s_ErrorMessage.Add(1619, "Install package open failed"); /* ERROR_INSTALL_PACKAGE_OPEN_FAILED */ + s_ErrorMessage.Add(1620, "Install package invalid"); /* ERROR_INSTALL_PACKAGE_INVALID */ + s_ErrorMessage.Add(1621, "Install UI failure"); /* ERROR_INSTALL_UI_FAILURE */ + s_ErrorMessage.Add(1622, "Install log failure"); /* ERROR_INSTALL_LOG_FAILURE */ + s_ErrorMessage.Add(1623, "Install language unsupported"); /* ERROR_INSTALL_LANGUAGE_UNSUPPORTED */ + s_ErrorMessage.Add(1624, "Install transform failure"); /* ERROR_INSTALL_TRANSFORM_FAILURE */ + s_ErrorMessage.Add(1625, "Install package rejected"); /* ERROR_INSTALL_PACKAGE_REJECTED */ + s_ErrorMessage.Add(1626, "Function not called"); /* ERROR_FUNCTION_NOT_CALLED */ + s_ErrorMessage.Add(1627, "Function failed"); /* ERROR_FUNCTION_FAILED */ + s_ErrorMessage.Add(1628, "Invalid table"); /* ERROR_INVALID_TABLE */ + s_ErrorMessage.Add(1629, "Datatype mismatch"); /* ERROR_DATATYPE_MISMATCH */ + s_ErrorMessage.Add(1630, "Unsupported type"); /* ERROR_UNSUPPORTED_TYPE */ + s_ErrorMessage.Add(1631, "Create failed"); /* ERROR_CREATE_FAILED */ + s_ErrorMessage.Add(1632, "Install temp unwritable"); /* ERROR_INSTALL_TEMP_UNWRITABLE */ + s_ErrorMessage.Add(1633, "Install platform unsupported"); /* ERROR_INSTALL_PLATFORM_UNSUPPORTED */ + s_ErrorMessage.Add(1634, "Install notused"); /* ERROR_INSTALL_NOTUSED */ + s_ErrorMessage.Add(1635, "Patch package open failed"); /* ERROR_PATCH_PACKAGE_OPEN_FAILED */ + s_ErrorMessage.Add(1636, "Patch package invalid"); /* ERROR_PATCH_PACKAGE_INVALID */ + s_ErrorMessage.Add(1637, "Patch package unsupported"); /* ERROR_PATCH_PACKAGE_UNSUPPORTED */ + s_ErrorMessage.Add(1638, "Product version"); /* ERROR_PRODUCT_VERSION */ + s_ErrorMessage.Add(1639, "Invalid command line"); /* ERROR_INVALID_COMMAND_LINE */ + s_ErrorMessage.Add(1640, "Install remote disallowed"); /* ERROR_INSTALL_REMOTE_DISALLOWED */ + s_ErrorMessage.Add(1641, "Success reboot initiated"); /* ERROR_SUCCESS_REBOOT_INITIATED */ + s_ErrorMessage.Add(1642, "Patch target not found"); /* ERROR_PATCH_TARGET_NOT_FOUND */ + s_ErrorMessage.Add(1643, "Patch package rejected"); /* ERROR_PATCH_PACKAGE_REJECTED */ + s_ErrorMessage.Add(1644, "Install transform rejected"); /* ERROR_INSTALL_TRANSFORM_REJECTED */ + s_ErrorMessage.Add(1700, "RPC S Invalid string binding"); /* RPC_S_INVALID_STRING_BINDING */ + s_ErrorMessage.Add(1701, "RPC S Wrong kind of binding"); /* RPC_S_WRONG_KIND_OF_BINDING */ + s_ErrorMessage.Add(1702, "RPC S Invalid binding"); /* RPC_S_INVALID_BINDING */ + s_ErrorMessage.Add(1703, "RPC S Protseq not supported"); /* RPC_S_PROTSEQ_NOT_SUPPORTED */ + s_ErrorMessage.Add(1704, "RPC S Invalid RPC protseq"); /* RPC_S_INVALID_RPC_PROTSEQ */ + s_ErrorMessage.Add(1705, "RPC S Invalid string UUID"); /* RPC_S_INVALID_STRING_UUID */ + s_ErrorMessage.Add(1706, "RPC S Invalid endpoint format"); /* RPC_S_INVALID_ENDPOINT_FORMAT */ + s_ErrorMessage.Add(1707, "RPC S Invalid net addr"); /* RPC_S_INVALID_NET_ADDR */ + s_ErrorMessage.Add(1708, "RPC S No endpoint found"); /* RPC_S_NO_ENDPOINT_FOUND */ + s_ErrorMessage.Add(1709, "RPC S Invalid timeout"); /* RPC_S_INVALID_TIMEOUT */ + s_ErrorMessage.Add(1710, "RPC S Object not found"); /* RPC_S_OBJECT_NOT_FOUND */ + s_ErrorMessage.Add(1711, "RPC S Already registered"); /* RPC_S_ALREADY_REGISTERED */ + s_ErrorMessage.Add(1712, "RPC S Type already registered"); /* RPC_S_TYPE_ALREADY_REGISTERED */ + s_ErrorMessage.Add(1713, "RPC S Already listening"); /* RPC_S_ALREADY_LISTENING */ + s_ErrorMessage.Add(1714, "RPC S Not protseqs registered"); /* RPC_S_NO_PROTSEQS_REGISTERED */ + s_ErrorMessage.Add(1715, "RPC S Not listening"); /* RPC_S_NOT_LISTENING */ + s_ErrorMessage.Add(1716, "RPC S Unknown mgr type"); /* RPC_S_UNKNOWN_MGR_TYPE */ + s_ErrorMessage.Add(1717, "RPC S Unknown IF"); /* RPC_S_UNKNOWN_IF */ + s_ErrorMessage.Add(1718, "RPC S No bindings"); /* RPC_S_NO_BINDINGS */ + s_ErrorMessage.Add(1719, "RPC S Not protseqs"); /* RPC_S_NO_PROTSEQS */ + s_ErrorMessage.Add(1720, "RPC S Can't create endpoint"); /* RPC_S_CANT_CREATE_ENDPOINT */ + s_ErrorMessage.Add(1721, "RPC S Out of resources"); /* RPC_S_OUT_OF_RESOURCES */ + s_ErrorMessage.Add(1722, "RPC S Server unavailable"); /* RPC_S_SERVER_UNAVAILABLE */ + s_ErrorMessage.Add(1723, "RPC S Server too busy"); /* RPC_S_SERVER_TOO_BUSY */ + s_ErrorMessage.Add(1724, "RPC S Invalid network options"); /* RPC_S_INVALID_NETWORK_OPTIONS */ + s_ErrorMessage.Add(1725, "RPC S No call active"); /* RPC_S_NO_CALL_ACTIVE */ + s_ErrorMessage.Add(1726, "RPC S Call failed"); /* RPC_S_CALL_FAILED */ + s_ErrorMessage.Add(1727, "RPC S Call failed DNE"); /* RPC_S_CALL_FAILED_DNE */ + s_ErrorMessage.Add(1728, "RPC S Protocol error"); /* RPC_S_PROTOCOL_ERROR */ + s_ErrorMessage.Add(1730, "RPC S Unsupported trans syn"); /* RPC_S_UNSUPPORTED_TRANS_SYN */ + s_ErrorMessage.Add(1732, "RPC S Unsupported type"); /* RPC_S_UNSUPPORTED_TYPE */ + s_ErrorMessage.Add(1733, "RPC S Invalid tag"); /* RPC_S_INVALID_TAG */ + s_ErrorMessage.Add(1734, "RPC S Invalid bound"); /* RPC_S_INVALID_BOUND */ + s_ErrorMessage.Add(1735, "RPC S No entry name"); /* RPC_S_NO_ENTRY_NAME */ + s_ErrorMessage.Add(1736, "RPC S Invalid name syntax"); /* RPC_S_INVALID_NAME_SYNTAX */ + s_ErrorMessage.Add(1737, "RPC S Unsupported name syntax"); /* RPC_S_UNSUPPORTED_NAME_SYNTAX */ + s_ErrorMessage.Add(1739, "RPC S UUID no address"); /* RPC_S_UUID_NO_ADDRESS */ + s_ErrorMessage.Add(1740, "RPC S Duplicate endpoint"); /* RPC_S_DUPLICATE_ENDPOINT */ + s_ErrorMessage.Add(1741, "RPC S Unknown authn type"); /* RPC_S_UNKNOWN_AUTHN_TYPE */ + s_ErrorMessage.Add(1742, "RPC S Max calls too small"); /* RPC_S_MAX_CALLS_TOO_SMALL */ + s_ErrorMessage.Add(1743, "RPC S String too long"); /* RPC_S_STRING_TOO_LONG */ + s_ErrorMessage.Add(1744, "RPC S Protseq not found"); /* RPC_S_PROTSEQ_NOT_FOUND */ + s_ErrorMessage.Add(1745, "RPC S Procnum out of range"); /* RPC_S_PROCNUM_OUT_OF_RANGE */ + s_ErrorMessage.Add(1746, "RPC S Binding has no auth"); /* RPC_S_BINDING_HAS_NO_AUTH */ + s_ErrorMessage.Add(1747, "RPC S Unknown authn service"); /* RPC_S_UNKNOWN_AUTHN_SERVICE */ + s_ErrorMessage.Add(1748, "RPC S Unknown authn level"); /* RPC_S_UNKNOWN_AUTHN_LEVEL */ + s_ErrorMessage.Add(1749, "RPC S Invalid auth identity"); /* RPC_S_INVALID_AUTH_IDENTITY */ + s_ErrorMessage.Add(1750, "RPC S Unknown authz service"); /* RPC_S_UNKNOWN_AUTHZ_SERVICE */ + s_ErrorMessage.Add(1751, "EPT S Invalid entry"); /* EPT_S_INVALID_ENTRY */ + s_ErrorMessage.Add(1752, "EPT S Can't perform op"); /* EPT_S_CANT_PERFORM_OP */ + s_ErrorMessage.Add(1753, "EPT S Not registered"); /* EPT_S_NOT_REGISTERED */ + s_ErrorMessage.Add(1754, "RPC S Nothing to export"); /* RPC_S_NOTHING_TO_EXPORT */ + s_ErrorMessage.Add(1755, "RPC S Incomplete name"); /* RPC_S_INCOMPLETE_NAME */ + s_ErrorMessage.Add(1756, "RPC S Invalid vers option"); /* RPC_S_INVALID_VERS_OPTION */ + s_ErrorMessage.Add(1757, "RPC S No more members"); /* RPC_S_NO_MORE_MEMBERS */ + s_ErrorMessage.Add(1758, "RPC S Not all objs unexported"); /* RPC_S_NOT_ALL_OBJS_UNEXPORTED */ + s_ErrorMessage.Add(1759, "RPC S Interface not found"); /* RPC_S_INTERFACE_NOT_FOUND */ + s_ErrorMessage.Add(1760, "RPC S Entry already exists"); /* RPC_S_ENTRY_ALREADY_EXISTS */ + s_ErrorMessage.Add(1761, "RPC S Entry not found"); /* RPC_S_ENTRY_NOT_FOUND */ + s_ErrorMessage.Add(1762, "RPC S Name service unavailable"); /* RPC_S_NAME_SERVICE_UNAVAILABLE */ + s_ErrorMessage.Add(1763, "RPC S Invalid naf ID"); /* RPC_S_INVALID_NAF_ID */ + s_ErrorMessage.Add(1764, "RPC S Cannot support"); /* RPC_S_CANNOT_SUPPORT */ + s_ErrorMessage.Add(1765, "RPC S No context available"); /* RPC_S_NO_CONTEXT_AVAILABLE */ + s_ErrorMessage.Add(1766, "RPC S Internal error"); /* RPC_S_INTERNAL_ERROR */ + s_ErrorMessage.Add(1767, "RPC S Zero divide"); /* RPC_S_ZERO_DIVIDE */ + s_ErrorMessage.Add(1768, "RPC S Address error"); /* RPC_S_ADDRESS_ERROR */ + s_ErrorMessage.Add(1769, "RPC S FP div zero"); /* RPC_S_FP_DIV_ZERO */ + s_ErrorMessage.Add(1770, "RPC S FP Underflow"); /* RPC_S_FP_UNDERFLOW */ + s_ErrorMessage.Add(1771, "RPC S Overflow"); /* RPC_S_FP_OVERFLOW */ + s_ErrorMessage.Add(1772, "RPC X No more entries"); /* RPC_X_NO_MORE_ENTRIES */ + s_ErrorMessage.Add(1773, "RPC X SS char trans open fail"); /* RPC_X_SS_CHAR_TRANS_OPEN_FAIL */ + s_ErrorMessage.Add(1774, "RPC X SS char trans short file"); /* RPC_X_SS_CHAR_TRANS_SHORT_FILE */ + s_ErrorMessage.Add(1775, "RPC S SS in null context"); /* RPC_X_SS_IN_NULL_CONTEXT */ + s_ErrorMessage.Add(1777, "RPC X SS context damaged"); /* RPC_X_SS_CONTEXT_DAMAGED */ + s_ErrorMessage.Add(1778, "RPC X SS handles mismatch"); /* RPC_X_SS_HANDLES_MISMATCH */ + s_ErrorMessage.Add(1779, "RPC X SS cannot get call handle"); /* RPC_X_SS_CANNOT_GET_CALL_HANDLE */ + s_ErrorMessage.Add(1780, "RPC X Null ref pointer"); /* RPC_X_NULL_REF_POINTER */ + s_ErrorMessage.Add(1781, "RPC X enum value out of range"); /* RPC_X_ENUM_VALUE_OUT_OF_RANGE */ + s_ErrorMessage.Add(1782, "RPC X byte count too small"); /* RPC_X_BYTE_COUNT_TOO_SMALL */ + s_ErrorMessage.Add(1783, "RPC X bad stub data"); /* RPC_X_BAD_STUB_DATA */ + s_ErrorMessage.Add(1784, "Invalid user buffer"); /* ERROR_INVALID_USER_BUFFER */ + s_ErrorMessage.Add(1785, "Unrecognised media"); /* ERROR_UNRECOGNIZED_MEDIA */ + s_ErrorMessage.Add(1786, "No trust lsa secret"); /* ERROR_NO_TRUST_LSA_SECRET */ + s_ErrorMessage.Add(1787, "No trust sam account"); /* ERROR_NO_TRUST_SAM_ACCOUNT */ + s_ErrorMessage.Add(1788, "Trusted domain failure"); /* ERROR_TRUSTED_DOMAIN_FAILURE */ + s_ErrorMessage.Add(1789, "Trusted relationship failure"); /* ERROR_TRUSTED_RELATIONSHIP_FAILURE */ + s_ErrorMessage.Add(1790, "Trust failure"); /* ERROR_TRUST_FAILURE */ + s_ErrorMessage.Add(1791, "RPC S call in progress"); /* RPC_S_CALL_IN_PROGRESS */ + s_ErrorMessage.Add(1792, "Error netlogon not started"); /* ERROR_NETLOGON_NOT_STARTED */ + s_ErrorMessage.Add(1793, "Account expired"); /* ERROR_ACCOUNT_EXPIRED */ + s_ErrorMessage.Add(1794, "Redirector has open handles"); /* ERROR_REDIRECTOR_HAS_OPEN_HANDLES */ + s_ErrorMessage.Add(1795, "Printer driver already installed"); /* ERROR_PRINTER_DRIVER_ALREADY_INSTALLED */ + s_ErrorMessage.Add(1796, "Unknown port"); /* ERROR_UNKNOWN_PORT */ + s_ErrorMessage.Add(1797, "Unknown printer driver"); /* ERROR_UNKNOWN_PRINTER_DRIVER */ + s_ErrorMessage.Add(1798, "Unknown printprocessor"); /* ERROR_UNKNOWN_PRINTPROCESSOR */ + s_ErrorMessage.Add(1799, "Invalid separator file"); /* ERROR_INVALID_SEPARATOR_FILE */ + s_ErrorMessage.Add(1800, "Invalid priority"); /* ERROR_INVALID_PRIORITY */ + s_ErrorMessage.Add(1801, "Invalid printer name"); /* ERROR_INVALID_PRINTER_NAME */ + s_ErrorMessage.Add(1802, "Printer already exists"); /* ERROR_PRINTER_ALREADY_EXISTS */ + s_ErrorMessage.Add(1803, "Invalid printer command"); /* ERROR_INVALID_PRINTER_COMMAND */ + s_ErrorMessage.Add(1804, "Invalid datatype"); /* ERROR_INVALID_DATATYPE */ + s_ErrorMessage.Add(1805, "Invalid environment"); /* ERROR_INVALID_ENVIRONMENT */ + s_ErrorMessage.Add(1806, "RPC S no more bindings"); /* RPC_S_NO_MORE_BINDINGS */ + s_ErrorMessage.Add(1807, "Nologon interdomain trust account"); /* ERROR_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT */ + s_ErrorMessage.Add(1808, "Nologon workstation trust account"); /* ERROR_NOLOGON_WORKSTATION_TRUST_ACCOUNT */ + s_ErrorMessage.Add(1809, "Nologon server trust account"); /* ERROR_NOLOGON_SERVER_TRUST_ACCOUNT */ + s_ErrorMessage.Add(1810, "Domain trust inconsistent"); /* ERROR_DOMAIN_TRUST_INCONSISTENT */ + s_ErrorMessage.Add(1811, "Server has open handles"); /* ERROR_SERVER_HAS_OPEN_HANDLES */ + s_ErrorMessage.Add(1812, "Resource data not found"); /* ERROR_RESOURCE_DATA_NOT_FOUND */ + s_ErrorMessage.Add(1813, "Resource type not found"); /* ERROR_RESOURCE_TYPE_NOT_FOUND */ + s_ErrorMessage.Add(1814, "Resource name not found"); /* ERROR_RESOURCE_NAME_NOT_FOUND */ + s_ErrorMessage.Add(1815, "Resource lang not found"); /* ERROR_RESOURCE_LANG_NOT_FOUND */ + s_ErrorMessage.Add(1816, "Not enough quota"); /* ERROR_NOT_ENOUGH_QUOTA */ + s_ErrorMessage.Add(1817, "RPC S no interfaces"); /* RPC_S_NO_INTERFACES */ + s_ErrorMessage.Add(1818, "RPC S Call cancelled"); /* RPC_S_CALL_CANCELLED */ + s_ErrorMessage.Add(1819, "RPC S Binding incomplete"); /* RPC_S_BINDING_INCOMPLETE */ + s_ErrorMessage.Add(1820, "RPC S Comm failure"); /* RPC_S_COMM_FAILURE */ + s_ErrorMessage.Add(1821, "RPC S Unsupported authn level"); /* RPC_S_UNSUPPORTED_AUTHN_LEVEL */ + s_ErrorMessage.Add(1822, "RPC S No princ name"); /* RPC_S_NO_PRINC_NAME */ + s_ErrorMessage.Add(1823, "RPC S Not RPC error"); /* RPC_S_NOT_RPC_ERROR */ + s_ErrorMessage.Add(1824, "RPC U UUID local only"); /* RPC_S_UUID_LOCAL_ONLY */ + s_ErrorMessage.Add(1825, "RPC S Sec pkg error"); /* RPC_S_SEC_PKG_ERROR */ + s_ErrorMessage.Add(1826, "RPC S Not cancelled"); /* RPC_S_NOT_CANCELLED */ + s_ErrorMessage.Add(1827, "RPC X Invalid ES action"); /* RPC_X_INVALID_ES_ACTION */ + s_ErrorMessage.Add(1828, "RPC X Wrong ES version"); /* RPC_X_WRONG_ES_VERSION */ + s_ErrorMessage.Add(1829, "RPC X Wrong stub version"); /* RPC_X_WRONG_STUB_VERSION */ + s_ErrorMessage.Add(1830, "RPC X Invalid pipe object"); /* RPC_X_INVALID_PIPE_OBJECT */ + s_ErrorMessage.Add(1831, "RPC X Wrong pipe order"); /* RPC_X_WRONG_PIPE_ORDER */ + s_ErrorMessage.Add(1832, "RPC X Wrong pipe version"); /* RPC_X_WRONG_PIPE_VERSION */ + s_ErrorMessage.Add(1898, "RPC S group member not found"); /* RPC_S_GROUP_MEMBER_NOT_FOUND */ + s_ErrorMessage.Add(1899, "EPT S Can't create"); /* EPT_S_CANT_CREATE */ + s_ErrorMessage.Add(1900, "RPC S Invalid object"); /* RPC_S_INVALID_OBJECT */ + s_ErrorMessage.Add(1901, "Invalid time"); /* ERROR_INVALID_TIME */ + s_ErrorMessage.Add(1902, "Invalid form name"); /* ERROR_INVALID_FORM_NAME */ + s_ErrorMessage.Add(1903, "Invalid form size"); /* ERROR_INVALID_FORM_SIZE */ + s_ErrorMessage.Add(1904, "Already waiting"); /* ERROR_ALREADY_WAITING */ + s_ErrorMessage.Add(1905, "Printer deleted"); /* ERROR_PRINTER_DELETED */ + s_ErrorMessage.Add(1906, "Invalid printer state"); /* ERROR_INVALID_PRINTER_STATE */ + s_ErrorMessage.Add(1907, "Password must change"); /* ERROR_PASSWORD_MUST_CHANGE */ + s_ErrorMessage.Add(1908, "Domain controller not found"); /* ERROR_DOMAIN_CONTROLLER_NOT_FOUND */ + s_ErrorMessage.Add(1909, "Account locked out"); /* ERROR_ACCOUNT_LOCKED_OUT */ + s_ErrorMessage.Add(1910, "OR Invalid OXID"); /* OR_INVALID_OXID */ + s_ErrorMessage.Add(1911, "OR Invalid OID"); /* OR_INVALID_OID */ + s_ErrorMessage.Add(1912, "OR Invalid set"); /* OR_INVALID_SET */ + s_ErrorMessage.Add(1913, "RPC S Send incomplete"); /* RPC_S_SEND_INCOMPLETE */ + s_ErrorMessage.Add(1914, "RPC S Invalid async handle"); /* RPC_S_INVALID_ASYNC_HANDLE */ + s_ErrorMessage.Add(1915, "RPC S Invalid async call"); /* RPC_S_INVALID_ASYNC_CALL */ + s_ErrorMessage.Add(1916, "RPC X Pipe closed"); /* RPC_X_PIPE_CLOSED */ + s_ErrorMessage.Add(1917, "RPC X Pipe discipline error"); /* RPC_X_PIPE_DISCIPLINE_ERROR */ + s_ErrorMessage.Add(1918, "RPC X Pipe empty"); /* RPC_X_PIPE_EMPTY */ + s_ErrorMessage.Add(1919, "No sitename"); /* ERROR_NO_SITENAME */ + s_ErrorMessage.Add(1920, "Can't access file"); /* ERROR_CANT_ACCESS_FILE */ + s_ErrorMessage.Add(1921, "Can't resolve filename"); /* ERROR_CANT_RESOLVE_FILENAME */ + s_ErrorMessage.Add(1922, "RPC S Entry type mismatch"); /* RPC_S_ENTRY_TYPE_MISMATCH */ + s_ErrorMessage.Add(1923, "RPC S Not all objs exported"); /* RPC_S_NOT_ALL_OBJS_EXPORTED */ + s_ErrorMessage.Add(1924, "RPC S Interface not exported"); /* RPC_S_INTERFACE_NOT_EXPORTED */ + s_ErrorMessage.Add(1925, "RPC S Profile not added"); /* RPC_S_PROFILE_NOT_ADDED */ + s_ErrorMessage.Add(1926, "RPC S PRF ELT not added"); /* RPC_S_PRF_ELT_NOT_ADDED */ + s_ErrorMessage.Add(1927, "RPC S PRF ELT not removed"); /* RPC_S_PRF_ELT_NOT_REMOVED */ + s_ErrorMessage.Add(1928, "RPC S GRP ELT not added"); /* RPC_S_GRP_ELT_NOT_ADDED */ + s_ErrorMessage.Add(1929, "RPC S GRP ELT not removed"); /* RPC_S_GRP_ELT_NOT_REMOVED */ + s_ErrorMessage.Add(1930, "KM driver blocked"); /* ERROR_KM_DRIVER_BLOCKED */ + s_ErrorMessage.Add(1931, "Context expired"); /* ERROR_CONTEXT_EXPIRED */ + s_ErrorMessage.Add(2000, "Invalid pixel format"); /* ERROR_INVALID_PIXEL_FORMAT */ + s_ErrorMessage.Add(2001, "Bad driver"); /* ERROR_BAD_DRIVER */ + s_ErrorMessage.Add(2002, "Invalid window style"); /* ERROR_INVALID_WINDOW_STYLE */ + s_ErrorMessage.Add(2003, "Metafile not supported"); /* ERROR_METAFILE_NOT_SUPPORTED */ + s_ErrorMessage.Add(2004, "Transform not supported"); /* ERROR_TRANSFORM_NOT_SUPPORTED */ + s_ErrorMessage.Add(2005, "Clipping not supported"); /* ERROR_CLIPPING_NOT_SUPPORTED */ + s_ErrorMessage.Add(2010, "Invalid CMM"); /* ERROR_INVALID_CMM */ + s_ErrorMessage.Add(2011, "Invalid profile"); /* ERROR_INVALID_PROFILE */ + s_ErrorMessage.Add(2012, "Tag not found"); /* ERROR_TAG_NOT_FOUND */ + s_ErrorMessage.Add(2013, "Tag not present"); /* ERROR_TAG_NOT_PRESENT */ + s_ErrorMessage.Add(2014, "Duplicate tag"); /* ERROR_DUPLICATE_TAG */ + s_ErrorMessage.Add(2015, "Profile not associated with device"); /* ERROR_PROFILE_NOT_ASSOCIATED_WITH_DEVICE */ + s_ErrorMessage.Add(2016, "Profile not found"); /* ERROR_PROFILE_NOT_FOUND */ + s_ErrorMessage.Add(2017, "Invalid colorspace"); /* ERROR_INVALID_COLORSPACE */ + s_ErrorMessage.Add(2018, "ICM not enabled"); /* ERROR_ICM_NOT_ENABLED */ + s_ErrorMessage.Add(2019, "Deleting ICM xform"); /* ERROR_DELETING_ICM_XFORM */ + s_ErrorMessage.Add(2020, "Invalid transform"); /* ERROR_INVALID_TRANSFORM */ + s_ErrorMessage.Add(2021, "Colorspace mismatch"); /* ERROR_COLORSPACE_MISMATCH */ + s_ErrorMessage.Add(2022, "Invalid colorindex"); /* ERROR_INVALID_COLORINDEX */ + s_ErrorMessage.Add(2108, "Connected other password"); /* ERROR_CONNECTED_OTHER_PASSWORD */ + s_ErrorMessage.Add(2109, "Connected other password default"); /* ERROR_CONNECTED_OTHER_PASSWORD_DEFAULT */ + s_ErrorMessage.Add(2202, "Bad username"); /* ERROR_BAD_USERNAME */ + s_ErrorMessage.Add(2250, "Not connected"); /* ERROR_NOT_CONNECTED */ + s_ErrorMessage.Add(2401, "Open files"); /* ERROR_OPEN_FILES */ + s_ErrorMessage.Add(2402, "Active connections"); /* ERROR_ACTIVE_CONNECTIONS */ + s_ErrorMessage.Add(2404, "Device in use"); /* ERROR_DEVICE_IN_USE */ + s_ErrorMessage.Add(3000, "Unknown print monitor"); /* ERROR_UNKNOWN_PRINT_MONITOR */ + s_ErrorMessage.Add(3001, "Printer driver in use"); /* ERROR_PRINTER_DRIVER_IN_USE */ + s_ErrorMessage.Add(3002, "Spool file not found"); /* ERROR_SPOOL_FILE_NOT_FOUND */ + s_ErrorMessage.Add(3003, "SPL no startdoc"); /* ERROR_SPL_NO_STARTDOC */ + s_ErrorMessage.Add(3004, "SPL no addjob"); /* ERROR_SPL_NO_ADDJOB */ + s_ErrorMessage.Add(3005, "Print processor already installed"); /* ERROR_PRINT_PROCESSOR_ALREADY_INSTALLED */ + s_ErrorMessage.Add(3006, "Print monitor already installed"); /* ERROR_PRINT_MONITOR_ALREADY_INSTALLED */ + s_ErrorMessage.Add(3007, "Invalid print monitor"); /* ERROR_INVALID_PRINT_MONITOR */ + s_ErrorMessage.Add(3008, "Print monitor in use"); /* ERROR_PRINT_MONITOR_IN_USE */ + s_ErrorMessage.Add(3009, "Printer has jobs queued"); /* ERROR_PRINTER_HAS_JOBS_QUEUED */ + s_ErrorMessage.Add(3010, "Success reboot required"); /* ERROR_SUCCESS_REBOOT_REQUIRED */ + s_ErrorMessage.Add(3011, "Success restart required"); /* ERROR_SUCCESS_RESTART_REQUIRED */ + s_ErrorMessage.Add(3012, "Printer not found"); /* ERROR_PRINTER_NOT_FOUND */ + s_ErrorMessage.Add(3013, "Printer driver warned"); /* ERROR_PRINTER_DRIVER_WARNED */ + s_ErrorMessage.Add(3014, "Printer driver blocked"); /* ERROR_PRINTER_DRIVER_BLOCKED */ + s_ErrorMessage.Add(4000, "Wins internal"); /* ERROR_WINS_INTERNAL */ + s_ErrorMessage.Add(4001, "Can not del local wins"); /* ERROR_CAN_NOT_DEL_LOCAL_WINS */ + s_ErrorMessage.Add(4002, "Static init"); /* ERROR_STATIC_INIT */ + s_ErrorMessage.Add(4003, "Inc backup"); /* ERROR_INC_BACKUP */ + s_ErrorMessage.Add(4004, "Full backup"); /* ERROR_FULL_BACKUP */ + s_ErrorMessage.Add(4005, "Rec not existent"); /* ERROR_REC_NON_EXISTENT */ + s_ErrorMessage.Add(4006, "RPL not allowed"); /* ERROR_RPL_NOT_ALLOWED */ + s_ErrorMessage.Add(4100, "DHCP address conflict"); /* ERROR_DHCP_ADDRESS_CONFLICT */ + s_ErrorMessage.Add(4200, "WMU GUID not found"); /* ERROR_WMI_GUID_NOT_FOUND */ + s_ErrorMessage.Add(4201, "WMI instance not found"); /* ERROR_WMI_INSTANCE_NOT_FOUND */ + s_ErrorMessage.Add(4202, "WMI ItemID not found"); /* ERROR_WMI_ITEMID_NOT_FOUND */ + s_ErrorMessage.Add(4203, "WMI try again"); /* ERROR_WMI_TRY_AGAIN */ + s_ErrorMessage.Add(4204, "WMI DP not found"); /* ERROR_WMI_DP_NOT_FOUND */ + s_ErrorMessage.Add(4205, "WMI unresolved instance ref"); /* ERROR_WMI_UNRESOLVED_INSTANCE_REF */ + s_ErrorMessage.Add(4206, "WMU already enabled"); /* ERROR_WMI_ALREADY_ENABLED */ + s_ErrorMessage.Add(4207, "WMU GUID disconnected"); /* ERROR_WMI_GUID_DISCONNECTED */ + s_ErrorMessage.Add(4208, "WMI server unavailable"); /* ERROR_WMI_SERVER_UNAVAILABLE */ + s_ErrorMessage.Add(4209, "WMI DP failed"); /* ERROR_WMI_DP_FAILED */ + s_ErrorMessage.Add(4210, "WMI invalid MOF"); /* ERROR_WMI_INVALID_MOF */ + s_ErrorMessage.Add(4211, "WMI invalid reginfo"); /* ERROR_WMI_INVALID_REGINFO */ + s_ErrorMessage.Add(4212, "WMI already disabled"); /* ERROR_WMI_ALREADY_DISABLED */ + s_ErrorMessage.Add(4213, "WMI read only"); /* ERROR_WMI_READ_ONLY */ + s_ErrorMessage.Add(4214, "WMI set failure"); /* ERROR_WMI_SET_FAILURE */ + s_ErrorMessage.Add(4300, "Invalid media"); /* ERROR_INVALID_MEDIA */ + s_ErrorMessage.Add(4301, "Invalid library"); /* ERROR_INVALID_LIBRARY */ + s_ErrorMessage.Add(4302, "Invalid media pool"); /* ERROR_INVALID_MEDIA_POOL */ + s_ErrorMessage.Add(4303, "Drive media mismatch"); /* ERROR_DRIVE_MEDIA_MISMATCH */ + s_ErrorMessage.Add(4304, "Media offline"); /* ERROR_MEDIA_OFFLINE */ + s_ErrorMessage.Add(4305, "Library offline"); /* ERROR_LIBRARY_OFFLINE */ + s_ErrorMessage.Add(4306, "Empty"); /* ERROR_EMPTY */ + s_ErrorMessage.Add(4307, "Not empty"); /* ERROR_NOT_EMPTY */ + s_ErrorMessage.Add(4308, "Media unavailable"); /* ERROR_MEDIA_UNAVAILABLE */ + s_ErrorMessage.Add(4309, "Resource disabled"); /* ERROR_RESOURCE_DISABLED */ + s_ErrorMessage.Add(4310, "Invalid cleaner"); /* ERROR_INVALID_CLEANER */ + s_ErrorMessage.Add(4311, "Unable to clean"); /* ERROR_UNABLE_TO_CLEAN */ + s_ErrorMessage.Add(4312, "Object not found"); /* ERROR_OBJECT_NOT_FOUND */ + s_ErrorMessage.Add(4313, "Database failure"); /* ERROR_DATABASE_FAILURE */ + s_ErrorMessage.Add(4314, "Database full"); /* ERROR_DATABASE_FULL */ + s_ErrorMessage.Add(4315, "Media incompatible"); /* ERROR_MEDIA_INCOMPATIBLE */ + s_ErrorMessage.Add(4316, "Resource not present"); /* ERROR_RESOURCE_NOT_PRESENT */ + s_ErrorMessage.Add(4317, "Invalid operation"); /* ERROR_INVALID_OPERATION */ + s_ErrorMessage.Add(4318, "Media not available"); /* ERROR_MEDIA_NOT_AVAILABLE */ + s_ErrorMessage.Add(4319, "Device not available"); /* ERROR_DEVICE_NOT_AVAILABLE */ + s_ErrorMessage.Add(4320, "Request refused"); /* ERROR_REQUEST_REFUSED */ + s_ErrorMessage.Add(4321, "Invalid drive object"); /* ERROR_INVALID_DRIVE_OBJECT */ + s_ErrorMessage.Add(4322, "Library full"); /* ERROR_LIBRARY_FULL */ + s_ErrorMessage.Add(4323, "Medium not accessible"); /* ERROR_MEDIUM_NOT_ACCESSIBLE */ + s_ErrorMessage.Add(4324, "Unable to load medium"); /* ERROR_UNABLE_TO_LOAD_MEDIUM */ + s_ErrorMessage.Add(4325, "Unable to inventory drive"); /* ERROR_UNABLE_TO_INVENTORY_DRIVE */ + s_ErrorMessage.Add(4326, "Unable to inventory slot"); /* ERROR_UNABLE_TO_INVENTORY_SLOT */ + s_ErrorMessage.Add(4327, "Unable to inventory transport"); /* ERROR_UNABLE_TO_INVENTORY_TRANSPORT */ + s_ErrorMessage.Add(4328, "Transport full"); /* ERROR_TRANSPORT_FULL */ + s_ErrorMessage.Add(4329, "Controlling ieport"); /* ERROR_CONTROLLING_IEPORT */ + s_ErrorMessage.Add(4330, "Unable to eject mounted media"); /* ERROR_UNABLE_TO_EJECT_MOUNTED_MEDIA */ + s_ErrorMessage.Add(4331, "Cleaner slot set"); /* ERROR_CLEANER_SLOT_SET */ + s_ErrorMessage.Add(4332, "Cleaner slot not set"); /* ERROR_CLEANER_SLOT_NOT_SET */ + s_ErrorMessage.Add(4333, "Cleaner cartridge spent"); /* ERROR_CLEANER_CARTRIDGE_SPENT */ + s_ErrorMessage.Add(4334, "Unexpected omid"); /* ERROR_UNEXPECTED_OMID */ + s_ErrorMessage.Add(4335, "Can't delete last item"); /* ERROR_CANT_DELETE_LAST_ITEM */ + s_ErrorMessage.Add(4336, "Message exceeds max size"); /* ERROR_MESSAGE_EXCEEDS_MAX_SIZE */ + s_ErrorMessage.Add(4337, "Volume contains sys files"); /* ERROR_VOLUME_CONTAINS_SYS_FILES */ + s_ErrorMessage.Add(4338, "Indigenous type"); /* ERROR_INDIGENOUS_TYPE */ + s_ErrorMessage.Add(4339, "No supporting drives"); /* ERROR_NO_SUPPORTING_DRIVES */ + s_ErrorMessage.Add(4340, "Cleaner cartridge installed"); /* ERROR_CLEANER_CARTRIDGE_INSTALLED */ + s_ErrorMessage.Add(4350, "Fill offline"); /* ERROR_FILE_OFFLINE */ + s_ErrorMessage.Add(4351, "Remote storage not active"); /* ERROR_REMOTE_STORAGE_NOT_ACTIVE */ + s_ErrorMessage.Add(4352, "Remote storage media error"); /* ERROR_REMOTE_STORAGE_MEDIA_ERROR */ + s_ErrorMessage.Add(4390, "Not a reparse point"); /* ERROR_NOT_A_REPARSE_POINT */ + s_ErrorMessage.Add(4391, "Reparse attribute conflict"); /* ERROR_REPARSE_ATTRIBUTE_CONFLICT */ + s_ErrorMessage.Add(4392, "Invalid reparse data"); /* ERROR_INVALID_REPARSE_DATA */ + s_ErrorMessage.Add(4393, "Reparse tag invalid"); /* ERROR_REPARSE_TAG_INVALID */ + s_ErrorMessage.Add(4394, "Reparse tag mismatch"); /* ERROR_REPARSE_TAG_MISMATCH */ + s_ErrorMessage.Add(4500, "Volume not sis enabled"); /* ERROR_VOLUME_NOT_SIS_ENABLED */ + s_ErrorMessage.Add(5001, "Dependent resource exists"); /* ERROR_DEPENDENT_RESOURCE_EXISTS */ + s_ErrorMessage.Add(5002, "Dependency not found"); /* ERROR_DEPENDENCY_NOT_FOUND */ + s_ErrorMessage.Add(5003, "Dependency already exists"); /* ERROR_DEPENDENCY_ALREADY_EXISTS */ + s_ErrorMessage.Add(5004, "Resource not online"); /* ERROR_RESOURCE_NOT_ONLINE */ + s_ErrorMessage.Add(5005, "Host node not available"); /* ERROR_HOST_NODE_NOT_AVAILABLE */ + s_ErrorMessage.Add(5006, "Resource not available"); /* ERROR_RESOURCE_NOT_AVAILABLE */ + s_ErrorMessage.Add(5007, "Resource not found"); /* ERROR_RESOURCE_NOT_FOUND */ + s_ErrorMessage.Add(5008, "Shutdown cluster"); /* ERROR_SHUTDOWN_CLUSTER */ + s_ErrorMessage.Add(5009, "Can't evict active node"); /* ERROR_CANT_EVICT_ACTIVE_NODE */ + s_ErrorMessage.Add(5010, "Object already exists"); /* ERROR_OBJECT_ALREADY_EXISTS */ + s_ErrorMessage.Add(5011, "Object in list"); /* ERROR_OBJECT_IN_LIST */ + s_ErrorMessage.Add(5012, "Group not available"); /* ERROR_GROUP_NOT_AVAILABLE */ + s_ErrorMessage.Add(5013, "Group not found"); /* ERROR_GROUP_NOT_FOUND */ + s_ErrorMessage.Add(5014, "Group not online"); /* ERROR_GROUP_NOT_ONLINE */ + s_ErrorMessage.Add(5015, "Host node not resource owner"); /* ERROR_HOST_NODE_NOT_RESOURCE_OWNER */ + s_ErrorMessage.Add(5016, "Host node not group owner"); /* ERROR_HOST_NODE_NOT_GROUP_OWNER */ + s_ErrorMessage.Add(5017, "Resmon create failed"); /* ERROR_RESMON_CREATE_FAILED */ + s_ErrorMessage.Add(5018, "Resmon online failed"); /* ERROR_RESMON_ONLINE_FAILED */ + s_ErrorMessage.Add(5019, "Resource online"); /* ERROR_RESOURCE_ONLINE */ + s_ErrorMessage.Add(5020, "Quorum resource"); /* ERROR_QUORUM_RESOURCE */ + s_ErrorMessage.Add(5021, "Not quorum capable"); /* ERROR_NOT_QUORUM_CAPABLE */ + s_ErrorMessage.Add(5022, "Cluster shutting down"); /* ERROR_CLUSTER_SHUTTING_DOWN */ + s_ErrorMessage.Add(5023, "Invalid state"); /* ERROR_INVALID_STATE */ + s_ErrorMessage.Add(5024, "Resource properties stored"); /* ERROR_RESOURCE_PROPERTIES_STORED */ + s_ErrorMessage.Add(5025, "Not quorum class"); /* ERROR_NOT_QUORUM_CLASS */ + s_ErrorMessage.Add(5026, "Core resource"); /* ERROR_CORE_RESOURCE */ + s_ErrorMessage.Add(5027, "Quorum resource online failed"); /* ERROR_QUORUM_RESOURCE_ONLINE_FAILED */ + s_ErrorMessage.Add(5028, "Quorumlog open failed"); /* ERROR_QUORUMLOG_OPEN_FAILED */ + s_ErrorMessage.Add(5029, "Clusterlog corrupt"); /* ERROR_CLUSTERLOG_CORRUPT */ + s_ErrorMessage.Add(5030, "Clusterlog record exceeds maxsize"); /* ERROR_CLUSTERLOG_RECORD_EXCEEDS_MAXSIZE */ + s_ErrorMessage.Add(5031, "Clusterlog exceeds maxsize"); /* ERROR_CLUSTERLOG_EXCEEDS_MAXSIZE */ + s_ErrorMessage.Add(5032, "Clusterlog chkpoint not found"); /* ERROR_CLUSTERLOG_CHKPOINT_NOT_FOUND */ + s_ErrorMessage.Add(5033, "Clusterlog not enough space"); /* ERROR_CLUSTERLOG_NOT_ENOUGH_SPACE */ + s_ErrorMessage.Add(5034, "Quorum owner alive"); /* ERROR_QUORUM_OWNER_ALIVE */ + s_ErrorMessage.Add(5035, "Network not available"); /* ERROR_NETWORK_NOT_AVAILABLE */ + s_ErrorMessage.Add(5036, "Node not available"); /* ERROR_NODE_NOT_AVAILABLE */ + s_ErrorMessage.Add(5037, "All nodes not available"); /* ERROR_ALL_NODES_NOT_AVAILABLE */ + s_ErrorMessage.Add(5038, "Resource failed"); /* ERROR_RESOURCE_FAILED */ + s_ErrorMessage.Add(5039, "Cluster invalid node"); /* ERROR_CLUSTER_INVALID_NODE */ + s_ErrorMessage.Add(5040, "Cluster node exists"); /* ERROR_CLUSTER_NODE_EXISTS */ + s_ErrorMessage.Add(5041, "Cluster join in progress"); /* ERROR_CLUSTER_JOIN_IN_PROGRESS */ + s_ErrorMessage.Add(5042, "Cluster node not found"); /* ERROR_CLUSTER_NODE_NOT_FOUND */ + s_ErrorMessage.Add(5043, "Cluster local node not found"); /* ERROR_CLUSTER_LOCAL_NODE_NOT_FOUND */ + s_ErrorMessage.Add(5044, "Cluster network exists"); /* ERROR_CLUSTER_NETWORK_EXISTS */ + s_ErrorMessage.Add(5045, "Cluster network not found"); /* ERROR_CLUSTER_NETWORK_NOT_FOUND */ + s_ErrorMessage.Add(5046, "Cluster netinterface exists"); /* ERROR_CLUSTER_NETINTERFACE_EXISTS */ + s_ErrorMessage.Add(5047, "Cluster netinterface not found"); /* ERROR_CLUSTER_NETINTERFACE_NOT_FOUND */ + s_ErrorMessage.Add(5048, "Cluster invalid request"); /* ERROR_CLUSTER_INVALID_REQUEST */ + s_ErrorMessage.Add(5049, "Cluster invalid network provider"); /* ERROR_CLUSTER_INVALID_NETWORK_PROVIDER */ + s_ErrorMessage.Add(5050, "Cluster node down"); /* ERROR_CLUSTER_NODE_DOWN */ + s_ErrorMessage.Add(5051, "Cluster node unreachable"); /* ERROR_CLUSTER_NODE_UNREACHABLE */ + s_ErrorMessage.Add(5052, "Cluster node not member"); /* ERROR_CLUSTER_NODE_NOT_MEMBER */ + s_ErrorMessage.Add(5053, "Cluster join not in progress"); /* ERROR_CLUSTER_JOIN_NOT_IN_PROGRESS */ + s_ErrorMessage.Add(5054, "Cluster invalid network"); /* ERROR_CLUSTER_INVALID_NETWORK */ + s_ErrorMessage.Add(5056, "Cluster node up"); /* ERROR_CLUSTER_NODE_UP */ + s_ErrorMessage.Add(5057, "Cluster ipaddr in use"); /* ERROR_CLUSTER_IPADDR_IN_USE */ + s_ErrorMessage.Add(5058, "Cluster node not paused"); /* ERROR_CLUSTER_NODE_NOT_PAUSED */ + s_ErrorMessage.Add(5059, "Cluster no security context"); /* ERROR_CLUSTER_NO_SECURITY_CONTEXT */ + s_ErrorMessage.Add(5060, "Cluster network not internal"); /* ERROR_CLUSTER_NETWORK_NOT_INTERNAL */ + s_ErrorMessage.Add(5061, "Cluster node already up"); /* ERROR_CLUSTER_NODE_ALREADY_UP */ + s_ErrorMessage.Add(5062, "Cluster node already down"); /* ERROR_CLUSTER_NODE_ALREADY_DOWN */ + s_ErrorMessage.Add(5063, "Cluster network already online"); /* ERROR_CLUSTER_NETWORK_ALREADY_ONLINE */ + s_ErrorMessage.Add(5064, "Cluster network already offline"); /* ERROR_CLUSTER_NETWORK_ALREADY_OFFLINE */ + s_ErrorMessage.Add(5065, "Cluster node already member"); /* ERROR_CLUSTER_NODE_ALREADY_MEMBER */ + s_ErrorMessage.Add(5066, "Cluster last internal network"); /* ERROR_CLUSTER_LAST_INTERNAL_NETWORK */ + s_ErrorMessage.Add(5067, "Cluster network has dependents"); /* ERROR_CLUSTER_NETWORK_HAS_DEPENDENTS */ + s_ErrorMessage.Add(5068, "Invalid operation on quorum"); /* ERROR_INVALID_OPERATION_ON_QUORUM */ + s_ErrorMessage.Add(5069, "Dependency not allowed"); /* ERROR_DEPENDENCY_NOT_ALLOWED */ + s_ErrorMessage.Add(5070, "Cluster node paused"); /* ERROR_CLUSTER_NODE_PAUSED */ + s_ErrorMessage.Add(5071, "Node can't host resource"); /* ERROR_NODE_CANT_HOST_RESOURCE */ + s_ErrorMessage.Add(5072, "Cluster node not ready"); /* ERROR_CLUSTER_NODE_NOT_READY */ + s_ErrorMessage.Add(5073, "Cluster node shutting down"); /* ERROR_CLUSTER_NODE_SHUTTING_DOWN */ + s_ErrorMessage.Add(5074, "Cluster join aborted"); /* ERROR_CLUSTER_JOIN_ABORTED */ + s_ErrorMessage.Add(5075, "Cluster incompatible versions"); /* ERROR_CLUSTER_INCOMPATIBLE_VERSIONS */ + s_ErrorMessage.Add(5076, "Cluster maxnum of resources exceeded"); /* ERROR_CLUSTER_MAXNUM_OF_RESOURCES_EXCEEDED */ + s_ErrorMessage.Add(5077, "Cluster system config changed"); /* ERROR_CLUSTER_SYSTEM_CONFIG_CHANGED */ + s_ErrorMessage.Add(5078, "Cluster resource type not found"); /* ERROR_CLUSTER_RESOURCE_TYPE_NOT_FOUND */ + s_ErrorMessage.Add(5079, "Cluster restype not supported"); /* ERROR_CLUSTER_RESTYPE_NOT_SUPPORTED */ + s_ErrorMessage.Add(5080, "Cluster resname not found"); /* ERROR_CLUSTER_RESNAME_NOT_FOUND */ + s_ErrorMessage.Add(5081, "Cluster no RPC packages registered"); /* ERROR_CLUSTER_NO_RPC_PACKAGES_REGISTERED */ + s_ErrorMessage.Add(5082, "Cluster owner not in preflist"); /* ERROR_CLUSTER_OWNER_NOT_IN_PREFLIST */ + s_ErrorMessage.Add(5083, "Cluster database seqmismatch"); /* ERROR_CLUSTER_DATABASE_SEQMISMATCH */ + s_ErrorMessage.Add(5084, "Resmon invalid state"); /* ERROR_RESMON_INVALID_STATE */ + s_ErrorMessage.Add(5085, "Cluster gum not locker"); /* ERROR_CLUSTER_GUM_NOT_LOCKER */ + s_ErrorMessage.Add(5086, "Quorum disk not found"); /* ERROR_QUORUM_DISK_NOT_FOUND */ + s_ErrorMessage.Add(5087, "Database backup corrupt"); /* ERROR_DATABASE_BACKUP_CORRUPT */ + s_ErrorMessage.Add(5088, "Cluster node already has DFS root"); /* ERROR_CLUSTER_NODE_ALREADY_HAS_DFS_ROOT */ + s_ErrorMessage.Add(5089, "Resource property unchangeable"); /* ERROR_RESOURCE_PROPERTY_UNCHANGEABLE */ + s_ErrorMessage.Add(5890, "Cluster membership invalid state"); /* ERROR_CLUSTER_MEMBERSHIP_INVALID_STATE */ + s_ErrorMessage.Add(5891, "Cluster quorumlog not found"); /* ERROR_CLUSTER_QUORUMLOG_NOT_FOUND */ + s_ErrorMessage.Add(5892, "Cluster membership halt"); /* ERROR_CLUSTER_MEMBERSHIP_HALT */ + s_ErrorMessage.Add(5893, "Cluster instance ID mismatch"); /* ERROR_CLUSTER_INSTANCE_ID_MISMATCH */ + s_ErrorMessage.Add(5894, "Cluster network not found for IP"); /* ERROR_CLUSTER_NETWORK_NOT_FOUND_FOR_IP */ + s_ErrorMessage.Add(5895, "Cluster property data type mismatch"); /* ERROR_CLUSTER_PROPERTY_DATA_TYPE_MISMATCH */ + s_ErrorMessage.Add(5896, "Cluster evict without cleanup"); /* ERROR_CLUSTER_EVICT_WITHOUT_CLEANUP */ + s_ErrorMessage.Add(5897, "Cluster parameter mismatch"); /* ERROR_CLUSTER_PARAMETER_MISMATCH */ + s_ErrorMessage.Add(5898, "Node cannot be clustered"); /* ERROR_NODE_CANNOT_BE_CLUSTERED */ + s_ErrorMessage.Add(5899, "Cluster wrong OS version"); /* ERROR_CLUSTER_WRONG_OS_VERSION */ + s_ErrorMessage.Add(5900, "Cluster can't create dup cluster name"); /* ERROR_CLUSTER_CANT_CREATE_DUP_CLUSTER_NAME */ + s_ErrorMessage.Add(6001, "Decryption failed"); /* ERROR_DECRYPTION_FAILED */ + s_ErrorMessage.Add(6002, "File encrypted"); /* ERROR_FILE_ENCRYPTED */ + s_ErrorMessage.Add(6003, "No recovery policy"); /* ERROR_NO_RECOVERY_POLICY */ + s_ErrorMessage.Add(6004, "No EFS"); /* ERROR_NO_EFS */ + s_ErrorMessage.Add(6005, "Wrong EFS"); /* ERROR_WRONG_EFS */ + s_ErrorMessage.Add(6006, "No user keys"); /* ERROR_NO_USER_KEYS */ + s_ErrorMessage.Add(6007, "File not encryped"); /* ERROR_FILE_NOT_ENCRYPTED */ + s_ErrorMessage.Add(6008, "Not export format"); /* ERROR_NOT_EXPORT_FORMAT */ + s_ErrorMessage.Add(6009, "File read only"); /* ERROR_FILE_READ_ONLY */ + s_ErrorMessage.Add(6010, "Dir EFS disallowed"); /* ERROR_DIR_EFS_DISALLOWED */ + s_ErrorMessage.Add(6011, "EFS server not trusted"); /* ERROR_EFS_SERVER_NOT_TRUSTED */ + s_ErrorMessage.Add(6012, "Bad recovery policy"); /* ERROR_BAD_RECOVERY_POLICY */ + s_ErrorMessage.Add(6013, "ETS alg blob too big"); /* ERROR_EFS_ALG_BLOB_TOO_BIG */ + s_ErrorMessage.Add(6014, "Volume not support EFS"); /* ERROR_VOLUME_NOT_SUPPORT_EFS */ + s_ErrorMessage.Add(6015, "EFS disabled"); /* ERROR_EFS_DISABLED */ + s_ErrorMessage.Add(6016, "EFS version not support"); /* ERROR_EFS_VERSION_NOT_SUPPORT */ + s_ErrorMessage.Add(6118, "No browser servers found"); /* ERROR_NO_BROWSER_SERVERS_FOUND */ + s_ErrorMessage.Add(6200, "Sched E service not localsystem"); /* SCHED_E_SERVICE_NOT_LOCALSYSTEM */ + s_ErrorMessage.Add(7001, "Ctx winstation name invalid"); /* ERROR_CTX_WINSTATION_NAME_INVALID */ + s_ErrorMessage.Add(7002, "Ctx invalid PD"); /* ERROR_CTX_INVALID_PD */ + s_ErrorMessage.Add(7003, "Ctx PD not found"); /* ERROR_CTX_PD_NOT_FOUND */ + s_ErrorMessage.Add(7004, "Ctx WD not found"); /* ERROR_CTX_WD_NOT_FOUND */ + s_ErrorMessage.Add(7005, "Ctx cannot make eventlog entry"); /* ERROR_CTX_CANNOT_MAKE_EVENTLOG_ENTRY */ + s_ErrorMessage.Add(7006, "Ctx service name collision"); /* ERROR_CTX_SERVICE_NAME_COLLISION */ + s_ErrorMessage.Add(7007, "Ctx close pending"); /* ERROR_CTX_CLOSE_PENDING */ + s_ErrorMessage.Add(7008, "Ctx no outbuf"); /* ERROR_CTX_NO_OUTBUF */ + s_ErrorMessage.Add(7009, "Ctx modem inf not found"); /* ERROR_CTX_MODEM_INF_NOT_FOUND */ + s_ErrorMessage.Add(7010, "Ctx invalid modemname"); /* ERROR_CTX_INVALID_MODEMNAME */ + s_ErrorMessage.Add(7011, "Ctx modem response error"); /* ERROR_CTX_MODEM_RESPONSE_ERROR */ + s_ErrorMessage.Add(7012, "Ctx modem response timeout"); /* ERROR_CTX_MODEM_RESPONSE_TIMEOUT */ + s_ErrorMessage.Add(7013, "Ctx modem response no carrier"); /* ERROR_CTX_MODEM_RESPONSE_NO_CARRIER */ + s_ErrorMessage.Add(7014, "Ctx modem response no dial tone"); /* ERROR_CTX_MODEM_RESPONSE_NO_DIALTONE */ + s_ErrorMessage.Add(7015, "Ctx modem response busy"); /* ERROR_CTX_MODEM_RESPONSE_BUSY */ + s_ErrorMessage.Add(7016, "Ctx modem response voice"); /* ERROR_CTX_MODEM_RESPONSE_VOICE */ + s_ErrorMessage.Add(7017, "Ctx TD error"); /* ERROR_CTX_TD_ERROR */ + s_ErrorMessage.Add(7022, "Ctx winstation not found"); /* ERROR_CTX_WINSTATION_NOT_FOUND */ + s_ErrorMessage.Add(7023, "Ctx winstation already exists"); /* ERROR_CTX_WINSTATION_ALREADY_EXISTS */ + s_ErrorMessage.Add(7024, "Ctx winstation busy"); /* ERROR_CTX_WINSTATION_BUSY */ + s_ErrorMessage.Add(7025, "Ctx bad video mode"); /* ERROR_CTX_BAD_VIDEO_MODE */ + s_ErrorMessage.Add(7035, "Ctx graphics invalid"); /* ERROR_CTX_GRAPHICS_INVALID */ + s_ErrorMessage.Add(7037, "Ctx logon disabled"); /* ERROR_CTX_LOGON_DISABLED */ + s_ErrorMessage.Add(7038, "Ctx not console"); /* ERROR_CTX_NOT_CONSOLE */ + s_ErrorMessage.Add(7040, "Ctx client query timeout"); /* ERROR_CTX_CLIENT_QUERY_TIMEOUT */ + s_ErrorMessage.Add(7041, "Ctx console disconnect"); /* ERROR_CTX_CONSOLE_DISCONNECT */ + s_ErrorMessage.Add(7042, "Ctx console connect"); /* ERROR_CTX_CONSOLE_CONNECT */ + s_ErrorMessage.Add(7044, "Ctx shadow denied"); /* ERROR_CTX_SHADOW_DENIED */ + s_ErrorMessage.Add(7045, "Ctx winstation access denied"); /* ERROR_CTX_WINSTATION_ACCESS_DENIED */ + s_ErrorMessage.Add(7049, "Ctx invalid WD"); /* ERROR_CTX_INVALID_WD */ + s_ErrorMessage.Add(7050, "Ctx shadow invalid"); /* ERROR_CTX_SHADOW_INVALID */ + s_ErrorMessage.Add(7051, "Ctx shadow disabled"); /* ERROR_CTX_SHADOW_DISABLED */ + s_ErrorMessage.Add(7052, "Ctx client licence in use"); /* ERROR_CTX_CLIENT_LICENSE_IN_USE */ + s_ErrorMessage.Add(7053, "Ctx client licence not set"); /* ERROR_CTX_CLIENT_LICENSE_NOT_SET */ + s_ErrorMessage.Add(7054, "Ctx licence not available"); /* ERROR_CTX_LICENSE_NOT_AVAILABLE */ + s_ErrorMessage.Add(7055, "Ctx licence client invalid"); /* ERROR_CTX_LICENSE_CLIENT_INVALID */ + s_ErrorMessage.Add(7056, "Ctx licence expired"); /* ERROR_CTX_LICENSE_EXPIRED */ + s_ErrorMessage.Add(7057, "Ctx shadow not running"); /* ERROR_CTX_SHADOW_NOT_RUNNING */ + s_ErrorMessage.Add(7058, "Ctx shadow ended by mode change"); /* ERROR_CTX_SHADOW_ENDED_BY_MODE_CHANGE */ + s_ErrorMessage.Add(8001, "FRS err invalid API sequence"); /* FRS_ERR_INVALID_API_SEQUENCE */ + s_ErrorMessage.Add(8002, "FRS err starting service"); /* FRS_ERR_STARTING_SERVICE */ + s_ErrorMessage.Add(8003, "FRS err stopping service"); /* FRS_ERR_STOPPING_SERVICE */ + s_ErrorMessage.Add(8004, "FRS err internal API"); /* FRS_ERR_INTERNAL_API */ + s_ErrorMessage.Add(8005, "FRS err internal"); /* FRS_ERR_INTERNAL */ + s_ErrorMessage.Add(8006, "FRS err service comm"); /* FRS_ERR_SERVICE_COMM */ + s_ErrorMessage.Add(8007, "FRS err insufficient priv"); /* FRS_ERR_INSUFFICIENT_PRIV */ + s_ErrorMessage.Add(8008, "FRS err authentication"); /* FRS_ERR_AUTHENTICATION */ + s_ErrorMessage.Add(8009, "FRS err parent insufficient priv"); /* FRS_ERR_PARENT_INSUFFICIENT_PRIV */ + s_ErrorMessage.Add(8010, "FRS err parent authentication"); /* FRS_ERR_PARENT_AUTHENTICATION */ + s_ErrorMessage.Add(8011, "FRS err child to parent comm"); /* FRS_ERR_CHILD_TO_PARENT_COMM */ + s_ErrorMessage.Add(8012, "FRS err parent to child comm"); /* FRS_ERR_PARENT_TO_CHILD_COMM */ + s_ErrorMessage.Add(8013, "FRS err sysvol populate"); /* FRS_ERR_SYSVOL_POPULATE */ + s_ErrorMessage.Add(8014, "FRS err sysvol populate timeout"); /* FRS_ERR_SYSVOL_POPULATE_TIMEOUT */ + s_ErrorMessage.Add(8015, "FRS err sysvol is busy"); /* FRS_ERR_SYSVOL_IS_BUSY */ + s_ErrorMessage.Add(8016, "FRS err sysvol demote"); /* FRS_ERR_SYSVOL_DEMOTE */ + s_ErrorMessage.Add(8017, "FRS err invalid service parameter"); /* FRS_ERR_INVALID_SERVICE_PARAMETER */ + s_ErrorMessage.Add(8200, "DS not installed"); /* ERROR_DS_NOT_INSTALLED */ + s_ErrorMessage.Add(8201, "DS membership evaluated locally"); /* ERROR_DS_MEMBERSHIP_EVALUATED_LOCALLY */ + s_ErrorMessage.Add(8202, "DS no attribute or value"); /* ERROR_DS_NO_ATTRIBUTE_OR_VALUE */ + s_ErrorMessage.Add(8203, "DS invalid attribute syntax"); /* ERROR_DS_INVALID_ATTRIBUTE_SYNTAX */ + s_ErrorMessage.Add(8204, "DS attribute type undefined"); /* ERROR_DS_ATTRIBUTE_TYPE_UNDEFINED */ + s_ErrorMessage.Add(8205, "DS attribute or value exists"); /* ERROR_DS_ATTRIBUTE_OR_VALUE_EXISTS */ + s_ErrorMessage.Add(8206, "DS busy"); /* ERROR_DS_BUSY */ + s_ErrorMessage.Add(8207, "DS unavailable"); /* ERROR_DS_UNAVAILABLE */ + s_ErrorMessage.Add(8208, "DS no rids allocated"); /* ERROR_DS_NO_RIDS_ALLOCATED */ + s_ErrorMessage.Add(8209, "DS no more rids"); /* ERROR_DS_NO_MORE_RIDS */ + s_ErrorMessage.Add(8210, "DS incorrect role owner"); /* ERROR_DS_INCORRECT_ROLE_OWNER */ + s_ErrorMessage.Add(8211, "DS ridmgr init error"); /* ERROR_DS_RIDMGR_INIT_ERROR */ + s_ErrorMessage.Add(8212, "DS obj class violation"); /* ERROR_DS_OBJ_CLASS_VIOLATION */ + s_ErrorMessage.Add(8213, "DS can't on non leaf"); /* ERROR_DS_CANT_ON_NON_LEAF */ + s_ErrorMessage.Add(8214, "DS can't on rnd"); /* ERROR_DS_CANT_ON_RDN */ + s_ErrorMessage.Add(8215, "DS can't mod obj class"); /* ERROR_DS_CANT_MOD_OBJ_CLASS */ + s_ErrorMessage.Add(8216, "DS cross dom move error"); /* ERROR_DS_CROSS_DOM_MOVE_ERROR */ + s_ErrorMessage.Add(8217, "DS GC not available"); /* ERROR_DS_GC_NOT_AVAILABLE */ + s_ErrorMessage.Add(8218, "Shared policy"); /* ERROR_SHARED_POLICY */ + s_ErrorMessage.Add(8219, "Policy object not found"); /* ERROR_POLICY_OBJECT_NOT_FOUND */ + s_ErrorMessage.Add(8220, "Policy only in DS"); /* ERROR_POLICY_ONLY_IN_DS */ + s_ErrorMessage.Add(8221, "Promotion active"); /* ERROR_PROMOTION_ACTIVE */ + s_ErrorMessage.Add(8222, "No promotion active"); /* ERROR_NO_PROMOTION_ACTIVE */ + s_ErrorMessage.Add(8224, "DS operations error"); /* ERROR_DS_OPERATIONS_ERROR */ + s_ErrorMessage.Add(8225, "DS protocol error"); /* ERROR_DS_PROTOCOL_ERROR */ + s_ErrorMessage.Add(8226, "DS timelimit exceeded"); /* ERROR_DS_TIMELIMIT_EXCEEDED */ + s_ErrorMessage.Add(8227, "DS sizelimit exceeded"); /* ERROR_DS_SIZELIMIT_EXCEEDED */ + s_ErrorMessage.Add(8228, "DS admin limit exceeded"); /* ERROR_DS_ADMIN_LIMIT_EXCEEDED */ + s_ErrorMessage.Add(8229, "DS compare false"); /* ERROR_DS_COMPARE_FALSE */ + s_ErrorMessage.Add(8230, "DS compare true"); /* ERROR_DS_COMPARE_TRUE */ + s_ErrorMessage.Add(8231, "DS auth method not supported"); /* ERROR_DS_AUTH_METHOD_NOT_SUPPORTED */ + s_ErrorMessage.Add(8232, "DS strong auth required"); /* ERROR_DS_STRONG_AUTH_REQUIRED */ + s_ErrorMessage.Add(8233, "DS inappropriate auth"); /* ERROR_DS_INAPPROPRIATE_AUTH */ + s_ErrorMessage.Add(8234, "DS auth unknown"); /* ERROR_DS_AUTH_UNKNOWN */ + s_ErrorMessage.Add(8235, "DS referral"); /* ERROR_DS_REFERRAL */ + s_ErrorMessage.Add(8236, "DS unavailable crit extension"); /* ERROR_DS_UNAVAILABLE_CRIT_EXTENSION */ + s_ErrorMessage.Add(8237, "DS confidentiality required"); /* ERROR_DS_CONFIDENTIALITY_REQUIRED */ + s_ErrorMessage.Add(8238, "DS inappropriate matching"); /* ERROR_DS_INAPPROPRIATE_MATCHING */ + s_ErrorMessage.Add(8239, "DS constraint violation"); /* ERROR_DS_CONSTRAINT_VIOLATION */ + s_ErrorMessage.Add(8240, "DS no such object"); /* ERROR_DS_NO_SUCH_OBJECT */ + s_ErrorMessage.Add(8241, "DS alias problem"); /* ERROR_DS_ALIAS_PROBLEM */ + s_ErrorMessage.Add(8242, "DS invalid dn syntax"); /* ERROR_DS_INVALID_DN_SYNTAX */ + s_ErrorMessage.Add(8243, "DS is leaf"); /* ERROR_DS_IS_LEAF */ + s_ErrorMessage.Add(8244, "DS alias deref problem"); /* ERROR_DS_ALIAS_DEREF_PROBLEM */ + s_ErrorMessage.Add(8245, "DS unwilling to perform"); /* ERROR_DS_UNWILLING_TO_PERFORM */ + s_ErrorMessage.Add(8246, "DS loop detect"); /* ERROR_DS_LOOP_DETECT */ + s_ErrorMessage.Add(8247, "DS naming violation"); /* ERROR_DS_NAMING_VIOLATION */ + s_ErrorMessage.Add(8248, "DS object results too large"); /* ERROR_DS_OBJECT_RESULTS_TOO_LARGE */ + s_ErrorMessage.Add(8249, "DS affects multiple dsas"); /* ERROR_DS_AFFECTS_MULTIPLE_DSAS */ + s_ErrorMessage.Add(8250, "DS server down"); /* ERROR_DS_SERVER_DOWN */ + s_ErrorMessage.Add(8251, "DS local error"); /* ERROR_DS_LOCAL_ERROR */ + s_ErrorMessage.Add(8252, "DS encoding error"); /* ERROR_DS_ENCODING_ERROR */ + s_ErrorMessage.Add(8253, "DS decoding error"); /* ERROR_DS_DECODING_ERROR */ + s_ErrorMessage.Add(8254, "DS filter unknown"); /* ERROR_DS_FILTER_UNKNOWN */ + s_ErrorMessage.Add(8255, "DS param error"); /* ERROR_DS_PARAM_ERROR */ + s_ErrorMessage.Add(8256, "DS not supported"); /* ERROR_DS_NOT_SUPPORTED */ + s_ErrorMessage.Add(8257, "DS no results returned"); /* ERROR_DS_NO_RESULTS_RETURNED */ + s_ErrorMessage.Add(8258, "DS control not found"); /* ERROR_DS_CONTROL_NOT_FOUND */ + s_ErrorMessage.Add(8259, "DS client loop"); /* ERROR_DS_CLIENT_LOOP */ + s_ErrorMessage.Add(8260, "DS referral limit exceeded"); /* ERROR_DS_REFERRAL_LIMIT_EXCEEDED */ + s_ErrorMessage.Add(8261, "DS sort control missing"); /* ERROR_DS_SORT_CONTROL_MISSING */ + s_ErrorMessage.Add(8262, "DS offset range error"); /* ERROR_DS_OFFSET_RANGE_ERROR */ + s_ErrorMessage.Add(8301, "DS root must be nc"); /* ERROR_DS_ROOT_MUST_BE_NC */ + s_ErrorMessage.Add(8302, "DS and replica inhibited"); /* ERROR_DS_ADD_REPLICA_INHIBITED */ + s_ErrorMessage.Add(8303, "DS att not def in schema"); /* ERROR_DS_ATT_NOT_DEF_IN_SCHEMA */ + s_ErrorMessage.Add(8304, "DS max obj size exceeded"); /* ERROR_DS_MAX_OBJ_SIZE_EXCEEDED */ + s_ErrorMessage.Add(8305, "DS obj string name exists"); /* ERROR_DS_OBJ_STRING_NAME_EXISTS */ + s_ErrorMessage.Add(8306, "DS no rdn defined in schema"); /* ERROR_DS_NO_RDN_DEFINED_IN_SCHEMA */ + s_ErrorMessage.Add(8307, "DS rdn doesn't match schema"); /* ERROR_DS_RDN_DOESNT_MATCH_SCHEMA */ + s_ErrorMessage.Add(8308, "DS no requested atts found"); /* ERROR_DS_NO_REQUESTED_ATTS_FOUND */ + s_ErrorMessage.Add(8309, "DS user buffer too small"); /* ERROR_DS_USER_BUFFER_TO_SMALL */ + s_ErrorMessage.Add(8310, "DS att is not on obj"); /* ERROR_DS_ATT_IS_NOT_ON_OBJ */ + s_ErrorMessage.Add(8311, "DS illegal mod operation"); /* ERROR_DS_ILLEGAL_MOD_OPERATION */ + s_ErrorMessage.Add(8312, "DS obj too large"); /* ERROR_DS_OBJ_TOO_LARGE */ + s_ErrorMessage.Add(8313, "DS bad instance type"); /* ERROR_DS_BAD_INSTANCE_TYPE */ + s_ErrorMessage.Add(8314, "DS masterdsa required"); /* ERROR_DS_MASTERDSA_REQUIRED */ + s_ErrorMessage.Add(8315, "DS object class required"); /* ERROR_DS_OBJECT_CLASS_REQUIRED */ + s_ErrorMessage.Add(8316, "DS missing required att"); /* ERROR_DS_MISSING_REQUIRED_ATT */ + s_ErrorMessage.Add(8317, "DS att not def for class"); /* ERROR_DS_ATT_NOT_DEF_FOR_CLASS */ + s_ErrorMessage.Add(8318, "DS att already exists"); /* ERROR_DS_ATT_ALREADY_EXISTS */ + s_ErrorMessage.Add(8320, "DS can't add att values"); /* ERROR_DS_CANT_ADD_ATT_VALUES */ + s_ErrorMessage.Add(8321, "DS single value constraint"); /* ERROR_DS_SINGLE_VALUE_CONSTRAINT */ + s_ErrorMessage.Add(8322, "DS range constraint"); /* ERROR_DS_RANGE_CONSTRAINT */ + s_ErrorMessage.Add(8323, "DS att val already exists"); /* ERROR_DS_ATT_VAL_ALREADY_EXISTS */ + s_ErrorMessage.Add(8324, "DS can't rem missing att"); /* ERROR_DS_CANT_REM_MISSING_ATT */ + s_ErrorMessage.Add(8325, "DS can't rem missing att val"); /* ERROR_DS_CANT_REM_MISSING_ATT_VAL */ + s_ErrorMessage.Add(8326, "DS root can't be subref"); /* ERROR_DS_ROOT_CANT_BE_SUBREF */ + s_ErrorMessage.Add(8327, "DS no chaining"); /* ERROR_DS_NO_CHAINING */ + s_ErrorMessage.Add(8328, "DS no chained eval"); /* ERROR_DS_NO_CHAINED_EVAL */ + s_ErrorMessage.Add(8329, "DS no parent object"); /* ERROR_DS_NO_PARENT_OBJECT */ + s_ErrorMessage.Add(8330, "DS parent is an alias"); /* ERROR_DS_PARENT_IS_AN_ALIAS */ + s_ErrorMessage.Add(8331, "DS can't mix master and reps"); /* ERROR_DS_CANT_MIX_MASTER_AND_REPS */ + s_ErrorMessage.Add(8332, "DS children exist"); /* ERROR_DS_CHILDREN_EXIST */ + s_ErrorMessage.Add(8333, "DS obj not found"); /* ERROR_DS_OBJ_NOT_FOUND */ + s_ErrorMessage.Add(8334, "DS aliased obj missing"); /* ERROR_DS_ALIASED_OBJ_MISSING */ + s_ErrorMessage.Add(8335, "DS bad name syntax"); /* ERROR_DS_BAD_NAME_SYNTAX */ + s_ErrorMessage.Add(8336, "DS alias points to alias"); /* ERROR_DS_ALIAS_POINTS_TO_ALIAS */ + s_ErrorMessage.Add(8337, "DS can't redef alias"); /* ERROR_DS_CANT_DEREF_ALIAS */ + s_ErrorMessage.Add(8338, "DS out of scope"); /* ERROR_DS_OUT_OF_SCOPE */ + s_ErrorMessage.Add(8339, "DS object being removed"); /* ERROR_DS_OBJECT_BEING_REMOVED */ + s_ErrorMessage.Add(8340, "DS can't delete dsa obj"); /* ERROR_DS_CANT_DELETE_DSA_OBJ */ + s_ErrorMessage.Add(8341, "DS generic error"); /* ERROR_DS_GENERIC_ERROR */ + s_ErrorMessage.Add(8342, "DS dsa must be int master"); /* ERROR_DS_DSA_MUST_BE_INT_MASTER */ + s_ErrorMessage.Add(8343, "DS class not dsa"); /* ERROR_DS_CLASS_NOT_DSA */ + s_ErrorMessage.Add(8344, "DS insuff access rights"); /* ERROR_DS_INSUFF_ACCESS_RIGHTS */ + s_ErrorMessage.Add(8345, "DS illegal superior"); /* ERROR_DS_ILLEGAL_SUPERIOR */ + s_ErrorMessage.Add(8346, "DS attribute owned by sam"); /* ERROR_DS_ATTRIBUTE_OWNED_BY_SAM */ + s_ErrorMessage.Add(8347, "DS name too many parts"); /* ERROR_DS_NAME_TOO_MANY_PARTS */ + s_ErrorMessage.Add(8348, "DS name too long"); /* ERROR_DS_NAME_TOO_LONG */ + s_ErrorMessage.Add(8349, "DS name value too long"); /* ERROR_DS_NAME_VALUE_TOO_LONG */ + s_ErrorMessage.Add(8350, "DS name unparseable"); /* ERROR_DS_NAME_UNPARSEABLE */ + s_ErrorMessage.Add(8351, "DS name type unknown"); /* ERROR_DS_NAME_TYPE_UNKNOWN */ + s_ErrorMessage.Add(8352, "DS not an object"); /* ERROR_DS_NOT_AN_OBJECT */ + s_ErrorMessage.Add(8353, "DS sec desc too short"); /* ERROR_DS_SEC_DESC_TOO_SHORT */ + s_ErrorMessage.Add(8354, "DS sec desc invalid"); /* ERROR_DS_SEC_DESC_INVALID */ + s_ErrorMessage.Add(8355, "DS no deleted name"); /* ERROR_DS_NO_DELETED_NAME */ + s_ErrorMessage.Add(8356, "DS subref must have parent"); /* ERROR_DS_SUBREF_MUST_HAVE_PARENT */ + s_ErrorMessage.Add(8357, "DS ncname must be nc"); /* ERROR_DS_NCNAME_MUST_BE_NC */ + s_ErrorMessage.Add(8358, "DS can't add system only"); /* ERROR_DS_CANT_ADD_SYSTEM_ONLY */ + s_ErrorMessage.Add(8359, "DS class must be concrete"); /* ERROR_DS_CLASS_MUST_BE_CONCRETE */ + s_ErrorMessage.Add(8360, "DS invalid dmd"); /* ERROR_DS_INVALID_DMD */ + s_ErrorMessage.Add(8361, "DS obj GUID exists"); /* ERROR_DS_OBJ_GUID_EXISTS */ + s_ErrorMessage.Add(8362, "DS not on backlink"); /* ERROR_DS_NOT_ON_BACKLINK */ + s_ErrorMessage.Add(8363, "DS no crossref for nc"); /* ERROR_DS_NO_CROSSREF_FOR_NC */ + s_ErrorMessage.Add(8364, "DS shutting down"); /* ERROR_DS_SHUTTING_DOWN */ + s_ErrorMessage.Add(8365, "DS unknown operation"); /* ERROR_DS_UNKNOWN_OPERATION */ + s_ErrorMessage.Add(8366, "DS invalid role owner"); /* ERROR_DS_INVALID_ROLE_OWNER */ + s_ErrorMessage.Add(8367, "DS couldn't contact fsmo"); /* ERROR_DS_COULDNT_CONTACT_FSMO */ + s_ErrorMessage.Add(8368, "DS cross nc dn rename"); /* ERROR_DS_CROSS_NC_DN_RENAME */ + s_ErrorMessage.Add(8369, "DS can't mod system only"); /* ERROR_DS_CANT_MOD_SYSTEM_ONLY */ + s_ErrorMessage.Add(8370, "DS replicator only"); /* ERROR_DS_REPLICATOR_ONLY */ + s_ErrorMessage.Add(8371, "DS obj class not defined"); /* ERROR_DS_OBJ_CLASS_NOT_DEFINED */ + s_ErrorMessage.Add(8372, "DS obj class not subclass"); /* ERROR_DS_OBJ_CLASS_NOT_SUBCLASS */ + s_ErrorMessage.Add(8373, "DS name reference invalid"); /* ERROR_DS_NAME_REFERENCE_INVALID */ + s_ErrorMessage.Add(8374, "DS cross ref exists"); /* ERROR_DS_CROSS_REF_EXISTS */ + s_ErrorMessage.Add(8375, "DS can't del master crossref"); /* ERROR_DS_CANT_DEL_MASTER_CROSSREF */ + s_ErrorMessage.Add(8376, "DS subtree notify not nc head"); /* ERROR_DS_SUBTREE_NOTIFY_NOT_NC_HEAD */ + s_ErrorMessage.Add(8377, "DS notify filter too complex"); /* ERROR_DS_NOTIFY_FILTER_TOO_COMPLEX */ + s_ErrorMessage.Add(8378, "DS dup rdn"); /* ERROR_DS_DUP_RDN */ + s_ErrorMessage.Add(8379, "DS dup oid"); /* ERROR_DS_DUP_OID */ + s_ErrorMessage.Add(8380, "DS dup mapi ID"); /* ERROR_DS_DUP_MAPI_ID */ + s_ErrorMessage.Add(8381, "DS dup schema ID GUID"); /* ERROR_DS_DUP_SCHEMA_ID_GUID */ + s_ErrorMessage.Add(8382, "DS dup LDAP display name"); /* ERROR_DS_DUP_LDAP_DISPLAY_NAME */ + s_ErrorMessage.Add(8383, "DS semantic att test"); /* ERROR_DS_SEMANTIC_ATT_TEST */ + s_ErrorMessage.Add(8384, "DS syntax mismatch"); /* ERROR_DS_SYNTAX_MISMATCH */ + s_ErrorMessage.Add(8385, "DS exists in must have"); /* ERROR_DS_EXISTS_IN_MUST_HAVE */ + s_ErrorMessage.Add(8386, "DS exists in may have"); /* ERROR_DS_EXISTS_IN_MAY_HAVE */ + s_ErrorMessage.Add(8387, "DS nonexistent may have"); /* ERROR_DS_NONEXISTENT_MAY_HAVE */ + s_ErrorMessage.Add(8388, "DS nonexistent must have"); /* ERROR_DS_NONEXISTENT_MUST_HAVE */ + s_ErrorMessage.Add(8389, "DS aux cls test fail"); /* ERROR_DS_AUX_CLS_TEST_FAIL */ + s_ErrorMessage.Add(8390, "DS nonexistent poss sup"); /* ERROR_DS_NONEXISTENT_POSS_SUP */ + s_ErrorMessage.Add(8391, "DS sub cls test fail"); /* ERROR_DS_SUB_CLS_TEST_FAIL */ + s_ErrorMessage.Add(8392, "DS bad rdn att ID syntax"); /* ERROR_DS_BAD_RDN_ATT_ID_SYNTAX */ + s_ErrorMessage.Add(8393, "DS exists in aux cls"); /* ERROR_DS_EXISTS_IN_AUX_CLS */ + s_ErrorMessage.Add(8394, "DS exists in sub cls"); /* ERROR_DS_EXISTS_IN_SUB_CLS */ + s_ErrorMessage.Add(8395, "DS exists in poss sup"); /* ERROR_DS_EXISTS_IN_POSS_SUP */ + s_ErrorMessage.Add(8396, "DS recalcschema failed"); /* ERROR_DS_RECALCSCHEMA_FAILED */ + s_ErrorMessage.Add(8397, "DS tree delete not finished"); /* ERROR_DS_TREE_DELETE_NOT_FINISHED */ + s_ErrorMessage.Add(8398, "DS can't delete"); /* ERROR_DS_CANT_DELETE */ + s_ErrorMessage.Add(8399, "DS att schema req ID"); /* ERROR_DS_ATT_SCHEMA_REQ_ID */ + s_ErrorMessage.Add(8400, "DS bad att schema syntax"); /* ERROR_DS_BAD_ATT_SCHEMA_SYNTAX */ + s_ErrorMessage.Add(8401, "DS can't cache att"); /* ERROR_DS_CANT_CACHE_ATT */ + s_ErrorMessage.Add(8402, "DS can't cache class"); /* ERROR_DS_CANT_CACHE_CLASS */ + s_ErrorMessage.Add(8403, "DS can't remove att cache"); /* ERROR_DS_CANT_REMOVE_ATT_CACHE */ + s_ErrorMessage.Add(8404, "DS can't remove class cache"); /* ERROR_DS_CANT_REMOVE_CLASS_CACHE */ + s_ErrorMessage.Add(8405, "DS can't retrieve DN"); /* ERROR_DS_CANT_RETRIEVE_DN */ + s_ErrorMessage.Add(8406, "DS missing supref"); /* ERROR_DS_MISSING_SUPREF */ + s_ErrorMessage.Add(8407, "DS can't retrieve instance"); /* ERROR_DS_CANT_RETRIEVE_INSTANCE */ + s_ErrorMessage.Add(8408, "DS code inconsistency"); /* ERROR_DS_CODE_INCONSISTENCY */ + s_ErrorMessage.Add(8409, "DS database error"); /* ERROR_DS_DATABASE_ERROR */ + s_ErrorMessage.Add(8410, "DS governsid missing"); /* ERROR_DS_GOVERNSID_MISSING */ + s_ErrorMessage.Add(8411, "DS missing expected att"); /* ERROR_DS_MISSING_EXPECTED_ATT */ + s_ErrorMessage.Add(8412, "DS ncname missing cr ref"); /* ERROR_DS_NCNAME_MISSING_CR_REF */ + s_ErrorMessage.Add(8413, "DS security checking error"); /* ERROR_DS_SECURITY_CHECKING_ERROR */ + s_ErrorMessage.Add(8414, "DS schema not loaded"); /* ERROR_DS_SCHEMA_NOT_LOADED */ + s_ErrorMessage.Add(8415, "DS schema alloc failed"); /* ERROR_DS_SCHEMA_ALLOC_FAILED */ + s_ErrorMessage.Add(8416, "DS att schema req syntax"); /* ERROR_DS_ATT_SCHEMA_REQ_SYNTAX */ + s_ErrorMessage.Add(8417, "DS gcverify error"); /* ERROR_DS_GCVERIFY_ERROR */ + s_ErrorMessage.Add(8418, "DS dra schema mismatch"); /* ERROR_DS_DRA_SCHEMA_MISMATCH */ + s_ErrorMessage.Add(8419, "DS can't find dsa obj"); /* ERROR_DS_CANT_FIND_DSA_OBJ */ + s_ErrorMessage.Add(8420, "DS can't find expected nc"); /* ERROR_DS_CANT_FIND_EXPECTED_NC */ + s_ErrorMessage.Add(8421, "DS can't find nc in cache"); /* ERROR_DS_CANT_FIND_NC_IN_CACHE */ + s_ErrorMessage.Add(8422, "DS can't retrieve child"); /* ERROR_DS_CANT_RETRIEVE_CHILD */ + s_ErrorMessage.Add(8423, "DS security illegal modify"); /* ERROR_DS_SECURITY_ILLEGAL_MODIFY */ + s_ErrorMessage.Add(8424, "DS can't replace hidden rec"); /* ERROR_DS_CANT_REPLACE_HIDDEN_REC */ + s_ErrorMessage.Add(8425, "DS bad hierarchy file"); /* ERROR_DS_BAD_HIERARCHY_FILE */ + s_ErrorMessage.Add(8426, "DS build hierarchy table failed"); /* ERROR_DS_BUILD_HIERARCHY_TABLE_FAILED */ + s_ErrorMessage.Add(8427, "DS config param missing"); /* ERROR_DS_CONFIG_PARAM_MISSING */ + s_ErrorMessage.Add(8428, "DS counting ab indices failed"); /* ERROR_DS_COUNTING_AB_INDICES_FAILED */ + s_ErrorMessage.Add(8429, "DS hierarchy table malloc failed"); /* ERROR_DS_HIERARCHY_TABLE_MALLOC_FAILED */ + s_ErrorMessage.Add(8430, "DS internal failure"); /* ERROR_DS_INTERNAL_FAILURE */ + s_ErrorMessage.Add(8431, "DS unknown error"); /* ERROR_DS_UNKNOWN_ERROR */ + s_ErrorMessage.Add(8432, "DS root requires class top"); /* ERROR_DS_ROOT_REQUIRES_CLASS_TOP */ + s_ErrorMessage.Add(8433, "DS refusing fmso roles"); /* ERROR_DS_REFUSING_FSMO_ROLES */ + s_ErrorMessage.Add(8434, "DS missing fmso settings"); /* ERROR_DS_MISSING_FSMO_SETTINGS */ + s_ErrorMessage.Add(8435, "DS unable to surrender roles"); /* ERROR_DS_UNABLE_TO_SURRENDER_ROLES */ + s_ErrorMessage.Add(8436, "DS dra generic"); /* ERROR_DS_DRA_GENERIC */ + s_ErrorMessage.Add(8437, "DS dra invalid parameter"); /* ERROR_DS_DRA_INVALID_PARAMETER */ + s_ErrorMessage.Add(8438, "DS dra busy"); /* ERROR_DS_DRA_BUSY */ + s_ErrorMessage.Add(8439, "DS dra bad dn"); /* ERROR_DS_DRA_BAD_DN */ + s_ErrorMessage.Add(8440, "DS dra bad nc"); /* ERROR_DS_DRA_BAD_NC */ + s_ErrorMessage.Add(8441, "DS dra dn exists"); /* ERROR_DS_DRA_DN_EXISTS */ + s_ErrorMessage.Add(8442, "DS dra internal error"); /* ERROR_DS_DRA_INTERNAL_ERROR */ + s_ErrorMessage.Add(8443, "DS dra inconsistent dit"); /* ERROR_DS_DRA_INCONSISTENT_DIT */ + s_ErrorMessage.Add(8444, "DS dra connection failed"); /* ERROR_DS_DRA_CONNECTION_FAILED */ + s_ErrorMessage.Add(8445, "DS dra bad instance type"); /* ERROR_DS_DRA_BAD_INSTANCE_TYPE */ + s_ErrorMessage.Add(8446, "DS dra out of mem"); /* ERROR_DS_DRA_OUT_OF_MEM */ + s_ErrorMessage.Add(8447, "DS dra mail problem"); /* ERROR_DS_DRA_MAIL_PROBLEM */ + s_ErrorMessage.Add(8448, "DS dra ref already exists"); /* ERROR_DS_DRA_REF_ALREADY_EXISTS */ + s_ErrorMessage.Add(8449, "DS dra ref not found"); /* ERROR_DS_DRA_REF_NOT_FOUND */ + s_ErrorMessage.Add(8450, "DS dra obj is rep source"); /* ERROR_DS_DRA_OBJ_IS_REP_SOURCE */ + s_ErrorMessage.Add(8451, "DS dra db error"); /* ERROR_DS_DRA_DB_ERROR */ + s_ErrorMessage.Add(8452, "DS dra no replica"); /* ERROR_DS_DRA_NO_REPLICA */ + s_ErrorMessage.Add(8453, "DS dra access denied"); /* ERROR_DS_DRA_ACCESS_DENIED */ + s_ErrorMessage.Add(8454, "DS dra not supported"); /* ERROR_DS_DRA_NOT_SUPPORTED */ + s_ErrorMessage.Add(8455, "DS dra RPC cancelled"); /* ERROR_DS_DRA_RPC_CANCELLED */ + s_ErrorMessage.Add(8456, "DS dra source disabled"); /* ERROR_DS_DRA_SOURCE_DISABLED */ + s_ErrorMessage.Add(8457, "DS dra sink disabled"); /* ERROR_DS_DRA_SINK_DISABLED */ + s_ErrorMessage.Add(8458, "DS dra name collision"); /* ERROR_DS_DRA_NAME_COLLISION */ + s_ErrorMessage.Add(8459, "DS dra source reinstalled"); /* ERROR_DS_DRA_SOURCE_REINSTALLED */ + s_ErrorMessage.Add(8460, "DS dra missing parent"); /* ERROR_DS_DRA_MISSING_PARENT */ + s_ErrorMessage.Add(8461, "DS dra preempted"); /* ERROR_DS_DRA_PREEMPTED */ + s_ErrorMessage.Add(8462, "DS dra abandon sync"); /* ERROR_DS_DRA_ABANDON_SYNC */ + s_ErrorMessage.Add(8463, "DS dra shutdown"); /* ERROR_DS_DRA_SHUTDOWN */ + s_ErrorMessage.Add(8464, "DS dra incompatible partial set"); /* ERROR_DS_DRA_INCOMPATIBLE_PARTIAL_SET */ + s_ErrorMessage.Add(8465, "DS dra source is partial replica"); /* ERROR_DS_DRA_SOURCE_IS_PARTIAL_REPLICA */ + s_ErrorMessage.Add(8466, "DS dra extn connection failed"); /* ERROR_DS_DRA_EXTN_CONNECTION_FAILED */ + s_ErrorMessage.Add(8467, "DS install schema mismatch"); /* ERROR_DS_INSTALL_SCHEMA_MISMATCH */ + s_ErrorMessage.Add(8468, "DS dup link ID"); /* ERROR_DS_DUP_LINK_ID */ + s_ErrorMessage.Add(8469, "DS name error resolving"); /* ERROR_DS_NAME_ERROR_RESOLVING */ + s_ErrorMessage.Add(8470, "DS name error not found"); /* ERROR_DS_NAME_ERROR_NOT_FOUND */ + s_ErrorMessage.Add(8471, "DS name error not unique"); /* ERROR_DS_NAME_ERROR_NOT_UNIQUE */ + s_ErrorMessage.Add(8472, "DS name error no mapping"); /* ERROR_DS_NAME_ERROR_NO_MAPPING */ + s_ErrorMessage.Add(8473, "DS name error domain only"); /* ERROR_DS_NAME_ERROR_DOMAIN_ONLY */ + s_ErrorMessage.Add(8474, "DS name error no syntactical mapping"); /* ERROR_DS_NAME_ERROR_NO_SYNTACTICAL_MAPPING */ + s_ErrorMessage.Add(8475, "DS constructed att mod"); /* ERROR_DS_CONSTRUCTED_ATT_MOD */ + s_ErrorMessage.Add(8476, "DS wrong om obj class"); /* ERROR_DS_WRONG_OM_OBJ_CLASS */ + s_ErrorMessage.Add(8477, "DS dra repl pending"); /* ERROR_DS_DRA_REPL_PENDING */ + s_ErrorMessage.Add(8478, "DS ds required"); /* ERROR_DS_DS_REQUIRED */ + s_ErrorMessage.Add(8479, "DS invalid LDAP display name"); /* ERROR_DS_INVALID_LDAP_DISPLAY_NAME */ + s_ErrorMessage.Add(8480, "DS non base search"); /* ERROR_DS_NON_BASE_SEARCH */ + s_ErrorMessage.Add(8481, "DS can't retrieve atts"); /* ERROR_DS_CANT_RETRIEVE_ATTS */ + s_ErrorMessage.Add(8482, "DS backlink without link"); /* ERROR_DS_BACKLINK_WITHOUT_LINK */ + s_ErrorMessage.Add(8483, "DS epoch mismatch"); /* ERROR_DS_EPOCH_MISMATCH */ + s_ErrorMessage.Add(8484, "DS src name mismatch"); /* ERROR_DS_SRC_NAME_MISMATCH */ + s_ErrorMessage.Add(8485, "DS src and dst nc identical"); /* ERROR_DS_SRC_AND_DST_NC_IDENTICAL */ + s_ErrorMessage.Add(8486, "DS dst nc mismatch"); /* ERROR_DS_DST_NC_MISMATCH */ + s_ErrorMessage.Add(8487, "DS not authoritive for dst nc"); /* ERROR_DS_NOT_AUTHORITIVE_FOR_DST_NC */ + s_ErrorMessage.Add(8488, "DS src GUID mismatch"); /* ERROR_DS_SRC_GUID_MISMATCH */ + s_ErrorMessage.Add(8489, "DS can't move deleted object"); /* ERROR_DS_CANT_MOVE_DELETED_OBJECT */ + s_ErrorMessage.Add(8490, "DS pdc operation in progress"); /* ERROR_DS_PDC_OPERATION_IN_PROGRESS */ + s_ErrorMessage.Add(8491, "DS cross domain cleanup reqd"); /* ERROR_DS_CROSS_DOMAIN_CLEANUP_REQD */ + s_ErrorMessage.Add(8492, "DS illegal xdom move operation"); /* ERROR_DS_ILLEGAL_XDOM_MOVE_OPERATION */ + s_ErrorMessage.Add(8493, "DS can't with acct group membershps"); /* ERROR_DS_CANT_WITH_ACCT_GROUP_MEMBERSHPS */ + s_ErrorMessage.Add(8494, "DS nc must have nc parent"); /* ERROR_DS_NC_MUST_HAVE_NC_PARENT */ + s_ErrorMessage.Add(8496, "DS dst domain not native"); /* ERROR_DS_DST_DOMAIN_NOT_NATIVE */ + s_ErrorMessage.Add(8497, "DS missing infrastructure container"); /* ERROR_DS_MISSING_INFRASTRUCTURE_CONTAINER */ + s_ErrorMessage.Add(8498, "DS can't move account group"); /* ERROR_DS_CANT_MOVE_ACCOUNT_GROUP */ + s_ErrorMessage.Add(8499, "DS can't move resource group"); /* ERROR_DS_CANT_MOVE_RESOURCE_GROUP */ + s_ErrorMessage.Add(8500, "DS invalid search flag"); /* ERROR_DS_INVALID_SEARCH_FLAG */ + s_ErrorMessage.Add(8501, "DS no tree delete above nc"); /* ERROR_DS_NO_TREE_DELETE_ABOVE_NC */ + s_ErrorMessage.Add(8502, "DS couldn't lock tree for delete"); /* ERROR_DS_COULDNT_LOCK_TREE_FOR_DELETE */ + s_ErrorMessage.Add(8503, "DS couldn't identify objects for tree delete"); /* ERROR_DS_COULDNT_IDENTIFY_OBJECTS_FOR_TREE_DELETE */ + s_ErrorMessage.Add(8504, "DS sam init failure"); /* ERROR_DS_SAM_INIT_FAILURE */ + s_ErrorMessage.Add(8505, "DS sensitive group violation"); /* ERROR_DS_SENSITIVE_GROUP_VIOLATION */ + s_ErrorMessage.Add(8506, "DS can't mod primarygroupid"); /* ERROR_DS_CANT_MOD_PRIMARYGROUPID */ + s_ErrorMessage.Add(8507, "DS illegal base schema mod"); /* ERROR_DS_ILLEGAL_BASE_SCHEMA_MOD */ + s_ErrorMessage.Add(8508, "DS nonsafe schema change"); /* ERROR_DS_NONSAFE_SCHEMA_CHANGE */ + s_ErrorMessage.Add(8509, "DS schema update disallowed"); /* ERROR_DS_SCHEMA_UPDATE_DISALLOWED */ + s_ErrorMessage.Add(8510, "DS can't create under schema"); /* ERROR_DS_CANT_CREATE_UNDER_SCHEMA */ + s_ErrorMessage.Add(8511, "DS install no src sch version"); /* ERROR_DS_INSTALL_NO_SRC_SCH_VERSION */ + s_ErrorMessage.Add(8512, "DS install no sch version in inifile"); /* ERROR_DS_INSTALL_NO_SCH_VERSION_IN_INIFILE */ + s_ErrorMessage.Add(8513, "DS invalid group type"); /* ERROR_DS_INVALID_GROUP_TYPE */ + s_ErrorMessage.Add(8514, "DS no nest globalgroup in mixeddomain"); /* ERROR_DS_NO_NEST_GLOBALGROUP_IN_MIXEDDOMAIN */ + s_ErrorMessage.Add(8515, "DS no nest localgroup in mixeddomain"); /* ERROR_DS_NO_NEST_LOCALGROUP_IN_MIXEDDOMAIN */ + s_ErrorMessage.Add(8516, "DS global can't have local member"); /* ERROR_DS_GLOBAL_CANT_HAVE_LOCAL_MEMBER */ + s_ErrorMessage.Add(8517, "DS global can't have universal member"); /* ERROR_DS_GLOBAL_CANT_HAVE_UNIVERSAL_MEMBER */ + s_ErrorMessage.Add(8518, "DS universal can't have local member"); /* ERROR_DS_UNIVERSAL_CANT_HAVE_LOCAL_MEMBER */ + s_ErrorMessage.Add(8519, "DS global can't have crossdomain member"); /* ERROR_DS_GLOBAL_CANT_HAVE_CROSSDOMAIN_MEMBER */ + s_ErrorMessage.Add(8520, "DS local can't have crossdomain local member"); /* ERROR_DS_LOCAL_CANT_HAVE_CROSSDOMAIN_LOCAL_MEMBER */ + s_ErrorMessage.Add(8521, "DS have primary members"); /* ERROR_DS_HAVE_PRIMARY_MEMBERS */ + s_ErrorMessage.Add(8522, "DS string sd conversion failed"); /* ERROR_DS_STRING_SD_CONVERSION_FAILED */ + s_ErrorMessage.Add(8523, "DS naming master gc"); /* ERROR_DS_NAMING_MASTER_GC */ + s_ErrorMessage.Add(8524, "DS lookup failure"); /* ERROR_DS_LOOKUP_FAILURE */ + s_ErrorMessage.Add(8525, "DS couldn't update spns"); /* ERROR_DS_COULDNT_UPDATE_SPNS */ + s_ErrorMessage.Add(8526, "DS can't retrieve sd"); /* ERROR_DS_CANT_RETRIEVE_SD */ + s_ErrorMessage.Add(8527, "DS key not unique"); /* ERROR_DS_KEY_NOT_UNIQUE */ + s_ErrorMessage.Add(8528, "DS wrong linked att syntax"); /* ERROR_DS_WRONG_LINKED_ATT_SYNTAX */ + s_ErrorMessage.Add(8529, "DS sam need bootkey password"); /* ERROR_DS_SAM_NEED_BOOTKEY_PASSWORD */ + s_ErrorMessage.Add(8530, "DS sam need bootkey floppy"); /* ERROR_DS_SAM_NEED_BOOTKEY_FLOPPY */ + s_ErrorMessage.Add(8531, "DS can't start"); /* ERROR_DS_CANT_START */ + s_ErrorMessage.Add(8532, "DS init failure"); /* ERROR_DS_INIT_FAILURE */ + s_ErrorMessage.Add(8533, "DS no pkt privacy on connection"); /* ERROR_DS_NO_PKT_PRIVACY_ON_CONNECTION */ + s_ErrorMessage.Add(8534, "DS source domain in forest"); /* ERROR_DS_SOURCE_DOMAIN_IN_FOREST */ + s_ErrorMessage.Add(8535, "DS destination domain not in forest"); /* ERROR_DS_DESTINATION_DOMAIN_NOT_IN_FOREST */ + s_ErrorMessage.Add(8536, "DS destination auditing not enabled"); /* ERROR_DS_DESTINATION_AUDITING_NOT_ENABLED */ + s_ErrorMessage.Add(8537, "DS can't find dc for src domain"); /* ERROR_DS_CANT_FIND_DC_FOR_SRC_DOMAIN */ + s_ErrorMessage.Add(8538, "DS src obj not group or user"); /* ERROR_DS_SRC_OBJ_NOT_GROUP_OR_USER */ + s_ErrorMessage.Add(8539, "DS src sid exists in forest"); /* ERROR_DS_SRC_SID_EXISTS_IN_FOREST */ + s_ErrorMessage.Add(8540, "DS src and dst object class mismatch"); /* ERROR_DS_SRC_AND_DST_OBJECT_CLASS_MISMATCH */ + s_ErrorMessage.Add(8541, "Sam init failure"); /* ERROR_SAM_INIT_FAILURE */ + s_ErrorMessage.Add(8542, "DS dra schema info ship"); /* ERROR_DS_DRA_SCHEMA_INFO_SHIP */ + s_ErrorMessage.Add(8543, "DS dra schema conflict"); /* ERROR_DS_DRA_SCHEMA_CONFLICT */ + s_ErrorMessage.Add(8544, "DS dra earlier schema conflict"); /* ERROR_DS_DRA_EARLIER_SCHEMA_CONLICT */ + s_ErrorMessage.Add(8545, "DS dra obj nc mismatch"); /* ERROR_DS_DRA_OBJ_NC_MISMATCH */ + s_ErrorMessage.Add(8546, "DS nc still has dsas"); /* ERROR_DS_NC_STILL_HAS_DSAS */ + s_ErrorMessage.Add(8547, "DS gc required"); /* ERROR_DS_GC_REQUIRED */ + s_ErrorMessage.Add(8548, "DS local member of local only"); /* ERROR_DS_LOCAL_MEMBER_OF_LOCAL_ONLY */ + s_ErrorMessage.Add(8549, "DS no fpo in universal groups"); /* ERROR_DS_NO_FPO_IN_UNIVERSAL_GROUPS */ + s_ErrorMessage.Add(8550, "DS can't add to gc"); /* ERROR_DS_CANT_ADD_TO_GC */ + s_ErrorMessage.Add(8551, "DS no checkpoint with pdc"); /* ERROR_DS_NO_CHECKPOINT_WITH_PDC */ + s_ErrorMessage.Add(8552, "DS source auditing not enabled"); /* ERROR_DS_SOURCE_AUDITING_NOT_ENABLED */ + s_ErrorMessage.Add(8553, "DS can't create in nondomain nc"); /* ERROR_DS_CANT_CREATE_IN_NONDOMAIN_NC */ + s_ErrorMessage.Add(8554, "DS invalid name for spn"); /* ERROR_DS_INVALID_NAME_FOR_SPN */ + s_ErrorMessage.Add(8555, "DS filter uses constructed attrs"); /* ERROR_DS_FILTER_USES_CONTRUCTED_ATTRS */ + s_ErrorMessage.Add(8556, "DS unicodepwd not in quotes"); /* ERROR_DS_UNICODEPWD_NOT_IN_QUOTES */ + s_ErrorMessage.Add(8557, "DS machine account quota exceeded"); /* ERROR_DS_MACHINE_ACCOUNT_QUOTA_EXCEEDED */ + s_ErrorMessage.Add(8558, "DS must be run on dst dc"); /* ERROR_DS_MUST_BE_RUN_ON_DST_DC */ + s_ErrorMessage.Add(8559, "DS src dc must be sp4 or greater"); /* ERROR_DS_SRC_DC_MUST_BE_SP4_OR_GREATER */ + s_ErrorMessage.Add(8560, "DS can't tree delete critical obj"); /* ERROR_DS_CANT_TREE_DELETE_CRITICAL_OBJ */ + s_ErrorMessage.Add(8561, "DS init failure console"); /* ERROR_DS_INIT_FAILURE_CONSOLE */ + s_ErrorMessage.Add(8562, "DS sam init failure console"); /* ERROR_DS_SAM_INIT_FAILURE_CONSOLE */ + s_ErrorMessage.Add(8563, "DS forest version too high"); /* ERROR_DS_FOREST_VERSION_TOO_HIGH */ + s_ErrorMessage.Add(8564, "DS domain version too high"); /* ERROR_DS_DOMAIN_VERSION_TOO_HIGH */ + s_ErrorMessage.Add(8565, "DS forest version too low"); /* ERROR_DS_FOREST_VERSION_TOO_LOW */ + s_ErrorMessage.Add(8566, "DS domain version too low"); /* ERROR_DS_DOMAIN_VERSION_TOO_LOW */ + s_ErrorMessage.Add(8567, "DS incompatible version"); /* ERROR_DS_INCOMPATIBLE_VERSION */ + s_ErrorMessage.Add(8568, "DS low dsa version"); /* ERROR_DS_LOW_DSA_VERSION */ + s_ErrorMessage.Add(8569, "DS no behaviour version in mixeddomain"); /* ERROR_DS_NO_BEHAVIOR_VERSION_IN_MIXEDDOMAIN */ + s_ErrorMessage.Add(8570, "DS not supported sort order"); /* ERROR_DS_NOT_SUPPORTED_SORT_ORDER */ + s_ErrorMessage.Add(8571, "DS name not unique"); /* ERROR_DS_NAME_NOT_UNIQUE */ + s_ErrorMessage.Add(8572, "DS machine account created prent4"); /* ERROR_DS_MACHINE_ACCOUNT_CREATED_PRENT4 */ + s_ErrorMessage.Add(8573, "DS out of version store"); /* ERROR_DS_OUT_OF_VERSION_STORE */ + s_ErrorMessage.Add(8574, "DS incompatible controls used"); /* ERROR_DS_INCOMPATIBLE_CONTROLS_USED */ + s_ErrorMessage.Add(8575, "DS no ref domain"); /* ERROR_DS_NO_REF_DOMAIN */ + s_ErrorMessage.Add(8576, "DS reserved link ID"); /* ERROR_DS_RESERVED_LINK_ID */ + s_ErrorMessage.Add(8577, "DS link ID not available"); /* ERROR_DS_LINK_ID_NOT_AVAILABLE */ + s_ErrorMessage.Add(8578, "DS ag can't have universal member"); /* ERROR_DS_AG_CANT_HAVE_UNIVERSAL_MEMBER */ + s_ErrorMessage.Add(8579, "DS modifydn disallowed by instance type"); /* ERROR_DS_MODIFYDN_DISALLOWED_BY_INSTANCE_TYPE */ + s_ErrorMessage.Add(8580, "DS no object move in schema nc"); /* ERROR_DS_NO_OBJECT_MOVE_IN_SCHEMA_NC */ + s_ErrorMessage.Add(8581, "DS modifydn disallowed by flag"); /* ERROR_DS_MODIFYDN_DISALLOWED_BY_FLAG */ + s_ErrorMessage.Add(8582, "DS modifydn wrong grandparent"); /* ERROR_DS_MODIFYDN_WRONG_GRANDPARENT */ + s_ErrorMessage.Add(8583, "DS name error trust referral"); /* ERROR_DS_NAME_ERROR_TRUST_REFERRAL */ + s_ErrorMessage.Add(8584, "Not supported on standard server"); /* ERROR_NOT_SUPPORTED_ON_STANDARD_SERVER */ + s_ErrorMessage.Add(8585, "DS can't access remote part of ad"); /* ERROR_DS_CANT_ACCESS_REMOTE_PART_OF_AD */ + s_ErrorMessage.Add(8586, "DS cr impossible to validate"); /* ERROR_DS_CR_IMPOSSIBLE_TO_VALIDATE */ + s_ErrorMessage.Add(8587, "DS thread limit exceeded"); /* ERROR_DS_THREAD_LIMIT_EXCEEDED */ + s_ErrorMessage.Add(8588, "DS not closest"); /* ERROR_DS_NOT_CLOSEST */ + s_ErrorMessage.Add(8589, "DS can't derive spn without server ref"); /* ERROR_DS_CANT_DERIVE_SPN_WITHOUT_SERVER_REF */ + s_ErrorMessage.Add(8590, "DS single user mode failed"); /* ERROR_DS_SINGLE_USER_MODE_FAILED */ + s_ErrorMessage.Add(8591, "DS ntdscript syntax error"); /* ERROR_DS_NTDSCRIPT_SYNTAX_ERROR */ + s_ErrorMessage.Add(8592, "DS ntdscript process error"); /* ERROR_DS_NTDSCRIPT_PROCESS_ERROR */ + s_ErrorMessage.Add(8593, "DS different repl epochs"); /* ERROR_DS_DIFFERENT_REPL_EPOCHS */ + s_ErrorMessage.Add(8594, "DS drs extensions changed"); /* ERROR_DS_DRS_EXTENSIONS_CHANGED */ + s_ErrorMessage.Add(8595, "DS replica set change not allowed on disabled cr"); /* ERROR_DS_REPLICA_SET_CHANGE_NOT_ALLOWED_ON_DISABLED_CR */ + s_ErrorMessage.Add(8596, "DS no msds intid"); /* ERROR_DS_NO_MSDS_INTID */ + s_ErrorMessage.Add(8597, "DS dup msds intid"); /* ERROR_DS_DUP_MSDS_INTID */ + s_ErrorMessage.Add(8598, "DS exists in rdnattid"); /* ERROR_DS_EXISTS_IN_RDNATTID */ + s_ErrorMessage.Add(8599, "DS authorisation failed"); /* ERROR_DS_AUTHORIZATION_FAILED */ + s_ErrorMessage.Add(8600, "DS invalid script"); /* ERROR_DS_INVALID_SCRIPT */ + s_ErrorMessage.Add(8601, "DS remote crossref op failed"); /* ERROR_DS_REMOTE_CROSSREF_OP_FAILED */ + s_ErrorMessage.Add(9001, "DNS error rcode format error"); /* DNS_ERROR_RCODE_FORMAT_ERROR */ + s_ErrorMessage.Add(9002, "DNS error rcode server failure"); /* DNS_ERROR_RCODE_SERVER_FAILURE */ + s_ErrorMessage.Add(9003, "DNS error rcode name error"); /* DNS_ERROR_RCODE_NAME_ERROR */ + s_ErrorMessage.Add(9004, "DNS error rcode not implemented"); /* DNS_ERROR_RCODE_NOT_IMPLEMENTED */ + s_ErrorMessage.Add(9005, "DNS error rcode refused"); /* DNS_ERROR_RCODE_REFUSED */ + s_ErrorMessage.Add(9006, "DNS error rcode yxdomain"); /* DNS_ERROR_RCODE_YXDOMAIN */ + s_ErrorMessage.Add(9007, "DNS error rcode yxrrset"); /* DNS_ERROR_RCODE_YXRRSET */ + s_ErrorMessage.Add(9008, "DNS error rcode nxrrset"); /* DNS_ERROR_RCODE_NXRRSET */ + s_ErrorMessage.Add(9009, "DNS error rcode notauth"); /* DNS_ERROR_RCODE_NOTAUTH */ + s_ErrorMessage.Add(9010, "DNS error rcode notzone"); /* DNS_ERROR_RCODE_NOTZONE */ + s_ErrorMessage.Add(9016, "DNS error rcode badsig"); /* DNS_ERROR_RCODE_BADSIG */ + s_ErrorMessage.Add(9017, "DNS error rcode badkey"); /* DNS_ERROR_RCODE_BADKEY */ + s_ErrorMessage.Add(9018, "DNS error rcode badtime"); /* DNS_ERROR_RCODE_BADTIME */ + s_ErrorMessage.Add(9501, "DNS info no records"); /* DNS_INFO_NO_RECORDS */ + s_ErrorMessage.Add(9502, "DNS error bad packet"); /* DNS_ERROR_BAD_PACKET */ + s_ErrorMessage.Add(9503, "DNS error no packet"); /* DNS_ERROR_NO_PACKET */ + s_ErrorMessage.Add(9504, "DNS error rcode"); /* DNS_ERROR_RCODE */ + s_ErrorMessage.Add(9505, "DNS error unsecure packet"); /* DNS_ERROR_UNSECURE_PACKET */ + s_ErrorMessage.Add(9551, "DNS error invalid type"); /* DNS_ERROR_INVALID_TYPE */ + s_ErrorMessage.Add(9552, "DNS error invalid IP address"); /* DNS_ERROR_INVALID_IP_ADDRESS */ + s_ErrorMessage.Add(9553, "DNS error invalid property"); /* DNS_ERROR_INVALID_PROPERTY */ + s_ErrorMessage.Add(9554, "DNS error try again later"); /* DNS_ERROR_TRY_AGAIN_LATER */ + s_ErrorMessage.Add(9555, "DNS error not unique"); /* DNS_ERROR_NOT_UNIQUE */ + s_ErrorMessage.Add(9556, "DNS error non RFC name"); /* DNS_ERROR_NON_RFC_NAME */ + s_ErrorMessage.Add(9557, "DNS status FQDN"); /* DNS_STATUS_FQDN */ + s_ErrorMessage.Add(9558, "DNS status dotted name"); /* DNS_STATUS_DOTTED_NAME */ + s_ErrorMessage.Add(9559, "DNS status single part name"); /* DNS_STATUS_SINGLE_PART_NAME */ + s_ErrorMessage.Add(9560, "DNS error invalid name char"); /* DNS_ERROR_INVALID_NAME_CHAR */ + s_ErrorMessage.Add(9561, "DNS error numeric name"); /* DNS_ERROR_NUMERIC_NAME */ + s_ErrorMessage.Add(9562, "DNS error not allowed on root server"); /* DNS_ERROR_NOT_ALLOWED_ON_ROOT_SERVER */ + s_ErrorMessage.Add(9601, "DNS error zone does not exist"); /* DNS_ERROR_ZONE_DOES_NOT_EXIST */ + s_ErrorMessage.Add(9602, "DNS error not zone info"); /* DNS_ERROR_NO_ZONE_INFO */ + s_ErrorMessage.Add(9603, "DNS error invalid zone operation"); /* DNS_ERROR_INVALID_ZONE_OPERATION */ + s_ErrorMessage.Add(9604, "DNS error zone configuration error"); /* DNS_ERROR_ZONE_CONFIGURATION_ERROR */ + s_ErrorMessage.Add(9605, "DNS error zone has not SOA record"); /* DNS_ERROR_ZONE_HAS_NO_SOA_RECORD */ + s_ErrorMessage.Add(9606, "DNS error zone has no NS records"); /* DNS_ERROR_ZONE_HAS_NO_NS_RECORDS */ + s_ErrorMessage.Add(9607, "DNS error zone locked"); /* DNS_ERROR_ZONE_LOCKED */ + s_ErrorMessage.Add(9608, "DNS error zone creation failed"); /* DNS_ERROR_ZONE_CREATION_FAILED */ + s_ErrorMessage.Add(9609, "DNS error zone already exists"); /* DNS_ERROR_ZONE_ALREADY_EXISTS */ + s_ErrorMessage.Add(9610, "DNS error autozone already exists"); /* DNS_ERROR_AUTOZONE_ALREADY_EXISTS */ + s_ErrorMessage.Add(9611, "DNS error invalid zone type"); /* DNS_ERROR_INVALID_ZONE_TYPE */ + s_ErrorMessage.Add(9612, "DNS error secondary requires master IP"); /* DNS_ERROR_SECONDARY_REQUIRES_MASTER_IP */ + s_ErrorMessage.Add(9613, "DNS error zone not secondary"); /* DNS_ERROR_ZONE_NOT_SECONDARY */ + s_ErrorMessage.Add(9614, "DNS error need secondary addresses"); /* DNS_ERROR_NEED_SECONDARY_ADDRESSES */ + s_ErrorMessage.Add(9615, "DNS error wins init failed"); /* DNS_ERROR_WINS_INIT_FAILED */ + s_ErrorMessage.Add(9616, "DNS error need wins servers"); /* DNS_ERROR_NEED_WINS_SERVERS */ + s_ErrorMessage.Add(9617, "DNS error nbstat init failed"); /* DNS_ERROR_NBSTAT_INIT_FAILED */ + s_ErrorMessage.Add(9618, "DNS error SOA delete invalid"); /* DNS_ERROR_SOA_DELETE_INVALID */ + s_ErrorMessage.Add(9619, "DNS error forwarder already exists"); /* DNS_ERROR_FORWARDER_ALREADY_EXISTS */ + s_ErrorMessage.Add(9620, "DNS error zone requires master IP"); /* DNS_ERROR_ZONE_REQUIRES_MASTER_IP */ + s_ErrorMessage.Add(9621, "DNS error zone is shutdown"); /* DNS_ERROR_ZONE_IS_SHUTDOWN */ + s_ErrorMessage.Add(9651, "DNS error primary requires datafile"); /* DNS_ERROR_PRIMARY_REQUIRES_DATAFILE */ + s_ErrorMessage.Add(9652, "DNS error invalid datafile name"); /* DNS_ERROR_INVALID_DATAFILE_NAME */ + s_ErrorMessage.Add(9653, "DNS error datafile open failure"); /* DNS_ERROR_DATAFILE_OPEN_FAILURE */ + s_ErrorMessage.Add(9654, "DNS error file writeback failed"); /* DNS_ERROR_FILE_WRITEBACK_FAILED */ + s_ErrorMessage.Add(9655, "DNS error datafile parsing"); /* DNS_ERROR_DATAFILE_PARSING */ + s_ErrorMessage.Add(9701, "DNS error record does not exist"); /* DNS_ERROR_RECORD_DOES_NOT_EXIST */ + s_ErrorMessage.Add(9702, "DNS error record format"); /* DNS_ERROR_RECORD_FORMAT */ + s_ErrorMessage.Add(9703, "DNS error node creation failed"); /* DNS_ERROR_NODE_CREATION_FAILED */ + s_ErrorMessage.Add(9704, "DNS error unknown record type"); /* DNS_ERROR_UNKNOWN_RECORD_TYPE */ + s_ErrorMessage.Add(9705, "DNS error record timed out"); /* DNS_ERROR_RECORD_TIMED_OUT */ + s_ErrorMessage.Add(9706, "DNS error name not in zone"); /* DNS_ERROR_NAME_NOT_IN_ZONE */ + s_ErrorMessage.Add(9707, "DNS error CNAME loop"); /* DNS_ERROR_CNAME_LOOP */ + s_ErrorMessage.Add(9708, "DNS error node is CNAME"); /* DNS_ERROR_NODE_IS_CNAME */ + s_ErrorMessage.Add(9709, "DNS error CNAME collision"); /* DNS_ERROR_CNAME_COLLISION */ + s_ErrorMessage.Add(9710, "DNS error record only at zone root"); /* DNS_ERROR_RECORD_ONLY_AT_ZONE_ROOT */ + s_ErrorMessage.Add(9711, "DNS error record already exists"); /* DNS_ERROR_RECORD_ALREADY_EXISTS */ + s_ErrorMessage.Add(9712, "DNS error secondary data"); /* DNS_ERROR_SECONDARY_DATA */ + s_ErrorMessage.Add(9713, "DNS error no create cache data"); /* DNS_ERROR_NO_CREATE_CACHE_DATA */ + s_ErrorMessage.Add(9714, "DNS error name does not exist"); /* DNS_ERROR_NAME_DOES_NOT_EXIST */ + s_ErrorMessage.Add(9715, "DNS warning PTR create failed"); /* DNS_WARNING_PTR_CREATE_FAILED */ + s_ErrorMessage.Add(9716, "DNS warning domain undeleted"); /* DNS_WARNING_DOMAIN_UNDELETED */ + s_ErrorMessage.Add(9717, "DNS error ds unavailable"); /* DNS_ERROR_DS_UNAVAILABLE */ + s_ErrorMessage.Add(9718, "DNS error ds zone already exists"); /* DNS_ERROR_DS_ZONE_ALREADY_EXISTS */ + s_ErrorMessage.Add(9719, "DNS error no bootfile if ds zone"); /* DNS_ERROR_NO_BOOTFILE_IF_DS_ZONE */ + s_ErrorMessage.Add(9751, "DNS info AXFR complete"); /* DNS_INFO_AXFR_COMPLETE */ + s_ErrorMessage.Add(9752, "DNS error AXFR"); /* DNS_ERROR_AXFR */ + s_ErrorMessage.Add(9753, "DNS info added local wins"); /* DNS_INFO_ADDED_LOCAL_WINS */ + s_ErrorMessage.Add(9801, "DNS status continue needed"); /* DNS_STATUS_CONTINUE_NEEDED */ + s_ErrorMessage.Add(9851, "DNS error no TCPIP"); /* DNS_ERROR_NO_TCPIP */ + s_ErrorMessage.Add(9852, "DNS error no DNS servers"); /* DNS_ERROR_NO_DNS_SERVERS */ + s_ErrorMessage.Add(9901, "DNS error dp does not exist"); /* DNS_ERROR_DP_DOES_NOT_EXIST */ + s_ErrorMessage.Add(9902, "DNS error dp already exists"); /* DNS_ERROR_DP_ALREADY_EXISTS */ + s_ErrorMessage.Add(9903, "DNS error dp not enlisted"); /* DNS_ERROR_DP_NOT_ENLISTED */ + s_ErrorMessage.Add(9904, "DNS error dp already enlisted"); /* DNS_ERROR_DP_ALREADY_ENLISTED */ + s_ErrorMessage.Add(10110, "E_NO_MORE"); /* WSA_E_NO_MORE */ + s_ErrorMessage.Add(10111, "E_CANCELLED"); /* WSA_E_CANCELLED */ + s_ErrorMessage.Add(11005, "QOS receivers"); /* WSA_QOS_RECEIVERS */ + s_ErrorMessage.Add(11006, "QOS senders"); /* WSA_QOS_SENDERS */ + s_ErrorMessage.Add(11007, "QOS no senders"); /* WSA_QOS_NO_SENDERS */ + s_ErrorMessage.Add(11008, "QOS no receivers"); /* WSA_QOS_NO_RECEIVERS */ + s_ErrorMessage.Add(11009, "QOS request confirmed"); /* WSA_QOS_REQUEST_CONFIRMED */ + s_ErrorMessage.Add(11010, "QOS admission failure"); /* WSA_QOS_ADMISSION_FAILURE */ + s_ErrorMessage.Add(11011, "QOS policy failure"); /* WSA_QOS_POLICY_FAILURE */ + s_ErrorMessage.Add(11012, "QOS bad style"); /* WSA_QOS_BAD_STYLE */ + s_ErrorMessage.Add(11013, "QOS bad object"); /* WSA_QOS_BAD_OBJECT */ + s_ErrorMessage.Add(11014, "QOS traffic ctrl error"); /* WSA_QOS_TRAFFIC_CTRL_ERROR */ + s_ErrorMessage.Add(11015, "QOS generic error"); /* WSA_QOS_GENERIC_ERROR */ + s_ErrorMessage.Add(11016, "QOS eservicetype"); /* WSA_QOS_ESERVICETYPE */ + s_ErrorMessage.Add(11017, "QOS eflowspec"); /* WSA_QOS_EFLOWSPEC */ + s_ErrorMessage.Add(11018, "QOS eprovspecbuf"); /* WSA_QOS_EPROVSPECBUF */ + s_ErrorMessage.Add(11019, "QOS efilterstyle"); /* WSA_QOS_EFILTERSTYLE */ + s_ErrorMessage.Add(11020, "QOS efiltertype"); /* WSA_QOS_EFILTERTYPE */ + s_ErrorMessage.Add(11021, "QOS efiltercount"); /* WSA_QOS_EFILTERCOUNT */ + s_ErrorMessage.Add(11022, "QOS eobjlength"); /* WSA_QOS_EOBJLENGTH */ + s_ErrorMessage.Add(11023, "QOS eflowcount"); /* WSA_QOS_EFLOWCOUNT */ + s_ErrorMessage.Add(11024, "QOS eunknownpsobj"); /* WSA_QOS_EUNKNOWNPSOBJ */ + s_ErrorMessage.Add(11025, "QOS epolicyobj"); /* WSA_QOS_EPOLICYOBJ */ + s_ErrorMessage.Add(11026, "QOS eflowdesc"); /* WSA_QOS_EFLOWDESC */ + s_ErrorMessage.Add(11027, "QOS epsflowspec"); /* WSA_QOS_EPSFLOWSPEC */ + s_ErrorMessage.Add(11028, "QOS epsfilterspec"); /* WSA_QOS_EPSFILTERSPEC */ + s_ErrorMessage.Add(11029, "QOS esdmodeobj"); /* WSA_QOS_ESDMODEOBJ */ + s_ErrorMessage.Add(11030, "QOS eshaperateobj"); /* WSA_QOS_ESHAPERATEOBJ */ + s_ErrorMessage.Add(11031, "QOS reserved petype"); /* WSA_QOS_RESERVED_PETYPE */ + s_ErrorMessage.Add(13000, "IPSEC qm policy exists"); /* ERROR_IPSEC_QM_POLICY_EXISTS */ + s_ErrorMessage.Add(13001, "IPSEC qm policy not found"); /* ERROR_IPSEC_QM_POLICY_NOT_FOUND */ + s_ErrorMessage.Add(13002, "IPSEC qm policy in use"); /* ERROR_IPSEC_QM_POLICY_IN_USE */ + s_ErrorMessage.Add(13003, "IPSEC mm policy exists"); /* ERROR_IPSEC_MM_POLICY_EXISTS */ + s_ErrorMessage.Add(13004, "IPSEC mm policy not found"); /* ERROR_IPSEC_MM_POLICY_NOT_FOUND */ + s_ErrorMessage.Add(13005, "IPSEC mm policy in use"); /* ERROR_IPSEC_MM_POLICY_IN_USE */ + s_ErrorMessage.Add(13006, "IPSEC mm filter exists"); /* ERROR_IPSEC_MM_FILTER_EXISTS */ + s_ErrorMessage.Add(13007, "IPSEC mm filter not found"); /* ERROR_IPSEC_MM_FILTER_NOT_FOUND */ + s_ErrorMessage.Add(13008, "IPSEC transport filter exists"); /* ERROR_IPSEC_TRANSPORT_FILTER_EXISTS */ + s_ErrorMessage.Add(13009, "IPSEC transport filter not found"); /* ERROR_IPSEC_TRANSPORT_FILTER_NOT_FOUND */ + s_ErrorMessage.Add(13010, "IPSEC mm auth exists"); /* ERROR_IPSEC_MM_AUTH_EXISTS */ + s_ErrorMessage.Add(13011, "IPSEC mm auth not found"); /* ERROR_IPSEC_MM_AUTH_NOT_FOUND */ + s_ErrorMessage.Add(13012, "IPSEC mm auth in use"); /* ERROR_IPSEC_MM_AUTH_IN_USE */ + s_ErrorMessage.Add(13013, "IPSEC default mm policy not found"); /* ERROR_IPSEC_DEFAULT_MM_POLICY_NOT_FOUND */ + s_ErrorMessage.Add(13014, "IPSEC default mm auth not found"); /* ERROR_IPSEC_DEFAULT_MM_AUTH_NOT_FOUND */ + s_ErrorMessage.Add(13015, "IPSEC default qm policy not found"); /* ERROR_IPSEC_DEFAULT_QM_POLICY_NOT_FOUND */ + s_ErrorMessage.Add(13016, "IPSEC tunnel filter exists"); /* ERROR_IPSEC_TUNNEL_FILTER_EXISTS */ + s_ErrorMessage.Add(13017, "IPSEC tunnel filter not found"); /* ERROR_IPSEC_TUNNEL_FILTER_NOT_FOUND */ + s_ErrorMessage.Add(13018, "IPSEC mm filter pending deletion"); /* ERROR_IPSEC_MM_FILTER_PENDING_DELETION */ + s_ErrorMessage.Add(13019, "IPSEC transport filter pending deletion"); /* ERROR_IPSEC_TRANSPORT_FILTER_PENDING_DELETION */ + s_ErrorMessage.Add(13020, "IPSEC tunnel filter pending deletion"); /* ERROR_IPSEC_TUNNEL_FILTER_PENDING_DELETION */ + s_ErrorMessage.Add(13021, "IPSEC mm policy pending deletion"); /* ERROR_IPSEC_MM_POLICY_PENDING_DELETION */ + s_ErrorMessage.Add(13022, "IPSEC mm auth pending deletion"); /* ERROR_IPSEC_MM_AUTH_PENDING_DELETION */ + s_ErrorMessage.Add(13023, "IPSEC qm policy pending deletion"); /* ERROR_IPSEC_QM_POLICY_PENDING_DELETION */ + s_ErrorMessage.Add(13801, "IPSEC IKE auth fail"); /* ERROR_IPSEC_IKE_AUTH_FAIL */ + s_ErrorMessage.Add(13802, "IPSEC IKE attrib fail"); /* ERROR_IPSEC_IKE_ATTRIB_FAIL */ + s_ErrorMessage.Add(13803, "IPSEC IKE negotiation pending"); /* ERROR_IPSEC_IKE_NEGOTIATION_PENDING */ + s_ErrorMessage.Add(13804, "IPSEC IKE general processing error"); /* ERROR_IPSEC_IKE_GENERAL_PROCESSING_ERROR */ + s_ErrorMessage.Add(13805, "IPSEC IKE timed out"); /* ERROR_IPSEC_IKE_TIMED_OUT */ + s_ErrorMessage.Add(13806, "IPSEC IKE no cert"); /* ERROR_IPSEC_IKE_NO_CERT */ + s_ErrorMessage.Add(13807, "IPSEC IKE sa deleted"); /* ERROR_IPSEC_IKE_SA_DELETED */ + s_ErrorMessage.Add(13808, "IPSEC IKE sa reaped"); /* ERROR_IPSEC_IKE_SA_REAPED */ + s_ErrorMessage.Add(13809, "IPSEC IKE mm acquire drop"); /* ERROR_IPSEC_IKE_MM_ACQUIRE_DROP */ + s_ErrorMessage.Add(13810, "IPSEC IKE qm acquire drop"); /* ERROR_IPSEC_IKE_QM_ACQUIRE_DROP */ + s_ErrorMessage.Add(13811, "IPSEC IKE queue drop mm"); /* ERROR_IPSEC_IKE_QUEUE_DROP_MM */ + s_ErrorMessage.Add(13812, "IPSEC IKE queue drop no mm"); /* ERROR_IPSEC_IKE_QUEUE_DROP_NO_MM */ + s_ErrorMessage.Add(13813, "IPSEC IKE drop no response"); /* ERROR_IPSEC_IKE_DROP_NO_RESPONSE */ + s_ErrorMessage.Add(13814, "IPSEC IKE mm delay drop"); /* ERROR_IPSEC_IKE_MM_DELAY_DROP */ + s_ErrorMessage.Add(13815, "IPSEC IKE qm delay drop"); /* ERROR_IPSEC_IKE_QM_DELAY_DROP */ + s_ErrorMessage.Add(13816, "IPSEC IKE error"); /* ERROR_IPSEC_IKE_ERROR */ + s_ErrorMessage.Add(13817, "IPSEC IKE crl failed"); /* ERROR_IPSEC_IKE_CRL_FAILED */ + s_ErrorMessage.Add(13818, "IPSEC IKE invalid key usage"); /* ERROR_IPSEC_IKE_INVALID_KEY_USAGE */ + s_ErrorMessage.Add(13819, "IPSEC IKE invalid cert type"); /* ERROR_IPSEC_IKE_INVALID_CERT_TYPE */ + s_ErrorMessage.Add(13820, "IPSEC IKE no private key"); /* ERROR_IPSEC_IKE_NO_PRIVATE_KEY */ + s_ErrorMessage.Add(13822, "IPSEC IKE dh fail"); /* ERROR_IPSEC_IKE_DH_FAIL */ + s_ErrorMessage.Add(13824, "IPSEC IKE invalid header"); /* ERROR_IPSEC_IKE_INVALID_HEADER */ + s_ErrorMessage.Add(13825, "IPSEC IKE no policy"); /* ERROR_IPSEC_IKE_NO_POLICY */ + s_ErrorMessage.Add(13826, "IPSEC IKE invalid signature"); /* ERROR_IPSEC_IKE_INVALID_SIGNATURE */ + s_ErrorMessage.Add(13827, "IPSEC IKE kerberos error"); /* ERROR_IPSEC_IKE_KERBEROS_ERROR */ + s_ErrorMessage.Add(13828, "IPSEC IKE no public key"); /* ERROR_IPSEC_IKE_NO_PUBLIC_KEY */ + s_ErrorMessage.Add(13829, "IPSEC IKE process err"); /* ERROR_IPSEC_IKE_PROCESS_ERR */ + s_ErrorMessage.Add(13830, "IPSEC IKE process err sa"); /* ERROR_IPSEC_IKE_PROCESS_ERR_SA */ + s_ErrorMessage.Add(13831, "IPSEC IKE process err prop"); /* ERROR_IPSEC_IKE_PROCESS_ERR_PROP */ + s_ErrorMessage.Add(13832, "IPSEC IKE process err trans"); /* ERROR_IPSEC_IKE_PROCESS_ERR_TRANS */ + s_ErrorMessage.Add(13833, "IPSEC IKE process err ke"); /* ERROR_IPSEC_IKE_PROCESS_ERR_KE */ + s_ErrorMessage.Add(13834, "IPSEC IKE process err ID"); /* ERROR_IPSEC_IKE_PROCESS_ERR_ID */ + s_ErrorMessage.Add(13835, "IPSEC IKE process err cert"); /* ERROR_IPSEC_IKE_PROCESS_ERR_CERT */ + s_ErrorMessage.Add(13836, "IPSEC IKE process err cert req"); /* ERROR_IPSEC_IKE_PROCESS_ERR_CERT_REQ */ + s_ErrorMessage.Add(13837, "IPSEC IKE process err hash"); /* ERROR_IPSEC_IKE_PROCESS_ERR_HASH */ + s_ErrorMessage.Add(13838, "IPSEC IKE process err sig"); /* ERROR_IPSEC_IKE_PROCESS_ERR_SIG */ + s_ErrorMessage.Add(13839, "IPSEC IKE process err nonce"); /* ERROR_IPSEC_IKE_PROCESS_ERR_NONCE */ + s_ErrorMessage.Add(13840, "IPSEC IKE process err notify"); /* ERROR_IPSEC_IKE_PROCESS_ERR_NOTIFY */ + s_ErrorMessage.Add(13841, "IPSEC IKE process err delete"); /* ERROR_IPSEC_IKE_PROCESS_ERR_DELETE */ + s_ErrorMessage.Add(13842, "IPSEC IKE process err vendor"); /* ERROR_IPSEC_IKE_PROCESS_ERR_VENDOR */ + s_ErrorMessage.Add(13843, "IPSEC IKE invalid payload"); /* ERROR_IPSEC_IKE_INVALID_PAYLOAD */ + s_ErrorMessage.Add(13844, "IPSEC IKE load soft sa"); /* ERROR_IPSEC_IKE_LOAD_SOFT_SA */ + s_ErrorMessage.Add(13845, "IPSEC IKE soft sa torn down"); /* ERROR_IPSEC_IKE_SOFT_SA_TORN_DOWN */ + s_ErrorMessage.Add(13846, "IPSEC IKE invalid cookie"); /* ERROR_IPSEC_IKE_INVALID_COOKIE */ + s_ErrorMessage.Add(13847, "IPSEC IKE no peer cert"); /* ERROR_IPSEC_IKE_NO_PEER_CERT */ + s_ErrorMessage.Add(13848, "IPSEC IKE peer CRL failed"); /* ERROR_IPSEC_IKE_PEER_CRL_FAILED */ + s_ErrorMessage.Add(13849, "IPSEC IKE policy change"); /* ERROR_IPSEC_IKE_POLICY_CHANGE */ + s_ErrorMessage.Add(13850, "IPSEC IKE no mm policy"); /* ERROR_IPSEC_IKE_NO_MM_POLICY */ + s_ErrorMessage.Add(13851, "IPSEC IKE notcbpriv"); /* ERROR_IPSEC_IKE_NOTCBPRIV */ + s_ErrorMessage.Add(13852, "IPSEC IKE secloadfail"); /* ERROR_IPSEC_IKE_SECLOADFAIL */ + s_ErrorMessage.Add(13853, "IPSEC IKE failsspinit"); /* ERROR_IPSEC_IKE_FAILSSPINIT */ + s_ErrorMessage.Add(13854, "IPSEC IKE failqueryssp"); /* ERROR_IPSEC_IKE_FAILQUERYSSP */ + s_ErrorMessage.Add(13855, "IPSEC IKE srvacqfail"); /* ERROR_IPSEC_IKE_SRVACQFAIL */ + s_ErrorMessage.Add(13856, "IPSEC IKE srvquerycred"); /* ERROR_IPSEC_IKE_SRVQUERYCRED */ + s_ErrorMessage.Add(13857, "IPSEC IKE getspifail"); /* ERROR_IPSEC_IKE_GETSPIFAIL */ + s_ErrorMessage.Add(13858, "IPSEC IKE invalid filter"); /* ERROR_IPSEC_IKE_INVALID_FILTER */ + s_ErrorMessage.Add(13859, "IPSEC IKE out of memory"); /* ERROR_IPSEC_IKE_OUT_OF_MEMORY */ + s_ErrorMessage.Add(13860, "IPSEC IKE add update key failed"); /* ERROR_IPSEC_IKE_ADD_UPDATE_KEY_FAILED */ + s_ErrorMessage.Add(13861, "IPSEC IKE invalid policy"); /* ERROR_IPSEC_IKE_INVALID_POLICY */ + s_ErrorMessage.Add(13862, "IPSEC IKE unknown doi"); /* ERROR_IPSEC_IKE_UNKNOWN_DOI */ + s_ErrorMessage.Add(13863, "IPSEC IKE invalid situation"); /* ERROR_IPSEC_IKE_INVALID_SITUATION */ + s_ErrorMessage.Add(13864, "IPSEC IKE dh failure"); /* ERROR_IPSEC_IKE_DH_FAILURE */ + s_ErrorMessage.Add(13865, "IPSEC IKE invalid group"); /* ERROR_IPSEC_IKE_INVALID_GROUP */ + s_ErrorMessage.Add(13866, "IPSEC IKE encrypt"); /* ERROR_IPSEC_IKE_ENCRYPT */ + s_ErrorMessage.Add(13867, "IPSEC IKE decrypt"); /* ERROR_IPSEC_IKE_DECRYPT */ + s_ErrorMessage.Add(13868, "IPSEC IKE policy match"); /* ERROR_IPSEC_IKE_POLICY_MATCH */ + s_ErrorMessage.Add(13869, "IPSEC IKE unsupported ID"); /* ERROR_IPSEC_IKE_UNSUPPORTED_ID */ + s_ErrorMessage.Add(13870, "IPSEC IKE invalid hash"); /* ERROR_IPSEC_IKE_INVALID_HASH */ + s_ErrorMessage.Add(13871, "IPSEC IKE invalid hash alg"); /* ERROR_IPSEC_IKE_INVALID_HASH_ALG */ + s_ErrorMessage.Add(13872, "IPSEC IKE invalid hash size"); /* ERROR_IPSEC_IKE_INVALID_HASH_SIZE */ + s_ErrorMessage.Add(13873, "IPSEC IKE invalid encrypt alg"); /* ERROR_IPSEC_IKE_INVALID_ENCRYPT_ALG */ + s_ErrorMessage.Add(13874, "IPSEC IKE invalid auth alg"); /* ERROR_IPSEC_IKE_INVALID_AUTH_ALG */ + s_ErrorMessage.Add(13875, "IPSEC IKE invalid sig"); /* ERROR_IPSEC_IKE_INVALID_SIG */ + s_ErrorMessage.Add(13876, "IPSEC IKE load failed"); /* ERROR_IPSEC_IKE_LOAD_FAILED */ + s_ErrorMessage.Add(13877, "IPSEC IKE rpc delete"); /* ERROR_IPSEC_IKE_RPC_DELETE */ + s_ErrorMessage.Add(13878, "IPSEC IKE benign reinit"); /* ERROR_IPSEC_IKE_BENIGN_REINIT */ + s_ErrorMessage.Add(13879, "IPSEC IKE invalid responder lifetime notify"); /* ERROR_IPSEC_IKE_INVALID_RESPONDER_LIFETIME_NOTIFY */ + s_ErrorMessage.Add(13881, "IPSEC IKE invalid cert keylen"); /* ERROR_IPSEC_IKE_INVALID_CERT_KEYLEN */ + s_ErrorMessage.Add(13882, "IPSEC IKE mm limit"); /* ERROR_IPSEC_IKE_MM_LIMIT */ + s_ErrorMessage.Add(13883, "IPSEC IKE negotiation disabled"); /* ERROR_IPSEC_IKE_NEGOTIATION_DISABLED */ + s_ErrorMessage.Add(13884, "IPSEC IKE neg status end"); /* ERROR_IPSEC_IKE_NEG_STATUS_END */ + s_ErrorMessage.Add(100001, "Device not configured"); /* WSAENXIO */ +#endif // MOBILE + s_ErrorMessagesInitialized = true; + } + } +#endif // UNITY } } \ No newline at end of file diff --git a/mcs/class/System/System.Net.NetworkInformation/IPGlobalProperties.cs b/mcs/class/System/System.Net.NetworkInformation/IPGlobalProperties.cs index 92bd3ffb363e..7246735678d0 100644 --- a/mcs/class/System/System.Net.NetworkInformation/IPGlobalProperties.cs +++ b/mcs/class/System/System.Net.NetworkInformation/IPGlobalProperties.cs @@ -59,8 +59,17 @@ public override string DhcpScopeName { public override string DomainName { get { byte [] bytes = new byte [256]; - if (getdomainname (bytes, 256) != 0) - throw new NetworkInformationException (); +#if UNITY + try + { +#endif + if (getdomainname (bytes, 256) != 0) + throw new NetworkInformationException (); +#if UNITY + } catch (EntryPointNotFoundException) { + return String.Empty; + } +#endif int len = Array.IndexOf (bytes, 0); return Encoding.ASCII.GetString (bytes, 0, len < 0 ? 256 : len); } @@ -613,6 +622,9 @@ public override NetBiosNodeType NodeType { [DllImport ("iphlpapi.dll")] static extern int GetIpStatisticsEx (out Win32_MIB_IPSTATS pStats, int dwFamily); + [DllImport ("Ws2_32.dll")] + static extern ushort ntohs (ushort netshort); + // Win32 structures [StructLayout (LayoutKind.Explicit)] @@ -673,10 +685,10 @@ public TcpConnectionInformation TcpInfo { class Win32_MIB_UDPROW { public uint LocalAddr; - public int LocalPort; + public uint LocalPort; public IPEndPoint LocalEndPoint { - get { return new IPEndPoint (LocalAddr, LocalPort); } + get { return new IPEndPoint (LocalAddr, ntohs((ushort)LocalPort)); } } } diff --git a/mcs/class/System/System.Net.Sockets/Socket.cs b/mcs/class/System/System.Net.Sockets/Socket.cs index fe7099144ec5..6b55a8655ee8 100644 --- a/mcs/class/System/System.Net.Sockets/Socket.cs +++ b/mcs/class/System/System.Net.Sockets/Socket.cs @@ -1160,7 +1160,19 @@ bool GetCheckedIPs (SocketAsyncEventArgs e, out IPAddress [] addresses) // while skipping entries that do not match the address family DnsEndPoint dep = e.RemoteEndPoint as DnsEndPoint; if (dep != null) { - addresses = Dns.GetHostAddresses (dep.Host); + var possibleAddresses = Dns.GetHostAddresses (dep.Host); + var numberOfAddresses = 0; + int[] addressIndices = new int[possibleAddresses.Length]; + for (var i = 0; i < possibleAddresses.Length; i++) { + if (possibleAddresses[i].AddressFamily == dep.AddressFamily) { + addressIndices[numberOfAddresses] = i; + numberOfAddresses++; + } + } + addresses = new IPAddress[numberOfAddresses]; + for (var i = 0; i < numberOfAddresses; i++) + addresses[i] = possibleAddresses[addressIndices[i]]; + return true; } else { e.ConnectByNameError = null; @@ -2793,9 +2805,16 @@ internal static int FamilyHint { } } +#if UNITY + [MethodImplAttribute(MethodImplOptions.InternalCall)] + extern static bool IsProtocolSupported_internal(NetworkInterfaceComponent networkInterface); +#endif + static bool IsProtocolSupported (NetworkInterfaceComponent networkInterface) { -#if MOBILE +#if UNITY + return IsProtocolSupported_internal(networkInterface); +#elif MOBILE return true; #else var nics = NetworkInterface.GetAllNetworkInterfaces (); diff --git a/mcs/class/System/System.Net/ServicePointManager.extra.cs b/mcs/class/System/System.Net/ServicePointManager.extra.cs index d971cdd84124..1d2502e11df5 100644 --- a/mcs/class/System/System.Net/ServicePointManager.extra.cs +++ b/mcs/class/System/System.Net/ServicePointManager.extra.cs @@ -7,7 +7,7 @@ // Copyright 2013-2014 Xamarin Inc. // -#if MOBILE +#if MOBILE && !UNITY using System; using System.Collections.Generic; diff --git a/mcs/class/System/common.sources b/mcs/class/System/common.sources index 418336ceef91..c3b0f8a1bf11 100644 --- a/mcs/class/System/common.sources +++ b/mcs/class/System/common.sources @@ -258,6 +258,14 @@ Mono.AppleTls/Trust.cs Mono.AppleTls/SslConnection.cs Mono.AppleTls/Items.cs +Mono.UnityTls/UnityTls.cs +Mono.UnityTls/UnityTlsProvider.cs +Mono.UnityTls/UnityTlsStream.cs +Mono.UnityTls/UnityTlsContext.cs +Mono.UnityTls/UnityTlsConversions.cs +Mono.UnityTls/Debug.cs +Mono.UnityTls/CertHelper.cs + Mono.Util/MonoPInvokeCallbackAttribute.cs MonoTouch/Dummy.cs diff --git a/mcs/class/System/unityaot_System.dll.sources b/mcs/class/System/unityaot_System.dll.sources new file mode 100644 index 000000000000..9bd62cd0ec26 --- /dev/null +++ b/mcs/class/System/unityaot_System.dll.sources @@ -0,0 +1,4 @@ +#include mobile_System.dll.sources +../System.Web/System.Web/HttpUtility.cs +../System.Web/System.Web.Util/Helpers.cs +../System.Web/System.Web.Util/HttpEncoder.cs diff --git a/mcs/class/System/unityjit_System.dll.sources b/mcs/class/System/unityjit_System.dll.sources new file mode 100644 index 000000000000..beb6f2415cf1 --- /dev/null +++ b/mcs/class/System/unityjit_System.dll.sources @@ -0,0 +1 @@ +#include net_4_x_System.dll.sources diff --git a/mcs/class/corlib/Assembly/AssemblyInfo.cs b/mcs/class/corlib/Assembly/AssemblyInfo.cs index 54b21cdf3ba7..2d2de030429d 100644 --- a/mcs/class/corlib/Assembly/AssemblyInfo.cs +++ b/mcs/class/corlib/Assembly/AssemblyInfo.cs @@ -59,7 +59,7 @@ [assembly: CLSCompliant (true)] [assembly: AssemblyDelaySign (true)] -#if MOBILE +#if MOBILE && !UNITY_AOT [assembly: AssemblyKeyFile ("../silverlight.pub")] #else [assembly: AssemblyKeyFile ("../ecma.pub")] diff --git a/mcs/class/corlib/System.IO/MonoIO.cs b/mcs/class/corlib/System.IO/MonoIO.cs index 3567809b9da5..68418f794f37 100644 --- a/mcs/class/corlib/System.IO/MonoIO.cs +++ b/mcs/class/corlib/System.IO/MonoIO.cs @@ -733,6 +733,9 @@ public extern static char PathSeparator { [MethodImplAttribute (MethodImplOptions.InternalCall)] extern static void DumpHandles (); + + [MethodImplAttribute (MethodImplOptions.InternalCall)] + public extern static bool RemapPath (string path, out string newPath); } } diff --git a/mcs/class/corlib/System.IO/Path.cs b/mcs/class/corlib/System.IO/Path.cs index bf0093e1203e..8aaa49340d27 100644 --- a/mcs/class/corlib/System.IO/Path.cs +++ b/mcs/class/corlib/System.IO/Path.cs @@ -422,6 +422,9 @@ internal static string InsecureGetFullPath (string path) if (IsDirectorySeparator (end) && (path [path.Length - 1] != DirectorySeparatorChar)) path += DirectorySeparatorChar; + string newPath; + if (MonoIO.RemapPath(path, out newPath)) + path = newPath; return path; } diff --git a/mcs/class/corlib/System.Runtime.InteropServices/Marshal.cs b/mcs/class/corlib/System.Runtime.InteropServices/Marshal.cs index e94898a5c386..e12d825cd58c 100644 --- a/mcs/class/corlib/System.Runtime.InteropServices/Marshal.cs +++ b/mcs/class/corlib/System.Runtime.InteropServices/Marshal.cs @@ -53,14 +53,14 @@ public static class Marshal public static readonly int SystemMaxDBCSCharSize = 2; // don't know what this is public static readonly int SystemDefaultCharSize = Environment.IsRunningOnWindows ? 2 : 1; -#if !MOBILE +#if !MOBILE || UNITY_AOT [MethodImplAttribute (MethodImplOptions.InternalCall)] private extern static int AddRefInternal (IntPtr pUnk); #endif public static int AddRef (IntPtr pUnk) { -#if !MOBILE +#if !MOBILE || UNITY_AOT if (pUnk == IntPtr.Zero) throw new ArgumentException ("Value cannot be null.", "pUnk"); return AddRefInternal (pUnk); @@ -210,7 +210,9 @@ public static IntPtr CreateAggregatedObject (IntPtr pOuter, T o) { public static object CreateWrapperOfType (object o, Type t) { -#if FULL_AOT_RUNTIME +#if UNITY_AOT + throw new NotImplementedException("Marshal.CreateWrapperOfType is not implemented."); +#elif FULL_AOT_RUNTIME throw new PlatformNotSupportedException (); #else __ComObject co = o as __ComObject; @@ -307,7 +309,7 @@ public static void ZeroFreeGlobalAllocUnicode (IntPtr s) FreeHGlobal (s); } -#if !FULL_AOT_RUNTIME +#if !FULL_AOT_RUNTIME || UNITY_AOT public static Guid GenerateGuidForType (Type type) { return type.GUID; @@ -342,15 +344,17 @@ public static object GetActiveObject (string progID) throw new NotImplementedException (); } -#if !MOBILE +#if !MOBILE || UNITY_AOT [MethodImplAttribute (MethodImplOptions.InternalCall)] private extern static IntPtr GetCCW (object o, Type T); private static IntPtr GetComInterfaceForObjectInternal (object o, Type T) { +#if !UNITY_AOT if (IsComObject (o)) return ((__ComObject)o).GetInterface (T); else +#endif return GetCCW (o, T); } #endif @@ -358,7 +362,7 @@ private static IntPtr GetComInterfaceForObjectInternal (object o, Type T) public static IntPtr GetComInterfaceForObject (object o, Type T) { -#if MOBILE +#if MOBILE && !UNITY_AOT throw new PlatformNotSupportedException (); #else IntPtr pItf = GetComInterfaceForObjectInternal (o, T); @@ -377,7 +381,7 @@ public static IntPtr GetComInterfaceForObject (T o) { return GetComInterfaceForObject ((object)o, typeof (T)); } -#if !FULL_AOT_RUNTIME +#if !FULL_AOT_RUNTIME || UNITY_AOT [MonoTODO] public static IntPtr GetComInterfaceForObjectInContext (object o, Type t) { @@ -430,7 +434,7 @@ public static IntPtr GetHINSTANCE (Module m) return m.GetHINSTANCE (); } -#endif // !FULL_AOT_RUNTIME +#endif // !FULL_AOT_RUNTIME || UNITY_AOT public static int GetExceptionCode () { @@ -453,14 +457,14 @@ public static int GetHRForException (Exception e) [ReliabilityContract (Consistency.WillNotCorruptState, Cer.Success)] public static int GetHRForLastWin32Error() { -#if FULL_AOT_RUNTIME +#if FULL_AOT_RUNTIME && !UNITY_AOT throw new PlatformNotSupportedException (); #else throw new NotImplementedException (); #endif } - -#if !FULL_AOT_RUNTIME + +#if !FULL_AOT_RUNTIME || UNITY_AOT [MethodImplAttribute (MethodImplOptions.InternalCall)] private extern static IntPtr GetIDispatchForObjectInternal (object o); @@ -471,7 +475,9 @@ public static IntPtr GetIDispatchForObject (object o) AddRef (pUnk); return pUnk; } +#endif // !FULL_AOT_RUNTIME || UNITY_AOT +#if !FULL_AOT_RUNTIME [MonoTODO] public static IntPtr GetIDispatchForObjectInContext (object o) { @@ -502,15 +508,16 @@ public static MemberInfo GetMethodInfoForComSlot (Type t, int slot, ref ComMembe { throw new NotImplementedException (); } +#endif // !FULL_AOT_RUNTIME +#if !FULL_AOT_RUNTIME || UNITY_AOT [MethodImplAttribute (MethodImplOptions.InternalCall)] private extern static IntPtr GetIUnknownForObjectInternal (object o); - -#endif // !FULL_AOT_RUNTIME +#endif // !FULL_AOT_RUNTIME || UNITY_AOT public static IntPtr GetIUnknownForObject (object o) { -#if FULL_AOT_RUNTIME +#if FULL_AOT_RUNTIME && !UNITY_AOT throw new PlatformNotSupportedException (); #else IntPtr pUnk = GetIUnknownForObjectInternal (o); @@ -522,7 +529,7 @@ public static IntPtr GetIUnknownForObject (object o) public static void GetNativeVariantForObject (object obj, IntPtr pDstNativeVariant) { -#if FULL_AOT_RUNTIME +#if FULL_AOT_RUNTIME && !UNITY_AOT throw new PlatformNotSupportedException (); #else Variant vt = new Variant(); @@ -535,29 +542,31 @@ public static void GetNativeVariantForObject (T obj, IntPtr pDstNativeVariant GetNativeVariantForObject ((object)obj, pDstNativeVariant); } -#if !MOBILE && !FULL_AOT_RUNTIME +#if (!MOBILE && !FULL_AOT_RUNTIME) || UNITY_AOT [MethodImplAttribute (MethodImplOptions.InternalCall)] private static extern object GetObjectForCCW (IntPtr pUnk); #endif public static object GetObjectForIUnknown (IntPtr pUnk) { -#if MOBILE || FULL_AOT_RUNTIME +#if (MOBILE || FULL_AOT_RUNTIME) && !UNITY_AOT throw new PlatformNotSupportedException (); #else object obj = GetObjectForCCW (pUnk); +#if !UNITY_AOT // was not a CCW if (obj == null) { ComInteropProxy proxy = ComInteropProxy.GetProxy (pUnk, typeof (__ComObject)); obj = proxy.GetTransparentProxy (); } +#endif return obj; #endif } public static object GetObjectForNativeVariant (IntPtr pSrcNativeVariant) { -#if FULL_AOT_RUNTIME +#if FULL_AOT_RUNTIME && !UNITY_AOT throw new PlatformNotSupportedException (); #else Variant vt = (Variant)Marshal.PtrToStructure(pSrcNativeVariant, typeof(Variant)); @@ -567,7 +576,7 @@ public static object GetObjectForNativeVariant (IntPtr pSrcNativeVariant) public static T GetObjectForNativeVariant (IntPtr pSrcNativeVariant) { -#if FULL_AOT_RUNTIME +#if FULL_AOT_RUNTIME && !UNITY_AOT throw new PlatformNotSupportedException (); #else Variant vt = (Variant)Marshal.PtrToStructure(pSrcNativeVariant, typeof(Variant)); @@ -577,7 +586,7 @@ public static T GetObjectForNativeVariant (IntPtr pSrcNativeVariant) public static object[] GetObjectsForNativeVariants (IntPtr aSrcNativeVariant, int cVars) { -#if FULL_AOT_RUNTIME +#if FULL_AOT_RUNTIME && !UNITY_AOT throw new PlatformNotSupportedException (); #else if (cVars < 0) @@ -592,7 +601,7 @@ public static object[] GetObjectsForNativeVariants (IntPtr aSrcNativeVariant, in public static T[] GetObjectsForNativeVariants (IntPtr aSrcNativeVariant, int cVars) { -#if FULL_AOT_RUNTIME +#if FULL_AOT_RUNTIME && !UNITY_AOT throw new PlatformNotSupportedException (); #else if (cVars < 0) @@ -608,7 +617,7 @@ public static T[] GetObjectsForNativeVariants (IntPtr aSrcNativeVariant, int [MonoTODO] public static int GetStartComSlot (Type t) { -#if FULL_AOT_RUNTIME +#if FULL_AOT_RUNTIME && !UNITY_AOT throw new PlatformNotSupportedException (); #else throw new NotImplementedException (); @@ -735,7 +744,7 @@ public static object GetUniqueObjectForIUnknown (IntPtr unknown) throw new PlatformNotSupportedException (); } -#if !MOBILE +#if !MOBILE || UNITY_AOT [MethodImplAttribute (MethodImplOptions.InternalCall)] public extern static bool IsComObject (object o); #else @@ -815,14 +824,14 @@ public static T PtrToStructure (IntPtr ptr) { return (T) PtrToStructure (ptr, typeof (T)); } -#if !MOBILE +#if !MOBILE || UNITY_AOT [MethodImplAttribute (MethodImplOptions.InternalCall)] private extern static int QueryInterfaceInternal (IntPtr pUnk, ref Guid iid, out IntPtr ppv); #endif public static int QueryInterface (IntPtr pUnk, ref Guid iid, out IntPtr ppv) { -#if !MOBILE +#if !MOBILE || UNITY_AOT if (pUnk == IntPtr.Zero) throw new ArgumentException ("Value cannot be null.", "pUnk"); return QueryInterfaceInternal (pUnk, ref iid, out ppv); @@ -986,7 +995,7 @@ public static IntPtr ReadIntPtr ([In, MarshalAs (UnmanagedType.AsAny)] object pt [MethodImplAttribute(MethodImplOptions.InternalCall)] public extern static IntPtr ReAllocHGlobal (IntPtr pv, IntPtr cb); -#if !MOBILE +#if !MOBILE || UNITY_AOT [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)] [MethodImplAttribute (MethodImplOptions.InternalCall)] private extern static int ReleaseInternal (IntPtr pUnk); @@ -995,7 +1004,7 @@ public static IntPtr ReadIntPtr ([In, MarshalAs (UnmanagedType.AsAny)] object pt [ReliabilityContract (Consistency.WillNotCorruptState, Cer.Success)] public static int Release (IntPtr pUnk) { -#if !MOBILE +#if !MOBILE || UNITY_AOT if (pUnk == IntPtr.Zero) throw new ArgumentException ("Value cannot be null.", "pUnk"); @@ -1005,14 +1014,14 @@ public static int Release (IntPtr pUnk) #endif } -#if !FULL_AOT_RUNTIME +#if !FULL_AOT_RUNTIME || UNITY_AOT [MethodImplAttribute (MethodImplOptions.InternalCall)] private extern static int ReleaseComObjectInternal (object co); #endif public static int ReleaseComObject (object o) { -#if FULL_AOT_RUNTIME +#if FULL_AOT_RUNTIME && !UNITY_AOT throw new PlatformNotSupportedException (); #else if (o == null) @@ -1752,7 +1761,7 @@ internal static void SetLastWin32Error (int error) { } -#if FEATURE_COMINTEROP || MONO_COM +#if FEATURE_COMINTEROP || MONO_COM || UNITY_AOT // Copied from referencesource/mscorlib/system/runtime/interopservices/marshal.cs //==================================================================== // return the raw IUnknown* for a COM Object not related to current diff --git a/mcs/class/corlib/System/Delegate.cs b/mcs/class/corlib/System/Delegate.cs index 48d78605147f..958b70ce816e 100644 --- a/mcs/class/corlib/System/Delegate.cs +++ b/mcs/class/corlib/System/Delegate.cs @@ -134,6 +134,8 @@ private static bool arg_type_match (Type delArgType, Type argType) { if (!match) { if (delArgType.IsEnum && Enum.GetUnderlyingType (delArgType) == argType) match = true; + else if (argType.IsEnum && Enum.GetUnderlyingType (argType) == delArgType) + match = true; } return match; diff --git a/mcs/class/corlib/System/TimeZone.cs b/mcs/class/corlib/System/TimeZone.cs index 1cfa2ee9bcc3..ba24b44788fa 100644 --- a/mcs/class/corlib/System/TimeZone.cs +++ b/mcs/class/corlib/System/TimeZone.cs @@ -210,5 +210,18 @@ public override bool IsDaylightSavingTime (DateTime dateTime) return LocalTimeZone.IsDaylightSavingTime (dateTime); } + + + // Internal method to get timezone data. + // data[0]: start of daylight saving time (in DateTime ticks). + // data[1]: end of daylight saving time (in DateTime ticks). + // data[2]: utcoffset (in TimeSpan ticks). + // data[3]: additional offset when daylight saving (in TimeSpan ticks). + // name[0]: name of this timezone when not daylight saving. + // name[1]: name of this timezone when daylight saving. +#if UNITY + [MethodImplAttribute(MethodImplOptions.InternalCall)] + public static extern bool GetTimeZoneData (int year, out Int64[] data, out string[] names); +#endif } } diff --git a/mcs/class/corlib/System/TimeZoneInfo.Unity.cs b/mcs/class/corlib/System/TimeZoneInfo.Unity.cs new file mode 100644 index 000000000000..9100a328670d --- /dev/null +++ b/mcs/class/corlib/System/TimeZoneInfo.Unity.cs @@ -0,0 +1,123 @@ +// +// System.TimeZoneInfo helper for Unity +// because the devices cannot access the file system to read the data +// +// Authors: +// Michael DeRoy +// Jonathan Chambers +// +// Copyright 2018 Unity Technologies, Inc. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +#if UNITY + +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Globalization; +using System.IO; + +namespace System { + + public partial class TimeZoneInfo { + enum TimeZoneData + { + DaylightSavingStartIdx, + DaylightSavingEndIdx, + UtcOffsetIdx, + AdditionalDaylightOffsetIdx + }; + + enum TimeZoneNames + { + StandardNameIdx, + DaylightNameIdx + }; + + static AdjustmentRule CreateAdjustmentRule(int year, out Int64[] data, out string[] names, string standardNameCurrentYear, string daylightNameCurrentYear) + { + if(!System.CurrentSystemTimeZone.GetTimeZoneData(year, out data, out names)) + return null; + var startTime = new DateTime (data[(int)TimeZoneData.DaylightSavingStartIdx]); + var endTime = new DateTime (data[(int)TimeZoneData.DaylightSavingEndIdx]); + var daylightOffset = new TimeSpan (data[(int)TimeZoneData.AdditionalDaylightOffsetIdx]); + + /* C# TimeZoneInfo does not support timezones the same way as unix. In unix, timezone files are specified by region such as + * America/New_York or Asia/Singapore. If a region like Asia/Singapore changes it's timezone from +0730 to +08, the UTC offset + * has changed, but there is no support in the C# code to transition to this new UTC offset except for the case of daylight + * savings time. As such we'll only generate timezone rules for a region at the times associated with the timezone of the current year. + */ + if(standardNameCurrentYear != names[(int)TimeZoneNames.StandardNameIdx]) + return null; + if(daylightNameCurrentYear != names[(int)TimeZoneNames.DaylightNameIdx]) + return null; + + var dlsTransitionStart = TransitionTime.CreateFixedDateRule(new DateTime(1,1,1).Add(startTime.TimeOfDay), + startTime.Month, startTime.Day); + var dlsTransitionEnd = TransitionTime.CreateFixedDateRule(new DateTime(1,1,1).Add(endTime.TimeOfDay), + endTime.Month, endTime.Day); + + var rule = TimeZoneInfo.AdjustmentRule.CreateAdjustmentRule(new DateTime(year, 1, 1), + new DateTime(year, 12, DateTime.DaysInMonth(year, 12)), + daylightOffset, + dlsTransitionStart, + dlsTransitionEnd); + return rule; + } + + static TimeZoneInfo CreateLocalUnity () + { + Int64[] data; + string[] names; + int currentYear = DateTime.UtcNow.Year; + if (!System.CurrentSystemTimeZone.GetTimeZoneData (currentYear, out data, out names)) + throw new NotSupportedException ("Can't get timezone name."); + + var utcOffsetTS = TimeSpan.FromTicks(data[(int)TimeZoneData.UtcOffsetIdx]); + char utcOffsetSign = (utcOffsetTS >= TimeSpan.Zero) ? '+' : '-'; + string displayName = "(GMT" + utcOffsetSign + utcOffsetTS.ToString(@"hh\:mm") + ") Local Time"; + string standardDisplayName = names[(int)TimeZoneNames.StandardNameIdx]; + string daylightDisplayName = names[(int)TimeZoneNames.DaylightNameIdx]; + + var adjustmentList = new List(); + bool disableDaylightSavings = data[(int)TimeZoneData.AdditionalDaylightOffsetIdx] <= 0; + //If the timezone supports daylight savings time, generate adjustment rules for the timezone + if(!disableDaylightSavings) + { + //the icall only supports years from 1970 through 2037. + int firstSupportedDate = 1971; + int lastSupportedDate = 2037; + + //first, generate rules from the current year until the last year mktime is guaranteed to supports + for(int year = currentYear; year <= lastSupportedDate; year++) + { + var rule = CreateAdjustmentRule(year, out data, out names, standardDisplayName, daylightDisplayName); + //breakout if timezone changes, or fails + if(rule == null) + break; + adjustmentList.Add(rule); + } + + for(int year = currentYear - 1; year >= firstSupportedDate; year--) + { + var rule = CreateAdjustmentRule(year, out data, out names, standardDisplayName, daylightDisplayName); + //breakout if timezone changes, or fails + if(rule == null) + break; + adjustmentList.Add(rule); + } + + adjustmentList.Sort( (rule1, rule2) => rule1.DateStart.CompareTo(rule2.DateStart) ); + } + return TimeZoneInfo.CreateCustomTimeZone("Local", + utcOffsetTS, + displayName, + standardDisplayName, + daylightDisplayName, + adjustmentList.ToArray(), + disableDaylightSavings); + } + } +} + +#endif diff --git a/mcs/class/corlib/System/TimeZoneInfo.cs b/mcs/class/corlib/System/TimeZoneInfo.cs index a1eaf2a7cf37..d05ff302d814 100644 --- a/mcs/class/corlib/System/TimeZoneInfo.cs +++ b/mcs/class/corlib/System/TimeZoneInfo.cs @@ -1,5 +1,4 @@ - -/* + /* * System.TimeZoneInfo * * Author(s) @@ -122,6 +121,11 @@ private static string readlink (string path) private static bool TryGetNameFromPath (string path, out string name) { name = null; +#if UNITY + //Avoids calling readlink on webgl, which causes abort due to dlopen + if(!File.Exists(path)) + return false; +#endif var linkPath = readlink (path); if (linkPath != null) { if (Path.IsPathRooted(linkPath)) @@ -165,14 +169,34 @@ static TimeZoneInfo CreateLocal () } #endif +#if UNITY + TimeZoneInfo localTimeZoneFallback = null; + try { + localTimeZoneFallback = CreateLocalUnity(); + } catch { + localTimeZoneFallback = null; + } + + if (localTimeZoneFallback == null) + localTimeZoneFallback = Utc; +#endif + var tz = Environment.GetEnvironmentVariable ("TZ"); if (tz != null) { if (tz == String.Empty) +#if UNITY + return localTimeZoneFallback; +#else return Utc; +#endif try { return FindSystemTimeZoneByFileName (tz, Path.Combine (TimeZoneDirectory, tz)); } catch { +#if UNITY + return localTimeZoneFallback; +#else return Utc; +#endif } } @@ -191,7 +215,11 @@ static TimeZoneInfo CreateLocal () } } +#if UNITY + return localTimeZoneFallback; +#else return Utc; +#endif } static TimeZoneInfo FindSystemTimeZoneByIdCore (string id) diff --git a/mcs/class/corlib/System/WeakAttribute.cs b/mcs/class/corlib/System/WeakAttribute.cs index 72de431d1727..b7a377935d1a 100644 --- a/mcs/class/corlib/System/WeakAttribute.cs +++ b/mcs/class/corlib/System/WeakAttribute.cs @@ -1,6 +1,6 @@ using System; -#if MOBILE +#if MOBILE && !UNITY namespace System { [AttributeUsage(AttributeTargets.Field)] diff --git a/mcs/class/corlib/Test/System/DelegateTest.cs b/mcs/class/corlib/Test/System/DelegateTest.cs index 26c449615b30..19a4bd894dc3 100644 --- a/mcs/class/corlib/Test/System/DelegateTest.cs +++ b/mcs/class/corlib/Test/System/DelegateTest.cs @@ -1395,6 +1395,23 @@ public void EnumBaseTypeConversion () { Assert.IsTrue (d (0, 0)); } + [Test] + public void EnumBaseTypeConversion2 () { + Func dm = EnumArg; + var d = (Func)Delegate.CreateDelegate (typeof (Func), dm.Method); + Assert.AreEqual (1, d (1)); + } + + public enum Enum22 { + none, + one, + two + } + + public static int EnumArg (Enum22 e) { + return (int)e; + } + #if !MONOTOUCH && !FULL_AOT_RUNTIME public static void DynInvokeWithClosedFirstArg (object a, object b) { diff --git a/mcs/class/corlib/Test/System/TypeTest.cs b/mcs/class/corlib/Test/System/TypeTest.cs index 6608ef9cc430..2c9bd2728afd 100644 --- a/mcs/class/corlib/Test/System/TypeTest.cs +++ b/mcs/class/corlib/Test/System/TypeTest.cs @@ -4886,6 +4886,30 @@ public void NullFullNameForSpecificGenericTypes() } } + // https://github.com/mono/mono/issues/6579 + [Test] + public void GetInterfaceCaseInsensitiveTest() + { + var type = typeof(Dictionary); + + Assert.NotNull ( + type.GetInterface ("System.Collections.IDictionary", false), + "strict named interface must be found (ignoreCase = false)" + ); + Assert.NotNull ( + type.GetInterface ("System.Collections.IDictionary", true), + "strict named interface must be found (ignoreCase = true)" + ); + Assert.Null ( + type.GetInterface ("System.Collections.Idictionary", false), + "interface, named in mixed case, must not be found (ignoreCase = false)" + ); + Assert.NotNull ( + type.GetInterface ("System.Collections.Idictionary", true), + "interface, named in mixed case, must be found (ignoreCase = true)" + ); + } + interface Bug59738Interface { } diff --git a/mcs/class/corlib/corlib.dll.sources b/mcs/class/corlib/corlib.dll.sources index fa940530add6..ec1c6983e422 100644 --- a/mcs/class/corlib/corlib.dll.sources +++ b/mcs/class/corlib/corlib.dll.sources @@ -142,6 +142,7 @@ System/TimeZoneInfo.cs System/TimeZoneInfo.Android.cs System/TimeZoneInfo.MonoTouch.cs System/TimeZoneInfo.Serialization.cs +System/TimeZoneInfo.Unity.cs System/TimeZoneInfo.WinRT.cs ../../build/common/MonoTODOAttribute.cs System/TypeIdentifier.cs diff --git a/mcs/class/referencesource/System.Core/System/Linq/Enumerable.cs b/mcs/class/referencesource/System.Core/System/Linq/Enumerable.cs index 84a043557188..91fdedb40f99 100644 --- a/mcs/class/referencesource/System.Core/System/Linq/Enumerable.cs +++ b/mcs/class/referencesource/System.Core/System/Linq/Enumerable.cs @@ -2776,7 +2776,11 @@ public string Empty { get { +#if UNITY_AOT + return SR.EmptyEnumerable; +#else return Strings.EmptyEnumerable; +#endif } } } @@ -2829,4 +2833,49 @@ public object[] Items [System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.Never)] private int count; } + +#if UNITY_AOT + // + /// An iterator that can produce an array or through an optimized path. + /// + internal interface IIListProvider : IEnumerable + { + /// + /// Produce an array of the sequence through an optimized path. + /// + /// The array. + TElement[] ToArray(); + + /// + /// Produce a of the sequence through an optimized path. + /// + /// The . + List ToList(); + + /// + /// Returns the count of elements in the sequence. + /// + /// If true then the count should only be calculated if doing + /// so is quick (sure or likely to be constant time), otherwise -1 should be returned. + /// The number of elements. + int GetCount(bool onlyIfCheap); + } + + internal static partial class Error + { + internal static Exception ArgumentNull(string s) => new ArgumentNullException(s); + + internal static Exception ArgumentOutOfRange(string s) => new ArgumentOutOfRangeException(s); + + internal static Exception MoreThanOneElement() => new InvalidOperationException(SR.MoreThanOneElement); + + internal static Exception MoreThanOneMatch() => new InvalidOperationException(SR.MoreThanOneMatch); + + internal static Exception NoElements() => new InvalidOperationException(SR.NoElements); + + internal static Exception NoMatch() => new InvalidOperationException(SR.NoMatch); + + internal static Exception NotSupported() => new NotSupportedException(); + } +#endif } diff --git a/mcs/class/referencesource/System/compmod/system/diagnostics/DiagnosticsConfiguration.cs b/mcs/class/referencesource/System/compmod/system/diagnostics/DiagnosticsConfiguration.cs index 5b5c81384b82..8bfb15ee1d38 100644 --- a/mcs/class/referencesource/System/compmod/system/diagnostics/DiagnosticsConfiguration.cs +++ b/mcs/class/referencesource/System/compmod/system/diagnostics/DiagnosticsConfiguration.cs @@ -168,8 +168,10 @@ internal static SystemDiagnosticsSection SystemDiagnosticsSection { } private static SystemDiagnosticsSection GetConfigSection() { - SystemDiagnosticsSection configSection = (SystemDiagnosticsSection) PrivilegedConfigurationManager.GetSection("system.diagnostics"); - return configSection; + object o = PrivilegedConfigurationManager.GetSection("system.diagnostics"); + if (o is SystemDiagnosticsSection) + return (SystemDiagnosticsSection)o; + return null; } internal static bool IsInitializing() { diff --git a/mcs/class/referencesource/System/services/monitoring/system/diagnosticts/Process.cs b/mcs/class/referencesource/System/services/monitoring/system/diagnosticts/Process.cs index 4fc2f7c2078c..10fb4ffe220c 100644 --- a/mcs/class/referencesource/System/services/monitoring/system/diagnosticts/Process.cs +++ b/mcs/class/referencesource/System/services/monitoring/system/diagnosticts/Process.cs @@ -230,7 +230,7 @@ public int ExitCode { get { EnsureState(State.Exited); #if MONO - if (exitCode == -1) + if (exitCode == -1 && !Environment.IsRunningOnWindows) throw new InvalidOperationException ("Cannot get the exit code from a non-child process on Unix"); #endif return exitCode; diff --git a/mcs/class/referencesource/System/services/monitoring/system/diagnosticts/ProcessModuleCollection.cs b/mcs/class/referencesource/System/services/monitoring/system/diagnosticts/ProcessModuleCollection.cs index 85d996b827a5..c774c51d173b 100644 --- a/mcs/class/referencesource/System/services/monitoring/system/diagnosticts/ProcessModuleCollection.cs +++ b/mcs/class/referencesource/System/services/monitoring/system/diagnosticts/ProcessModuleCollection.cs @@ -54,7 +54,7 @@ public void CopyTo(ProcessModule[] array, int index) { InnerList.CopyTo(array, index); } -#if MOBILE +#if MOBILE && !UNITY [Obsolete ("This API is no longer available", true)] public int Capacity { get { diff --git a/mcs/class/referencesource/System/services/monitoring/system/diagnosticts/ProcessThreadCollection.cs b/mcs/class/referencesource/System/services/monitoring/system/diagnosticts/ProcessThreadCollection.cs index 94fa2f43bbd1..80e77f748dd5 100644 --- a/mcs/class/referencesource/System/services/monitoring/system/diagnosticts/ProcessThreadCollection.cs +++ b/mcs/class/referencesource/System/services/monitoring/system/diagnosticts/ProcessThreadCollection.cs @@ -78,7 +78,7 @@ public void CopyTo(ProcessThread[] array, int index) { InnerList.CopyTo(array, index); } -#if MOBILE +#if MOBILE && !UNITY [Obsolete ("This API is no longer available", true)] public int Capacity { get { diff --git a/mcs/class/referencesource/mscorlib/system/reflection/binder.cs b/mcs/class/referencesource/mscorlib/system/reflection/binder.cs index 3d14d37f29c3..dd8d60f2f506 100644 --- a/mcs/class/referencesource/mscorlib/system/reflection/binder.cs +++ b/mcs/class/referencesource/mscorlib/system/reflection/binder.cs @@ -52,7 +52,7 @@ public abstract PropertyInfo SelectProperty(BindingFlags bindingAttr,PropertyInf public abstract void ReorderArgumentArray(ref Object[] args, Object state); -#if !FEATURE_COMINTEROP +#if !FEATURE_COMINTEROP && !UNITY // CanChangeType // This method checks whether the value can be converted into the property type. public virtual bool CanChangeType(Object value,Type type,CultureInfo culture) diff --git a/mcs/class/referencesource/mscorlib/system/rttype.cs b/mcs/class/referencesource/mscorlib/system/rttype.cs index 61b46433b342..42a445bc5cf5 100644 --- a/mcs/class/referencesource/mscorlib/system/rttype.cs +++ b/mcs/class/referencesource/mscorlib/system/rttype.cs @@ -3413,9 +3413,12 @@ public override Type GetInterface(String fullname, bool ignoreCase) #if MONO List list = null; + var nameComparison = ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal; foreach (RuntimeType t in GetInterfaces ()) { - if (t.Name != name) - continue; + + if (!String.Equals(t.Name, name, nameComparison)) { + continue; + } if (list == null) list = new List (2); diff --git a/mcs/class/referencesource/mscorlib/system/runtime/interopservices/attributes.cs b/mcs/class/referencesource/mscorlib/system/runtime/interopservices/attributes.cs index a970216007b9..1c5f52bcbb26 100644 --- a/mcs/class/referencesource/mscorlib/system/runtime/interopservices/attributes.cs +++ b/mcs/class/referencesource/mscorlib/system/runtime/interopservices/attributes.cs @@ -1,4 +1,4 @@ -#if MONO_COM +#if MONO_COM || UNITY_AOT #define FEATURE_COMINTEROP #endif // ==++== diff --git a/mcs/class/referencesource/mscorlib/system/runtime/interopservices/windowsruntime/windowsruntimemarshal.cs b/mcs/class/referencesource/mscorlib/system/runtime/interopservices/windowsruntime/windowsruntimemarshal.cs index 15a0c70d64dd..9ef7580c9e30 100644 --- a/mcs/class/referencesource/mscorlib/system/runtime/interopservices/windowsruntime/windowsruntimemarshal.cs +++ b/mcs/class/referencesource/mscorlib/system/runtime/interopservices/windowsruntime/windowsruntimemarshal.cs @@ -1278,7 +1278,7 @@ public static IActivationFactory GetActivationFactory(Type type) if (type == null) throw new ArgumentNullException("type"); -#if FEATURE_COMINTEROP || MONO_COM +#if FEATURE_COMINTEROP || MONO_COM || UNITY_AOT if (type.IsWindowsRuntimeObject && type.IsImport) { return (IActivationFactory)Marshal.GetNativeActivationFactory(type); diff --git a/mcs/class/referencesource/mscorlib/system/threading/synchronizationcontext.cs b/mcs/class/referencesource/mscorlib/system/threading/synchronizationcontext.cs index 98e2f3fb73eb..4c5290eb74a0 100644 --- a/mcs/class/referencesource/mscorlib/system/threading/synchronizationcontext.cs +++ b/mcs/class/referencesource/mscorlib/system/threading/synchronizationcontext.cs @@ -252,7 +252,7 @@ public static void SetSynchronizationContext(SynchronizationContext syncContext) ec.SynchronizationContextNoFlow = syncContext; } -#if MOBILE_LEGACY +#if MOBILE_LEGACY && !UNITY_AOT [Obsolete("The method is not supported and will be removed")] public static void SetThreadStaticContext(SynchronizationContext syncContext) { diff --git a/mcs/class/referencesource/mscorlib/system/type.cs b/mcs/class/referencesource/mscorlib/system/type.cs index ef7472f5016d..1f337f0c1fef 100644 --- a/mcs/class/referencesource/mscorlib/system/type.cs +++ b/mcs/class/referencesource/mscorlib/system/type.cs @@ -1249,7 +1249,7 @@ public bool IsCOMObject { get {return IsCOMObjectImpl();} } -#if FEATURE_COMINTEROP || MONO_COM +#if FEATURE_COMINTEROP || MONO_COM || UNITY_AOT internal bool IsWindowsRuntimeObject { [Pure] get { return IsWindowsRuntimeObjectImpl(); } @@ -1313,7 +1313,7 @@ protected virtual bool IsValueTypeImpl() // Protected routine to determine if this class represents a COM object abstract protected bool IsCOMObjectImpl(); -#if FEATURE_COMINTEROP || MONO_COM +#if FEATURE_COMINTEROP || MONO_COM || UNITY_AOT // Protected routine to determine if this class represents a Windows Runtime object virtual internal bool IsWindowsRuntimeObjectImpl() { throw new NotImplementedException(); diff --git a/mcs/errors/cs0151-4.cs b/mcs/errors/cs0151-4.cs index 0e45b1a9049d..c9e05589e4dd 100644 --- a/mcs/errors/cs0151-4.cs +++ b/mcs/errors/cs0151-4.cs @@ -1,5 +1,6 @@ // CS0151: A switch expression of type `S1?' cannot be converted to an integral type, bool, char, string, enum or nullable type -// Line: 24 +// Line: 25 +// Compiler options: -langversion:5 using System; diff --git a/mcs/errors/known-issues-net_4_x b/mcs/errors/known-issues-net_4_x index c9ed9317350d..54902e03e7be 100644 --- a/mcs/errors/known-issues-net_4_x +++ b/mcs/errors/known-issues-net_4_x @@ -14,6 +14,9 @@ # Parser problems cs0080.cs +# Undocumented switch governing rules +cs0151-4.cs NO ERROR + # Operators cs0457-2.cs cs0457.cs diff --git a/mcs/mcs/convert.cs b/mcs/mcs/convert.cs index f4012fbd2223..2fd5bcc55859 100644 --- a/mcs/mcs/convert.cs +++ b/mcs/mcs/convert.cs @@ -1232,6 +1232,13 @@ public static Expression UserDefinedConversion (ResolveContext rc, Expression so FindApplicableUserDefinedConversionOperators (rc, operators, source_type_expr, target_type, restr, ref candidates); } + if (source_type_expr == source && source_type.IsNullableType) { + operators = MemberCache.GetUserOperator (source_type.TypeArguments [0], Operator.OpType.Implicit, declared_only); + if (operators != null) { + FindApplicableUserDefinedConversionOperators (rc, operators, source_type_expr, target_type, restr, ref candidates); + } + } + if (!implicitOnly) { operators = MemberCache.GetUserOperator (source_type, Operator.OpType.Explicit, declared_only); if (operators != null) { diff --git a/mcs/tests/gtest-647.cs b/mcs/tests/gtest-647.cs new file mode 100644 index 000000000000..4aae641f85f2 --- /dev/null +++ b/mcs/tests/gtest-647.cs @@ -0,0 +1,34 @@ +using System; + +public class Program +{ + public static int Main () + { + int B = default (MyStruct?); + if (MyStruct.counter != 1) + return 1; + + switch (default (MyStruct?)) { + case 0: + break; + default: + return 2; + } + + if (MyStruct.counter != 2) + return 4; + + return 0; + } + + public struct MyStruct + { + public static int counter; + + public static implicit operator int (MyStruct? s) + { + ++counter; + return 0; + } + } +} \ No newline at end of file diff --git a/mcs/tests/ver-il-net_4_x.xml b/mcs/tests/ver-il-net_4_x.xml index 3d4d271f3db2..4180824c10d5 100644 --- a/mcs/tests/ver-il-net_4_x.xml +++ b/mcs/tests/ver-il-net_4_x.xml @@ -11064,7 +11064,7 @@ - 72 + 60 62 @@ -19505,7 +19505,7 @@ - 267 + 255 7 @@ -20144,6 +20144,21 @@ + + + + 99 + + + 7 + + + + + 22 + + + diff --git a/mono/eglib/gdate-unity.c b/mono/eglib/gdate-unity.c new file mode 100644 index 000000000000..c25eda909206 --- /dev/null +++ b/mono/eglib/gdate-unity.c @@ -0,0 +1,8 @@ +#include +#include "Thread-c-api.h" + +void +g_usleep(gulong microseconds) +{ + UnityPalSleep(microseconds/1000); +} diff --git a/mono/eglib/gdir-unity.c b/mono/eglib/gdir-unity.c new file mode 100644 index 000000000000..a3d8eec30e93 --- /dev/null +++ b/mono/eglib/gdir-unity.c @@ -0,0 +1,134 @@ +#include + +#include "Directory-c-api.h" +#include "Error-c-api.h" + +struct _GDir { + UnityPalFindHandle* handle; + gchar* current; + gchar* next; + const gchar* path_for_rewind; +}; + +static gboolean +setup_dir_handle(GDir*dir, const gchar* path, GError **error) +{ + gchar* path_search; + char* result_file_name = NULL; + gint unused_attributes; + UnityPalErrorCode result; + + dir->path_for_rewind = g_strdup (path); + path_search = g_malloc ((strlen(path) + 3)*sizeof(gchar)); + strcpy (path_search, path); +#ifdef G_OS_WIN32 + strcat (path_search, "\\*"); +#else + strcat (path_search, "/*"); +#endif + + dir->handle = UnityPalDirectoryFindHandleNew(path_search); + result = UnityPalDirectoryFindFirstFile(dir->handle, path_search, &result_file_name, &unused_attributes); + if (!UnityPalSuccess(result)) { + if (error) + *error = g_error_new (G_LOG_DOMAIN, g_file_error_from_errno (result), strerror (result)); + g_free (dir); + return FALSE; + } + + while ((strcmp (result_file_name, ".") == 0) || (strcmp (result_file_name, "..") == 0)) { + result = UnityPalDirectoryFindNextFile(dir->handle, &result_file_name, &unused_attributes); + if (!UnityPalSuccess(result)) { + result_file_name = NULL; + break; + } + } + + dir->current = NULL; + dir->next = result_file_name; + return TRUE; +} + +static void close_dir_handle(GDir* dir) +{ + UnityPalDirectoryCloseOSHandle(dir->handle); + UnityPalDirectoryFindHandleDelete(dir->handle); + dir->handle = 0; +} + +GDir * +g_dir_open (const gchar *path, guint flags, GError **error) +{ + GDir *dir; + gboolean success; + + g_return_val_if_fail (path != NULL, NULL); + g_return_val_if_fail (error == NULL || *error == NULL, NULL); + + dir = g_new0 (GDir, 1); + + success = setup_dir_handle(dir, path, error); + if (!success) + return NULL; + + return dir; +} + +const gchar * +g_dir_read_name (GDir *dir) +{ + char* result_file_name; + gint unused_attributes; + UnityPalErrorCode result; + + g_return_val_if_fail (dir != NULL && dir->handle != 0, NULL); + + if (dir->current) + g_free (dir->current); + dir->current = NULL; + + dir->current = dir->next; + + if (!dir->current) + return NULL; + + dir->next = NULL; + + do { + result = UnityPalDirectoryFindNextFile(dir->handle, &result_file_name, &unused_attributes); + if (!UnityPalSuccess(result)) { + dir->next = NULL; + return dir->current; + } + } while ((strcmp (result_file_name, ".") == 0) || (strcmp (result_file_name, "..") == 0)); + + dir->next = result_file_name; + return dir->current; +} + +void +g_dir_rewind (GDir *dir) +{ + g_return_if_fail (dir != NULL && dir->handle != NULL); + + close_dir_handle(dir); + setup_dir_handle(dir, dir->path_for_rewind, NULL); +} + +void +g_dir_close (GDir *dir) +{ + g_return_if_fail (dir != NULL && dir->handle != 0); + + if (dir->current) + g_free (dir->current); + dir->current = NULL; + if (dir->next) + g_free (dir->next); + dir->next = NULL; + if (dir->path_for_rewind) + g_free(dir->path_for_rewind); + dir->path_for_rewind = NULL; + close_dir_handle(dir); + g_free (dir); +} diff --git a/mono/eglib/gfile-unity.c b/mono/eglib/gfile-unity.c new file mode 100644 index 000000000000..c7c6edf232f1 --- /dev/null +++ b/mono/eglib/gfile-unity.c @@ -0,0 +1,107 @@ +#include +#include +#include + +#include "File-c-api.h" +#include "Directory-c-api.h" + +gboolean +g_file_get_contents(const gchar *filename, gchar **contents, gsize *length, GError **error) +{ + gchar *str; + int palError; + UnityPalFileStat st; + long offset; + UnityPalFileHandle* handle = NULL; + int nread; + + handle = UnityPalOpen(filename, kFileModeOpen, 0, 0, 0, &palError); + if (handle == NULL) + { + if (error != NULL) + *error = g_error_new(G_LOG_DOMAIN, g_file_error_from_errno(palError), "Error opening file"); + return FALSE; + } + + if (UnityPalGetFileStat(filename, &st, &palError) == 0) + { + if (error != NULL) + *error = g_error_new(G_LOG_DOMAIN, g_file_error_from_errno(palError), "Error getting file attributes"); + UnityPalClose(handle, &palError); + return FALSE; + } + + str = g_malloc(st.length + 1); + offset = 0; + do + { + nread = UnityPalRead(handle, str + offset, st.length - offset, &palError); + if (nread > 0) + { + offset += nread; + } + } + while ((nread > 0 && offset < st.length) || (nread == -1 && errno == EINTR)); + + UnityPalClose(handle, &palError); + str[st.length] = '\0'; + if (length) + { + *length = st.length; + } + *contents = str; + return TRUE; +} + +gchar * +g_get_current_dir(void) +{ + int unused; + return UnityPalDirectoryGetCurrent(&unused); +} + +gboolean +g_file_test(const gchar *filename, GFileTest test) +{ + int palError = 0; + UnityPalFileAttributes attr; + + if (filename == NULL || test == 0) + return FALSE; + + attr = UnityPalGetFileAttributes(filename, &palError); + + if (palError != 0) + return FALSE; + + if ((test & G_FILE_TEST_EXISTS) != 0) + { + return TRUE; + } + + if ((test & G_FILE_TEST_IS_EXECUTABLE) != 0) + { + return UnityPalIsExecutable(filename) ? TRUE : FALSE; + } + + if ((test & G_FILE_TEST_IS_REGULAR) != 0) + { + if (attr & (kFileAttributeDevice | kFileAttributeDirectory)) + return FALSE; + return TRUE; + } + + if ((test & G_FILE_TEST_IS_DIR) != 0) + { + if (attr & kFileAttributeDirectory) + return TRUE; + } + + /* make this last in case it is OR'd with something else */ + if ((test & G_FILE_TEST_IS_SYMLINK) != 0) + { + return FALSE; + } + + return FALSE; +} diff --git a/mono/eglib/glib.h b/mono/eglib/glib.h index 333639f677ab..c7a8b972cef6 100644 --- a/mono/eglib/glib.h +++ b/mono/eglib/glib.h @@ -14,7 +14,11 @@ #endif #include + +/* inttypes.h is only available from VS2013 */ +#if !defined(_MSC_VER) || (_MSC_VER >= 1800) #include +#endif #include #ifndef EGLIB_NO_REMAP @@ -44,6 +48,10 @@ #define G_END_DECLS #endif +#if defined(_MSC_VER) && _MSC_VER < 1900 +#define inline __inline +#endif + G_BEGIN_DECLS /* @@ -881,7 +889,11 @@ gboolean g_file_test (const gchar *filename, GFileTest test); #define g_open open #define g_rename rename #define g_stat stat +#ifdef G_OS_WIN32 +#define g_unlink _unlink +#else #define g_unlink unlink +#endif #define g_fopen fopen #define g_lstat lstat #define g_rmdir rmdir diff --git a/mono/eglib/gmisc-unity.c b/mono/eglib/gmisc-unity.c new file mode 100644 index 000000000000..b1d32812e74a --- /dev/null +++ b/mono/eglib/gmisc-unity.c @@ -0,0 +1,77 @@ +#include +#include + +#include "Environment-c-api.h" +#include "Locale-c-api.h" +#include "Path-c-api.h" + +gboolean +g_hasenv(const gchar *variable) +{ + return g_getenv(variable) != NULL; +} + +gchar * +g_getenv(const gchar *variable) +{ + return UnityPalGetEnvironmentVariable(variable); +} + +gboolean +g_setenv(const gchar *variable, const gchar *value, gboolean overwrite) +{ + // This method assumes overwrite is always true. + UnityPalSetEnvironmentVariable(variable, value); + + // No code in Mono actually checks the return value. + return TRUE; +} + +void +g_unsetenv(const gchar *variable) +{ + UnityPalSetEnvironmentVariable(variable, ""); +} + +static gboolean locale_initialized = FALSE; + +gchar* +g_win32_getlocale(void) +{ + if (locale_initialized == FALSE) + { + UnityPalLocaleInitialize(); + locale_initialized = TRUE; + } + + return UnityPalGetLocale(); +} + +gboolean +g_path_is_absolute(const char *filename) +{ + return UnityPalIsAbsolutePath(filename); +} + +const gchar * +g_get_home_dir(void) +{ + return UnityPalGetHomeDirectory(); +} + +const char * +g_get_user_name(void) +{ + return UnityPalGetOsUserName(); +} + +static const char *tmp_dir; + +const gchar * +g_get_tmp_dir(void) +{ + if (tmp_dir == NULL) + tmp_dir = UnityPalGetTempPath(); + + return tmp_dir; +} diff --git a/mono/eglib/gpath.c b/mono/eglib/gpath.c index 21e777046034..01113ee0ce69 100644 --- a/mono/eglib/gpath.c +++ b/mono/eglib/gpath.c @@ -251,11 +251,17 @@ g_find_program_in_path (const gchar *program) x = NULL; probe_path = g_build_path (G_DIR_SEPARATOR_S, l, program, NULL); - if (access (probe_path, X_OK) == 0){ /* FIXME: on windows this is just a read permissions test */ +#if !defined(NO_HAVE_ACCESS) +#ifdef G_OS_WIN32 + if (_access (probe_path, X_OK) == 0){ /* FIXME: on windows this is just a read permissions test */ +#else + if (access(probe_path, X_OK) == 0) { +#endif g_free (curdir); g_free (p); return probe_path; } +#endif g_free (probe_path); #ifdef G_OS_WIN32 @@ -265,12 +271,14 @@ g_find_program_in_path (const gchar *program) while (suffix_list[listx]) { program_exe = g_strjoin(NULL,program,suffix_list[listx],NULL); probe_path = g_build_path (G_DIR_SEPARATOR_S, l, program_exe, NULL); - if (access (probe_path, X_OK) == 0){ /* FIXME: on windows this is just a read permissions test */ +#if !defined(NO_HAVE_ACCESS) + if (_access (probe_path, X_OK) == 0){ /* FIXME: on windows this is just a read permissions test */ g_free (curdir); g_free (p); g_free (program_exe); return probe_path; } +#endif listx++; g_free (probe_path); g_free (program_exe); diff --git a/mono/eglib/gunicode-win32-uwp.c b/mono/eglib/gunicode-win32-uwp.c index ef36ffc17f51..359ed2458431 100644 --- a/mono/eglib/gunicode-win32-uwp.c +++ b/mono/eglib/gunicode-win32-uwp.c @@ -19,9 +19,9 @@ g_get_charset (G_CONST_RETURN char **charset) { if (my_charset == NULL) { static char buf [14]; - CPINFOEXA cp_info; + CPINFOEXW cp_info; - GetCPInfoExA (CP_ACP, 0, &cp_info); + GetCPInfoExW (CP_ACP, 0, &cp_info); sprintf (buf, "CP%u", cp_info.CodePage); my_charset = buf; is_utf8 = FALSE; diff --git a/mono/eglib/gunicode-win32.c b/mono/eglib/gunicode-win32.c index a35cfcd48c12..993583629ca3 100644 --- a/mono/eglib/gunicode-win32.c +++ b/mono/eglib/gunicode-win32.c @@ -7,7 +7,7 @@ #include #include -#if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) +#if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT | HAVE_XBOXONE_WINAPI_SUPPORT) #define CODESET 1 #include @@ -30,7 +30,7 @@ g_get_charset (G_CONST_RETURN char **charset) return is_utf8; } -#else /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */ +#else /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT | HAVE_XBOXONE_WINAPI_SUPPORT) */ #ifdef _MSC_VER // Quiet Visual Studio linker warning, LNK4221, in cases when this source file intentional ends up empty. diff --git a/mono/metadata/Makefile.am b/mono/metadata/Makefile.am index 1ea96434ef5a..c0e5065842f9 100644 --- a/mono/metadata/Makefile.am +++ b/mono/metadata/Makefile.am @@ -96,13 +96,24 @@ endif boehm_libraries = $(shared_boehm_libraries) libmonoruntime-static.la endif +if SUPPORT_BDWGC if DISABLE_EXECUTABLES -noinst_LTLIBRARIES = libmonoruntime-config.la $(shared_sgen_libraries) $(shared_boehm_libraries) +shared_bdwgc_libraries = libmonoruntimebdwgc.la else -noinst_LTLIBRARIES = libmonoruntime-config.la $(boehm_libraries) $(sgen_libraries) +if SHARED_MONO +shared_bdwgc_libraries = libmonoruntimebdwgc.la +endif +endif +bdwgc_libraries = $(shared_bdwgc_libraries) libmonoruntimebdwgc-static.la endif -AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/mono $(LIBGC_CPPFLAGS) $(GLIB_CFLAGS) $(SHARED_CFLAGS) +if DISABLE_EXECUTABLES +noinst_LTLIBRARIES = libmonoruntime-config.la $(shared_sgen_libraries) $(shared_boehm_libraries) $(shared_bdwgc_libraries) +else +noinst_LTLIBRARIES = libmonoruntime-config.la $(boehm_libraries) $(sgen_libraries) $(bdwgc_libraries) +endif + +AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/mono $(GLIB_CFLAGS) $(SHARED_CFLAGS) # # Make sure any prefix changes are updated in the binaries too. @@ -132,8 +143,16 @@ null_gc_sources = \ null-gc-handles.h \ null-gc-handles.c +unity_sources = \ + unity-memory-info.c \ + unity-memory-info.h \ + unity-utils.c \ + unity-utils.h \ + unity-icall.c + common_sources = \ $(platform_sources) \ + $(unity_sources) \ appdomain.c \ domain.c \ appdomain-icalls.h \ @@ -301,6 +320,9 @@ gc_dependent_sources = \ gc.c \ monitor.c +unity_gc_dependent_sources = \ + unity-liveness.c + boehm_sources = \ boehm-gc.c @@ -317,19 +339,28 @@ sgen_sources = \ sgen-mono.c \ sgen-client-mono.h -libmonoruntime_la_SOURCES = $(common_sources) $(gc_dependent_sources) $(null_gc_sources) $(boehm_sources) -libmonoruntime_la_CFLAGS = $(BOEHM_DEFINES) +libmonoruntime_la_SOURCES = $(common_sources) $(gc_dependent_sources) $(unity_gc_dependent_sources) $(null_gc_sources) $(boehm_sources) +libmonoruntime_la_CFLAGS = $(BOEHM_DEFINES) $(LIBGC_CPPFLAGS) libmonoruntime_la_LIBADD = libmonoruntime-config.la -libmonoruntimesgen_la_SOURCES = $(common_sources) $(gc_dependent_sources) $(sgen_sources) +libmonoruntimebdwgc_la_SOURCES = $(common_sources) $(gc_dependent_sources) $(unity_gc_dependent_sources) $(null_gc_sources) $(boehm_sources) +libmonoruntimebdwgc_la_CFLAGS = $(BDWGC_DEFINES) $(LIBGCBDWGC_CPPFLAGS) +libmonoruntimebdwgc_la_LIBADD = libmonoruntime-config.la $(btls_libs) + +libmonoruntimesgen_la_SOURCES = $(common_sources) $(gc_dependent_sources) $(unity_gc_dependent_sources) $(sgen_sources) libmonoruntimesgen_la_CFLAGS = $(SGEN_DEFINES) libmonoruntimesgen_la_LIBADD = libmonoruntime-config.la libmonoruntime_static_la_SOURCES = $(libmonoruntime_la_SOURCES) libmonoruntime_static_la_LDFLAGS = -static -libmonoruntime_static_la_CFLAGS = $(BOEHM_DEFINES) +libmonoruntime_static_la_CFLAGS = $(BOEHM_DEFINES) $(LIBGC_CPPFLAGS) libmonoruntime_static_la_LIBADD = $(bundle_obj) libmonoruntime-config.la +libmonoruntimebdwgc_static_la_SOURCES = $(libmonoruntimebdwgc_la_SOURCES) +libmonoruntimebdwgc_static_la_LDFLAGS = -static +libmonoruntimebdwgc_static_la_CFLAGS = $(BDWGC_DEFINES) $(LIBGCBDWGC_CPPFLAGS) +libmonoruntimebdwgc_static_la_LIBADD = $(bundle_obj) libmonoruntime-config.la $(btls_static_libs) + libmonoruntimesgen_static_la_SOURCES = $(libmonoruntimesgen_la_SOURCES) libmonoruntimesgen_static_la_LDFLAGS = -static libmonoruntimesgen_static_la_CFLAGS = $(SGEN_DEFINES) diff --git a/mono/metadata/appdomain.c b/mono/metadata/appdomain.c index 304432e39c34..3234f6228ea9 100644 --- a/mono/metadata/appdomain.c +++ b/mono/metadata/appdomain.c @@ -2175,6 +2175,9 @@ ves_icall_System_AppDomain_LoadAssemblyRaw (MonoAppDomainHandle ad, return refass; } + /* Clear the reference added by mono_image_open_from_data_full above */ + mono_image_close (image); + refass = mono_assembly_get_object_handle (domain, ass, error); if (!MONO_HANDLE_IS_NULL(refass)) MONO_HANDLE_SET (refass, evidence, evidence); diff --git a/mono/metadata/assembly.c b/mono/metadata/assembly.c index 4d4409d96561..b681385be67a 100644 --- a/mono/metadata/assembly.c +++ b/mono/metadata/assembly.c @@ -441,6 +441,56 @@ mono_set_assemblies_path (const char* path) } } +/** +* mono_set_assemblies_path_null_separated: +* @path: list of paths that contain directories where Mono will look for assemblies +* +* Use this method to override the standard assembly lookup system and +* override any assemblies coming from the GAC. This is the method +* that supports the MONO_PATH variable. +* +* Notice that MONO_PATH and this method are really a very bad idea as +* it prevents the GAC from working and it prevents the standard +* resolution mechanisms from working. Nonetheless, for some debugging +* situations and bootstrapping setups, this is useful to have. +*/ +void +mono_set_assemblies_path_null_separated(const char* path) +{ + char **dest; + + int numPaths = 0; + char* path_count_ptr = path; + while (*path_count_ptr) + { + path_count_ptr += strlen(path_count_ptr) + 1; + numPaths++; + } + dest = g_new(char**, sizeof(char*) * (numPaths + 1)); + + if (assemblies_path) + g_strfreev(assemblies_path); + assemblies_path = dest; + char* current_path = path; + while (*current_path) + { + *dest++ = mono_path_canonicalize(current_path); + current_path += strlen(current_path) + 1; + } + *dest = NULL; + + if (g_getenv("MONO_DEBUG") == NULL) + return; + + char** print_assembly_str = assemblies_path; + while (*print_assembly_str) { + if (**print_assembly_str && !g_file_test(*print_assembly_str, G_FILE_TEST_IS_DIR)) + g_warning("'%s' in MONO_PATH doesn't exist or has wrong permissions.", *print_assembly_str); + + print_assembly_str++; + } +} + static void check_path_env (void) { @@ -777,7 +827,7 @@ compute_base (char *path) return NULL; /* Not a well known Mono executable, we are embedded, cant guess the base */ - if (strcmp (p, "/mono") && strcmp (p, "/mono-boehm") && strcmp (p, "/mono-sgen") && strcmp (p, "/pedump") && strcmp (p, "/monodis")) + if (strcmp (p, "/mono") && strcmp (p, "/mono-boehm") && strcmp (p, "/mono-bdwgc") && strcmp (p, "/mono-sgen") && strcmp (p, "/pedump") && strcmp (p, "/monodis")) return NULL; *p = 0; @@ -785,7 +835,7 @@ compute_base (char *path) if (p == NULL) return NULL; - if (strcmp (p, "/bin") != 0) + if (strstr (p, "/bin") == 0) return NULL; *p = 0; return path; diff --git a/mono/metadata/assembly.h b/mono/metadata/assembly.h index 1a6f35198406..a34b5ed6c0e7 100644 --- a/mono/metadata/assembly.h +++ b/mono/metadata/assembly.h @@ -114,6 +114,7 @@ MONO_API void mono_register_machine_config (const char *config_xml); MONO_API void mono_set_rootdir (void); MONO_API void mono_set_dirs (const char *assembly_dir, const char *config_dir); MONO_API void mono_set_assemblies_path (const char* path); +MONO_API void mono_set_assemblies_path_null_separated(const char* path); MONO_END_DECLS #endif diff --git a/mono/metadata/boehm-gc.c b/mono/metadata/boehm-gc.c index 462d3a115257..260a09842a69 100644 --- a/mono/metadata/boehm-gc.c +++ b/mono/metadata/boehm-gc.c @@ -180,8 +180,8 @@ mono_gc_base_init (void) default_push_other_roots = GC_push_other_roots; GC_push_other_roots = mono_push_other_roots; -#if !defined(HOST_ANDROID) - /* If GC_no_dls is set to true, GC_find_limit is not called. This causes a seg fault on Android. */ +#if defined(HAVE_BDWGC_GC) || !defined(HOST_ANDROID) + /* If GC_no_dls is set to true, GC_find_limit is not called. This causes a seg fault on Android With Mono's Older Boehm. */ GC_no_dls = TRUE; #endif { @@ -250,7 +250,11 @@ mono_gc_base_init (void) mono_thread_info_attach (); +#ifdef HAVE_BDWGC_GC + GC_set_on_event (on_gc_notification); +#else GC_set_on_collection_event (on_gc_notification); +#endif GC_on_heap_resize = on_gc_heap_resize; gc_initialized = TRUE; @@ -393,6 +397,14 @@ mono_gc_thread_attach (MonoThreadInfo* info) return info; } +void +mono_gc_thread_detach (MonoThreadInfo *p) +{ +#if HAVE_BDWGC_GC + GC_unregister_my_thread (); +#endif +} + void mono_gc_thread_detach_with_lock (MonoThreadInfo *p) { @@ -486,7 +498,7 @@ on_gc_notification (GC_EventType event) } #endif UnlockedAdd64 (&gc_stats.major_gc_time, mono_100ns_ticks () - gc_start_time); - mono_trace_message (MONO_TRACE_GC, "gc took %" G_GINT64_FORMAT " usecs", (mono_100ns_ticks () - gc_start_time) / 10); +// mono_trace_message (MONO_TRACE_GC, "gc took %" G_GINT64_FORMAT " usecs", (mono_100ns_ticks () - gc_start_time) / 10); break; default: break; @@ -969,6 +981,10 @@ create_allocator (int atype, int tls_key, gboolean slowpath) g_assert_not_reached (); +#ifdef HAVE_BDWGC_GC + return NULL; +#else + if (atype == ATYPE_FREEPTR) { name = slowpath ? "SlowAllocPtrfree" : "AllocPtrfree"; } else if (atype == ATYPE_FREEPTR_FOR_BOX) { @@ -1180,6 +1196,7 @@ create_allocator (int atype, int tls_key, gboolean slowpath) mono_mb_free (mb); return res; +#endif } static MonoMethod* alloc_method_cache [ATYPE_NUM]; @@ -1215,6 +1232,7 @@ mono_gc_get_managed_allocator (MonoClass *klass, gboolean for_box, gboolean know */ return NULL; +#if 0 if (!SMALL_ENOUGH (klass->instance_size)) return NULL; if (mono_class_has_finalizer (klass) || mono_class_is_marshalbyref (klass)) @@ -1246,6 +1264,7 @@ mono_gc_get_managed_allocator (MonoClass *klass, gboolean for_box, gboolean know */ } return mono_gc_get_managed_allocator_by_type (atype, MANAGED_ALLOCATOR_REGULAR); +#endif } MonoMethod* @@ -1288,7 +1307,7 @@ mono_gc_get_managed_allocator_by_type (int atype, ManagedAllocatorVariant varian guint32 mono_gc_get_managed_allocator_types (void) { - return ATYPE_NUM; + return 0; } MonoMethod* @@ -1367,7 +1386,7 @@ mono_gc_invoke_with_gc_lock (MonoGCLockedCallbackFunc func, void *data) char* mono_gc_get_description (void) { - return g_strdup (DEFAULT_GC_NAME); + return g_strdup ("BDWGC"); } void @@ -1505,7 +1524,11 @@ mono_gc_pthread_create (pthread_t *new_thread, const pthread_attr_t *attr, void #ifdef HOST_WIN32 BOOL APIENTRY mono_gc_dllmain (HMODULE module_handle, DWORD reason, LPVOID reserved) { +#ifdef GC_INSIDE_DLL return GC_DllMain (module_handle, reason, reserved); +#else + return TRUE; +#endif } #endif @@ -1535,7 +1558,9 @@ mono_gc_get_vtable_bits (MonoClass *klass) void mono_gc_register_altstack (gpointer stack, gint32 stack_size, gpointer altstack, gint32 altstack_size) { +#if !HAVE_BDWGC_GC GC_register_altstack (stack, stack_size, altstack, altstack_size); +#endif } int @@ -1574,14 +1599,22 @@ mono_gc_make_root_descr_user (MonoGCRootMarkFunc marker) void mono_gc_toggleref_add (MonoObject *object, mono_bool strong_ref) { +#ifndef HAVE_BDWGC_GC if (GC_toggleref_add ((GC_PTR)object, (int)strong_ref) != GC_SUCCESS) g_error ("GC_toggleref_add failed\n"); +#else + g_assert_not_reached (); +#endif } void mono_gc_toggleref_register_callback (MonoToggleRefStatus (*proccess_toggleref) (MonoObject *obj)) { +#ifndef HAVE_BDWGC_GC GC_set_toggleref_func ((GC_ToggleRefStatus (*) (GC_PTR obj)) proccess_toggleref); +#else + g_assert_not_reached (); +#endif } /* Test support code */ @@ -1630,7 +1663,11 @@ mono_gc_register_finalizer_callbacks (MonoGCFinalizerCallbacks *callbacks) fin_callbacks = *callbacks; +#ifndef HAVE_BDWGC_GC GC_set_await_finalize_proc ((void (*) (GC_PTR))fin_notifier); +#else + g_assert_not_reached (); +#endif } #define BITMAP_SIZE (sizeof (*((HandleData *)NULL)->bitmap) * CHAR_BIT) diff --git a/mono/metadata/class-internals.h b/mono/metadata/class-internals.h index f7d946c0a195..081c851d5dfa 100644 --- a/mono/metadata/class-internals.h +++ b/mono/metadata/class-internals.h @@ -75,6 +75,10 @@ struct _MonoMethod { MonoMethodSignature *signature; /* name is useful mostly for debugging */ const char *name; +#ifdef IL2CPP_ON_MONO + void* method_pointer; + void* invoke_pointer; +#endif /* this is used by the inlining algorithm */ unsigned int inline_info:1; unsigned int inline_failure:1; @@ -221,6 +225,7 @@ typedef enum { MONO_EXCEPTION_OUT_OF_MEMORY = 14, MONO_EXCEPTION_INLINE_FAILED = 15, MONO_EXCEPTION_MONO_ERROR = 16, + MONO_EXCEPTION_MEMBER_ACCESS = 17, /* add other exception type */ } MonoExceptionType; @@ -381,6 +386,8 @@ struct _MonoClass { /* Infrequently used items. See class-accessors.c: InfrequentDataKind for what goes into here. */ MonoPropertyBag infrequent_data; + + void *unity_user_data; }; typedef struct { @@ -1260,7 +1267,7 @@ mono_class_set_type_load_failure (MonoClass *klass, const char * fmt, ...) MONO_ MonoException* mono_class_get_exception_for_failure (MonoClass *klass); -char* +UNITY_MONO_API char* mono_type_get_name_full (MonoType *type, MonoTypeNameFormat format); char* diff --git a/mono/metadata/class.c b/mono/metadata/class.c index 82927e85285d..ccdae030ef9b 100644 --- a/mono/metadata/class.c +++ b/mono/metadata/class.c @@ -55,6 +55,7 @@ MonoStats mono_stats; gboolean mono_print_vtable = FALSE; gboolean mono_align_small_structs = FALSE; +extern gboolean mono_allow_gc_aware_layout; /* Statistics */ gint32 inflated_classes_size, inflated_methods_size; @@ -1842,9 +1843,14 @@ mono_class_layout_fields (MonoClass *klass, int base_instance_size, int packing_ * what the default is for other runtimes. */ /* corlib is missing [StructLayout] directives in many places */ - if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT) { + if (mono_allow_gc_aware_layout && (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT)) { if (!klass->valuetype) gc_aware_layout = TRUE; + /* Unity depends on List`1 layout in native code */ + if (klass->image == mono_defaults.corlib && + strcmp (klass->name_space, "System.Collections.Generic") == 0 && + strcmp (klass->name, "List`1") == 0) + gc_aware_layout = FALSE; } /* Compute klass->blittable */ diff --git a/mono/metadata/cominterop.c b/mono/metadata/cominterop.c index 1caa6ca0f992..ed3964dbc5be 100644 --- a/mono/metadata/cominterop.c +++ b/mono/metadata/cominterop.c @@ -1692,17 +1692,6 @@ ves_icall_System_Runtime_InteropServices_Marshal_GetCCW (MonoObject* object, Mon #endif } - -MonoBoolean -ves_icall_System_Runtime_InteropServices_Marshal_IsComObject (MonoObject* object) -{ -#ifndef DISABLE_COM - return (MonoBoolean)cominterop_object_is_rcw (object); -#else - g_assert_not_reached (); -#endif -} - gint32 ves_icall_System_Runtime_InteropServices_Marshal_ReleaseComObjectInternal (MonoObject* object) { @@ -3688,6 +3677,16 @@ ves_icall_System_Runtime_InteropServices_Marshal_QueryInterfaceInternal (gpointe #endif /* DISABLE_COM */ +MonoBoolean +ves_icall_System_Runtime_InteropServices_Marshal_IsComObject (MonoObject* object) +{ +#ifndef DISABLE_COM + return (MonoBoolean)cominterop_object_is_rcw (object); +#else + return FALSE; +#endif +} + MonoString * ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringBSTR (gpointer ptr) { diff --git a/mono/metadata/console-unity.c b/mono/metadata/console-unity.c new file mode 100644 index 000000000000..97376f4c95ad --- /dev/null +++ b/mono/metadata/console-unity.c @@ -0,0 +1,47 @@ +#include +#include "Console-c-api.h" +#include "File-c-api.h" /* required for IAtty */ + +#if defined(PLATFORM_UNITY) + +void +mono_console_init (void) +{ +} + +void +mono_console_handle_async_ops (void) +{ +} + +MonoBoolean +ves_icall_System_ConsoleDriver_Isatty (gpointer handle) +{ + return UnityPalIsatty(handle); +} + +MonoBoolean +ves_icall_System_ConsoleDriver_SetEcho (MonoBoolean want_echo) +{ + return UnityPalConsoleSetEcho(want_echo); +} + +MonoBoolean +ves_icall_System_ConsoleDriver_SetBreak (MonoBoolean want_break) +{ + return UnityPalConsoleSetBreak(want_break); +} + +gint32 +ves_icall_System_ConsoleDriver_InternalKeyAvailable (gint32 timeout) +{ + return UnityPalConsoleInternalKeyAvailable(timeout); +} + +MonoBoolean +ves_icall_System_ConsoleDriver_TtySetup (MonoString *keypad, MonoString *teardown, MonoArray **control_chars, int **size) +{ + return UnityPalConsoleTtySetup(keypad, teardown, control_chars, size); +} + +#endif /* PLATFORM_UNITY */ diff --git a/mono/metadata/domain-internals.h b/mono/metadata/domain-internals.h index 6d8042c07680..a55277ff94eb 100644 --- a/mono/metadata/domain-internals.h +++ b/mono/metadata/domain-internals.h @@ -577,7 +577,7 @@ mono_runtime_get_no_exec (void); void mono_domain_parse_assembly_bindings (MonoDomain *domain, int amajor, int aminor, gchar *domain_config_file_name); -gboolean +UNITY_MONO_API gboolean mono_assembly_name_parse (const char *name, MonoAssemblyName *aname); MonoImage *mono_assembly_open_from_bundle (const char *filename, diff --git a/mono/metadata/file-mmap-unity.c b/mono/metadata/file-mmap-unity.c new file mode 100644 index 000000000000..cc338f107977 --- /dev/null +++ b/mono/metadata/file-mmap-unity.c @@ -0,0 +1,110 @@ + +#include +#include + +#include +#include "MemoryMappedFile-c-api.h" +#include "File-c-api.h" + +typedef struct { + void *address; + size_t length; +} MmapInstance; + +enum { + BAD_CAPACITY_FOR_FILE_BACKED = 1, + CAPACITY_SMALLER_THAN_FILE_SIZE, + FILE_NOT_FOUND, + FILE_ALREADY_EXISTS, + PATH_TOO_LONG, + COULD_NOT_OPEN, + CAPACITY_MUST_BE_POSITIVE, + INVALID_FILE_MODE, + COULD_NOT_MAP_MEMORY, + ACCESS_DENIED, + CAPACITY_LARGER_THAN_LOGICAL_ADDRESS_SPACE +}; + +#ifndef HOST_WIN32 + +typedef struct { + int kind; + int ref_count; + size_t capacity; + char *name; + int fd; +} MmapHandle; + +#endif + +void mono_mmap_close (void *mmap_handle) +{ + /* Not Supported in UnityPAL */ + g_assert_not_reached(); +} + +void mono_mmap_configure_inheritability (void *mmap_handle, gboolean inheritability) +{ + /* Not Supported in UnityPAL */ + g_assert_not_reached(); +} + +void mono_mmap_flush (void *mmap_handle) +{ + /* Not Supported in UnityPAL */ + g_assert_not_reached(); +} + +void *mono_mmap_open_file (MonoString *string, int mode, MonoString *mapName, gint64 *capacity, int access, int options, int *error) +{ + /* Not Supported in UnityPAL */ + g_assert_not_reached(); + return NULL; +} + +void *mono_mmap_open_handle (void *handle, MonoString *mapName, gint64 *capacity, int access, int options, int *error) +{ + /* Not Supported in UnityPAL */ + g_assert_not_reached(); + return NULL; +} + +int mono_mmap_map (void *handle, gint64 offset, gint64 *size, int access, void **mmap_handle, void **base_address) +{ + /* We are dropping access parameter, UnityPAL does not support */ + g_assert (handle); + + MmapInstance *h = g_malloc0 (sizeof (MmapInstance)); + h->length = *size; + + h->address = UnityPalMemoryMappedFileMapWithParams((UnityPalFileHandle*) handle, (size_t) *size, (size_t) offset); + + if (h->address) + { + *mmap_handle = h; + *base_address = (char*) h->address + offset; + return 0; + } + else + { + g_free (h); + return COULD_NOT_MAP_MEMORY; + } +} + +gboolean +mono_mmap_unmap (void *mmap_handle) +{ + g_assert (mmap_handle); + + MmapInstance *h = (MmapInstance *)mmap_handle; + + UnityPalMemoryMappedFileUnmapWithParams(h->address, h->length); + + g_free (h); + + /* UnityPAL does not give any indication of success or failure of an unmap, forced + to always return true */ + + return TRUE; +} diff --git a/mono/metadata/gc-internals.h b/mono/metadata/gc-internals.h index 7c3cb0146663..c40fbae71fc0 100644 --- a/mono/metadata/gc-internals.h +++ b/mono/metadata/gc-internals.h @@ -90,7 +90,7 @@ extern void mono_gc_set_stack_end (void *stack_end); /* only valid after the RECLAIM_START GC event and before RECLAIM_END * Not exported in public headers, but can be linked to (unsupported). */ -gboolean mono_object_is_alive (MonoObject* obj); +MONO_API gboolean mono_object_is_alive (MonoObject* obj); gboolean mono_gc_is_finalizer_thread (MonoThread *thread); void mono_gchandle_set_target (guint32 gchandle, MonoObject *obj); @@ -125,7 +125,7 @@ void* mono_gc_alloc_fixed (size_t size, MonoGCDescriptor descr, MonoG void mono_gc_free_fixed (void* addr); /* make sure the gchandle was allocated for an object in domain */ -gboolean mono_gchandle_is_in_domain (guint32 gchandle, MonoDomain *domain); +UNITY_MONO_API gboolean mono_gchandle_is_in_domain (guint32 gchandle, MonoDomain *domain); void mono_gchandle_free_domain (MonoDomain *domain); typedef void (*FinalizerThreadCallback) (gpointer user_data); @@ -358,6 +358,7 @@ gboolean mono_gc_is_critical_method (MonoMethod *method); gpointer mono_gc_thread_attach (THREAD_INFO_TYPE *info); +void mono_gc_thread_detach (THREAD_INFO_TYPE *info); void mono_gc_thread_detach_with_lock (THREAD_INFO_TYPE *info); gboolean mono_gc_thread_in_critical_region (THREAD_INFO_TYPE *info); diff --git a/mono/metadata/gc.c b/mono/metadata/gc.c index 99ba7244fce6..11d20fe6a9a7 100644 --- a/mono/metadata/gc.c +++ b/mono/metadata/gc.c @@ -708,7 +708,7 @@ static volatile gboolean finished; void mono_gc_finalize_notify (void) { -#ifdef DEBUG +#if defined(DEBUG) && !defined(IL2CPP_ON_MONO) g_message ( "%s: prodding finalizer", __func__); #endif diff --git a/mono/metadata/handle.h b/mono/metadata/handle.h index 5355a5b950a6..a83618d6b152 100644 --- a/mono/metadata/handle.h +++ b/mono/metadata/handle.h @@ -286,6 +286,15 @@ mono_thread_info_push_stack_mark (MonoThreadInfo *info, void *mark) return __ret; \ } while (0); } while (0) +#define ICALL_RETURN_OBJ_TYPED(HANDLE,TYPE) \ + do { \ + CLEAR_STACK_WATERMARK \ + CLEAR_ICALL_COMMON \ + void* __ret = (HANDLE == NULL_HANDLE) ? NULL : MONO_HANDLE_RAW (HANDLE); \ + CLEAR_ICALL_FRAME \ + return (TYPE)__ret; \ + } while (0); } while (0) + /* Handle macros/functions */ @@ -507,7 +516,7 @@ uintptr_t mono_array_handle_length (MonoArrayHandle arr); static inline void mono_handle_array_getref (MonoObjectHandleOut dest, MonoArrayHandle array, uintptr_t index) { - MONO_HANDLE_SUPPRESS (mono_gc_wbarrier_generic_store (&dest->__raw, mono_array_get (MONO_HANDLE_RAW (array),gpointer, index))); + MONO_HANDLE_SUPPRESS (mono_gc_wbarrier_generic_store (&dest->__raw, mono_array_get (MONO_HANDLE_RAW (array),MonoObject*, index))); } #define mono_handle_class(o) MONO_HANDLE_SUPPRESS (mono_object_class (MONO_HANDLE_RAW (MONO_HANDLE_UNSUPPRESS (o)))) diff --git a/mono/metadata/icall-def.h b/mono/metadata/icall-def.h index c7aa0b5766d9..4e6d11f6a542 100644 --- a/mono/metadata/icall-def.h +++ b/mono/metadata/icall-def.h @@ -114,6 +114,9 @@ ICALL(KPAIR_4, "_ProtectMachine", ves_icall_Mono_Security_Cryptography_KeyPairPe ICALL(KPAIR_5, "_ProtectUser", ves_icall_Mono_Security_Cryptography_KeyPairPersistence_ProtectUser) #endif /* !PLATFORM_RO_FS */ +ICALL_TYPE(UNITYTLS, "Mono.Unity.UnityTls", UNITYTLS_1) +ICALL(UNITYTLS_1, "GetUnityTlsInterface", mono_unity_get_unitytls_interface) + ICALL_TYPE(APPDOM, "System.AppDomain", APPDOM_23) HANDLES(ICALL(APPDOM_23, "DoUnhandledException", ves_icall_System_AppDomain_DoUnhandledException)) HANDLES(ICALL(APPDOM_1, "ExecuteAssembly", ves_icall_System_AppDomain_ExecuteAssembly)) @@ -186,6 +189,9 @@ ICALL(CONSOLE_3, "SetBreak", ves_icall_System_ConsoleDriver_SetBreak ) ICALL(CONSOLE_4, "SetEcho", ves_icall_System_ConsoleDriver_SetEcho ) ICALL(CONSOLE_5, "TtySetup", ves_icall_System_ConsoleDriver_TtySetup ) +ICALL_TYPE(TZONE, "System.CurrentSystemTimeZone", TZONE_1) +ICALL(TZONE_1, "GetTimeZoneData", ves_icall_System_CurrentSystemTimeZone_GetTimeZoneData) + ICALL_TYPE(DTIME, "System.DateTime", DTIME_1) ICALL(DTIME_1, "GetSystemTimeAsFileTime", mono_100ns_datetime) @@ -383,6 +389,7 @@ ICALL(MONOIO_15, "MoveFile(char*,char*,System.IO.MonoIOError&)", ves_icall_Syste #endif /* !PLATFORM_RO_FS */ ICALL(MONOIO_16, "Open(char*,System.IO.FileMode,System.IO.FileAccess,System.IO.FileShare,System.IO.FileOptions,System.IO.MonoIOError&)", ves_icall_System_IO_MonoIO_Open) HANDLES(ICALL(MONOIO_17, "Read(intptr,byte[],int,int,System.IO.MonoIOError&)", ves_icall_System_IO_MonoIO_Read)) +ICALL(MONOIO_39, "RemapPath(string,string&)", ves_icall_System_IO_MonoIO_RemapPath) #ifndef PLATFORM_RO_FS ICALL(MONOIO_18, "RemoveDirectory(char*,System.IO.MonoIOError&)", ves_icall_System_IO_MonoIO_RemoveDirectory) ICALL(MONOIO_18M, "ReplaceFile(char*,char*,char*,bool,System.IO.MonoIOError&)", ves_icall_System_IO_MonoIO_ReplaceFile) @@ -463,6 +470,7 @@ HANDLES(ICALL(SOCK_6b, "Duplicate_internal", ves_icall_System_Net_Sockets_Socket HANDLES(ICALL(SOCK_7, "GetSocketOption_arr_internal(intptr,System.Net.Sockets.SocketOptionLevel,System.Net.Sockets.SocketOptionName,byte[]&,int&)", ves_icall_System_Net_Sockets_Socket_GetSocketOption_arr_internal)) HANDLES(ICALL(SOCK_8, "GetSocketOption_obj_internal(intptr,System.Net.Sockets.SocketOptionLevel,System.Net.Sockets.SocketOptionName,object&,int&)", ves_icall_System_Net_Sockets_Socket_GetSocketOption_obj_internal)) HANDLES(ICALL(SOCK_21, "IOControl_internal(intptr,int,byte[],byte[],int&)", ves_icall_System_Net_Sockets_Socket_IOControl_internal)) +ICALL(SOCK_22, "IsProtocolSupported_internal", ves_icall_System_Net_Sockets_Socket_IsProtocolSupported_internal) HANDLES(ICALL(SOCK_9, "Listen_internal(intptr,int,int&)", ves_icall_System_Net_Sockets_Socket_Listen_internal)) HANDLES(ICALL(SOCK_10, "LocalEndPoint_internal(intptr,int,int&)", ves_icall_System_Net_Sockets_Socket_LocalEndPoint_internal)) HANDLES(ICALL(SOCK_11, "Poll_internal", ves_icall_System_Net_Sockets_Socket_Poll_internal)) @@ -696,8 +704,8 @@ ICALL(MARSHAL_11, "GetLastWin32Error", ves_icall_System_Runtime_InteropServices_ ICALL(MARSHAL_53, "GetNativeActivationFactory", ves_icall_System_Runtime_InteropServices_Marshal_GetNativeActivationFactory) ICALL(MARSHAL_47, "GetObjectForCCW", ves_icall_System_Runtime_InteropServices_Marshal_GetObjectForCCW) ICALL(MARSHAL_54, "GetRawIUnknownForComObjectNoAddRef", ves_icall_System_Runtime_InteropServices_Marshal_GetRawIUnknownForComObjectNoAddRef) -ICALL(MARSHAL_48, "IsComObject", ves_icall_System_Runtime_InteropServices_Marshal_IsComObject) #endif +ICALL(MARSHAL_48, "IsComObject", ves_icall_System_Runtime_InteropServices_Marshal_IsComObject) HANDLES(ICALL(MARSHAL_12, "OffsetOf", ves_icall_System_Runtime_InteropServices_Marshal_OffsetOf)) HANDLES(ICALL(MARSHAL_13, "Prelink", ves_icall_System_Runtime_InteropServices_Marshal_Prelink)) HANDLES(ICALL(MARSHAL_14, "PrelinkAll", ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll)) @@ -757,6 +765,9 @@ ICALL_TYPE(REMSER, "System.Runtime.Remoting.RemotingServices", REMSER_0) HANDLES(ICALL(REMSER_0, "GetVirtualMethod", ves_icall_Remoting_RemotingServices_GetVirtualMethod)) ICALL(REMSER_1, "InternalExecute", ves_icall_InternalExecute) HANDLES(ICALL(REMSER_2, "IsTransparentProxy", ves_icall_IsTransparentProxy)) +#else +ICALL_TYPE(REMSER, "System.Runtime.Remoting.RemotingServices", REMSER_0) +ICALL(REMSER_0, "IsTransparentProxy", ves_icall_IsTransparentProxy) #endif ICALL_TYPE(RVH, "System.Runtime.Versioning.VersioningHelper", RVH_1) diff --git a/mono/metadata/icall-internals.h b/mono/metadata/icall-internals.h index c172b8404bcb..c3ee79d03999 100644 --- a/mono/metadata/icall-internals.h +++ b/mono/metadata/icall-internals.h @@ -10,6 +10,10 @@ #include #include +// UNITY +guint32 +ves_icall_System_CurrentSystemTimeZone_GetTimeZoneData (guint32 year, MonoArray **data, MonoArray **names); + // On Windows platform implementation of bellow methods are hosted in separate source file // icall-windows.c or icall-windows-*.c. On other platforms the implementation is still keept // in icall.c still declared as static and in some places even inlined. diff --git a/mono/metadata/icall.c b/mono/metadata/icall.c index d91754d9861c..3537675aabcf 100644 --- a/mono/metadata/icall.c +++ b/mono/metadata/icall.c @@ -85,6 +85,7 @@ #include #include #include +#include #include #include #include @@ -1095,6 +1096,9 @@ ves_icall_System_ValueType_InternalGetHashCode (MonoObject *this_obj, MonoArray case MONO_TYPE_I4: result ^= *(gint32*)((guint8*)this_obj + field->offset); break; + case MONO_TYPE_PTR: + result ^= mono_aligned_addr_hash (*(gpointer*)((guint8*)this_obj + field->offset)); + break; case MONO_TYPE_STRING: { MonoString *s; s = *(MonoString**)((guint8*)this_obj + field->offset); @@ -1194,6 +1198,10 @@ ves_icall_System_ValueType_Equals (MonoObject *this_obj, MonoObject *that, MonoA if (*(double*)((guint8*)this_obj + field->offset) != *(double*)((guint8*)that + field->offset)) return FALSE; break; + case MONO_TYPE_PTR: + if (*(gpointer*)((guint8*)this_obj + field->offset) != *(gpointer*)((guint8*)that + field->offset)) + return FALSE; + break; case MONO_TYPE_STRING: { @@ -7050,6 +7058,12 @@ ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (Mo g_assert_not_reached (); } +ICALL_EXPORT MonoBoolean +ves_icall_IsTransparentProxy (MonoObject *proxy) +{ + return 0; +} + #endif ICALL_EXPORT MonoObjectHandle diff --git a/mono/metadata/il2cpp-compat-metadata.h b/mono/metadata/il2cpp-compat-metadata.h new file mode 100644 index 000000000000..62d1500e5d3b --- /dev/null +++ b/mono/metadata/il2cpp-compat-metadata.h @@ -0,0 +1,36 @@ +#pragma once + +#ifdef RUNTIME_IL2CPP + +#include +#include + +#if defined(_POSIX_VERSION) +#include +#endif + +#define mono_gc_make_root_descr_all_refs il2cpp_mono_gc_make_root_descr_all_refs +#define mono_gc_alloc_fixed il2cpp_mono_gc_alloc_fixed +#define mono_gc_free_fixed il2cpp_gc_free_fixed +#define mono_gc_is_moving il2cpp_mono_gc_is_moving +#define mono_gc_invoke_with_gc_lock il2cpp_mono_gc_invoke_with_gc_lock +#define mono_gc_pthread_create il2cpp_mono_gc_pthread_create +#define mono_gc_register_root_wbarrier il2cpp_mono_gc_register_root_wbarrier +#define mono_gc_wbarrier_generic_store il2cpp_mono_gc_wbarrier_generic_store +#define mono_gc_make_vector_descr il2cpp_mono_gc_make_vector_descr +#define mono_gc_deregister_root il2cpp_mono_gc_deregister_root + +int il2cpp_mono_gc_register_root_wbarrier (char *start, size_t size, MonoGCDescriptor descr, MonoGCRootSource source, void *key, const char *msg); +SgenDescriptor il2cpp_mono_gc_make_root_descr_all_refs(int numbits); +MonoGCDescriptor il2cpp_mono_gc_make_vector_descr (void); +void* il2cpp_mono_gc_alloc_fixed (size_t size, void* descr, MonoGCRootSource source, void *key, const char *msg); +gboolean il2cpp_mono_gc_is_moving(); + +typedef void* (*MonoGCLockedCallbackFunc) (void *data); +void* il2cpp_mono_gc_invoke_with_gc_lock (MonoGCLockedCallbackFunc func, void *data); + +#ifndef HOST_WIN32 +int il2cpp_mono_gc_pthread_create (pthread_t *new_thread, const pthread_attr_t *attr, void *(*start_routine)(void *), void *arg); +#endif + +#endif diff --git a/mono/metadata/image.c b/mono/metadata/image.c index 548e52715e12..b0b9b285ae58 100644 --- a/mono/metadata/image.c +++ b/mono/metadata/image.c @@ -41,6 +41,7 @@ #include #include #include +#include #include #include #ifdef HAVE_UNISTD_H @@ -1359,6 +1360,9 @@ do_mono_image_open (const char *fname, MonoImageOpenStatus *status, MonoCLIImageInfo *iinfo; MonoImage *image; MonoFileMap *filed; + const char *fname_remap; + if (fname_remap = mono_unity_remap_path (fname)) + fname = fname_remap; if ((filed = mono_file_map_open (fname)) == NULL){ if (IS_PORTABILITY_SET) { @@ -1372,6 +1376,7 @@ do_mono_image_open (const char *fname, MonoImageOpenStatus *status, if (filed == NULL) { if (status) *status = MONO_IMAGE_ERROR_ERRNO; + g_free((void*)fname_remap); return NULL; } } @@ -1391,6 +1396,7 @@ do_mono_image_open (const char *fname, MonoImageOpenStatus *status, g_free (image); if (status) *status = MONO_IMAGE_IMAGE_INVALID; + g_free((void*)fname_remap); return NULL; } iinfo = g_new0 (MonoCLIImageInfo, 1); @@ -1404,6 +1410,7 @@ do_mono_image_open (const char *fname, MonoImageOpenStatus *status, image->core_clr_platform_code = mono_security_core_clr_determine_platform_image (image); mono_file_map_close (filed); + g_free((void*)fname_remap); return do_mono_image_load (image, status, care_about_cli, care_about_pecoff); } diff --git a/mono/metadata/jit-info.c b/mono/metadata/jit-info.c index 3344679e8123..cc04f866005f 100644 --- a/mono/metadata/jit-info.c +++ b/mono/metadata/jit-info.c @@ -196,6 +196,8 @@ jit_info_table_chunk_index (MonoJitInfoTableChunk *chunk, MonoThreadHazardPointe return left; } +/* When changing this method, make sure to also update oop_jit_info_table_find + in mono/metadata/oop.c. */ static MonoJitInfo* jit_info_table_find (MonoJitInfoTable *table, MonoThreadHazardPointers *hp, gint8 *addr) { diff --git a/mono/metadata/loader.c b/mono/metadata/loader.c index edced98b6d9a..c2a959705486 100644 --- a/mono/metadata/loader.c +++ b/mono/metadata/loader.c @@ -40,6 +40,7 @@ #include #include #include +#include #include #include #include @@ -1114,21 +1115,26 @@ static MonoDl* cached_module_load (const char *name, int flags, char **err) { MonoDl *res; + const char *name_remap; if (err) *err = NULL; + if (name_remap = mono_unity_remap_path (name)) + name = name_remap; global_loader_data_lock (); if (!global_module_map) global_module_map = g_hash_table_new (g_str_hash, g_str_equal); res = (MonoDl *)g_hash_table_lookup (global_module_map, name); if (res) { global_loader_data_unlock (); + g_free((void*)name_remap); return res; } res = mono_dl_open (name, flags, err); if (res) g_hash_table_insert (global_module_map, g_strdup (name), res); global_loader_data_unlock (); + g_free((void*)name_remap); return res; } @@ -1257,6 +1263,22 @@ mono_lookup_pinvoke_call (MonoMethod *method, const char **exc_class, const char } } + if (mono_get_find_plugin_callback ()) + { + const char* unity_new_scope = mono_get_find_plugin_callback () (new_scope); + if (unity_new_scope == NULL) + { + if (exc_class) + { + *exc_class = "DllNotFoundException"; + *exc_arg = new_scope; + } + return NULL; + } + + new_scope = unity_new_scope; + } + /* * Try loading the module using a variety of names */ diff --git a/mono/metadata/marshal.c b/mono/metadata/marshal.c index d2859202fbe6..f95f51cb79c8 100644 --- a/mono/metadata/marshal.c +++ b/mono/metadata/marshal.c @@ -1616,9 +1616,11 @@ emit_ptr_to_object_conv (MonoMethodBuilder *mb, MonoType *type, MonoMarshalConv mono_mb_emit_byte (mb, CEE_STIND_REF); break; } - case MONO_MARSHAL_CONV_ARRAY_LPARRAY: - g_error ("Structure field of type %s can't be marshalled as LPArray", mono_class_from_mono_type (type)->name); + case MONO_MARSHAL_CONV_ARRAY_LPARRAY: { + char *msg = g_strdup_printf ("Structure field of type %s can't be marshalled as LPArray", mono_class_from_mono_type (type)->name); + mono_mb_emit_exception_marshal_directive (mb, msg); break; + } #ifndef DISABLE_COM case MONO_MARSHAL_CONV_OBJECT_INTERFACE: @@ -1823,6 +1825,10 @@ emit_object_to_ptr_conv (MonoMethodBuilder *mb, MonoType *type, MonoMarshalConv if (type->type == MONO_TYPE_SZARRAY) { eklass = type->data.klass; + } else if (type->type == MONO_TYPE_ARRAY) { + eklass = type->data.array->eklass; + if (!eklass->blittable) + g_assert_not_reached (); } else { g_assert_not_reached (); } diff --git a/mono/metadata/metadata-internals.h b/mono/metadata/metadata-internals.h index e849706e19e9..1ad92b319a65 100644 --- a/mono/metadata/metadata-internals.h +++ b/mono/metadata/metadata-internals.h @@ -964,5 +964,8 @@ mono_loader_get_strict_strong_names (void); char* mono_signature_get_managed_fmt_string (MonoMethodSignature *sig); +gboolean +mono_type_in_image (MonoType *type, MonoImage *image); + #endif /* __MONO_METADATA_INTERNALS_H__ */ diff --git a/mono/metadata/metadata.c b/mono/metadata/metadata.c index b2d75f335d80..378ceb4dc139 100644 --- a/mono/metadata/metadata.c +++ b/mono/metadata/metadata.c @@ -2401,6 +2401,12 @@ type_in_image (MonoType *type, MonoImage *image) } } +gboolean +mono_type_in_image (MonoType *type, MonoImage *image) +{ + return type_in_image (type, image); +} + static inline void image_sets_lock (void) { @@ -4788,6 +4794,7 @@ mono_metadata_localscope_from_methoddef (MonoImage *meta, guint32 index) static void mono_backtrace (int limit) { +#ifndef _MSC_VER void *array[limit]; char **names; int i; @@ -4797,6 +4804,7 @@ mono_backtrace (int limit) g_print ("\t%s\n", names [i]); } g_free (names); +#endif } #endif diff --git a/mono/metadata/mono-hash.c b/mono/metadata/mono-hash.c index b62947b83415..bf099f653497 100644 --- a/mono/metadata/mono-hash.c +++ b/mono/metadata/mono-hash.c @@ -32,6 +32,7 @@ #include #include "mono-hash.h" #include "metadata/gc-internals.h" +#include "metadata/il2cpp-compat-metadata.h" #include #include #include diff --git a/mono/metadata/null-gc.c b/mono/metadata/null-gc.c index 6e35625cbeb9..88ab715cf5ec 100644 --- a/mono/metadata/null-gc.c +++ b/mono/metadata/null-gc.c @@ -296,6 +296,11 @@ mono_gc_thread_attach (MonoThreadInfo* info) return info; } +void +mono_gc_thread_detach (MonoThreadInfo *p) +{ +} + void mono_gc_thread_detach_with_lock (MonoThreadInfo *p) { diff --git a/mono/metadata/object-internals.h b/mono/metadata/object-internals.h index cb42761d6c20..ed7bdd3f1888 100644 --- a/mono/metadata/object-internals.h +++ b/mono/metadata/object-internals.h @@ -1690,7 +1690,7 @@ typedef enum { MonoRuntimeUnhandledExceptionPolicy mono_runtime_unhandled_exception_policy_get (void); -void +UNITY_MONO_API void mono_runtime_unhandled_exception_policy_set (MonoRuntimeUnhandledExceptionPolicy policy); void diff --git a/mono/metadata/object.c b/mono/metadata/object.c index 3d69dca594e3..94a92c7517fa 100644 --- a/mono/metadata/object.c +++ b/mono/metadata/object.c @@ -5196,7 +5196,9 @@ mono_runtime_try_invoke_array (MonoMethod *method, void *obj, MonoArray *params, if (mono_class_is_nullable (method->klass)) { /* Need to create a boxed vtype instead */ +#ifndef IL2CPP_ON_MONO g_assert (!obj); +#endif if (!params) return NULL; @@ -6283,6 +6285,24 @@ mono_string_new_len_checked (MonoDomain *domain, const char *text, guint length, return o; } +static MonoString* +mono_string_new_internal (MonoDomain *domain, const char *text) +{ + MonoError error; + MonoString *res = NULL; + res = mono_string_new_checked (domain, text, &error); + if (!is_ok (&error)) { + /* Mono API compatability: assert on Out of Memory errors, + * return NULL otherwise (most likely an invalid UTF-8 byte + * sequence). */ + if (mono_error_get_error_code (&error) == MONO_ERROR_OUT_OF_MEMORY) + mono_error_assert_ok (&error); + else + mono_error_cleanup (&error); + } + return res; +} + /** * mono_string_new: * \param text a pointer to a UTF-8 string @@ -6293,11 +6313,7 @@ mono_string_new_len_checked (MonoDomain *domain, const char *text, guint length, MonoString* mono_string_new (MonoDomain *domain, const char *text) { - MonoError error; - MonoString *res = NULL; - res = mono_string_new_checked (domain, text, &error); - mono_error_assert_ok (&error); - return res; + return mono_string_new_internal (domain, text); } /** @@ -6370,16 +6386,7 @@ mono_string_new_wrapper (const char *text) { MONO_REQ_GC_UNSAFE_MODE; - MonoDomain *domain = mono_domain_get (); - - if (text) { - MonoError error; - MonoString *result = mono_string_new_checked (domain, text, &error); - mono_error_assert_ok (&error); - return result; - } - - return NULL; + return mono_string_new_internal (mono_domain_get (), text); } /** diff --git a/mono/metadata/oop.c b/mono/metadata/oop.c new file mode 100644 index 000000000000..9d8251ed37ff --- /dev/null +++ b/mono/metadata/oop.c @@ -0,0 +1,434 @@ +/* + * oop.c: These functions allow us to access the MonoDomain internals for purposes of post-mortem + * inspection by another process. All data is immutable: these calls are guaranteed to have no + * side-effects. These routines are not thread safe. This does not work with AOT modules. + * + * Author: + * Pete Lewis + * + * Copyright 2017 Unity Technologies (http://www.unity3d.com) + * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com) + * Copyright 2004-2009 Novell, Inc (http://www.novell.com) + */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef _M_X64 +#include +extern GList* g_dynamic_function_table_begin; +extern SRWLOCK g_dynamic_function_table_lock; +#endif + +// petele: todo: move this structure into a mono header +typedef struct _MonoStackFrameDetails +{ + char* methodName; + size_t methodNameLen; + char* className; + size_t classNameLen; + char* assemblyName; + size_t assemblyNameLen; +} MonoStackFrameDetails; + +typedef gboolean(*ReadMemoryCallback)(void* buffer, gsize* read, const void* address, gsize size, void* userdata); +typedef gboolean(*ReadExceptionCallback)(const void* address, gsize size, void* userdata); + +typedef struct _OutOfProcessMono +{ + ReadMemoryCallback readMemory; + ReadExceptionCallback readException; + void* userData; +} OutOfProcessMono; + +static OutOfProcessMono g_oop = { NULL, NULL }; + +#define OFFSET_MEMBER(type, base, member) ((gpointer)((gchar*)(base) + offsetof(type, member))) + +void read_exception(const void* address, gsize size) +{ + g_assert(g_oop.readException); + g_oop.readException(address, size, g_oop.userData); +} + +gsize read_memory(void* buffer, const void* address, gsize size) +{ + if (!buffer || !size) + return 0; + + gsize read = 0; + if (!g_oop.readMemory || !g_oop.readMemory(buffer, &read, address, size, g_oop.userData)) { + read_exception(address, size); + } + + return read; +} + +// Read a null-terminated string out-of-process +gsize read_nt_string(char* buffer, gsize max_size, const void* address) +{ + if (!buffer || !max_size) + return 0; + + if (!g_oop.readMemory) { + read_exception(address, 1); + return 0; + } + + gsize read = 0; + if (!g_oop.readMemory(buffer, &read, address, max_size, g_oop.userData)) { + // Failed to read, but just because we may not have read max_size, we still + // might be OK if at least one character was read (i.e. the null-terminator) + if (read == 0) + read_exception(address, 1); + } + + // Ensure there's a null-terminator + buffer[min(read, max_size-1)] = '\0'; + + return read; +} + +gpointer read_pointer(const void* address) +{ + gpointer ptr = NULL; + read_memory(&ptr, address, sizeof(ptr)); + return ptr; +} + +gint64 read_qword(const void* address) +{ + gint64 v = 0; + read_memory(&v, address, sizeof(v)); + return v; +} + +gint32 read_dword(const void* address) +{ + gint32 v = 0; + read_memory(&v, address, sizeof(v)); + return v; +} + +GList* read_glist_next(GList* list) { return (GList*) read_pointer(OFFSET_MEMBER(GList, list, next)); } +gpointer read_glist_data(GList* list) { return read_pointer(OFFSET_MEMBER(GList, list, data)); } + +MONO_API void +mono_unity_oop_init( + ReadMemoryCallback rmcb, + ReadExceptionCallback recb, + void* userdata) +{ + g_oop.readMemory = rmcb; + g_oop.readException = recb; + g_oop.userData = userdata; +} + +MONO_API void +mono_unity_oop_shutdown(void) +{ + memset(&g_oop, 0, sizeof(g_oop)); +} + +#ifdef _M_X64 +gboolean TryAcquireSpinWait(PSRWLOCK lock, unsigned int spinWait) +{ + do + { + if (TryAcquireSRWLockExclusive(&g_dynamic_function_table_lock)) + return TRUE; + } while (spinWait--); + + return FALSE; +} +#endif + +MONO_API GList* +mono_unity_lock_dynamic_function_access_tables64(unsigned int spinWait) +{ +#ifdef _M_X64 + if (spinWait >= 0x7fffffff) { + AcquireSRWLockExclusive(&g_dynamic_function_table_lock); + } + else if (!TryAcquireSpinWait(&g_dynamic_function_table_lock, spinWait)) { + return NULL; + } + return g_dynamic_function_table_begin; +#else + return NULL; +#endif +} + +MONO_API void +mono_unity_unlock_dynamic_function_access_tables64(void) +{ +#ifdef _M_X64 + ReleaseSRWLockExclusive(&g_dynamic_function_table_lock); +#else + return NULL; +#endif +} + +MONO_API GList* +mono_unity_oop_iterate_dynamic_function_access_tables64( + GList* current) +{ +#ifdef _M_X64 + if (current != NULL) + return read_glist_next(current); + else + return NULL; +#else + return NULL; +#endif +} + +MONO_API gboolean +mono_unity_oop_get_dynamic_function_access_table64( + GList* tableEntry, + gsize* moduleStart, + gsize* moduleEnd, + void** functionTable, + gsize* functionTableSize) +{ +#ifdef _M_X64 + if (!tableEntry || !moduleStart || !moduleEnd || !functionTable || !functionTableSize) + return FALSE; + + const DynamicFunctionTableEntry* entry = read_glist_data(tableEntry); + *moduleStart = read_qword(OFFSET_MEMBER(DynamicFunctionTableEntry, entry, begin_range)); + *moduleEnd = read_qword(OFFSET_MEMBER(DynamicFunctionTableEntry, entry, end_range)); + *functionTable = read_pointer(OFFSET_MEMBER(DynamicFunctionTableEntry, entry, rt_funcs)); + *functionTableSize = read_dword(OFFSET_MEMBER(DynamicFunctionTableEntry, entry, rt_funcs_max_count)); + + return TRUE; +#else + return FALSE; +#endif +} + +static int oop_jit_info_table_index( + const MonoJitInfoTableChunk** chunks, // non-local + int num_chunks, + const gint8* addr) +{ + static const int error = 0x7fffffff; + + int left = 0, right = num_chunks; + + g_assert(left < right); + + do { + const MonoJitInfoTableChunk* chunkPtr; + const gint8* last_code_end; + int pos = (left + right) / 2; + + chunkPtr = read_pointer(chunks + pos); + if (chunkPtr == NULL) + return error; + + last_code_end = read_pointer(OFFSET_MEMBER(MonoJitInfoTableChunk, chunkPtr, last_code_end)); + if (last_code_end == NULL) + return error; + + if (addr < last_code_end) + right = pos; + else + left = pos + 1; + } while (left < right); + g_assert(left == right); + + if (left >= num_chunks) + return num_chunks - 1; + return left; +} + +static int +oop_jit_info_table_chunk_index( + const MonoJitInfo** chunk_data, + int num_elements, + const gint8 *addr) +{ + const MonoJitInfo* ji; + int left = 0, right = num_elements; + + while (left < right) { + int pos = (left + right) / 2; + + const gint8 *code_start; + const gint8 *code_end; + int code_size; + + ji = chunk_data[pos]; + + code_start = (const gint8*)read_pointer(OFFSET_MEMBER(MonoJitInfo, ji, code_start)); + code_size = read_dword(OFFSET_MEMBER(MonoJitInfo, ji, code_size)); + code_end = code_start + code_size; + + if (addr < code_end) + right = pos; + else + left = pos + 1; + } + + g_assert(left == right); + + return left; +} + +/* This method is an out-of-process version of jit_info_table_find. */ +static const MonoJitInfo* +oop_jit_info_table_find( + const MonoDomain *domain, + const char *addr, + gboolean allow_trampolines) +{ + const MonoJitInfoTable* tablePtr; + const MonoJitInfoTableChunk** chunkListPtr; + MonoJitInfoTableChunk chunk; + MonoJitInfo ji; + int chunk_pos, pos; + + // Get the domain's jit_info_table pointer. + tablePtr = read_pointer(OFFSET_MEMBER(MonoDomain, domain, jit_info_table)); + if (tablePtr == NULL) + return NULL; + + int num_chunks = read_dword(OFFSET_MEMBER(MonoJitInfoTable, tablePtr, num_chunks)); + + // Get the chunk array + chunkListPtr = (const MonoJitInfoTableChunk**)OFFSET_MEMBER(MonoJitInfoTable, tablePtr, chunks); + + chunk_pos = oop_jit_info_table_index(chunkListPtr, num_chunks, (const gint8*)addr); + if (chunk_pos > num_chunks) + return NULL; + + // read the entire chunk + read_memory(&chunk, read_pointer(chunkListPtr + chunk_pos), sizeof(MonoJitInfoTableChunk)); + + pos = oop_jit_info_table_chunk_index((const MonoJitInfo**)chunk.data, chunk.num_elements, addr); + if (pos > chunk.num_elements) + return NULL; + + /* We now have a position that's very close to that of the + first element whose end address is higher than the one + we're looking for. If we don't have the exact position, + then we have a position below that one, so we'll just + search upward until we find our element. */ + do { + read_memory(&chunk, read_pointer(chunkListPtr + chunk_pos), sizeof(MonoJitInfoTableChunk)); + + while (pos < chunk.num_elements) { + read_memory(&ji, chunk.data[pos], sizeof(ji)); + + ++pos; + + if (ji.d.method == NULL) { + continue; + } + if ((gint8*)addr >= (gint8*)ji.code_start + && (gint8*)addr < (gint8*)ji.code_start + ji.code_size) { + if (ji.is_trampoline && !allow_trampolines) { + return NULL; + } + return chunk.data[pos-1]; + } + + /* If we find a non-tombstone element which is already + beyond what we're looking for, we have to end the + search. */ + if ((gint8*)addr < (gint8*)ji.code_start) + return NULL; + } + + ++chunk_pos; + pos = 0; + } while (chunk_pos < num_chunks); + + return NULL; +} + +int +mono_unity_oop_get_stack_frame_details( + const MonoDomain* domain, + const void* frameAddress, + MonoStackFrameDetails* frameDetails) +{ + const MonoJitInfo* ji; + + ji = oop_jit_info_table_find(domain, (const char*)frameAddress, FALSE); + if (ji) + { + const MonoMethod* method = read_pointer(OFFSET_MEMBER(MonoJitInfo, ji, d.method)); + const MonoClass* klass = read_pointer(OFFSET_MEMBER(MonoMethod, method, klass)); + const MonoImage* image = read_pointer(OFFSET_MEMBER(MonoClass, klass, image)); + size_t classNameLen = max(frameDetails->classNameLen, 256); + char* className = (char*)malloc(classNameLen); + char* nsName = (char*)malloc(classNameLen); + + frameDetails->methodNameLen = read_nt_string( + frameDetails->methodName, + frameDetails->methodNameLen, + read_pointer(OFFSET_MEMBER(MonoMethod, method, name))); + + if (frameDetails->className && frameDetails->classNameLen > 0) { + read_nt_string( + nsName, + classNameLen, + read_pointer(OFFSET_MEMBER(MonoClass, klass, name_space))); + + read_nt_string( + className, + classNameLen, + read_pointer(OFFSET_MEMBER(MonoClass, klass, name))); + + if (*nsName) { + frameDetails->classNameLen = sprintf_s( + frameDetails->className, + frameDetails->classNameLen, + "%s.%s", + nsName, + className); + } else { + frameDetails->classNameLen = sprintf_s( + frameDetails->className, + frameDetails->classNameLen, + "%s", + className); + } + } + + frameDetails->assemblyNameLen = read_nt_string( + frameDetails->assemblyName, + frameDetails->assemblyNameLen, + read_pointer(OFFSET_MEMBER(MonoImage, image, assembly_name))); + + free(className); + free(nsName); + + return TRUE; + } + + return FALSE; +} diff --git a/mono/metadata/profiler-events.h b/mono/metadata/profiler-events.h index 5e933d0c9fbf..c603ca224323 100644 --- a/mono/metadata/profiler-events.h +++ b/mono/metadata/profiler-events.h @@ -95,6 +95,7 @@ MONO_PROFILER_EVENT_1(gc_finalized_object, GCFinalizedObject, MonoObject *, obje MONO_PROFILER_EVENT_5(gc_root_register, RootRegister, const mono_byte *, start, uintptr_t, size, MonoGCRootSource, source, const void *, key, const char *, name) MONO_PROFILER_EVENT_1(gc_root_unregister, RootUnregister, const mono_byte *, start) MONO_PROFILER_EVENT_3(gc_roots, GCRoots, uint64_t, count, const mono_byte *const *, addresses, MonoObject *const *, objects) +MONO_PROFILER_EVENT_2(fileio, FileIO, uint64_t, kind, uint64_t, size) MONO_PROFILER_EVENT_1(monitor_contention, MonitorContention, MonoObject *, object) MONO_PROFILER_EVENT_1(monitor_failed, MonitorFailed, MonoObject *, object) diff --git a/mono/metadata/profiler-private.h b/mono/metadata/profiler-private.h index 3c0fe896c4ff..6b5b0be860e3 100644 --- a/mono/metadata/profiler-private.h +++ b/mono/metadata/profiler-private.h @@ -59,6 +59,7 @@ typedef struct { guint32 sample_freq; gboolean allocations; + gboolean fileio; gboolean call_contexts; void (*context_enable) (void); diff --git a/mono/metadata/profiler.c b/mono/metadata/profiler.c index 69c7e8030b32..a4c7a71c6e0b 100644 --- a/mono/metadata/profiler.c +++ b/mono/metadata/profiler.c @@ -134,6 +134,7 @@ load_profiler_from_installation (const char *libname, const char *name, const ch * This function may \b only be called by embedders prior to running managed * code. */ +#ifndef RUNTIME_IL2CPP void mono_profiler_load (const char *desc) { @@ -167,6 +168,7 @@ mono_profiler_load (const char *desc) g_free (mname); } +#endif /** * mono_profiler_create: @@ -238,6 +240,7 @@ mono_profiler_set_cleanup_callback (MonoProfilerHandle handle, MonoProfilerClean * This function may \b only be called from a profiler's init function or prior * to running managed code. */ +#ifndef RUNTIME_IL2CPP mono_bool mono_profiler_enable_coverage (void) { @@ -252,6 +255,7 @@ mono_profiler_enable_coverage (void) return mono_profiler_state.code_coverage = TRUE; } +#endif /** * mono_profiler_set_coverage_filter_callback: @@ -299,6 +303,7 @@ coverage_unlock (void) * * This function is \b not async safe. */ +#ifndef RUNTIME_IL2CPP mono_bool mono_profiler_get_coverage_data (MonoProfilerHandle handle, MonoMethod *method, MonoProfilerCoverageCallback cb) { @@ -402,6 +407,7 @@ mono_profiler_get_coverage_data (MonoProfilerHandle handle, MonoMethod *method, return TRUE; } +#endif MonoProfilerCoverageInfo * mono_profiler_coverage_alloc (MonoMethod *method, guint32 entries) @@ -553,12 +559,20 @@ mono_profiler_sampling_thread_wait (void) mono_bool mono_profiler_enable_allocations (void) { - if (mono_profiler_state.startup_done) +#ifndef RUNTIME_IL2CPP + if (mono_gc_get_managed_allocator_types () > 0 && mono_profiler_state.startup_done) return FALSE; +#endif return mono_profiler_state.allocations = TRUE; } +mono_bool +mono_profiler_enable_fileio (void) +{ + return mono_profiler_state.fileio = TRUE; +} + /** * mono_profiler_set_call_instrumentation_filter_callback: * @@ -944,6 +958,7 @@ typedef void (*MonoLegacyProfileAllocFunc) (MonoLegacyProfiler *prof, MonoObject typedef void (*MonoLegacyProfileMethodFunc) (MonoLegacyProfiler *prof, MonoMethod *method); typedef void (*MonoLegacyProfileExceptionFunc) (MonoLegacyProfiler *prof, MonoObject *object); typedef void (*MonoLegacyProfileExceptionClauseFunc) (MonoLegacyProfiler *prof, MonoMethod *method, int clause_type, int clause_num); +typedef void (*MonoLegacyProfileFileIOFunc) (MonoLegacyProfiler *prof, int kind, int size); struct _MonoProfiler { MonoProfilerHandle handle; @@ -954,6 +969,7 @@ struct _MonoProfiler { MonoLegacyProfileGCResizeFunc gc_heap_resize; MonoLegacyProfileJitResult jit_end2; MonoLegacyProfileAllocFunc allocation; + MonoLegacyProfileFileIOFunc fileio; MonoLegacyProfileMethodFunc enter; MonoLegacyProfileMethodFunc leave; MonoLegacyProfileExceptionFunc throw_callback; @@ -970,6 +986,7 @@ MONO_API void mono_profiler_install_jit_end (MonoLegacyProfileJitResult end); MONO_API void mono_profiler_set_events (int flags); MONO_API void mono_profiler_install_allocation (MonoLegacyProfileAllocFunc callback); MONO_API void mono_profiler_install_enter_leave (MonoLegacyProfileMethodFunc enter, MonoLegacyProfileMethodFunc fleave); +MONO_API void mono_profiler_install_fileio (MonoLegacyProfileFileIOFunc callback); MONO_API void mono_profiler_install_exception (MonoLegacyProfileExceptionFunc throw_callback, MonoLegacyProfileMethodFunc exc_method_leave, MonoLegacyProfileExceptionClauseFunc clause_callback); static void @@ -1063,10 +1080,49 @@ mono_profiler_install_jit_end (MonoLegacyProfileJitResult end) } } + +static MonoProfilerCallInstrumentationFlags +call_instrumentation_filter_callback (MonoProfiler *prof, MonoMethod *method) +{ + return MONO_PROFILER_CALL_INSTRUMENTATION_ENTER | MONO_PROFILER_CALL_INSTRUMENTATION_LEAVE | MONO_PROFILER_CALL_INSTRUMENTATION_TAIL_CALL | MONO_PROFILER_CALL_INSTRUMENTATION_EXCEPTION_LEAVE; +} + +typedef enum +{ + MONO_PROFILE_NONE = 0, + MONO_PROFILE_APPDOMAIN_EVENTS = 1 << 0, + MONO_PROFILE_ASSEMBLY_EVENTS = 1 << 1, + MONO_PROFILE_MODULE_EVENTS = 1 << 2, + MONO_PROFILE_CLASS_EVENTS = 1 << 3, + MONO_PROFILE_JIT_COMPILATION = 1 << 4, + MONO_PROFILE_INLINING = 1 << 5, + MONO_PROFILE_EXCEPTIONS = 1 << 6, + MONO_PROFILE_ALLOCATIONS = 1 << 7, + MONO_PROFILE_GC = 1 << 8, + MONO_PROFILE_THREADS = 1 << 9, + MONO_PROFILE_REMOTING = 1 << 10, + MONO_PROFILE_TRANSITIONS = 1 << 11, + MONO_PROFILE_ENTER_LEAVE = 1 << 12, + MONO_PROFILE_COVERAGE = 1 << 13, + MONO_PROFILE_INS_COVERAGE = 1 << 14, + MONO_PROFILE_STATISTICAL = 1 << 15, + MONO_PROFILE_FILEIO = 1 << 16 +} LegacyMonoProfileFlags; + void mono_profiler_set_events (int flags) { + if (flags & MONO_PROFILE_ENTER_LEAVE) + mono_profiler_set_call_instrumentation_filter_callback (current->handle, call_instrumentation_filter_callback); + else + mono_profiler_set_call_instrumentation_filter_callback (current->handle, NULL); /* Do nothing. */ + + if (flags & MONO_PROFILE_ALLOCATIONS) + mono_profiler_enable_allocations (); + + if (flags & MONO_PROFILE_FILEIO) + mono_profiler_enable_fileio (); } static void @@ -1084,6 +1140,21 @@ mono_profiler_install_allocation (MonoLegacyProfileAllocFunc callback) mono_profiler_set_gc_allocation_callback (current->handle, allocation_cb); } +static void +fileio_cb (MonoProfiler *prof, uint64_t kind, uint64_t size) +{ + prof->fileio (prof->profiler, kind, size); +} + +void +mono_profiler_install_fileio (MonoLegacyProfileFileIOFunc callback) +{ + current->fileio = callback; + + if (callback) + mono_profiler_set_fileio_callback (current->handle, fileio_cb); +} + static void enter_cb (MonoProfiler *prof, MonoMethod *method, MonoProfilerCallContext *context) { diff --git a/mono/metadata/profiler.h b/mono/metadata/profiler.h index 11ddd4b71d48..f86021698410 100644 --- a/mono/metadata/profiler.h +++ b/mono/metadata/profiler.h @@ -43,7 +43,9 @@ typedef void (*MonoProfilerCoverageCallback) (MonoProfiler *prof, const MonoProf MONO_API mono_bool mono_profiler_enable_coverage (void); MONO_API void mono_profiler_set_coverage_filter_callback (MonoProfilerHandle handle, MonoProfilerCoverageFilterCallback cb); +#ifndef RUNTIME_IL2CPP MONO_API mono_bool mono_profiler_get_coverage_data (MonoProfilerHandle handle, MonoMethod *method, MonoProfilerCoverageCallback cb); +#endif typedef enum { /** @@ -68,6 +70,7 @@ MONO_API mono_bool mono_profiler_set_sample_mode (MonoProfilerHandle handle, Mon MONO_API mono_bool mono_profiler_get_sample_mode (MonoProfilerHandle handle, MonoProfilerSampleMode *mode, uint32_t *freq); MONO_API mono_bool mono_profiler_enable_allocations (void); +MONO_API mono_bool mono_profiler_enable_fileio (void); typedef struct _MonoProfilerCallContext MonoProfilerCallContext; diff --git a/mono/metadata/security-manager.h b/mono/metadata/security-manager.h index d9f49ceb510c..d92e169d2164 100644 --- a/mono/metadata/security-manager.h +++ b/mono/metadata/security-manager.h @@ -57,7 +57,7 @@ MonoMethod* mono_get_context_capture_method (void); MonoSecurityManager* mono_security_manager_get_methods (void); /* Security mode */ -void mono_security_set_mode (MonoSecurityMode mode); +UNITY_MONO_API void mono_security_set_mode (MonoSecurityMode mode); MonoSecurityMode mono_security_get_mode (void); /* internal calls */ diff --git a/mono/metadata/sgen-mono.c b/mono/metadata/sgen-mono.c index 800b8c87989f..1477057d27b0 100644 --- a/mono/metadata/sgen-mono.c +++ b/mono/metadata/sgen-mono.c @@ -2439,6 +2439,11 @@ sgen_client_thread_attach (SgenThreadInfo* info) info->client_info.info.handle_stack = mono_handle_stack_alloc (); } +void +mono_gc_thread_detach (SgenThreadInfo *info) +{ +} + void mono_gc_thread_detach_with_lock (SgenThreadInfo *info) { diff --git a/mono/metadata/threads-types.h b/mono/metadata/threads-types.h index 2feb0ba4f848..4189f7a75094 100644 --- a/mono/metadata/threads-types.h +++ b/mono/metadata/threads-types.h @@ -209,7 +209,7 @@ gboolean mono_thread_test_and_set_state (MonoInternalThread *thread, MonoThreadS void mono_thread_init_apartment_state (void); void mono_thread_cleanup_apartment_state (void); -void mono_threads_set_shutting_down (void); +UNITY_MONO_API void mono_threads_set_shutting_down (void); gunichar2* mono_thread_get_name (MonoInternalThread *this_obj, guint32 *name_len); @@ -218,11 +218,11 @@ void mono_thread_self_abort (void); void mono_thread_set_name_internal (MonoInternalThread *this_obj, MonoString *name, gboolean permanent, gboolean reset, MonoError *error); -void mono_thread_suspend_all_other_threads (void); +UNITY_MONO_API void mono_thread_suspend_all_other_threads (void); gboolean mono_threads_abort_appdomain_threads (MonoDomain *domain, int timeout); -void mono_thread_push_appdomain_ref (MonoDomain *domain); -void mono_thread_pop_appdomain_ref (void); +UNITY_MONO_API void mono_thread_push_appdomain_ref (MonoDomain *domain); +UNITY_MONO_API void mono_thread_pop_appdomain_ref (void); gboolean mono_thread_has_appdomain_ref (MonoThread *thread, MonoDomain *domain); MonoException* mono_thread_request_interruption (mono_bool running_managed); diff --git a/mono/metadata/threads.c b/mono/metadata/threads.c index 205e733936b9..367fb67fc560 100644 --- a/mono/metadata/threads.c +++ b/mono/metadata/threads.c @@ -55,6 +55,8 @@ #include #include +#include + #ifdef HAVE_SIGNAL_H #include #endif @@ -199,6 +201,7 @@ static gint32 thread_interruption_requested = 0; static MonoOSEvent background_change_event; static gboolean shutting_down = FALSE; +gboolean unity_shutting_down = FALSE; static gint32 managed_thread_id_counter = 0; @@ -1983,6 +1986,13 @@ ves_icall_System_Threading_WaitHandle_Wait_internal (gpointer *handles, gint32 n return map_native_wait_result_to_managed (ret, numhandles); } +/* + * UWP doesn't support SignalObjectAndWait until SDK version 15063. Our minspec currently is 10240. + * Since we don't care about running Mono runtime for now, let's just disable this icall and reevaluate + * in some months when we have to get libmono with IL2CPP up & running + */ +#if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) + gint32 ves_icall_System_Threading_WaitHandle_SignalAndWait_Internal (gpointer toSignal, gpointer toWait, gint32 ms, MonoError *error) { @@ -2010,6 +2020,8 @@ ves_icall_System_Threading_WaitHandle_SignalAndWait_Internal (gpointer toSignal, return map_native_wait_result_to_managed (ret, 1); } +#endif + gint32 ves_icall_System_Threading_Interlocked_Increment_Int (gint32 *location) { return mono_atomic_inc_i32 (location); @@ -3034,6 +3046,8 @@ thread_detach (MonoThreadInfo *info) g_assert (info); + mono_gc_thread_detach (info); + if (!mono_thread_info_try_get_internal_thread_gchandle (info, &gchandle)) return; @@ -3208,7 +3222,7 @@ static void build_wait_tids (gpointer key, gpointer value, gpointer user) /* Ignore background threads, we abort them later */ /* Do not lock here since it is not needed and the caller holds threads_lock */ - if (thread->state & ThreadState_Background) { + if (thread->state & ThreadState_Background || unity_shutting_down) { THREAD_DEBUG (g_message ("%s: ignoring background thread %"G_GSIZE_FORMAT, __func__, (gsize)thread->tid)); return; /* just leave, ignore */ } @@ -4848,7 +4862,7 @@ async_abort_critical (MonoThreadInfo *info, gpointer ud) gboolean protected_wrapper; gboolean running_managed; - if (mono_get_eh_callbacks ()->mono_install_handler_block_guard (mono_thread_info_get_suspend_state (info))) + if (mono_unity_get_enable_handler_block_guards () && mono_get_eh_callbacks ()->mono_install_handler_block_guard (mono_thread_info_get_suspend_state (info))) return MonoResumeThread; /*someone is already interrupting it*/ @@ -5369,3 +5383,24 @@ mono_thread_internal_is_current (MonoInternalThread *internal) g_assert (internal); return mono_native_thread_id_equals (mono_native_thread_id_get (), MONO_UINT_TO_NATIVE_THREAD_ID (internal->tid)); } + +MonoException* mono_unity_thread_check_exception() +{ + MonoInternalThread *thread = mono_thread_internal_current(); + MonoThread *sys_thread = mono_thread_current(); + + lock_thread(thread); + + if (sys_thread->pending_exception) { + MonoException *exc; + + exc = sys_thread->pending_exception; + sys_thread->pending_exception = NULL; + + unlock_thread(thread); + return exc; + } + + unlock_thread(thread); + return NULL; +} diff --git a/mono/metadata/unity-icall.c b/mono/metadata/unity-icall.c new file mode 100644 index 000000000000..1de9b6be406d --- /dev/null +++ b/mono/metadata/unity-icall.c @@ -0,0 +1,259 @@ +/** + * \file + * Unity icall support for Mono. + * + * Copyright 2016 Unity + * Licensed under the MIT license. See LICENSE file in the project root for full license information. +*/ +#include +#include +#include "mono/utils/mono-compiler.h" +#include +#include +#include +#include +#include +#include + +#ifdef HAVE_SYS_TIME_H +#include +#endif + +/* + * Magic number to convert a time which is relative to + * Jan 1, 1970 into a value which is relative to Jan 1, 0001. + */ +#define EPOCH_ADJUST ((guint64)62135596800LL) + +/* + * Magic number to convert FILETIME base Jan 1, 1601 to DateTime - base Jan, 1, 0001 + */ +#define FILETIME_ADJUST ((guint64)504911232000000000LL) + +#ifdef PLATFORM_WIN32 +/* convert a SYSTEMTIME which is of the form "last thursday in october" to a real date */ +static void +convert_to_absolute_date(SYSTEMTIME *date) +{ +#define IS_LEAP(y) ((y % 4) == 0 && ((y % 100) != 0 || (y % 400) == 0)) + static int days_in_month[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; + static int leap_days_in_month[] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; + /* from the calendar FAQ */ + int a = (14 - date->wMonth) / 12; + int y = date->wYear - a; + int m = date->wMonth + 12 * a - 2; + int d = (1 + y + y/4 - y/100 + y/400 + (31*m)/12) % 7; + + /* d is now the day of the week for the first of the month (0 == Sunday) */ + + int day_of_week = date->wDayOfWeek; + + /* set day_in_month to the first day in the month which falls on day_of_week */ + int day_in_month = 1 + (day_of_week - d); + if (day_in_month <= 0) + day_in_month += 7; + + /* wDay is 1 for first weekday in month, 2 for 2nd ... 5 means last - so work that out allowing for days in the month */ + date->wDay = day_in_month + (date->wDay - 1) * 7; + if (date->wDay > (IS_LEAP(date->wYear) ? leap_days_in_month[date->wMonth - 1] : days_in_month[date->wMonth - 1])) + date->wDay -= 7; +} +#endif + +#ifndef PLATFORM_WIN32 +/* + * Return's the offset from GMT of a local time. + * + * tm is a local time + * t is the same local time as seconds. + */ +static int +gmt_offset(struct tm *tm, time_t t) +{ +#if defined (HAVE_TM_GMTOFF) + return tm->tm_gmtoff; +#else + struct tm g; + time_t t2; + g = *gmtime(&t); + g.tm_isdst = tm->tm_isdst; + t2 = mktime(&g); + return (int)difftime(t, t2); +#endif +} +#endif +/* + * This is heavily based on zdump.c from glibc 2.2. + * + * * data[0]: start of daylight saving time (in DateTime ticks). + * * data[1]: end of daylight saving time (in DateTime ticks). + * * data[2]: utcoffset (in TimeSpan ticks). + * * data[3]: additional offset when daylight saving (in TimeSpan ticks). + * * name[0]: name of this timezone when not daylight saving. + * * name[1]: name of this timezone when daylight saving. + * + * FIXME: This only works with "standard" Unix dates (years between 1900 and 2100) while + * the class library allows years between 1 and 9999. + * + * Returns true on success and zero on failure. + */ +guint32 +ves_icall_System_CurrentSystemTimeZone_GetTimeZoneData (guint32 year, MonoArray **data, MonoArray **names) +{ + MonoError error; +#ifndef PLATFORM_WIN32 + MonoDomain *domain = mono_domain_get (); + struct tm start, tt; + time_t t; + + long int gmtoff; + int is_daylight = 0, day; + char tzone [64]; + + MONO_CHECK_ARG_NULL (data, FALSE); + MONO_CHECK_ARG_NULL (names, FALSE); + + mono_gc_wbarrier_generic_store (data, (MonoObject*) mono_array_new_checked (domain, mono_defaults.int64_class, 4, &error)); + mono_gc_wbarrier_generic_store (names, (MonoObject*) mono_array_new_checked (domain, mono_defaults.string_class, 2, &error)); + + /* + * no info is better than crashing: we'll need our own tz data + * to make this work properly, anyway. The range is probably + * reduced to 1970 .. 2037 because that is what mktime is + * guaranteed to support (we get into an infinite loop + * otherwise). + */ + + memset (&start, 0, sizeof (start)); + + start.tm_mday = 1; + start.tm_year = year-1900; + + t = mktime (&start); + + if ((year < 1970) || (year > 2037) || (t == -1)) { + t = time (NULL); + tt = *localtime (&t); + strftime (tzone, sizeof (tzone), "%Z", &tt); + mono_array_setref ((*names), 0, mono_string_new_checked (domain, tzone, &error)); + mono_array_setref ((*names), 1, mono_string_new_checked (domain, tzone, &error)); + return 1; + } + + gmtoff = gmt_offset (&start, t); + + /* For each day of the year, calculate the tm_gmtoff. */ + for (day = 0; day < 365; day++) { + + t += 3600*24; + tt = *localtime (&t); + + /* Daylight saving starts or ends here. */ + if (gmt_offset (&tt, t) != gmtoff) { + struct tm tt1; + time_t t1; + + /* Try to find the exact hour when daylight saving starts/ends. */ + t1 = t; + do { + t1 -= 3600; + tt1 = *localtime (&t1); + } while (gmt_offset (&tt1, t1) != gmtoff); + + /* Try to find the exact minute when daylight saving starts/ends. */ + do { + t1 += 60; + tt1 = *localtime (&t1); + } while (gmt_offset (&tt1, t1) == gmtoff); + t1+=gmtoff; + strftime (tzone, sizeof (tzone), "%Z", &tt); + + /* Write data, if we're already in daylight saving, we're done. */ + if (is_daylight) { + mono_array_setref ((*names), 0, mono_string_new_checked (domain, tzone, &error)); + mono_array_set ((*data), gint64, 1, ((gint64)t1 + EPOCH_ADJUST) * 10000000L); + return 1; + } else { + mono_array_setref ((*names), 1, mono_string_new_checked (domain, tzone, &error)); + mono_array_set ((*data), gint64, 0, ((gint64)t1 + EPOCH_ADJUST) * 10000000L); + is_daylight = 1; + } + + /* This is only set once when we enter daylight saving. */ + mono_array_set ((*data), gint64, 2, (gint64)gmtoff * 10000000L); + mono_array_set ((*data), gint64, 3, (gint64)(gmt_offset (&tt, t) - gmtoff) * 10000000L); + + gmtoff = gmt_offset (&tt, t); + } + } + + if (!is_daylight) { + strftime (tzone, sizeof (tzone), "%Z", &tt); + mono_array_setref ((*names), 0, mono_string_new_checked (domain, tzone, &error)); + mono_array_setref ((*names), 1, mono_string_new_checked (domain, tzone, &error)); + mono_array_set ((*data), gint64, 0, 0); + mono_array_set ((*data), gint64, 1, 0); + mono_array_set ((*data), gint64, 2, (gint64) gmtoff * 10000000L); + mono_array_set ((*data), gint64, 3, 0); + } + + return 1; +#else + MonoDomain *domain = mono_domain_get (); + TIME_ZONE_INFORMATION tz_info; + FILETIME ft; + int i; + int err, tz_id; + + tz_id = GetTimeZoneInformation (&tz_info); + if (tz_id == TIME_ZONE_ID_INVALID) + return 0; + + MONO_CHECK_ARG_NULL (data); + MONO_CHECK_ARG_NULL (names); + + mono_gc_wbarrier_generic_store (data, mono_array_new (domain, mono_defaults.int64_class, 4)); + mono_gc_wbarrier_generic_store (names, mono_array_new (domain, mono_defaults.string_class, 2)); + + for (i = 0; i < 32; ++i) + if (!tz_info.DaylightName [i]) + break; + mono_array_setref ((*names), 1, mono_string_new_utf16 (domain, tz_info.DaylightName, i)); + for (i = 0; i < 32; ++i) + if (!tz_info.StandardName [i]) + break; + mono_array_setref ((*names), 0, mono_string_new_utf16 (domain, tz_info.StandardName, i)); + + if ((year <= 1601) || (year > 30827)) { + /* + * According to MSDN, the MS time functions can't handle dates outside + * this interval. + */ + return 1; + } + + /* even if the timezone has no daylight savings it may have Bias (e.g. GMT+13 it seems) */ + if (tz_id != TIME_ZONE_ID_UNKNOWN) { + tz_info.StandardDate.wYear = year; + convert_to_absolute_date(&tz_info.StandardDate); + err = SystemTimeToFileTime (&tz_info.StandardDate, &ft); + //g_assert(err); + if (err == 0) + return 0; + + mono_array_set ((*data), gint64, 1, FILETIME_ADJUST + (((guint64)ft.dwHighDateTime<<32) | ft.dwLowDateTime)); + tz_info.DaylightDate.wYear = year; + convert_to_absolute_date(&tz_info.DaylightDate); + err = SystemTimeToFileTime (&tz_info.DaylightDate, &ft); + //g_assert(err); + if (err == 0) + return 0; + + mono_array_set ((*data), gint64, 0, FILETIME_ADJUST + (((guint64)ft.dwHighDateTime<<32) | ft.dwLowDateTime)); + } + mono_array_set ((*data), gint64, 2, (tz_info.Bias + tz_info.StandardBias) * -600000000LL); + mono_array_set ((*data), gint64, 3, (tz_info.DaylightBias - tz_info.StandardBias) * -600000000LL); + + return 1; +#endif +} diff --git a/mono/metadata/unity-liveness.c b/mono/metadata/unity-liveness.c new file mode 100644 index 000000000000..d5f13ecead74 --- /dev/null +++ b/mono/metadata/unity-liveness.c @@ -0,0 +1,646 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +typedef struct _LivenessState LivenessState; + +typedef struct _GPtrArray custom_growable_array; +#define array_at_index(array,index) (array)->pdata[(index)] + +#if defined(HAVE_SGEN_GC) +void sgen_stop_world (int generation); +void sgen_restart_world (int generation); +#elif defined(HAVE_BOEHM_GC) +#ifdef HAVE_BDWGC_GC +extern void GC_stop_world_external(); +extern void GC_start_world_external(); +#else +void GC_stop_world_external() +{ + g_assert_not_reached (); +} +void GC_start_world_external() +{ + g_assert_not_reached (); +} +#endif +#else +#error need to implement liveness GC API +#endif + +custom_growable_array* array_create_and_initialize (guint capacity) +{ + custom_growable_array* array = g_ptr_array_sized_new(capacity); + array->len = 0; + return array; +} + +gboolean array_is_full(custom_growable_array* array) +{ + return g_ptr_array_capacity(array) == array->len; +} + +void array_destroy (custom_growable_array* array) +{ + g_ptr_array_free(array, TRUE); +} + +void array_push_back(custom_growable_array* array, gpointer value) +{ + g_assert(!array_is_full(array)); + array->pdata[array->len] = value; + array->len++; +} + +gpointer array_pop_back(custom_growable_array* array) +{ + array->len--; + return array->pdata[array->len]; +} + +void array_clear(custom_growable_array* array) +{ + array->len = 0; +} + +void array_grow(custom_growable_array* array) +{ + int oldlen = array->len; + g_ptr_array_set_size(array, g_ptr_array_capacity(array)*2); + array->len = oldlen; +} + +typedef void (*register_object_callback)(gpointer* arr, int size, void* callback_userdata); +typedef void (*WorldStateChanged)(); +struct _LivenessState +{ + gint first_index_in_all_objects; + custom_growable_array* all_objects; + + MonoClass* filter; + + custom_growable_array* process_array; + guint initial_alloc_count; + + void* callback_userdata; + + register_object_callback filter_callback; + WorldStateChanged onWorldStartCallback; + WorldStateChanged onWorldStopCallback; +}; + +/* Liveness calculation */ +MONO_API LivenessState* mono_unity_liveness_allocate_struct (MonoClass* filter, guint max_count, register_object_callback callback, void* callback_userdata, WorldStateChanged onWorldStartCallback, WorldStateChanged onWorldStopCallback); +MONO_API void mono_unity_liveness_stop_gc_world (LivenessState* state); +MONO_API void mono_unity_liveness_finalize (LivenessState* state); +MONO_API void mono_unity_liveness_start_gc_world (LivenessState* state); +MONO_API void mono_unity_liveness_free_struct (LivenessState* state); + +MONO_API LivenessState* mono_unity_liveness_calculation_begin (MonoClass* filter, guint max_count, register_object_callback callback, void* callback_userdata, WorldStateChanged onStartWorldCallback, WorldStateChanged onStopWorldCallback); +MONO_API void mono_unity_liveness_calculation_end (LivenessState* state); + +MONO_API void mono_unity_liveness_calculation_from_root (MonoObject* root, LivenessState* state); +MONO_API void mono_unity_liveness_calculation_from_statics (LivenessState* state); + +#define MARK_OBJ(obj) \ + do { \ + (obj)->vtable = (MonoVTable*)(((gsize)(obj)->vtable) | (gsize)1); \ + } while (0) + +#define CLEAR_OBJ(obj) \ + do { \ + (obj)->vtable = (MonoVTable*)(((gsize)(obj)->vtable) & ~(gsize)1); \ + } while (0) + +#define IS_MARKED(obj) \ + (((gsize)(obj)->vtable) & (gsize)1) + +#define GET_VTABLE(obj) \ + ((MonoVTable*)(((gsize)(obj)->vtable) & ~(gsize)1)) + + +void mono_filter_objects(LivenessState* state); + +void mono_reset_state(LivenessState* state) +{ + state->first_index_in_all_objects = state->all_objects->len; + array_clear(state->process_array); +} + +void array_safe_grow(LivenessState* state, custom_growable_array* array) +{ + // if all_objects run out of space, run through list + // clear bit in vtable, start the world, reallocate, stop the world and continue + int i; + for (i = 0; i < state->all_objects->len; i++) + { + MonoObject* object = array_at_index(state->all_objects,i); + CLEAR_OBJ(object); + } + mono_unity_liveness_start_gc_world(state); + array_grow(array); + mono_unity_liveness_stop_gc_world (state); + for (i = 0; i < state->all_objects->len; i++) + { + MonoObject* object = array_at_index(state->all_objects,i); + MARK_OBJ(object); + } +} + +static gboolean should_process_value (MonoObject* val, MonoClass* filter) +{ + MonoClass* val_class = GET_VTABLE(val)->klass; + if (filter && + !mono_class_has_parent (val_class, filter)) + return FALSE; + + return TRUE; +} + +static void mono_traverse_array (MonoArray* array, LivenessState* state); +static void mono_traverse_object (MonoObject* object, LivenessState* state); +static void mono_traverse_gc_desc (MonoObject* object, LivenessState* state); +static void mono_traverse_objects (LivenessState* state); + +static void mono_traverse_generic_object( MonoObject* object, LivenessState* state ) +{ +#ifdef HAVE_SGEN_GC + gsize gc_desc = 0; +#else + gsize gc_desc = (gsize)(GET_VTABLE(object)->gc_descr); +#endif + + if (gc_desc & (gsize)1) + mono_traverse_gc_desc (object, state); + else if (GET_VTABLE(object)->klass->rank) + mono_traverse_array ((MonoArray*)object, state); + else + mono_traverse_object (object, state); +} + + +static void mono_add_process_object (MonoObject* object, LivenessState* state) +{ + if (object && !IS_MARKED(object)) + { + gboolean has_references = GET_VTABLE(object)->klass->has_references; + if(has_references || should_process_value(object,state->filter)) + { + if (array_is_full(state->all_objects)) + array_safe_grow(state, state->all_objects); + array_push_back(state->all_objects, object); + MARK_OBJ(object); + } + // Check if klass has further references - if not skip adding + if (has_references) + { + if(array_is_full(state->process_array)) + array_safe_grow(state, state->process_array); + array_push_back(state->process_array, object); + } + } +} + +static gboolean mono_field_can_contain_references(MonoClassField* field) +{ + if (MONO_TYPE_ISSTRUCT(field->type)) + return TRUE; + if (field->type->attrs & FIELD_ATTRIBUTE_LITERAL) + return FALSE; + if (field->type->type == MONO_TYPE_STRING) + return FALSE; + return MONO_TYPE_IS_REFERENCE(field->type); +} + +static void mono_traverse_object_internal (MonoObject* object, gboolean isStruct, MonoClass* klass, LivenessState* state) +{ + int i; + MonoClassField *field; + MonoClass *p; + + g_assert (object); + + // subtract the added offset for the vtable. This is added to the offset even though it is a struct + if(isStruct) + object--; + + for (p = klass; p != NULL; p = p->parent) + { + if (p->size_inited == 0) + continue; + for (i = 0; i < mono_class_get_field_count (p); i++) + { + field = &p->fields[i]; + if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) + continue; + + if(!mono_field_can_contain_references(field)) + continue; + + if (MONO_TYPE_ISSTRUCT(field->type)) + { + char* offseted = (char*)object; + offseted += field->offset; + if (field->type->type == MONO_TYPE_GENERICINST) + { + g_assert(field->type->data.generic_class->cached_class); + mono_traverse_object_internal((MonoObject*)offseted, TRUE, field->type->data.generic_class->cached_class, state); + } + else + mono_traverse_object_internal((MonoObject*)offseted, TRUE, field->type->data.klass, state); + continue; + } + + if (field->offset == -1) { + g_assert_not_reached (); + } else { + MonoObject* val = NULL; + MonoVTable *vtable = NULL; + mono_field_get_value (object, field, &val); + mono_add_process_object (val, state); + } + } + } +} + +static void mono_traverse_object (MonoObject* object, LivenessState* state) +{ + mono_traverse_object_internal (object, FALSE, GET_VTABLE(object)->klass, state); +} + +static void mono_traverse_gc_desc (MonoObject* object, LivenessState* state) +{ +#define WORDSIZE ((int)sizeof(gsize)*8) + int i = 0; + gsize mask = (gsize)(GET_VTABLE(object)->gc_descr); + + g_assert (mask & (gsize)1); + + for (i = 0; i < WORDSIZE-2; i++) + { + gsize offset = ((gsize)1 << (WORDSIZE - 1 - i)); + if (mask & offset) + { + MonoObject* val = *(MonoObject**)(((char*)object) + i * sizeof(void*)); + mono_add_process_object(val, state); + } + } +} + +static void mono_traverse_objects (LivenessState* state) +{ + int i = 0; + MonoObject* object = NULL; + + while (state->process_array->len > 0) + { + object = array_pop_back(state->process_array); + mono_traverse_generic_object(object, state); + } +} + +static void mono_traverse_array (MonoArray* array, LivenessState* state) +{ + int i = 0; + gboolean has_references; + MonoObject* object = (MonoObject*)array; + MonoClass* element_class; + size_t elementClassSize; + size_t array_length; + + g_assert (object); + + + + element_class = GET_VTABLE(object)->klass->element_class; + has_references = !mono_class_is_valuetype(element_class); + g_assert(element_class->size_inited != 0); + + for (i = 0; i < mono_class_get_field_count (element_class); i++) + { + has_references |= mono_field_can_contain_references(&element_class->fields[i]); + } + + if (!has_references) + return; + + array_length = mono_array_length (array); + if (element_class->valuetype) + { + elementClassSize = mono_class_array_element_size (element_class); + for (i = 0; i < array_length; i++) + { + MonoObject* object = (MonoObject*)mono_array_addr_with_size (array, elementClassSize, i); + mono_traverse_object_internal (object, 1, element_class, state); + + // Add 128 objects at a time and then traverse, 64 seems not be enough + if( ((i+1) & 127) == 0) + mono_traverse_objects(state); + } + } + else + { + for (i = 0; i < array_length; i++) + { + MonoObject* val = mono_array_get(array, MonoObject*, i); + mono_add_process_object(val, state); + + // Add 128 objects at a time and then traverse, 64 seems not be enough + if( ((i+1) & 127) == 0) + mono_traverse_objects(state); + } + } +} + + +void mono_filter_objects(LivenessState* state) +{ + gpointer filtered_objects[64]; + gint num_objects = 0; + + int i = state->first_index_in_all_objects; + for ( ; i < state->all_objects->len; i++) + { + MonoObject* object = state->all_objects->pdata[i]; + if (should_process_value (object, state->filter)) + filtered_objects[num_objects++] = object; + if (num_objects == 64) + { + state->filter_callback(filtered_objects, 64, state->callback_userdata); + num_objects = 0; + } + } + + if (num_objects != 0) + state->filter_callback(filtered_objects, num_objects, state->callback_userdata); +} + +/** + * mono_unity_liveness_calculation_from_statics: + * + * Returns an array of MonoObject* that are reachable from the static roots + * in the current domain and derive from @filter (if not NULL). + */ +void mono_unity_liveness_calculation_from_statics(LivenessState* liveness_state) +{ + int i, j; + MonoDomain* domain = mono_domain_get(); + + mono_reset_state(liveness_state); + + + for (i = 0; i < domain->class_vtable_array->len; ++i) + { + MonoVTable* vtable = (MonoVTable *)g_ptr_array_index (domain->class_vtable_array, i); + MonoClass* klass = vtable->klass; + MonoClassField *field; + if (!klass) + continue; + if (!klass->has_static_refs) + continue; + if (klass->image == mono_defaults.corlib) + continue; + if (klass->size_inited == 0) + continue; + for (j = 0; j < mono_class_get_field_count (klass); j++) + { + field = &klass->fields[j]; + if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) + continue; + if(!mono_field_can_contain_references(field)) + continue; + // shortcut check for special statics + if (field->offset == -1) + continue; + + if (MONO_TYPE_ISSTRUCT(field->type)) + { + char* offseted = (char*)mono_vtable_get_static_field_data (vtable); + offseted += field->offset; + if (field->type->type == MONO_TYPE_GENERICINST) + { + g_assert(field->type->data.generic_class->cached_class); + mono_traverse_object_internal((MonoObject*)offseted, TRUE, field->type->data.generic_class->cached_class, liveness_state); + } + else + { + mono_traverse_object_internal((MonoObject*)offseted, TRUE, field->type->data.klass, liveness_state); + } + } + else + { + MonoError error; + MonoObject* val = NULL; + + mono_field_static_get_value_checked (mono_class_vtable (domain, klass), field, &val, &error); + + if (val && mono_error_ok (&error)) + { + mono_add_process_object(val, liveness_state); + } + mono_error_cleanup (&error); + } + } + } + mono_traverse_objects (liveness_state); + //Filter objects and call callback to register found objects + mono_filter_objects(liveness_state); +} + +void mono_unity_liveness_add_object_callback(gpointer* objs, gint count, void* arr) +{ + int i; + GPtrArray* objects = (GPtrArray*)arr; + for (i = 0; i < count; i++) + { + if (g_ptr_array_capacity(objects) > objects->len) + objects->pdata[objects->len++] = objs[i]; + } +} + +/** + * mono_unity_liveness_calculation_from_statics_managed: + * + * Returns a gchandle to an array of MonoObject* that are reachable from the static roots + * in the current domain and derive from type retrieved from @filter_handle (if not NULL). + */ +gpointer mono_unity_liveness_calculation_from_statics_managed(gpointer filter_handle, WorldStateChanged onWorldStartCallback, WorldStateChanged onWorldStopCallback) +{ + int i = 0; + MonoArray *res = NULL; + MonoReflectionType* filter_type = (MonoReflectionType*)mono_gchandle_get_target (GPOINTER_TO_UINT(filter_handle)); + MonoClass* filter = NULL; + GPtrArray* objects = NULL; + LivenessState* liveness_state = NULL; + MonoError* error = NULL; + + if (filter_type) + filter = mono_class_from_mono_type (filter_type->type); + + objects = g_ptr_array_sized_new(1000); + objects->len = 0; + + liveness_state = mono_unity_liveness_calculation_begin (filter, 1000, mono_unity_liveness_add_object_callback, (void*)objects, onWorldStartCallback, onWorldStopCallback); + + mono_unity_liveness_calculation_from_statics (liveness_state); + + mono_unity_liveness_calculation_end (liveness_state); + + res = mono_array_new_checked (mono_domain_get (), filter ? filter: mono_defaults.object_class, objects->len, error); + for (i = 0; i < objects->len; ++i) { + MonoObject* o = g_ptr_array_index (objects, i); + mono_array_setref (res, i, o); + } + g_ptr_array_free (objects, TRUE); + + + return (gpointer)mono_gchandle_new ((MonoObject*)res, FALSE); + +} + +/** + * mono_unity_liveness_calculation_from_root: + * + * Returns an array of MonoObject* that are reachable from @root + * in the current domain and derive from @filter (if not NULL). + */ +void mono_unity_liveness_calculation_from_root (MonoObject* root, LivenessState* liveness_state) +{ + mono_reset_state (liveness_state); + + array_push_back (liveness_state->process_array,root); + + mono_traverse_objects (liveness_state); + + //Filter objects and call callback to register found objects + mono_filter_objects (liveness_state); +} + +/** + * mono_unity_liveness_calculation_from_root_managed: + * + * Returns a gchandle to an array of MonoObject* that are reachable from the static roots + * in the current domain and derive from type retrieved from @filter_handle (if not NULL). + */ +gpointer mono_unity_liveness_calculation_from_root_managed(gpointer root_handle, gpointer filter_handle, WorldStateChanged onWorldStartCallback, WorldStateChanged onWorldStopCallback) +{ + int i = 0; + MonoArray *res = NULL; + MonoReflectionType* filter_type = (MonoReflectionType*)mono_gchandle_get_target (GPOINTER_TO_UINT(filter_handle)); + MonoObject* root = mono_gchandle_get_target (GPOINTER_TO_UINT(root_handle)); + MonoClass* filter = NULL; + GPtrArray* objects = NULL; + LivenessState* liveness_state = NULL; + MonoError* error = NULL; + + objects = g_ptr_array_sized_new(1000); + objects->len = 0; + + if (filter_type) + filter = mono_class_from_mono_type (filter_type->type); + + liveness_state = mono_unity_liveness_calculation_begin (filter, 1000, mono_unity_liveness_add_object_callback, (void*)objects, onWorldStartCallback, onWorldStopCallback); + + mono_unity_liveness_calculation_from_root (root, liveness_state); + + mono_unity_liveness_calculation_end (liveness_state); + + res = mono_array_new_checked (mono_domain_get (), filter ? filter: mono_defaults.object_class, objects->len, error); + for (i = 0; i < objects->len; ++i) { + MonoObject* o = g_ptr_array_index (objects, i); + mono_array_setref (res, i, o); + } + + g_ptr_array_free (objects, TRUE); + + return (gpointer)mono_gchandle_new ((MonoObject*)res, FALSE); +} + +LivenessState* mono_unity_liveness_allocate_struct (MonoClass* filter, guint max_count, register_object_callback callback, void* callback_userdata, WorldStateChanged onWorldStartCallback, WorldStateChanged onWorldStopCallback) +{ + LivenessState* state = NULL; + + // construct liveness_state; + // allocate memory for the following structs + // all_objects: contains a list of all referenced objects to be able to clean the vtable bits after the traversal + // process_array. array that contains the objcets that should be processed. this should run depth first to reduce memory usage + // if all_objects run out of space, run through list, add objects that match the filter, clear bit in vtable and then clear the array. + + state = g_new(LivenessState, 1); + max_count = max_count < 1000 ? 1000 : max_count; + state->all_objects = array_create_and_initialize(max_count*4); + state->process_array = array_create_and_initialize (max_count); + + state->first_index_in_all_objects = 0; + state->filter = filter; + + state->callback_userdata = callback_userdata; + state->filter_callback = callback; + state->onWorldStartCallback = onWorldStartCallback; + state->onWorldStopCallback = onWorldStopCallback; + + return state; +} + +void mono_unity_liveness_finalize (LivenessState* state) +{ + int i; + for (i = 0; i < state->all_objects->len; i++) + { + MonoObject* object = g_ptr_array_index(state->all_objects,i); + CLEAR_OBJ(object); + } +} + +void mono_unity_liveness_free_struct (LivenessState* state) +{ + //cleanup the liveness_state + array_destroy(state->all_objects); + array_destroy(state->process_array); + g_free(state); +} + +void mono_unity_liveness_stop_gc_world (LivenessState* state) +{ + state->onWorldStopCallback(); +#if defined(HAVE_SGEN_GC) + sgen_stop_world (1); +#elif defined(HAVE_BOEHM_GC) + GC_stop_world_external (); +#else +#error need to implement liveness GC API +#endif +} + +void mono_unity_liveness_start_gc_world (LivenessState* state) +{ +#if defined(HAVE_SGEN_GC) + sgen_restart_world (1); +#elif defined(HAVE_BOEHM_GC) + GC_start_world_external (); +#else +#error need to implement liveness GC API +#endif + state->onWorldStartCallback(); +} + +LivenessState* mono_unity_liveness_calculation_begin (MonoClass* filter, guint max_count, register_object_callback callback, void* callback_userdata, WorldStateChanged onWorldStartCallback, WorldStateChanged onWorldStopCallback) +{ + LivenessState* state = mono_unity_liveness_allocate_struct (filter, max_count, callback, callback_userdata, onWorldStartCallback, onWorldStopCallback); + mono_unity_liveness_stop_gc_world (state); + // no allocations can happen beyond this point + return state; +} + +void mono_unity_liveness_calculation_end (LivenessState* state) +{ + mono_unity_liveness_finalize(state); + mono_unity_liveness_start_gc_world(state); + mono_unity_liveness_free_struct(state); +} diff --git a/mono/metadata/unity-memory-info.c b/mono/metadata/unity-memory-info.c new file mode 100644 index 000000000000..5b531ad41c61 --- /dev/null +++ b/mono/metadata/unity-memory-info.c @@ -0,0 +1,15 @@ +#include +#include +#include "unity-memory-info.h" + +MonoManagedMemorySnapshot* mono_unity_capture_memory_snapshot() +{ + MonoManagedMemorySnapshot* snapshot; + snapshot = g_new0(MonoManagedMemorySnapshot, 1); + return snapshot; +} + +void mono_unity_free_captured_memory_snapshot(MonoManagedMemorySnapshot* snapshot) +{ + g_free(snapshot); +} \ No newline at end of file diff --git a/mono/metadata/unity-memory-info.h b/mono/metadata/unity-memory-info.h new file mode 100644 index 000000000000..f8b777b06eeb --- /dev/null +++ b/mono/metadata/unity-memory-info.h @@ -0,0 +1,100 @@ +#ifndef __UNITY_MONO_MEMORY_INFO_H +#define __UNITY_MONO_MEMORY_INFO_H + +#include + +typedef struct MonoMetadataField +{ + uint32_t offset; + uint32_t typeIndex; + const char* name; + gboolean isStatic; +} MonoMetadataField; + +typedef enum MonoMetadataTypeFlags +{ + kNone = 0, + kValueType = 1 << 0, + kArray = 1 << 1, + kArrayRankMask = 0xFFFF0000 +} MonoMetadataTypeFlags; + +typedef struct MonoMetadataType +{ + MonoMetadataTypeFlags flags; // If it's an array, rank is encoded in the upper 2 bytes + MonoMetadataField* fields; + uint32_t fieldCount; + uint32_t staticsSize; + uint8_t* statics; + uint32_t baseOrElementTypeIndex; + char* name; + const char* assemblyName; + uint64_t typeInfoAddress; + uint32_t size; +} MonoMetadataType; + +typedef struct MonoMetadataSnapshot +{ + uint32_t typeCount; + MonoMetadataType* types; +} MonoMetadataSnapshot; + +typedef struct MonoManagedMemorySection +{ + uint64_t sectionStartAddress; + uint32_t sectionSize; + uint8_t* sectionBytes; +} MonoManagedMemorySection; + +typedef struct MonoManagedHeap +{ + uint32_t sectionCount; + MonoManagedMemorySection* sections; +} MonoManagedHeap; + +typedef struct MonoStacks +{ + uint32_t stackCount; + MonoManagedMemorySection* stacks; +} MonoStacks; + +typedef struct NativeObject +{ + uint32_t gcHandleIndex; + uint32_t size; + uint32_t instanceId; + uint32_t classId; + uint32_t referencedNativeObjectIndicesCount; + uint32_t* referencedNativeObjectIndices; +} NativeObject; + +typedef struct MonoGCHandles +{ + uint32_t trackedObjectCount; + uint64_t* pointersToObjects; +} MonoGCHandles; + +typedef struct MonoRuntimeInformation +{ + uint32_t pointerSize; + uint32_t objectHeaderSize; + uint32_t arrayHeaderSize; + uint32_t arrayBoundsOffsetInHeader; + uint32_t arraySizeOffsetInHeader; + uint32_t allocationGranularity; +} MonoRuntimeInformation; + +typedef struct MonoManagedMemorySnapshot +{ + MonoManagedHeap heap; + MonoStacks stacks; + MonoMetadataSnapshot metadata; + MonoGCHandles gcHandles; + MonoRuntimeInformation runtimeInformation; + void* additionalUserInformation; +} MonoManagedMemorySnapshot; + +MONO_API MonoManagedMemorySnapshot* mono_unity_capture_memory_snapshot(); +MONO_API void mono_unity_free_captured_memory_snapshot(MonoManagedMemorySnapshot* snapshot); + +#endif diff --git a/mono/metadata/unity-utils.c b/mono/metadata/unity-utils.c new file mode 100644 index 000000000000..3f936239f682 --- /dev/null +++ b/mono/metadata/unity-utils.c @@ -0,0 +1,1323 @@ +#include + + +#include + +/* allow Unity to use deprecated functions for now */ +#ifdef MONO_RT_EXTERNAL_ONLY +#undef MONO_RT_EXTERNAL_ONLY +#define MONO_RT_EXTERNAL_ONLY +#endif +#include +#include +#include +#ifdef WIN32 +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#ifdef WIN32 +#define UTF8_2_WIDE(src,dst) MultiByteToWideChar( CP_UTF8, 0, src, -1, dst, MAX_PATH ) +#endif + +#undef exit + +void unity_mono_exit( int code ) +{ + //fprintf( stderr, "mono: exit called, code %d\n", code ); + exit( code ); +} + + +GString* gEmbeddingHostName = 0; + + +MONO_API void mono_unity_set_embeddinghostname(const char* name) +{ + gEmbeddingHostName = g_string_new(name); +} + + + +MonoString* mono_unity_get_embeddinghostname() +{ + if (gEmbeddingHostName == 0) + mono_unity_set_embeddinghostname("mono"); + return mono_string_new_wrapper(gEmbeddingHostName->str); +} + +static gboolean socket_security_enabled = FALSE; + +gboolean +mono_unity_socket_security_enabled_get () +{ + return socket_security_enabled; +} + +void +mono_unity_socket_security_enabled_set (gboolean enabled) +{ + socket_security_enabled = enabled; +} + +void mono_unity_set_vprintf_func (vprintf_func func) +{ + //set_vprintf_func (func); +} + +MONO_API gboolean +mono_unity_class_is_interface (MonoClass* klass) +{ + return MONO_CLASS_IS_INTERFACE(klass); +} + +MONO_API gboolean +mono_unity_class_is_abstract (MonoClass* klass) +{ + return (mono_class_get_flags (klass) & TYPE_ATTRIBUTE_ABSTRACT); +} + +// classes_ref is a preallocated array of *length_ref MonoClass* +// returned classes are stored in classes_ref, number of stored classes is stored in length_ref +// return value is number of classes found (which may be greater than number of classes stored) +unsigned mono_unity_get_all_classes_with_name_case (MonoImage *image, const char *name, MonoClass **classes_ref, unsigned *length_ref) +{ + MonoClass *klass; + MonoTableInfo *tdef = &image->tables [MONO_TABLE_TYPEDEF]; + int i, count; + guint32 attrs, visibility; + unsigned length = 0; + + /* (yoinked from icall.c) we start the count from 1 because we skip the special type */ + for (i = 1; i < tdef->rows; ++i) + { + klass = mono_class_get (image, (i + 1) | MONO_TOKEN_TYPE_DEF); + if (klass && klass->name && 0 == mono_utf8_strcasecmp (klass->name, name)) + { + if (length < *length_ref) + classes_ref[length] = klass; + ++length; + } + } + + if (length < *length_ref) + *length_ref = length; + return length; +} + +gboolean +unity_mono_method_is_generic (MonoMethod* method) +{ + return method->is_generic; +} + +MONO_API MonoMethod* +unity_mono_reflection_method_get_method(MonoReflectionMethod* mrf) +{ + if(!mrf) + return NULL; + + return mrf->method; +} + +MONO_API void +mono_unity_g_free(void *ptr) +{ + g_free (ptr); +} + + +MONO_API MonoClass* +mono_custom_attrs_get_attrs (MonoCustomAttrInfo *ainfo, gpointer *iter) +{ + int index = -1; + if (!iter) + return NULL; + if (!*iter) + { + *iter = 1; + return ainfo->attrs[0].ctor->klass; + } + + index = GPOINTER_TO_INT (*iter); + if (index >= ainfo->num_attrs) + return NULL; + *iter = GINT_TO_POINTER (index + 1); + return ainfo->attrs[index].ctor->klass; +} + +MONO_API gboolean +mono_class_is_inflated (MonoClass *klass) +{ + g_assert(klass); + return (klass->class_kind == MONO_CLASS_GINST); +} + +MONO_API void +mono_thread_pool_cleanup (void) +{ + // TODO_UNITY : I am not sure we need to call this anymore + mono_threadpool_cleanup (); +} + +MONO_API void* +mono_class_get_userdata (MonoClass* klass) +{ + return klass->unity_user_data; +} + +MONO_API void +mono_class_set_userdata(MonoClass* klass, void* userdata) +{ + klass->unity_user_data = userdata; +} + +MONO_API int +mono_class_get_userdata_offset() +{ + return offsetof(struct _MonoClass, unity_user_data); +} + + +static UnityFindPluginCallback unity_find_plugin_callback; + +MONO_API void +mono_set_find_plugin_callback (UnityFindPluginCallback find) +{ + unity_find_plugin_callback = find; +} + +MONO_API UnityFindPluginCallback +mono_get_find_plugin_callback () +{ + return unity_find_plugin_callback; +} + +//object + +void mono_unity_object_init(void* obj, MonoClass* klass) +{ + if (klass->valuetype) + memset(obj, 0, klass->instance_size - sizeof(MonoObject)); + else + *(MonoObject**)obj = NULL; +} + +MonoObject* mono_unity_object_isinst_sealed(MonoObject* obj, MonoClass* targetType) +{ + return obj->vtable->klass == targetType ? obj : NULL; +} + +void mono_unity_object_unbox_nullable(MonoObject* obj, MonoClass* nullableArgumentClass, void* storage) +{ + uint32_t valueSize = nullableArgumentClass->instance_size - sizeof(MonoObject); + + if (obj == NULL) + { + *((mono_byte*)(storage)+valueSize) = 0; + } + else if (obj->vtable->klass != nullableArgumentClass) + { + mono_raise_exception_deprecated (mono_get_exception_invalid_cast()); + } + else + { + memcpy(storage, mono_object_unbox(obj), valueSize); + *((mono_byte*)(storage)+valueSize) = 1; + } +} + +MonoClass* mono_unity_object_get_class(MonoObject *obj) +{ + return obj->vtable->klass; +} + +MonoObject* mono_unity_object_compare_exchange(MonoObject **location, MonoObject *value, MonoObject *comparand) +{ + return ves_icall_System_Threading_Interlocked_CompareExchange_T(location, value, comparand); +} + +MonoObject* mono_unity_object_exchange(MonoObject **location, MonoObject *value) +{ + return ves_icall_System_Threading_Interlocked_Exchange_T(location, value); +} + +gboolean mono_unity_object_check_box_cast(MonoObject *obj, MonoClass *klass) +{ + return (obj->vtable->klass->element_class == klass->element_class); +} + +//class + +const char* mono_unity_class_get_image_name(MonoClass* klass) +{ + return klass->image->assembly_name; +} + +MonoClass* mono_unity_class_get_generic_definition(MonoClass* klass) +{ + MonoGenericClass* generic_class = mono_class_try_get_generic_class (klass); + if (generic_class) + return generic_class->container_class; + + return NULL; +} + +MonoClass* mono_unity_class_inflate_generic_class(MonoClass *gklass, MonoGenericContext *context) +{ + MonoError error; + return mono_class_inflate_generic_class_checked(gklass, context, &error); +} + +gboolean mono_unity_class_has_parent_unsafe(MonoClass *klass, MonoClass *parent) +{ + return mono_class_has_parent_fast(klass, parent); +} + +MonoAssembly* mono_unity_class_get_assembly(MonoClass *klass) +{ + return klass->image->assembly; +} + +gboolean mono_unity_class_is_array(MonoClass *klass) +{ + return klass->rank > 0; +} + +MonoClass* mono_unity_class_get_element_class(MonoClass *klass) +{ + return klass->element_class; +} + +gboolean mono_unity_class_is_delegate(MonoClass *klass) +{ + return klass->delegate; +} + +int mono_unity_class_get_instance_size(MonoClass *klass) +{ + return klass->instance_size; +} + +MonoClass* mono_unity_class_get_castclass(MonoClass *klass) +{ + return klass->cast_class; +} + +guint32 mono_unity_class_get_native_size(MonoClass* klass) +{ + MonoMarshalType* info = mono_marshal_load_type_info(klass); + return info->native_size; +} + +MonoBoolean mono_unity_class_is_string(MonoClass* klass) +{ + if (mono_class_get_type(klass)->type == MONO_TYPE_STRING) + return TRUE; + return FALSE; +} + +MonoBoolean mono_unity_class_is_class_type(MonoClass* klass) +{ + if (mono_class_get_type(klass)->type == MONO_TYPE_CLASS) + return TRUE; + return FALSE; +} + +MONO_API gboolean +mono_class_is_generic(MonoClass *klass) +{ + g_assert(klass); + return (klass->class_kind == MONO_CLASS_GTD); +} + +MONO_API gboolean +mono_class_is_blittable(MonoClass *klass) +{ + g_assert(klass); + return klass->blittable; +} + +gboolean mono_unity_class_has_cctor(MonoClass *klass) +{ + return klass->has_cctor ? TRUE : FALSE; +} + +//method + +MonoMethod* mono_unity_method_get_generic_definition(MonoMethod* method) +{ + if (method->is_inflated) + return ((MonoMethodInflated*)method)->declaring; + + return NULL; +} + +MonoReflectionMethod* mono_unity_method_get_object(MonoMethod *method) +{ + MonoError unused; + return mono_method_get_object_checked(mono_domain_get(), method, NULL, &unused); +} + +MonoMethod* mono_unity_method_alloc0(MonoClass* klass) +{ + return mono_image_alloc0(klass->image, sizeof(MonoMethod)); +} + +MonoMethod* mono_unity_method_delegate_invoke_wrapper(MonoClass* klass) +{ + MonoMethod* method = (MonoMethod*)mono_image_alloc0(klass->image, sizeof(MonoMethod)); + MonoMethod *invoke = mono_get_delegate_invoke (klass); + method->signature = mono_metadata_signature_dup_full (klass->image, mono_method_signature (invoke)); + return method; +} + +gboolean mono_unity_method_is_static(MonoMethod *method) +{ + return method->flags & METHOD_ATTRIBUTE_STATIC; +} + +MonoClass* mono_unity_method_get_class(const MonoMethod *method) +{ + return method->klass; +} + +#ifdef IL2CPP_ON_MONO + +void* mono_unity_method_get_method_pointer(MonoMethod* method) +{ + return method->method_pointer; +} + +void mono_unity_method_set_method_pointer(MonoMethod* method, void *p) +{ + method->method_pointer = p; +} + +void* mono_unity_method_get_invoke_pointer(MonoMethod* method) +{ + return method->invoke_pointer; +} + +void mono_unity_method_set_invoke_pointer(MonoMethod* method, void *p) +{ + method->invoke_pointer = p; +} + +#endif + +const char* mono_unity_method_get_name(const MonoMethod *method) +{ + return method->name; +} + + +//must match the hash in il2cpp code generation +static guint32 hash_string_djb2(guchar *str) +{ + guint32 hash = 5381; + int c; + + while (c = *str++) + hash = ((hash << 5) + hash) + c; /* hash * 33 + c */ + + return hash; +} + +static guint32 get_array_structure_hash(MonoArrayType *atype) +{ + char buffer[100]; + char *ptr = buffer; + + *ptr++ = '['; + + char numbuffer[10]; + + for (int i = 0; i < atype->rank; ++i) + { + if (atype->numlobounds > 0 && atype->lobounds[i] != 0) + { + snprintf(numbuffer, 10, "%d", atype->lobounds[i]); + char *ptrnum = numbuffer; + while (*ptrnum) + *ptr++ = *ptrnum++; + + *ptr++ = ':'; + } + + if (atype->numsizes > 0 && atype->sizes[i] != 0) + { + snprintf(numbuffer, 10, "%d", atype->sizes[i]); + char *ptrnum = numbuffer; + while (*ptrnum) + *ptr++ = *ptrnum++; + } + + if (i < atype->rank - 1) + *ptr++ = ','; + } + + *ptr++ = ']'; + *ptr++ = 0; + + return hash_string_djb2(buffer); +} + +/* Begin: Hash computation helper functions */ + +static void get_type_hashes(MonoType *type, GList *hashes, gboolean inflate); +static void get_type_hashes_generic_inst(MonoGenericInst *inst, GList *hashes, gboolean inflate); + + +static void get_type_hashes_generic_inst(MonoGenericInst *inst, GList *hashes, gboolean inflate) +{ + for (int i = 0; i < inst->type_argc; ++i) + { + MonoType *type = inst->type_argv[i]; + get_type_hashes(type, hashes, inflate); + } +} + +static void get_type_hashes(MonoType *type, GList *hashes, gboolean inflate) +{ + if (type->type != MONO_TYPE_GENERICINST) + { + MonoClass *klass = NULL; + + switch (type->type) + { + case MONO_TYPE_ARRAY: + { + MonoArrayType *atype = type->data.array; + g_list_append(hashes, MONO_TOKEN_TYPE_SPEC); + g_list_append(hashes, get_array_structure_hash(atype)); + get_type_hashes(&(atype->eklass->this_arg), hashes, inflate); + break; + } + case MONO_TYPE_CLASS: + case MONO_TYPE_VALUETYPE: + klass = type->data.klass; + break; + case MONO_TYPE_BOOLEAN: + klass = mono_defaults.boolean_class; + break; + case MONO_TYPE_CHAR: + klass = mono_defaults.char_class; + break; + case MONO_TYPE_I: + klass = mono_defaults.int_class; + break; + case MONO_TYPE_U: + klass = mono_defaults.uint_class; + break; + case MONO_TYPE_I1: + klass = mono_defaults.sbyte_class; + break; + case MONO_TYPE_U1: + klass = mono_defaults.byte_class; + break; + case MONO_TYPE_I2: + klass = mono_defaults.int16_class; + break; + case MONO_TYPE_U2: + klass = mono_defaults.uint16_class; + break; + case MONO_TYPE_I4: + klass = mono_defaults.int32_class; + break; + case MONO_TYPE_U4: + klass = mono_defaults.uint32_class; + break; + case MONO_TYPE_I8: + klass = mono_defaults.int64_class; + break; + case MONO_TYPE_U8: + klass = mono_defaults.uint64_class; + break; + case MONO_TYPE_R4: + klass = mono_defaults.single_class; + break; + case MONO_TYPE_R8: + klass = mono_defaults.double_class; + break; + case MONO_TYPE_STRING: + klass = mono_defaults.string_class; + break; + case MONO_TYPE_OBJECT: + klass = mono_defaults.object_class; + break; + } + + if (klass) + { + g_list_append(hashes, klass->type_token); + g_list_append(hashes, hash_string_djb2(klass->image->module_name)); + } + + return; + } + else + { + g_list_append(hashes, type->data.generic_class->container_class->type_token); + g_list_append(hashes, hash_string_djb2(type->data.generic_class->container_class->image->module_name)); + + if (inflate) + get_type_hashes_generic_inst(type->data.generic_class->context.class_inst, hashes, inflate); + } + +} + +static GList* get_type_hashes_method(MonoMethod *method, gboolean inflate) +{ + GList *hashes = monoeg_g_list_alloc(); + + hashes->data = method->token; + g_list_append(hashes, hash_string_djb2(method->klass->image->module_name)); + + if (inflate && method->klass->class_kind == MONO_CLASS_GINST) + { + g_list_append(hashes, method->klass->type_token); + get_type_hashes_generic_inst(mono_class_get_generic_class (method->klass)->context.class_inst, hashes, inflate); + } + + if (inflate && method->is_inflated) + { + MonoGenericContext* methodGenericContext = mono_method_get_context(method); + if (methodGenericContext->method_inst != NULL) + get_type_hashes_generic_inst(methodGenericContext->method_inst, hashes, inflate); + } + + return hashes; +} + +//hash combination function must match the one used in IL2CPP codegen +static guint64 combine_hashes(guint64 hash1, guint64 hash2) +{ + const guint64 seed = 486187739; + return hash1 * seed + hash2; +} + +static void combine_all_hashes(gpointer data, gpointer user_data) +{ + guint64 *hash = (guint64*)user_data; + if (*hash == 0) + *hash = (guint64)data; + else + *hash = combine_hashes(*hash, (guint64)(uintptr_t)data); +} + +/* End: Hash computation helper functions */ + +guint64 mono_unity_method_get_hash(MonoMethod *method, gboolean inflate) +{ + GList *hashes = get_type_hashes_method(method, inflate); + + guint64 hash = 0; + + g_list_first(hashes); + g_list_foreach(hashes, combine_all_hashes, &hash); + g_list_free(hashes); + + return hash; +} + +guint64 mono_unity_type_get_hash(MonoType *type, gboolean inflate) +{ + GList *hashes = monoeg_g_list_alloc(); + + get_type_hashes(type, hashes, inflate); + + guint64 hash = 0; + + g_list_first(hashes); + g_list_foreach(hashes, combine_all_hashes, &hash); + g_list_free(hashes); + + return hash; +} + + +MonoMethod* mono_unity_method_get_aot_array_helper_from_wrapper(MonoMethod *method) +{ + MonoMethod *m; + const char *prefix; + MonoGenericContext ctx; + MonoType *args[16]; + char *mname, *iname, *s, *s2, *helper_name = NULL; + + prefix = "System.Collections.Generic"; + s = g_strdup_printf("%s", method->name + strlen(prefix) + 1); + s2 = strstr(s, "`1."); + g_assert(s2); + s2[0] = '\0'; + iname = s; + mname = s2 + 3; + + //printf ("X: %s %s\n", iname, mname); + + if (!strcmp(iname, "IList")) + helper_name = g_strdup_printf("InternalArray__%s", mname); + else + helper_name = g_strdup_printf("InternalArray__%s_%s", iname, mname); + m = mono_class_get_method_from_name(mono_defaults.array_class, helper_name, mono_method_signature(method)->param_count); + g_assert(m); + g_free(helper_name); + g_free(s); + + if (m->is_generic) { + MonoError error; + memset(&ctx, 0, sizeof(ctx)); + args[0] = &method->klass->element_class->byval_arg; + ctx.method_inst = mono_metadata_get_generic_inst(1, args); + m = mono_class_inflate_generic_method_checked(m, &ctx, &error); + g_assert(mono_error_ok(&error)); /* FIXME don't swallow the error */ + } + + return m; +} + +MonoObject* mono_unity_method_convert_return_type_if_needed(MonoMethod *method, void *value) +{ + if (method->signature && method->signature->ret->type == MONO_TYPE_PTR) + { + MonoError unused; + return mono_value_box_checked(mono_domain_get(), mono_defaults.int_class, &value, &unused); + } + + return (MonoObject*)value; +} + +MONO_API gboolean +unity_mono_method_is_inflated(MonoMethod* method) +{ + return method->is_inflated; +} + +guint32 mono_unity_method_get_token(MonoMethod *method) +{ + return method->token; +} + +//domain + + +void mono_unity_domain_install_finalize_runtime_invoke(MonoDomain* domain, RuntimeInvokeFunction callback) +{ + domain->finalize_runtime_invoke = callback; +} + +void mono_unity_domain_install_capture_context_runtime_invoke(MonoDomain* domain, RuntimeInvokeFunction callback) +{ + domain->capture_context_runtime_invoke = callback; +} + +void mono_unity_domain_install_capture_context_method(MonoDomain* domain, gpointer callback) +{ + domain->capture_context_method = callback; +} + +//array + +int mono_unity_array_get_element_size(MonoArray *arr) +{ + return arr->obj.vtable->klass->sizes.element_size; +} + +MonoClass* mono_unity_array_get_class(MonoArray *arr) +{ + return arr->obj.vtable->klass; +} + +mono_array_size_t mono_unity_array_get_max_length(MonoArray *arr) +{ + return arr->max_length; +} + +//type + +gboolean mono_unity_type_is_generic_instance(MonoType *type) +{ + return type->type == MONO_TYPE_GENERICINST; +} + +MonoGenericClass* mono_unity_type_get_generic_class(MonoType *type) +{ + if (type->type != MONO_TYPE_GENERICINST) + return NULL; + + return type->data.generic_class; +} + +gboolean mono_unity_type_is_enum_type(MonoType *type) +{ + if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) + return TRUE; + if (type->type == MONO_TYPE_GENERICINST && type->data.generic_class->container_class->enumtype) + return TRUE; + return FALSE; +} + +gboolean mono_unity_type_is_boolean(MonoType *type) +{ + return type->type == MONO_TYPE_BOOLEAN; +} + +MonoClass* mono_unity_type_get_element_class(MonoType *type) +{ + return type->data.klass->element_class; +} + +//generic class + +MonoGenericContext mono_unity_generic_class_get_context(MonoGenericClass *klass) +{ + return klass->context; +} + +MonoClass* mono_unity_generic_class_get_container_class(MonoGenericClass *klass) +{ + return klass->container_class; +} + +//method signature + +MonoClass* mono_unity_signature_get_class_for_param(MonoMethodSignature *sig, int index) +{ + MonoType *type = sig->params[index]; + return mono_class_from_mono_type(type); +} + +int mono_unity_signature_num_parameters(MonoMethodSignature *sig) +{ + return sig->param_count; +} + +gboolean mono_unity_signature_param_is_byref(MonoMethodSignature *sig, int index) +{ + return sig->params[index]->byref; +} + +//generic inst + +guint mono_unity_generic_inst_get_type_argc(MonoGenericInst *inst) +{ + return inst->type_argc; +} + +MonoType* mono_unity_generic_inst_get_type_argument(MonoGenericInst *inst, int index) +{ + return inst->type_argv[index]; +} + +//exception + +MonoString* mono_unity_exception_get_message(MonoException *exc) +{ + return exc->message; +} + +MonoString* mono_unity_exception_get_stack_trace(MonoException *exc) +{ + return exc->stack_trace; +} + +MonoObject* mono_unity_exception_get_inner_exception(MonoException *exc) +{ + return exc->inner_ex; +} + +MonoArray* mono_unity_exception_get_trace_ips(MonoException *exc) +{ + return exc->trace_ips; +} + +void mono_unity_exception_set_trace_ips(MonoException *exc, MonoArray *ips) +{ + g_assert(sizeof((exc)->trace_ips) == sizeof(void**)); + mono_gc_wbarrier_set_field((MonoObject*)(exc), &((exc)->trace_ips), (MonoObject*)ips); +} + +MonoException* mono_unity_exception_get_marshal_directive(const char* msg) +{ + return mono_exception_from_name_msg(mono_get_corlib(), "System.Runtime.InteropServices", "MarshalDirectiveException", msg); +} + +//defaults + +MonoClass* mono_unity_defaults_get_int_class() +{ + return mono_defaults.int_class; +} + +MonoClass* mono_unity_defaults_get_stack_frame_class() +{ + return mono_defaults.stack_frame_class; +} + +MonoClass* mono_unity_defaults_get_int32_class() +{ + return mono_defaults.int32_class; +} + +MonoClass* mono_unity_defaults_get_char_class() +{ + return mono_defaults.char_class; +} + +MonoClass* mono_unity_defaults_get_delegate_class() +{ + return mono_defaults.delegate_class; +} + +MonoClass* mono_unity_defaults_get_byte_class() +{ + return mono_defaults.byte_class; +} + +//unitytls + +static unitytls_interface_struct* gUnitytlsInterface = NULL; + +MONO_API unitytls_interface_struct* +mono_unity_get_unitytls_interface() +{ + return gUnitytlsInterface; +} + +MONO_API void +mono_unity_install_unitytls_interface(unitytls_interface_struct* callbacks) +{ + gUnitytlsInterface = callbacks; +} + +//misc + +MonoAssembly* mono_unity_assembly_get_mscorlib() +{ + return mono_defaults.corlib->assembly; +} + +MonoImage* mono_unity_image_get_mscorlib() +{ + return mono_defaults.corlib->assembly->image; +} + +MonoClass* mono_unity_generic_container_get_parameter_class(MonoGenericContainer* generic_container, gint index) +{ + MonoGenericParam *param = mono_generic_container_get_param(generic_container, index); + return mono_class_from_generic_parameter_internal(param); +} + +MonoString* mono_unity_string_append_assembly_name_if_necessary(MonoString* typeName, const char* assemblyName) +{ + if (typeName != NULL) + { + MonoTypeNameParse info; + + // The mono_reflection_parse_type function will mangle the name, so don't use this copy later. + MonoError unused; + char* nameForParsing = mono_string_to_utf8_checked(typeName, &unused); + if (mono_reflection_parse_type(nameForParsing, &info)) + { + if (!info.assembly.name) + { + GString* assemblyQualifiedName = g_string_new(0); + char* name = mono_string_to_utf8_checked(typeName, &unused); + g_string_append_printf(assemblyQualifiedName, "%s, %s", name, assemblyName); + + typeName = mono_string_new(mono_domain_get(), assemblyQualifiedName->str); + + g_string_free(assemblyQualifiedName, FALSE); + mono_free(name); + } + } + + mono_free(nameForParsing); + } + + return typeName; +} + +void mono_unity_memory_barrier() +{ + mono_memory_barrier(); +} + +MonoObject* mono_unity_delegate_get_target(MonoDelegate *delegate) +{ + return delegate->target; +} + +gchar* mono_unity_get_runtime_build_info(const char *date, const char *time) +{ + return g_strdup_printf("Unity IL2CPP(%s %s)", date, time); +} + +void* mono_unity_get_field_address(MonoObject *obj, MonoVTable *vt, MonoClassField *field) +{ + // This is a copy of mono_field_get_addr - we need to consider how to expose that on the public API. + MONO_REQ_GC_UNSAFE_MODE; + + guint8 *src; + + if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) { + if (field->offset == -1) { + /* Special static */ + gpointer addr; + + mono_domain_lock(vt->domain); + addr = g_hash_table_lookup(vt->domain->special_static_fields, field); + mono_domain_unlock(vt->domain); + src = (guint8 *)mono_get_special_static_data(GPOINTER_TO_UINT(addr)); + } + else { + src = (guint8*)mono_vtable_get_static_field_data(vt) + field->offset; + } + } + else { + src = (guint8*)obj + field->offset; + } + + return src; +} + +gboolean mono_unity_thread_state_init_from_handle(MonoThreadUnwindState *tctx, MonoThreadInfo *info, void* fixme) +{ + tctx->valid = TRUE; + tctx->unwind_data[MONO_UNWIND_DATA_DOMAIN] = mono_domain_get(); + tctx->unwind_data[MONO_UNWIND_DATA_LMF] = NULL; + tctx->unwind_data[MONO_UNWIND_DATA_JIT_TLS] = NULL; + + return TRUE; +} + +void mono_unity_stackframe_set_method(MonoStackFrame *sf, MonoMethod *method) +{ + g_assert(sizeof(sf->method) == sizeof(void**)); + MonoError unused; + mono_gc_wbarrier_set_field((MonoObject*)(sf), &(sf->method), (MonoObject*)mono_method_get_object_checked(mono_domain_get(), method, NULL, &unused)); +} + +MonoType* mono_unity_reflection_type_get_type(MonoReflectionType *type) +{ + return type->type; +} + +// layer to proxy differences between old and new Mono versions + +MONO_API void +mono_unity_runtime_set_main_args (int argc, const char* argv[]) +{ + mono_runtime_set_main_args (argc, argv); +} + +MONO_API MonoString* +mono_unity_string_empty_wrapper () +{ + return mono_string_empty (mono_domain_get ()); +} + +MONO_API MonoArray* +mono_unity_array_new_2d (MonoDomain *domain, MonoClass *eklass, size_t size0, size_t size1) +{ + MonoError error; + uintptr_t sizes[] = { (uintptr_t)size0, (uintptr_t)size1 }; + MonoClass* ac = mono_array_class_get (eklass, 2); + + MonoArray* array = mono_array_new_full_checked (domain, ac, sizes, NULL, &error); + mono_error_cleanup (&error); + + return array; +} + +MONO_API MonoArray* +mono_unity_array_new_3d (MonoDomain *domain, MonoClass *eklass, size_t size0, size_t size1, size_t size2) +{ + MonoError error; + uintptr_t sizes[] = { (uintptr_t)size0, (uintptr_t)size1, (uintptr_t)size2 }; + MonoClass* ac = mono_array_class_get (eklass, 3); + + MonoArray* array = mono_array_new_full_checked (domain, ac, sizes, NULL, &error); + mono_error_cleanup (&error); + + return array; +} + +MONO_API void +mono_unity_domain_set_config (MonoDomain *domain, const char *base_dir, const char *config_file_name) +{ + mono_domain_set_config (domain, base_dir, config_file_name); +} + +// only needed on OSX +MONO_API int +mono_unity_backtrace_from_context (void* context, void* array[], int count) +{ + return 0; +} + +MONO_API MonoException* +mono_unity_loader_get_last_error_and_error_prepare_exception () +{ + return NULL; +} + +MONO_API void +mono_unity_install_memory_callbacks (MonoAllocatorVTable* callbacks) +{ + mono_set_allocator_vtable (callbacks); +} + +static char* data_dir = NULL; +MONO_API void +mono_unity_set_data_dir(const char* dir) +{ + if (data_dir) + g_free(data_dir); + + data_dir = g_new(char*, strlen(dir) + 1); + strcpy(data_dir, dir); +} + +MONO_API char* +mono_unity_get_data_dir() +{ + return data_dir; +} + +MONO_API MonoClass* +mono_unity_class_get_generic_type_definition (MonoClass* klass) +{ + MonoGenericClass* generic_class = mono_class_try_get_generic_class (klass); + return generic_class ? generic_class->container_class : NULL; +} + +MONO_API MonoClass* +mono_unity_class_get_generic_parameter_at (MonoClass* klass, guint32 index) +{ + MonoGenericContainer* generic_container = mono_class_try_get_generic_container (klass); + if (!generic_container || index >= generic_container->type_argc) + return NULL; + + return mono_class_from_generic_parameter_internal (mono_generic_container_get_param (generic_container, index)); +} + +MONO_API guint32 +mono_unity_class_get_generic_parameter_count (MonoClass* klass) +{ + MonoGenericContainer* generic_container = mono_class_try_get_generic_container (klass); + + if (!generic_container) + return 0; + + return generic_container->type_argc; +} + +MONO_API MonoClass* +mono_unity_class_get(MonoImage* image, guint32 type_token) +{ + // Unity expects to try to get classes that don't exist, and + // have a value of NULL returned. So eat the error message. + MonoError unused; + MonoClass* klass= mono_class_get_checked(image, type_token, &unused); + mono_error_cleanup(&unused); + return klass; +} + +MONO_API gpointer +mono_unity_alloc(gsize size) +{ + return g_malloc(size); +} + + +MONO_API void +mono_unity_thread_fast_attach (MonoDomain *domain) +{ + MonoInternalThread *thread; + + g_assert (domain); + g_assert (domain != mono_get_root_domain ()); + + thread = mono_thread_internal_current (); + g_assert (thread); + + mono_thread_push_appdomain_ref (domain); + g_assert (mono_domain_set (domain, FALSE)); + + //mono_profiler_thread_fast_attach (thread->tid); +} + +MONO_API void +mono_unity_thread_fast_detach () +{ + MonoInternalThread *thread; + MonoDomain *current_domain; + + thread = mono_thread_internal_current (); + g_assert (thread); + + current_domain = mono_domain_get (); + + g_assert (current_domain); + g_assert (current_domain != mono_get_root_domain ()); + + //mono_profiler_thread_fast_detach (thread->tid); + + // Migrating to the root domain and popping the domain reference allows + // the thread to stay alive and keep running while the domain can be unloaded + g_assert (mono_domain_set (mono_get_root_domain (), FALSE)); + mono_thread_pop_appdomain_ref (); +} + +// hack, FIXME jon + +/* +size_t RemapPathFunction (const char* path, char* buffer, size_t buffer_len) + path = original path + buffer = provided buffer to fill out + buffer_len = byte size of buffer (above) + return value = buffer size needed, incl. terminating 0 + * may be called with buffer = null / buffer_len = 0, or a shorter-than-necessary-buffer. + * return value is always the size _needed_; not the size written. + * terminating zero should always be written. + * if buffer_len is less than needed, buffer content is undefined + * if return value is 0 no remapping is needed / available +*/ +static RemapPathFunction g_RemapPathFunc = NULL; + +void +mono_unity_register_path_remapper (RemapPathFunction func) +{ + g_RemapPathFunc = func; +} + +/* calls remapper function if registered; allocates memory if remapping is available */ +static inline size_t +call_remapper(const char* path, char** buf) +{ + size_t len; + + if (!g_RemapPathFunc) + return 0; + + *buf = NULL; + len = g_RemapPathFunc(path, *buf, 0); + + if (len == 0) + return 0; + + *buf = g_new (char, len); + g_RemapPathFunc(path, *buf, len); + + return len; +} + +MonoBoolean +ves_icall_System_IO_MonoIO_RemapPath (MonoString *path, MonoString **new_path) +{ + MonoError error; + const gunichar2* path_remapped; + + if (!g_RemapPathFunc) + return 0; + + path_remapped = mono_unity_remap_path_utf16 (mono_string_chars (path)); + + if (!path_remapped) + return FALSE; + + mono_gc_wbarrier_generic_store (new_path, (MonoObject*)mono_string_from_utf16_checked (path_remapped, &error)); + + g_free (path_remapped); + + mono_error_set_pending_exception (&error); + + return TRUE; +} + +const char* +mono_unity_remap_path (const char* path) +{ + const char* path_remap = NULL; + call_remapper (path, &path_remap); + + return path_remap; +} + +const gunichar2* +mono_unity_remap_path_utf16 (const gunichar2* path) +{ + const gunichar2* path_remap = NULL; + char * utf8_path; + char * buf; + char * path_end; + size_t len; + + if (!g_RemapPathFunc) + return path_remap; + + utf8_path = g_utf16_to_utf8 (path, -1, NULL, NULL, NULL); + len = call_remapper (utf8_path, &buf); + if (len == 0) + { + g_free (utf8_path); + return path_remap; + } + + path_end = memchr (buf, '\0', len); + len = path_end ? (size_t)(path_end - buf) : len; + + path_remap = g_utf8_to_utf16 (buf, len, NULL, NULL, NULL); + + g_free (utf8_path); + g_free (buf); + + return path_remap; +} + +MonoMethod* +mono_method_get_method_definition (MonoMethod *method) +{ + while (method->is_inflated) + method = ((MonoMethodInflated*)method)->declaring; + return method; +} + +gboolean mono_allow_gc_aware_layout = TRUE; + +void +mono_class_set_allow_gc_aware_layout(mono_bool allow) +{ + mono_allow_gc_aware_layout = allow; +} + +static mono_bool enable_handler_block_guards = TRUE; + +void +mono_unity_set_enable_handler_block_guards (mono_bool allow) +{ + enable_handler_block_guards = allow; +} + +mono_bool +mono_unity_get_enable_handler_block_guards (void) +{ + return enable_handler_block_guards; +} diff --git a/mono/metadata/unity-utils.h b/mono/metadata/unity-utils.h new file mode 100644 index 000000000000..1bec5570544e --- /dev/null +++ b/mono/metadata/unity-utils.h @@ -0,0 +1,198 @@ +#ifndef __UNITY_MONO_UTILS_H +#define __UNITY_MONO_UTILS_H + +#include +#include +#include +#include + +typedef void(*vprintf_func)(const char* msg, va_list args); +typedef struct { + void* (*malloc_func)(size_t size); + void(*free_func)(void *ptr); + void* (*calloc_func)(size_t nmemb, size_t size); + void* (*realloc_func)(void *ptr, size_t size); +} MonoMemoryCallbacks; + +/** + * Custom exit function, called instead of system exit() + */ +void unity_mono_exit( int code ); + +/** + * Closes redirected output files. + */ +void unity_mono_close_output(void); + +extern MonoString* mono_unity_get_embeddinghostname(void); + +#ifdef WIN32 +FILE* unity_fopen( const char *name, const char *mode ); +#endif + +extern gboolean mono_unity_socket_security_enabled_get (void); +MONO_API extern void mono_unity_socket_security_enabled_set (gboolean enabled); +MONO_API void mono_unity_set_vprintf_func(vprintf_func func); + + +void unity_mono_install_memory_callbacks(MonoMemoryCallbacks* callbacks); + +MONO_API gboolean +unity_mono_method_is_generic (MonoMethod* method); + +typedef const char*(*UnityFindPluginCallback)(const char*); + +MONO_API void +mono_set_find_plugin_callback(UnityFindPluginCallback find); + +MONO_API UnityFindPluginCallback +mono_get_find_plugin_callback(); + +//object +void mono_unity_object_init(void* obj, MonoClass* klass); +MonoObject* mono_unity_object_isinst_sealed(MonoObject* obj, MonoClass* targetType); +void mono_unity_object_unbox_nullable(MonoObject* obj, MonoClass* nullableArgumentClass, void* storage); +MonoClass* mono_unity_object_get_class(MonoObject *obj); +MonoObject* mono_unity_object_compare_exchange(MonoObject **location, MonoObject *value, MonoObject *comparand); +MonoObject* mono_unity_object_exchange(MonoObject **location, MonoObject *value); +gboolean mono_unity_object_check_box_cast(MonoObject *obj, MonoClass *klass); + +//class +const char* mono_unity_class_get_image_name(MonoClass* klass); +MonoClass* mono_unity_class_get_generic_definition(MonoClass* klass); +MonoClass* mono_unity_class_inflate_generic_class(MonoClass *gklass, MonoGenericContext *context); +gboolean mono_unity_class_has_parent_unsafe(MonoClass *klass, MonoClass *parent); +MonoAssembly* mono_unity_class_get_assembly(MonoClass *klass); +gboolean mono_unity_class_is_array(MonoClass *klass); +MonoClass* mono_unity_class_get_element_class(MonoClass *klass); +gboolean mono_unity_class_is_delegate(MonoClass *klass); +int mono_unity_class_get_instance_size(MonoClass *klass); +MonoClass* mono_unity_class_get_castclass(MonoClass *klass); +guint32 mono_unity_class_get_native_size(MonoClass* klass); +MonoBoolean mono_unity_class_is_string(MonoClass* klass); +MonoBoolean mono_unity_class_is_class_type(MonoClass* klass); +MONO_API gboolean mono_class_is_generic(MonoClass *klass); +MONO_API gboolean mono_class_is_blittable(MonoClass *klass); +MONO_API gboolean mono_class_is_inflated(MonoClass *klass); +gboolean mono_unity_class_has_cctor(MonoClass *klass); + +//method +MonoMethod* mono_unity_method_get_generic_definition(MonoMethod* method); +MonoReflectionMethod* mono_unity_method_get_object(MonoMethod *method); +MonoMethod* mono_unity_method_alloc0(MonoClass* klass); +MonoMethod* mono_unity_method_delegate_invoke_wrapper(MonoClass* klass); +gboolean mono_unity_method_is_static(MonoMethod *method); +MonoClass* mono_unity_method_get_class(const MonoMethod *method); + +#ifdef IL2CPP_ON_MONO +void* mono_unity_method_get_method_pointer(MonoMethod* method); +void mono_unity_method_set_method_pointer(MonoMethod* method, void *p); +void* mono_unity_method_get_invoke_pointer(MonoMethod* method); +void mono_unity_method_set_invoke_pointer(MonoMethod* method, void *p); +#endif + +const char* mono_unity_method_get_name(const MonoMethod *method); +guint64 mono_unity_method_get_hash(MonoMethod *method, gboolean inflate); +MonoMethod* mono_unity_method_get_aot_array_helper_from_wrapper(MonoMethod *method); +MonoObject* mono_unity_method_convert_return_type_if_needed(MonoMethod *method, void *value); +MONO_API gboolean unity_mono_method_is_inflated(MonoMethod* method); +guint32 mono_unity_method_get_token(MonoMethod *method); + +//domain +void mono_unity_domain_install_finalize_runtime_invoke(MonoDomain* domain, RuntimeInvokeFunction callback); +void mono_unity_domain_install_capture_context_runtime_invoke(MonoDomain* domain, RuntimeInvokeFunction callback); +void mono_unity_domain_install_capture_context_method(MonoDomain* domain, void* callback); + +//array +int mono_unity_array_get_element_size(MonoArray *arr); +MonoClass* mono_unity_array_get_class(MonoArray *arr); +mono_array_size_t mono_unity_array_get_max_length(MonoArray *arr); + +//type +gboolean mono_unity_type_is_generic_instance(MonoType *type); +MonoGenericClass* mono_unity_type_get_generic_class(MonoType *type); +gboolean mono_unity_type_is_enum_type(MonoType *type); +gboolean mono_unity_type_is_boolean(MonoType *type); +MonoClass* mono_unity_type_get_element_class(MonoType *type); //only safe to call when the type has a defined klass data element +guint64 mono_unity_type_get_hash(MonoType *type, gboolean inflate); + +//generic class +MonoGenericContext mono_unity_generic_class_get_context(MonoGenericClass *klass); +MonoClass* mono_unity_generic_class_get_container_class(MonoGenericClass *klass); + +//method signature +MonoClass* mono_unity_signature_get_class_for_param(MonoMethodSignature *sig, int index); +int mono_unity_signature_num_parameters(MonoMethodSignature *sig); +gboolean mono_unity_signature_param_is_byref(MonoMethodSignature *sig, int index); + +//generic inst +guint mono_unity_generic_inst_get_type_argc(MonoGenericInst *inst); +MonoType* mono_unity_generic_inst_get_type_argument(MonoGenericInst *inst, int index); + +//exception +MonoString* mono_unity_exception_get_message(MonoException *exc); +MonoString* mono_unity_exception_get_stack_trace(MonoException *exc); +MonoObject* mono_unity_exception_get_inner_exception(MonoException *exc); +MonoArray* mono_unity_exception_get_trace_ips(MonoException *exc); +void mono_unity_exception_set_trace_ips(MonoException *exc, MonoArray *ips); +MonoException* mono_unity_exception_get_marshal_directive(const char* msg); + +//defaults +MonoClass* mono_unity_defaults_get_int_class(); +MonoClass* mono_unity_defaults_get_stack_frame_class(); +MonoClass* mono_unity_defaults_get_int32_class(); +MonoClass* mono_unity_defaults_get_char_class(); +MonoClass* mono_unity_defaults_get_delegate_class(); +MonoClass* mono_unity_defaults_get_byte_class(); + +//unitytls +typedef struct unitytls_interface_struct unitytls_interface_struct; +MONO_API unitytls_interface_struct* mono_unity_get_unitytls_interface(); +MONO_API void mono_unity_install_unitytls_interface(unitytls_interface_struct* callbacks); + +//misc +MonoAssembly* mono_unity_assembly_get_mscorlib(); +MonoImage* mono_unity_image_get_mscorlib(); +MonoClass* mono_unity_generic_container_get_parameter_class(MonoGenericContainer* generic_container, gint index); +MonoString* mono_unity_string_append_assembly_name_if_necessary(MonoString* typeName, const char* assemblyName); +void mono_unity_memory_barrier(); +MonoException* mono_unity_thread_check_exception(); +MonoObject* mono_unity_delegate_get_target(MonoDelegate *delegate); +gchar* mono_unity_get_runtime_build_info(const char *date, const char *time); +void* mono_unity_get_field_address(MonoObject *obj, MonoVTable *vt, MonoClassField *field); +gboolean mono_unity_thread_state_init_from_handle(MonoThreadUnwindState *tctx, MonoThreadInfo *info, void* fixme); +void mono_unity_stackframe_set_method(MonoStackFrame *sf, MonoMethod *method); +MonoType* mono_unity_reflection_type_get_type(MonoReflectionType *type); +MONO_API void mono_unity_set_data_dir(const char* dir); +MONO_API char* mono_unity_get_data_dir(); +MONO_API MonoClass* mono_unity_class_get(MonoImage* image, guint32 type_token); +MONO_API gpointer mono_unity_alloc(gsize size); +MONO_API void mono_unity_g_free (void *ptr); + +MONO_API MonoClass* mono_custom_attrs_get_attrs (MonoCustomAttrInfo *ainfo, gpointer *iter); + +typedef size_t (*RemapPathFunction)(const char* path, char* buffer, size_t buffer_len); +MONO_API void mono_unity_register_path_remapper (RemapPathFunction func); + +const char* +mono_unity_remap_path (const char* path); + +const gunichar2* +mono_unity_remap_path_utf16 (const gunichar2* path); + +MonoBoolean +ves_icall_System_IO_MonoIO_RemapPath (MonoString *path, MonoString **new_path); + +MonoMethod* +mono_method_get_method_definition(MonoMethod *method); + +void +mono_class_set_allow_gc_aware_layout(mono_bool allow); + +MONO_API void +mono_unity_set_enable_handler_block_guards (mono_bool allow); + +mono_bool +mono_unity_get_enable_handler_block_guards (void); + +#endif diff --git a/mono/metadata/verify-internals.h b/mono/metadata/verify-internals.h index 821de196bdd6..51a996c76741 100644 --- a/mono/metadata/verify-internals.h +++ b/mono/metadata/verify-internals.h @@ -19,7 +19,7 @@ typedef enum { MONO_VERIFIER_MODE_STRICT } MiniVerifierMode; -void mono_verifier_set_mode (MiniVerifierMode mode); +UNITY_MONO_API void mono_verifier_set_mode (MiniVerifierMode mode); void mono_verifier_enable_verify_all (void); gboolean mono_verifier_is_enabled_for_image (MonoImage *image); diff --git a/mono/metadata/w32error-unity.c b/mono/metadata/w32error-unity.c new file mode 100644 index 000000000000..5617f52f549f --- /dev/null +++ b/mono/metadata/w32error-unity.c @@ -0,0 +1,27 @@ +#include +#include "w32error.h" + +#if defined(PLATFORM_UNITY) && defined(UNITY_USE_PLATFORM_STUBS) + +guint32 +mono_w32error_get_last (void) +{ + g_assert(0 && "This function is not yet implemented for the Unity platform."); + return 0; +} + +void +mono_w32error_set_last (guint32 error) +{ + g_assert(0 && "This function is not yet implemented for the Unity platform."); +} + +guint32 +mono_w32error_unix_to_win32 (guint32 error) +{ + g_assert(0 && "This function is not yet implemented for the Unity platform."); + return 0; +} + + +#endif /* PLATFORM_UNITY && UNITY_USE_PLATFORM_STUBS */ diff --git a/mono/metadata/w32event-unity.c b/mono/metadata/w32event-unity.c new file mode 100644 index 000000000000..e1a570ba0f8a --- /dev/null +++ b/mono/metadata/w32event-unity.c @@ -0,0 +1,84 @@ +#include "w32event.h" +#include "Handle-c-api.h" +#include "Event-c-api.h" +#include "Error-c-api.h" + +void +mono_w32event_init (void) +{ +} + +gpointer +mono_w32event_create (gboolean manual, gboolean initial) +{ + UnityPalEvent* event = UnityPalEventNew(manual, initial); + return UnityPalEventHandleNew(event); +} + +gboolean +mono_w32event_close (gpointer handle) +{ + UnityPalHandleDestroy(handle); + return TRUE; +} + +void +mono_w32event_set (gpointer handle) +{ + UnityPalEventSet(UnityPalEventHandleGet(handle)); +} + +void +mono_w32event_reset (gpointer handle) +{ + UnityPalEventReset(UnityPalEventHandleGet(handle)); +} + +gpointer +ves_icall_System_Threading_Events_CreateEvent_internal (MonoBoolean manual, MonoBoolean initial, MonoStringHandle name, gint32 *err, MonoError *error) +{ + error_init (error); + if (!MONO_HANDLE_IS_NULL (name)) + { + g_assertion_message("Named events are not supported by the Unity platform."); + return NULL; + } + + UnityPalEvent* event = UnityPalEventNew(manual, initial); + *err = UnityPalGetLastError(); + return UnityPalEventHandleNew(event); +} + +gboolean +ves_icall_System_Threading_Events_SetEvent_internal (gpointer handle) +{ + UnityPalErrorCode result = UnityPalEventSet(UnityPalEventHandleGet(handle)); + return UnityPalSuccess(result); +} + +gboolean +ves_icall_System_Threading_Events_ResetEvent_internal (gpointer handle) +{ + UnityPalErrorCode result = UnityPalEventReset(UnityPalEventHandleGet(handle)); + return UnityPalSuccess(result); +} + +void +ves_icall_System_Threading_Events_CloseEvent_internal (gpointer handle) +{ + UnityPalHandleDestroy(handle); +} + +gpointer +ves_icall_System_Threading_Events_OpenEvent_internal (MonoStringHandle name, gint32 rights, gint32 *err, MonoError *error) +{ + g_assertion_message("Named events are not supported by the Unity platform."); + return NULL; +} + +MonoW32HandleNamespace* +mono_w32event_get_namespace (MonoW32HandleNamedEvent *event) +{ + g_assertion_message("Named events are not supported by the Unity platform."); + return NULL; +} diff --git a/mono/metadata/w32file-unity.c b/mono/metadata/w32file-unity.c new file mode 100644 index 000000000000..786c41111bd4 --- /dev/null +++ b/mono/metadata/w32file-unity.c @@ -0,0 +1,554 @@ +#include +#include + + + +#include "Directory-c-api.h" +#include "File-c-api.h" +#include "w32error.h" +#include "w32file.h" +#include "utils/strenc.h" +#include + + +#ifdef HOST_WIN32 + +gunichar2 +ves_icall_System_IO_MonoIO_get_VolumeSeparatorChar () +{ + return (gunichar2) ':'; /* colon */ +} + +gunichar2 +ves_icall_System_IO_MonoIO_get_DirectorySeparatorChar () +{ + return (gunichar2) '\\'; /* backslash */ +} + +gunichar2 +ves_icall_System_IO_MonoIO_get_AltDirectorySeparatorChar () +{ + return (gunichar2) '/'; /* forward slash */ +} + +gunichar2 +ves_icall_System_IO_MonoIO_get_PathSeparator () +{ + return (gunichar2) ';'; /* semicolon */ +} + +void ves_icall_System_IO_MonoIO_DumpHandles (void) +{ + return; +} +#endif /* HOST_WIN32 */ + +gpointer +mono_w32file_create(const gunichar2 *name, guint32 fileaccess, guint32 sharemode, guint32 createmode, guint32 attrs) +{ + int error = 0; + gpointer handle; + gchar* palPath = mono_unicode_to_external(name); + handle = UnityPalOpen(palPath, (int) createmode, (int) fileaccess, (int) sharemode, attrs, &error); + mono_w32error_set_last(error); + g_free(palPath); + + if (handle == NULL) + return INVALID_HANDLE_VALUE; + + return handle; +} + +gboolean +mono_w32file_close (gpointer handle) +{ + if (handle == NULL) + return FALSE; + + int error = 0; + gboolean result = UnityPalClose(handle, &error); + mono_w32error_set_last(error); + + return result; +} + +gboolean +mono_w32file_read(gpointer handle, gpointer buffer, guint32 numbytes, guint32 *bytesread) +{ + int error = 0; + + *bytesread = UnityPalRead(handle, buffer, numbytes, &error); + mono_w32error_set_last(error); + + return TRUE; +} + +gboolean +mono_w32file_write (gpointer handle, gconstpointer buffer, guint32 numbytes, guint32 *byteswritten) +{ + int error = 0; + + *byteswritten = UnityPalWrite(handle, buffer, numbytes, &error); + mono_w32error_set_last(error); + + return (*byteswritten > 0); +} + +gboolean +mono_w32file_flush (gpointer handle) +{ + int error = 0; + + gboolean result = UnityPalFlush(handle, &error); + mono_w32error_set_last(error); + + return result; +} + +gboolean +mono_w32file_truncate (gpointer handle) +{ + int error = 0; + + gboolean result = UnityPalTruncate(handle, &error); + mono_w32error_set_last(error); + + return result; +} + +guint32 +mono_w32file_seek (gpointer handle, gint32 movedistance, gint32 *highmovedistance, guint32 method) +{ + int error = 0; + + int32_t result = UnityPalSeek(handle, movedistance, 0, &error); + mono_w32error_set_last(error); + + return result; +} + +gint +mono_w32file_get_type (gpointer handle) +{ + if (handle == NULL) + return 0; + + return UnityPalGetFileType(handle); +} + +gboolean +mono_w32file_get_times (gpointer handle, FILETIME *create_time, FILETIME *access_time, FILETIME *write_time) +{ + /* Not Supported in UnityPAL */ + g_assert_not_reached(); +} + +gboolean +mono_w32file_set_times (gpointer handle, const FILETIME *create_time, const FILETIME *access_time, const FILETIME *write_time) +{ + int error = 0; + + gboolean result = UnityPalSetFileTime(handle, create_time, access_time, write_time, &error); + mono_w32error_set_last(error); + + return result; +} + +gpointer +mono_w32file_find_first (const gunichar2 *pattern, WIN32_FIND_DATA *find_data) +{ + gchar* palPath = mono_unicode_to_external(pattern); + UnityPalFindHandle* findHandle = UnityPalDirectoryFindHandleNew(palPath); + int32_t resultAttributes = 0; + + int32_t result = 0; + const char* filename; + + result = UnityPalDirectoryFindFirstFile(findHandle, palPath, &filename, &resultAttributes); + + if (result != 0) + { + mono_w32error_set_last(result); + return INVALID_HANDLE_VALUE; + } + + find_data->dwFileAttributes = resultAttributes; + + gunichar2 *utf16_basename; + glong bytes; + utf16_basename = g_utf8_to_utf16 (filename, -1, NULL, &bytes, NULL); + + /* this next section of memset and memcpy is code from mono, the cFileName field is + gunichar2 cFileName [MAX_PATH]. + Notes from mono: + Truncating a utf16 string like this might leave the last + gchar incomplete + utf16 is 2 * utf8 + */ + bytes *= 2; + memset (find_data->cFileName, '\0', (MAX_PATH * 2)); + memcpy (find_data->cFileName, utf16_basename, bytes < (MAX_PATH * 2) - 2 ? bytes : (MAX_PATH * 2) - 2); + + g_free(filename); + g_free(palPath); + g_free(utf16_basename); + + find_data->dwReserved0 = 0; + find_data->dwReserved1 = 0; + + find_data->cAlternateFileName [0] = 0; + + return findHandle; +} + +gboolean +mono_w32file_find_next (gpointer handle, WIN32_FIND_DATA *find_data) +{ + + int32_t resultAttributes = 0; + int32_t result; + const char* filename; + + result = UnityPalDirectoryFindNextFile(handle, &filename, &resultAttributes); + + find_data->dwFileAttributes = resultAttributes; + gunichar2 *utf16_basename; + glong bytes; + utf16_basename = g_utf8_to_utf16 (filename, -1, NULL, &bytes, NULL); + bytes *= 2; + + memset (find_data->cFileName, '\0', (MAX_PATH * 2)); + memcpy (find_data->cFileName, utf16_basename, bytes < (MAX_PATH * 2) - 2 ? bytes : (MAX_PATH * 2) - 2); + + g_free(filename); + g_free(utf16_basename); + + find_data->dwReserved0 = 0; + find_data->dwReserved1 = 0; + + find_data->cAlternateFileName [0] = 0; + + return (result == 0); +} + +gboolean +mono_w32file_find_close (gpointer handle) +{ + gboolean result = UnityPalDirectoryCloseOSHandle(handle); + UnityPalDirectoryFindHandleDelete(handle); + + return result; +} + +gboolean +mono_w32file_create_directory (const gunichar2 *name) +{ + int error = 0; + + gchar* palPath = mono_unicode_to_external(name); + gboolean result = UnityPalDirectoryCreate(palPath, &error); + mono_w32error_set_last(error); + g_free(palPath); + + return result; +} + +guint32 +mono_w32file_get_attributes (const gunichar2 *name) +{ + int error = 0; + + gchar* palPath = mono_unicode_to_external(name); + guint32 result = UnityPalGetFileAttributes(palPath, &error); + mono_w32error_set_last(error); + g_free(palPath); + + return result; +} + +gboolean +mono_w32file_get_attributes_ex (const gunichar2 *name, MonoIOStat *stat) +{ + gboolean result; + UnityPalFileStat palStat; + int error = 0; + + gchar* palPath = mono_unicode_to_external(name); + result = UnityPalGetFileStat(palPath, &palStat, &error); + mono_w32error_set_last(error); + + if (result) { + stat->attributes = palStat.attributes; + stat->creation_time = palStat.creation_time; + stat->last_access_time = palStat.last_access_time; + stat->last_write_time = palStat.last_write_time; + stat->length = palStat.length; + } + g_free(palPath); + + return result; +} + +gboolean +mono_w32file_set_attributes (const gunichar2 *name, guint32 attrs) +{ + int error = 0; + + gchar* palPath = mono_unicode_to_external(name); + gboolean result = UnityPalSetFileAttributes(palPath, attrs, &error); + mono_w32error_set_last(error); + g_free(palPath); + + return result; +} + +gboolean +mono_w32file_create_pipe (gpointer *readpipe, gpointer *writepipe, guint32 size) +{ + return UnityPalCreatePipe(*readpipe, *writepipe); +} + +gboolean +mono_w32file_get_disk_free_space (const gunichar2 *path_name, guint64 *free_bytes_avail, guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes) +{ + g_assert_not_reached(); + return FALSE; +} + +gboolean +mono_w32file_get_volume_information (const gunichar2 *path, gunichar2 *volumename, gint volumesize, gint *outserial, gint *maxcomp, gint *fsflags, gunichar2 *fsbuffer, gint fsbuffersize) +{ + g_assert_not_reached(); + return FALSE; +} + +gboolean +mono_w32file_move (const gunichar2 *path, const gunichar2 *dest, gint32 *error) +{ + gboolean result; + *error = 0; + MONO_ENTER_GC_SAFE; + + gchar* palPath = mono_unicode_to_external(path); + gchar* palDest = mono_unicode_to_external(dest); + result = UnityPalMoveFile(palPath, palDest, error); + mono_w32error_set_last(*error); + g_free(palPath); + g_free(palDest); + + MONO_EXIT_GC_SAFE; + + return result; +} + +gboolean +mono_w32file_replace (const gunichar2 *destination_file_name, const gunichar2 *source_file_name, const gunichar2 *destination_backup_file_name, guint32 flags, gint32 *error) +{ + gboolean result; + gchar* destPath = NULL; + gchar* sourcePath = NULL; + gchar* destBackupPath = NULL; + + if (destination_file_name != NULL) + { + destPath = mono_unicode_to_external(destination_file_name); + } + + if (source_file_name != NULL) + { + sourcePath = mono_unicode_to_external(source_file_name); + } + + if (destination_backup_file_name != NULL) + { + destBackupPath = mono_unicode_to_external(destination_backup_file_name); + } + + MONO_ENTER_GC_SAFE; + + result = UnityPalReplaceFile(sourcePath, destPath, destBackupPath, 0, error); + mono_w32error_set_last(*error); + + MONO_EXIT_GC_SAFE; + + g_free(destPath); + g_free(sourcePath); + g_free(destBackupPath); + + return result; +} + +gboolean +mono_w32file_copy (const gunichar2 *path, const gunichar2 *dest, gboolean overwrite, gint32 *error) +{ + gboolean result; + *error = 0; + + MONO_ENTER_GC_SAFE; + + gchar* palPath = mono_unicode_to_external(path); + gchar* palDest = mono_unicode_to_external(dest); + result = UnityPalCopyFile(palPath, palDest, overwrite, error); + mono_w32error_set_last(*error); + g_free(palPath); + g_free(palDest); + + MONO_EXIT_GC_SAFE; + + return result; +} + +gboolean +mono_w32file_lock (gpointer handle, gint64 position, gint64 length, gint32 *error) +{ + MONO_ENTER_GC_SAFE; + + UnityPalLock(handle, position, length, error); + mono_w32error_set_last(*error); + + MONO_EXIT_GC_SAFE; + + return (*error == 0); +} + +gboolean +mono_w32file_unlock (gpointer handle, gint64 position, gint64 length, gint32 *error) +{ + MONO_ENTER_GC_SAFE; + + UnityPalUnlock(handle, position, length, error); + mono_w32error_set_last(*error); + + MONO_EXIT_GC_SAFE; + + return (*error == 0); +} + +gpointer +mono_w32file_get_console_input (void) +{ + return UnityPalGetStdInput(); +} + +gpointer +mono_w32file_get_console_output (void) +{ + return UnityPalGetStdOutput(); +} + +gpointer +mono_w32file_get_console_error (void) +{ + return UnityPalGetStdError(); +} + +gint64 +mono_w32file_get_file_size (gpointer handle, gint32 *error) +{ + gint64 length; + + MONO_ENTER_GC_SAFE; + + length = UnityPalGetLength(handle, error); + mono_w32error_set_last(*error); + + MONO_EXIT_GC_SAFE; + + return length; +} + +guint32 +mono_w32file_get_drive_type (const gunichar2 *root_path_name) +{ + return 0; +} + +gint32 +mono_w32file_get_logical_drive (guint32 len, gunichar2 *buf) +{ + return -1; +} + +gboolean +mono_w32file_remove_directory (const gunichar2 *name) +{ + int error = 0; + + gchar* palPath = mono_unicode_to_external (name); + gboolean result = UnityPalDirectoryRemove(palPath, &error); + mono_w32error_set_last(error); + g_free(palPath); + + return result; +} + +gboolean mono_w32file_delete(const gunichar2 *name) +{ + int error = 0; + + gchar* palPath = mono_unicode_to_external (name); + gboolean result = UnityPalDeleteFile(palPath, &error); + mono_w32error_set_last (error); + g_free(palPath); + + return result; +} + +guint32 +mono_w32file_get_cwd (guint32 length, gunichar2 *buffer) +{ + /* length is the number of characters in buffer, including the null terminator */ + /* count is the number of characters in the current directory, including the null terminator */ + gunichar2 *utf16_path; + glong count; + uintptr_t bytes; + int error = 0; + + const char* palPath = UnityPalDirectoryGetCurrent(&error); + mono_w32error_set_last (error); + utf16_path = mono_unicode_from_external(palPath, &bytes); + count = (bytes / 2) + 1; + + if (count <= length) { + /* Add the terminator */ + memset (buffer, '\0', bytes+2); + memcpy (buffer, utf16_path, bytes); + } + + g_free(utf16_path); + g_free(palPath); + + return count; +} + +gboolean +mono_w32file_set_cwd (const gunichar2 *path) +{ + int error = 0; + + gchar* palPath = mono_unicode_to_external(path); + gboolean result = UnityPalDirectorySetCurrent(palPath, &error); + mono_w32error_set_last (error); + g_free(palPath); + + return result; +} + +gboolean +mono_w32file_set_length (gpointer handle, gint64 length, gint32 *error) +{ + gboolean result = UnityPalSetLength(handle, length, error); + mono_w32error_set_last(*error); + + return result; +} + +void +mono_w32file_cleanup (void) +{ +} + +void +mono_w32file_init (void) +{ +} diff --git a/mono/metadata/w32file-unix.c b/mono/metadata/w32file-unix.c index 94d9b547da3a..b170a3872afb 100644 --- a/mono/metadata/w32file-unix.c +++ b/mono/metadata/w32file-unix.c @@ -40,6 +40,7 @@ #include "w32file-unix-glob.h" #include "w32error.h" #include "fdhandle.h" +#include "mono/metadata/profiler-private.h" #include "utils/mono-io-portability.h" #include "utils/mono-logger-internals.h" #include "utils/mono-os-mutex.h" @@ -1037,6 +1038,7 @@ file_read(FileHandle *filehandle, gpointer buffer, guint32 numbytes, guint32 *by if (bytesread != NULL) { *bytesread = ret; + MONO_PROFILER_RAISE (fileio, (1, *bytesread)); } return(TRUE); @@ -1104,6 +1106,7 @@ file_write(FileHandle *filehandle, gconstpointer buffer, guint32 numbytes, guint } if (byteswritten != NULL) { *byteswritten = ret; + MONO_PROFILER_RAISE (fileio, (0, *byteswritten)); } return(TRUE); } diff --git a/mono/metadata/w32file-win32.c b/mono/metadata/w32file-win32.c index 7d08aefdeeb0..90fc55bfa08f 100644 --- a/mono/metadata/w32file-win32.c +++ b/mono/metadata/w32file-win32.c @@ -11,6 +11,7 @@ #include #include #include "mono/metadata/w32file-win32-internals.h" +#include "mono/metadata/profiler-private.h" void mono_w32file_init (void) @@ -87,6 +88,7 @@ mono_w32file_read(gpointer handle, gpointer buffer, guint32 numbytes, guint32 *b gboolean res; MONO_ENTER_GC_SAFE; res = ReadFile (handle, buffer, numbytes, bytesread, NULL); + MONO_PROFILER_RAISE (fileio, (1, *bytesread)); MONO_EXIT_GC_SAFE; return res; } @@ -97,6 +99,7 @@ mono_w32file_write (gpointer handle, gconstpointer buffer, guint32 numbytes, gui gboolean res; MONO_ENTER_GC_SAFE; res = WriteFile (handle, buffer, numbytes, byteswritten, NULL); + MONO_PROFILER_RAISE (fileio, (0, *byteswritten)); MONO_EXIT_GC_SAFE; return res; } diff --git a/mono/metadata/w32file.c b/mono/metadata/w32file.c index 2fbb9a0005a2..78569331c169 100644 --- a/mono/metadata/w32file.c +++ b/mono/metadata/w32file.c @@ -34,6 +34,7 @@ #include #include #include +#include #include #include #include @@ -190,7 +191,11 @@ MonoBoolean ves_icall_System_IO_MonoIO_CreateDirectory (const gunichar2 *path, gint32 *error) { gboolean ret; + const gunichar2 *path_remapped; + if (path_remapped = mono_unity_remap_path_utf16 (path)) + path = path_remapped; + *error=ERROR_SUCCESS; ret=mono_w32file_create_directory (path); @@ -198,6 +203,8 @@ ves_icall_System_IO_MonoIO_CreateDirectory (const gunichar2 *path, gint32 *error *error=mono_w32error_get_last (); } + g_free (path_remapped); + return(ret); } @@ -205,6 +212,10 @@ MonoBoolean ves_icall_System_IO_MonoIO_RemoveDirectory (const gunichar2 *path, gint32 *error) { gboolean ret; + const gunichar2 *path_remapped; + + if (path_remapped = mono_unity_remap_path_utf16 (path)) + path = path_remapped; *error=ERROR_SUCCESS; @@ -213,6 +224,8 @@ ves_icall_System_IO_MonoIO_RemoveDirectory (const gunichar2 *path, gint32 *error *error=mono_w32error_get_last (); } + g_free (path_remapped); + return(ret); } @@ -221,6 +234,10 @@ ves_icall_System_IO_MonoIO_FindFirstFile (const gunichar2 *path_with_pattern, Mo { HANDLE hnd; WIN32_FIND_DATA data; + const gunichar2 *path_with_pattern_remapped; + + if (path_with_pattern_remapped = mono_unity_remap_path_utf16 (path_with_pattern)) + path_with_pattern = path_with_pattern_remapped; hnd = mono_w32file_find_first (path_with_pattern, &data); @@ -228,6 +245,7 @@ ves_icall_System_IO_MonoIO_FindFirstFile (const gunichar2 *path_with_pattern, Mo MONO_HANDLE_ASSIGN (file_name, NULL_HANDLE_STRING); *file_attr = 0; *ioerror = mono_w32error_get_last (); + g_free (path_with_pattern_remapped); return hnd; } @@ -239,6 +257,7 @@ ves_icall_System_IO_MonoIO_FindFirstFile (const gunichar2 *path_with_pattern, Mo *file_attr = data.dwFileAttributes; *ioerror = ERROR_SUCCESS; + g_free (path_with_pattern_remapped); return hnd; } @@ -315,6 +334,10 @@ ves_icall_System_IO_MonoIO_SetCurrentDirectory (const gunichar2 *path, gint32 *error) { gboolean ret; + const gunichar2 *path_remapped; + + if (path_remapped = mono_unity_remap_path_utf16 (path)) + path = path_remapped; *error=ERROR_SUCCESS; @@ -322,15 +345,31 @@ ves_icall_System_IO_MonoIO_SetCurrentDirectory (const gunichar2 *path, if(ret==FALSE) { *error=mono_w32error_get_last (); } - + + g_free (path_remapped); + return(ret); } MonoBoolean ves_icall_System_IO_MonoIO_MoveFile (const gunichar2 *path, const gunichar2 *dest, gint32 *error) { + gboolean ret; + const gunichar2 *path_remapped; + const gunichar2 *dest_remapped; + + if (path_remapped = mono_unity_remap_path_utf16 (path)) + path = path_remapped; + if (dest_remapped = mono_unity_remap_path_utf16 (dest)) + dest = dest_remapped; + *error=ERROR_SUCCESS; - return mono_w32file_move (path, dest, error); + ret = mono_w32file_move (path, dest, error); + + g_free (path_remapped); + g_free (dest_remapped); + + return ret; } MonoBoolean @@ -338,29 +377,63 @@ ves_icall_System_IO_MonoIO_ReplaceFile (const gunichar2 *source_file_name, const const gunichar2 *destination_backup_file_name, MonoBoolean ignore_metadata_errors, gint32 *error) { + gboolean ret; guint32 replace_flags = REPLACEFILE_WRITE_THROUGH; + const gunichar2 *source_file_name_remapped; + const gunichar2 *destination_file_name_remapped; + const gunichar2 *destination_backup_file_name_remapped; + if (source_file_name_remapped = mono_unity_remap_path_utf16 (source_file_name)) + source_file_name = source_file_name_remapped; + if (destination_file_name_remapped = mono_unity_remap_path_utf16 (destination_file_name)) + destination_file_name = destination_file_name_remapped; + if (destination_backup_file_name_remapped = mono_unity_remap_path_utf16 (destination_backup_file_name)) + destination_backup_file_name = destination_backup_file_name_remapped; *error = ERROR_SUCCESS; if (ignore_metadata_errors) replace_flags |= REPLACEFILE_IGNORE_MERGE_ERRORS; /* FIXME: source and destination file names must not be NULL, but apparently they might be! */ - return mono_w32file_replace (destination_file_name, source_file_name, + ret = mono_w32file_replace (destination_file_name, source_file_name, destination_backup_file_name, replace_flags, error); + + g_free (source_file_name_remapped); + g_free (destination_file_name_remapped); + g_free (destination_backup_file_name_remapped); + + return ret; } MonoBoolean ves_icall_System_IO_MonoIO_CopyFile (const gunichar2 *path, const gunichar2 *dest, MonoBoolean overwrite, gint32 *error) { + gboolean ret; + const gunichar2 *path_remapped; + const gunichar2 *dest_remapped; + + if (path_remapped = mono_unity_remap_path_utf16 (path)) + path = path_remapped; + if (dest_remapped = mono_unity_remap_path_utf16 (dest)) + dest = dest_remapped; + *error=ERROR_SUCCESS; - return mono_w32file_copy (path, dest, overwrite, error); + ret = mono_w32file_copy (path, dest, overwrite, error); + + g_free (path_remapped); + g_free (dest_remapped); + + return ret; } MonoBoolean ves_icall_System_IO_MonoIO_DeleteFile (const gunichar2 *path, gint32 *error) { gboolean ret; + const gunichar2 *path_remapped; + + if (path_remapped = mono_unity_remap_path_utf16 (path)) + path = path_remapped; *error=ERROR_SUCCESS; @@ -368,6 +441,8 @@ ves_icall_System_IO_MonoIO_DeleteFile (const gunichar2 *path, gint32 *error) if(ret==FALSE) { *error=mono_w32error_get_last (); } + + g_free (path_remapped); return(ret); } @@ -376,6 +451,11 @@ gint32 ves_icall_System_IO_MonoIO_GetFileAttributes (const gunichar2 *path, gint32 *error) { gint32 ret; + const gunichar2 *path_remapped; + + if (path_remapped = mono_unity_remap_path_utf16 (path)) + path = path_remapped; + *error=ERROR_SUCCESS; ret = mono_w32file_get_attributes (path); @@ -390,6 +470,9 @@ ves_icall_System_IO_MonoIO_GetFileAttributes (const gunichar2 *path, gint32 *err /* if(ret==INVALID_FILE_ATTRIBUTES) { */ *error=mono_w32error_get_last (); } + + g_free (path_remapped); + return(ret); } @@ -430,6 +513,10 @@ MonoBoolean ves_icall_System_IO_MonoIO_GetFileStat (const gunichar2 *path, MonoIOStat *stat, gint32 *error) { gboolean result; + const gunichar2 *path_remapped; + + if (path_remapped = mono_unity_remap_path_utf16 (path)) + path = path_remapped; *error=ERROR_SUCCESS; @@ -440,6 +527,8 @@ ves_icall_System_IO_MonoIO_GetFileStat (const gunichar2 *path, MonoIOStat *stat, memset (stat, 0, sizeof (MonoIOStat)); } + g_free (path_remapped); + return result; } @@ -450,6 +539,10 @@ ves_icall_System_IO_MonoIO_Open (const gunichar2 *filename, gint32 mode, { HANDLE ret; int attributes, attrs; + const gunichar2 *filename_remapped; + + if (filename_remapped = mono_unity_remap_path_utf16 (filename)) + filename = filename_remapped; *error=ERROR_SUCCESS; @@ -485,8 +578,10 @@ ves_icall_System_IO_MonoIO_Open (const gunichar2 *filename, gint32 mode, ret=mono_w32file_create (filename, convert_access ((MonoFileAccess)access_mode), convert_share ((MonoFileShare)share), convert_mode ((MonoFileMode)mode), attributes); if(ret==INVALID_HANDLE_VALUE) { *error=mono_w32error_get_last (); - } - + } + + g_free (filename_remapped); + return(ret); } diff --git a/mono/metadata/w32handle.c b/mono/metadata/w32handle.c index 5ba22cab55c4..7ba74ef23fce 100644 --- a/mono/metadata/w32handle.c +++ b/mono/metadata/w32handle.c @@ -68,7 +68,7 @@ mono_w32handle_set_signal_state (MonoW32Handle *handle_data, gboolean state, gbo { #ifdef DEBUG g_message ("%s: setting state of %p to %s (broadcast %s)", __func__, - handle, state?"TRUE":"FALSE", broadcast?"TRUE":"FALSE"); + handle_data, state?"TRUE":"FALSE", broadcast?"TRUE":"FALSE"); #endif if (state) { diff --git a/mono/metadata/w32mutex-unity.c b/mono/metadata/w32mutex-unity.c new file mode 100644 index 000000000000..f58205fca35c --- /dev/null +++ b/mono/metadata/w32mutex-unity.c @@ -0,0 +1,49 @@ +#include "w32mutex.h" +#include "Mutex-c-api.h" + +void +mono_w32mutex_init (void) +{ +} + +gpointer +ves_icall_System_Threading_Mutex_CreateMutex_internal (MonoBoolean owned, MonoStringHandle name, MonoBoolean *created, MonoError *error) +{ + UnityPalMutex* mutex = NULL; + + *created = TRUE; + + if (!name) { + mutex = UnityPalMutexNew (owned); + } else { + g_assertion_message ("Named mutexes are not supported by the Unity platform."); + } + + return UnityPalMutexHandleNew(mutex); +} + +MonoBoolean +ves_icall_System_Threading_Mutex_ReleaseMutex_internal (gpointer handle) +{ + UnityPalMutexUnlock(UnityPalMutexHandleGet(handle)); + return TRUE; +} + +gpointer +ves_icall_System_Threading_Mutex_OpenMutex_internal (MonoStringHandle name, gint32 rights, gint32 *err, MonoError *error) +{ + g_assertion_message ("Named mutexes are not supported by the Unity platform."); + return NULL; +} + +MonoW32HandleNamespace* +mono_w32mutex_get_namespace (MonoW32HandleNamedMutex *mutex) +{ + g_assertion_message ("Named mutexes are not supported by the Unity platform."); + return NULL; +} + +void +mono_w32mutex_abandon (void) +{ +} diff --git a/mono/metadata/w32process-unity.c b/mono/metadata/w32process-unity.c new file mode 100644 index 000000000000..0b79fe252865 --- /dev/null +++ b/mono/metadata/w32process-unity.c @@ -0,0 +1,182 @@ +#include +#include + +#if defined(PLATFORM_UNITY) && defined(UNITY_USE_PLATFORM_STUBS) + +#ifdef HOST_WIN32 +typedef struct { + gpointer lpBaseOfDll; + guint32 SizeOfImage; + gpointer EntryPoint; +} MODULEINFO; +#endif + +void +mono_w32process_init (void) +{ + g_assert(0 && "This function is not yet implemented for the Unity platform."); +} + +void +mono_w32process_cleanup (void) +{ + g_assert(0 && "This function is not yet implemented for the Unity platform."); +} + +gpointer +ves_icall_System_Diagnostics_Process_GetProcess_internal (guint32 pid) +{ + g_assert(0 && "This function is not yet implemented for the Unity platform."); + return NULL; +} + +MonoBoolean +ves_icall_System_Diagnostics_Process_ShellExecuteEx_internal (MonoW32ProcessStartInfo *proc_start_info, MonoW32ProcessInfo *process_info) +{ + g_assert(0 && "This function is not yet implemented for the Unity platform."); + return FALSE; +} + +MonoBoolean +ves_icall_System_Diagnostics_Process_CreateProcess_internal (MonoW32ProcessStartInfo *proc_start_info, gpointer stdin_handle, + gpointer stdout_handle, gpointer stderr_handle, MonoW32ProcessInfo *process_info) +{ + g_assert(0 && "This function is not yet implemented for the Unity platform."); + return FALSE; +} + +MonoArray * +ves_icall_System_Diagnostics_Process_GetProcesses_internal (void) +{ + g_assert(0 && "This function is not yet implemented for the Unity platform."); + return NULL; +} + +MonoBoolean +ves_icall_Microsoft_Win32_NativeMethods_CloseProcess (gpointer handle) +{ + g_assert(0 && "This function is not yet implemented for the Unity platform."); + return FALSE; +} + +MonoBoolean +ves_icall_Microsoft_Win32_NativeMethods_TerminateProcess (gpointer handle, gint32 exitcode) +{ + g_assert(0 && "This function is not yet implemented for the Unity platform."); + return FALSE; +} + +MonoBoolean +ves_icall_Microsoft_Win32_NativeMethods_GetExitCodeProcess (gpointer handle, gint32 *exitcode) +{ + g_assert(0 && "This function is not yet implemented for the Unity platform."); + return FALSE; +} + +MonoBoolean +ves_icall_Microsoft_Win32_NativeMethods_GetProcessWorkingSetSize (gpointer handle, gsize *min, gsize *max) +{ + g_assert(0 && "This function is not yet implemented for the Unity platform."); + return FALSE; +} + +MonoBoolean +ves_icall_Microsoft_Win32_NativeMethods_SetProcessWorkingSetSize (gpointer handle, gsize min, gsize max) +{ + g_assert(0 && "This function is not yet implemented for the Unity platform."); + return FALSE; +} + +gint32 +ves_icall_Microsoft_Win32_NativeMethods_GetPriorityClass (gpointer handle) +{ + g_assert(0 && "This function is not yet implemented for the Unity platform."); + return 0; +} + +MonoBoolean +ves_icall_Microsoft_Win32_NativeMethods_SetPriorityClass (gpointer handle, gint32 priorityClass) +{ + g_assert(0 && "This function is not yet implemented for the Unity platform."); + return FALSE; +} + +MonoBoolean +ves_icall_Microsoft_Win32_NativeMethods_GetProcessTimes (gpointer handle, gint64 *creationtime, gint64 *exittime, gint64 *kerneltime, gint64 *usertime) +{ + g_assert(0 && "This function is not yet implemented for the Unity platform."); + return FALSE; +} + +gpointer +ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcess (void) +{ + g_assert(0 && "This function is not yet implemented for the Unity platform."); + return FALSE; +} + +gboolean +mono_w32process_get_fileversion_info (gunichar2 *filename, gpointer* data) +{ + g_assert(0 && "This function is not yet implemented for the Unity platform."); + return FALSE; +} + +guint32 +mono_w32process_get_fileversion_info_size (gunichar2 *filename, guint32 *handle) +{ + g_assert(0 && "This function is not yet implemented for the Unity platform."); + return 0; +} + +guint32 +mono_w32process_get_pid (gpointer handle) +{ + g_assert(0 && "This function is not yet implemented for the Unity platform."); + return 0; +} + +guint32 +mono_w32process_module_get_filename (gpointer process, gpointer module, gunichar2 *basename, guint32 size) +{ + g_assert(0 && "This function is not yet implemented for the Unity platform."); + return 0; +} + +gboolean +mono_w32process_module_get_information (gpointer process, gpointer module, MODULEINFO *modinfo, guint32 size) +{ + g_assert(0 && "This function is not yet implemented for the Unity platform."); + return FALSE; +} + +guint32 +mono_w32process_module_get_name (gpointer process, gpointer module, gunichar2 *basename, guint32 size) +{ + g_assert(0 && "This function is not yet implemented for the Unity platform."); + return 0; +} + + +gboolean +mono_w32process_try_get_modules (gpointer process, gpointer *modules, guint32 size, guint32 *needed) +{ + g_assert(0 && "This function is not yet implemented for the Unity platform."); + return FALSE; +} + +guint32 +mono_w32process_ver_language_name (guint32 lang, gunichar2 *lang_out, guint32 lang_len) +{ + g_assert(0 && "This function is not yet implemented for the Unity platform."); + return 0; +} + +gboolean +mono_w32process_ver_query_value (gconstpointer datablock, const gunichar2 *subblock, gpointer *buffer, guint32 *len) +{ + g_assert(0 && "This function is not yet implemented for the Unity platform."); + return FALSE; +} + +#endif /* PLATFORM_UNITY && UNITY_USE_PLATFORM_STUBS */ diff --git a/mono/metadata/w32process-unix.c b/mono/metadata/w32process-unix.c index 48d5e7af8465..2fb87faa4d44 100644 --- a/mono/metadata/w32process-unix.c +++ b/mono/metadata/w32process-unix.c @@ -1401,34 +1401,35 @@ process_add_sigchld_handler (void) void mono_w32process_signal_finished (void) { - int status; - int pid; - Process *process; + mono_coop_mutex_lock (&processes_mutex); + + for (Process* process = processes; process; process = process->next) { + int status = -1; + int pid; - do { do { - pid = waitpid (-1, &status, WNOHANG); + pid = waitpid (process->pid, &status, WNOHANG); } while (pid == -1 && errno == EINTR); - if (pid <= 0) - break; - - mono_coop_mutex_lock (&processes_mutex); + // possible values of 'pid': + // process->pid : the status changed for this child + // 0 : status unchanged for this PID + // ECHILD : process has been reaped elsewhere (or never existed) + // EINVAL : invalid PID or other argument - for (process = processes; process; process = process->next) { - if (process->pid != pid) - continue; - if (process->signalled) - continue; + // Therefore, we ignore status unchanged (nothing to do) and error + // events (process is cleaned up later). + if (pid <= 0) + continue; + if (process->signalled) + continue; - process->signalled = TRUE; - process->status = status; - mono_coop_sem_post (&process->exit_sem); - break; - } + process->signalled = TRUE; + process->status = status; + mono_coop_sem_post (&process->exit_sem); + } - mono_coop_mutex_unlock (&processes_mutex); - } while (1); + mono_coop_mutex_unlock (&processes_mutex); } static gboolean diff --git a/mono/metadata/w32semaphore-unity.c b/mono/metadata/w32semaphore-unity.c new file mode 100644 index 000000000000..778cb1693ccc --- /dev/null +++ b/mono/metadata/w32semaphore-unity.c @@ -0,0 +1,42 @@ +#include "w32semaphore.h" +#include "Semaphore-c-api.h" +#include "Error-c-api.h" + +void +mono_w32semaphore_init (void) +{ +} + +gpointer +ves_icall_System_Threading_Semaphore_CreateSemaphore_internal (gint32 initialCount, gint32 maximumCount, MonoString *name, gint32 *error) +{ + if (name != NULL) + { + g_assertion_message("Named semaphores are not supported by the Unity platform."); + return NULL; + } + + UnityPalSemaphore* semaphore = UnityPalSemaphoreNew(initialCount, maximumCount); + *error = UnityPalGetLastError(); + return UnityPalSemaphoreHandleNew(semaphore); +} + +MonoBoolean +ves_icall_System_Threading_Semaphore_ReleaseSemaphore_internal (gpointer handle, gint32 releaseCount, gint32 *prevcount) +{ + return UnityPalSemaphorePost(UnityPalSemaphoreHandleGet(handle), releaseCount, prevcount); +} + +gpointer +ves_icall_System_Threading_Semaphore_OpenSemaphore_internal (MonoString *name, gint32 rights, gint32 *error) +{ + g_assertion_message("Named semaphores are not supported by the Unity platform."); + return NULL; +} + +MonoW32HandleNamespace* +mono_w32semaphore_get_namespace (MonoW32HandleNamedSemaphore *semaphore) +{ + g_assertion_message("Named semaphores are not supported by the Unity platform."); + return NULL; +} diff --git a/mono/metadata/w32socket-internals.h b/mono/metadata/w32socket-internals.h index 62e2eb154c9c..7557818a630d 100644 --- a/mono/metadata/w32socket-internals.h +++ b/mono/metadata/w32socket-internals.h @@ -63,6 +63,9 @@ mono_w32socket_cleanup (void); SOCKET mono_w32socket_accept (SOCKET s, struct sockaddr *addr, socklen_t *addrlen, gboolean blocking); +SOCKET +mono_w32socket_accept_internal (SOCKET s, struct sockaddr *addr, socklen_t *addrlen, gboolean blocking); + int mono_w32socket_connect (SOCKET s, const struct sockaddr *name, int namelen, gboolean blocking); diff --git a/mono/metadata/w32socket-unity.c b/mono/metadata/w32socket-unity.c new file mode 100644 index 000000000000..38729c773d95 --- /dev/null +++ b/mono/metadata/w32socket-unity.c @@ -0,0 +1,201 @@ +#include "w32socket.h" +#include "w32socket-internals.h" + +#if defined(PLATFORM_UNITY) && defined(UNITY_USE_PLATFORM_STUBS) + +#ifdef NO_HAVE_TRANSMIT_FILE_BUFFERS + +typedef struct { + gpointer Head; + guint32 HeadLength; + gpointer Tail; + guint32 TailLength; +} TRANSMIT_FILE_BUFFERS; + +#endif + +gboolean +ves_icall_System_Net_Sockets_Socket_SupportPortReuse (MonoProtocolType proto, MonoError* error) +{ + g_assert(0 && "This function is not yet implemented for the Unity platform."); + return FALSE; +} + +MonoBoolean +ves_icall_System_Net_Dns_GetHostByName_internal (MonoStringHandle host, MonoStringHandleOut h_name, MonoArrayHandleOut h_aliases, MonoArrayHandleOut h_addr_list, gint32 hint, MonoError *error) +{ + g_assert(0 && "This function is not yet implemented for the Unity platform."); + return FALSE; +} + +void +mono_w32socket_initialize (void) +{ + g_assert(0 && "This function is not yet implemented for the Unity platform."); +} + +void +mono_w32socket_cleanup (void) +{ + g_assert(0 && "This function is not yet implemented for the Unity platform."); +} + +SOCKET mono_w32socket_accept (SOCKET s, struct sockaddr *addr, socklen_t *addrlen, gboolean blocking) +{ + g_assert(0 && "This function is not yet implemented for the Unity platform."); + return INVALID_SOCKET; +} + +int mono_w32socket_connect (SOCKET s, const struct sockaddr *name, int namelen, gboolean blocking) +{ + g_assert(0 && "This function is not yet implemented for the Unity platform."); + return 0; +} + +int mono_w32socket_recv (SOCKET s, char *buf, int len, int flags, gboolean blocking) +{ + g_assert(0 && "This function is not yet implemented for the Unity platform."); + return 0; +} + +int mono_w32socket_recvfrom (SOCKET s, char *buf, int len, int flags, struct sockaddr *from, socklen_t *fromlen, gboolean blocking) +{ + g_assert(0 && "This function is not yet implemented for the Unity platform."); + return 0; +} + +int mono_w32socket_recvbuffers (SOCKET s, WSABUF *lpBuffers, guint32 dwBufferCount, guint32 *lpNumberOfBytesRecvd, guint32 *lpFlags, gpointer lpOverlapped, gpointer lpCompletionRoutine, gboolean blocking) +{ + g_assert(0 && "This function is not yet implemented for the Unity platform."); + return 0; +} + +int mono_w32socket_send (SOCKET s, char *buf, int len, int flags, gboolean blocking) +{ + g_assert(0 && "This function is not yet implemented for the Unity platform."); + return 0; +} + +int mono_w32socket_sendto (SOCKET s, const char *buf, int len, int flags, const struct sockaddr *to, int tolen, gboolean blocking) +{ + g_assert(0 && "This function is not yet implemented for the Unity platform."); + return 0; +} + +int mono_w32socket_sendbuffers (SOCKET s, WSABUF *lpBuffers, guint32 dwBufferCount, guint32 *lpNumberOfBytesRecvd, guint32 lpFlags, gpointer lpOverlapped, gpointer lpCompletionRoutine, gboolean blocking) +{ + g_assert(0 && "This function is not yet implemented for the Unity platform."); + return 0; +} + +BOOL mono_w32socket_transmit_file (SOCKET hSocket, gpointer hFile, TRANSMIT_FILE_BUFFERS *lpTransmitBuffers, guint32 dwReserved, gboolean blocking) +{ + g_assert(0 && "This function is not yet implemented for the Unity platform."); + return FALSE; +} + +gint +mono_w32socket_disconnect (SOCKET sock, gboolean reuse) +{ + g_assert(0 && "This function is not yet implemented for the Unity platform."); + return 0; +} + +gint +mono_w32socket_set_blocking (SOCKET sock, gboolean blocking) +{ + g_assert(0 && "This function is not yet implemented for the Unity platform."); + return 0; +} + +gint +mono_w32socket_get_available (SOCKET sock, guint64 *amount) +{ + g_assert(0 && "This function is not yet implemented for the Unity platform."); + return 0; +} + +void +mono_w32socket_set_last_error (gint32 error) +{ + g_assert(0 && "This function is not yet implemented for the Unity platform."); +} + +gint32 +mono_w32socket_get_last_error (void) +{ + g_assert(0 && "This function is not yet implemented for the Unity platform."); + return 0; +} + +gint32 +mono_w32socket_convert_error (gint error) +{ + g_assert(0 && "This function is not yet implemented for the Unity platform."); + return 0; +} + +gint +mono_w32socket_bind (SOCKET sock, struct sockaddr *addr, socklen_t addrlen) +{ + g_assert(0 && "This function is not yet implemented for the Unity platform."); + return 0; +} + +gint +mono_w32socket_getpeername (SOCKET sock, struct sockaddr *name, socklen_t *namelen) +{ + g_assert(0 && "This function is not yet implemented for the Unity platform."); + return 0; +} + +gint +mono_w32socket_getsockname (SOCKET sock, struct sockaddr *name, socklen_t *namelen) +{ + g_assert(0 && "This function is not yet implemented for the Unity platform."); + return 0; +} + +gint +mono_w32socket_getsockopt (SOCKET sock, gint level, gint optname, gpointer optval, socklen_t *optlen) +{ + g_assert(0 && "This function is not yet implemented for the Unity platform."); + return 0; +} + +gint +mono_w32socket_setsockopt (SOCKET sock, gint level, gint optname, const gpointer optval, socklen_t optlen) +{ + g_assert(0 && "This function is not yet implemented for the Unity platform."); + return 0; +} + +gint +mono_w32socket_listen (SOCKET sock, gint backlog) +{ + g_assert(0 && "This function is not yet implemented for the Unity platform."); + return 0; +} + +gint +mono_w32socket_shutdown (SOCKET sock, gint how) +{ + g_assert(0 && "This function is not yet implemented for the Unity platform."); + return 0; +} + +SOCKET +mono_w32socket_socket (int domain, int type, int protocol) +{ + g_assert(0 && "This function is not yet implemented for the Unity platform."); + return INVALID_SOCKET; +} + +gboolean +mono_w32socket_close (SOCKET sock) +{ + g_assert(0 && "This function is not yet implemented for the Unity platform."); + return FALSE; +} + +#endif /* PLATFORM_UNITY && UNITY_USE_PLATFORM_STUBS */ diff --git a/mono/metadata/w32socket-win32.c b/mono/metadata/w32socket-win32.c index 076500687bae..ff89617d270d 100644 --- a/mono/metadata/w32socket-win32.c +++ b/mono/metadata/w32socket-win32.c @@ -136,7 +136,6 @@ static gboolean alertable_socket_wait (SOCKET sock, int event_bit) SOCKET mono_w32socket_accept (SOCKET s, struct sockaddr *addr, socklen_t *addrlen, gboolean blocking) { - MonoInternalThread *curthread = mono_thread_internal_current (); SOCKET newsock = INVALID_SOCKET; MONO_ENTER_GC_SAFE; ALERTABLE_SOCKET_CALL (FD_ACCEPT_BIT, blocking, TRUE, newsock, accept, s, addr, addrlen); @@ -186,7 +185,7 @@ int mono_w32socket_send (SOCKET s, char *buf, int len, int flags, gboolean block { int ret = SOCKET_ERROR; MONO_ENTER_GC_SAFE; - ALERTABLE_SOCKET_CALL (FD_WRITE_BIT, blocking, FALSE, ret, send, s, buf, len, flags); + ALERTABLE_SOCKET_CALL (FD_WRITE_BIT, blocking, TRUE, ret, send, s, buf, len, flags); MONO_EXIT_GC_SAFE; return ret; } @@ -195,7 +194,7 @@ int mono_w32socket_sendto (SOCKET s, const char *buf, int len, int flags, const { int ret = SOCKET_ERROR; MONO_ENTER_GC_SAFE; - ALERTABLE_SOCKET_CALL (FD_WRITE_BIT, blocking, FALSE, ret, sendto, s, buf, len, flags, to, tolen); + ALERTABLE_SOCKET_CALL (FD_WRITE_BIT, blocking, TRUE, ret, sendto, s, buf, len, flags, to, tolen); MONO_EXIT_GC_SAFE; return ret; } @@ -204,7 +203,7 @@ int mono_w32socket_sendbuffers (SOCKET s, WSABUF *lpBuffers, guint32 dwBufferCou { int ret = SOCKET_ERROR; MONO_ENTER_GC_SAFE; - ALERTABLE_SOCKET_CALL (FD_WRITE_BIT, blocking, FALSE, ret, WSASend, s, lpBuffers, dwBufferCount, lpNumberOfBytesRecvd, lpFlags, lpOverlapped, lpCompletionRoutine); + ALERTABLE_SOCKET_CALL (FD_WRITE_BIT, blocking, TRUE, ret, WSASend, s, lpBuffers, dwBufferCount, lpNumberOfBytesRecvd, lpFlags, lpOverlapped, lpCompletionRoutine); MONO_EXIT_GC_SAFE; return ret; } @@ -331,8 +330,10 @@ gint mono_w32socket_get_available (SOCKET sock, guint64 *amount) { gint ret; + u_long amount_long = 0; MONO_ENTER_GC_SAFE; - ret = ioctlsocket (sock, FIONREAD, (int*) amount); + ret = ioctlsocket (sock, FIONREAD, &amount_long); + *amount = amount_long; MONO_EXIT_GC_SAFE; return ret; } diff --git a/mono/metadata/w32socket.c b/mono/metadata/w32socket.c index 8fab506185d0..4e9121f0edf9 100644 --- a/mono/metadata/w32socket.c +++ b/mono/metadata/w32socket.c @@ -2466,6 +2466,12 @@ ves_icall_System_Net_Sockets_Socket_IOControl_internal (gsize sock, gint32 code, return (gint)output_bytes; } +MonoBoolean +ves_icall_System_Net_Sockets_Socket_IsProtocolSupported_internal (gint32 networkInterface) +{ + return TRUE; +} + static gboolean addrinfo_add_string (MonoDomain *domain, const char *s, MonoArrayHandle arr, int index, MonoError *error) { diff --git a/mono/metadata/w32socket.h b/mono/metadata/w32socket.h index b03ac936738b..4208591c41fc 100644 --- a/mono/metadata/w32socket.h +++ b/mono/metadata/w32socket.h @@ -265,6 +265,9 @@ ves_icall_System_Net_Dns_GetHostByName_internal (MonoStringHandle host, MonoStri MonoArrayHandleOut h_aliases, MonoArrayHandleOut h_addr_list, gint32 hint, MonoError *error); +MonoBoolean +ves_icall_System_Net_Sockets_Socket_IsProtocolSupported_internal (gint32 networkInterface); + MonoBoolean ves_icall_System_Net_Dns_GetHostByAddr_internal (MonoStringHandle addr, MonoStringHandleOut h_name, MonoArrayHandleOut h_aliases, MonoArrayHandleOut h_addr_list, diff --git a/mono/mini/.gitignore b/mono/mini/.gitignore index af434f4218a0..0fb8914a9923 100644 --- a/mono/mini/.gitignore +++ b/mono/mini/.gitignore @@ -31,6 +31,7 @@ /TAGS /mono-sgen /mono-boehm +/mono-bdwgc /buildver-sgen.h /buildver-boehm.h /regressiontests.out diff --git a/mono/mini/Makefile.am.in b/mono/mini/Makefile.am.in index 498fd7029c0d..a2b7cbd30227 100755 --- a/mono/mini/Makefile.am.in +++ b/mono/mini/Makefile.am.in @@ -18,12 +18,21 @@ libgc_libs=$(monodir)/libgc/libmonogc.la libgc_static_libs=$(monodir)/libgc/libmonogc-static.la endif +libbdwgc_libs=$(monodir)/external/bdwgc/libgc.la +libbdwgc_static_libs=$(monodir)/external/bdwgc/libgc-static.la + boehm_libs= \ $(monodir)/mono/metadata/libmonoruntime.la \ $(monodir)/mono/utils/libmonoutils.la \ $(GLIB_LIBS) $(LIBICONV) \ $(libgc_libs) +bdwgc_libs= \ + $(monodir)/mono/metadata/libmonoruntimebdwgc.la \ + $(monodir)/mono/utils/libmonoutils.la \ + $(GLIB_LIBS) $(LIBICONV) \ + $(libbdwgc_libs) + sgen_libs = \ $(monodir)/mono/metadata/libmonoruntimesgen.la \ $(monodir)/mono/sgen/libmonosgen.la \ @@ -36,6 +45,12 @@ boehm_static_libs= \ $(GLIB_LIBS) $(LIBICONV) \ $(libgc_static_libs) +bdwgc_static_libs= \ + $(monodir)/mono/metadata/libmonoruntimebdwgc-static.la \ + $(monodir)/mono/utils/libmonoutils.la \ + $(GLIB_LIBS) $(LIBICONV) \ + $(libbdwgc_static_libs) + sgen_static_libs = \ $(monodir)/mono/metadata/libmonoruntimesgen-static.la \ $(monodir)/mono/sgen/libmonosgen-static.la \ @@ -102,15 +117,28 @@ boehm_libraries = libmonoboehm-2.0.la boehm_static_libraries = libmini-static.la $(boehm_static_libs) boehm_binaries = mono-boehm endif + +if SUPPORT_BDWGC +bdwgc_libraries = libmonobdwgc-2.0.la +bdwgc_static_libraries = libmini-static.la $(bdwgc_static_libs) +bdwgc_binaries = mono-bdwgc +endif if SUPPORT_SGEN mono_bin_suffix = sgen libmono_suffix = sgen -else +endif + +if SUPPORT_BOEHM mono_bin_suffix = boehm libmono_suffix = boehm endif +if SUPPORT_BDWGC +mono_bin_suffix = bdwgc +libmono_suffix = bdwgc +endif + if DISABLE_EXECUTABLES else mono: mono-$(mono_bin_suffix) @@ -127,9 +155,9 @@ endif if DISABLE_EXECUTABLES else if HOST_WIN32 -bin_PROGRAMS = $(boehm_binaries) $(sgen_binaries) monow +bin_PROGRAMS = $(boehm_binaries) $(bdwgc_binaries) $(sgen_binaries) monow else -bin_PROGRAMS = $(boehm_binaries) $(sgen_binaries) +bin_PROGRAMS = $(boehm_binaries) $(bdwgc_binaries) $(sgen_binaries) endif endif @@ -140,10 +168,10 @@ noinst_PROGRAMS = mono endif if DISABLE_EXECUTABLES -shared_libraries = $(boehm_libraries) $(sgen_libraries) +shared_libraries = $(boehm_libraries) $(bdwgc_libraries) $(sgen_libraries) else if SHARED_MONO -shared_libraries = $(boehm_libraries) $(sgen_libraries) +shared_libraries = $(boehm_libraries) $(bdwgc_libraries) $(sgen_libraries) endif endif @@ -179,6 +207,11 @@ mono_CFLAGS = $(AM_CFLAGS) mono_boehm_CFLAGS = $(AM_CFLAGS) +mono_bdwgc_SOURCES = \ + main.c + +mono_bdwgc_CFLAGS = $(AM_CFLAGS) + AM_CPPFLAGS = $(LIBGC_CPPFLAGS) mono_sgen_SOURCES = \ @@ -201,6 +234,16 @@ endif mono_boehm-main.$(OBJEXT): buildver-boehm.h endif +if SUPPORT_BDWGC +if DISABLE_EXECUTABLES +buildver-boehm.h: libmini-static.la $(monodir)/mono/metadata/libmonoruntimebdwgc.la +else +buildver-boehm.h: libmini-static.la $(monodir)/mono/metadata/libmonoruntimebdwgc-static.la +endif + @echo "const char *build_date = \"`date`\";" > buildver-boehm.h +mono_bdwgc-main.$(OBJEXT): buildver-boehm.h +endif + if DISABLE_EXECUTABLES buildver-sgen.h: libmini-static.la $(monodir)/mono/metadata/libmonoruntimesgen.la $(monodir)/mono/sgen/libmonosgen.la else @@ -227,9 +270,11 @@ if STATIC_MONO # This leads to higher performance, especially with TLS MONO_LIB=$(boehm_static_libraries) MONO_SGEN_LIB=$(sgen_static_libraries) +MONO_BDWGC_LIB=$(bdwgc_static_libraries) else MONO_LIB=libmonoboehm-2.0.la MONO_SGEN_LIB=libmonosgen-2.0.la +MONO_BDWGC_LIB=libmonobdwgc-2.0.la endif if LOADED_LLVM @@ -249,6 +294,17 @@ mono_boehm_LDADD = \ mono_boehm_LDFLAGS = \ $(static_flags) -export-dynamic $(monobinldflags) $(monobin_platform_ldflags) +mono_bdwgc_LDADD = \ + $(MONO_BDWGC_LIB) \ + $(GLIB_LIBS) \ + $(LLVMMONOF) \ + $(LIBICONV) \ + -lm \ + $(MONO_DTRACE_OBJECT) + +mono_bdwgc_LDFLAGS = \ + $(static_flags) -export-dynamic $(monobinldflags) $(monobin_platform_ldflags) + mono_sgen_LDADD = \ $(MONO_SGEN_LIB) \ $(GLIB_LIBS) \ @@ -289,13 +345,23 @@ if SUPPORT_BOEHM monow_LDADD = $(mono_boehm_LDADD) monow_LDFLAGS = $(mono_boehm_LDFLAGS) -mwindows monow_SOURCES = $(mono_boehm_SOURCES) -else +endif +if SUPPORT_BDWGC +monow_LDADD = $(mono_bdwgc_LDADD) +monow_LDFLAGS = $(mono_bdwgc_LDFLAGS) -mwindows +monow_SOURCES = $(mono_bdwgc_SOURCES) +endif +if SUPPORT_SGEN monow_LDADD = $(mono_sgen_LDADD) monow_LDFLAGS = $(mono_sgen_LDFLAGS) -mwindows monow_SOURCES = $(mono_sgen_SOURCES) endif endif + +unity_sources = \ + mini-unity.c + wasm_sources = \ mini-wasm.c \ mini-wasm.h \ @@ -480,6 +546,8 @@ common_sources = \ type-checking.c \ lldb.h \ lldb.c \ + mixed_callstack_plugin.h \ + mixed_callstack_plugin.c \ memory-access.c \ mini-profiler.c \ interp-stubs.c \ @@ -636,7 +704,7 @@ os_sources = $(darwin_sources) $(posix_sources) monobin_platform_ldflags=-framework CoreFoundation -framework Foundation endif -libmini_la_SOURCES = $(common_sources) $(llvm_sources) $(llvm_runtime_sources) $(interp_sources) $(arch_sources) $(os_sources) +libmini_la_SOURCES = $(common_sources) $(llvm_sources) $(llvm_runtime_sources) $(interp_sources) $(arch_sources) $(os_sources) $(unity_sources) libmini_la_CFLAGS = $(mono_CFLAGS) libmonoboehm_2_0_la_SOURCES = @@ -644,6 +712,11 @@ libmonoboehm_2_0_la_CFLAGS = $(mono_boehm_CFLAGS) libmonoboehm_2_0_la_LIBADD = libmini.la $(boehm_libs) $(LIBMONO_DTRACE_OBJECT) $(LLVMMONOF) libmonoboehm_2_0_la_LDFLAGS = $(libmonoldflags) $(monobin_platform_ldflags) +libmonobdwgc_2_0_la_SOURCES = +libmonobdwgc_2_0_la_CFLAGS = $(mono_bdwgc_CFLAGS) +libmonobdwgc_2_0_la_LIBADD = libmini.la $(bdwgc_libs) $(LIBMONO_DTRACE_OBJECT) $(LLVMMONOF) +libmonobdwgc_2_0_la_LDFLAGS = $(libmonoldflags) $(monobin_platform_ldflags) + libmonosgen_2_0_la_SOURCES = libmonosgen_2_0_la_CFLAGS = $(mono_sgen_CFLAGS) libmonosgen_2_0_la_LIBADD = libmini.la $(sgen_libs) $(LIBMONO_DTRACE_OBJECT) $(LLVMMONOF) diff --git a/mono/mini/debugger-agent.c b/mono/mini/debugger-agent.c index 8b7ea714ee87..5212b713c247 100644 --- a/mono/mini/debugger-agent.c +++ b/mono/mini/debugger-agent.c @@ -53,9 +53,12 @@ #include #endif +#ifndef RUNTIME_IL2CPP #include #include +#endif #include +#ifndef RUNTIME_IL2CPP #include #include #include @@ -63,7 +66,9 @@ #include #include #include +#endif #include +#include #include #include #include @@ -73,12 +78,21 @@ #include #include #include -#include "debugger-agent.h" + +#ifndef RUNTIME_IL2CPP #include "mini.h" #include "seq-points.h" #include "aot-runtime.h" #include "mini-runtime.h" #include "interp/interp.h" +#endif + +#ifdef RUNTIME_IL2CPP +#include +#include +#include +#define MONO_ARCH_SOFT_DEBUG_SUPPORTED +#endif /* * On iOS we can't use System.Environment.Exit () as it will do the wrong @@ -101,7 +115,14 @@ #include -#define THREAD_TO_INTERNAL(thread) (thread)->internal_thread +#define THREAD_TO_INTERNAL(thread) thread->internal_thread + +#include "debugger-agent.h" + +#ifdef RUNTIME_IL2CPP +const Il2CppDebuggerMetadataRegistration *g_il2cpp_metadata; +#endif + typedef struct { gboolean enabled; @@ -138,7 +159,9 @@ typedef struct */ MonoMethod *api_method; MonoContext ctx; +#ifndef RUNTIME_IL2CPP MonoDebugMethodJitInfo *jit; +#endif MonoJitInfo *ji; MonoInterpFrameHandle interp_frame; int flags; @@ -175,6 +198,10 @@ struct _InvokeData typedef struct { MonoThreadUnwindState context; +#ifdef RUNTIME_IL2CPP + Il2CppThreadUnwindState il2cpp_context; +#endif + /* This is computed on demand when it is requested using the wire protocol */ /* It is freed up when the thread is resumed */ int frame_count; @@ -207,6 +234,8 @@ typedef struct { MonoContext handler_ctx; /* Whenever thread_stop () was called for this thread */ gboolean terminated; + /* If thread should be suspended and processed. FALSE if fast detach has been called */ + gboolean attached; /* Whenever to disable breakpoints (used during invokes) */ gboolean disable_breakpoints; @@ -242,6 +271,9 @@ typedef struct { InvokeData *invoke; StackFrameInfo catch_frame; +#ifdef RUNTIME_IL2CPP + MonoException *exception; +#endif gboolean has_catch_frame; /* @@ -274,7 +306,7 @@ typedef struct { #define HEADER_LENGTH 11 #define MAJOR_VERSION 2 -#define MINOR_VERSION 45 +#define MINOR_VERSION 46 typedef enum { CMD_SET_VM = 1, @@ -290,7 +322,8 @@ typedef enum { CMD_SET_TYPE = 23, CMD_SET_MODULE = 24, CMD_SET_FIELD = 25, - CMD_SET_EVENT = 64 + CMD_SET_EVENT = 64, + CMD_SET_POINTER = 65 } CommandSet; typedef enum { @@ -495,7 +528,8 @@ typedef enum { CMD_TYPE_GET_INTERFACES = 16, CMD_TYPE_GET_INTERFACE_MAP = 17, CMD_TYPE_IS_INITIALIZED = 18, - CMD_TYPE_CREATE_INSTANCE = 19 + CMD_TYPE_CREATE_INSTANCE = 19, + CMD_TYPE_GET_VALUE_SIZE = 20 } CmdType; typedef enum { @@ -518,6 +552,10 @@ typedef enum { CMD_STRING_REF_GET_CHARS = 3 } CmdString; +typedef enum { + CMD_POINTER_GET_VALUE = 1 +} CmdPointer; + typedef enum { CMD_OBJECT_REF_GET_TYPE = 1, CMD_OBJECT_REF_GET_VALUES = 2, @@ -592,7 +630,7 @@ typedef struct { char *category, *message; /* For EVENT_KIND_TYPE_LOAD */ MonoClass *klass; -} EventInfo; +} DebuggerEventInfo; typedef struct { guint8 *buf, *p, *end; @@ -604,8 +642,6 @@ typedef struct ReplyPacket { Buffer *data; } ReplyPacket; -#define DEBUG(level,s) do { if (G_UNLIKELY ((level) <= log_level)) { s; fflush (log_file); } } while (0) - #ifdef HOST_ANDROID #define DEBUG_PRINTF(level, ...) do { if (G_UNLIKELY ((level) <= log_level)) { g_print (__VA_ARGS__); } } while (0) #else @@ -755,7 +791,9 @@ static void invalidate_each_thread (gpointer key, gpointer value, gpointer user_ static void assembly_load (MonoProfiler *prof, MonoAssembly *assembly); +#ifndef RUNTIME_IL2CPP static void assembly_unload (MonoProfiler *prof, MonoAssembly *assembly); +#endif static void emit_assembly_load (gpointer assembly, gpointer user_data); @@ -795,8 +833,14 @@ static void ids_cleanup (void); static void suspend_init (void); +#ifndef RUNTIME_IL2CPP static void ss_start (SingleStepReq *ss_req, MonoMethod *method, SeqPoint *sp, MonoSeqPointInfo *info, MonoContext *ctx, DebuggerTlsData *tls, gboolean step_to_catch, StackFrame **frames, int nframes); +#else +static Il2CppSequencePoint* il2cpp_find_catch_sequence_point(DebuggerTlsData *tls); +static void ss_start_il2cpp(SingleStepReq *ss_req, DebuggerTlsData *tls, Il2CppSequencePoint *catchFrameSp); +static void GetSequencePointsAndSourceFilesUniqueSequencePoints(MonoMethod* method, GPtrArray** sequencePoints, GPtrArray** uniqueFileSequencePoints, GArray** uniqueFileSequencePointIndices); +#endif //RUNTIME_IL2CPP static ErrorCode ss_create (MonoInternalThread *thread, StepSize size, StepDepth depth, StepFilter filter, EventRequest *req); static void ss_destroy (SingleStepReq *req); @@ -814,6 +858,25 @@ static void register_socket_transport (void); #endif +#ifndef RUNTIME_IL2CPP +static MonoAssembly* mono_domain_get_assemblies_iter(MonoDomain *domain, void* *iter) +{ + if (!iter) + return NULL; + + if (*iter) + *iter = ((GList*)(*iter))->next; + else + *iter = domain->domain_assemblies; + + + if (*iter) + return ((GList*)(*iter))->data; + else + return NULL; +} +#endif + static inline gboolean is_debugger_thread (void) { @@ -823,7 +886,11 @@ is_debugger_thread (void) if (!internal) return FALSE; +#ifndef RUNTIME_IL2CPP return internal->debugger_thread; +#else + return debugger_thread_id == mono_native_thread_id_get (); +#endif } static int @@ -1000,7 +1067,9 @@ mono_debugger_agent_init (void) mono_profiler_set_thread_started_callback (prof, thread_startup); mono_profiler_set_thread_stopped_callback (prof, thread_end); mono_profiler_set_assembly_loaded_callback (prof, assembly_load); +#ifndef RUNTIME_IL2CPP mono_profiler_set_assembly_unloading_callback (prof, assembly_unload); +#endif mono_profiler_set_jit_done_callback (prof, jit_done); mono_profiler_set_jit_failed_callback (prof, jit_failed); @@ -1038,6 +1107,7 @@ mono_debugger_agent_init (void) breakpoints_init (); suspend_init (); +#ifndef RUNTIME_IL2CPP mini_get_debug_options ()->gen_sdb_seq_points = TRUE; /* * This is needed because currently we don't handle liveness info. @@ -1056,6 +1126,7 @@ mono_debugger_agent_init (void) * workaround. */ mini_get_debug_options ()->load_aot_jit_info_eagerly = TRUE; +#endif // !RUNTIME_IL2CPP #ifdef HAVE_SETPGID if (agent_config.setpgid) @@ -1066,6 +1137,26 @@ mono_debugger_agent_init (void) finish_agent_init (TRUE); } +#ifdef RUNTIME_IL2CPP +void +mono_debugger_run_debugger_thread_func(void* arg) +{ + debugger_thread(arg); +} + +typedef struct { + void(*il2cpp_debugger_save_thread_context)(Il2CppThreadUnwindState* context); +} MonoDebuggerRuntimeCallbacks; + +static MonoDebuggerRuntimeCallbacks callbacks; + +void mono_debugger_install_runtime_callbacks(MonoDebuggerRuntimeCallbacks* cbs) +{ + callbacks = *cbs; +} + +#endif // RUNTIME_IL2CPP + /* * finish_agent_init: * @@ -1193,7 +1284,13 @@ static int socket_transport_accept (int socket_fd) { MONO_ENTER_GC_SAFE; +#if defined(HOST_WIN32) && !defined(RUNTIME_IL2CPP) + conn_fd = mono_w32socket_accept (socket_fd, NULL, NULL, TRUE); + if (conn_fd != -1) + mono_w32socket_set_blocking (conn_fd, TRUE); +#else conn_fd = accept (socket_fd, NULL, NULL); +#endif MONO_EXIT_GC_SAFE; if (conn_fd == -1) { @@ -1372,7 +1469,11 @@ socket_transport_connect (const char *address) break; /* Success */ MONO_ENTER_GC_SAFE; +#ifdef HOST_WIN32 + closesocket (sfd); +#else close (sfd); +#endif MONO_EXIT_GC_SAFE; } @@ -1397,6 +1498,9 @@ socket_transport_close1 (void) /* Close the read part only so it can still send back replies */ /* Also shut down the connection listener so that we can exit normally */ #ifdef HOST_WIN32 + MonoThreadInfo* info = mono_thread_info_lookup (debugger_thread_id); + if (info) + mono_threads_suspend_abort_syscall (info); /* SD_RECEIVE doesn't break the recv in the debugger thread */ shutdown (conn_fd, SD_BOTH); shutdown (listen_fd, SD_BOTH); @@ -1648,12 +1752,15 @@ start_debugger_thread (void) { MonoError error; MonoInternalThread *thread; - +#ifdef RUNTIME_IL2CPP + il2cpp_start_debugger_thread (); +#else thread = mono_thread_create_internal (mono_get_root_domain (), debugger_thread, NULL, MONO_THREAD_CREATE_FLAGS_DEBUGGER, &error); mono_error_assert_ok (&error); debugger_thread_handle = mono_threads_open_thread_handle (thread->handle); g_assert (debugger_thread_handle); +#endif // RUNTIME_IL2CPP; } /* @@ -2170,6 +2277,38 @@ typedef struct { /* Protected by the dbg lock */ static GPtrArray *ids [ID_NUM]; +#ifdef RUNTIME_IL2CPP + +static GHashTable* s_jit_info_hashtable; + +void mono_debugger_il2cpp_init (const Il2CppDebuggerMetadataRegistration *data) +{ + s_jit_info_hashtable = g_hash_table_new_full(mono_aligned_addr_hash, NULL, NULL, NULL); + g_il2cpp_metadata = data; + debug_options.native_debugger_break = FALSE; +} + +static gpointer +unity_mono_jit_find_compiled_method_with_jit_info(MonoDomain *domain, MonoMethod *method, MonoJitInfo **ji) +{ + MonoJitInfo* ji2; + + g_assert(mono_get_root_domain() == domain); + + ji2 = g_hash_table_lookup(s_jit_info_hashtable, method); + + if (!ji2) + { + *ji = NULL; + return NULL; + } + + *ji = ji2; + return ji2->code_start; +} + +#endif // RUNTIME_IL2CPP + static void ids_init (void) { @@ -2197,7 +2336,7 @@ ids_cleanup (void) void mono_debugger_agent_free_domain_info (MonoDomain *domain) { - AgentDomainInfo *info = (AgentDomainInfo *)domain_jit_info (domain)->agent_info; + AgentDomainInfo *info = (AgentDomainInfo *)VM_DOMAIN_GET_AGENT_INFO(domain); int i, j; GHashTableIter iter; GPtrArray *file_names; @@ -2232,7 +2371,7 @@ mono_debugger_agent_free_domain_info (MonoDomain *domain) g_free (info); } - domain_jit_info (domain)->agent_info = NULL; + VM_DOMAIN_SET_AGENT_INFO(domain, NULL); /* Clear ids referencing structures in the domain */ dbg_lock (); @@ -2259,10 +2398,10 @@ get_agent_domain_info (MonoDomain *domain) mono_domain_lock (domain); - info = (AgentDomainInfo *)domain_jit_info (domain)->agent_info; + info = (AgentDomainInfo *)VM_DOMAIN_GET_AGENT_INFO(domain); if (!info) { info = g_new0 (AgentDomainInfo, 1); - domain_jit_info (domain)->agent_info = info; + VM_DOMAIN_SET_AGENT_INFO(domain, info); info->loaded_classes = g_hash_table_new (mono_aligned_addr_hash, NULL); info->source_files = g_hash_table_new (mono_aligned_addr_hash, NULL); info->source_file_to_class = g_hash_table_new (g_str_hash, g_str_equal); @@ -2331,11 +2470,13 @@ decode_ptr_id (guint8 *buf, guint8 **endbuf, guint8 *limit, IdType type, MonoDom res = (Id *)g_ptr_array_index (ids [type], GPOINTER_TO_INT (id - 1)); dbg_unlock (); +#ifndef RUNTIME_IL2CPP if (res->domain == NULL || res->domain->state == MONO_APPDOMAIN_UNLOADED) { DEBUG_PRINTF (1, "ERR_UNLOADED, id=%d, type=%d.\n", id, type); *err = ERR_UNLOADED; return NULL; } +#endif if (domain) *domain = res->domain; @@ -2361,7 +2502,7 @@ decode_typeid (guint8 *buf, guint8 **endbuf, guint8 *limit, MonoDomain **domain, if (G_UNLIKELY (log_level >= 2) && klass) { char *s; - s = mono_type_full_name (&klass->byval_arg); + s = mono_type_full_name (mono_class_get_type(klass)); DEBUG_PRINTF (2, "[dbg] recv class [%s]\n", s); g_free (s); } @@ -2421,7 +2562,7 @@ buffer_add_typeid (Buffer *buf, MonoDomain *domain, MonoClass *klass) if (G_UNLIKELY (log_level >= 2) && klass) { char *s; - s = mono_type_full_name (&klass->byval_arg); + s = mono_type_full_name (mono_class_get_type(klass)); if (is_debugger_thread ()) DEBUG_PRINTF (2, "[dbg] send class [%s]\n", s); else @@ -2449,8 +2590,9 @@ buffer_add_assemblyid (Buffer *buf, MonoDomain *domain, MonoAssembly *assembly) int id; id = buffer_add_ptr_id (buf, domain, ID_ASSEMBLY, assembly); - if (G_UNLIKELY (log_level >= 2) && assembly) + if (G_UNLIKELY (log_level >= 2) && assembly) { DEBUG_PRINTF (2, "[dbg] send assembly [%s][%s][%d]\n", assembly->aname.name, domain->friendly_name, id); + } } static inline void @@ -2482,7 +2624,7 @@ static void invoke_method (void); /* * SUSPEND/RESUME */ - +#ifndef RUNTIME_IL2CPP static MonoJitInfo* get_top_method_ji (gpointer ip, MonoDomain **domain, gpointer *out_ip) { @@ -2511,6 +2653,7 @@ get_top_method_ji (gpointer ip, MonoDomain **domain, gpointer *out_ip) } return ji; } +#endif /* * save_thread_context: @@ -2526,10 +2669,14 @@ save_thread_context (MonoContext *ctx) tls = (DebuggerTlsData *)mono_native_tls_get_value (debugger_tls_id); g_assert (tls); +#ifndef RUNTIME_IL2CPP if (ctx) mono_thread_state_init_from_monoctx (&tls->context, ctx); else mono_thread_state_init_from_current (&tls->context); +#else + callbacks.il2cpp_debugger_save_thread_context(&tls->il2cpp_context); +#endif // !RUNTIME_IL2CPP } /* Number of threads suspended */ @@ -2596,7 +2743,7 @@ copy_unwind_state_from_frame_data (MonoThreadUnwindState *to, GetLastFrameUserDa to->unwind_data [MONO_UNWIND_DATA_JIT_TLS] = jit_tls; to->valid = TRUE; } - +#ifndef RUNTIME_IL2CPP /* * thread_interrupt: * @@ -2681,6 +2828,7 @@ thread_interrupt (DebuggerTlsData *tls, MonoThreadInfo *info, MonoJitInfo *ji) } } } +#endif /* * reset_native_thread_suspend_state: @@ -2716,6 +2864,12 @@ debugger_interrupt_critical (MonoThreadInfo *info, gpointer user_data) MonoJitInfo *ji; data->valid_info = TRUE; +#ifdef RUNTIME_IL2CPP + if (!data->tls->suspended && !data->tls->suspending) { + data->tls->suspended = TRUE; + mono_coop_sem_post(&suspend_sem); + } +#else ji = mono_jit_info_table_find_internal ( (MonoDomain *)mono_thread_info_get_suspend_state (info)->unwind_data [MONO_UNWIND_DATA_DOMAIN], (char *)MONO_CONTEXT_GET_IP (&mono_thread_info_get_suspend_state (info)->ctx), @@ -2724,6 +2878,7 @@ debugger_interrupt_critical (MonoThreadInfo *info, gpointer user_data) /* This is signal safe */ thread_interrupt (data->tls, info, ji); +#endif // RUNTIME_IL2CPP return MonoResumeThread; } @@ -2761,9 +2916,11 @@ notify_thread (gpointer key, gpointer value, gpointer user_data) static void process_suspend (DebuggerTlsData *tls, MonoContext *ctx) { +#ifndef RUNTIME_IL2CPP guint8 *ip = (guint8 *)MONO_CONTEXT_GET_IP (ctx); MonoJitInfo *ji; MonoMethod *method; +#endif if (mono_loader_lock_is_owned_by_self ()) { /* @@ -2793,12 +2950,14 @@ process_suspend (DebuggerTlsData *tls, MonoContext *ctx) return; } +#ifndef RUNTIME_IL2CPP ji = get_top_method_ji (ip, NULL, NULL); g_assert (ji); /* Can't suspend in these methods */ method = jinfo_get_method (ji); - if (method->klass == mono_defaults.string_class && (!strcmp (method->name, "memset") || strstr (method->name, "memcpy"))) + if (method->klass == mono_defaults.string_class && (!strcmp (mono_method_get_name(method), "memset") || strstr (mono_method_get_name(method), "memcpy"))) return; +#endif save_thread_context (ctx); @@ -2920,8 +3079,10 @@ free_frames (StackFrame **frames, int nframes) int i; for (i = 0; i < nframes; ++i) { +#ifndef RUNTIME_IL2CPP if (frames [i]->jit) mono_debug_free_method_jit_info (frames [i]->jit); +#endif g_free (frames [i]); } g_free (frames); @@ -3213,7 +3374,7 @@ compute_frame_info (MonoInternalThread *thread, DebuggerTlsData *tls) { ComputeFramesUserData user_data; GSList *tmp; - int i, findex, new_frame_count; + int i=0, findex, new_frame_count; StackFrame **new_frames, *f; MonoUnwindOptions opts = (MonoUnwindOptions)(MONO_UNWIND_DEFAULT | MONO_UNWIND_REG_LOCATIONS); @@ -3221,7 +3382,7 @@ compute_frame_info (MonoInternalThread *thread, DebuggerTlsData *tls) if (tls->frames && tls->frames_up_to_date) return; - DEBUG_PRINTF (1, "Frames for %p(tid=%lx):\n", thread, (glong)thread->tid); + DEBUG_PRINTF (1, "Frames for %p(tid=%lx):\n", thread, thread->tid); user_data.tls = tls; user_data.frames = NULL; @@ -3229,10 +3390,17 @@ compute_frame_info (MonoInternalThread *thread, DebuggerTlsData *tls) tls->frame_count = 0; return; } if (!tls->really_suspended && tls->async_state.valid) { +#ifdef RUNTIME_IL2CPP + NOT_IMPLEMENTED; +#else /* Have to use the state saved by the signal handler */ process_frame (&tls->async_last_frame, NULL, &user_data); mono_walk_stack_with_state (process_frame, &tls->async_state, opts, &user_data); +#endif // RUNTIME_IL2CPP } else if (tls->filter_state.valid) { +#ifdef RUNTIME_IL2CPP + NOT_IMPLEMENTED; +#else /* * We are inside an exception filter. * @@ -3246,8 +3414,33 @@ compute_frame_info (MonoInternalThread *thread, DebuggerTlsData *tls) * After that, we resume unwinding from the location where the exception has been thrown. */ mono_walk_stack_with_state (process_frame, &tls->filter_state, opts, &user_data); +#endif // RUNTIME_IL2CPP } else if (tls->context.valid) { +#ifdef RUNTIME_IL2CPP + NOT_IMPLEMENTED; +#else mono_walk_stack_with_state (process_frame, &tls->context, opts, &user_data); +#endif // RUNTIME_IL2CPP +#ifdef RUNTIME_IL2CPP + } else if (tls->il2cpp_context.frameCount > 0) { + for (int frame_index = tls->il2cpp_context.frameCount - 1; frame_index >= 0; --frame_index) + { + Il2CppSequencePoint* seq_point = tls->il2cpp_context.sequencePoints[frame_index]; + StackFrame* frame = g_new0(StackFrame, 1); + MonoMethod *sp_method = il2cpp_get_seq_point_method(seq_point); + frame->method = sp_method; + frame->actual_method = sp_method; + frame->api_method = sp_method; + frame->il_offset = seq_point->ilOffset; + frame->native_offset = 0; + frame->flags = 0; + frame->ji = 0; + frame->domain = mono_domain_get(); + frame->has_ctx = 1; + + user_data.frames = g_slist_append(user_data.frames, frame); + } +#endif // RUNTIME_IL2CPP } else { // FIXME: tls->frame_count = 0; @@ -3265,10 +3458,12 @@ compute_frame_info (MonoInternalThread *thread, DebuggerTlsData *tls) * the still valid stack frames. */ for (i = 0; i < tls->frame_count; ++i) { +#ifndef RUNTIME_IL2CPP if (MONO_CONTEXT_GET_SP (&tls->frames [i]->ctx) == MONO_CONTEXT_GET_SP (&f->ctx)) { f->id = tls->frames [i]->id; break; } +#endif // !RUNTIME_IL2CPP } if (i >= tls->frame_count) @@ -3382,6 +3577,7 @@ dbg_path_get_basename (const char *filename) return g_strdup (&r[1]); } +#ifndef RUNTIME_IL2CPP static void init_jit_info_dbg_attrs (MonoJitInfo *ji) { @@ -3426,6 +3622,27 @@ init_jit_info_dbg_attrs (MonoJitInfo *ji) mono_memory_barrier (); ji->dbg_attrs_inited = TRUE; } +#endif //RUNTIME_IL2CPP + +static gboolean find_source_file_in_hash_table(const char* needle, GHashTable* haystack) +{ + gboolean found = FALSE; + char *s = strdup_tolower(needle); + if (g_hash_table_lookup(haystack, s)) { + found = TRUE; + } else { + char *s2 = dbg_path_get_basename(needle); + char *s3 = strdup_tolower(s2); + + if (g_hash_table_lookup(haystack, s3)) + found = TRUE; + g_free(s2); + g_free(s3); + } + g_free(s); + + return found; +} /* * EVENT HANDLING @@ -3442,10 +3659,14 @@ init_jit_info_dbg_attrs (MonoJitInfo *ji) * LOCKING: Assumes the loader lock is held. */ static GSList* -create_event_list (EventKind event, GPtrArray *reqs, MonoJitInfo *ji, EventInfo *ei, int *suspend_policy) +create_event_list (EventKind event, GPtrArray *reqs, MonoJitInfo *ji, DebuggerEventInfo *ei, int *suspend_policy) { int i, j; GSList *events = NULL; +#if RUNTIME_IL2CPP + Il2CppSequencePoint *sp = (Il2CppSequencePoint*)ji; + MonoMethod *sp_method = ji ? il2cpp_get_seq_point_method(sp) : NULL; +#endif *suspend_policy = SUSPEND_POLICY_NONE; @@ -3479,7 +3700,7 @@ create_event_list (EventKind event, GPtrArray *reqs, MonoJitInfo *ji, EventInfo } else if (mod->kind == MOD_KIND_EXCEPTION_ONLY && ei) { if (mod->data.exc_class && mod->subclasses && !mono_class_is_assignable_from (mod->data.exc_class, ei->exc->vtable->klass)) filtered = TRUE; - if (mod->data.exc_class && !mod->subclasses && mod->data.exc_class != ei->exc->vtable->klass) + if (mod->data.exc_class && !mod->subclasses && mod->data.exc_class != ei->exc->vtable->klass) filtered = TRUE; if (ei->caught && !mod->caught) filtered = TRUE; @@ -3492,20 +3713,44 @@ create_event_list (EventKind event, GPtrArray *reqs, MonoJitInfo *ji, EventInfo if (assemblies) { for (k = 0; assemblies [k]; ++k) +#ifdef RUNTIME_IL2CPP + { + if (assemblies[k] == sp_method->klass->image->assembly) + found = TRUE; + } +#else if (assemblies [k] == jinfo_get_method (ji)->klass->image->assembly) found = TRUE; +#endif } if (!found) filtered = TRUE; } else if (mod->kind == MOD_KIND_SOURCE_FILE_ONLY && ei && ei->klass) { gpointer iter = NULL; MonoMethod *method; +#ifndef RUNTIME_IL2CPP MonoDebugSourceInfo *sinfo; +#endif char *source_file, *s; gboolean found = FALSE; int i; GPtrArray *source_file_list; +#ifdef RUNTIME_IL2CPP + int fileCount; + const char **files; + + files = il2cpp_get_source_files_for_type(ei->klass, &fileCount); + for (int i = 0; i < fileCount; ++i) + { + char *s = strdup_tolower(files[i]); + + found = find_source_file_in_hash_table(s, mod->data.source_files); + g_free(s); + if (found) + break; + } +#else while ((method = mono_class_get_methods (ei->klass, &iter))) { MonoDebugMethodInfo *minfo = mono_debug_lookup_method (method); @@ -3513,27 +3758,14 @@ create_event_list (EventKind event, GPtrArray *reqs, MonoJitInfo *ji, EventInfo mono_debug_get_seq_points (minfo, &source_file, &source_file_list, NULL, NULL, NULL); for (i = 0; i < source_file_list->len; ++i) { sinfo = (MonoDebugSourceInfo *)g_ptr_array_index (source_file_list, i); - /* - * Do a case-insesitive match by converting the file name to - * lowercase. - */ - s = strdup_tolower (sinfo->source_file); - if (g_hash_table_lookup (mod->data.source_files, s)) - found = TRUE; - else { - char *s2 = dbg_path_get_basename (sinfo->source_file); - char *s3 = strdup_tolower (s2); - - if (g_hash_table_lookup (mod->data.source_files, s3)) - found = TRUE; - g_free (s2); - g_free (s3); - } - g_free (s); + found = find_source_file_in_hash_table(sinfo->source_file, mod->data.source_files); + if (found) + break; } g_ptr_array_free (source_file_list, TRUE); } } +#endif if (!found) filtered = TRUE; } else if (mod->kind == MOD_KIND_TYPE_NAME_ONLY && ei && ei->klass) { @@ -3544,6 +3776,13 @@ create_event_list (EventKind event, GPtrArray *reqs, MonoJitInfo *ji, EventInfo filtered = TRUE; g_free (s); } else if (mod->kind == MOD_KIND_STEP) { +#ifdef RUNTIME_IL2CPP + if ((mod->data.filter & STEP_FILTER_STATIC_CTOR) && sp && + (sp_method->flags & METHOD_ATTRIBUTE_SPECIAL_NAME) && + !strcmp (sp_method->name, ".cctor") && + (sp_method != ((SingleStepReq*)req->info)->start_method)) + filtered = TRUE; +#else if ((mod->data.filter & STEP_FILTER_STATIC_CTOR) && ji && (jinfo_get_method (ji)->flags & METHOD_ATTRIBUTE_SPECIAL_NAME) && !strcmp (jinfo_get_method (ji)->name, ".cctor") && @@ -3564,6 +3803,7 @@ create_event_list (EventKind event, GPtrArray *reqs, MonoJitInfo *ji, EventInfo if (ji->dbg_non_user_code) filtered = TRUE; } +#endif } } @@ -3619,7 +3859,11 @@ event_to_string (EventKind event) * The EVENTS list is freed by this function. */ static void +#ifndef RUNTIME_IL2CPP process_event (EventKind event, gpointer arg, gint32 il_offset, MonoContext *ctx, GSList *events, int suspend_policy) +#else +process_event (EventKind event, gpointer arg, gint32 il_offset, MonoContext *ctx, GSList *events, int suspend_policy, uint64_t il2cpp_seqpoint_id) +#endif { Buffer buf; GSList *l; @@ -3708,6 +3952,9 @@ process_event (EventKind event, gpointer arg, gint32 il_offset, MonoContext *ctx case EVENT_KIND_METHOD_ENTRY: case EVENT_KIND_METHOD_EXIT: buffer_add_methodid (&buf, domain, (MonoMethod *)arg); +#if defined(RUNTIME_IL2CPP) && defined(IL2CPP_DEBUGGER_TESTS) + buffer_add_long (&buf, il2cpp_seqpoint_id); +#endif break; case EVENT_KIND_ASSEMBLY_LOAD: buffer_add_assemblyid (&buf, domain, (MonoAssembly *)arg); @@ -3730,6 +3977,9 @@ process_event (EventKind event, gpointer arg, gint32 il_offset, MonoContext *ctx case EVENT_KIND_STEP: buffer_add_methodid (&buf, domain, (MonoMethod *)arg); buffer_add_long (&buf, il_offset); +#if defined(RUNTIME_IL2CPP) && defined(IL2CPP_DEBUGGER_TESTS) + buffer_add_long (&buf, il2cpp_seqpoint_id); +#endif break; case EVENT_KIND_VM_START: buffer_add_domainid (&buf, mono_get_root_domain ()); @@ -3739,8 +3989,11 @@ process_event (EventKind event, gpointer arg, gint32 il_offset, MonoContext *ctx buffer_add_int (&buf, mono_environment_exitcode_get ()); break; case EVENT_KIND_EXCEPTION: { - EventInfo *ei = (EventInfo *)arg; + DebuggerEventInfo *ei = (DebuggerEventInfo *)arg; buffer_add_objid (&buf, ei->exc); +#if defined(RUNTIME_IL2CPP) && defined(IL2CPP_DEBUGGER_TESTS) + buffer_add_long(&buf, il2cpp_seqpoint_id); +#endif /* * We are not yet suspending, so get_objref () will not keep this object alive. So we need to do it * later after the suspension. (#12494). @@ -3751,7 +4004,7 @@ process_event (EventKind event, gpointer arg, gint32 il_offset, MonoContext *ctx case EVENT_KIND_USER_BREAK: break; case EVENT_KIND_USER_LOG: { - EventInfo *ei = (EventInfo *)arg; + DebuggerEventInfo *ei = (DebuggerEventInfo *)arg; buffer_add_int (&buf, ei->level); buffer_add_string (&buf, ei->category ? ei->category : ""); buffer_add_string (&buf, ei->message ? ei->message : ""); @@ -3830,7 +4083,7 @@ process_profiler_event (EventKind event, gpointer arg) { int suspend_policy; GSList *events; - EventInfo ei, *ei_arg = NULL; + DebuggerEventInfo ei, *ei_arg = NULL; if (event == EVENT_KIND_TYPE_LOAD) { ei.klass = (MonoClass *)arg; @@ -3841,7 +4094,11 @@ process_profiler_event (EventKind event, gpointer arg) events = create_event_list (event, NULL, NULL, ei_arg, &suspend_policy); mono_loader_unlock (); +#ifndef RUNTIME_IL2CPP process_event (event, arg, 0, NULL, events, suspend_policy); +#else + process_event (event, arg, 0, NULL, events, suspend_policy, 0); +#endif } static void @@ -3898,9 +4155,22 @@ thread_startup (MonoProfiler *prof, uintptr_t tid) } tls = (DebuggerTlsData *)mono_native_tls_get_value (debugger_tls_id); - g_assert (!tls); - // FIXME: Free this somewhere + if (tls) { +#ifndef RUNTIME_IL2CPP + if (!tls->terminated) + MONO_GC_UNREGISTER_ROOT(tls->thread); +#endif +#ifdef RUNTIME_IL2CPP + il2cpp_gc_free_fixed (tls); +#else + g_free (tls); +#endif + } +#ifdef RUNTIME_IL2CPP + tls = il2cpp_gc_alloc_fixed(sizeof(DebuggerTlsData)); +#else tls = g_new0 (DebuggerTlsData, 1); +#endif MONO_GC_REGISTER_ROOT_SINGLE (tls->thread, MONO_ROOT_SOURCE_DEBUGGER, NULL, "Debugger Thread Reference"); tls->thread = thread; mono_native_tls_set_value (debugger_tls_id, tls); @@ -3932,11 +4202,13 @@ thread_end (MonoProfiler *prof, uintptr_t tid) if (thread) { mono_g_hash_table_remove (tid_to_thread_obj, GUINT_TO_POINTER (tid)); tls = (DebuggerTlsData *)mono_g_hash_table_lookup (thread_to_tls, thread); - if (tls) { + if (tls && !tls->terminated) { /* FIXME: Maybe we need to free this instead, but some code can't handle that */ tls->terminated = TRUE; /* Can't remove from tid_to_thread, as that would defeat the check in thread_start () */ +#ifndef RUNTIME_IL2CPP MONO_GC_UNREGISTER_ROOT (tls->thread); +#endif tls->thread = NULL; } } @@ -4030,6 +4302,7 @@ assembly_load (MonoProfiler *prof, MonoAssembly *assembly) dbg_unlock (); } +#ifndef RUNTIME_IL2CPP static void assembly_unload (MonoProfiler *prof, MonoAssembly *assembly) { @@ -4041,6 +4314,7 @@ assembly_unload (MonoProfiler *prof, MonoAssembly *assembly) clear_event_requests_for_assembly (assembly); clear_types_for_assembly (assembly); } +#endif static void send_type_load (MonoClass *klass) @@ -4100,10 +4374,12 @@ send_assemblies_for_domain (MonoDomain *domain, void *user_data) mono_domain_set (domain, TRUE); mono_domain_assemblies_lock (domain); - for (tmp = domain->domain_assemblies; tmp; tmp = tmp->next) { - MonoAssembly* ass = (MonoAssembly *)tmp->data; - emit_assembly_load (ass, NULL); - } + + void *iter = NULL; + MonoAssembly *ass; + while (ass = mono_domain_get_assemblies_iter(domain, &iter)) + emit_assembly_load(ass, NULL); + mono_domain_assemblies_unlock (domain); mono_domain_set (old_domain, TRUE); @@ -4124,6 +4400,13 @@ jit_failed (MonoProfiler *prof, MonoMethod *method) static void jit_end (MonoProfiler *prof, MonoMethod *method, MonoJitInfo *jinfo) { +#ifdef RUNTIME_IL2CPP + //if (!result) + { + g_hash_table_insert(s_jit_info_hashtable, method, jinfo); + } +#endif // RUNTIME_IL2CPP + /* * We emit type load events when the first method of the type is JITted, * since the class load profiler callbacks might be called with the @@ -4166,6 +4449,9 @@ typedef struct { guint8 *ip; MonoJitInfo *ji; MonoDomain *domain; +#ifdef RUNTIME_IL2CPP + Il2CppSequencePoint* seq_point; +#endif } BreakpointInstance; /* @@ -4208,6 +4494,8 @@ breakpoints_init (void) * Insert the breakpoint described by BP into the method described by * JI. */ +#ifndef RUNTIME_IL2CPP + static void insert_breakpoint (MonoSeqPointInfo *seq_points, MonoDomain *domain, MonoJitInfo *ji, MonoBreakpoint *bp, MonoError *error) { @@ -4297,6 +4585,7 @@ insert_breakpoint (MonoSeqPointInfo *seq_points, MonoDomain *domain, MonoJitInfo DEBUG_PRINTF (1, "[dbg] Inserted breakpoint at %s:[il=0x%x,native=0x%x] [%p](%d).\n", mono_method_full_name (jinfo_get_method (ji), TRUE), (int)it.seq_point.il_offset, (int)it.seq_point.native_offset, inst->ip, count); } + static void remove_breakpoint (BreakpointInstance *inst) { @@ -4322,7 +4611,9 @@ remove_breakpoint (BreakpointInstance *inst) #else NOT_IMPLEMENTED; #endif -} +} + +#endif // !RUNTIME_IL2CPP /* * This doesn't take any locks. @@ -4334,6 +4625,9 @@ bp_matches_method (MonoBreakpoint *bp, MonoMethod *method) if (!bp->method) return TRUE; +#ifdef RUNTIME_IL2CPP + return il2cpp_mono_methods_match(bp->method, method); +#else if (method == bp->method) return TRUE; if (method->is_inflated && ((MonoMethodInflated*)method)->declaring == bp->method) @@ -4357,6 +4651,7 @@ bp_matches_method (MonoBreakpoint *bp, MonoMethod *method) } return FALSE; +#endif // RUNTIME_IL2CPP } /* @@ -4367,6 +4662,7 @@ bp_matches_method (MonoBreakpoint *bp, MonoMethod *method) static void add_pending_breakpoints (MonoMethod *method, MonoJitInfo *ji) { +#ifndef RUNTIME_IL2CPP int i, j; MonoSeqPointInfo *seq_points; MonoDomain *domain; @@ -4415,8 +4711,11 @@ add_pending_breakpoints (MonoMethod *method, MonoJitInfo *ji) } mono_loader_unlock (); +#endif } +#ifndef RUNTIME_IL2CPP + static void set_bp_in_method (MonoDomain *domain, MonoMethod *method, MonoSeqPointInfo *seq_points, MonoBreakpoint *bp, MonoError *error) { @@ -4446,6 +4745,8 @@ set_bp_in_method (MonoDomain *domain, MonoMethod *method, MonoSeqPointInfo *seq_ insert_breakpoint (seq_points, domain, ji, bp, error); } +#endif + static void clear_breakpoint (MonoBreakpoint *bp); @@ -4494,6 +4795,37 @@ set_breakpoint (MonoMethod *method, long il_offset, EventRequest *req, MonoError method_seq_points = g_ptr_array_new (); mono_loader_lock (); +#ifdef RUNTIME_IL2CPP + void *seqPointIter = NULL; + Il2CppSequencePoint *seqPoint; + while(seqPoint = il2cpp_get_method_sequence_points(method, &seqPointIter)) + { + if (bp_matches_method(bp, il2cpp_get_seq_point_method(seqPoint)) && seqPoint->ilOffset == bp->il_offset) + { + if (req->event_kind == EVENT_KIND_BREAKPOINT && seqPoint->kind == kSequencePointKind_StepOut) + continue; + + if (req->event_kind == EVENT_KIND_STEP) + { + SingleStepReq *ssreq = (SingleStepReq*)req->info; + if (ssreq->depth == STEP_DEPTH_OUT && seqPoint->kind != kSequencePointKind_StepOut) + continue; + } + + BreakpointInstance* inst = g_new0(BreakpointInstance, 1); + inst->il_offset = bp->il_offset;// it.seq_point.il_offset; + inst->native_offset = 0;// it.seq_point.native_offset; + inst->domain = mono_domain_get(); + inst->seq_point = seqPoint; + + seqPoint->isActive++; + + mono_loader_lock(); + g_ptr_array_add(bp->children, inst); + mono_loader_unlock(); + } + } +#else g_hash_table_iter_init (&iter, domains); while (g_hash_table_iter_next (&iter, (void**)&domain, NULL)) { mono_domain_lock (domain); @@ -4515,6 +4847,7 @@ set_breakpoint (MonoMethod *method, long il_offset, EventRequest *req, MonoError seq_points = (MonoSeqPointInfo *)g_ptr_array_index (method_seq_points, i); set_bp_in_method (domain, m, seq_points, bp, error); } +#endif // RUNTIME_IL2CPP g_ptr_array_add (breakpoints, bp); mono_loader_unlock (); @@ -4531,6 +4864,73 @@ set_breakpoint (MonoMethod *method, long il_offset, EventRequest *req, MonoError return bp; } +#ifdef RUNTIME_IL2CPP + +static MonoBreakpoint* set_breakpoint_fast(Il2CppSequencePoint *sp, EventRequest *req, MonoError *error) +{ + MonoBreakpoint *bp; + GHashTableIter iter, iter2; + MonoDomain *domain; + MonoMethod *m; + MonoSeqPointInfo *seq_points; + GPtrArray *methods; + GPtrArray *method_domains; + GPtrArray *method_seq_points; + int i; + + if (error) + error_init(error); + + // FIXME: + // - suspend/resume the vm to prevent code patching problems + // - multiple breakpoints on the same location + // - dynamic methods + // - races + + bp = g_new0(MonoBreakpoint, 1); + bp->method = il2cpp_get_seq_point_method(sp); + bp->il_offset = sp->ilOffset; + bp->req = req; + bp->children = g_ptr_array_new(); + + DEBUG_PRINTF(1, "[dbg] Setting %sbreakpoint at %s:0x%x.\n", (req->event_kind == EVENT_KIND_STEP) ? "single step " : "", bp->method ? mono_method_full_name(bp->method, TRUE) : "", (int)bp->il_offset); + + methods = g_ptr_array_new(); + method_domains = g_ptr_array_new(); + method_seq_points = g_ptr_array_new(); + + mono_loader_lock(); + + BreakpointInstance* inst = g_new0(BreakpointInstance, 1); + inst->il_offset = bp->il_offset;// it.seq_point.il_offset; + inst->native_offset = 0;// it.seq_point.native_offset; + inst->domain = mono_domain_get(); + inst->seq_point = sp; + + sp->isActive++; + + mono_loader_lock(); + g_ptr_array_add(bp->children, inst); + mono_loader_unlock(); + + g_ptr_array_add(breakpoints, bp); + mono_loader_unlock(); + + g_ptr_array_free(methods, TRUE); + g_ptr_array_free(method_domains, TRUE); + g_ptr_array_free(method_seq_points, TRUE); + + if (error && !mono_error_ok(error)) + { + clear_breakpoint(bp); + return NULL; + } + + return bp; +} + +#endif // RUNTIME_IL2CPP + static void clear_breakpoint (MonoBreakpoint *bp) { @@ -4540,7 +4940,11 @@ clear_breakpoint (MonoBreakpoint *bp) for (i = 0; i < bp->children->len; ++i) { BreakpointInstance *inst = (BreakpointInstance *)g_ptr_array_index (bp->children, i); - remove_breakpoint (inst); +#ifndef RUNTIME_IL2CPP + remove_breakpoint(inst); +#else + inst->seq_point->isActive--; +#endif g_free (inst); } @@ -4572,14 +4976,20 @@ breakpoints_cleanup (void) } } - for (i = 0; i < breakpoints->len; ++i) - g_free (g_ptr_array_index (breakpoints, i)); + if (breakpoints) + { + for (i = 0; i < breakpoints->len; ++i) + g_free (g_ptr_array_index (breakpoints, i)); - g_ptr_array_free (breakpoints, TRUE); - g_hash_table_destroy (bp_locs); + g_ptr_array_free (breakpoints, TRUE); + breakpoints = NULL; + } - breakpoints = NULL; - bp_locs = NULL; + if (bp_locs) + { + g_hash_table_destroy (bp_locs); + bp_locs = NULL; + } mono_loader_unlock (); } @@ -4607,7 +5017,11 @@ clear_breakpoints_for_domain (MonoDomain *domain) BreakpointInstance *inst = (BreakpointInstance *)g_ptr_array_index (bp->children, j); if (inst->domain == domain) { +#ifndef RUNTIME_IL2CPP remove_breakpoint (inst); +#else + inst->seq_point->isActive--; +#endif g_free (inst); @@ -4632,6 +5046,7 @@ static void ss_calculate_framecount (DebuggerTlsData *tls, MonoContext *ctx) compute_frame_info (tls->thread, tls); } +#ifndef RUNTIME_IL2CPP static gboolean ensure_jit (StackFrame* frame) { @@ -4651,6 +5066,7 @@ ensure_jit (StackFrame* frame) } return TRUE; } +#endif /* * ss_update: @@ -4660,12 +5076,14 @@ ensure_jit (StackFrame* frame) static gboolean ss_update (SingleStepReq *req, MonoJitInfo *ji, SeqPoint *sp, DebuggerTlsData *tls, MonoContext *ctx, MonoMethod* method) { +#ifndef RUNTIME_IL2CPP MonoDebugMethodInfo *minfo; MonoDebugSourceLocation *loc = NULL; +#endif gboolean hit = TRUE; if (req->async_stepout_method == method) { - DEBUG_PRINTF (1, "[%p] Breakpoint hit during async step-out at %s hit, continuing stepping out.\n", (gpointer)(gsize)mono_native_thread_id_get (), method->name); + DEBUG_PRINTF (1, "[%p] Breakpoint hit during async step-out at %s hit, continuing stepping out.\n", (gpointer)(gsize)mono_native_thread_id_get (), mono_method_get_name(method)); return FALSE; } @@ -4700,6 +5118,7 @@ ss_update (SingleStepReq *req, MonoJitInfo *ji, SeqPoint *sp, DebuggerTlsData *t } } +#ifndef RUNTIME_IL2CPP MonoDebugMethodAsyncInfo* async_method = mono_debug_lookup_method_async_debug_info (method); if (async_method) { for (int i = 0; i < async_method->num_awaits; i++) { @@ -4710,11 +5129,14 @@ ss_update (SingleStepReq *req, MonoJitInfo *ji, SeqPoint *sp, DebuggerTlsData *t } mono_debug_free_method_async_debug_info (async_method); } +#endif if (req->size != STEP_SIZE_LINE) return TRUE; /* Have to check whenever a different source line was reached */ + +#ifndef RUNTIME_IL2CPP minfo = mono_debug_lookup_method (method); if (minfo) @@ -4737,9 +5159,75 @@ ss_update (SingleStepReq *req, MonoJitInfo *ji, SeqPoint *sp, DebuggerTlsData *t ss_req->last_line = loc->row; mono_debug_free_source_location (loc); } +#else + NOT_IMPLEMENTED; +#endif + + return hit; +} + +#ifdef RUNTIME_IL2CPP +/* +* ss_update_il2cpp: +* +* Return FALSE if single stepping needs to continue. +*/ +static gboolean +ss_update_il2cpp(SingleStepReq *req, DebuggerTlsData *tls, MonoContext *ctx, Il2CppSequencePoint *sequencePoint) +{ + gboolean hit = TRUE; + MonoMethod *sp_method = il2cpp_get_seq_point_method(sequencePoint); + + if (il2cpp_mono_methods_match(req->async_stepout_method, sp_method)) + { + DEBUG_PRINTF(1, "[%p] Breakpoint hit during async step-out at %s hit, continuing stepping out.\n", (gpointer)(gsize)mono_native_thread_id_get(), mono_method_get_name(sp_method)); + return FALSE; + } + + if ((req->depth == STEP_DEPTH_OVER || req->depth == STEP_DEPTH_OUT) && hit && !req->async_stepout_method) + { + gboolean is_step_out = req->depth == STEP_DEPTH_OUT; + + // Because functions can call themselves recursively, we need to make sure we're stopping at the right stack depth. + // In case of step out, the target is the frame *enclosing* the one where the request was made. + int target_frames = req->nframes + (is_step_out ? -1 : 0); + if (req->nframes > 0 && tls->il2cpp_context.frameCount > 0 && tls->il2cpp_context.frameCount > target_frames) + { + /* Hit the breakpoint in a recursive call, don't halt */ + DEBUG_PRINTF(1, "[%p] Breakpoint at lower frame while stepping %s, continuing single stepping.\n", (gpointer)(gsize)mono_native_thread_id_get(), is_step_out ? "out" : "over"); + return FALSE; + } + } + + if (req->size != STEP_SIZE_LINE) + return TRUE; + + /* Have to check whenever a different source line was reached */ + + if (sequencePoint->lineEnd < 0) + { + DEBUG_PRINTF(1, "[%p] No line number info for il offset %x, continuing single stepping.\n", (gpointer)(gsize)mono_native_thread_id_get(), sequencePoint->ilOffset); + ss_req->last_method = sp_method; + hit = FALSE; + } + else if (sequencePoint->lineEnd >= 0 && sp_method == ss_req->last_method && sequencePoint->lineEnd == ss_req->last_line) + { + if (tls->il2cpp_context.frameCount == req->nframes) + { // If the frame has changed we're clearly not on the same source line. + DEBUG_PRINTF(1, "[%p] Same source line (%d), continuing single stepping.\n", (gpointer)(gsize)mono_native_thread_id_get(), sequencePoint->lineEnd); + hit = FALSE; + } + } + + if (sequencePoint->lineEnd >= 0) + { + ss_req->last_method = sp_method; + ss_req->last_line = sequencePoint->lineEnd; + } return hit; } +#endif static gboolean breakpoint_matches_assembly (MonoBreakpoint *bp, MonoAssembly *assembly) @@ -4750,6 +5238,7 @@ breakpoint_matches_assembly (MonoBreakpoint *bp, MonoAssembly *assembly) static gpointer get_this_addr (StackFrame *frame) { +#ifndef RUNTIME_IL2CPP if (frame->ji->is_interp) return mini_get_interp_callbacks ()->frame_get_this (frame->interp_frame); @@ -4760,6 +5249,10 @@ get_this_addr (StackFrame *frame) guint8 *addr = (guint8 *)mono_arch_context_get_int_reg (&frame->ctx, var->index & ~MONO_DEBUG_VAR_ADDRESS_MODE_FLAGS); addr += (gint32)var->offset; return addr; +#else + g_assert_not_reached (); + return NULL; +#endif } static MonoMethod* @@ -4887,6 +5380,7 @@ get_notify_debugger_of_wait_completion_method (void) return notify_debugger_of_wait_completion_method_cache; } +#ifndef RUNTIME_IL2CPP static void process_breakpoint (DebuggerTlsData *tls, gboolean from_signal) { @@ -4957,7 +5451,7 @@ process_breakpoint (DebuggerTlsData *tls, gboolean from_signal) g_assert (found_sp); - DEBUG_PRINTF (1, "[%p] Breakpoint hit, method=%s, ip=%p, [il=0x%x,native=0x%x].\n", (gpointer) (gsize) mono_native_thread_id_get (), method->name, ip, sp.il_offset, native_offset); + DEBUG_PRINTF (1, "[%p] Breakpoint hit, method=%s, ip=%p, [il=0x%x,native=0x%x].\n", (gpointer) (gsize) mono_native_thread_id_get (), mono_method_get_name(method), ip, sp.il_offset, native_offset); bp = NULL; for (i = 0; i < breakpoints->len; ++i) { @@ -5005,14 +5499,12 @@ process_breakpoint (DebuggerTlsData *tls, gboolean from_signal) //make sure we have enough data to get current async method instance id if (tls->frame_count == 0 || !ensure_jit (tls->frames [0])) continue; - //Check method is async before calling get_this_async_id MonoDebugMethodAsyncInfo* asyncMethod = mono_debug_lookup_method_async_debug_info (method); if (!asyncMethod) continue; else mono_debug_free_method_async_debug_info (asyncMethod); - //breakpoint was hit in parallelly executing async method, ignore it if (ss_req->async_id != get_this_async_id (tls->frames [0])) continue; @@ -5039,9 +5531,9 @@ process_breakpoint (DebuggerTlsData *tls, gboolean from_signal) if (ss_reqs->len > 0) ss_events = create_event_list (EVENT_KIND_STEP, ss_reqs, ji, NULL, &suspend_policy); - if (bp_reqs->len > 0) + else if (bp_reqs->len > 0) bp_events = create_event_list (EVENT_KIND_BREAKPOINT, bp_reqs, ji, NULL, &suspend_policy); - if (kind != EVENT_KIND_BREAKPOINT) + else if (kind != EVENT_KIND_BREAKPOINT) enter_leave_events = create_event_list (kind, NULL, ji, NULL, &suspend_policy); mono_loader_unlock (); @@ -5060,6 +5552,7 @@ process_breakpoint (DebuggerTlsData *tls, gboolean from_signal) if (enter_leave_events) process_event (kind, method, 0, ctx, enter_leave_events, suspend_policy); } +#endif /* Process a breakpoint/single step event after resuming from a signal handler */ static void @@ -5083,11 +5576,13 @@ process_signal_event (void (*func) (DebuggerTlsData*, gboolean)) g_assert_not_reached (); } +#ifndef RUNTIME_IL2CPP static void process_breakpoint_from_signal (void) { process_signal_event (process_breakpoint); } +#endif static void resume_from_signal_handler (void *sigctx, void *func) @@ -5120,6 +5615,7 @@ resume_from_signal_handler (void *sigctx, void *func) #endif } +#ifndef RUNTIME_IL2CPP void mono_debugger_agent_breakpoint_hit (void *sigctx) { @@ -5130,6 +5626,7 @@ mono_debugger_agent_breakpoint_hit (void *sigctx) */ resume_from_signal_handler (sigctx, process_breakpoint_from_signal); } +#endif typedef struct { gboolean found; @@ -5169,16 +5666,22 @@ mono_debugger_agent_user_break (void) memset (&data, 0, sizeof (UserBreakCbData)); data.ctx = &ctx; +#ifndef RUNTIME_IL2CPP /* Obtain a context */ MONO_CONTEXT_SET_IP (&ctx, NULL); mono_walk_stack_with_ctx (user_break_cb, NULL, (MonoUnwindOptions)0, &data); g_assert (data.found); +#endif mono_loader_lock (); events = create_event_list (EVENT_KIND_USER_BREAK, NULL, NULL, NULL, &suspend_policy); mono_loader_unlock (); +#ifndef RUNTIME_IL2CPP process_event (EVENT_KIND_USER_BREAK, NULL, 0, &ctx, events, suspend_policy); +#else + process_event (EVENT_KIND_USER_BREAK, NULL, 0, &ctx, events, suspend_policy, 0); +#endif } else if (debug_options.native_debugger_break) { G_BREAKPOINT (); } @@ -5201,7 +5704,11 @@ ss_depth_to_string (StepDepth depth) } static void +#ifndef RUNTIME_IL2CPP process_single_step_inner (DebuggerTlsData *tls, gboolean from_signal) +#else +process_single_step_inner (DebuggerTlsData *tls, gboolean from_signal, int sequencePointId) +#endif { MonoJitInfo *ji; guint8 *ip; @@ -5214,9 +5721,15 @@ process_single_step_inner (DebuggerTlsData *tls, gboolean from_signal) SeqPoint sp; MonoSeqPointInfo *info; +#ifndef RUNTIME_IL2CPP /* Skip the instruction causing the single step */ +#ifndef RUNTIME_IL2CPP if (from_signal) mono_arch_skip_single_step (ctx); +#else + NOT_IMPLEMENTED; +#endif +#endif if (suspend_count > 0) { /* Fastpath during invokes, see in process_suspend () */ @@ -5233,14 +5746,18 @@ process_single_step_inner (DebuggerTlsData *tls, gboolean from_signal) if (mono_thread_internal_current () != ss_req->thread) return; +#ifndef RUNTIME_IL2CPP + ip = (guint8 *)MONO_CONTEXT_GET_IP (ctx); ji = get_top_method_ji (ip, &domain, (gpointer*)&ip); g_assert (ji && !ji->is_trampoline); +#ifndef RUNTIME_IL2CPP if (log_level > 0) { DEBUG_PRINTF (1, "[%p] Single step event (depth=%s) at %s (%p)[0x%x], sp %p, last sp %p\n", (gpointer) (gsize) mono_native_thread_id_get (), ss_depth_to_string (ss_req->depth), mono_method_full_name (jinfo_get_method (ji), TRUE), MONO_CONTEXT_GET_IP (ctx), (int)((guint8*)MONO_CONTEXT_GET_IP (ctx) - (guint8*)ji->code_start), MONO_CONTEXT_GET_SP (ctx), ss_req->last_sp); } +#endif method = jinfo_get_method (ji); g_assert (method); @@ -5253,7 +5770,7 @@ process_single_step_inner (DebuggerTlsData *tls, gboolean from_signal) * Stopping in memset makes half-initialized vtypes visible. * Stopping in memcpy makes half-copied vtypes visible. */ - if (method->klass == mono_defaults.string_class && (!strcmp (method->name, "memset") || strstr (method->name, "memcpy"))) + if (method->klass == mono_defaults.string_class && (!strcmp (mono_method_get_name(method), "memset") || strstr (mono_method_get_name(method), "memcpy"))) return; /* @@ -5291,10 +5808,11 @@ process_single_step_inner (DebuggerTlsData *tls, gboolean from_signal) if ((ss_req->filter & STEP_FILTER_STATIC_CTOR) && (method->flags & METHOD_ATTRIBUTE_SPECIAL_NAME) && - !strcmp (method->name, ".cctor")) + !strcmp (mono_method_get_name(method), ".cctor")) return; // FIXME: Has to lock earlier +#endif reqs = g_ptr_array_new (); @@ -5302,13 +5820,47 @@ process_single_step_inner (DebuggerTlsData *tls, gboolean from_signal) g_ptr_array_add (reqs, ss_req->req); +#ifndef RUNTIME_IL2CPP events = create_event_list (EVENT_KIND_STEP, reqs, ji, NULL, &suspend_policy); - +#else + events = create_event_list(EVENT_KIND_STEP, reqs, il2cpp_get_sequence_point(sequencePointId), NULL, &suspend_policy); +#endif + g_ptr_array_free (reqs, TRUE); mono_loader_unlock (); +#ifndef RUNTIME_IL2CPP process_event (EVENT_KIND_STEP, jinfo_get_method (ji), il_offset, ctx, events, suspend_policy); +#else + Il2CppSequencePoint* sequence_pt = tls->il2cpp_context.sequencePoints[tls->il2cpp_context.frameCount - 1]; + MonoMethod *sp_method = il2cpp_get_seq_point_method(sequence_pt); + + /* + * This could be in ss_update method, but mono_find_next_seq_point_for_native_offset is pretty expensive method, + * hence we prefer this check here. + */ + if (ss_req->user_assemblies) + { + gboolean found = FALSE; + for (int k = 0; ss_req->user_assemblies[k]; k++) + { + if (ss_req->user_assemblies[k] == sp_method->klass->image->assembly) + { + found = TRUE; + break; + } + } + + if (!found) + return; + } + + if(!ss_update_il2cpp(ss_req,tls,ctx,sequence_pt)) + return; + + process_event(EVENT_KIND_STEP, sp_method, sequence_pt->ilOffset, NULL, events, suspend_policy, sequencePointId); +#endif } static void @@ -5349,7 +5901,11 @@ mono_debugger_agent_single_step_event (void *sigctx) } void +#ifndef RUNTIME_IL2CPP debugger_agent_single_step_from_context (MonoContext *ctx) +#else +debugger_agent_single_step_from_context (MonoContext *ctx, int sequencePointId) +#endif { DebuggerTlsData *tls; MonoThreadUnwindState orig_restore_state; @@ -5364,6 +5920,7 @@ debugger_agent_single_step_from_context (MonoContext *ctx) g_assert (tls); +#ifndef RUNTIME_IL2CPP /* Have to save/restore the restore_ctx as we can be called recursively during invokes etc. */ memcpy (&orig_restore_state, &tls->restore_state, sizeof (MonoThreadUnwindState)); mono_thread_state_init_from_monoctx (&tls->restore_state, ctx); @@ -5373,8 +5930,14 @@ debugger_agent_single_step_from_context (MonoContext *ctx) memcpy (ctx, &tls->restore_state.ctx, sizeof (MonoContext)); memcpy (&tls->restore_state, &orig_restore_state, sizeof (MonoThreadUnwindState)); +#else + save_thread_context(NULL); + + process_single_step_inner(tls, FALSE, sequencePointId); +#endif } +#ifndef RUNTIME_IL2CPP void debugger_agent_breakpoint_from_context (MonoContext *ctx) { @@ -5401,6 +5964,7 @@ debugger_agent_breakpoint_from_context (MonoContext *ctx) if (MONO_CONTEXT_GET_IP (ctx) == orig_ip - 1) MONO_CONTEXT_SET_IP (ctx, orig_ip); } +#endif /* * start_single_stepping: @@ -5416,7 +5980,9 @@ start_single_stepping (void) if (val == 1) { mono_arch_start_single_stepping (); +#ifndef RUNTIME_IL2CPP mini_get_interp_callbacks ()->start_single_stepping (); +#endif } #else g_assert_not_reached (); @@ -5431,7 +5997,9 @@ stop_single_stepping (void) if (val == 0) { mono_arch_stop_single_stepping (); +#ifndef RUNTIME_IL2CPP mini_get_interp_callbacks ()->stop_single_stepping (); +#endif } #else g_assert_not_reached (); @@ -5543,6 +6111,37 @@ ss_bp_add_one (SingleStepReq *ss_req, int *ss_req_bp_count, GHashTable **ss_req_ } } +#ifdef RUNTIME_IL2CPP + +static void ss_bp_add_one_il2cpp(SingleStepReq *ss_req, int *ss_req_bp_count, GHashTable **ss_req_bp_cache, Il2CppSequencePoint *sp) +{ + // This list is getting too long, switch to using the hash table + if (!*ss_req_bp_cache && *ss_req_bp_count > MAX_LINEAR_SCAN_BPS) + { + *ss_req_bp_cache = g_hash_table_new(ss_bp_hash, ss_bp_eq); + for (GSList *l = ss_req->bps; l; l = l->next) + g_hash_table_insert(*ss_req_bp_cache, l->data, l->data); + } + + MonoMethod *sp_method = il2cpp_get_seq_point_method(sp); + + if (ss_bp_is_unique(ss_req->bps, *ss_req_bp_cache, sp_method, sp->ilOffset)) + { + // Create and add breakpoint + MonoBreakpoint *bp = set_breakpoint_fast(sp, ss_req->req, NULL); + ss_req->bps = g_slist_append(ss_req->bps, bp); + if (*ss_req_bp_cache) + g_hash_table_insert(*ss_req_bp_cache, bp, bp); + (*ss_req_bp_count)++; + } + else + { + DEBUG_PRINTF(1, "[dbg] Candidate breakpoint at %s:[il=0x%x] is a duplicate for this step request, will not add.\n", mono_method_full_name(sp_method, TRUE), (int)sp->ilOffset); + } +} + +#endif // RUNTIME_IL2CPP + static gboolean is_last_non_empty (SeqPoint* sp, MonoSeqPointInfo *info) { @@ -5573,6 +6172,7 @@ is_last_non_empty (SeqPoint* sp, MonoSeqPointInfo *info) * belong to the same thread as CTX. * If FRAMES is not-null, use that instead of tls->frames for placing breakpoints etc. */ +#ifndef RUNTIME_IL2CPP static void ss_start (SingleStepReq *ss_req, MonoMethod *method, SeqPoint* sp, MonoSeqPointInfo *info, MonoContext *ctx, DebuggerTlsData *tls, gboolean step_to_catch, StackFrame **frames, int nframes) @@ -5752,6 +6352,26 @@ ss_start (SingleStepReq *ss_req, MonoMethod *method, SeqPoint* sp, MonoSeqPointI ss_req->depth = STEP_DEPTH_INTO; } + if (ss_req->depth == STEP_DEPTH_OVER) { + /* Need to stop in catch clauses as well */ + for (i = 0; i < nframes; ++i) { + StackFrame *frame = frames[i]; + + if (frame->ji) { + MonoJitInfo *jinfo = frame->ji; + for (j = 0; j < jinfo->num_clauses; ++j) { + MonoJitExceptionInfo *ei = &jinfo->clauses[j]; + + found_sp = mono_find_next_seq_point_for_native_offset(frame->domain, frame->method, (char*)ei->handler_start - (char*)jinfo->code_start, NULL, &local_sp); + sp = (found_sp) ? &local_sp : NULL; + + if (found_sp) + ss_bp_add_one(ss_req, &ss_req_bp_count, &ss_req_bp_cache, frame->method, sp->il_offset); + } + } + } + } + if (ss_req->depth == STEP_DEPTH_INTO) { /* Enable global stepping so we stop at method entry too */ enable_global = TRUE; @@ -5781,6 +6401,78 @@ ss_start (SingleStepReq *ss_req, MonoMethod *method, SeqPoint* sp, MonoSeqPointI g_hash_table_destroy (ss_req_bp_cache); } +#else + +static void +ss_start_il2cpp(SingleStepReq *ss_req, DebuggerTlsData *tls, Il2CppSequencePoint *catchFrameSp) +{ + // When 8 or more entries are in bps, we build a hash table to serve as a set of breakpoints. + // Recreating this on each pass is a little wasteful but at least keeps behavior linear. + int ss_req_bp_count = g_slist_length(ss_req->bps); + GHashTable *ss_req_bp_cache = NULL; + gboolean enable_global = FALSE; + + /* Stop the previous operation */ + ss_stop(ss_req); + + DEBUG_PRINTF(0, "Step depth: %d\n", ss_req->depth); + + if (catchFrameSp) { + ss_bp_add_one_il2cpp (ss_req, &ss_req_bp_count, &ss_req_bp_cache, catchFrameSp); + } else { + if (ss_req->depth == STEP_DEPTH_OVER) + { + MonoMethod* currentMethod = il2cpp_get_seq_point_method(tls->il2cpp_context.sequencePoints[tls->il2cpp_context.frameCount - 1]); + + void *seqPointIter = NULL; + Il2CppSequencePoint *seqPoint; + while(seqPoint = il2cpp_get_method_sequence_points(currentMethod, &seqPointIter)) + { + if (seqPoint->kind != kSequencePointKind_Normal) + continue; + + if (il2cpp_mono_methods_match(il2cpp_get_seq_point_method(seqPoint), currentMethod)) + ss_bp_add_one_il2cpp(ss_req, &ss_req_bp_count, &ss_req_bp_cache, seqPoint); + } + } + + if (tls->il2cpp_context.frameCount > 1) + { + Il2CppSequencePoint* sequencePointForStepOut = tls->il2cpp_context.sequencePoints[tls->il2cpp_context.frameCount - 2]; + g_assert(sequencePointForStepOut->kind == kSequencePointKind_StepOut); + ss_bp_add_one_il2cpp(ss_req, &ss_req_bp_count, &ss_req_bp_cache, sequencePointForStepOut); + } + + if (ss_req->depth == STEP_DEPTH_INTO) + { + /* Enable global stepping so we stop at method entry too */ + enable_global = TRUE; + } + } + + if (ss_req_bp_cache) + g_hash_table_destroy(ss_req_bp_cache); + + if (enable_global) + { + DEBUG_PRINTF(1, "[dbg] Turning on global single stepping.\n"); + ss_req->global = TRUE; + start_single_stepping(); + } + else if (!ss_req->bps) + { + DEBUG_PRINTF(1, "[dbg] Turning on global single stepping.\n"); + ss_req->global = TRUE; + start_single_stepping(); + } + else + { + ss_req->global = FALSE; + } +} + +#endif // RUNTIME_IL2CPP + /* * Start single stepping of thread THREAD */ @@ -5793,7 +6485,9 @@ ss_create (MonoInternalThread *thread, StepSize size, StepDepth depth, StepFilte SeqPoint local_sp; gboolean found_sp; MonoMethod *method = NULL; +#ifndef RUNTIME_IL2CPP MonoDebugMethodInfo *minfo; +#endif gboolean step_to_catch = FALSE; gboolean set_ip = FALSE; StackFrame **frames = NULL; @@ -5831,6 +6525,25 @@ ss_create (MonoInternalThread *thread, StepSize size, StepDepth depth, StepFilte tls = (DebuggerTlsData *)mono_g_hash_table_lookup (thread_to_tls, thread); mono_loader_unlock (); g_assert (tls); + +#ifdef RUNTIME_IL2CPP + ss_req->nframes = tls->il2cpp_context.frameCount; + Il2CppSequencePoint *catchFrameSp = NULL; + + if (tls->il2cpp_context.frameCount > 0) + { + Il2CppSequencePoint* seq_point = tls->il2cpp_context.sequencePoints[tls->il2cpp_context.frameCount - 1]; + MonoMethod *sp_method = il2cpp_get_seq_point_method(seq_point); + ss_req->start_method = sp_method; + ss_req->last_method = sp_method; + ss_req->last_line = seq_point->lineEnd; + + if (tls->exception) + catchFrameSp = il2cpp_find_catch_sequence_point(tls); + } + + ss_start_il2cpp(ss_req, tls, catchFrameSp); +#else if (!tls->context.valid) { DEBUG_PRINTF (1, "Received a single step request on a thread with no managed frames."); return ERR_INVALID_ARGUMENT; @@ -5921,6 +6634,7 @@ ss_create (MonoInternalThread *thread, StepSize size, StepDepth depth, StepFilte if (frames) free_frames (frames, nframes); +#endif return ERR_NONE; } @@ -5965,7 +6679,7 @@ mono_debugger_agent_debug_log (int level, MonoString *category, MonoString *mess MonoError error; int suspend_policy; GSList *events; - EventInfo ei; + DebuggerEventInfo ei; if (!agent_config.enabled) return; @@ -5985,8 +6699,11 @@ mono_debugger_agent_debug_log (int level, MonoString *category, MonoString *mess ei.message = mono_string_to_utf8_checked (message, &error); mono_error_cleanup (&error); } - +#ifndef RUNTIME_IL2CPP process_event (EVENT_KIND_USER_LOG, &ei, 0, NULL, events, suspend_policy); +#else + process_event (EVENT_KIND_USER_LOG, &ei, 0, NULL, events, suspend_policy, 0); +#endif g_free (ei.category); g_free (ei.message); @@ -6005,19 +6722,175 @@ mono_debugger_agent_unhandled_exception (MonoException *exc) { int suspend_policy; GSList *events; - EventInfo ei; + DebuggerEventInfo ei; if (!inited) return; - memset (&ei, 0, sizeof (EventInfo)); + memset (&ei, 0, sizeof (DebuggerEventInfo)); ei.exc = (MonoObject*)exc; mono_loader_lock (); events = create_event_list (EVENT_KIND_EXCEPTION, NULL, NULL, &ei, &suspend_policy); mono_loader_unlock (); +#ifndef RUNTIME_IL2CPP process_event (EVENT_KIND_EXCEPTION, &ei, 0, NULL, events, suspend_policy); +#else + process_event (EVENT_KIND_EXCEPTION, &ei, 0, NULL, events, suspend_policy, 0); +#endif +} +#endif + +#ifdef RUNTIME_IL2CPP + +static Il2CppSequencePoint* il2cpp_find_catch_sequence_point_in_method(Il2CppSequencePoint* callSp, MonoException *exc) +{ + uint8_t tryDepth = callSp->tryDepth; + MonoMethod *method = il2cpp_get_seq_point_method(callSp); + int32_t ilOffset = callSp->ilOffset; + Il2CppSequencePoint *sp; + + void *seqPointIter = NULL; + while (sp = il2cpp_get_method_sequence_points(method, &seqPointIter)) + { + MonoClass *catchType = il2cpp_get_class_from_index(sp->catchTypeIndex); + if (sp->tryDepth == tryDepth && sp->ilOffset > ilOffset && catchType != NULL && mono_class_is_assignable_from(catchType, exc->object.vtable->klass)) + return sp; + } + + return NULL; +} + +static Il2CppSequencePoint* il2cpp_find_catch_sequence_point(DebuggerTlsData *tls) +{ + int frameIndex = tls->il2cpp_context.frameCount - 1; + while (frameIndex >= 0) + { + Il2CppSequencePoint* sp = il2cpp_find_catch_sequence_point_in_method(tls->il2cpp_context.sequencePoints[frameIndex], tls->exception); + if (sp) + return sp; + + --frameIndex; + } + + return NULL; +} + +static Il2CppSequencePoint* il2cpp_find_catch_sequence_point_from_exeption(DebuggerTlsData *tls, MonoException *exc, Il2CppSequencePoint *firstSp) +{ + Il2CppSequencePoint* sp; + + if (firstSp) + { + sp = il2cpp_find_catch_sequence_point_in_method(firstSp, exc); + if (sp) + return sp; + } + + int frameIndex = tls->il2cpp_context.frameCount - 1; + while (frameIndex >= 0) + { + sp = il2cpp_find_catch_sequence_point_in_method(tls->il2cpp_context.sequencePoints[frameIndex], exc); + if (sp) + return sp; + + --frameIndex; + } + + return NULL; +} + +void +unity_debugger_agent_handle_exception(MonoException *exc, Il2CppSequencePoint *sequencePoint) +{ + int i, j, suspend_policy; + GSList *events; + DebuggerEventInfo ei; + DebuggerTlsData *tls = NULL; + + if (thread_to_tls != NULL) + { + MonoInternalThread *thread = mono_thread_internal_current(); + + mono_loader_lock(); + tls = (DebuggerTlsData *)mono_g_hash_table_lookup(thread_to_tls, thread); + mono_loader_unlock(); + + if (tls && tls->abort_requested) + return; + if (tls && tls->disable_breakpoints) + return; + } + + memset(&ei, 0, sizeof(DebuggerEventInfo)); + + ei.exc = (MonoObject*)exc; + ei.caught = FALSE; + Il2CppSequencePoint *catchSp = NULL; + + if (tls) + { + catchSp = il2cpp_find_catch_sequence_point_from_exeption(tls, exc, sequencePoint); + if (catchSp) + ei.caught = TRUE; + } + + mono_loader_lock(); + + MonoMethod *sp_method = il2cpp_get_seq_point_method(sequencePoint); + + /* Treat exceptions which are caught in non-user code as unhandled */ + for (i = 0; i < event_requests->len; ++i) + { + EventRequest *req = (EventRequest *)g_ptr_array_index(event_requests, i); + if (req->event_kind != EVENT_KIND_EXCEPTION) + continue; + + for (j = 0; j < req->nmodifiers; ++j) + { + Modifier *mod = &req->modifiers[j]; + + if (mod->kind == MOD_KIND_ASSEMBLY_ONLY && sequencePoint) + { + int k; + gboolean found = FALSE; + MonoAssembly **assemblies = mod->data.assemblies; + + if (assemblies) + { + for (k = 0; assemblies[k]; ++k) + if (assemblies[k] == sp_method->klass->image->assembly) + found = TRUE; + } + if (!found) + ei.caught = FALSE; + } + } + } + + events = create_event_list(EVENT_KIND_EXCEPTION, NULL, NULL, &ei, &suspend_policy); + mono_loader_unlock(); + + if (tls && ei.caught) + { + if (!ss_req || !ss_req->bps) { + tls->exception = exc; + } else if (ss_req->bps && catchSp) { + int ss_req_bp_count = g_slist_length(ss_req->bps); + GHashTable *ss_req_bp_cache = NULL; + + ss_bp_add_one_il2cpp(ss_req, &ss_req_bp_count, &ss_req_bp_cache, catchSp); + + if (ss_req_bp_cache) + g_hash_table_destroy(ss_req_bp_cache); + } + } + + process_event(EVENT_KIND_EXCEPTION, &ei, 0, NULL, events, suspend_policy, sequencePoint ? sequencePoint->id : 0); + + if (tls) + tls->exception = NULL; } #endif @@ -6028,7 +6901,7 @@ mono_debugger_agent_handle_exception (MonoException *exc, MonoContext *throw_ctx int i, j, suspend_policy; GSList *events; MonoJitInfo *ji, *catch_ji; - EventInfo ei; + DebuggerEventInfo ei; DebuggerTlsData *tls = NULL; if (thread_to_tls != NULL) { @@ -6044,7 +6917,7 @@ mono_debugger_agent_handle_exception (MonoException *exc, MonoContext *throw_ctx return; } - memset (&ei, 0, sizeof (EventInfo)); + memset (&ei, 0, sizeof (DebuggerEventInfo)); /* Just-In-Time debugging */ if (!catch_ctx) { @@ -6056,7 +6929,11 @@ mono_debugger_agent_handle_exception (MonoException *exc, MonoContext *throw_ctx */ events = g_slist_append (NULL, GUINT_TO_POINTER (0xffffff)); ei.exc = (MonoObject*)exc; +#ifndef RUNTIME_IL2CPP process_event (EVENT_KIND_EXCEPTION, &ei, 0, throw_ctx, events, SUSPEND_POLICY_ALL); +#else + process_event (EVENT_KIND_EXCEPTION, &ei, 0, throw_ctx, events, SUSPEND_POLICY_ALL, 0); +#endif return; } } else if (agent_config.onthrow && !inited) { @@ -6081,7 +6958,11 @@ mono_debugger_agent_handle_exception (MonoException *exc, MonoContext *throw_ctx */ events = g_slist_append (NULL, GUINT_TO_POINTER (0xffffff)); ei.exc = (MonoObject*)exc; +#ifndef RUNTIME_IL2CPP process_event (EVENT_KIND_EXCEPTION, &ei, 0, throw_ctx, events, SUSPEND_POLICY_ALL); +#else + process_event (EVENT_KIND_EXCEPTION, &ei, 0, throw_ctx, events, SUSPEND_POLICY_ALL, 0); +#endif return; } } @@ -6137,7 +7018,11 @@ mono_debugger_agent_handle_exception (MonoException *exc, MonoContext *throw_ctx } } +#ifndef RUNTIME_IL2CPP process_event (EVENT_KIND_EXCEPTION, &ei, 0, throw_ctx, events, suspend_policy); +#else + process_event (EVENT_KIND_EXCEPTION, &ei, 0, throw_ctx, events, suspend_policy, 0); +#endif if (tls) tls->has_catch_frame = FALSE; @@ -6204,8 +7089,8 @@ mono_debugger_agent_end_exception_filter (MonoException *exc, MonoContext *ctx, * AS_VTYPE determines whenever to treat primitive types as primitive types or * vtypes. */ -static void -buffer_add_value_full (Buffer *buf, MonoType *t, void *addr, MonoDomain *domain, +#ifndef RUNTIME_IL2CPP +static void buffer_add_value_full (Buffer *buf, MonoType *t, void *addr, MonoDomain *domain, gboolean as_vtype, GHashTable *parent_vtypes) { MonoObject *obj; @@ -6283,6 +7168,8 @@ buffer_add_value_full (Buffer *buf, MonoType *t, void *addr, MonoDomain *domain, buffer_add_byte (buf, t->type); buffer_add_long (buf, val); + if (CHECK_PROTOCOL_VERSION(2, 46)) + buffer_add_typeid (buf, domain, mono_class_from_mono_type (t)); break; } handle_ref: @@ -6385,6 +7272,218 @@ buffer_add_value_full (Buffer *buf, MonoType *t, void *addr, MonoDomain *domain, NOT_IMPLEMENTED; } } +#else +static void buffer_add_value_full(Buffer *buf, MonoType *t, void *addr, MonoDomain *domain, + gboolean as_vtype, GHashTable *parent_vtypes) +{ + MonoObject *obj; + gboolean boxed_vtype = FALSE; + + if (il2cpp_type_is_byref(t)) + { + if (!(*(void**)addr)) + { + /* This can happen with compiler generated locals */ + //printf ("%s\n", mono_type_full_name (t)); + buffer_add_byte(buf, VALUE_TYPE_ID_NULL); + return; + } + g_assert(*(void**)addr); + addr = *(void**)addr; + } + + if (as_vtype) + { + switch (il2cpp_type_get_type(t)) + { + case MONO_TYPE_BOOLEAN: + case MONO_TYPE_I1: + case MONO_TYPE_U1: + case MONO_TYPE_CHAR: + case MONO_TYPE_I2: + case MONO_TYPE_U2: + case MONO_TYPE_I4: + case MONO_TYPE_U4: + case MONO_TYPE_R4: + case MONO_TYPE_I8: + case MONO_TYPE_U8: + case MONO_TYPE_R8: + case MONO_TYPE_I: + case MONO_TYPE_U: + case MONO_TYPE_PTR: + goto handle_vtype; + break; + default: + break; + } + } + + switch (il2cpp_type_get_type(t)) + { + case MONO_TYPE_VOID: + buffer_add_byte(buf, il2cpp_type_get_type(t)); + break; + case MONO_TYPE_BOOLEAN: + case MONO_TYPE_I1: + case MONO_TYPE_U1: + buffer_add_byte(buf, il2cpp_type_get_type(t)); + buffer_add_int(buf, *(gint8*)addr); + break; + case MONO_TYPE_CHAR: + case MONO_TYPE_I2: + case MONO_TYPE_U2: + buffer_add_byte(buf, il2cpp_type_get_type(t)); + buffer_add_int(buf, *(gint16*)addr); + break; + case MONO_TYPE_I4: + case MONO_TYPE_U4: + case MONO_TYPE_R4: + buffer_add_byte(buf, il2cpp_type_get_type(t)); + buffer_add_int(buf, *(gint32*)addr); + break; + case MONO_TYPE_I8: + case MONO_TYPE_U8: + case MONO_TYPE_R8: + buffer_add_byte(buf, il2cpp_type_get_type(t)); + buffer_add_long(buf, *(gint64*)addr); + break; + case MONO_TYPE_I: + case MONO_TYPE_U: + /* Treat it as a vtype */ + goto handle_vtype; + case MONO_TYPE_PTR: { + gssize val = *(gssize*)addr; + + buffer_add_byte(buf, il2cpp_type_get_type(t)); + buffer_add_long(buf, val); + break; + } + handle_ref: + case MONO_TYPE_STRING: + case MONO_TYPE_SZARRAY: + case MONO_TYPE_OBJECT: + case MONO_TYPE_CLASS: + case MONO_TYPE_ARRAY: + obj = *(MonoObject**)addr; + + if (!obj) + { + buffer_add_byte(buf, VALUE_TYPE_ID_NULL); + } + else + { + MonoClass *klass = il2cpp_object_get_class(obj); + if (il2cpp_class_is_valuetype(klass)) + { + t = il2cpp_class_get_type(il2cpp_object_get_class(obj)); + addr = mono_object_unbox(obj); + boxed_vtype = TRUE; + goto handle_vtype; + } + else if (il2cpp_class_get_rank(klass)) + { + buffer_add_byte(buf, il2cpp_type_get_type(il2cpp_class_get_type(klass))); + } + else if (il2cpp_type_get_type(il2cpp_class_get_type(klass)) == MONO_TYPE_GENERICINST) + { + buffer_add_byte(buf, MONO_TYPE_CLASS); + } + else + { + buffer_add_byte(buf, il2cpp_type_get_type(il2cpp_class_get_type(klass))); + } + buffer_add_objid(buf, obj); + } + break; + handle_vtype: + case MONO_TYPE_VALUETYPE: + case MONO_TYPE_TYPEDBYREF: { + int nfields; + gpointer iter; + MonoClassField *f; + MonoClass *klass = mono_class_from_mono_type(t); + int vtype_index; + + if (boxed_vtype) + { + /* + * Handle boxed vtypes recursively referencing themselves using fields. + */ + if (!parent_vtypes) + parent_vtypes = g_hash_table_new(NULL, NULL); + vtype_index = GPOINTER_TO_INT(g_hash_table_lookup(parent_vtypes, addr)); + if (vtype_index) + { + if (CHECK_PROTOCOL_VERSION(2, 33)) + { + buffer_add_byte(buf, VALUE_TYPE_ID_PARENT_VTYPE); + buffer_add_int(buf, vtype_index - 1); + } + else + { + /* The client can't handle PARENT_VTYPE */ + buffer_add_byte(buf, VALUE_TYPE_ID_NULL); + } + break; + } + else + { + g_hash_table_insert(parent_vtypes, addr, GINT_TO_POINTER(g_hash_table_size(parent_vtypes) + 1)); + } + } + + buffer_add_byte(buf, MONO_TYPE_VALUETYPE); + buffer_add_byte(buf, klass->enumtype); + buffer_add_typeid(buf, domain, klass); + + nfields = 0; + iter = NULL; + while ((f = mono_class_get_fields(klass, &iter))) + { + if (f->type->attrs & FIELD_ATTRIBUTE_STATIC) + continue; + if (mono_field_is_deleted(f)) + continue; + nfields++; + } + buffer_add_int(buf, nfields); + + iter = NULL; + while ((f = mono_class_get_fields(klass, &iter))) + { + if (f->type->attrs & FIELD_ATTRIBUTE_STATIC) + continue; + if (mono_field_is_deleted(f)) + continue; + buffer_add_value_full(buf, f->type, (guint8*)addr + f->offset - sizeof(MonoObject), domain, FALSE, parent_vtypes); + } + + if (boxed_vtype) + { + g_hash_table_remove(parent_vtypes, addr); + if (g_hash_table_size(parent_vtypes) == 0) + { + g_hash_table_destroy(parent_vtypes); + parent_vtypes = NULL; + } + } + break; + } + case MONO_TYPE_GENERICINST: + if (mono_type_generic_inst_is_valuetype(t)) + { + goto handle_vtype; + } + else + { + goto handle_ref; + } + break; + default: + NOT_IMPLEMENTED; + } +} +#endif static void buffer_add_value (Buffer *buf, MonoType *t, void *addr, MonoDomain *domain) @@ -6432,7 +7531,7 @@ decode_vtype (MonoType *t, MonoDomain *domain, guint8 *addr, guint8 *buf, guint8 if (t && klass != mono_class_from_mono_type (t)) { char *name = mono_type_full_name (t); - char *name2 = mono_type_full_name (&klass->byval_arg); + char *name2 = mono_type_full_name (mono_class_get_type(klass)); DEBUG_PRINTF (1, "[%p] Expected value of type %s, got %s.\n", (gpointer) (gsize) mono_native_thread_id_get (), name, name2); g_free (name); g_free (name2); @@ -6443,7 +7542,7 @@ decode_vtype (MonoType *t, MonoDomain *domain, guint8 *addr, guint8 *buf, guint8 while ((f = mono_class_get_fields (klass, &iter))) { if (f->type->attrs & FIELD_ATTRIBUTE_STATIC) continue; - if (mono_field_is_deleted (f)) + if (mono_field_is_deleted(f)) continue; err = decode_value (f->type, domain, (guint8*)addr + f->offset - sizeof (MonoObject), buf, &buf, limit); if (err != ERR_NONE) @@ -6571,7 +7670,7 @@ decode_value_internal (MonoType *t, int type, MonoDomain *domain, guint8 *addr, return ERR_INVALID_ARGUMENT; } } - if (obj && obj->vtable->domain != domain) + if (obj && VM_OBJECT_GET_DOMAIN(obj) != domain) return ERR_INVALID_ARGUMENT; mono_gc_wbarrier_generic_store (addr, obj); @@ -6638,7 +7737,7 @@ decode_value (MonoType *t, MonoDomain *domain, guint8 *addr, guint8 *buf, guint8 int type = decode_byte (buf, &buf, limit); if (t->type == MONO_TYPE_GENERICINST && mono_class_is_nullable (mono_class_from_mono_type (t))) { - MonoType *targ = t->data.generic_class->context.class_inst->type_argv [0]; + MonoType *targ = t->data.generic_class->context.class_inst->type_argv[0]; guint8 *nullable_buf; /* @@ -6677,6 +7776,7 @@ decode_value (MonoType *t, MonoDomain *domain, guint8 *addr, guint8 *buf, guint8 return decode_value_internal (t, type, domain, addr, buf, endbuf, limit); } +#ifndef RUNTIME_IL2CPP static void add_var (Buffer *buf, MonoDebugMethodJitInfo *jit, MonoType *t, MonoDebugVarInfo *var, MonoContext *ctx, MonoDomain *domain, gboolean as_vtype) { @@ -6763,7 +7863,9 @@ add_var (Buffer *buf, MonoDebugMethodJitInfo *jit, MonoType *t, MonoDebugVarInfo g_assert_not_reached (); } } +#endif +#ifndef RUNTIME_IL2CPP static void set_var (MonoType *t, MonoDebugVarInfo *var, MonoContext *ctx, MonoDomain *domain, guint8 *val, mgreg_t **reg_locations, MonoContext *restore_ctx) { @@ -6867,6 +7969,7 @@ set_var (MonoType *t, MonoDebugVarInfo *var, MonoContext *ctx, MonoDomain *domai g_assert_not_reached (); } } +#endif static void set_interp_var (MonoType *t, gpointer addr, guint8 *val_buf) @@ -6997,7 +8100,7 @@ clear_event_requests_for_assembly (MonoAssembly *assembly) static gboolean type_comes_from_assembly (gpointer klass, gpointer also_klass, gpointer assembly) { - return (mono_class_get_image ((MonoClass*)klass) == mono_assembly_get_image ((MonoAssembly*)assembly)); + return mono_type_in_image (mono_class_get_type ((MonoClass*)klass), mono_assembly_get_image ((MonoAssembly*)assembly)); } /* @@ -7005,6 +8108,7 @@ type_comes_from_assembly (gpointer klass, gpointer also_klass, gpointer assembly * * Clears types from loaded_classes for a given assembly */ +#ifndef RUNTIME_IL2CPP static void clear_types_for_assembly (MonoAssembly *assembly) { @@ -7021,6 +8125,7 @@ clear_types_for_assembly (MonoAssembly *assembly) g_hash_table_foreach_remove (info->loaded_classes, type_comes_from_assembly, assembly); mono_loader_unlock (); } +#endif static void add_thread (gpointer key, gpointer value, gpointer user_data) @@ -7045,8 +8150,10 @@ do_invoke_method (DebuggerTlsData *tls, Buffer *buf, InvokeData *invoke, guint8 MonoObject *this_arg, *res, *exc = NULL; MonoDomain *domain; guint8 *this_buf; -#ifdef MONO_ARCH_SOFT_DEBUG_SUPPORTED +#ifndef RUNTIME_IL2CPP +#ifdef MONO_ARCH_SOFT_DEBUG_SUPPORTED MonoLMFExt ext; +#endif #endif MonoStopwatch watch; @@ -7089,12 +8196,14 @@ do_invoke_method (DebuggerTlsData *tls, Buffer *buf, InvokeData *invoke, guint8 memset (this_buf, 0, mono_class_instance_size (m->klass)); p = tmp_p; } else { - err = decode_value (&m->klass->byval_arg, domain, this_buf, p, &p, end); + err = decode_value(&m->klass->byval_arg, domain, this_buf, p, &p, end); + if (err != ERR_NONE) return err; } } else { err = decode_value (&m->klass->byval_arg, domain, this_buf, p, &p, end); + if (err != ERR_NONE) return err; } @@ -7129,7 +8238,7 @@ do_invoke_method (DebuggerTlsData *tls, Buffer *buf, InvokeData *invoke, guint8 DEBUG_PRINTF (1, "[%p] Invoking method '%s' on receiver '%s'.\n", (gpointer) (gsize) mono_native_thread_id_get (), mono_method_full_name (m, TRUE), this_arg ? this_arg->vtable->klass->name : ""); - if (this_arg && this_arg->vtable->domain != domain) + if (this_arg && VM_OBJECT_GET_DOMAIN(this_arg) != domain) NOT_IMPLEMENTED; if (!m->klass->valuetype && !(m->flags & METHOD_ATTRIBUTE_STATIC) && !this_arg) { @@ -7161,7 +8270,7 @@ do_invoke_method (DebuggerTlsData *tls, Buffer *buf, InvokeData *invoke, guint8 err = decode_value (sig->params [i], domain, (guint8*)&args [i], p, &p, end); if (err != ERR_NONE) break; - if (args [i] && ((MonoObject*)args [i])->vtable->domain != domain) + if (args [i] && VM_OBJECT_GET_DOMAIN(((MonoObject*)args [i])) != domain) NOT_IMPLEMENTED; if (sig->params [i]->byref) { @@ -7176,8 +8285,12 @@ do_invoke_method (DebuggerTlsData *tls, Buffer *buf, InvokeData *invoke, guint8 if (err != ERR_NONE) break; if (mono_class_is_nullable (arg_class)) { +#ifndef RUNTIME_IL2CPP args [i] = mono_nullable_box (arg_buf [i], arg_class, &error); mono_error_assert_ok (&error); +#else + g_assert_not_reached (); +#endif } else { args [i] = arg_buf [i]; } @@ -7195,7 +8308,8 @@ do_invoke_method (DebuggerTlsData *tls, Buffer *buf, InvokeData *invoke, guint8 /* * Add an LMF frame to link the stack frames on the invoke method with our caller. */ -#ifdef MONO_ARCH_SOFT_DEBUG_SUPPORTED +#ifndef RUNTIME_IL2CPP +#ifdef MONO_ARCH_SOFT_DEBUG_SUPPORTED if (invoke->has_ctx) { /* Setup our lmf */ memset (&ext, 0, sizeof (ext)); @@ -7204,10 +8318,11 @@ do_invoke_method (DebuggerTlsData *tls, Buffer *buf, InvokeData *invoke, guint8 mono_push_lmf (&ext); } +#endif #endif mono_stopwatch_start (&watch); - res = mono_runtime_try_invoke (m, m->klass->valuetype ? (gpointer) this_buf : (gpointer) this_arg, args, &exc, &error); + res = mono_runtime_try_invoke (m, m->klass->valuetype ? (gpointer)this_buf : (gpointer)this_arg, args, &exc, &error); if (!mono_error_ok (&error) && exc == NULL) { exc = (MonoObject*) mono_error_convert_to_exception (&error); } else { @@ -7217,7 +8332,7 @@ do_invoke_method (DebuggerTlsData *tls, Buffer *buf, InvokeData *invoke, guint8 DEBUG_PRINTF (1, "[%p] Invoke result: %p, exc: %s, time: %ld ms.\n", (gpointer) (gsize) mono_native_thread_id_get (), res, exc ? exc->vtable->klass->name : NULL, (long)mono_stopwatch_elapsed_ms (&watch)); if (exc) { buffer_add_byte (buf, 0); - buffer_add_value (buf, &mono_defaults.object_class->byval_arg, &exc, domain); + buffer_add_value (buf, &VM_DEFAULTS_OBJECT_CLASS->byval_arg, &exc, domain); } else { gboolean out_this = FALSE; gboolean out_args = FALSE; @@ -7227,16 +8342,16 @@ do_invoke_method (DebuggerTlsData *tls, Buffer *buf, InvokeData *invoke, guint8 if ((invoke->flags & INVOKE_FLAG_RETURN_OUT_ARGS) && CHECK_PROTOCOL_VERSION (2, 35)) out_args = TRUE; buffer_add_byte (buf, 1 + (out_this ? 2 : 0) + (out_args ? 4 : 0)); - if (m->string_ctor) { + if (VM_METHOD_IS_STRING_CTOR(m)) { buffer_add_value (buf, &mono_get_string_class ()->byval_arg, &res, domain); - } else if (sig->ret->type == MONO_TYPE_VOID && !m->string_ctor) { + } else if ( sig->ret->type == MONO_TYPE_VOID && !VM_METHOD_IS_STRING_CTOR(m)) { if (!strcmp (m->name, ".ctor")) { if (!m->klass->valuetype) - buffer_add_value (buf, &mono_defaults.object_class->byval_arg, &this_arg, domain); + buffer_add_value (buf, &VM_DEFAULTS_OBJECT_CLASS->byval_arg, &this_arg, domain); else buffer_add_value (buf, &m->klass->byval_arg, this_buf, domain); } else { - buffer_add_value (buf, &mono_defaults.void_class->byval_arg, NULL, domain); + buffer_add_value (buf, &VM_DEFAULTS_VOID_CLASS->byval_arg, NULL, domain); } } else if (MONO_TYPE_IS_REFERENCE (sig->ret)) { buffer_add_value (buf, sig->ret, &res, domain); @@ -7274,9 +8389,11 @@ do_invoke_method (DebuggerTlsData *tls, Buffer *buf, InvokeData *invoke, guint8 tls->disable_breakpoints = FALSE; +#ifndef RUNTIME_IL2CPP #ifdef MONO_ARCH_SOFT_DEBUG_SUPPORTED if (invoke->has_ctx) mono_pop_lmf ((MonoLMF*)&ext); +#endif #endif *endp = p; @@ -7411,13 +8528,20 @@ get_source_files_for_type (MonoClass *klass) { gpointer iter = NULL; MonoMethod *method; +#ifndef RUNTIME_IL2CPP MonoDebugSourceInfo *sinfo; +#endif GPtrArray *files; int i, j; files = g_ptr_array_new (); - while ((method = mono_class_get_methods (klass, &iter))) { +#ifdef RUNTIME_IL2CPP + const char **fileNames = il2cpp_get_source_files_for_type(klass, &i); + for (j = 0; j < i; ++j) + g_ptr_array_add(files, g_strdup(fileNames[j])); +#else + while ((method = mono_class_get_methods(klass, &iter))) { MonoDebugMethodInfo *minfo = mono_debug_lookup_method (method); GPtrArray *source_file_list; @@ -7434,6 +8558,7 @@ get_source_files_for_type (MonoClass *klass) g_ptr_array_free (source_file_list, TRUE); } } +#endif return files; } @@ -7481,6 +8606,8 @@ vm_commands (int command, int id, guint8 *p, guint8 *end, Buffer *buf) clear_suspended_objs (); break; case CMD_VM_DISPOSE: + suspend_vm (); + wait_for_suspend (); /* Clear all event requests */ mono_loader_lock (); while (event_requests->len > 0) { @@ -7532,7 +8659,7 @@ vm_commands (int command, int id, guint8 *p, guint8 *end, Buffer *buf) wait_for_suspend (); #ifdef TRY_MANAGED_SYSTEM_ENVIRONMENT_EXIT - env_class = mono_class_try_load_from_name (mono_defaults.corlib, "System", "Environment"); + env_class = mono_class_try_load_from_name (VM_DEFAULTS_CORLIB_IMAGE, "System", "Environment"); if (env_class) exit_method = mono_class_get_method_from_name (env_class, "Exit", 1); #endif @@ -7719,7 +8846,7 @@ vm_commands (int command, int id, guint8 *p, guint8 *end, Buffer *buf) mono_loader_lock (); g_hash_table_iter_init (&iter, domains); while (g_hash_table_iter_next (&iter, NULL, (void**)&domain)) { - AgentDomainInfo *info = (AgentDomainInfo *)domain_jit_info (domain)->agent_info; + AgentDomainInfo *info = (AgentDomainInfo *)VM_DOMAIN_GET_AGENT_INFO(domain); /* Update 'source_file_to_class' cache */ g_hash_table_iter_init (&kiter, info->loaded_classes); @@ -7820,10 +8947,11 @@ vm_commands (int command, int id, guint8 *p, guint8 *end, Buffer *buf) GSList *tmp; mono_domain_assemblies_lock (domain); - for (tmp = domain->domain_assemblies; tmp; tmp = tmp->next) { - ass = (MonoAssembly *)tmp->data; - - if (ass->image) { + void *iter = NULL; + while (ass = mono_domain_get_assemblies_iter (domain, &iter)) + { + if (ass->image) + { MonoError probe_type_error; /* FIXME really okay to call while holding locks? */ t = mono_reflection_get_type_checked (ass->image, ass->image, &info, ignore_case, &type_resolve, &probe_type_error); @@ -7935,7 +9063,7 @@ event_commands (int command, guint8 *p, guint8 *end, Buffer *buf) if (exc_class) { req->modifiers [i].data.exc_class = exc_class; - if (!mono_class_is_assignable_from (mono_defaults.exception_class, exc_class)) { + if (!mono_class_is_assignable_from (VM_DEFAULTS_EXCEPTION_CLASS, exc_class)) { g_free (req); return ERR_INVALID_ARGUMENT; } @@ -8006,6 +9134,21 @@ event_commands (int command, guint8 *p, guint8 *end, Buffer *buf) return err; } +#if RUNTIME_IL2CPP + { + DebuggerTlsData* tls; + mono_loader_lock(); + tls = (DebuggerTlsData *)mono_g_hash_table_lookup(thread_to_tls, THREAD_TO_INTERNAL(step_thread)); + mono_loader_unlock(); + + if (tls->il2cpp_context.frameCount == 1 && depth == STEP_DEPTH_OUT) + { + g_free(req); + return ERR_NONE; + } + } +#endif + err = ss_create (THREAD_TO_INTERNAL (step_thread), size, depth, filter, req); if (err != ERR_NONE) { g_free (req); @@ -8097,6 +9240,7 @@ domain_commands (int command, guint8 *p, guint8 *end, Buffer *buf) { ErrorCode err; MonoDomain *domain; + void *iter = NULL; switch (command) { case CMD_APPDOMAIN_GET_ROOT_DOMAIN: { @@ -8120,12 +9264,20 @@ domain_commands (int command, guint8 *p, guint8 *end, Buffer *buf) return err; mono_loader_lock (); count = 0; +#ifndef RUNTIME_IL2CPP for (tmp = domain->domain_assemblies; tmp; tmp = tmp->next) { +#else + while(il2cpp_domain_get_assemblies_iter(domain, &iter)) { +#endif //RUNTIME_IL2CPP count ++; } buffer_add_int (buf, count); +#ifndef RUNTIME_IL2CPP for (tmp = domain->domain_assemblies; tmp; tmp = tmp->next) { ass = (MonoAssembly *)tmp->data; +#else + while(ass = il2cpp_domain_get_assemblies_iter(domain, &iter)) { +#endif //RUNTIME_IL2CPP buffer_add_assemblyid (buf, domain, ass); } mono_loader_unlock (); @@ -8135,8 +9287,11 @@ domain_commands (int command, guint8 *p, guint8 *end, Buffer *buf) domain = decode_domainid (p, &p, end, NULL, &err); if (err != ERR_NONE) return err; - +#ifndef RUNTIME_IL2CPP buffer_add_assemblyid (buf, domain, domain->entry_assembly); +#else + buffer_add_assemblyid (buf, domain, NULL); +#endif //RUNTIME_IL2CPP break; } case CMD_APPDOMAIN_GET_CORLIB: { @@ -8185,7 +9340,7 @@ domain_commands (int command, guint8 *p, guint8 *end, Buffer *buf) o = mono_object_new_checked (domain, klass, &error); mono_error_assert_ok (&error); - err = decode_value (&klass->byval_arg, domain, (guint8 *)mono_object_unbox (o), p, &p, end); + err = decode_value (mono_class_get_type(klass), domain, (guint8 *)mono_object_unbox (o), p, &p, end); if (err != ERR_NONE) return err; @@ -8202,6 +9357,14 @@ domain_commands (int command, guint8 *p, guint8 *end, Buffer *buf) static ErrorCode get_assembly_object_command (MonoDomain *domain, MonoAssembly *ass, Buffer *buf, MonoError *error) { +#ifdef RUNTIME_IL2CPP + MonoReflectionAssemblyHandle o = il2cpp_mono_assembly_get_object_handle(domain, ass, error); + if (o == NULL) { + return ERR_INVALID_OBJECT; + } + buffer_add_objid(buf, (MonoObject*)o); + return ERR_NONE; +#else HANDLE_FUNCTION_ENTER(); ErrorCode err = ERR_NONE; error_init (error); @@ -8213,6 +9376,7 @@ get_assembly_object_command (MonoDomain *domain, MonoAssembly *ass, Buffer *buf, buffer_add_objid (buf, MONO_HANDLE_RAW (MONO_HANDLE_CAST (MonoObject, o))); leave: HANDLE_FUNCTION_RETURN_VAL (err); +#endif } @@ -8230,7 +9394,7 @@ assembly_commands (int command, guint8 *p, guint8 *end, Buffer *buf) switch (command) { case CMD_ASSEMBLY_GET_LOCATION: { buffer_add_string (buf, mono_image_get_filename (ass->image)); - break; + break; } case CMD_ASSEMBLY_GET_ENTRY_POINT: { guint32 token; @@ -8239,6 +9403,13 @@ assembly_commands (int command, guint8 *p, guint8 *end, Buffer *buf) if (ass->image->dynamic) { buffer_add_id (buf, 0); } else { +#ifdef RUNTIME_IL2CPP + m = il2cpp_mono_image_get_entry_point(ass->image); + if (m == NULL) + buffer_add_id (buf, 0); + else + buffer_add_methodid (buf, domain, m); +#else token = mono_image_get_entry_point (ass->image); if (token == 0) { buffer_add_id (buf, 0); @@ -8249,6 +9420,7 @@ assembly_commands (int command, guint8 *p, guint8 *end, Buffer *buf) mono_error_cleanup (&error); /* FIXME don't swallow the error */ buffer_add_methodid (buf, domain, m); } +#endif // RUNTIME_IL2CPP } break; } @@ -8304,15 +9476,17 @@ assembly_commands (int command, guint8 *p, guint8 *end, Buffer *buf) case CMD_ASSEMBLY_GET_NAME: { gchar *name; MonoAssembly *mass = ass; - +#ifdef RUNTIME_IL2CPP + name = il2cpp_assembly_get_full_name(mass); +#else name = g_strdup_printf ( "%s, Version=%d.%d.%d.%d, Culture=%s, PublicKeyToken=%s%s", mass->aname.name, mass->aname.major, mass->aname.minor, mass->aname.build, mass->aname.revision, - mass->aname.culture && *mass->aname.culture? mass->aname.culture: "neutral", - mass->aname.public_key_token [0] ? (char *)mass->aname.public_key_token : "null", + mass->aname.culture && *mass->aname.culture ? mass->aname.culture : "neutral", + mass->aname.public_key_token[0] ? (char *)mass->aname.public_key_token : "null", (mass->aname.flags & ASSEMBLYREF_RETARGETABLE_FLAG) ? ", Retargetable=Yes" : ""); - +#endif buffer_add_string (buf, name); g_free (name); break; @@ -8337,12 +9511,12 @@ module_commands (int command, guint8 *p, guint8 *end, Buffer *buf) basename = g_path_get_basename (image->name); buffer_add_string (buf, basename); // name - buffer_add_string (buf, image->module_name); // scopename + buffer_add_string (buf, VM_IMAGE_GET_MODULE_NAME(image)); // scopename buffer_add_string (buf, image->name); // fqname buffer_add_string (buf, mono_image_get_guid (image)); // guid buffer_add_assemblyid (buf, domain, image->assembly); // assembly g_free (basename); - break; + break; } default: return ERR_NOT_IMPLEMENTED; @@ -8388,6 +9562,7 @@ buffer_add_cattr_arg (Buffer *buf, MonoType *t, MonoDomain *domain, MonoObject * buffer_add_value (buf, t, mono_object_unbox (val), domain); } +#ifndef RUNTIME_IL2CPP static ErrorCode buffer_add_cattrs (Buffer *buf, MonoDomain *domain, MonoImage *image, MonoClass *attr_klass, MonoCustomAttrInfo *cinfo) { @@ -8464,6 +9639,7 @@ buffer_add_cattrs (Buffer *buf, MonoDomain *domain, MonoImage *image, MonoClass return ERR_NONE; } +#endif //RUNTIME_IL2CPP /* FIXME: Code duplication with icall.c */ static void @@ -8476,8 +9652,8 @@ collect_interfaces (MonoClass *klass, GHashTable *ifaces, MonoError *error) if (!mono_error_ok (error)) return; - for (i = 0; i < klass->interface_count; i++) { - ic = klass->interfaces [i]; + gpointer iter = NULL; + while (ic = mono_class_get_interfaces(klass, &iter)) { g_hash_table_insert (ifaces, ic, ic); collect_interfaces (ic, ifaces, error); @@ -8492,6 +9668,7 @@ type_commands_internal (int command, MonoClass *klass, MonoDomain *domain, guint MonoError error; MonoClass *nested; MonoType *type; + int type_tag; gpointer iter; guint8 b; int nnested; @@ -8500,34 +9677,36 @@ type_commands_internal (int command, MonoClass *klass, MonoDomain *domain, guint switch (command) { case CMD_TYPE_GET_INFO: { - buffer_add_string (buf, klass->name_space); - buffer_add_string (buf, klass->name); + buffer_add_string (buf, mono_class_get_namespace(klass)); + buffer_add_string (buf, mono_class_get_name(klass)); // FIXME: byref - name = mono_type_get_name_full (&klass->byval_arg, MONO_TYPE_NAME_FORMAT_FULL_NAME); + type = mono_class_get_type(klass); + name = mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_FULL_NAME); buffer_add_string (buf, name); g_free (name); - buffer_add_assemblyid (buf, domain, klass->image->assembly); - buffer_add_moduleid (buf, domain, klass->image); - buffer_add_typeid (buf, domain, klass->parent); - if (klass->rank || klass->byval_arg.type == MONO_TYPE_PTR) - buffer_add_typeid (buf, domain, klass->element_class); + buffer_add_assemblyid (buf, domain, mono_image_get_assembly(mono_class_get_image(klass))); + buffer_add_moduleid (buf, domain, mono_class_get_image(klass)); + buffer_add_typeid (buf, domain, mono_class_get_parent(klass)); + + type_tag = mono_type_get_type(type); + if (mono_class_get_rank(klass) || type_tag == MONO_TYPE_PTR) + buffer_add_typeid (buf, domain, mono_class_get_element_class(klass)); else buffer_add_id (buf, 0); - buffer_add_int (buf, klass->type_token); - buffer_add_byte (buf, klass->rank); + buffer_add_int (buf, mono_class_get_type_token(klass)); + buffer_add_byte (buf, mono_class_get_rank(klass)); buffer_add_int (buf, mono_class_get_flags (klass)); b = 0; - type = &klass->byval_arg; // FIXME: Can't decide whenever a class represents a byref type if (FALSE) b |= (1 << 0); - if (type->type == MONO_TYPE_PTR) + if (type_tag == MONO_TYPE_PTR) b |= (1 << 1); - if (!type->byref && (((type->type >= MONO_TYPE_BOOLEAN) && (type->type <= MONO_TYPE_R8)) || (type->type == MONO_TYPE_I) || (type->type == MONO_TYPE_U))) + if (!mono_type_is_byref(type) && (((type_tag >= MONO_TYPE_BOOLEAN) && (type_tag <= MONO_TYPE_R8)) || (type_tag == MONO_TYPE_I) || (type_tag == MONO_TYPE_U))) b |= (1 << 2); - if (type->type == MONO_TYPE_VALUETYPE) + if (type_tag == MONO_TYPE_VALUETYPE) b |= (1 << 3); - if (klass->enumtype) + if (mono_class_is_enum(klass)) b |= (1 << 4); if (mono_class_is_gtd (klass)) b |= (1 << 5); @@ -8546,7 +9725,7 @@ type_commands_internal (int command, MonoClass *klass, MonoDomain *domain, guint if (mono_class_is_gtd (klass)) buffer_add_typeid (buf, domain, klass); else if (mono_class_is_ginst (klass)) - buffer_add_typeid (buf, domain, mono_class_get_generic_class (klass)->container_class); + buffer_add_typeid (buf, domain, VM_GENERIC_CLASS_GET_CONTAINER_CLASS(mono_class_get_generic_class (klass))); else buffer_add_id (buf, 0); } @@ -8554,12 +9733,12 @@ type_commands_internal (int command, MonoClass *klass, MonoDomain *domain, guint int count, i; if (mono_class_is_ginst (klass)) { - MonoGenericInst *inst = mono_class_get_generic_class (klass)->context.class_inst; + MonoGenericInst *inst = mono_class_get_generic_class(klass)->context.class_inst; count = inst->type_argc; buffer_add_int (buf, count); for (i = 0; i < count; i++) - buffer_add_typeid (buf, domain, mono_class_from_mono_type (inst->type_argv [i])); + buffer_add_typeid (buf, domain, mono_class_from_mono_type (inst->type_argv[i])); } else if (mono_class_is_gtd (klass)) { MonoGenericContainer *container = mono_class_get_generic_container (klass); MonoClass *pklass; @@ -8608,8 +9787,8 @@ type_commands_internal (int command, MonoClass *klass, MonoDomain *domain, guint while ((f = mono_class_get_fields (klass, &iter))) { buffer_add_fieldid (buf, domain, f); buffer_add_string (buf, f->name); - buffer_add_typeid (buf, domain, mono_class_from_mono_type (f->type)); - buffer_add_int (buf, f->type->attrs); + buffer_add_typeid (buf, domain, mono_class_from_mono_type (mono_field_get_type(f))); + buffer_add_int (buf, mono_field_get_type(f)->attrs); i ++; } g_assert (i == nfields); @@ -8637,6 +9816,7 @@ type_commands_internal (int command, MonoClass *klass, MonoDomain *domain, guint break; } case CMD_TYPE_GET_CATTRS: { +#ifndef RUNTIME_IL2CPP MonoClass *attr_klass; MonoCustomAttrInfo *cinfo; @@ -8651,12 +9831,17 @@ type_commands_internal (int command, MonoClass *klass, MonoDomain *domain, guint return ERR_LOADER_ERROR; } - err = buffer_add_cattrs (buf, domain, klass->image, attr_klass, cinfo); + err = buffer_add_cattrs (buf, domain, mono_class_get_image(klass), attr_klass, cinfo); if (err != ERR_NONE) return err; break; +#else + buffer_add_int (buf, 0); + return ERR_NONE; +#endif //RUNTIME_IL2CPP } case CMD_TYPE_GET_FIELD_CATTRS: { +#ifndef RUNTIME_IL2CPP MonoClass *attr_klass; MonoCustomAttrInfo *cinfo; MonoClassField *field; @@ -8674,12 +9859,17 @@ type_commands_internal (int command, MonoClass *klass, MonoDomain *domain, guint return ERR_LOADER_ERROR; } - err = buffer_add_cattrs (buf, domain, klass->image, attr_klass, cinfo); + err = buffer_add_cattrs (buf, domain, mono_class_get_image(klass), attr_klass, cinfo); if (err != ERR_NONE) return err; break; +#else + buffer_add_int (buf, 0); + return ERR_NONE; +#endif //RUNTIME_IL2CPP } case CMD_TYPE_GET_PROPERTY_CATTRS: { +#ifndef RUNTIME_IL2CPP MonoClass *attr_klass; MonoCustomAttrInfo *cinfo; MonoProperty *prop; @@ -8697,10 +9887,14 @@ type_commands_internal (int command, MonoClass *klass, MonoDomain *domain, guint return ERR_LOADER_ERROR; } - err = buffer_add_cattrs (buf, domain, klass->image, attr_klass, cinfo); + err = buffer_add_cattrs (buf, domain, mono_class_get_image(klass), attr_klass, cinfo); if (err != ERR_NONE) return err; break; +#else + buffer_add_int (buf, 0); + return ERR_NONE; +#endif //RUNTIME_IL2CPP } case CMD_TYPE_GET_VALUES: case CMD_TYPE_GET_VALUES_2: { @@ -8733,16 +9927,21 @@ type_commands_internal (int command, MonoClass *klass, MonoDomain *domain, guint if (!(f->type->attrs & FIELD_ATTRIBUTE_STATIC)) return ERR_INVALID_FIELDID; + +#ifdef RUNTIME_IL2CPP + if (!thread && f->offset == THREAD_STATIC_FIELD_OFFSET) + return ERR_INVALID_FIELDID; +#else special_static_type = mono_class_field_get_special_static_type (f); if (special_static_type != SPECIAL_STATIC_NONE) { if (!(thread && special_static_type == SPECIAL_STATIC_THREAD)) return ERR_INVALID_FIELDID; } - +#endif /* Check that the field belongs to the object */ found = FALSE; for (k = klass; k; k = k->parent) { - if (k == f->parent) { + if (k == f->parent) { found = TRUE; break; } @@ -8774,15 +9973,15 @@ type_commands_internal (int command, MonoClass *klass, MonoDomain *domain, guint if (err != ERR_NONE) return err; - if (!(f->type->attrs & FIELD_ATTRIBUTE_STATIC)) + if (!(mono_field_get_type(f)->attrs & FIELD_ATTRIBUTE_STATIC)) return ERR_INVALID_FIELDID; if (mono_class_field_is_special_static (f)) return ERR_INVALID_FIELDID; /* Check that the field belongs to the object */ found = FALSE; - for (k = klass; k; k = k->parent) { - if (k == f->parent) { + for (k = klass; k; k = mono_class_get_parent(k)) { + if (k == mono_field_get_parent(f)) { found = TRUE; break; } @@ -8792,14 +9991,14 @@ type_commands_internal (int command, MonoClass *klass, MonoDomain *domain, guint // FIXME: Check for literal/const - vtable = mono_class_vtable (domain, f->parent); - val = (guint8 *)g_malloc (mono_class_instance_size (mono_class_from_mono_type (f->type))); - err = decode_value (f->type, domain, val, p, &p, end); + vtable = mono_class_vtable (domain, mono_field_get_parent(f)); + val = (guint8 *)g_malloc (mono_class_instance_size (mono_class_from_mono_type (mono_field_get_type(f)))); + err = decode_value (mono_field_get_type(f), domain, val, p, &p, end); if (err != ERR_NONE) { g_free (val); return err; } - if (MONO_TYPE_IS_REFERENCE (f->type)) + if (MONO_TYPE_IS_REFERENCE (mono_field_get_type(f))) mono_field_static_set_value (vtable, f, *(gpointer*)val); else mono_field_static_set_value (vtable, f, val); @@ -8808,7 +10007,7 @@ type_commands_internal (int command, MonoClass *klass, MonoDomain *domain, guint break; } case CMD_TYPE_GET_OBJECT: { - MonoObject *o = (MonoObject*)mono_type_get_object_checked (domain, &klass->byval_arg, &error); + MonoObject *o = (MonoObject*)mono_type_get_object_checked (domain, mono_class_get_type(klass), &error); if (!mono_error_ok (&error)) { mono_error_cleanup (&error); return ERR_INVALID_OBJECT; @@ -8912,11 +10111,11 @@ type_commands_internal (int command, MonoClass *klass, MonoDomain *domain, guint iclass = decode_typeid (p, &p, end, NULL, &err); if (err != ERR_NONE) return err; - +#ifndef RUNTIME_IL2CPP ioffset = mono_class_interface_offset_with_variance (klass, iclass, &variance_used); if (ioffset == -1) return ERR_INVALID_ARGUMENT; - +#endif nmethods = mono_class_num_methods (iclass); buffer_add_int (buf, nmethods); @@ -8924,8 +10123,13 @@ type_commands_internal (int command, MonoClass *klass, MonoDomain *domain, guint while ((method = mono_class_get_methods (iclass, &iter))) { buffer_add_methodid (buf, domain, method); } + for (i = 0; i < nmethods; ++i) - buffer_add_methodid (buf, domain, klass->vtable [i + ioffset]); +#ifdef RUNTIME_IL2CPP + buffer_add_methodid(buf, domain, il2cpp_get_interface_method(klass, iclass, i)); +#else + buffer_add_methodid(buf, domain, klass->vtable[i + ioffset]); +#endif } break; } @@ -8933,7 +10137,11 @@ type_commands_internal (int command, MonoClass *klass, MonoDomain *domain, guint MonoVTable *vtable = mono_class_vtable (domain, klass); if (vtable) +#ifndef RUNTIME_IL2CPP buffer_add_int (buf, (vtable->initialized || vtable->init_failed) ? 1 : 0); +#else + buffer_add_int (buf, klass->initialized ? 1 : 0); +#endif else buffer_add_int (buf, 0); break; @@ -8947,6 +10155,13 @@ type_commands_internal (int command, MonoClass *klass, MonoDomain *domain, guint buffer_add_objid (buf, obj); break; } + case CMD_TYPE_GET_VALUE_SIZE: { + int32_t value_size; + + value_size = mono_class_value_size (klass, NULL); + buffer_add_int (buf, value_size); + break; + } default: return ERR_NOT_IMPLEMENTED; } @@ -8970,13 +10185,90 @@ type_commands (int command, guint8 *p, guint8 *end, Buffer *buf) mono_domain_set (domain, TRUE); - err = type_commands_internal (command, klass, domain, p, end, buf); + err = type_commands_internal (command, klass, domain, p, end, buf); + + mono_domain_set (old_domain, TRUE); + + return err; +} + +#ifdef RUNTIME_IL2CPP + +gint CompareSeqPointsByIlOffset(gconstpointer a, gconstpointer b) +{ + Il2CppSequencePoint *seqPointA = *(Il2CppSequencePoint**)a; + Il2CppSequencePoint *seqPointB = *(Il2CppSequencePoint**)b; + + if (seqPointA->ilOffset < seqPointB->ilOffset) + return -1; + else if (seqPointA->ilOffset > seqPointB->ilOffset) + return 1; + else + return 0; +} + +static void GetSequencePointsAndSourceFilesUniqueSequencePoints(MonoMethod* method, GPtrArray** sequencePoints, GPtrArray** uniqueFileSequencePoints, GArray** uniqueFileSequencePointIndices) +{ + int i; + *sequencePoints = g_ptr_array_new(); + *uniqueFileSequencePoints = g_ptr_array_new(); + *uniqueFileSequencePointIndices = g_array_new(FALSE, FALSE, sizeof(int)); + + void *seqPointIter = NULL; + Il2CppSequencePoint *seqPoint; + while (seqPoint = il2cpp_get_method_sequence_points(method, &seqPointIter)) + { + if(seqPoint->ilOffset == METHOD_ENTRY_IL_OFFSET || seqPoint->ilOffset == METHOD_EXIT_IL_OFFSET) + continue; + + if (il2cpp_mono_methods_match(il2cpp_get_seq_point_method(seqPoint), method)) + g_ptr_array_add(*sequencePoints, seqPoint); + } + + g_ptr_array_sort(*sequencePoints, CompareSeqPointsByIlOffset); + + for(i=0;i < (*sequencePoints)->len;++i) + { + int j; + seqPoint = (Il2CppSequencePoint*)(*sequencePoints)->pdata[i]; + + for (j = 0; j < (*uniqueFileSequencePoints)->len; j++) + { + Il2CppSequencePoint* uniqueSequencePoint = g_ptr_array_index(*uniqueFileSequencePoints, j); + if (uniqueSequencePoint->sourceFileIndex == seqPoint->sourceFileIndex) + break; + } + + if (j == (*uniqueFileSequencePoints)->len) + g_ptr_array_add(*uniqueFileSequencePoints, seqPoint); + + int index = (*uniqueFileSequencePoints)->len - 1; + g_array_append_val(*uniqueFileSequencePointIndices, index); + } +} - mono_domain_set (old_domain, TRUE); +static void GetExecutionContextAndHeaderInfo(MonoMethod* method, uint32_t* executionContextInfoCount, const Il2CppMethodExecutionContextInfo **executionContextInfo, const Il2CppMethodHeaderInfo **headerInfo, const Il2CppMethodScope **scopes) +{ + void *seqPointIter = NULL; + Il2CppSequencePoint *seqPoint; + while (seqPoint = il2cpp_get_method_sequence_points(method, &seqPointIter)) + { + if (il2cpp_mono_methods_match(il2cpp_get_seq_point_method(seqPoint), method)) + { + Il2CppMethodExecutionContextInfoIndex *index = &g_il2cpp_metadata->methodExecutionContextInfoIndexes[seqPoint->methodIndex]; + *executionContextInfoCount = index->count; + *executionContextInfo = &g_il2cpp_metadata->methodExecutionContextInfos[index->tableIndex][index->startIndex]; + *headerInfo = &g_il2cpp_metadata->methodHeaderInfos[seqPoint->methodIndex]; + *scopes = &g_il2cpp_metadata->methodScopes[(*headerInfo)->startScope]; + return; + } + } - return err; + g_assert(FALSE); // shouldn't be ever reached } +#endif // RUNTIME_IL2CPP + static ErrorCode method_commands_internal (int command, MonoMethod *method, MonoDomain *domain, guint8 *p, guint8 *end, Buffer *buf) { @@ -8985,18 +10277,20 @@ method_commands_internal (int command, MonoMethod *method, MonoDomain *domain, g switch (command) { case CMD_METHOD_GET_NAME: { - buffer_add_string (buf, method->name); - break; + buffer_add_string (buf, mono_method_get_name(method)); + break; } case CMD_METHOD_GET_DECLARING_TYPE: { - buffer_add_typeid (buf, domain, method->klass); + buffer_add_typeid (buf, domain, mono_method_get_class(method)); break; } case CMD_METHOD_GET_DEBUG_INFO: { MonoError error; + int i, j; +#ifndef RUNTIME_IL2CPP MonoDebugMethodInfo *minfo; char *source_file; - int i, j, n_il_offsets; + int n_il_offsets; int *source_files; GPtrArray *source_file_list; MonoSymSeqPoint *sym_seq_points; @@ -9061,6 +10355,67 @@ method_commands_internal (int command, MonoMethod *method, MonoDomain *domain, g g_free (sym_seq_points); g_ptr_array_free (source_file_list, TRUE); mono_metadata_free_mh (header); +#else + GPtrArray* sequencePoints; + GPtrArray* uniqueFileSequencePoints; + GArray* uniqueFileSequencePointIndices; + GetSequencePointsAndSourceFilesUniqueSequencePoints(method, &sequencePoints, &uniqueFileSequencePoints, &uniqueFileSequencePointIndices); + + buffer_add_int(buf, 0); + if (CHECK_PROTOCOL_VERSION(2, 13)) { + buffer_add_int(buf, uniqueFileSequencePoints->len); + for (i = 0; i < uniqueFileSequencePoints->len; ++i) { + Il2CppSequencePoint* sequencePoint = g_ptr_array_index(uniqueFileSequencePoints, i); + buffer_add_string(buf, g_il2cpp_metadata->sequencePointSourceFiles[sequencePoint->sourceFileIndex].file); + if (CHECK_PROTOCOL_VERSION(2, 14)) { + buffer_add_data(buf, g_il2cpp_metadata->sequencePointSourceFiles[sequencePoint->sourceFileIndex].hash, 16); + } + } + } + else { + if (uniqueFileSequencePoints->len > 0) { + buffer_add_string(buf, g_il2cpp_metadata->sequencePointSourceFiles[((Il2CppSequencePoint*)g_ptr_array_index(uniqueFileSequencePoints, 0))->sourceFileIndex].file); + } else { + buffer_add_string(buf, ""); + } + } + + int numSeqPoints = 0; + + for (i = 0; i < sequencePoints->len; ++i) { + Il2CppSequencePoint* sequencePoint = g_ptr_array_index(sequencePoints, i); + if (sequencePoint->kind == kSequencePointKind_StepOut) + continue; + else + ++numSeqPoints; + } + + buffer_add_int(buf, numSeqPoints); + DEBUG_PRINTF(10, "Line number table for method %s:\n", mono_method_full_name(method, TRUE)); + for (i = 0; i < sequencePoints->len; ++i) { + Il2CppSequencePoint* sequencePoint = g_ptr_array_index(sequencePoints, i); + + if (sequencePoint->kind == kSequencePointKind_StepOut) + continue; + + DEBUG_PRINTF(10, "IL%x -> %s:%d %d %d %d\n", sequencePoint->ilOffset, g_il2cpp_metadata->sequencePointSourceFiles[sequencePoint->sourceFileIndex], + sequencePoint->lineStart, sequencePoint->columnStart, sequencePoint->lineEnd, sequencePoint->columnEnd); + buffer_add_int(buf, sequencePoint->ilOffset); + buffer_add_int(buf, sequencePoint->lineStart); + if (CHECK_PROTOCOL_VERSION(2, 13)) + buffer_add_int(buf, g_array_index(uniqueFileSequencePointIndices, int, i)); + if (CHECK_PROTOCOL_VERSION(2, 19)) + buffer_add_int(buf, sequencePoint->columnStart); + if (CHECK_PROTOCOL_VERSION(2, 32)) { + buffer_add_int(buf, sequencePoint->lineEnd); + buffer_add_int(buf, sequencePoint->columnEnd); + } + } + + g_ptr_array_free(sequencePoints, TRUE); + g_ptr_array_free(uniqueFileSequencePoints, TRUE); + g_array_free(uniqueFileSequencePointIndices, TRUE); +#endif break; } case CMD_METHOD_GET_PARAM_INFO: { @@ -9091,6 +10446,7 @@ method_commands_internal (int command, MonoMethod *method, MonoDomain *domain, g } case CMD_METHOD_GET_LOCALS_INFO: { MonoError error; +#ifndef RUNTIME_IL2CPP int i, num_locals; MonoDebugLocalsInfo *locals; int *locals_map = NULL; @@ -9164,30 +10520,86 @@ method_commands_internal (int command, MonoMethod *method, MonoDomain *domain, g if (locals) mono_debug_free_locals (locals); g_free (locals_map); +#else + uint32_t executionInfoCount, localVariableCount = 0, i; + const Il2CppMethodExecutionContextInfo* executionContextInfo; + const Il2CppMethodHeaderInfo* headerInfo; + const Il2CppMethodScope* scopes; + + GetExecutionContextAndHeaderInfo(method, &executionInfoCount, &executionContextInfo, &headerInfo, &scopes); + + if (CHECK_PROTOCOL_VERSION(2, 43)) { + if (headerInfo) + { + buffer_add_int(buf, headerInfo->numScopes); + for (i = 0; i < headerInfo->numScopes; ++i) + { + buffer_add_int(buf, scopes[i].startOffset); + buffer_add_int(buf, scopes[i].endOffset); + } + } + else + { + buffer_add_int(buf, 0); + } + } + for (i = 0; i < executionInfoCount; i++) + { + if (executionContextInfo[i].variableKind == kMethodVariableKind_LocalVariable) + localVariableCount++; + } + + buffer_add_int(buf, localVariableCount); + + for (i = 0; i < executionInfoCount; i++) + { + if (executionContextInfo[i].variableKind == kMethodVariableKind_LocalVariable) + buffer_add_typeid(buf, domain, mono_class_from_mono_type(il2cpp_get_type_from_index(executionContextInfo[i].typeIndex))); + } + + for (i = 0; i < executionInfoCount; i++) + { + if (executionContextInfo[i].variableKind == kMethodVariableKind_LocalVariable) + buffer_add_string(buf, g_il2cpp_metadata->methodExecutionContextInfoStrings[executionContextInfo[i].nameIndex]); + } + + for (i = 0; i < executionInfoCount; i++) + { + if (executionContextInfo[i].variableKind == kMethodVariableKind_LocalVariable) { + buffer_add_int(buf, executionContextInfo[i].startOffset); + buffer_add_int(buf, executionContextInfo[i].endOffset); + } + } +#endif // !RUNTIME_IL2CPP break; } - case CMD_METHOD_GET_INFO: - buffer_add_int (buf, method->flags); - buffer_add_int (buf, method->iflags); - buffer_add_int (buf, method->token); + case CMD_METHOD_GET_INFO: { + int iflags; + buffer_add_int (buf, mono_method_get_flags(method, &iflags)); + buffer_add_int (buf, iflags); + buffer_add_int (buf, mono_method_get_token(method)); + gboolean is_generic = FALSE; + gboolean is_inflated = FALSE; if (CHECK_PROTOCOL_VERSION (2, 12)) { guint8 attrs = 0; - if (method->is_generic) + is_generic = method->is_generic; + is_inflated = method->is_inflated; + if (is_generic) attrs |= (1 << 0); if (mono_method_signature (method)->generic_param_count) attrs |= (1 << 1); buffer_add_byte (buf, attrs); - if (method->is_generic || method->is_inflated) { + if (is_generic || is_inflated) { MonoMethod *result; - if (method->is_generic) { + if (is_generic) { result = method; } else { MonoMethodInflated *imethod = (MonoMethodInflated *)method; - - result = imethod->declaring; - if (imethod->context.class_inst) { + + result = VM_INFLATED_METHOD_GET_DECLARING(imethod); + if (VM_INFLATED_METHOD_GET_CLASS_INST(imethod)) { MonoClass *klass = ((MonoMethod *) imethod)->klass; /*Generic methods gets the context of the GTD.*/ if (mono_class_get_context (klass)) { @@ -9206,18 +10618,18 @@ method_commands_internal (int command, MonoMethod *method, MonoDomain *domain, g if (mono_method_signature (method)->generic_param_count) { int count, i; - if (method->is_inflated) { + if (is_inflated) { MonoGenericInst *inst = mono_method_get_context (method)->method_inst; if (inst) { count = inst->type_argc; buffer_add_int (buf, count); for (i = 0; i < count; i++) - buffer_add_typeid (buf, domain, mono_class_from_mono_type (inst->type_argv [i])); + buffer_add_typeid (buf, domain, mono_class_from_mono_type (inst->type_argv[i])); } else { buffer_add_int (buf, 0); } - } else if (method->is_generic) { + } else if (is_generic) { MonoGenericContainer *container = mono_method_get_generic_container (method); count = mono_method_signature (method)->generic_param_count; @@ -9236,7 +10648,9 @@ method_commands_internal (int command, MonoMethod *method, MonoDomain *domain, g } } break; + } case CMD_METHOD_GET_BODY: { +#ifndef RUNTIME_IL2CPP MonoError error; int i; @@ -9271,8 +10685,10 @@ method_commands_internal (int command, MonoMethod *method, MonoDomain *domain, g mono_metadata_free_mh (header); } - break; +#else + return ERR_NOT_IMPLEMENTED; +#endif } case CMD_METHOD_RESOLVE_TOKEN: { guint32 token = decode_int (p, &p, end); @@ -9344,6 +10760,7 @@ method_commands_internal (int command, MonoMethod *method, MonoDomain *domain, g break; } case CMD_METHOD_GET_CATTRS: { +#ifndef RUNTIME_IL2CPP MonoError error; MonoClass *attr_klass; MonoCustomAttrInfo *cinfo; @@ -9363,6 +10780,10 @@ method_commands_internal (int command, MonoMethod *method, MonoDomain *domain, g if (err != ERR_NONE) return err; break; +#else + buffer_add_int (buf, 0); + return ERR_NONE; +#endif //RUNTIME_IL2CPP } case CMD_METHOD_MAKE_GENERIC_METHOD: { MonoError error; @@ -9386,7 +10807,7 @@ method_commands_internal (int command, MonoMethod *method, MonoDomain *domain, g g_free (type_argv); return ERR_INVALID_ARGUMENT; } - type_argv [i] = &klass->byval_arg; + type_argv [i] = mono_class_get_type(klass); } ginst = mono_metadata_get_generic_inst (type_argc, type_argv); g_free (type_argv); @@ -9522,6 +10943,7 @@ thread_commands (int command, guint8 *p, guint8 *end, Buffer *buf) buffer_add_long (buf, (guint64)thread->tid); break; case CMD_THREAD_SET_IP: { +#ifndef RUNTIME_IL2CPP DebuggerTlsData *tls; MonoMethod *method; MonoDomain *domain; @@ -9566,6 +10988,9 @@ thread_commands (int command, guint8 *p, guint8 *end, Buffer *buf) } else { MONO_CONTEXT_SET_IP (&tls->restore_state.ctx, (guint8*)tls->frames [0]->ji->code_start + sp.native_offset); } +#else + return ERR_NOT_IMPLEMENTED; +#endif break; } default: @@ -9575,6 +11000,56 @@ thread_commands (int command, guint8 *p, guint8 *end, Buffer *buf) return ERR_NONE; } +#ifdef RUNTIME_IL2CPP + +static uint32_t GetExecutionContextIndexAndType(const Il2CppSequencePoint* sequencePoint, MethodVariableKind variableKind, uint32_t variablePosition, MonoType **type) +{ + uint32_t executionContextPosition, variablesIterated = 0; + + Il2CppMethodExecutionContextInfoIndex *index = &g_il2cpp_metadata->methodExecutionContextInfoIndexes[sequencePoint->methodIndex]; + Il2CppMethodExecutionContextInfo *executionContextInfos = &g_il2cpp_metadata->methodExecutionContextInfos[index->tableIndex][index->startIndex]; + + for (executionContextPosition = 0;; executionContextPosition++) + { + g_assert(executionContextPosition < index->count); + + if (executionContextInfos[executionContextPosition].variableKind == variableKind) + { + if (variablesIterated == variablePosition) + { + *type = il2cpp_get_type_from_index(executionContextInfos[executionContextPosition].typeIndex); + return executionContextPosition; + } + + variablesIterated++; + } + } +} + +static void GetVariable(DebuggerTlsData* tls, StackFrame* frame, MethodVariableKind variableKind, uint32_t variablePosition, MonoType** type, void** var) +{ + for (int frame_index = 0; frame_index < tls->il2cpp_context.frameCount; ++frame_index) + { + if (il2cpp_get_seq_point_method(tls->il2cpp_context.sequencePoints[frame_index]) == frame->actual_method) + { + Il2CppSequencePoint* sequencePoint = tls->il2cpp_context.sequencePoints[frame_index]; + Il2CppSequencePointExecutionContext* executionContext = tls->il2cpp_context.executionContexts[frame_index]; + uint32_t executionContextPosition = GetExecutionContextIndexAndType(sequencePoint, variableKind, variablePosition, type); + *var = executionContext->values[executionContextPosition]; + } + } +} + +static void SendVariableData(DebuggerTlsData* tls, StackFrame* frame, Buffer* buf, MethodVariableKind variableKind, uint32_t variablePosition) +{ + MonoType* localVariableType; + void* localVariableValue; + GetVariable(tls, frame, variableKind, variablePosition, &localVariableType, &localVariableValue); + buffer_add_value_full(buf, localVariableType, localVariableValue, frame->domain, FALSE, NULL); +} + +#endif + static ErrorCode frame_commands (int command, guint8 *p, guint8 *end, Buffer *buf) { @@ -9585,10 +11060,12 @@ frame_commands (int command, guint8 *p, guint8 *end, Buffer *buf) int pos, i, len, frame_idx; DebuggerTlsData *tls; StackFrame *frame; - MonoDebugMethodJitInfo *jit; MonoMethodSignature *sig; gssize id; +#ifndef RUNTIME_IL2CPP + MonoDebugMethodJitInfo *jit; MonoMethodHeader *header; +#endif objid = decode_objid (p, &p, end); err = get_object (objid, (MonoObject**)&thread_obj); @@ -9624,25 +11101,31 @@ frame_commands (int command, guint8 *p, guint8 *end, Buffer *buf) if (!frame->has_ctx) return ERR_ABSENT_INFORMATION; +#ifndef RUNTIME_IL2CPP if (!ensure_jit (frame)) return ERR_ABSENT_INFORMATION; jit = frame->jit; +#endif sig = mono_method_signature (frame->actual_method); +#ifndef RUNTIME_IL2CPP if (!(jit->has_var_info || frame->ji->is_interp) || !mono_get_seq_points (frame->domain, frame->actual_method)) /* * The method is probably from an aot image compiled without soft-debug, variables might be dead, etc. */ return ERR_ABSENT_INFORMATION; +#endif switch (command) { case CMD_STACK_FRAME_GET_VALUES: { MonoError error; len = decode_int (p, &p, end); +#ifndef RUNTIME_IL2CPP header = mono_method_get_header_checked (frame->actual_method, &error); mono_error_assert_ok (&error); /* FIXME report error */ +#endif for (i = 0; i < len; ++i) { pos = decode_int (p, &p, end); @@ -9652,6 +11135,7 @@ frame_commands (int command, guint8 *p, guint8 *end, Buffer *buf) DEBUG_PRINTF (4, "[dbg] send arg %d.\n", pos); +#ifndef RUNTIME_IL2CPP if (frame->ji->is_interp) { guint8 *addr; @@ -9663,7 +11147,11 @@ frame_commands (int command, guint8 *p, guint8 *end, Buffer *buf) add_var (buf, jit, sig->params [pos], &jit->params [pos], &frame->ctx, frame->domain, FALSE); } +#else + SendVariableData (tls, frame, buf, kMethodVariableKind_Parameter, pos); +#endif } else { +#ifndef RUNTIME_IL2CPP MonoDebugLocalsInfo *locals; locals = mono_debug_lookup_locals (frame->method); @@ -9686,9 +11174,14 @@ frame_commands (int command, guint8 *p, guint8 *end, Buffer *buf) add_var (buf, jit, header->locals [pos], &jit->locals [pos], &frame->ctx, frame->domain, FALSE); } +#else + SendVariableData (tls, frame, buf, kMethodVariableKind_LocalVariable, pos); +#endif } } +#ifndef RUNTIME_IL2CPP mono_metadata_free_mh (header); +#endif break; } case CMD_STACK_FRAME_GET_THIS: { @@ -9697,8 +11190,9 @@ frame_commands (int command, guint8 *p, guint8 *end, Buffer *buf) if (frame->api_method->klass->valuetype) { if (!sig->hasthis) { MonoObject *p = NULL; - buffer_add_value (buf, &mono_defaults.object_class->byval_arg, &p, frame->domain); + buffer_add_value (buf, &VM_DEFAULTS_OBJECT_CLASS->byval_arg, &p, frame->domain); } else { +#ifndef RUNTIME_IL2CPP if (frame->ji->is_interp) { guint8 *addr; @@ -9708,12 +11202,23 @@ frame_commands (int command, guint8 *p, guint8 *end, Buffer *buf) } else { add_var (buf, jit, &frame->actual_method->klass->this_arg, jit->this_var, &frame->ctx, frame->domain, TRUE); } +#else + for (int frame_index = 0; frame_index < tls->il2cpp_context.frameCount; ++frame_index) + { + if (il2cpp_get_seq_point_method(tls->il2cpp_context.sequencePoints[frame_index]) == frame->actual_method) + { + buffer_add_value_full (buf, &frame->actual_method->klass->this_arg, tls->il2cpp_context.executionContexts[frame_index]->values[0], frame->domain, TRUE, NULL); + break; + } + } +#endif } } else { if (!sig->hasthis) { MonoObject *p = NULL; buffer_add_value (buf, &frame->actual_method->klass->byval_arg, &p, frame->domain); } else { +#ifndef RUNTIME_IL2CPP if (frame->ji->is_interp) { guint8 *addr; @@ -9723,6 +11228,9 @@ frame_commands (int command, guint8 *p, guint8 *end, Buffer *buf) } else { add_var (buf, jit, &frame->api_method->klass->byval_arg, jit->this_var, &frame->ctx, frame->domain, TRUE); } +#else + SendVariableData (tls, frame, buf, kMethodVariableKind_This, 0); +#endif } } break; @@ -9731,12 +11239,18 @@ frame_commands (int command, guint8 *p, guint8 *end, Buffer *buf) MonoError error; guint8 *val_buf; MonoType *t; +#ifndef RUNTIME_IL2CPP MonoDebugVarInfo *var = NULL; +#else + void *var; +#endif gboolean is_arg = FALSE; len = decode_int (p, &p, end); +#ifndef RUNTIME_IL2CPP header = mono_method_get_header_checked (frame->actual_method, &error); mono_error_assert_ok (&error); /* FIXME report error */ +#endif for (i = 0; i < len; ++i) { pos = decode_int (p, &p, end); @@ -9744,12 +11258,17 @@ frame_commands (int command, guint8 *p, guint8 *end, Buffer *buf) if (pos < 0) { pos = - pos - 1; +#ifndef RUNTIME_IL2CPP g_assert (pos >= 0 && pos < jit->num_params); t = sig->params [pos]; var = &jit->params [pos]; +#else + GetVariable (tls, frame, kMethodVariableKind_Parameter, pos, &t, &var); +#endif is_arg = TRUE; } else { +#ifndef RUNTIME_IL2CPP MonoDebugLocalsInfo *locals; locals = mono_debug_lookup_locals (frame->method); @@ -9762,6 +11281,9 @@ frame_commands (int command, guint8 *p, guint8 *end, Buffer *buf) t = header->locals [pos]; var = &jit->locals [pos]; +#else + GetVariable(tls, frame, kMethodVariableKind_LocalVariable, pos, &t, &var); +#endif } if (MONO_TYPE_IS_REFERENCE (t)) @@ -9772,6 +11294,7 @@ frame_commands (int command, guint8 *p, guint8 *end, Buffer *buf) if (err != ERR_NONE) return err; +#ifndef RUNTIME_IL2CPP if (frame->ji->is_interp) { guint8 *addr; @@ -9783,8 +11306,13 @@ frame_commands (int command, guint8 *p, guint8 *end, Buffer *buf) } else { set_var (t, var, &frame->ctx, frame->domain, val_buf, frame->reg_locations, &tls->restore_state.ctx); } +#else + il2cpp_set_var (val_buf, var, t); +#endif } +#ifndef RUNTIME_IL2CPP mono_metadata_free_mh (header); +#endif break; } case CMD_STACK_FRAME_GET_DOMAIN: { @@ -9795,7 +11323,11 @@ frame_commands (int command, guint8 *p, guint8 *end, Buffer *buf) case CMD_STACK_FRAME_SET_THIS: { guint8 *val_buf; MonoType *t; +#ifndef RUNTIME_IL2CPP MonoDebugVarInfo *var; +#else + void *var; +#endif t = &frame->actual_method->klass->byval_arg; /* Checked by the sender */ @@ -9806,6 +11338,7 @@ frame_commands (int command, guint8 *p, guint8 *end, Buffer *buf) if (err != ERR_NONE) return err; +#ifndef RUNTIME_IL2CPP if (frame->ji->is_interp) { guint8 *addr; @@ -9817,6 +11350,10 @@ frame_commands (int command, guint8 *p, guint8 *end, Buffer *buf) set_var (&frame->actual_method->klass->this_arg, var, &frame->ctx, frame->domain, val_buf, frame->reg_locations, &tls->restore_state.ctx); } +#else + GetVariable (tls, frame, kMethodVariableKind_This, 0, &t, &var); + il2cpp_set_var(val_buf, var, &frame->actual_method->klass->this_arg); +#endif break; } default: @@ -9826,7 +11363,7 @@ frame_commands (int command, guint8 *p, guint8 *end, Buffer *buf) return ERR_NONE; } -static ErrorCode +static int array_commands (int command, guint8 *p, guint8 *end, Buffer *buf) { MonoArray *arr; @@ -9847,8 +11384,8 @@ array_commands (int command, guint8 *p, guint8 *end, Buffer *buf) buffer_add_int (buf, 0); } else { for (i = 0; i < arr->obj.vtable->klass->rank; ++i) { - buffer_add_int (buf, arr->bounds [i].length); - buffer_add_int (buf, arr->bounds [i].lower_bound); + buffer_add_int (buf, arr->bounds[i].length); + buffer_add_int (buf, arr->bounds[i].lower_bound); } } break; @@ -9863,7 +11400,7 @@ array_commands (int command, guint8 *p, guint8 *end, Buffer *buf) esize = mono_array_element_size (arr->obj.vtable->klass); for (i = index; i < index + len; ++i) { elem = (gpointer*)((char*)arr->vector + (i * esize)); - buffer_add_value (buf, &arr->obj.vtable->klass->element_class->byval_arg, elem, arr->obj.vtable->domain); + buffer_add_value (buf, &arr->obj.vtable->klass->element_class->byval_arg, elem, VM_OBJECT_GET_DOMAIN(arr)); } break; case CMD_ARRAY_REF_SET_VALUES: @@ -9877,8 +11414,7 @@ array_commands (int command, guint8 *p, guint8 *end, Buffer *buf) esize = mono_array_element_size (arr->obj.vtable->klass); for (i = index; i < index + len; ++i) { elem = (gpointer*)((char*)arr->vector + (i * esize)); - - decode_value (&arr->obj.vtable->klass->element_class->byval_arg, arr->obj.vtable->domain, (guint8 *)elem, p, &p, end); + decode_value (&arr->obj.vtable->klass->element_class->byval_arg, VM_OBJECT_GET_DOMAIN(arr), (guint8 *)elem, p, &p, end); } break; default: @@ -9942,6 +11478,34 @@ string_commands (int command, guint8 *p, guint8 *end, Buffer *buf) return ERR_NONE; } +static ErrorCode +pointer_commands (int command, guint8 *p, guint8 *end, Buffer *buf) +{ + ErrorCode err; + gint64 addr; + MonoClass* klass; + MonoDomain* domain = NULL; + + switch (command) { + case CMD_POINTER_GET_VALUE: + addr = decode_long (p, &p, end); + klass = decode_typeid (p, &p, end, &domain, &err); + if (err != ERR_NONE) + return err; + + if (klass->byval_arg.type != MONO_TYPE_PTR) + return ERR_INVALID_ARGUMENT; + + buffer_add_value (buf, &klass->element_class->byval_arg, (gpointer)addr, domain); + + break; + default: + return ERR_NOT_IMPLEMENTED; + } + + return ERR_NONE; +} + static ErrorCode object_commands (int command, guint8 *p, guint8 *end, Buffer *buf) { @@ -9982,8 +11546,12 @@ object_commands (int command, guint8 *p, guint8 *end, Buffer *buf) switch (command) { case CMD_OBJECT_REF_GET_TYPE: +#ifndef RUNTIME_IL2CPP /* This handles transparent proxies too */ - buffer_add_typeid (buf, obj->vtable->domain, mono_class_from_mono_type (((MonoReflectionType*)obj->vtable->type)->type)); + buffer_add_typeid (buf, VM_OBJECT_GET_DOMAIN(obj), mono_class_from_mono_type (((MonoReflectionType*)obj->vtable->type)->type)); +#else + buffer_add_typeid (buf, VM_OBJECT_GET_DOMAIN(obj), obj->vtable->klass); +#endif //RUNTIME_IL2CPP break; case CMD_OBJECT_REF_GET_VALUES: len = decode_int (p, &p, end); @@ -10004,7 +11572,7 @@ object_commands (int command, guint8 *p, guint8 *end, Buffer *buf) if (!found) return ERR_INVALID_FIELDID; - if (f->type->attrs & FIELD_ATTRIBUTE_STATIC) { + if (f->type->attrs & FIELD_ATTRIBUTE_STATIC) { guint8 *val; MonoVTable *vtable; @@ -10012,14 +11580,14 @@ object_commands (int command, guint8 *p, guint8 *end, Buffer *buf) return ERR_INVALID_FIELDID; g_assert (f->type->attrs & FIELD_ATTRIBUTE_STATIC); - vtable = mono_class_vtable (obj->vtable->domain, f->parent); + vtable = mono_class_vtable (VM_OBJECT_GET_DOMAIN(obj), f->parent); val = (guint8 *)g_malloc (mono_class_instance_size (mono_class_from_mono_type (f->type))); mono_field_static_get_value_checked (vtable, f, val, &error); if (!is_ok (&error)) { mono_error_cleanup (&error); /* FIXME report the error */ return ERR_INVALID_OBJECT; } - buffer_add_value (buf, f->type, val, obj->vtable->domain); + buffer_add_value (buf, f->type, val, VM_OBJECT_GET_DOMAIN(obj)); g_free (val); } else { guint8 *field_value = NULL; @@ -10035,10 +11603,11 @@ object_commands (int command, guint8 *p, guint8 *end, Buffer *buf) #else g_assert_not_reached (); #endif - } else - field_value = (guint8*)obj + f->offset; + } + else + field_value = (guint8*)(obj) + f->offset; - buffer_add_value (buf, f->type, field_value, obj->vtable->domain); + buffer_add_value (buf, f->type, field_value, VM_OBJECT_GET_DOMAIN(obj)); } } break; @@ -10069,10 +11638,10 @@ object_commands (int command, guint8 *p, guint8 *end, Buffer *buf) return ERR_INVALID_FIELDID; g_assert (f->type->attrs & FIELD_ATTRIBUTE_STATIC); - vtable = mono_class_vtable (obj->vtable->domain, f->parent); + vtable = mono_class_vtable (VM_OBJECT_GET_DOMAIN(obj), f->parent); val = (guint8 *)g_malloc (mono_class_instance_size (mono_class_from_mono_type (f->type))); - err = decode_value (f->type, obj->vtable->domain, val, p, &p, end); + err = decode_value (f->type, VM_OBJECT_GET_DOMAIN(obj), val, p, &p, end); if (err != ERR_NONE) { g_free (val); return err; @@ -10080,7 +11649,7 @@ object_commands (int command, guint8 *p, guint8 *end, Buffer *buf) mono_field_static_set_value (vtable, f, val); g_free (val); } else { - err = decode_value (f->type, obj->vtable->domain, (guint8*)obj + f->offset, p, &p, end); + err = decode_value (f->type, VM_OBJECT_GET_DOMAIN(obj), (guint8*)obj + f->offset, p, &p, end); if (err != ERR_NONE) return err; } @@ -10090,11 +11659,11 @@ object_commands (int command, guint8 *p, guint8 *end, Buffer *buf) buffer_add_long (buf, (gssize)obj); break; case CMD_OBJECT_REF_GET_DOMAIN: - buffer_add_domainid (buf, obj->vtable->domain); + buffer_add_domainid (buf, VM_OBJECT_GET_DOMAIN(obj)); break; case CMD_OBJECT_REF_GET_INFO: - buffer_add_typeid (buf, obj->vtable->domain, mono_class_from_mono_type (((MonoReflectionType*)obj->vtable->type)->type)); - buffer_add_domainid (buf, obj->vtable->domain); + buffer_add_typeid (buf, VM_OBJECT_GET_DOMAIN(obj), mono_class_from_mono_type(VM_OBJECT_GET_TYPE(obj))); + buffer_add_domainid (buf, VM_OBJECT_GET_DOMAIN(obj)); break; default: return ERR_NOT_IMPLEMENTED; @@ -10135,6 +11704,8 @@ command_set_to_string (CommandSet command_set) return "FIELD"; case CMD_SET_EVENT: return "EVENT"; + case CMD_SET_POINTER: + return "POINTER"; default: return ""; } @@ -10231,7 +11802,9 @@ static const char* type_cmds_str[] = { "GET_METHODS_BY_NAME_FLAGS", "GET_INTERFACES", "GET_INTERFACE_MAP", - "IS_INITIALIZED" + "IS_INITIALIZED", + "CREATE_INSTANCE", + "GET_VALUE_SIZE" }; static const char* stack_frame_cmds_str[] = { @@ -10254,6 +11827,10 @@ static const char* string_cmds_str[] = { "GET_CHARS" }; +static const char* pointer_cmds_str[] = { + "GET_VALUE" +}; + static const char* object_cmds_str[] = { "GET_TYPE", "GET_VALUES", @@ -10327,6 +11904,10 @@ cmd_to_string (CommandSet set, int command) cmds = event_cmds_str; cmds_len = G_N_ELEMENTS (event_cmds_str); break; + case CMD_SET_POINTER: + cmds = pointer_cmds_str; + cmds_len = G_N_ELEMENTS (pointer_cmds_str); + break; default: return NULL; } @@ -10387,10 +11968,15 @@ debugger_thread (void *arg) gboolean attach_failed = FALSE; DEBUG_PRINTF (1, "[dbg] Agent thread started, pid=%p\n", (gpointer) (gsize) mono_native_thread_id_get ()); - - debugger_thread_id = mono_native_thread_id_get (); + debugger_thread_id = mono_native_thread_id_get (); +#ifdef RUNTIME_IL2CPP + MonoThread *thread = mono_thread_attach (il2cpp_mono_get_root_domain ()); +#endif MonoInternalThread *internal = mono_thread_internal_current (); +#ifdef RUNTIME_IL2CPP + internal->debugger_thread = 1; +#endif MonoString *str = mono_string_new_checked (mono_domain_get (), "Debugger agent", &error); mono_error_assert_ok (&error); mono_thread_set_name_internal (internal, str, TRUE, FALSE, &error); @@ -10407,6 +11993,17 @@ debugger_thread (void *arg) mono_set_is_debugger_attached (TRUE); /* Send start event to client */ process_profiler_event (EVENT_KIND_VM_START, mono_thread_get_main ()); +#ifdef RUNTIME_IL2CPP + { + MonoDomain* domain = il2cpp_mono_get_root_domain(); + appdomain_load(NULL, domain); + AgentDomainInfo *info = VM_DOMAIN_GET_AGENT_INFO(domain); + void *iter = NULL; + MonoClass *klass; + while(klass = il2cpp_iterate_loaded_classes(&iter)) + g_hash_table_insert(info->loaded_classes, klass, klass); + } +#endif } } else { mono_set_is_debugger_attached (TRUE); @@ -10418,17 +12015,21 @@ debugger_thread (void *arg) /* This will break if the socket is closed during shutdown too */ if (res != HEADER_LENGTH) { DEBUG_PRINTF (1, "[dbg] transport_recv () returned %d, expected %d.\n", res, HEADER_LENGTH); - break; - } - - p = header; - end = header + HEADER_LENGTH; + len = HEADER_LENGTH; + id = 0; + flags = 0; + command_set = CMD_SET_VM; + command = CMD_VM_DISPOSE; + } else { + p = header; + end = header + HEADER_LENGTH; - len = decode_int (p, &p, end); - id = decode_int (p, &p, end); - flags = decode_byte (p, &p, end); - command_set = (CommandSet)decode_byte (p, &p, end); - command = decode_byte (p, &p, end); + len = decode_int (p, &p, end); + id = decode_int (p, &p, end); + flags = decode_byte (p, &p, end); + command_set = (CommandSet)decode_byte (p, &p, end); + command = decode_byte (p, &p, end); + } g_assert (flags == 0); @@ -10504,6 +12105,9 @@ debugger_thread (void *arg) case CMD_SET_STRING_REF: err = string_commands (command, p, end, &buf); break; + case CMD_SET_POINTER: + err = pointer_commands (command, p, end, &buf); + break; case CMD_SET_OBJECT_REF: err = object_commands (command, p, end, &buf); break; @@ -10538,6 +12142,10 @@ debugger_thread (void *arg) mono_set_is_debugger_attached (FALSE); +#ifdef RUNTIME_IL2CPP + il2cpp_mono_free_method_signatures(); +#endif + mono_coop_mutex_lock (&debugger_thread_exited_mutex); debugger_thread_exited = TRUE; mono_coop_cond_signal (&debugger_thread_exited_cond); @@ -10550,8 +12158,207 @@ debugger_thread (void *arg) start_debugger_thread (); } +#ifdef RUNTIME_IL2CPP + mono_thread_detach (thread); +#endif + return 0; } +#ifdef RUNTIME_IL2CPP + +static void +unity_process_breakpoint_inner(DebuggerTlsData *tls, gboolean from_signal, Il2CppSequencePoint* sequencePoint) +{ + MonoJitInfo *ji = NULL; + guint8 *ip; + int i, j, suspend_policy; + MonoBreakpoint *bp; + BreakpointInstance *inst; + GPtrArray *bp_reqs, *ss_reqs_orig, *ss_reqs; + GSList *bp_events = NULL, *ss_events = NULL, *enter_leave_events = NULL; + EventKind kind = EVENT_KIND_BREAKPOINT; + MonoContext *ctx = &tls->restore_state.ctx; + //MonoSeqPointInfo *info; + SeqPoint sp; + gboolean found_sp; + MonoMethod* method = il2cpp_get_seq_point_method(sequencePoint); + + /* + * Skip the instruction causing the breakpoint signal. + */ + unity_mono_jit_find_compiled_method_with_jit_info(mono_domain_get(), method, &ji); + + if (from_signal) + g_assert_not_reached(); + + if (method->wrapper_type || tls->disable_breakpoints) + return; + + bp_reqs = g_ptr_array_new(); + ss_reqs = g_ptr_array_new(); + ss_reqs_orig = g_ptr_array_new(); + + mono_loader_lock(); + + bp = NULL; + for (i = 0; i < breakpoints->len; ++i) { + bp = (MonoBreakpoint *)g_ptr_array_index(breakpoints, i); + + if (!bp->method || !il2cpp_mono_methods_match(bp->method, method)) + continue; + + if (bp->req->event_kind == EVENT_KIND_STEP) + { + SingleStepReq *ss_req = (SingleStepReq *)bp->req->info; + gboolean validFrame = FALSE; + validFrame |= ss_req->depth == STEP_DEPTH_INTO; + validFrame |= ss_req->depth == STEP_DEPTH_OVER && tls->il2cpp_context.frameCount <= ss_req->nframes; + validFrame |= ss_req->depth == STEP_DEPTH_OUT && tls->il2cpp_context.frameCount < ss_req->nframes; + if (!validFrame) + continue; + } + + for (j = 0; j < bp->children->len; ++j) { + inst = (BreakpointInstance *)g_ptr_array_index(bp->children, j); + if (inst->il_offset == sequencePoint->ilOffset) { + if (bp->req->event_kind == EVENT_KIND_STEP) { + for (int k = 0; k < bp->children->len; ++k) + { + BreakpointInstance *inst1 = (BreakpointInstance *)g_ptr_array_index(bp->children, k); + if (inst1->seq_point == sequencePoint) + { + g_ptr_array_add(ss_reqs_orig, bp->req); + break; + } + } + } + else { + g_ptr_array_add(bp_reqs, bp->req); + } + } + } + } + + if (bp_reqs->len == 0 && ss_reqs_orig->len == 0) + { + for (i = 0; i < breakpoints->len; ++i) + { + bp = (MonoBreakpoint *)g_ptr_array_index(breakpoints, i); + + if (bp) + { + /* Maybe a method entry/exit event */ + if ((bp->il_offset == METHOD_ENTRY_IL_OFFSET) && (bp->il_offset == sequencePoint->ilOffset)) + { + kind = EVENT_KIND_METHOD_ENTRY; + break; + } + else if ((bp->il_offset == METHOD_EXIT_IL_OFFSET) && (bp->il_offset == sequencePoint->ilOffset)) + { + kind = EVENT_KIND_METHOD_EXIT; + break; + } + } + } + } + + g_assert(ss_reqs_orig->len <= 1); + if (ss_reqs_orig->len == 1) + { + EventRequest *req = (EventRequest *)g_ptr_array_index(ss_reqs_orig, 0); + SingleStepReq *ss_req = (SingleStepReq *)req->info; + gboolean hit = ss_update_il2cpp(ss_req, tls, ctx, sequencePoint); + if (hit) + { + g_ptr_array_add(ss_reqs, req); + Il2CppSequencePoint *catchFrameSp = NULL; + if (tls->exception) + catchFrameSp = il2cpp_find_catch_sequence_point(tls); + + ss_start_il2cpp(ss_req, tls, catchFrameSp); + } + } + + if (ss_reqs->len > 0) + ss_events = create_event_list(EVENT_KIND_STEP, ss_reqs, sequencePoint, NULL, &suspend_policy); + else if (bp_reqs->len > 0) + bp_events = create_event_list(EVENT_KIND_BREAKPOINT, bp_reqs, sequencePoint, NULL, &suspend_policy); + else if (kind != EVENT_KIND_BREAKPOINT) + enter_leave_events = create_event_list(kind, NULL, sequencePoint, NULL, &suspend_policy); + + mono_loader_unlock(); + + g_ptr_array_free(bp_reqs, TRUE); + g_ptr_array_free(ss_reqs, TRUE); + + /* + * FIXME: The first event will suspend, so the second will only be sent after the + * resume. + */ + if (ss_events) + process_event(EVENT_KIND_STEP, method, 0, ctx, ss_events, suspend_policy, sequencePoint->id); + if (bp_events) + process_event(kind, method, 0, ctx, bp_events, suspend_policy, sequencePoint->id); + if (enter_leave_events) + process_event(kind, method, 0, ctx, enter_leave_events, suspend_policy, sequencePoint->id); +} + +void +unity_debugger_agent_breakpoint(Il2CppSequencePoint* sequencePoint) +{ + DebuggerTlsData *tls; + MonoThreadUnwindState orig_restore_state; + guint8 *orig_ip; + + if (is_debugger_thread()) + return; + + tls = (DebuggerTlsData *)mono_native_tls_get_value(debugger_tls_id); + g_assert(tls); + + save_thread_context(NULL); + + unity_process_breakpoint_inner(tls, FALSE, sequencePoint); +} + +gboolean unity_debugger_agent_is_global_breakpoint_active() +{ + if (!ss_req) + return FALSE; + else + return ss_req->global; +} + +int32_t unity_debugger_agent_is_single_stepping () +{ + return ss_count; +} + +gboolean unity_sequence_point_active(Il2CppSequencePoint *seqPoint) +{ + gboolean global = unity_debugger_agent_is_global_breakpoint_active(); + + if ((seqPoint->ilOffset != METHOD_ENTRY_IL_OFFSET) && (seqPoint->ilOffset != METHOD_EXIT_IL_OFFSET)) + return seqPoint->isActive || global || unity_debugger_agent_is_single_stepping (); + + int i = 0; + while (i < event_requests->len) + { + EventRequest *req = (EventRequest *)g_ptr_array_index (event_requests, i); + + if ((req->event_kind == EVENT_KIND_METHOD_ENTRY && seqPoint->ilOffset == METHOD_ENTRY_IL_OFFSET) || + (req->event_kind == EVENT_KIND_METHOD_EXIT && seqPoint->ilOffset == METHOD_EXIT_IL_OFFSET)) + { + return seqPoint->isActive || global || unity_debugger_agent_is_single_stepping (); + } + + ++i; + } + + return FALSE; +} + +#endif // RUNTIME_IL2CPP #else /* DISABLE_DEBUGGER_AGENT */ diff --git a/mono/mini/debugger-agent.h b/mono/mini/debugger-agent.h index 1ff9de11db46..581579c21c82 100644 --- a/mono/mini/debugger-agent.h +++ b/mono/mini/debugger-agent.h @@ -5,12 +5,21 @@ #ifndef __MONO_DEBUGGER_AGENT_H__ #define __MONO_DEBUGGER_AGENT_H__ +#ifndef RUNTIME_IL2CPP #include "mini.h" +#endif + +#include "il2cpp-compat.h" #include MONO_API void mono_debugger_agent_parse_options (char *options); +#ifdef RUNTIME_IL2CPP +void +mono_debugger_run_debugger_thread_func(void* arg); +#endif // RUNTIME_IL2CPP + void mono_debugger_agent_init (void); @@ -21,7 +30,11 @@ void mono_debugger_agent_single_step_event (void *sigctx); void +#ifndef RUNTIME_IL2CPP debugger_agent_single_step_from_context (MonoContext *ctx); +#else +debugger_agent_single_step_from_context (MonoContext *ctx, int sequencePointId); +#endif void debugger_agent_breakpoint_from_context (MonoContext *ctx); diff --git a/mono/mini/exceptions-amd64.c b/mono/mini/exceptions-amd64.c index 6870052bc3bd..1773c784acec 100644 --- a/mono/mini/exceptions-amd64.c +++ b/mono/mini/exceptions-amd64.c @@ -130,7 +130,7 @@ get_win32_restore_stack (void) * Unhandled Exception Filter * Top-level per-process exception handler. */ -static LONG CALLBACK seh_vectored_exception_handler(EXCEPTION_POINTERS* ep) +LONG CALLBACK seh_vectored_exception_handler(EXCEPTION_POINTERS* ep) { EXCEPTION_RECORD* er; CONTEXT* ctx; @@ -1069,11 +1069,11 @@ mono_arch_unwindinfo_add_alloc_stack (PUNWIND_INFO unwindinfo, MonoUnwindOp *unw static gboolean g_dyn_func_table_inited; // Dynamic function table used when registering unwind info for OS unwind support. -static GList *g_dynamic_function_table_begin; -static GList *g_dynamic_function_table_end; +GList *g_dynamic_function_table_begin; +GList *g_dynamic_function_table_end; // SRW lock (lightweight read/writer lock) protecting dynamic function table. -static SRWLOCK g_dynamic_function_table_lock = SRWLOCK_INIT; +SRWLOCK g_dynamic_function_table_lock = SRWLOCK_INIT; // Module handle used when explicit loading ntdll. static HMODULE g_ntdll; diff --git a/mono/mini/il2cpp-c-types.h b/mono/mini/il2cpp-c-types.h new file mode 100644 index 000000000000..627d0cc8366d --- /dev/null +++ b/mono/mini/il2cpp-c-types.h @@ -0,0 +1,120 @@ +#ifndef __IL2CPP_MONO_DEBUGGER_OPAQUE_TYPES_H__ +#define __IL2CPP_MONO_DEBUGGER_OPAQUE_TYPES_H__ + +#if defined(RUNTIME_IL2CPP) +#include "il2cpp-class-internals.h" +#include "il2cpp-object-internals.h" +#include "vm-utils/Debugger.h" +#endif // RUNTIME_IL2CPP + +#define IL2CPP_MONO_PUBLIC_KEY_TOKEN_LENGTH 17 + +//Converted to il2cpp types +#define MonoType Il2CppType +#define MonoClass Il2CppClass +#define MonoImage Il2CppImage +#define MonoMethod MethodInfo +#define MonoMethodInflated MethodInfo +#define MonoClassField FieldInfo +#define MonoArrayType Il2CppArrayType +#define MonoGenericParam Il2CppGenericParameter +#define MonoGenericInst Il2CppGenericInst +#define MonoGenericContext Il2CppGenericContext +#define MonoGenericClass Il2CppGenericClass +#define MonoGenericContainer Il2CppGenericContainer +#define MonoProperty PropertyInfo +#define MonoString Il2CppString +#define MonoArray Il2CppArraySize +#define MonoThread Il2CppThread +#define MonoInternalThread Il2CppInternalThread +#define MonoReflectionType Il2CppReflectionType +#define MonoProfiler Il2CppProfiler +#define MonoAssembly Il2CppAssembly +#define MonoAssembyName Il2CppAssemblyName +#define MonoMethodHeader Il2CppMethodHeaderInfo +#define MonoReflectionAssembly Il2CppReflectionAssembly +#define MonoAppDomain Il2CppAppDomain +#define MonoDomain Il2CppDomain +#define MonoDomainFunc Il2CppDomainFunc +#define MonoObject Il2CppObject +#define MonoVTable Il2CppVTable +#define MonoException Il2CppException +#define MonoMarshalByRefObject Il2CppMarshalByRefObject + +//Unsupported in il2cpp, should never be referenced +#define MonoCustomAttrInfo #error Custom Attributes Not Supported +#define MonoCustomAttrEntry #error Custom Attributes Not Supported +#define CattrNamedArg #error Custom Attributes Not Supported +#define MonoJitTlsData #error Jit TLS Data Unsupported + +//still stubs everywhere +typedef struct _Il2CppMonoMethodSignature Il2CppMonoMethodSignature; +typedef struct _Il2CppMonoRuntimeExceptionHandlingCallbacks Il2CppMonoRuntimeExceptionHandlingCallbacks; +typedef struct Il2CppDefaults Il2CppMonoDefaults; +typedef struct _Il2CppMonoTypeNameParse Il2CppMonoTypeNameParse; +typedef struct _Il2CppMonoDebugOptions Il2CppMonoDebugOptions; +typedef struct _Il2CppEmptyStruct Il2CppMonoLMF; + +typedef MonoStackFrameInfo StackFrameInfo; +typedef gpointer MonoInterpFrameHandle; + +typedef gboolean (*Il2CppMonoInternalStackWalk) (MonoStackFrameInfo *frame, MonoContext *ctx, gpointer data); + +struct _Il2CppMonoRuntimeExceptionHandlingCallbacks +{ + void (*il2cpp_mono_walk_stack_with_state) (Il2CppMonoInternalStackWalk func, MonoThreadUnwindState *state, MonoUnwindOptions options, void *user_data); +}; + +struct _Il2CppMonoMethodSignature +{ + MonoType *ret; + guint16 param_count; + unsigned int generic_param_count : 16; + unsigned int call_convention : 6; + unsigned int hasthis : 1; + MonoType **params; +}; + +struct _Il2CppMonoTypeNameParse +{ + MonoAssemblyName assembly; + void *il2cppTypeNameParseInfo; +}; + +struct _Il2CppMonoDebugOptions +{ + gboolean native_debugger_break; +}; + +struct _Il2CppEmptyStruct +{ + int dummy; +}; + +TYPED_HANDLE_DECL (MonoObject); +TYPED_HANDLE_DECL (MonoReflectionAssembly); +Il2CppMonoDefaults il2cpp_mono_defaults; +Il2CppMonoDebugOptions il2cpp_mono_debug_options; + +typedef void (*Il2CppMonoProfileFunc) (MonoProfiler *prof); +typedef void (*Il2CppMonoProfileAppDomainFunc) (MonoProfiler *prof, MonoDomain *domain); +typedef void (*Il2CppMonoProfileAppDomainResult) (MonoProfiler *prof, MonoDomain *domain, int result); +typedef void (*Il2CppMonoProfileAssemblyFunc) (MonoProfiler *prof, MonoAssembly *assembly); +typedef void (*Il2CppMonoProfileJitResult) (MonoProfiler *prof, MonoMethod *method, MonoJitInfo* jinfo, int result); +typedef void (*Il2CppMonoProfileAssemblyResult) (MonoProfiler *prof, MonoAssembly *assembly, int result); +typedef void (*Il2CppMonoProfileThreadFunc) (MonoProfiler *prof, uintptr_t tid); +typedef gboolean (*Il2CppMonoJitStackWalk) (MonoStackFrameInfo *frame, MonoContext *ctx, gpointer data); +typedef void (*Il2CppDomainFunc) (MonoDomain *domain, void* user_data); + +typedef void (*emit_assembly_load_callback)(void*, void*); +typedef void(*emit_type_load_callback)(void*, void*, void*); + +void il2cpp_set_thread_state_background(MonoThread* thread); +void* il2cpp_domain_get_agent_info(MonoAppDomain* domain); +void il2cpp_domain_set_agent_info(MonoAppDomain* domain, void* agentInfo); +void il2cpp_start_debugger_thread(); +void* il2cpp_gc_alloc_fixed(size_t size); +void il2cpp_gc_free_fixed(void* address); +const char* il2cpp_domain_get_name(MonoDomain* domain); + +#endif diff --git a/mono/mini/il2cpp-compat.h b/mono/mini/il2cpp-compat.h new file mode 100644 index 000000000000..98a748f6cdef --- /dev/null +++ b/mono/mini/il2cpp-compat.h @@ -0,0 +1,462 @@ +#pragma once + +#include +#if defined(RUNTIME_IL2CPP) +#include "il2cpp-c-types.h" +#include "il2cpp-api.h" +#else +#include +#include +#include +#endif //RUNTIME_IL2CPP + +#ifdef RUNTIME_IL2CPP + +#define THREAD_STATIC_FIELD_OFFSET -1 + +#define VM_DOMAIN_GET_AGENT_INFO(domain) il2cpp_domain_get_agent_info(domain) +#define VM_DOMAIN_SET_AGENT_INFO(domain, value) il2cpp_domain_set_agent_info(domain, value) +#define VM_METHOD_IS_STRING_CTOR(method) il2cpp_method_is_string_ctor(method) +#define VM_INFLATED_METHOD_GET_DECLARING(imethod) il2cpp_method_get_generic_definition(imethod) +#define VM_INFLATED_METHOD_GET_CLASS_INST(imethod) il2cpp_method_get_generic_class_inst(imethod) +#define VM_OBJECT_GET_DOMAIN(object) il2cpp_mono_domain_get() +#define VM_OBJECT_GET_TYPE(object) il2cpp_mono_object_get_type(object) +#define VM_GENERIC_CLASS_GET_CONTAINER_CLASS(gklass) il2cpp_generic_class_get_container_class(gklass) +#define VM_DEFAULTS_OBJECT_CLASS il2cpp_defaults_object_class() +#define VM_DEFAULTS_EXCEPTION_CLASS il2cpp_defaults_exception_class() +#define VM_DEFAULTS_CORLIB_IMAGE il2cpp_defaults_corlib_image() +#define VM_DEFAULTS_VOID_CLASS il2cpp_defaults_void_class() +//Fixme module name as image name seems bad +#define VM_IMAGE_GET_MODULE_NAME(image) il2cpp_image_name(image) +#else +#define VM_DOMAIN_GET_AGENT_INFO(domain) domain_jit_info (domain)->agent_info +#define VM_DOMAIN_SET_AGENT_INFO(domain, value) domain_jit_info (domain)->agent_info = value +#define VM_METHOD_IS_STRING_CTOR(method) method->string_ctor +#define VM_INFLATED_METHOD_GET_DECLARING(imethod) (imethod)->declaring +#define VM_INFLATED_METHOD_GET_CLASS_INST(imethod) (imethod)->context.class_inst +#define VM_OBJECT_GET_DOMAIN(object) ((MonoObject*)object)->vtable->domain +#define VM_OBJECT_GET_TYPE(object) ((MonoReflectionType*)object->vtable->type)->type +#define VM_GENERIC_CLASS_GET_CONTAINER_CLASS(gklass) (gklass)->container_class +#define VM_DEFAULTS_OBJECT_CLASS mono_defaults.object_class +#define VM_DEFAULTS_EXCEPTION_CLASS mono_defaults.exception_class +#define VM_DEFAULTS_CORLIB_IMAGE mono_defaults.corlib +#define VM_DEFAULTS_VOID_CLASS mono_defaults.void_class +#define VM_IMAGE_GET_MODULE_NAME(image) (image)->module_name +#endif + +#if defined(RUNTIME_IL2CPP) + +#define MonoMethodSignature Il2CppMonoMethodSignature +#define MonoRuntimeExceptionHandlingCallbacks Il2CppMonoRuntimeExceptionHandlingCallbacks +#define debug_options il2cpp_mono_debug_options +#define MonoTypeNameParse Il2CppMonoTypeNameParse +#define MonoDebugOptions Il2CppMonoDebugOptions +#define MonoLMF Il2CppMonoLMF + +#define mono_image_get_entry_point il2cpp_mono_image_get_entry_point +#define mono_image_get_filename il2cpp_mono_image_get_filename +#define mono_image_get_guid il2cpp_mono_image_get_guid +#define mono_type_get_class il2cpp_mono_type_get_class +#define mono_type_is_struct il2cpp_mono_type_is_struct +#define mono_type_is_reference il2cpp_mono_type_is_reference +#define mono_metadata_free_mh il2cpp_mono_metadata_free_mh +#define mono_method_signature il2cpp_mono_method_signature +#define mono_method_get_param_names il2cpp_mono_method_get_param_names +#define mono_type_generic_inst_is_valuetype il2cpp_mono_type_generic_inst_is_valuetype +#define mono_method_get_header_checked il2cpp_mono_method_get_header_checked +#define mono_class_init il2cpp_mono_class_init +#define mono_class_vtable il2cpp_mono_class_vtable +#define mono_class_get_field_from_name il2cpp_mono_class_get_field_from_name +#define mono_array_element_size il2cpp_mono_array_element_size +#define mono_class_instance_size il2cpp_mono_class_instance_size +#define mono_class_value_size il2cpp_mono_class_value_size +#define mono_class_is_assignable_from il2cpp_mono_class_is_assignable_from +#define mono_class_from_mono_type il2cpp_mono_class_from_mono_type +#define mono_class_get_flags il2cpp_class_get_flags +#define mono_class_num_fields il2cpp_mono_class_num_fields +#define mono_class_num_methods il2cpp_mono_class_num_methods +#define mono_class_num_properties il2cpp_mono_class_num_properties +#define mono_class_get_fields il2cpp_mono_class_get_fields +#define mono_class_get_methods il2cpp_mono_class_get_methods +#define mono_class_get_properties il2cpp_mono_class_get_properties +#define mono_class_get_nested_types il2cpp_class_get_nested_types_accepts_generic +#define mono_field_get_name il2cpp_mono_field_get_name +#define mono_class_get_method_from_name il2cpp_class_get_method_from_name +#define mono_string_chars il2cpp_mono_string_chars +#define mono_class_is_abstract il2cpp_class_is_abstract +#define mono_string_length il2cpp_mono_string_length +#define mono_array_addr_with_size il2cpp_mono_array_addr_with_size +#define mono_array_length il2cpp_mono_array_length +#define mono_string_new il2cpp_mono_string_new +#define mono_string_new_checked il2cpp_mono_string_new_checked +#define mono_string_to_utf8_checked il2cpp_mono_string_to_utf8_checked +#define mono_object_hash il2cpp_mono_object_hash +#define mono_object_unbox il2cpp_mono_object_unbox +#define mono_object_get_virtual_method il2cpp_object_get_virtual_method +#define mono_field_set_value il2cpp_mono_field_set_value +#define mono_field_static_set_value il2cpp_mono_field_static_set_value +#define mono_gchandle_new_weakref il2cpp_mono_gchandle_new_weakref +#define mono_gchandle_get_target il2cpp_mono_gchandle_get_target +#define mono_gchandle_free il2cpp_mono_gchandle_free +#define mono_gc_wbarrier_generic_store il2cpp_mono_gc_wbarrier_generic_store +#define mono_reflection_parse_type_checked il2cpp_mono_reflection_parse_type_checked +#define mono_reflection_free_type_info il2cpp_mono_reflection_free_type_info +#define mono_get_root_domain il2cpp_mono_get_root_domain +#define mono_runtime_quit il2cpp_mono_runtime_quit +#define mono_runtime_is_shutting_down il2cpp_mono_runtime_is_shutting_down +#define mono_domain_get il2cpp_mono_domain_get +#define mono_domain_set il2cpp_mono_domain_set +#define mono_domain_foreach il2cpp_mono_domain_foreach +#define mono_jit_info_table_find il2cpp_mono_jit_info_table_find +#define mono_jit_info_get_method il2cpp_mono_jit_info_get_method +#define mono_debug_find_method il2cpp_mono_debug_find_method +#define mono_debug_free_method_jit_info il2cpp_mono_debug_free_method_jit_info +#define mono_debug_il_offset_from_address il2cpp_mono_debug_il_offset_from_address +#define mono_set_is_debugger_attached il2cpp_mono_set_is_debugger_attached +#define mono_type_full_name il2cpp_mono_type_full_name +#define mono_method_full_name il2cpp_mono_method_full_name +#define mono_thread_current il2cpp_mono_thread_current +#define mono_thread_get_main il2cpp_mono_thread_get_main +#define mono_thread_attach il2cpp_mono_thread_attach +#define mono_thread_detach il2cpp_mono_thread_detach +#define mono_domain_lock il2cpp_mono_domain_lock +#define mono_domain_unlock il2cpp_mono_domain_unlock +#define mono_jit_info_table_find_internal il2cpp_mono_jit_info_table_find_internal +#define mono_aligned_addr_hash il2cpp_mono_aligned_addr_hash +#define mono_metadata_get_generic_inst il2cpp_mono_metadata_get_generic_inst +#define mono_get_method_checked il2cpp_mono_get_method_checked +#define mono_class_interface_offset_with_variance il2cpp_mono_class_interface_offset_with_variance +#define mono_class_setup_supertypes il2cpp_mono_class_setup_supertypes +#define mono_class_setup_vtable il2cpp_mono_class_setup_vtable +#define mono_class_setup_methods il2cpp_mono_class_setup_methods +#define mono_class_field_is_special_static il2cpp_mono_class_field_is_special_static +#define mono_class_field_get_special_static_type il2cpp_mono_class_field_get_special_static_type +#define mono_class_get_context il2cpp_mono_class_get_context +#define mono_method_get_context il2cpp_mono_method_get_context +#define mono_method_get_generic_container il2cpp_mono_method_get_generic_container +#define mono_class_inflate_generic_method_full_checked il2cpp_mono_class_inflate_generic_method_full_checked +#define mono_class_inflate_generic_method_checked il2cpp_mono_class_inflate_generic_method_checked +#define mono_loader_lock il2cpp_mono_loader_lock +#define mono_loader_unlock il2cpp_mono_loader_unlock +#define mono_loader_lock_track_ownership il2cpp_mono_loader_lock_track_ownership +#define mono_loader_lock_is_owned_by_self il2cpp_mono_loader_lock_is_owned_by_self +#define mono_method_get_wrapper_data il2cpp_mono_method_get_wrapper_data +#define mono_type_get_name_full il2cpp_mono_type_get_name_full +#define mono_class_is_nullable il2cpp_mono_class_is_nullable +#define mono_class_get_generic_container il2cpp_mono_class_get_generic_container +#define mono_class_setup_interfaces il2cpp_mono_class_setup_interfaces +#define mono_class_get_methods_by_name il2cpp_mono_class_get_methods_by_name +#define mono_ldtoken_checked il2cpp_mono_ldtoken_checked +#define mono_class_from_generic_parameter_internal il2cpp_mono_class_from_generic_parameter_internal +#define mono_class_load_from_name il2cpp_mono_class_load_from_name +#define mono_class_try_load_from_name il2cpp_class_from_name +#define mono_class_get_generic_class il2cpp_mono_class_get_generic_class +#define mono_thread_internal_current il2cpp_mono_thread_internal_current +#define mono_thread_internal_is_current il2cpp_mono_thread_internal_is_current +#define mono_thread_internal_abort il2cpp_mono_thread_internal_abort +#define mono_thread_internal_reset_abort il2cpp_mono_thread_internal_reset_abort +#define mono_thread_get_name il2cpp_mono_thread_get_name +#define mono_thread_set_name_internal il2cpp_mono_thread_set_name_internal +#define mono_thread_suspend_all_other_threads il2cpp_mono_thread_suspend_all_other_threads +#define mono_stack_mark_record_size il2cpp_mono_stack_mark_record_size +#define mono_get_eh_callbacks il2cpp_mono_get_eh_callbacks +#define mono_nullable_init il2cpp_mono_nullable_init +#define mono_value_box_checked il2cpp_mono_value_box_checked +#define mono_field_static_get_value_checked il2cpp_mono_field_static_get_value_checked +#define mono_field_static_get_value_for_thread il2cpp_mono_field_static_get_value_for_thread +#define mono_field_get_value_object_checked il2cpp_mono_field_get_value_object_checked +#define mono_object_new_checked il2cpp_mono_object_new_checked +#define mono_ldstr_checked il2cpp_mono_ldstr_checked +#define mono_runtime_try_invoke il2cpp_mono_runtime_try_invoke +#define mono_runtime_invoke_checked il2cpp_mono_runtime_invoke_checked +#define mono_gc_base_init il2cpp_mono_gc_base_init +#define mono_gc_register_root il2cpp_mono_gc_register_root +#define mono_gc_deregister_root il2cpp_mono_gc_deregister_root +#define mono_environment_exitcode_get il2cpp_mono_environment_exitcode_get +#define mono_environment_exitcode_set il2cpp_mono_environment_exitcode_set +#define mono_threadpool_suspend il2cpp_mono_threadpool_suspend +#define mono_threadpool_resume il2cpp_mono_threadpool_resume +#define mono_assembly_get_image il2cpp_mono_assembly_get_image +#define mono_runtime_try_shutdown il2cpp_mono_runtime_try_shutdown +#define mono_verifier_is_method_valid_generic_instantiation il2cpp_mono_verifier_is_method_valid_generic_instantiation +#define mono_reflection_get_type_checked il2cpp_mono_reflection_get_type_checked +#define mono_assembly_get_object_handle il2cpp_mono_assembly_get_object_handle +#define mono_type_get_object_checked il2cpp_mono_type_get_object_checked +#define mono_network_init il2cpp_mono_network_init +#define mono_w32socket_set_blocking il2cpp_mono_w32socket_set_blocking + +#define mono_get_runtime_build_info il2cpp_mono_get_runtime_build_info +#define mono_marshal_method_from_wrapper il2cpp_mono_marshal_method_from_wrapper +#define mini_get_debug_options il2cpp_mini_get_debug_options +#define mono_jit_find_compiled_method_with_jit_info il2cpp_mono_jit_find_compiled_method_with_jit_info +#define mono_get_lmf_addr il2cpp_mono_get_lmf_addr +#define mono_set_lmf il2cpp_mono_set_lmf +#define mono_aot_get_method_checked il2cpp_mono_aot_get_method_checked +#define mono_arch_setup_resume_sighandler_ctx il2cpp_mono_arch_setup_resume_sighandler_ctx +#define mono_arch_set_breakpoint il2cpp_mono_arch_set_breakpoint +#define mono_arch_clear_breakpoint il2cpp_mono_arch_clear_breakpoint +#define mono_arch_start_single_stepping il2cpp_mono_arch_start_single_stepping +#define mono_arch_stop_single_stepping il2cpp_mono_arch_stop_single_stepping +#define mono_arch_skip_breakpoint il2cpp_mono_arch_skip_breakpoint +#define mono_arch_skip_single_step il2cpp_mono_arch_skip_single_step +#define mono_arch_context_get_int_reg il2cpp_mono_arch_context_get_int_reg +#define mono_arch_context_set_int_reg il2cpp_mono_arch_context_set_int_reg +#define mono_walk_stack_with_ctx il2cpp_mono_walk_stack_with_ctx +#define mono_walk_stack_with_state il2cpp_mono_walk_stack_with_state +#define mono_thread_state_init_from_current il2cpp_mono_thread_state_init_from_current +#define mono_thread_state_init_from_monoctx il2cpp_mono_thread_state_init_from_monoctx +#define mini_jit_info_table_find il2cpp_mini_jit_info_table_find +#define mono_restore_context il2cpp_mono_restore_context +#define mono_method_get_declaring_generic_method il2cpp_mono_method_get_declaring_generic_method +#define jinfo_get_method il2cpp_jinfo_get_method +#define mono_defaults il2cpp_mono_defaults +#define mono_find_prev_seq_point_for_native_offset il2cpp_mono_find_prev_seq_point_for_native_offset +#define mono_w32socket_accept_internal il2cpp_mono_w32socket_accept_internal +#define mono_find_next_seq_point_for_native_offset il2cpp_mono_find_next_seq_point_for_native_offset +#define mono_class_has_parent il2cpp_mono_class_has_parent +#define mono_class_is_gtd il2cpp_class_is_generic +#define mono_class_is_ginst il2cpp_class_is_inflated +#define mono_generic_container_get_param il2cpp_mono_generic_container_get_param +#define mono_find_seq_point il2cpp_mono_find_seq_point +#define mono_seq_point_iterator_init il2cpp_mono_seq_point_iterator_init +#define mono_seq_point_iterator_next il2cpp_mono_seq_point_iterator_next +#define mono_seq_point_init_next il2cpp_mono_seq_point_init_next +#define mono_get_seq_points il2cpp_mono_get_seq_points +#define G_BREAKPOINT IL2CPP_G_BREAKPOINT +#define mono_thread_info_safe_suspend_and_run il2cpp_mono_thread_info_safe_suspend_and_run +#define mono_error_cleanup il2cpp_mono_error_cleanup +#define mono_error_convert_to_exception il2cpp_mono_error_convert_to_exception +#define mono_error_get_message il2cpp_mono_error_get_message +#define mono_error_assert_ok_pos il2cpp_mono_error_assert_ok_pos +#define mono_class_get_namespace il2cpp_class_get_namespace +#define mono_class_get_name il2cpp_class_get_name +#define mono_object_get_class il2cpp_object_get_class +#define mono_field_get_parent il2cpp_field_get_parent +#define mono_class_get_parent il2cpp_class_get_parent +#define mono_field_get_type il2cpp_field_get_type +#define mono_method_get_name il2cpp_method_get_name +#define mono_class_get_type il2cpp_class_get_type +#define mono_method_get_class il2cpp_method_get_class +#define mono_class_get_image il2cpp_class_get_image +#define mono_class_get_interfaces il2cpp_class_get_interfaces +#undef MONO_CLASS_IS_INTERFACE +#define MONO_CLASS_IS_INTERFACE il2cpp_class_is_interface +#define mono_image_get_assembly il2cpp_image_get_assembly +#define mono_image_get_name il2cpp_image_get_name +#define mono_type_get_type il2cpp_type_get_type +#define mono_class_get_rank il2cpp_class_get_rank +#define mono_class_get_element_class il2cpp_class_get_element_class +#define mono_class_get_type_token il2cpp_class_get_type_token +#define mono_type_is_byref il2cpp_type_is_byref +#define mono_class_is_enum il2cpp_class_is_enum +#define mono_method_get_flags il2cpp_method_get_flags +#define mono_method_get_token il2cpp_method_get_token +#define mono_method_is_generic il2cpp_method_is_generic +#define mono_method_is_inflated il2cpp_method_is_inflated +#undef mono_field_is_deleted +#define mono_field_is_deleted il2cpp_field_is_deleted +#define mono_domain_get_assemblies_iter il2cpp_domain_get_assemblies_iter + +#undef mono_domain_assemblies_lock +#define mono_domain_assemblies_lock +#undef mono_domain_assemblies_unlock +#define mono_domain_assemblies_unlock + +#define mono_get_string_class il2cpp_mono_get_string_class + +#define MONO_MAX_IREGS 1 +#define NOT_IMPLEMENTED do { g_assert_not_reached (); } while (0) + +MonoMethod* il2cpp_mono_image_get_entry_point (MonoImage *image); +const char* il2cpp_mono_image_get_filename (MonoImage *image); +const char* il2cpp_mono_image_get_guid (MonoImage *image); +MonoClass* il2cpp_mono_type_get_class (MonoType *type); +mono_bool il2cpp_mono_type_is_struct (MonoType *type); +mono_bool il2cpp_mono_type_is_reference (MonoType *type); +void il2cpp_mono_metadata_free_mh (MonoMethodHeader *mh); +Il2CppMonoMethodSignature* il2cpp_mono_method_signature (MonoMethod *m); +void il2cpp_mono_method_get_param_names (MonoMethod *method, const char **names); +mono_bool il2cpp_mono_type_generic_inst_is_valuetype (MonoType *type); +MonoMethodHeader* il2cpp_mono_method_get_header_checked (MonoMethod *method, MonoError *error); +gboolean il2cpp_mono_class_init (MonoClass *klass); +MonoVTable* il2cpp_mono_class_vtable (MonoDomain *domain, MonoClass *klass); +MonoClassField* il2cpp_mono_class_get_field_from_name (MonoClass *klass, const char *name); +int32_t il2cpp_mono_array_element_size (MonoClass *ac); +int32_t il2cpp_mono_class_instance_size (MonoClass *klass); +int32_t il2cpp_mono_class_value_size (MonoClass *klass, uint32_t *align); +gboolean il2cpp_mono_class_is_assignable_from (MonoClass *klass, MonoClass *oklass); +MonoClass* il2cpp_mono_class_from_mono_type (MonoType *type); +int il2cpp_mono_class_num_fields (MonoClass *klass); +int il2cpp_mono_class_num_methods (MonoClass *klass); +int il2cpp_mono_class_num_properties (MonoClass *klass); +MonoClassField* il2cpp_mono_class_get_fields (MonoClass* klass, gpointer *iter); +MonoMethod* il2cpp_mono_class_get_methods (MonoClass* klass, gpointer *iter); +MonoProperty* il2cpp_mono_class_get_properties (MonoClass* klass, gpointer *iter); +const char* il2cpp_mono_field_get_name (MonoClassField *field); +mono_unichar2* il2cpp_mono_string_chars (MonoString *s); +int il2cpp_mono_string_length (MonoString *s); +char* il2cpp_mono_array_addr_with_size (MonoArray *array, int size, uintptr_t idx); +uintptr_t il2cpp_mono_array_length (MonoArray *array); +MonoString* il2cpp_mono_string_new (MonoDomain *domain, const char *text); +MonoString* il2cpp_mono_string_new (MonoDomain *domain, const char *text); +MonoString* il2cpp_mono_string_new_checked (MonoDomain *domain, const char *text, MonoError *merror); +char* il2cpp_mono_string_to_utf8_checked (MonoString *string_obj, MonoError *error); +int il2cpp_mono_object_hash (MonoObject* obj); +void* il2cpp_mono_object_unbox (MonoObject *obj); +void il2cpp_mono_field_set_value (MonoObject *obj, MonoClassField *field, void *value); +void il2cpp_mono_field_static_set_value (MonoVTable *vt, MonoClassField *field, void *value); +uint32_t il2cpp_mono_gchandle_new_weakref (MonoObject *obj, mono_bool track_resurrection); +MonoObject* il2cpp_mono_gchandle_get_target (uint32_t gchandle); +void il2cpp_mono_gchandle_free (uint32_t gchandle); +void il2cpp_mono_gc_wbarrier_generic_store (void* ptr, MonoObject* value); +int il2cpp_mono_reflection_parse_type_checked (char *name, Il2CppMonoTypeNameParse *info, MonoError *error); +void il2cpp_mono_reflection_free_type_info (Il2CppMonoTypeNameParse *info); +MonoDomain* il2cpp_mono_get_root_domain (void); +void il2cpp_mono_runtime_quit (void); +gboolean il2cpp_mono_runtime_is_shutting_down (void); +MonoDomain* il2cpp_mono_domain_get (void); +gboolean il2cpp_mono_domain_set (MonoDomain *domain, gboolean force); +void il2cpp_mono_domain_foreach(MonoDomainFunc func, gpointer user_data); +MonoJitInfo* il2cpp_mono_jit_info_table_find(MonoDomain* domain, char* addr); +MonoMethod* il2cpp_mono_jit_info_get_method(MonoJitInfo* ji); +gint32 il2cpp_mono_debug_il_offset_from_address(MonoMethod* method, MonoDomain* domain, guint32 native_offset); +void il2cpp_mono_set_is_debugger_attached(gboolean attached); +char* il2cpp_mono_type_full_name(MonoType* type); +char* il2cpp_mono_method_full_name(MonoMethod* method, gboolean signature); +MonoThread* il2cpp_mono_thread_current(); +MonoThread* il2cpp_mono_thread_get_main(); +MonoThread* il2cpp_mono_thread_attach(MonoDomain* domain); +void il2cpp_mono_domain_lock(MonoDomain* domain); +void il2cpp_mono_domain_unlock(MonoDomain* domain); +MonoJitInfo* il2cpp_mono_jit_info_table_find_internal(MonoDomain* domain, char* addr, gboolean try_aot, gboolean allow_trampolines); +guint il2cpp_mono_aligned_addr_hash(gconstpointer ptr); +MonoGenericInst* il2cpp_mono_metadata_get_generic_inst(int type_argc, MonoType** type_argv); +MonoMethod* il2cpp_mono_get_method_checked(MonoImage* image, guint32 token, MonoClass* klass, MonoGenericContext* context, MonoError* error); +int il2cpp_mono_class_interface_offset_with_variance(MonoClass* klass, MonoClass* itf, gboolean* non_exact_match); +void il2cpp_mono_class_setup_supertypes(MonoClass* klass); +void il2cpp_mono_class_setup_vtable(MonoClass* klass); +void il2cpp_mono_class_setup_methods(MonoClass* klass); +gboolean il2cpp_mono_class_field_is_special_static(MonoClassField* field); +guint32 il2cpp_mono_class_field_get_special_static_type(MonoClassField* field); +MonoGenericContext* il2cpp_mono_class_get_context(MonoClass* klass); +MonoGenericContext* il2cpp_mono_method_get_context(MonoMethod* method); +MonoGenericContainer* il2cpp_mono_method_get_generic_container(MonoMethod* method); +MonoMethod* il2cpp_mono_class_inflate_generic_method_full_checked(MonoMethod* method, MonoClass* klass_hint, MonoGenericContext* context, MonoError* error); +MonoMethod* il2cpp_mono_class_inflate_generic_method_checked(MonoMethod* method, MonoGenericContext* context, MonoError* error); +void il2cpp_mono_loader_lock(); +void il2cpp_mono_loader_unlock(); +void il2cpp_mono_loader_lock_track_ownership(gboolean track); +gboolean il2cpp_mono_loader_lock_is_owned_by_self(); +gpointer il2cpp_mono_method_get_wrapper_data(MonoMethod* method, guint32 id); +char* il2cpp_mono_type_get_name_full(MonoType* type, MonoTypeNameFormat format); +gboolean il2cpp_mono_class_is_nullable(MonoClass* klass); +MonoGenericContainer* il2cpp_mono_class_get_generic_container(MonoClass* klass); +void il2cpp_mono_class_setup_interfaces(MonoClass* klass, MonoError* error); +GPtrArray* il2cpp_mono_class_get_methods_by_name(MonoClass* klass, const char* name, guint32 bflags, gboolean ignore_case, gboolean allow_ctors, MonoError* error); +gpointer il2cpp_mono_ldtoken_checked(MonoImage* image, guint32 token, MonoClass** handle_class, MonoGenericContext* context, MonoError* error); +MonoClass* il2cpp_mono_class_from_generic_parameter_internal(MonoGenericParam* param); +MonoClass* il2cpp_mono_class_load_from_name(MonoImage* image, const char* name_space, const char* name); +MonoGenericClass* il2cpp_mono_class_get_generic_class(MonoClass* klass); +MonoInternalThread* il2cpp_mono_thread_internal_current(); +gboolean il2cpp_mono_thread_internal_is_current(MonoInternalThread* thread); +void il2cpp_mono_thread_internal_abort(MonoInternalThread* thread, gboolean appdomain_unload); +void il2cpp_mono_thread_internal_reset_abort(MonoInternalThread* thread); +gunichar2* il2cpp_mono_thread_get_name(MonoInternalThread* this_obj, guint32* name_len); +void il2cpp_mono_thread_set_name_internal(MonoInternalThread* this_obj, MonoString* name, gboolean permanent, gboolean reset, MonoError* error); +void il2cpp_mono_thread_suspend_all_other_threads(); +void il2cpp_mono_stack_mark_record_size(MonoThreadInfo* info, HandleStackMark* stackmark, const char* func_name); +Il2CppMonoRuntimeExceptionHandlingCallbacks* il2cpp_mono_get_eh_callbacks(); +void il2cpp_mono_nullable_init(guint8* buf, MonoObject* value, MonoClass* klass); +MonoObject* il2cpp_mono_value_box_checked(MonoDomain* domain, MonoClass* klass, gpointer value, MonoError* error); +void il2cpp_mono_field_static_get_value_checked(MonoVTable* vt, MonoClassField* field, void* value, MonoError* error); +void il2cpp_mono_field_static_get_value_for_thread(MonoInternalThread* thread, MonoVTable* vt, MonoClassField* field, void* value, MonoError* error); +MonoObject* il2cpp_mono_field_get_value_object_checked(MonoDomain* domain, MonoClassField* field, MonoObject* obj, MonoError* error); +MonoObject* il2cpp_mono_object_new_checked(MonoDomain* domain, MonoClass* klass, MonoError* error); +MonoString* il2cpp_mono_ldstr_checked(MonoDomain* domain, MonoImage* image, guint32 idx, MonoError* error); +MonoObject* il2cpp_mono_runtime_try_invoke(MonoMethod* method, void* obj, void** params, MonoObject** exc, MonoError* error); +MonoObject* il2cpp_mono_runtime_invoke_checked(MonoMethod* method, void* obj, void** params, MonoError* error); +void il2cpp_mono_gc_base_init(); +int il2cpp_mono_gc_register_root(char* start, size_t size, MonoGCDescriptor descr, MonoGCRootSource source, void *key, const char* msg); +void il2cpp_mono_gc_deregister_root(char* addr); +gint32 il2cpp_mono_environment_exitcode_get(); +void il2cpp_mono_environment_exitcode_set(gint32 value); +void il2cpp_mono_threadpool_suspend(); +void il2cpp_mono_threadpool_resume(); +gboolean il2cpp_mono_runtime_try_shutdown(); +gboolean il2cpp_mono_verifier_is_method_valid_generic_instantiation(MonoMethod* method); +MonoType* il2cpp_mono_reflection_get_type_checked(MonoImage* rootimage, MonoImage* image, Il2CppMonoTypeNameParse* info, gboolean ignorecase, gboolean* type_resolve, MonoError* error); +MonoReflectionAssemblyHandle il2cpp_mono_assembly_get_object_handle(MonoDomain* domain, MonoAssembly* assembly, MonoError* error); +MonoReflectionType* il2cpp_mono_type_get_object_checked(MonoDomain* domain, MonoType* type, MonoError* error); +void il2cpp_mono_network_init(); +gint il2cpp_mono_w32socket_set_blocking(SOCKET sock, gboolean blocking); + +char* il2cpp_mono_get_runtime_build_info(); +MonoMethod* il2cpp_mono_marshal_method_from_wrapper(MonoMethod* wrapper); +MonoDebugOptions* il2cpp_mini_get_debug_options(); +gpointer il2cpp_mono_jit_find_compiled_method_with_jit_info(MonoDomain* domain, MonoMethod* method, MonoJitInfo** ji); +MonoLMF** il2cpp_mono_get_lmf_addr(); +void il2cpp_mono_set_lmf(MonoLMF* lmf); +gpointer il2cpp_mono_aot_get_method_checked(MonoDomain* domain, MonoMethod* method, MonoError* error); +void il2cpp_mono_arch_setup_resume_sighandler_ctx(MonoContext* ctx, gpointer func); +void il2cpp_mono_arch_set_breakpoint(MonoJitInfo* ji, guint8* ip); +void il2cpp_mono_arch_clear_breakpoint(MonoJitInfo* ji, guint8* ip); +void il2cpp_mono_arch_start_single_stepping(); +void il2cpp_mono_arch_stop_single_stepping(); +void il2cpp_mono_arch_skip_breakpoint(MonoContext* ctx, MonoJitInfo* ji); +void il2cpp_mono_arch_skip_single_step(MonoContext* ctx); +mgreg_t il2cpp_mono_arch_context_get_int_reg(MonoContext* ctx, int reg); +void il2cpp_mono_arch_context_set_int_reg(MonoContext* ctx, int reg, mgreg_t val); +void il2cpp_mono_walk_stack_with_ctx(Il2CppMonoJitStackWalk func, MonoContext* start_ctx, MonoUnwindOptions unwind_options, void* user_data); +void il2cpp_mono_walk_stack_with_state(Il2CppMonoJitStackWalk func, MonoThreadUnwindState* state, MonoUnwindOptions unwind_options, void* user_data); +gboolean il2cpp_mono_thread_state_init_from_current(MonoThreadUnwindState* ctx); +gboolean il2cpp_mono_thread_state_init_from_monoctx(MonoThreadUnwindState* ctx, MonoContext* mctx); +MonoJitInfo* il2cpp_mini_jit_info_table_find(MonoDomain* domain, char* addr, MonoDomain** out_domain); +void il2cpp_mono_restore_context(MonoContext* ctx); +MonoMethod* il2cpp_mono_method_get_declaring_generic_method(MonoMethod* method); +MonoMethod* il2cpp_jinfo_get_method (MonoJitInfo *ji); +gboolean il2cpp_mono_find_prev_seq_point_for_native_offset (MonoDomain *domain, MonoMethod *method, gint32 native_offset, MonoSeqPointInfo **info, SeqPoint* seq_point); +SOCKET il2cpp_mono_w32socket_accept_internal (SOCKET s, struct sockaddr *addr, socklen_t *addrlen, gboolean blocking); +gboolean il2cpp_mono_find_next_seq_point_for_native_offset (MonoDomain *domain, MonoMethod *method, gint32 native_offset, MonoSeqPointInfo **info, SeqPoint* seq_point); +gboolean il2cpp_mono_class_has_parent (MonoClass *klass, MonoClass *parent); +MonoGenericParam* il2cpp_mono_generic_container_get_param (MonoGenericContainer *gc, int i); +gboolean il2cpp_mono_find_seq_point (MonoDomain *domain, MonoMethod *method, gint32 il_offset, MonoSeqPointInfo **info, SeqPoint *seq_point); +void il2cpp_mono_seq_point_iterator_init (SeqPointIterator* it, MonoSeqPointInfo* info); +gboolean il2cpp_mono_seq_point_iterator_next (SeqPointIterator* it); +void il2cpp_mono_seq_point_init_next (MonoSeqPointInfo* info, SeqPoint sp, SeqPoint* next); +MonoSeqPointInfo* il2cpp_mono_get_seq_points (MonoDomain *domain, MonoMethod *method); +void IL2CPP_G_BREAKPOINT(); +void il2cpp_mono_thread_info_safe_suspend_and_run (MonoNativeThreadId id, gboolean interrupt_kernel, MonoSuspendThreadCallback callback, gpointer user_data); +void il2cpp_mono_error_cleanup (MonoError *oerror); +MonoException* il2cpp_mono_error_convert_to_exception (MonoError *target_error); +const char* il2cpp_mono_error_get_message (MonoError *oerror); +void il2cpp_mono_error_assert_ok_pos (MonoError *error, const char* filename, int lineno); +Il2CppSequencePoint* il2cpp_get_sequence_points(void* *iter); +Il2CppSequencePoint* il2cpp_get_method_sequence_points(MonoMethod* method, void* *iter); +MonoClass* il2cpp_class_get_nested_types_accepts_generic(MonoClass *monoClass, void* *iter); +MonoClass* il2cpp_defaults_object_class(); +guint8 il2cpp_array_rank(MonoArray *monoArr); +const char* il2cpp_image_name(MonoImage *monoImage); +guint8* il2cpp_field_get_address(MonoObject *obj, MonoClassField *monoField); +MonoType* il2cpp_mono_object_get_type(MonoObject* object); +MonoClass* il2cpp_defaults_exception_class(); +MonoImage* il2cpp_defaults_corlib_image(); +bool il2cpp_method_is_string_ctor (const MonoMethod * method); +MonoClass* il2cpp_defaults_void_class(); +void il2cpp_set_var(guint8* newValue, void *value, MonoType *localVariableTypeMono); +MonoMethod* il2cpp_get_interface_method(MonoClass* klass, MonoClass* itf, int slot); +gboolean il2cpp_field_is_deleted(MonoClassField *field); +MonoClass* il2cpp_iterate_loaded_classes(void* *iter); +MonoAssembly* il2cpp_domain_get_assemblies_iter(MonoAppDomain *domain, void* *iter); +const char** il2cpp_get_source_files_for_type(MonoClass *klass, int *count); +MonoMethod* il2cpp_method_get_generic_definition(MonoMethodInflated *imethod); +MonoGenericInst* il2cpp_method_get_generic_class_inst(MonoMethodInflated *imethod); +MonoClass* il2cpp_generic_class_get_container_class(MonoGenericClass *gclass); +void il2cpp_mono_thread_detach(MonoThread* thread); +MonoClass* il2cpp_mono_get_string_class (void); +Il2CppSequencePoint* il2cpp_get_sequence_point(int id); +char* il2cpp_assembly_get_full_name(MonoAssembly *assembly); +const MonoMethod* il2cpp_get_seq_point_method(Il2CppSequencePoint *seqPoint); +const MonoClass* il2cpp_get_class_from_index(int index); +const MonoType* il2cpp_get_type_from_index(int index); + +#endif // RUNTIME_IL2CPP diff --git a/mono/mini/il2cpp-stubs.cpp b/mono/mini/il2cpp-stubs.cpp new file mode 100644 index 000000000000..060d8b68b3e0 --- /dev/null +++ b/mono/mini/il2cpp-stubs.cpp @@ -0,0 +1,1529 @@ +#if defined(RUNTIME_IL2CPP) + +#include "il2cpp-config.h" +#include +#include "gc/GCHandle.h" +#include "gc/GarbageCollector.h" +#include "gc/WriteBarrier.h" +#include "gc/gc_wrapper.h" +#include "metadata/FieldLayout.h" +#include "vm/Assembly.h" +#include "vm/AssemblyName.h" +#include "vm/Class.h" +#include "vm/Domain.h" +#include "vm/Field.h" +#include "vm/GenericContainer.h" +#include "vm/GenericClass.h" +#include "vm/Image.h" +#include "vm/Method.h" +#include "vm/Object.h" +#include "vm/Profiler.h" +#include "vm/Reflection.h" +#include "vm/Runtime.h" +#include "vm/String.h" +#include "vm/Thread.h" +#include "vm/ThreadPoolMs.h" +#include "vm/Type.h" +#include "vm-utils/Debugger.h" +#include "metadata/GenericMetadata.h" + +extern "C" { + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "il2cpp-c-types.h" +#include + +static MonoGHashTable *method_signatures; + +static il2cpp::os::Mutex s_il2cpp_mono_loader_lock(false); +static uint64_t s_il2cpp_mono_loader_lock_tid = 0; + +MonoMethod* il2cpp_mono_image_get_entry_point (MonoImage *image) +{ + return (MonoMethod*)il2cpp::vm::Image::GetEntryPoint((Il2CppImage*)image); +} + +const char* il2cpp_mono_image_get_filename (MonoImage *monoImage) +{ + Il2CppImage *image = (Il2CppImage*)monoImage; + return image->name; +} + +const char* il2cpp_mono_image_get_guid (MonoImage *image) +{ + return "00000000-0000-0000-0000-000000000000"; //IL2CPP doesn't have image GUIDs +} + +MonoClass* il2cpp_mono_type_get_class (MonoType *type) +{ + return (MonoClass*) il2cpp::vm::Type::GetClass((Il2CppType*)type); +} + +mono_bool il2cpp_mono_type_is_struct (MonoType *type) +{ + return il2cpp::vm::Type::IsStruct((Il2CppType*)type); +} + +mono_bool il2cpp_mono_type_is_reference (MonoType *type) +{ + return il2cpp::vm::Type::IsReference((Il2CppType*)type); +} + +void il2cpp_mono_metadata_free_mh (MonoMethodHeader *mh) +{ + IL2CPP_ASSERT(0 && "This method is not yet implemented"); +} + +Il2CppMonoMethodSignature* il2cpp_mono_method_signature (MonoMethod *m) +{ + MethodInfo* method = (MethodInfo*)m; + + if (method_signatures == NULL) + method_signatures = mono_g_hash_table_new_type(NULL, NULL, MONO_HASH_KEY_GC, MONO_ROOT_SOURCE_DEBUGGER, NULL, "method-to-signature for il2cpp table"); + + Il2CppMonoMethodSignature* existing_signature = (Il2CppMonoMethodSignature*)mono_g_hash_table_lookup(method_signatures, method); + if (existing_signature != NULL) + return existing_signature; + + Il2CppMonoMethodSignature* sig = g_new(Il2CppMonoMethodSignature, 1); + + sig->call_convention = MONO_CALL_DEFAULT; + sig->hasthis = il2cpp::vm::Method::IsInstance(method); + sig->ret = (MonoType*)il2cpp::vm::Method::GetReturnType(method); + + sig->generic_param_count = 0; + + if (method->is_generic) + { + sig->generic_param_count = il2cpp::vm::Method::GetGenericParamCount(method); + } + else if (method->is_inflated) + { + if (method->genericMethod->context.method_inst) + sig->generic_param_count += method->genericMethod->context.method_inst->type_argc; + + if (method->genericMethod->context.class_inst) + sig->generic_param_count += method->genericMethod->context.class_inst->type_argc; + } + + sig->param_count = il2cpp::vm::Method::GetParamCount(method); + sig->params = g_new(MonoType*, sig->param_count); + for (int i = 0; i < sig->param_count; ++i) + sig->params[i] = (MonoType*)il2cpp::vm::Method::GetParam(method, i); + + mono_g_hash_table_insert(method_signatures, method, sig); + + return sig; +} + +static void il2cpp_mono_free_method_signature(gpointer unused1, gpointer value, gpointer unused2) +{ + Il2CppMonoMethodSignature* sig = (Il2CppMonoMethodSignature*)value; + g_free(sig->params); + g_free(sig); +} + +void il2cpp_mono_free_method_signatures() +{ + if (method_signatures != NULL) + { + mono_g_hash_table_foreach(method_signatures, il2cpp_mono_free_method_signature, NULL); + mono_g_hash_table_destroy(method_signatures); + method_signatures = NULL; + } +} + +void il2cpp_mono_method_get_param_names (MonoMethod *m, const char **names) +{ + MethodInfo* method = (MethodInfo*)m; + uint32_t numberOfParameters = il2cpp::vm::Method::GetParamCount(method); + for (int i = 0; i < numberOfParameters; ++i) + names[i] = il2cpp::vm::Method::GetParamName(method, i); +} + +mono_bool il2cpp_mono_type_generic_inst_is_valuetype (MonoType *monoType) +{ + static const int kBitIsValueType = 1; + Il2CppType *type = (Il2CppType*)monoType; + const Il2CppTypeDefinition *typeDef = il2cpp::vm::MetadataCache::GetTypeDefinitionFromIndex(type->data.generic_class->typeDefinitionIndex); + return (typeDef->bitfield >> (kBitIsValueType - 1)) & 0x1; +} + +MonoMethodHeader* il2cpp_mono_method_get_header_checked (MonoMethod *method, MonoError *error) +{ + return NULL; +} + +gboolean il2cpp_mono_class_init (MonoClass *klass) +{ + IL2CPP_ASSERT(0 && "This method is not yet implemented"); + return 0; +} + +MonoVTable* il2cpp_mono_class_vtable (MonoDomain *domain, MonoClass *klass) +{ + return (MonoVTable*)((Il2CppClass*)klass)->vtable; +} + +MonoClassField* il2cpp_mono_class_get_field_from_name (MonoClass *klass, const char *name) +{ + IL2CPP_ASSERT(0 && "This method is not yet implemented"); + return NULL; +} + +int32_t il2cpp_mono_array_element_size (MonoClass *monoClass) +{ + Il2CppClass *klass = (Il2CppClass*)monoClass; + return klass->element_size; +} + +int32_t il2cpp_mono_class_instance_size (MonoClass *klass) +{ + return il2cpp::vm::Class::GetInstanceSize((Il2CppClass*)klass); +} + +int32_t il2cpp_mono_class_value_size (MonoClass *klass, uint32_t *align) +{ + return il2cpp::vm::Class::GetValueSize((Il2CppClass*)klass, align); +} + +gboolean il2cpp_mono_class_is_assignable_from (MonoClass *klass, MonoClass *oklass) +{ + return il2cpp::vm::Class::IsAssignableFrom((Il2CppClass*)klass, (Il2CppClass*)oklass); +} + +MonoClass* il2cpp_mono_class_from_mono_type (MonoType *type) +{ + return (MonoClass*)il2cpp::vm::Class::FromIl2CppType((Il2CppType*)type); +} + +int il2cpp_mono_class_num_fields (MonoClass *klass) +{ + return il2cpp::vm::Class::GetNumFields((Il2CppClass*)klass); +} + +int il2cpp_mono_class_num_methods (MonoClass *klass) +{ + return il2cpp::vm::Class::GetNumMethods((Il2CppClass*)klass); +} + +int il2cpp_mono_class_num_properties (MonoClass *klass) +{ + return il2cpp::vm::Class::GetNumProperties((Il2CppClass*)klass); +} + +MonoClassField* il2cpp_mono_class_get_fields (MonoClass* klass, gpointer *iter) +{ + return (MonoClassField*)il2cpp::vm::Class::GetFields((Il2CppClass*)klass, iter); +} + +MonoMethod* il2cpp_mono_class_get_methods (MonoClass* klass, gpointer *iter) +{ + return (MonoMethod*)il2cpp::vm::Class::GetMethods((Il2CppClass*)klass, iter); +} + +MonoProperty* il2cpp_mono_class_get_properties (MonoClass* klass, gpointer *iter) +{ + return (MonoProperty*)il2cpp::vm::Class::GetProperties((Il2CppClass*)klass, iter); +} + +const char* il2cpp_mono_field_get_name (MonoClassField *field) +{ + return il2cpp::vm::Field::GetName((FieldInfo*)field); +} + +mono_unichar2* il2cpp_mono_string_chars (MonoString *monoStr) +{ + Il2CppString *str = (Il2CppString*)monoStr; + return (mono_unichar2*)str->chars; +} + +int il2cpp_mono_string_length (MonoString *monoStr) +{ + Il2CppString *str = (Il2CppString*)monoStr; + return str->length; +} + +char* il2cpp_mono_array_addr_with_size (MonoArray *array, int size, uintptr_t idx) +{ + IL2CPP_ASSERT(0 && "This method is not yet implemented"); + return NULL; +} + +uintptr_t il2cpp_mono_array_length (MonoArray *array) +{ + IL2CPP_ASSERT(0 && "This method is not yet implemented"); + return 0; +} + +MonoString* il2cpp_mono_string_new (MonoDomain *domain, const char *text) +{ + return (MonoString*)il2cpp::vm::String::New(text); +} + + +MonoString* il2cpp_mono_string_new_checked (MonoDomain *domain, const char *text, MonoError *merror) +{ + error_init(merror); + return il2cpp_mono_string_new (domain, text); +} + +char* il2cpp_mono_string_to_utf8_checked (MonoString *string_obj, MonoError *error) +{ + error_init(error); + Il2CppString *str = (Il2CppString*)string_obj; + std::string s = il2cpp::utils::StringUtils::Utf16ToUtf8(str->chars, str->length); + return g_strdup(s.c_str()); +} + +int il2cpp_mono_object_hash (MonoObject* obj) +{ + return (int)((intptr_t)obj >> 3); +} + +void* il2cpp_mono_object_unbox (MonoObject *monoObj) +{ + Il2CppObject *obj = (Il2CppObject*)monoObj; + return il2cpp::vm::Object::Unbox(obj); +} + +void il2cpp_mono_field_set_value (MonoObject *obj, MonoClassField *field, void *value) +{ + IL2CPP_ASSERT(0 && "This method is not yet implemented"); +} + +void il2cpp_mono_field_static_set_value (MonoVTable *vt, MonoClassField *field, void *value) +{ + il2cpp::vm::Field::StaticSetValue((FieldInfo*)field, value); +} + +uint32_t il2cpp_mono_gchandle_new_weakref (MonoObject *obj, mono_bool track_resurrection) +{ + return il2cpp::gc::GCHandle::NewWeakref((Il2CppObject*)obj, track_resurrection == 0 ? false : true); +} + +MonoObject* il2cpp_mono_gchandle_get_target (uint32_t gchandle) +{ + return (MonoObject*)il2cpp::gc::GCHandle::GetTarget(gchandle); +} + +void il2cpp_mono_gchandle_free (uint32_t gchandle) +{ + il2cpp::gc::GCHandle::Free(gchandle); +} + +void il2cpp_mono_gc_wbarrier_generic_store (void* ptr, MonoObject* value) +{ + il2cpp::gc::WriteBarrier::GenericStore(ptr, (Il2CppObject*)value); +} + +int il2cpp_mono_reflection_parse_type_checked (char *name, Il2CppMonoTypeNameParse *monoInfo, MonoError *error) +{ + error_init(error); + il2cpp::vm::TypeNameParseInfo *pInfo = new il2cpp::vm::TypeNameParseInfo(); + std::string nameStr = name; + std::replace(nameStr.begin(), nameStr.end(), '/', '+'); + il2cpp::vm::TypeNameParser parser(nameStr, *pInfo, false); + monoInfo->assembly.name = NULL; + monoInfo->il2cppTypeNameParseInfo = pInfo; + return parser.Parse(); +} + +void il2cpp_mono_reflection_free_type_info (Il2CppMonoTypeNameParse *info) +{ + delete (il2cpp::vm::TypeNameParseInfo*)info->il2cppTypeNameParseInfo; +} + +MonoDomain* il2cpp_mono_get_root_domain (void) +{ + return (MonoDomain*)il2cpp::vm::Domain::GetCurrent(); +} + +void il2cpp_mono_runtime_quit (void) +{ + IL2CPP_ASSERT(0 && "This method is not yet implemented"); +} + +gboolean il2cpp_mono_runtime_is_shutting_down (void) +{ + return il2cpp::vm::Runtime::IsShuttingDown() ? TRUE : FALSE; +} + +MonoDomain* il2cpp_mono_domain_get (void) +{ + return il2cpp_mono_get_root_domain(); +} + +gboolean il2cpp_mono_domain_set (MonoDomain *domain, gboolean force) +{ + IL2CPP_ASSERT(domain == il2cpp_mono_get_root_domain()); + return TRUE; +} + +void il2cpp_mono_domain_foreach(MonoDomainFunc func, gpointer user_data) +{ + func((MonoDomain*)il2cpp_mono_get_root_domain(), user_data); +} + +MonoJitInfo* il2cpp_mono_jit_info_table_find(MonoDomain* domain, char* addr) +{ + IL2CPP_ASSERT(0 && "This method is not yet implemented"); + return NULL; +} + +MonoMethod* il2cpp_mono_jit_info_get_method(MonoJitInfo* ji) +{ + IL2CPP_ASSERT(0 && "This method is not yet implemented"); + return NULL; +} + +gint32 il2cpp_mono_debug_il_offset_from_address(MonoMethod* method, MonoDomain* domain, guint32 native_offset) +{ + IL2CPP_ASSERT(0 && "This method is not yet implemented"); + return 0; +} + +void il2cpp_mono_set_is_debugger_attached(gboolean attached) +{ +#if IL2CPP_MONO_DEBUGGER + il2cpp::utils::Debugger::SetIsDebuggerAttached(attached == TRUE); +#endif +} + +char* il2cpp_mono_type_full_name(MonoType* type) +{ + std::string name = il2cpp::vm::Type::GetName((Il2CppType*)type, IL2CPP_TYPE_NAME_FORMAT_FULL_NAME); + return g_strdup(name.c_str()); +} + +char* il2cpp_mono_method_full_name(MonoMethod* method, gboolean signature) +{ + return g_strdup(((MethodInfo*)method)->name); +} + +MonoThread* il2cpp_mono_thread_current() +{ + return (MonoThread*)il2cpp::vm::Thread::Current(); +} + +MonoThread* il2cpp_mono_thread_get_main() +{ + return (MonoThread*)il2cpp::vm::Thread::Main(); +} + +MonoThread* il2cpp_mono_thread_attach(MonoDomain* domain) +{ + return (MonoThread*)il2cpp::vm::Thread::Attach((Il2CppDomain*)domain); +} + +void il2cpp_mono_thread_detach(MonoThread* thread) +{ + il2cpp::vm::Thread::Detach((Il2CppThread*)thread); +} + +void il2cpp_mono_domain_lock(MonoDomain* domain) +{ +} + +void il2cpp_mono_domain_unlock(MonoDomain* domain) +{ +} + +MonoJitInfo* il2cpp_mono_jit_info_table_find_internal(MonoDomain* domain, char* addr, gboolean try_aot, gboolean allow_trampolines) +{ + IL2CPP_ASSERT(0 && "This method is not yet implemented"); + return NULL; +} + +guint il2cpp_mono_aligned_addr_hash(gconstpointer ptr) +{ + return GPOINTER_TO_UINT(ptr) >> 3; +} + +MonoGenericInst* il2cpp_mono_metadata_get_generic_inst(int type_argc, MonoType** type_argv) +{ + return (MonoGenericInst*)il2cpp::vm::MetadataCache::GetGenericInst((Il2CppType**)type_argv, type_argc); +} + +MonoMethod* il2cpp_mono_get_method_checked(MonoImage* image, guint32 token, MonoClass* klass, MonoGenericContext* context, MonoError* error) +{ + IL2CPP_ASSERT(0 && "This method is not yet implemented"); + return NULL; +} + +SgenDescriptor il2cpp_mono_gc_make_root_descr_all_refs(int numbits) +{ + return NULL; +} + +int il2cpp_mono_gc_register_root_wbarrier (char *start, size_t size, MonoGCDescriptor descr, MonoGCRootSource source, void *key, const char *msg) +{ + il2cpp::gc::GarbageCollector::RegisterRoot(start, size); + return 1; +} + +MonoGCDescriptor il2cpp_mono_gc_make_vector_descr (void) +{ + return 0; +} + +int il2cpp_mono_class_interface_offset_with_variance(MonoClass* klass, MonoClass* itf, gboolean* non_exact_match) +{ + IL2CPP_ASSERT(0 && "This method is not yet implemented"); + return 0; +} + +void il2cpp_mono_class_setup_supertypes(MonoClass* klass) +{ + IL2CPP_ASSERT(0 && "This method is not yet implemented"); +} + +void il2cpp_mono_class_setup_vtable(MonoClass* klass) +{ + il2cpp::vm::Class::Init((Il2CppClass*)klass); +} + +void il2cpp_mono_class_setup_methods(MonoClass* klass) +{ + il2cpp::vm::Class::SetupMethods((Il2CppClass*)klass); +} + +gboolean il2cpp_mono_class_field_is_special_static(MonoClassField* field) +{ + return il2cpp::vm::Field::IsNormalStatic((FieldInfo*)field) ? FALSE : TRUE; +} + +guint32 il2cpp_mono_class_field_get_special_static_type(MonoClassField* field) +{ + IL2CPP_ASSERT(0 && "This method is not yet implemented"); + return 0; +} + +MonoGenericContext* il2cpp_mono_class_get_context(MonoClass* klass) +{ + return (MonoGenericContext*)&((Il2CppClass*)klass)->generic_class->context; +} + +MonoGenericContext* il2cpp_mono_method_get_context(MonoMethod* monoMethod) +{ + MethodInfo * method = (MethodInfo*)monoMethod; + + if (!method->is_inflated || method->is_generic) + return NULL; + + return (MonoGenericContext*) &((MethodInfo*)method)->genericMethod->context; +} + +MonoGenericContainer* il2cpp_mono_method_get_generic_container(MonoMethod* monoMethod) +{ + MethodInfo * method = (MethodInfo*)monoMethod; + + if (method->is_inflated || !method->is_generic) + return NULL; + + return (MonoGenericContainer*) method->genericContainer; +} + +MonoMethod* il2cpp_mono_class_inflate_generic_method_full_checked(MonoMethod* method, MonoClass* klass_hint, MonoGenericContext* context, MonoError* error) +{ + error_init(error); + return (MonoMethod*) il2cpp::metadata::GenericMetadata::Inflate((MethodInfo*)method, (Il2CppClass*)klass_hint, (Il2CppGenericContext*)context); +} + +MonoMethod* il2cpp_mono_class_inflate_generic_method_checked(MonoMethod* method, MonoGenericContext* context, MonoError* error) +{ + error_init(error); + return (MonoMethod*)il2cpp::metadata::GenericMetadata::Inflate((MethodInfo*)method, NULL, (Il2CppGenericContext*)context); +} + +void il2cpp_mono_loader_lock() +{ + s_il2cpp_mono_loader_lock.Lock(); + s_il2cpp_mono_loader_lock_tid = il2cpp::os::Thread::CurrentThreadId(); +} + +void il2cpp_mono_loader_unlock() +{ + s_il2cpp_mono_loader_lock_tid = 0; + s_il2cpp_mono_loader_lock.Unlock(); +} + +void il2cpp_mono_loader_lock_track_ownership(gboolean track) +{ +} + +gboolean il2cpp_mono_loader_lock_is_owned_by_self() +{ + return s_il2cpp_mono_loader_lock_tid == il2cpp::os::Thread::CurrentThreadId(); +} + +gpointer il2cpp_mono_method_get_wrapper_data(MonoMethod* method, guint32 id) +{ + IL2CPP_ASSERT(0 && "This method is not yet implemented"); + return 0; +} + +char* il2cpp_mono_type_get_name_full(MonoType* type, MonoTypeNameFormat format) +{ + std::string name = il2cpp::vm::Type::GetName((Il2CppType*)type, (Il2CppTypeNameFormat)format); + return g_strdup(name.c_str()); +} + +gboolean il2cpp_mono_class_is_nullable(MonoClass* klass) +{ + return il2cpp::vm::Class::IsNullable((Il2CppClass*)klass); +} + +MonoGenericContainer* il2cpp_mono_class_get_generic_container(MonoClass* klass) +{ + return (MonoGenericContainer*)il2cpp::vm::Class::GetGenericContainer((Il2CppClass*)klass); +} + +void il2cpp_mono_class_setup_interfaces(MonoClass* klass, MonoError* error) +{ + error_init(error); + il2cpp::vm::Class::SetupInterfaces((Il2CppClass*)klass); +} + +enum { + BFLAGS_IgnoreCase = 1, + BFLAGS_DeclaredOnly = 2, + BFLAGS_Instance = 4, + BFLAGS_Static = 8, + BFLAGS_Public = 0x10, + BFLAGS_NonPublic = 0x20, + BFLAGS_FlattenHierarchy = 0x40, + BFLAGS_InvokeMethod = 0x100, + BFLAGS_CreateInstance = 0x200, + BFLAGS_GetField = 0x400, + BFLAGS_SetField = 0x800, + BFLAGS_GetProperty = 0x1000, + BFLAGS_SetProperty = 0x2000, + BFLAGS_ExactBinding = 0x10000, + BFLAGS_SuppressChangeType = 0x20000, + BFLAGS_OptionalParamBinding = 0x40000 +}; + +static gboolean +method_nonpublic (MethodInfo* method, gboolean start_klass) +{ + switch (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) { + case METHOD_ATTRIBUTE_ASSEM: + return (start_klass || il2cpp_defaults.generic_ilist_class); + case METHOD_ATTRIBUTE_PRIVATE: + return start_klass; + case METHOD_ATTRIBUTE_PUBLIC: + return FALSE; + default: + return TRUE; + } +} + +GPtrArray* il2cpp_mono_class_get_methods_by_name(MonoClass* il2cppMonoKlass, const char* name, guint32 bflags, gboolean ignore_case, gboolean allow_ctors, MonoError* error) +{ + GPtrArray *array; + Il2CppClass *klass = (Il2CppClass*)il2cppMonoKlass; + Il2CppClass *startklass; + MethodInfo *method; + gpointer iter; + int match, nslots; + /*FIXME, use MonoBitSet*/ + /*guint32 method_slots_default [8]; + guint32 *method_slots = NULL;*/ + int (*compare_func) (const char *s1, const char *s2) = NULL; + + array = g_ptr_array_new (); + startklass = klass; + error_init (error); + + if (name != NULL) + compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp; + + /*il2cpp_mono_class_setup_methods (klass); + il2cpp_mono_class_setup_vtable (klass); + + if (is_generic_parameter (&klass->byval_arg)) + nslots = mono_class_get_vtable_size (klass->parent); + else + nslots = MONO_CLASS_IS_INTERFACE (klass) ? mono_class_num_methods (klass) : mono_class_get_vtable_size (klass); + if (nslots >= sizeof (method_slots_default) * 8) { + method_slots = g_new0 (guint32, nslots / 32 + 1); + } else { + method_slots = method_slots_default; + memset (method_slots, 0, sizeof (method_slots_default)); + }*/ +handle_parent: + il2cpp_mono_class_setup_methods ((MonoClass*)klass); + il2cpp_mono_class_setup_vtable ((MonoClass*)klass); + + iter = NULL; + while ((method = (MethodInfo*)il2cpp_mono_class_get_methods ((MonoClass*)klass, &iter))) { + match = 0; + /*if (method->slot != -1) { + g_assert (method->slot < nslots); + if (method_slots [method->slot >> 5] & (1 << (method->slot & 0x1f))) + continue; + if (!(method->flags & METHOD_ATTRIBUTE_NEW_SLOT)) + method_slots [method->slot >> 5] |= 1 << (method->slot & 0x1f); + }*/ + + if (!allow_ctors && method->name [0] == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)) + continue; + if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) { + if (bflags & BFLAGS_Public) + match++; + } else if ((bflags & BFLAGS_NonPublic) && method_nonpublic (method, (klass == startklass))) { + match++; + } + if (!match) + continue; + match = 0; + if (method->flags & METHOD_ATTRIBUTE_STATIC) { + if (bflags & BFLAGS_Static) + if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass)) + match++; + } else { + if (bflags & BFLAGS_Instance) + match++; + } + + if (!match) + continue; + + if (name != NULL) { + if (compare_func (name, method->name)) + continue; + } + + match = 0; + g_ptr_array_add (array, method); + } + if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent)) + goto handle_parent; + /*if (method_slots != method_slots_default) + g_free (method_slots);*/ + + return array; +} + +gpointer il2cpp_mono_ldtoken_checked(MonoImage* image, guint32 token, MonoClass** handle_class, MonoGenericContext* context, MonoError* error) +{ + IL2CPP_ASSERT(0 && "This method is not yet implemented"); + return 0; +} + +MonoClass* il2cpp_mono_class_from_generic_parameter_internal(MonoGenericParam* param) +{ + return (MonoClass*)il2cpp::vm::Class::FromGenericParameter((Il2CppGenericParameter*)param); +} + +MonoClass* il2cpp_mono_class_load_from_name(MonoImage* image, const char* name_space, const char* name) +{ + IL2CPP_ASSERT(0 && "This method is not yet implemented"); + return NULL; +} + +MonoGenericClass* il2cpp_mono_class_get_generic_class(MonoClass* monoClass) +{ + Il2CppClass *klass = (Il2CppClass*)monoClass; + return (MonoGenericClass*)klass->generic_class; +} + +MonoInternalThread* il2cpp_mono_thread_internal_current() +{ + return (MonoInternalThread*)(((Il2CppThread*)il2cpp_mono_thread_current())->internal_thread); +} + +gboolean il2cpp_mono_thread_internal_is_current(MonoInternalThread* thread) +{ + return il2cpp_mono_thread_internal_current () == thread; +} + +void il2cpp_mono_thread_internal_abort(MonoInternalThread* thread, gboolean appdomain_unload) +{ + il2cpp::vm::Thread::RequestAbort((Il2CppInternalThread*)thread); +} + +void il2cpp_mono_thread_internal_reset_abort(MonoInternalThread* thread) +{ + il2cpp::vm::Thread::ResetAbort((Il2CppInternalThread*)thread); +} + +gunichar2* il2cpp_mono_thread_get_name(MonoInternalThread* this_obj, guint32* name_len) +{ + std::string name = il2cpp::vm::Thread::GetName((Il2CppInternalThread*)this_obj); + + if (name_len != NULL) + *name_len = name.size(); + + if (name.empty()) + return NULL; + return g_utf8_to_utf16(name.c_str(), name.size(), NULL, NULL, NULL); +} + +void il2cpp_mono_thread_set_name_internal(MonoInternalThread* this_obj, MonoString* name, gboolean permanent, gboolean reset, MonoError* error) +{ + il2cpp::vm::Thread::SetName((Il2CppInternalThread*)this_obj, (Il2CppString*)name); + error_init(error); +} + +void il2cpp_mono_thread_suspend_all_other_threads() +{ + IL2CPP_ASSERT(0 && "This method is not yet implemented"); +} + +void il2cpp_mono_stack_mark_record_size(MonoThreadInfo* info, HandleStackMark* stackmark, const char* func_name) +{ + IL2CPP_ASSERT(0 && "This method is not yet implemented"); +} + +Il2CppMonoRuntimeExceptionHandlingCallbacks* il2cpp_mono_get_eh_callbacks() +{ + IL2CPP_ASSERT(0 && "This method is not yet implemented"); + return NULL; +} + +void il2cpp_mono_nullable_init(guint8* buf, MonoObject* value, MonoClass* klass) +{ + il2cpp::vm::Object::NullableInit(buf, (Il2CppObject*)value, (Il2CppClass*)klass); +} + +MonoObject* il2cpp_mono_value_box_checked(MonoDomain* domain, MonoClass* klass, gpointer value, MonoError* error) +{ + error_init(error); + return (MonoObject*)il2cpp::vm::Object::Box((Il2CppClass*)klass, value); +} + +void il2cpp_mono_field_static_get_value_checked(MonoVTable* vt, MonoClassField* field, void* value, MonoError* error) +{ + error_init(error); + il2cpp::vm::Field::StaticGetValue((FieldInfo*)field, value); +} + +void il2cpp_mono_field_static_get_value_for_thread(MonoInternalThread* thread, MonoVTable* vt, MonoClassField* field, void* value, MonoError* error) +{ + error_init(error); + il2cpp::vm::Field::StaticGetValueForThread((FieldInfo*)field, value, (Il2CppInternalThread*)thread); +} + +MonoObject* il2cpp_mono_field_get_value_object_checked(MonoDomain* domain, MonoClassField* field, MonoObject* obj, MonoError* error) +{ + IL2CPP_ASSERT(0 && "This method is not yet implemented"); + return NULL; +} + +MonoObject* il2cpp_mono_object_new_checked(MonoDomain* domain, MonoClass* klass, MonoError* error) +{ + error_init(error); + return (MonoObject*)il2cpp::vm::Object::New((Il2CppClass*)klass); +} + +MonoString* il2cpp_mono_ldstr_checked(MonoDomain* domain, MonoImage* image, guint32 idx, MonoError* error) +{ + IL2CPP_ASSERT(0 && "This method is not yet implemented"); + return NULL; +} + +MonoObject* il2cpp_mono_runtime_try_invoke(MonoMethod* method, void* obj, void** params, MonoObject** exc, MonoError* error) +{ + error_init(error); + + if (((MethodInfo*)method)->klass->valuetype) + obj = static_cast(obj) - 1; + + return (MonoObject*)il2cpp::vm::Runtime::Invoke((MethodInfo*)method, obj, params, (Il2CppException**)exc); +} + +MonoObject* il2cpp_mono_runtime_invoke_checked(MonoMethod* method, void* obj, void** params, MonoError* error) +{ + IL2CPP_ASSERT(0 && "This method is not yet implemented"); + return NULL; +} + +void il2cpp_mono_gc_base_init() +{ +} + +static il2cpp::os::Mutex s_il2cpp_gc_root_lock(false); +int il2cpp_mono_gc_register_root(char* start, size_t size, MonoGCDescriptor descr, MonoGCRootSource source, const char* msg) +{ + il2cpp::gc::GarbageCollector::RegisterRoot(start, size); + return 1; +} + +void il2cpp_mono_gc_deregister_root(char* addr) +{ + il2cpp::gc::GarbageCollector::UnregisterRoot(addr); +} + +#ifndef HOST_WIN32 +int il2cpp_mono_gc_pthread_create (pthread_t *new_thread, const pthread_attr_t *attr, void *(*start_routine)(void *), void *arg) +{ + IL2CPP_ASSERT(0 && "This method is not yet implemented"); + return 0; +} +#endif + +gboolean il2cpp_mono_gc_is_moving() +{ + return FALSE; +} + +gint32 il2cpp_mono_environment_exitcode_get() +{ + return il2cpp::vm::Runtime::GetExitCode(); +} + +void il2cpp_mono_environment_exitcode_set(gint32 value) +{ + IL2CPP_ASSERT(0 && "This method is not yet implemented"); +} + +void il2cpp_mono_threadpool_suspend() +{ +#if NET_4_0 + il2cpp::vm::ThreadPoolMs::Suspend(); +#endif // NET_4_0 +} + +void il2cpp_mono_threadpool_resume() +{ +#if NET_4_0 + il2cpp::vm::ThreadPoolMs::Resume(); +#endif // NET_4_0 +} + +MonoImage* il2cpp_mono_assembly_get_image(MonoAssembly* assembly) +{ + return (MonoImage*)il2cpp::vm::Assembly::GetImage((Il2CppAssembly*)assembly); +} + +gboolean il2cpp_mono_runtime_try_shutdown() +{ + il2cpp::vm::Runtime::Shutdown(); + return TRUE; +} + +gboolean il2cpp_mono_verifier_is_method_valid_generic_instantiation(MonoMethod* method) +{ + if (!method) + return FALSE; + + if (!((MethodInfo*)method)->is_generic && ((MethodInfo*)method)->is_inflated && ((MethodInfo*)method)->methodPointer) + return TRUE; + + return FALSE; +} + +MonoType* il2cpp_mono_reflection_get_type_checked(MonoImage* rootimage, MonoImage* image, Il2CppMonoTypeNameParse* info, gboolean ignorecase, gboolean* type_resolve, MonoError* error) +{ + error_init(error); + + Il2CppClass *klass = il2cpp::vm::Image::FromTypeNameParseInfo((Il2CppImage*)image, *((il2cpp::vm::TypeNameParseInfo*)info->il2cppTypeNameParseInfo), ignorecase); + if (!klass) + return NULL; + + return (MonoType*)il2cpp::vm::Class::GetType(klass); +} + +MonoReflectionAssemblyHandle il2cpp_mono_assembly_get_object_handle(MonoDomain* domain, MonoAssembly* assembly, MonoError* error) +{ + return (MonoReflectionAssemblyHandle)il2cpp::vm::Reflection::GetAssemblyObject((const Il2CppAssembly *)assembly); +} + +MonoReflectionType* il2cpp_mono_type_get_object_checked(MonoDomain* domain, MonoType* type, MonoError* error) +{ + error_init(error); + return (MonoReflectionType*)il2cpp::vm::Reflection::GetTypeObject((const Il2CppType*)type); +} + +void il2cpp_mono_network_init() +{ +} + +gint il2cpp_mono_w32socket_set_blocking(void* sock, gboolean blocking) +{ + IL2CPP_ASSERT(0 && "This method is not yet implemented"); + return 0; +} + +char* il2cpp_mono_get_runtime_build_info() +{ + return g_strdup_printf ("%s (%s)", "0.0", "IL2CPP"); +} + +MonoMethod* il2cpp_mono_marshal_method_from_wrapper(MonoMethod* wrapper) +{ + IL2CPP_ASSERT(0 && "This method is not yet implemented"); + return NULL; +} + +Il2CppMonoDebugOptions* il2cpp_mini_get_debug_options() +{ + IL2CPP_ASSERT(0 && "This method is not yet implemented"); + return NULL; +} + +gpointer il2cpp_mono_jit_find_compiled_method_with_jit_info(MonoDomain* domain, MonoMethod* method, MonoJitInfo** ji) +{ + IL2CPP_ASSERT(0 && "This method is not yet implemented"); + return 0; +} + +Il2CppMonoLMF** il2cpp_mono_get_lmf_addr() +{ + IL2CPP_ASSERT(0 && "This method is not yet implemented"); + return NULL; +} + +void il2cpp_mono_set_lmf(Il2CppMonoLMF* lmf) +{ + IL2CPP_ASSERT(0 && "This method is not yet implemented"); +} + +gpointer il2cpp_mono_aot_get_method_checked(MonoDomain* domain, MonoMethod* method, MonoError* error) +{ + IL2CPP_ASSERT(0 && "This method is not yet implemented"); + return 0; +} + +void il2cpp_mono_arch_setup_resume_sighandler_ctx(MonoContext* ctx, gpointer func) +{ + IL2CPP_ASSERT(0 && "This method is not yet implemented"); +} + +void il2cpp_mono_arch_set_breakpoint(MonoJitInfo* ji, guint8* ip) +{ + IL2CPP_ASSERT(0 && "This method is not yet implemented"); +} + +void il2cpp_mono_arch_clear_breakpoint(MonoJitInfo* ji, guint8* ip) +{ + IL2CPP_ASSERT(0 && "This method is not yet implemented"); +} + +void il2cpp_mono_arch_start_single_stepping() +{ + //IL2CPP_ASSERT(0 && "This method is not yet implemented"); +} + +void il2cpp_mono_arch_stop_single_stepping() +{ + //IL2CPP_ASSERT(0 && "This method is not yet implemented"); +} + +void il2cpp_mono_arch_skip_breakpoint(MonoContext* ctx, MonoJitInfo* ji) +{ + IL2CPP_ASSERT(0 && "This method is not yet implemented"); +} + +void il2cpp_mono_arch_skip_single_step(MonoContext* ctx) +{ + IL2CPP_ASSERT(0 && "This method is not yet implemented"); +} + +mgreg_t il2cpp_mono_arch_context_get_int_reg(MonoContext* ctx, int reg) +{ + IL2CPP_ASSERT(0 && "This method is not yet implemented"); + return 0; +} + +void il2cpp_mono_arch_context_set_int_reg(MonoContext* ctx, int reg, mgreg_t val) +{ + IL2CPP_ASSERT(0 && "This method is not yet implemented"); +} + +void il2cpp_mono_walk_stack_with_ctx(Il2CppMonoJitStackWalk func, MonoContext* start_ctx, MonoUnwindOptions unwind_options, void* user_data) +{ + IL2CPP_ASSERT(0 && "This method is not yet implemented"); +} + +void il2cpp_mono_walk_stack_with_state(Il2CppMonoJitStackWalk func, MonoThreadUnwindState* state, MonoUnwindOptions unwind_options, void* user_data) +{ + IL2CPP_ASSERT(0 && "This method is not yet implemented"); +} + +gboolean il2cpp_mono_thread_state_init_from_current(MonoThreadUnwindState* ctx) +{ + IL2CPP_ASSERT(0 && "This method is not yet implemented"); + return 0; +} + +gboolean il2cpp_mono_thread_state_init_from_monoctx(MonoThreadUnwindState* ctx, MonoContext* mctx) +{ + IL2CPP_ASSERT(0 && "This method is not yet implemented"); + return 0; +} + +MonoJitInfo* il2cpp_mini_jit_info_table_find(MonoDomain* domain, char* addr, MonoDomain** out_domain) +{ + IL2CPP_ASSERT(0 && "This method is not yet implemented"); + return NULL; +} + +void il2cpp_mono_restore_context(MonoContext* ctx) +{ + IL2CPP_ASSERT(0 && "This method is not yet implemented"); +} + +MonoMethod* il2cpp_mono_method_get_declaring_generic_method(MonoMethod* method) +{ + IL2CPP_ASSERT(0 && "This method is not yet implemented"); + return NULL; +} + +gboolean il2cpp_mono_error_ok (MonoError *error) +{ + IL2CPP_ASSERT(0 && "This method is not yet implemented"); + return 0; +} + +MonoMethod* il2cpp_jinfo_get_method (MonoJitInfo *ji) +{ + IL2CPP_ASSERT(0 && "This method is not yet implemented"); + return NULL; +} + +gboolean il2cpp_mono_find_prev_seq_point_for_native_offset (MonoDomain *domain, MonoMethod *method, gint32 native_offset, MonoSeqPointInfo **info, SeqPoint* seq_point) +{ + IL2CPP_ASSERT(0 && "This method is not yet implemented"); + return 0; +} + +void il2cpp_mono_error_cleanup (MonoError *oerror) +{ +} + +void il2cpp_mono_error_init (MonoError *error) +{ + IL2CPP_ASSERT(0 && "This method is not yet implemented"); +} + +void* il2cpp_mono_w32socket_accept_internal (void* s, struct sockaddr *addr, void *addrlen, gboolean blocking) +{ + IL2CPP_ASSERT(0 && "This method is not yet implemented"); + return 0; +} + +gboolean il2cpp_mono_find_next_seq_point_for_native_offset (MonoDomain *domain, MonoMethod *method, gint32 native_offset, MonoSeqPointInfo **info, SeqPoint* seq_point) +{ + IL2CPP_ASSERT(0 && "This method is not yet implemented"); + return 0; +} + +gboolean il2cpp_mono_class_has_parent (MonoClass *klass, MonoClass *parent) +{ + IL2CPP_ASSERT(0 && "This method is not yet implemented"); + return 0; +} + +MonoGenericParam* il2cpp_mono_generic_container_get_param (MonoGenericContainer *gc, int i) +{ + return (MonoGenericParam*)il2cpp::vm::GenericContainer::GetGenericParameter((Il2CppGenericContainer*)gc, i); +} + +gboolean il2cpp_mono_find_seq_point (MonoDomain *domain, MonoMethod *method, gint32 il_offset, MonoSeqPointInfo **info, SeqPoint *seq_point) +{ + IL2CPP_ASSERT(0 && "This method is not yet implemented"); + return 0; +} + +void il2cpp_mono_seq_point_iterator_init (SeqPointIterator* it, MonoSeqPointInfo* info) +{ + IL2CPP_ASSERT(0 && "This method is not yet implemented"); +} + +gboolean il2cpp_mono_seq_point_iterator_next (SeqPointIterator* it) +{ + IL2CPP_ASSERT(0 && "This method is not yet implemented"); + return 0; +} + +void il2cpp_mono_seq_point_init_next (MonoSeqPointInfo* info, SeqPoint sp, SeqPoint* next) +{ + IL2CPP_ASSERT(0 && "This method is not yet implemented"); +} + +MonoSeqPointInfo* il2cpp_mono_get_seq_points (MonoDomain *domain, MonoMethod *method) +{ + IL2CPP_ASSERT(0 && "This method is not yet implemented"); + return NULL; +} + +void IL2CPP_G_BREAKPOINT() +{ + IL2CPP_ASSERT(0 && "This method is not yet implemented"); +} + +void il2cpp_mono_thread_info_safe_suspend_and_run (MonoNativeThreadId id, gboolean interrupt_kernel, MonoSuspendThreadCallback callback, gpointer user_data) +{ + callback(NULL, user_data); +} + +MonoException* il2cpp_mono_error_convert_to_exception (MonoError *target_error) +{ + IL2CPP_ASSERT(0 && "This method is not yet implemented"); + return NULL; +} + +const char* il2cpp_mono_error_get_message (MonoError *oerror) +{ + IL2CPP_ASSERT(0 && "This method is not yet implemented"); + return NULL; +} + +void il2cpp_mono_error_assert_ok_pos (MonoError *error, const char* filename, int lineno) +{ + if (error->error_code == MONO_ERROR_NONE) + return; + + g_error ("%s:%d\n", filename, lineno); +} + +void* il2cpp_mono_gc_alloc_fixed (size_t size, void* descr, MonoGCRootSource source, void *key, const char *msg) +{ + return il2cpp_gc_alloc_fixed(size); +} + +typedef void* (*Il2CppMonoGCLockedCallbackFunc) (void *data); +void* il2cpp_mono_gc_invoke_with_gc_lock (Il2CppMonoGCLockedCallbackFunc func, void *data) +{ + return il2cpp::gc::GarbageCollector::CallWithAllocLockHeld (func, data); +} + +// These functions expose the IL2CPP VM C++ API to C + +void* il2cpp_domain_get_agent_info(MonoAppDomain* domain) +{ + return ((Il2CppDomain*)domain)->agent_info; +} + +void il2cpp_domain_set_agent_info(MonoAppDomain* domain, void* agentInfo) +{ + ((Il2CppDomain*)domain)->agent_info = agentInfo; +} + +MonoAssembly* il2cpp_domain_get_assemblies_iter(MonoAppDomain *domain, void* *iter) +{ + if (!iter) + return NULL; + + il2cpp::vm::AssemblyVector* assemblies = il2cpp::vm::Assembly::GetAllAssemblies(); + + if (!*iter) + { + il2cpp::vm::AssemblyVector::iterator *pIter = new il2cpp::vm::AssemblyVector::iterator(); + *pIter = assemblies->begin(); + *iter = pIter; + return (MonoAssembly*)**pIter; + } + + il2cpp::vm::AssemblyVector::iterator *pIter = (il2cpp::vm::AssemblyVector::iterator*)*iter; + (*pIter)++; + if (*pIter != assemblies->end()) + { + return (MonoAssembly*)(**pIter); + } + else + { + delete pIter; + *iter = NULL; + } + + return NULL; +} + +void il2cpp_start_debugger_thread() +{ +#if IL2CPP_MONO_DEBUGGER + il2cpp::utils::Debugger::StartDebuggerThread(); +#endif +} + +void* il2cpp_gc_alloc_fixed(size_t size) +{ + return il2cpp::gc::GarbageCollector::AllocateFixed(size, NULL); +} + +void il2cpp_gc_free_fixed(void* address) +{ + il2cpp::gc::GarbageCollector::FreeFixed(address); +} + +const char* il2cpp_domain_get_name(MonoDomain* domain) +{ + return ((Il2CppDomain*)domain)->friendly_name; +} + +Il2CppSequencePoint* il2cpp_get_sequence_points(void* *iter) +{ +#if IL2CPP_MONO_DEBUGGER + return (Il2CppSequencePoint*)il2cpp::utils::Debugger::GetSequencePoints(iter); +#else + return NULL; +#endif +} + +Il2CppSequencePoint* il2cpp_get_method_sequence_points(MonoMethod* method, void* *iter) +{ +#if IL2CPP_MONO_DEBUGGER + if (!method) + return (Il2CppSequencePoint*)il2cpp::utils::Debugger::GetSequencePoints(iter); + else + return (Il2CppSequencePoint*)il2cpp::utils::Debugger::GetSequencePoints((const MethodInfo*)method, iter); +#else + return NULL; +#endif +} + +gboolean il2cpp_mono_methods_match(MonoMethod* left, MonoMethod* right) +{ + MethodInfo* leftMethod = (MethodInfo*)left; + MethodInfo* rightMethod = (MethodInfo*)right; + + if (rightMethod == leftMethod) + return TRUE; + if (rightMethod == NULL || leftMethod == NULL) + return FALSE; + if (rightMethod->is_inflated && !rightMethod->is_generic && rightMethod->genericMethod->methodDefinition == leftMethod) + return TRUE; + if (leftMethod->is_inflated && !leftMethod->is_generic && leftMethod->genericMethod->methodDefinition == rightMethod) + return TRUE; + if (leftMethod->is_generic && rightMethod->is_inflated && rightMethod->methodPointer && + leftMethod->klass == rightMethod->klass && + strcmp(leftMethod->name, rightMethod->name) == 0) + { + if (leftMethod->parameters_count != rightMethod->parameters_count) + return FALSE; + + for(int i = 0;i < leftMethod->parameters_count;++i) + { + if ((leftMethod->parameters[i].parameter_type->type != IL2CPP_TYPE_MVAR) && (leftMethod->parameters[i].parameter_type->type != IL2CPP_TYPE_VAR) && (leftMethod->parameters[i].parameter_type != rightMethod->parameters[i].parameter_type)) + return FALSE; + } + + return TRUE; + } + + return FALSE; +} + +MonoClass* il2cpp_class_get_nested_types_accepts_generic(MonoClass *monoClass, void* *iter) +{ + Il2CppClass *klass = (Il2CppClass*)monoClass; + if (klass->generic_class) + return NULL; + + return (MonoClass*)il2cpp::vm::Class::GetNestedTypes(klass, iter); +} + +MonoClass* il2cpp_defaults_object_class() +{ + return (MonoClass*)il2cpp_defaults.object_class; +} + +guint8 il2cpp_array_rank(MonoArray *monoArr) +{ + Il2CppArray *arr = (Il2CppArray*)monoArr; + return arr->klass->rank; +} + +const char* il2cpp_image_name(MonoImage *monoImage) +{ + Il2CppImage *image = (Il2CppImage*)monoImage; + return image->name; +} + +guint8* il2cpp_field_get_address(MonoObject *obj, MonoClassField *monoField) +{ + FieldInfo *field = (FieldInfo*)monoField; + return (guint8*)obj + field->offset; +} + +MonoType* il2cpp_mono_object_get_type(MonoObject* object) +{ + return (MonoType*)&(((Il2CppObject*)object)->klass->byval_arg); +} + +MonoClass* il2cpp_defaults_exception_class() +{ + return (MonoClass*)il2cpp_defaults.exception_class; +} + +MonoImage* il2cpp_defaults_corlib_image() +{ + return (MonoImage*)il2cpp_defaults.corlib; +} + +bool il2cpp_method_is_string_ctor(const MonoMethod * method) +{ + MethodInfo* methodInfo = (MethodInfo*)method; + return methodInfo->klass == il2cpp_defaults.string_class && !strcmp (methodInfo->name, ".ctor"); +} + +MonoClass* il2cpp_defaults_void_class() +{ + return (MonoClass*)il2cpp_defaults.void_class; +} + +void il2cpp_set_var(guint8* newValue, void *value, MonoType *localVariableTypeMono) +{ + il2cpp::metadata::SizeAndAlignment sa = il2cpp::metadata::FieldLayout::GetTypeSizeAndAlignment((const Il2CppType*)localVariableTypeMono); + if (((Il2CppType*)localVariableTypeMono)->byref) + memcpy(*(void**)value, newValue, sa.size); + else + memcpy(value, newValue, sa.size); +} + +MonoMethod* il2cpp_get_interface_method(MonoClass* klass, MonoClass* itf, int slot) +{ + const VirtualInvokeData* data = il2cpp::vm::Class::GetInterfaceInvokeDataFromVTable((Il2CppClass*)klass, (Il2CppClass*)itf, slot); + if (!data) + return NULL; + + return (MonoMethod*)data->method; +} + +gboolean il2cpp_field_is_deleted(MonoClassField *field) +{ + return il2cpp::vm::Field::IsDeleted((FieldInfo*)field); +} + +struct TypeIterState +{ + il2cpp::vm::AssemblyVector* assemblies; + il2cpp::vm::AssemblyVector::iterator assembly; + Il2CppImage* image; + il2cpp::vm::TypeVector types; + il2cpp::vm::TypeVector::iterator type; +}; + +MonoClass* il2cpp_iterate_loaded_classes(void* *iter) +{ + if (!iter) + return NULL; + + if (!*iter) + { + TypeIterState *state = new TypeIterState(); + state->assemblies = il2cpp::vm::Assembly::GetAllAssemblies(); + state->assembly = state->assemblies->begin(); + state->image = il2cpp::vm::Assembly::GetImage(*state->assembly); + il2cpp::vm::Image::GetTypes(state->image, true, &state->types); + state->type = state->types.begin(); + *iter = state; + return (MonoClass*)*state->type; + } + + TypeIterState *state = (TypeIterState*)*iter; + + state->type++; + if (state->type == state->types.end()) + { + state->assembly++; + if (state->assembly == state->assemblies->end()) + { + delete state; + *iter = NULL; + return NULL; + } + + state->image = il2cpp::vm::Assembly::GetImage(*state->assembly); + il2cpp::vm::Image::GetTypes(state->image, true, &state->types); + state->type = state->types.begin(); + } + + return (MonoClass*)*state->type; +} + +const char** il2cpp_get_source_files_for_type(MonoClass *klass, int *count) +{ +#if IL2CPP_MONO_DEBUGGER + return il2cpp::utils::Debugger::GetTypeSourceFiles((Il2CppClass*)klass, *count); +#else + return NULL; +#endif +} + +MonoMethod* il2cpp_method_get_generic_definition(MonoMethodInflated *imethod) +{ + MethodInfo *method = (MethodInfo*)imethod; + + if (!method->is_inflated || method->is_generic) + return NULL; + + return (MonoMethod*)((MethodInfo*)imethod)->genericMethod->methodDefinition; +} + + +MonoGenericInst* il2cpp_method_get_generic_class_inst(MonoMethodInflated *imethod) +{ + MethodInfo *method = (MethodInfo*)imethod; + + if (!method->is_inflated || method->is_generic) + return NULL; + + return (MonoGenericInst*)method->genericMethod->context.class_inst; +} + +MonoClass* il2cpp_generic_class_get_container_class(MonoGenericClass *gclass) +{ + return (MonoClass*)il2cpp::vm::GenericClass::GetTypeDefinition((Il2CppGenericClass*)gclass); +} + + +MonoClass* il2cpp_mono_get_string_class (void) +{ + return (MonoClass*)il2cpp_defaults.string_class; +} + +Il2CppSequencePoint* il2cpp_get_sequence_point(int id) +{ +#if IL2CPP_MONO_DEBUGGER + return il2cpp::utils::Debugger::GetSequencePoint(id); +#else + return NULL; +#endif +} + +char* il2cpp_assembly_get_full_name(MonoAssembly *assembly) +{ + std::string s = il2cpp::vm::AssemblyName::AssemblyNameToString(assembly->aname); + return g_strdup(s.c_str()); +} + +const MonoMethod* il2cpp_get_seq_point_method(Il2CppSequencePoint *seqPoint) +{ +#if IL2CPP_MONO_DEBUGGER + return il2cpp::utils::Debugger::GetSequencePointMethod(seqPoint); +#else + return NULL; +#endif +} + +const MonoClass* il2cpp_get_class_from_index(int index) +{ + if (index < 0) + return NULL; + + return il2cpp::vm::MetadataCache::GetTypeInfoFromTypeIndex(index); +} + +const MonoType* il2cpp_get_type_from_index(int index) +{ + return il2cpp::vm::MetadataCache::GetIl2CppTypeFromIndex(index); +} + +} +#endif // RUNTIME_IL2CPP diff --git a/mono/mini/method-to-ir.c b/mono/mini/method-to-ir.c index ed9001779cf9..c85f78df9119 100644 --- a/mono/mini/method-to-ir.c +++ b/mono/mini/method-to-ir.c @@ -3653,6 +3653,14 @@ handle_alloc (MonoCompile *cfg, MonoClass *klass, gboolean for_box, int context_ MonoInst *iargs [2]; void *alloc_ftn; + if (mono_class_get_flags (klass) & TYPE_ATTRIBUTE_ABSTRACT) { + char* full_name = mono_type_get_full_name (klass); + cfg->exception_message = g_strdup_printf ("Cannot create an abstract class: %s", full_name); + g_free (full_name); + mono_cfg_set_exception (cfg, MONO_EXCEPTION_MEMBER_ACCESS); + return NULL; + } + if (context_used) { MonoInst *data; MonoRgctxInfoType rgctx_info; diff --git a/mono/mini/mini-amd64.c b/mono/mini/mini-amd64.c index 4b7a7cc77507..309dcd95c2ff 100644 --- a/mono/mini/mini-amd64.c +++ b/mono/mini/mini-amd64.c @@ -606,7 +606,7 @@ add_valuetype_win64 (MonoMethodSignature *signature, ArgInfo *arg_info, MonoType get_valuetype_size_win64 (klass, signature->pinvoke, arg_info, type, &arg_class, &arg_size); /* Only drop value type if its not an empty struct as input that must be represented in call */ - if ((arg_size == 0 && !arg_info->pass_empty_struct) || (arg_size == 0 && arg_info->pass_empty_struct && is_return)) { + if ((arg_size == 0 && !arg_info->pass_empty_struct) || (arg_info->pass_empty_struct && is_return)) { arg_info->storage = ArgValuetypeInReg; arg_info->pair_storage [0] = arg_info->pair_storage [1] = ArgNone; } else { @@ -2228,7 +2228,8 @@ mono_arch_emit_outarg_vt (MonoCompile *cfg, MonoInst *ins, MonoInst *src) g_assert (ainfo->storage == ArgValuetypeAddrInIReg || (ainfo->storage == ArgValuetypeAddrOnStack && ainfo->pair_storage [0] == ArgNone)); vtaddr = mono_compile_create_var (cfg, &ins->klass->byval_arg, OP_LOCAL); - + vtaddr->backend.is_pinvoke = call->signature->pinvoke; + MONO_INST_NEW (cfg, load, OP_LDADDR); cfg->has_indirection = TRUE; load->inst_p0 = vtaddr; diff --git a/mono/mini/mini-arm.c b/mono/mini/mini-arm.c index 75e4fd098a4e..b2601706af5d 100644 --- a/mono/mini/mini-arm.c +++ b/mono/mini/mini-arm.c @@ -1524,7 +1524,7 @@ get_call_info (MonoMemPool *mp, MonoMethodSignature *sig) ainfo->storage = RegTypeStructByVal; ainfo->struct_size = size; ainfo->align = align; - /* FIXME: align stack_size if needed */ + if (eabi_supported) { if (align >= 8 && (gr & 1)) gr ++; @@ -1542,9 +1542,8 @@ get_call_info (MonoMemPool *mp, MonoMethodSignature *sig) gr += n_in_regs; nwords -= n_in_regs; } - if (sig->call_convention == MONO_CALL_VARARG) - /* This matches the alignment in mono_ArgIterator_IntGetNextArg () */ - stack_size = ALIGN_TO (stack_size, align); + stack_size = ALIGN_TO (stack_size, align); + ainfo->offset = stack_size; /*g_print ("offset for arg %d at %d\n", n, stack_size);*/ stack_size += nwords * sizeof (gpointer); diff --git a/mono/mini/mini-runtime.c b/mono/mini/mini-runtime.c index 6a27b69fc127..472787db6ac8 100644 --- a/mono/mini/mini-runtime.c +++ b/mono/mini/mini-runtime.c @@ -85,6 +85,7 @@ #include "mini-llvm.h" #include "debugger-agent.h" #include "lldb.h" +#include "mixed_callstack_plugin.h" #include "mini-runtime.h" #ifdef MONO_ARCH_LLVM_SUPPORTED @@ -498,6 +499,7 @@ mono_tramp_info_register_internal (MonoTrampInfo *info, MonoDomain *domain, gboo mono_save_trampoline_xdebug_info (info); mono_lldb_save_trampoline_info (info); + mixed_callstack_plugin_save_trampoline_info (info); #ifdef MONO_ARCH_HAVE_UNWIND_TABLE if (!aot) @@ -3431,6 +3433,8 @@ mini_parse_debug_option (const char *option) debug_options.gdb = TRUE; else if (!strcmp (option, "lldb")) debug_options.lldb = TRUE; + else if (!strcmp (option, "unity-mixed-callstack")) + debug_options.unity_mixed_callstack = TRUE; else if (!strcmp (option, "explicit-null-checks")) debug_options.explicit_null_checks = TRUE; else if (!strcmp (option, "gen-seq-points")) @@ -3920,6 +3924,9 @@ mini_init (const char *filename, const char *runtime_version) mono_lldb_init (""); mono_dont_free_domains = TRUE; } + if (mini_get_debug_options()->unity_mixed_callstack || g_hasenv ("UNITY_MIXED_CALLSTACK")) { + mixed_callstack_plugin_init (""); + } #ifdef XDEBUG_ENABLED char *mono_xdebug = g_getenv ("MONO_XDEBUG"); diff --git a/mono/mini/mini-trampolines.c b/mono/mini/mini-trampolines.c index 9558c9132576..30fa8daf2914 100644 --- a/mono/mini/mini-trampolines.c +++ b/mono/mini/mini-trampolines.c @@ -21,6 +21,7 @@ #include "mini.h" #include "lldb.h" +#include "mixed_callstack_plugin.h" #include "aot-runtime.h" #include "mini-runtime.h" @@ -1384,6 +1385,7 @@ mono_create_specific_trampoline (gpointer arg1, MonoTrampolineType tramp_type, M else code = mono_arch_create_specific_trampoline (arg1, tramp_type, domain, &len); mono_lldb_save_specific_trampoline_info (arg1, tramp_type, domain, code, len); + mixed_callstack_plugin_save_specific_trampoline_info (arg1, tramp_type, domain, code, len); if (code_len) *code_len = len; return code; diff --git a/mono/mini/mini-unity.c b/mono/mini/mini-unity.c new file mode 100644 index 000000000000..84cd5567bbb4 --- /dev/null +++ b/mono/mini/mini-unity.c @@ -0,0 +1,32 @@ +#include +#include + +#ifdef WIN32 + +extern LONG CALLBACK seh_vectored_exception_handler(EXCEPTION_POINTERS* ep); +LONG mono_unity_seh_handler(EXCEPTION_POINTERS* ep) +{ +#if defined(TARGET_X86) || defined(TARGET_AMD64) + return seh_vectored_exception_handler(ep); +#else + g_assert_not_reached(); +#endif +} + +int (*gUnhandledExceptionHandler)(EXCEPTION_POINTERS*) = NULL; + +void mono_unity_set_unhandled_exception_handler(void* handler) +{ + gUnhandledExceptionHandler = handler; +} + +#endif // WIN32 + +extern gboolean unity_shutting_down; + +MONO_API void +mono_unity_jit_cleanup (MonoDomain *domain) +{ + unity_shutting_down = TRUE; + mono_jit_cleanup (domain); +} diff --git a/mono/mini/mini.c b/mono/mini/mini.c index bdda6265d3e9..2d3e0a3f9ee5 100644 --- a/mono/mini/mini.c +++ b/mono/mini/mini.c @@ -78,6 +78,7 @@ #include "llvm-runtime.h" #include "mini-llvm.h" #include "lldb.h" +#include "mixed_callstack_plugin.h" #include "aot-runtime.h" #include "mini-runtime.h" @@ -3861,6 +3862,7 @@ mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, JitFl if (!cfg->compile_aot) { mono_save_xdebug_info (cfg); mono_lldb_save_method_info (cfg); + mixed_callstack_plugin_save_method_info (cfg); } if (cfg->verbose_level >= 2) { @@ -4185,6 +4187,7 @@ mono_jit_compile_method_inner (MonoMethod *method, MonoDomain *target_domain, in case MONO_EXCEPTION_TYPE_LOAD: case MONO_EXCEPTION_MISSING_FIELD: case MONO_EXCEPTION_MISSING_METHOD: + case MONO_EXCEPTION_MEMBER_ACCESS: case MONO_EXCEPTION_FILE_NOT_FOUND: case MONO_EXCEPTION_BAD_IMAGE: case MONO_EXCEPTION_INVALID_PROGRAM: { @@ -4204,6 +4207,8 @@ mono_jit_compile_method_inner (MonoMethod *method, MonoDomain *target_domain, in ex = mono_get_exception_bad_image_format (cfg->exception_message); else if (cfg->exception_type == MONO_EXCEPTION_INVALID_PROGRAM) ex = mono_exception_from_name_msg (mono_defaults.corlib, "System", "InvalidProgramException", cfg->exception_message); + else if (cfg->exception_type == MONO_EXCEPTION_MEMBER_ACCESS) + ex = mono_exception_from_name_msg (mono_defaults.corlib, "System", "MemberAccessException", cfg->exception_message); else g_assert_not_reached (); } diff --git a/mono/mini/mini.h b/mono/mini/mini.h index d1618623b7bd..ca8eb0a7116a 100644 --- a/mono/mini/mini.h +++ b/mono/mini/mini.h @@ -1849,6 +1849,7 @@ typedef struct { gboolean dyn_runtime_invoke; gboolean gdb; gboolean lldb; + gboolean unity_mixed_callstack; gboolean use_fallback_tls; /* * Whenever data such as next sequence points and flags is required. diff --git a/mono/mini/mixed_callstack_plugin.c b/mono/mini/mixed_callstack_plugin.c new file mode 100644 index 000000000000..0b26dcfa6d88 --- /dev/null +++ b/mono/mini/mixed_callstack_plugin.c @@ -0,0 +1,155 @@ +#include "mixed_callstack_plugin.h" +#include "mono/metadata/mono-debug.h" +#include "mono/metadata/profiler.h" + +#if !defined(DISABLE_JIT) && defined(HOST_WIN32) + +static gboolean enabled; +static mono_mutex_t mutex; +static HANDLE fileHandle; +int pmipFileNum; + +#define mixed_callstack_plugin_lock() mono_os_mutex_lock (&mutex) +#define mixed_callstack_plugin_unlock() mono_os_mutex_unlock (&mutex) + +void +create_next_pmip_file() +{ + char* file_name = g_strdup_printf("pmip_%d_%d.txt", GetCurrentProcessId(), pmipFileNum++); + char* path = g_build_filename(g_get_tmp_dir(), file_name, NULL); + char* version = "UnityMixedCallstacks:1.0\n"; + long bytesWritten = 0; + + mixed_callstack_plugin_lock (); + + if(fileHandle) + CloseHandle(fileHandle); + + fileHandle = CreateFileA(path, + GENERIC_WRITE, + FILE_SHARE_DELETE | FILE_SHARE_READ, + NULL, + CREATE_ALWAYS, + FILE_FLAG_DELETE_ON_CLOSE, + NULL); + + if (INVALID_HANDLE_VALUE != fileHandle) + enabled = TRUE; + + WriteFile(fileHandle, version, strlen(version), &bytesWritten, NULL); + + mixed_callstack_plugin_unlock (); + + g_free(file_name); + g_free(path); +} + +void +mixed_callstack_plugin_init (const char *options) +{ + pmipFileNum = 0; + + mono_os_mutex_init_recursive(&mutex); + + MonoProfilerHandle prof = mono_profiler_create(NULL); + mono_profiler_set_domain_unloaded_callback(prof, mixed_callstack_plugin_on_domain_unload_end); + + create_next_pmip_file(); +} + +void +mixed_callstack_plugin_on_domain_unload_end() +{ + if(!enabled) + return; + + create_next_pmip_file(); +} + +void +mixed_callstack_plugin_save_method_info (MonoCompile *cfg) +{ + char* method_name; + long bytesWritten = 0; + char frame[1024]; + int bytes; + + if (!enabled) + return; + + method_name = mono_method_full_name (cfg->method, TRUE); + + bytes = snprintf (frame, sizeof (frame), "%p;%p;[%s] %s\n", cfg->native_code, ((char*)cfg->native_code) + cfg->code_size, cfg->method->klass->image->module_name, method_name); + /* negative value is encoding error */ + if (bytes < 0 || bytes > sizeof (frame)) + return; + + mixed_callstack_plugin_lock (); + WriteFile(fileHandle, frame, bytes, &bytesWritten, NULL); + mixed_callstack_plugin_unlock (); + + g_free(method_name); +} + +void +mixed_callstack_plugin_remove_method (MonoDomain *domain, MonoMethod *method, MonoJitDynamicMethodInfo *info) +{ +} + +void +mixed_callstack_plugin_save_trampoline_info (MonoTrampInfo *info) +{ + char* frame; + long bytesWritten = 0; + + if (!enabled) + return; + + mixed_callstack_plugin_lock (); + frame = g_strdup_printf ("%p;%p;%s\n", info->code, ((char*)info->code) + info->code_size, info->name ? info->name : ""); + WriteFile(fileHandle, frame, strlen(frame), &bytesWritten, NULL); + mixed_callstack_plugin_unlock (); + + g_free(frame); +} + +void +mixed_callstack_plugin_save_specific_trampoline_info (gpointer arg1, MonoTrampolineType tramp_type, MonoDomain *domain, gpointer code, guint32 code_len) +{ + +} + +#else + +void +mixed_callstack_plugin_init (const char *options) +{ + g_error ("Only Available On Windows With Jit Enabled"); +} + +void +mixed_callstack_plugin_on_domain_unload_end() +{ +} + +void +mixed_callstack_plugin_save_method_info (MonoCompile *cfg) +{ +} + +void +mixed_callstack_plugin_save_trampoline_info (MonoTrampInfo *info) +{ +} + +void +mixed_callstack_plugin_remove_method (MonoDomain *domain, MonoMethod *method, MonoJitDynamicMethodInfo *info) +{ +} + +void +mixed_callstack_plugin_save_specific_trampoline_info (gpointer arg1, MonoTrampolineType tramp_type, MonoDomain *domain, gpointer code, guint32 code_len) +{ +} + +#endif diff --git a/mono/mini/mixed_callstack_plugin.h b/mono/mini/mixed_callstack_plugin.h new file mode 100644 index 000000000000..89935824e7dd --- /dev/null +++ b/mono/mini/mixed_callstack_plugin.h @@ -0,0 +1,18 @@ +#ifndef __MIXED_CALLSTACK_PLUGIN_H__ +#define __MIXED_CALLSTACK_PLUGIN_H__ + +#include "config.h" +#include "mini.h" + +void mixed_callstack_plugin_init (const char *options); + +void mixed_callstack_plugin_save_method_info (MonoCompile *cfg); + +void mixed_callstack_plugin_save_trampoline_info (MonoTrampInfo *info); + +void mixed_callstack_plugin_remove_method (MonoDomain *domain, MonoMethod *method, MonoJitDynamicMethodInfo *info); + +void mixed_callstack_plugin_save_specific_trampoline_info (gpointer arg1, MonoTrampolineType tramp_type, MonoDomain *domain, gpointer code, guint32 code_len); + +void mixed_callstack_plugin_on_domain_unload_end(); +#endif diff --git a/mono/profiler/log-args.c b/mono/profiler/log-args.c index 0c8bd040a386..3c707283859d 100644 --- a/mono/profiler/log-args.c +++ b/mono/profiler/log-args.c @@ -27,6 +27,7 @@ static NameAndMask event_list[] = { { "counters", PROFLOG_COUNTER_EVENTS }, { "alloc", PROFLOG_ALLOC_ALIAS, PROFLOG_ALLOC_ALIAS | PROFLOG_GC_ROOT_EVENTS }, + { "fileio", PROFLOG_FILEIO_EVENTS }, { "legacy", PROFLOG_LEGACY_ALIAS }, }; diff --git a/mono/profiler/log.c b/mono/profiler/log.c index e0c19bed121e..c31f386edde0 100644 --- a/mono/profiler/log.c +++ b/mono/profiler/log.c @@ -112,7 +112,10 @@ static gint32 sync_points_ctr, coverage_methods_ctr, coverage_statements_ctr, coverage_classes_ctr, - coverage_assemblies_ctr; + coverage_assemblies_ctr, + fileio_reads_ctr, + fileio_writes_ctr; + // Pending data to be written to the log, for a single thread. // Threads periodically flush their own LogBuffers by calling safe_send @@ -1656,6 +1659,37 @@ finalize_object_end (MonoProfiler *prof, MonoObject *obj) EXIT_LOG; } +static void +fileio (MonoProfiler *prof, uint64_t kind, uint64_t size) +{ + if (kind == 0) + { + ENTER_LOG (&fileio_writes_ctr, buf, + EVENT_SIZE /* event */ + + LEB128_SIZE /* kind */ + + LEB128_SIZE /* size */ + ); + emit_event (buf, TYPE_FILEIO); + emit_value (buf, kind); + emit_value (buf, size); + + EXIT_LOG; + } + else + { + ENTER_LOG (&fileio_reads_ctr, buf, + EVENT_SIZE /* event */ + + LEB128_SIZE /* kind */ + + LEB128_SIZE /* size */ + ); + emit_event (buf, TYPE_FILEIO); + emit_value (buf, kind); + emit_value (buf, size); + + EXIT_LOG; + } +} + static char* push_nesting (char *p, MonoClass *klass) { @@ -4416,6 +4450,28 @@ proflog_icall_SetGCAllocationEvents (MonoBoolean value) mono_coop_mutex_unlock (&log_profiler.api_mutex); } +ICALL_EXPORT MonoBoolean +proflog_icall_GetFileIOEvents (void) +{ + return ENABLED (PROFLOG_FILEIO_EVENTS); +} + +ICALL_EXPORT void +proflog_icall_SetFileIOEvents (MonoBoolean value) +{ + mono_coop_mutex_lock (&log_profiler.api_mutex); + + if (value) { + ENABLE (PROFLOG_FILEIO_EVENTS); + mono_profiler_set_fileio_callback (log_profiler.handle, fileio); + } else { + DISABLE (PROFLOG_FILEIO_EVENTS); + mono_profiler_set_fileio_callback (log_profiler.handle, NULL); + } + + mono_coop_mutex_unlock (&log_profiler.api_mutex); +} + ICALL_EXPORT MonoBoolean proflog_icall_GetGCMoveEvents (void) { @@ -4604,6 +4660,8 @@ runtime_initialized (MonoProfiler *profiler) register_counter ("Event: Coverage statements", &coverage_statements_ctr); register_counter ("Event: Coverage classes", &coverage_classes_ctr); register_counter ("Event: Coverage assemblies", &coverage_assemblies_ctr); + register_counter ("Event: File IO reads", &fileio_reads_ctr); + register_counter ("Event: File IO writes", &fileio_writes_ctr); counters_init (); @@ -4848,6 +4906,9 @@ mono_profiler_init_log (const char *desc) mono_profiler_set_gc_finalizing_object_callback (handle, finalize_object_begin); } + if (ENABLED (PROFLOG_FILEIO_EVENTS)) + mono_profiler_set_fileio_callback (handle, fileio); + //On Demand heapshot uses the finalizer thread to force a collection and thus a heapshot mono_profiler_set_gc_finalized_callback (handle, finalize_end); diff --git a/mono/profiler/log.h b/mono/profiler/log.h index 8ea1991e36ec..7d306a764997 100644 --- a/mono/profiler/log.h +++ b/mono/profiler/log.h @@ -386,6 +386,7 @@ enum { TYPE_RUNTIME, TYPE_COVERAGE, TYPE_META, + TYPE_FILEIO, /* extended type for TYPE_HEAP */ TYPE_HEAP_START = 0 << 4, TYPE_HEAP_END = 1 << 4, @@ -491,10 +492,11 @@ typedef enum { #define PROFLOG_COUNTER_EVENTS (1 << 8) #define PROFLOG_SAMPLE_EVENTS (1 << 9) #define PROFLOG_JIT_EVENTS (1 << 10) +#define PROFLOG_FILEIO_EVENTS (1 << 11) #define PROFLOG_ALLOC_ALIAS (PROFLOG_GC_EVENTS | PROFLOG_GC_ALLOCATION_EVENTS | PROFLOG_GC_MOVE_EVENTS) #define PROFLOG_HEAPSHOT_ALIAS (PROFLOG_GC_EVENTS | PROFLOG_GC_ROOT_EVENTS) -#define PROFLOG_LEGACY_ALIAS (PROFLOG_EXCEPTION_EVENTS | PROFLOG_MONITOR_EVENTS | PROFLOG_GC_EVENTS | PROFLOG_GC_MOVE_EVENTS | PROFLOG_GC_ROOT_EVENTS | PROFLOG_GC_HANDLE_EVENTS | PROFLOG_GC_FINALIZATION_EVENTS | PROFLOG_COUNTER_EVENTS) +#define PROFLOG_LEGACY_ALIAS (PROFLOG_EXCEPTION_EVENTS | PROFLOG_MONITOR_EVENTS | PROFLOG_GC_EVENTS | PROFLOG_GC_MOVE_EVENTS | PROFLOG_GC_ROOT_EVENTS | PROFLOG_GC_HANDLE_EVENTS | PROFLOG_GC_FINALIZATION_EVENTS | PROFLOG_COUNTER_EVENTS | PROFLOG_FILEIO_EVENTS) typedef struct { //Events explicitly enabled diff --git a/mono/tests/Makefile.am b/mono/tests/Makefile.am index cff377fc0276..27adedd99182 100755 --- a/mono/tests/Makefile.am +++ b/mono/tests/Makefile.am @@ -608,7 +608,8 @@ TESTS_IL_SRC= \ gsharing-valuetype-layout.il \ invalid_generic_instantiation.il \ bug-45841-fpstack-exceptions.il \ - instance_tailrec.il + instance_tailrec.il \ + newobj-abstract.il TESTS_GSHARED_SRC = \ generics-sharing.2.cs \ diff --git a/mono/tests/libtest.c b/mono/tests/libtest.c index 46f8cc5d3d52..338d8223555e 100644 --- a/mono/tests/libtest.c +++ b/mono/tests/libtest.c @@ -280,6 +280,25 @@ mono_return_nested_float (void) return f; } +struct Scalar4 { + double val[4]; +}; + +struct Rect { + int x; + int y; + int width; + int height; +}; + +LIBTEST_API char * STDCALL +mono_return_struct_4_double (void *ptr, struct Rect rect, struct Scalar4 sc4, int a, int b, int c) +{ + char *buffer = (char *) malloc (1024 * sizeof (char)); + sprintf (buffer, "sc4 = {%.1f, %.1f, %.1f, %.1f }, a=%x, b=%x, c=%x\n", (float) sc4.val [0], (float) sc4.val [1], (float) sc4.val [2], (float) sc4.val [3], a, b, c); + return buffer; +} + LIBTEST_API int STDCALL mono_test_many_int_arguments (int a, int b, int c, int d, int e, int f, int g, int h, int i, int j); diff --git a/mono/tests/newobj-abstract.il b/mono/tests/newobj-abstract.il new file mode 100644 index 000000000000..52d5913cc27d --- /dev/null +++ b/mono/tests/newobj-abstract.il @@ -0,0 +1,61 @@ +.assembly extern mscorlib {} + +.assembly 'newobj-abstract' {} + +.class private auto ansi beforefieldinit Program + extends [mscorlib]System.Object +{ + .method public hidebysig static int32 Main() cil managed + { + .entrypoint + .locals init (int32 V_0) + + ldc.i4.1 + stloc.0 + .try + { + call void Program::NewAbstract() + leave.s leavetarget + + } // end .try + catch [mscorlib]System.MemberAccessException + { + pop + ldc.i4.0 + stloc.0 + leave.s leavetarget + } +leavetarget: + ldloc.0 + ret + } // end of method Program::Main + + .method public hidebysig static void NewAbstract() cil managed + { + newobj instance void Foo::.ctor() + call void [mscorlib]System.GC::KeepAlive(object) + ret + } + + .method public hidebysig specialname rtspecialname + instance void .ctor() cil managed + { + ldarg.0 + call instance void [mscorlib]System.Object::.ctor() + ret + } + +} + +.class private abstract auto ansi beforefieldinit Foo + extends [mscorlib]System.Object +{ + .method public hidebysig specialname rtspecialname + instance void .ctor() cil managed + { + ldarg.0 + call instance void [mscorlib]System.Object::.ctor() + ret + } + +} diff --git a/mono/tests/pinvoke11.cs b/mono/tests/pinvoke11.cs index 252700fe3442..776dbc4035f2 100644 --- a/mono/tests/pinvoke11.cs +++ b/mono/tests/pinvoke11.cs @@ -60,6 +60,39 @@ public struct NestedFloat { public float f4; } +[Serializable] +[StructLayout(LayoutKind.Sequential)] +public struct Rectangle +{ + public int X; + public int Y; + public int Width; + public int Height; + + public Rectangle(int x, int y, int width, int height) + { + X = x; + Y = y; + Width = width; + Height = height; + } +} + +[Serializable] +public struct Scalar4 { + public double Val0; + public double Val1; + public double Val2; + public double Val3; + + public Scalar4 (double v0, double v1, double v2, double v3) { + Val0 = v0; + Val1 = v1; + Val2 = v2; + Val3 = v3; + } +} + public class Test { [DllImport ("libtest")] @@ -89,6 +122,10 @@ public class Test [DllImport ("libtest", EntryPoint="mono_return_nested_float")] public static extern NestedFloat mono_return_nested_float (); + [DllImport("libtest", EntryPoint="mono_return_struct_4_double")] + [return: MarshalAs(UnmanagedType.LPStr)] + public static extern string mono_return_struct_4_double (IntPtr ptr, Rectangle rect, Scalar4 sc4, int a, int b, int c); + static int Main() { if (mono_return_int (5) != 5) @@ -159,6 +196,14 @@ static int Main() if (f.fi.f1 != 1.0) return 12; + Rectangle rect = new Rectangle (10, 10, 100, 20); + Scalar4 sc4 = new Scalar4 (32, 64, 128, 256); + var sc4_ret = mono_return_struct_4_double (IntPtr.Zero, rect, sc4, 0x1337, 0x1234, 0x9876); + if (sc4_ret != "sc4 = {32.0, 64.0, 128.0, 256.0 }, a=1337, b=1234, c=9876\n") { + Console.WriteLine ("sc4_ret = " + sc4_ret); + return 13; + } + return 0; } } diff --git a/mono/utils/atomic.h b/mono/utils/atomic.h index bbf79ebea4ab..c26f65b5e938 100755 --- a/mono/utils/atomic.h +++ b/mono/utils/atomic.h @@ -167,7 +167,7 @@ static inline void mono_atomic_store_i8 (volatile gint8 *dst, gint8 val) { #if (_MSC_VER >= 1600) - InterlockedExchange8 ((CHAR volatile *)dst, (CHAR)val); + _InterlockedExchange8 ((CHAR volatile *)dst, (CHAR)val); #else *dst = val; mono_memory_barrier (); diff --git a/mono/utils/dlmalloc.c b/mono/utils/dlmalloc.c index 296893ff2e7f..39850671934f 100644 --- a/mono/utils/dlmalloc.c +++ b/mono/utils/dlmalloc.c @@ -461,7 +461,9 @@ DEFAULT_MMAP_THRESHOLD default: 256K #endif /* _WIN32 */ #endif /* WIN32 */ #ifdef WIN32 +#ifndef WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN +#endif #include #define HAVE_MMAP 1 #define HAVE_MORECORE 0 @@ -1214,7 +1216,7 @@ extern void* sbrk(ptrdiff_t); # define _SC_PAGE_SIZE _SC_PAGESIZE # endif # endif -# ifdef _SC_PAGE_SIZE +# if defined (HAVE_SYSCONF) && defined (_SC_PAGESIZE) # define malloc_getpagesize sysconf(_SC_PAGE_SIZE) # else # if defined(BSD) || defined(DGUX) || defined(HAVE_GETPAGESIZE) diff --git a/mono/utils/gc_wrapper.h b/mono/utils/gc_wrapper.h index 0bc7a45d2254..0e14fbf0a911 100644 --- a/mono/utils/gc_wrapper.h +++ b/mono/utils/gc_wrapper.h @@ -11,7 +11,29 @@ #include #ifdef HAVE_BOEHM_GC +#ifdef HAVE_BDWGC_GC +/* Use unity's updated Boehm GC from IL2CPP */ +#define ALL_INTERIOR_POINTERS 1 +#define GC_GCJ_SUPPORT 1 +#define JAVA_FINALIZATION 1 +#define NO_EXECUTE_PERMISSION 1 +#define GC_NO_THREADS_DISCOVERY 1 +#define IGNORE_DYNAMIC_LOADING 1 +#define GC_DONT_REGISTER_MAIN_STATIC_DATA 1 +#define GC_VERSION_MAJOR 7 +#define GC_VERSION_MINOR 4 +#define GC_VERSION_MICRO 0 +#define GC_THREADS 1 +#define USE_MMAP 1 +#define USE_MUNMAP 1 +#define GC_EventType GCEventType + +# include +# include +# include +#else /* HAVE_BDWGC_GC */ +/*Use Mono's Boehm */ # ifdef _MSC_VER # include # else @@ -48,6 +70,7 @@ #if defined(HOST_WIN32) #define CreateThread GC_CreateThread #endif +#endif /* HAVE_BDWGC_GC */ #elif defined(HAVE_SGEN_GC) diff --git a/mono/utils/mono-compiler.h b/mono/utils/mono-compiler.h index f659cdeaf1d6..51439b5f6d67 100644 --- a/mono/utils/mono-compiler.h +++ b/mono/utils/mono-compiler.h @@ -36,7 +36,9 @@ #endif #include +#if _MSC_VER < 1900 /* VS 2015 */ #define trunc(x) (((x) < 0) ? ceil((x)) : floor((x))) +#endif #if _MSC_VER < 1800 /* VS 2013 */ #define isnan(x) _isnan(x) #define isinf(x) (_isnan(x) ? 0 : (_fpclass(x) == _FPCLASS_NINF) ? -1 : (_fpclass(x) == _FPCLASS_PINF) ? 1 : 0) diff --git a/mono/utils/mono-context.c b/mono/utils/mono-context.c index 4dfbbb34163e..f4266854876f 100644 --- a/mono/utils/mono-context.c +++ b/mono/utils/mono-context.c @@ -395,11 +395,24 @@ mono_monoctx_to_sigctx (MonoContext *mctx, void *ctx) #include #include +#ifdef HOST_WIN32 +#include +#endif + void mono_sigctx_to_monoctx (void *sigctx, MonoContext *mctx) { #ifdef MONO_CROSS_COMPILE g_assert_not_reached (); +#elif defined(HOST_WIN32) + CONTEXT *context = (CONTEXT*)sigctx; + + mctx->pc = context->Pc; + mctx->cpsr = context->Cpsr; + memcpy (&mctx->regs, &context->R0, sizeof (DWORD) * 16); + + /* Why are we only copying 16 registers?! There are 32! */ + memcpy (&mctx->fregs, &context->D, sizeof (double) * 16); #else arm_ucontext *my_uc = sigctx; @@ -418,6 +431,15 @@ mono_monoctx_to_sigctx (MonoContext *mctx, void *ctx) { #ifdef MONO_CROSS_COMPILE g_assert_not_reached (); +#elif defined(HOST_WIN32) + CONTEXT *context = (CONTEXT*)ctx; + + context->Pc = mctx->pc; + context->Cpsr = mctx->cpsr; + memcpy (&context->R0, &mctx->regs, sizeof (DWORD) * 16); + + /* Why are we only copying 16 registers?! There are 32! */ + memcpy (&context->D, &mctx->fregs, sizeof (double) * 16); #else arm_ucontext *my_uc = ctx; diff --git a/mono/utils/mono-dl-unity.c b/mono/utils/mono-dl-unity.c new file mode 100644 index 000000000000..6f3c33e9849f --- /dev/null +++ b/mono/utils/mono-dl-unity.c @@ -0,0 +1,75 @@ +#include +#include "mono/utils/mono-dl.h" + +#if defined(PLATFORM_UNITY) && defined(UNITY_USE_PLATFORM_STUBS) + +const char* +mono_dl_get_so_prefix (void) +{ + g_assert(0 && "This function is not yet implemented for the Unity platform."); + return NULL; +} + +const char** +mono_dl_get_so_suffixes (void) +{ + g_assert(0 && "This function is not yet implemented for the Unity platform."); + return NULL; +} + +void* +mono_dl_open_file (const char *file, int flags) +{ + g_assert(0 && "This function is not yet implemented for the Unity platform."); + return NULL; +} + +void +mono_dl_close_handle (MonoDl *module) +{ + g_assert(0 && "This function is not yet implemented for the Unity platform."); +} + +void* +mono_dl_lookup_symbol_in_process (const char *symbol_name) +{ + g_assert(0 && "This function is not yet implemented for the Unity platform."); + return NULL; +} + +void* +mono_dl_lookup_symbol (MonoDl *module, const char *symbol_name) +{ + g_assert(0 && "This function is not yet implemented for the Unity platform."); + return NULL; +} + +int +mono_dl_convert_flags (int flags) +{ + g_assert(0 && "This function is not yet implemented for the Unity platform."); + return 0; +} + +char* +mono_dl_current_error_string (void) +{ + g_assert(0 && "This function is not yet implemented for the Unity platform."); + return NULL; +} + +int +mono_dl_get_executable_path (char *buf, int buflen) +{ + g_assert(0 && "This function is not yet implemented for the Unity platform."); + return 0; +} + +const char* +mono_dl_get_system_dir (void) +{ + g_assert(0 && "This function is not yet implemented for the Unity platform."); + return NULL; +} + +#endif /* PLATFORM_UNITY && UNITY_USE_PLATFORM_STUBS */ diff --git a/mono/utils/mono-dl-windows-uwp.c b/mono/utils/mono-dl-windows-uwp.c index e3e5ddf7b6ad..f88b81c5ce5d 100644 --- a/mono/utils/mono-dl-windows-uwp.c +++ b/mono/utils/mono-dl-windows-uwp.c @@ -9,7 +9,7 @@ #include #include "mono/utils/mono-compiler.h" -#if G_HAVE_API_SUPPORT(HAVE_UWP_WINAPI_SUPPORT) +#if G_HAVE_API_SUPPORT(HAVE_UWP_WINAPI_SUPPORT | HAVE_XBOXONE_WINAPI_SUPPORT) #include #include "mono/utils/mono-dl-windows-internals.h" @@ -37,7 +37,7 @@ mono_dl_current_error_string (void) return ret; } -#else /* G_HAVE_API_SUPPORT(HAVE_UWP_WINAPI_SUPPORT) */ +#else /* G_HAVE_API_SUPPORT(HAVE_UWP_WINAPI_SUPPORT | HAVE_XBOXONE_WINAPI_SUPPORT) */ MONO_EMPTY_SOURCE_FILE (mono_dl_windows_uwp); -#endif /* G_HAVE_API_SUPPORT(HAVE_UWP_WINAPI_SUPPORT) */ +#endif /* G_HAVE_API_SUPPORT(HAVE_UWP_WINAPI_SUPPORT | HAVE_XBOXONE_WINAPI_SUPPORT) */ diff --git a/mono/utils/mono-dl-windows.c b/mono/utils/mono-dl-windows.c index ab26660fed43..9ebb14b8bf70 100644 --- a/mono/utils/mono-dl-windows.c +++ b/mono/utils/mono-dl-windows.c @@ -55,7 +55,11 @@ mono_dl_open_file (const char *file, int flags) #endif guint32 last_error = 0; +#if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT | HAVE_XBOXONE_WINAPI_SUPPORT) hModule = LoadLibrary (file_utf16); +#else + hModule = LoadPackagedLibrary (file_utf16, NULL); +#endif if (!hModule) last_error = GetLastError (); @@ -68,7 +72,11 @@ mono_dl_open_file (const char *file, int flags) if (!hModule) SetLastError (last_error); } else { +#if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) hModule = GetModuleHandle (NULL); +#else + g_assert(0 && "Not supported"); +#endif } return hModule; } diff --git a/mono/utils/mono-error-internals.h b/mono/utils/mono-error-internals.h index 045d85ec38ec..cbb452c4ca1c 100644 --- a/mono/utils/mono-error-internals.h +++ b/mono/utils/mono-error-internals.h @@ -63,7 +63,7 @@ struct _MonoErrorBoxed { void mono_error_assert_ok_pos (MonoError *error, const char* filename, int lineno) MONO_LLVM_INTERNAL; -#define mono_error_assert_ok(e) mono_error_assert_ok_pos (e, __FILE__, __LINE__); +#define mono_error_assert_ok(e) mono_error_assert_ok_pos (e, __FILE__, __LINE__) void mono_error_dup_strings (MonoError *error, gboolean dup_strings); diff --git a/mono/utils/mono-error.c b/mono/utils/mono-error.c index b63be628a46d..aeab3a8762a1 100644 --- a/mono/utils/mono-error.c +++ b/mono/utils/mono-error.c @@ -60,12 +60,16 @@ mono_error_prepare (MonoErrorInternal *error) static MonoClass* get_class (MonoErrorInternal *error) { +#ifndef RUNTIME_IL2CPP MonoClass *klass = NULL; if (is_managed_exception (error)) klass = mono_object_class (mono_gchandle_get_target (error->exn.instance_handle)); else klass = error->exn.klass; return klass; +#else + g_assert_not_reached (); +#endif } static const char* @@ -115,6 +119,7 @@ mono_error_init (MonoError *error) void mono_error_cleanup (MonoError *oerror) { +#ifndef RUNTIME_IL2CPP MonoErrorInternal *error = (MonoErrorInternal*)oerror; short int orig_error_code = error->error_code; gboolean free_strings = error->flags & MONO_ERROR_FREE_STRINGS; @@ -153,7 +158,9 @@ mono_error_cleanup (MonoError *oerror) g_free ((char*)error->member_signature); error->type_name = error->assembly_name = error->member_name = error->exception_name_space = error->exception_name = error->first_argument = error->member_signature = NULL; error->exn.klass = NULL; - +#else + g_assert_not_reached (); +#endif } gboolean @@ -387,23 +394,31 @@ mono_error_set_field_load (MonoError *oerror, MonoClass *klass, const char *fiel void mono_error_set_bad_image_name (MonoError *oerror, const char *assembly_name, const char *msg_format, ...) { +#ifndef RUNTIME_IL2CPP MonoErrorInternal *error = (MonoErrorInternal*)oerror; mono_error_prepare (error); error->error_code = MONO_ERROR_BAD_IMAGE; mono_error_set_assembly_name (oerror, assembly_name); set_error_message (); +#else + g_assert_not_reached (); +#endif } void mono_error_set_bad_image (MonoError *oerror, MonoImage *image, const char *msg_format, ...) { +#ifndef RUNTIME_IL2CPP MonoErrorInternal *error = (MonoErrorInternal*)oerror; mono_error_prepare (error); error->error_code = MONO_ERROR_BAD_IMAGE; error->assembly_name = image ? mono_image_get_name (image) : ""; set_error_message (); +#else + g_assert_not_reached (); +#endif } void @@ -521,21 +536,29 @@ mono_error_set_invalid_cast (MonoError *oerror) void mono_error_set_exception_instance (MonoError *oerror, MonoException *exc) { +#ifndef RUNTIME_IL2CPP MonoErrorInternal *error = (MonoErrorInternal*)oerror; mono_error_prepare (error); error->error_code = MONO_ERROR_EXCEPTION_INSTANCE; error->exn.instance_handle = mono_gchandle_new (exc ? &exc->object : NULL, FALSE); +#else + g_assert_not_reached (); +#endif } void mono_error_set_exception_handle (MonoError *oerror, MonoExceptionHandle exc) { +#ifndef RUNTIME_IL2CPP MonoErrorInternal *error = (MonoErrorInternal*)oerror; mono_error_prepare (error); error->error_code = MONO_ERROR_EXCEPTION_INSTANCE; error->exn.instance_handle = mono_gchandle_from_handle (MONO_HANDLE_CAST(MonoObject, exc), FALSE); +#else + g_assert_not_reached (); +#endif } void @@ -576,6 +599,7 @@ mono_error_set_argument_null (MonoError *oerror, const char *argument, const cha void mono_error_set_not_verifiable (MonoError *oerror, MonoMethod *method, const char *msg_format, ...) { +#ifndef RUNTIME_IL2CPP MonoErrorInternal *error = (MonoErrorInternal*)oerror; mono_error_prepare (error); @@ -586,6 +610,9 @@ mono_error_set_not_verifiable (MonoError *oerror, MonoMethod *method, const char } set_error_message (); +#else + g_assert_not_reached (); +#endif } @@ -636,6 +663,7 @@ set_message_on_exception (MonoException *exception, MonoErrorInternal *error, Mo MonoException* mono_error_prepare_exception (MonoError *oerror, MonoError *error_out) { +#ifndef RUNTIME_IL2CPP MonoErrorInternal *error = (MonoErrorInternal*)oerror; MonoException* exception = NULL; @@ -677,11 +705,11 @@ mono_error_prepare_exception (MonoError *oerror, MonoError *error_out) break; } } - exception = mono_exception_from_name_four_strings_checked (mono_defaults.corlib, "System", "MissingMethodException", type_name, method_name, signature, message, error_out); + exception = mono_exception_from_name_four_strings_checked (mono_get_corlib (), "System", "MissingMethodException", type_name, method_name, signature, message, error_out); if (exception) set_message_on_exception (exception, error, error_out); } else { - exception = mono_exception_from_name_msg (mono_defaults.corlib, "System", "MissingMethodException", error->full_message); + exception = mono_exception_from_name_msg (mono_get_corlib (), "System", "MissingMethodException", error->full_message); } break; @@ -697,11 +725,11 @@ mono_error_prepare_exception (MonoError *oerror, MonoError *error_out) break; } - exception = mono_exception_from_name_two_strings_checked (mono_defaults.corlib, "System", "MissingFieldException", type_name, field_name, error_out); + exception = mono_exception_from_name_two_strings_checked (mono_get_corlib (), "System", "MissingFieldException", type_name, field_name, error_out); if (exception) set_message_on_exception (exception, error, error_out); } else { - exception = mono_exception_from_name_msg (mono_defaults.corlib, "System", "MissingFieldException", error->full_message); + exception = mono_exception_from_name_msg (mono_get_corlib (), "System", "MissingFieldException", error->full_message); } break; @@ -725,7 +753,7 @@ mono_error_prepare_exception (MonoError *oerror, MonoError *error_out) if (exception && error->full_message != NULL && strcmp (error->full_message, "")) set_message_on_exception (exception, error, error_out); } else { - exception = mono_exception_from_name_msg (mono_defaults.corlib, "System", "TypeLoadException", error->full_message); + exception = mono_exception_from_name_msg (mono_get_corlib (), "System", "TypeLoadException", error->full_message); } break; @@ -749,12 +777,12 @@ mono_error_prepare_exception (MonoError *oerror, MonoError *error_out) if (error->error_code == MONO_ERROR_FILE_NOT_FOUND) exception = mono_exception_from_name_two_strings_checked (mono_get_corlib (), "System.IO", "FileNotFoundException", msg, assembly_name, error_out); else - exception = mono_exception_from_name_two_strings_checked (mono_defaults.corlib, "System", "BadImageFormatException", msg, assembly_name, error_out); + exception = mono_exception_from_name_two_strings_checked (mono_get_corlib (), "System", "BadImageFormatException", msg, assembly_name, error_out); } else { if (error->error_code == MONO_ERROR_FILE_NOT_FOUND) exception = mono_exception_from_name_msg (mono_get_corlib (), "System.IO", "FileNotFoundException", error->full_message); else - exception = mono_exception_from_name_msg (mono_defaults.corlib, "System", "BadImageFormatException", error->full_message); + exception = mono_exception_from_name_msg (mono_get_corlib (), "System", "BadImageFormatException", error->full_message); } break; @@ -785,7 +813,7 @@ mono_error_prepare_exception (MonoError *oerror, MonoError *error_out) mono_error_set_out_of_memory (error_out, "Could not allocate message"); break; } - exception = mono_exception_from_name_msg (mono_defaults.corlib, "System.Security", "VerificationException", message); + exception = mono_exception_from_name_msg (mono_get_corlib (), "System.Security", "VerificationException", message); g_free (message); g_free (type_name); break; @@ -794,7 +822,7 @@ mono_error_prepare_exception (MonoError *oerror, MonoError *error_out) if (!error->exception_name_space || !error->exception_name) mono_error_set_execution_engine (error_out, "MonoError with generic error but no exception name was supplied"); else - exception = mono_exception_from_name_msg (mono_defaults.corlib, error->exception_name_space, error->exception_name, error->full_message); + exception = mono_exception_from_name_msg (mono_get_corlib (), error->exception_name_space, error->exception_name, error->full_message); break; case MONO_ERROR_EXCEPTION_INSTANCE: @@ -808,9 +836,9 @@ mono_error_prepare_exception (MonoError *oerror, MonoError *error_out) case MONO_ERROR_INVALID_PROGRAM: { gboolean lacks_message = error->flags & MONO_ERROR_INCOMPLETE; if (lacks_message) - return mono_exception_from_name_msg (mono_defaults.corlib, "System", "InvalidProgramException", ""); + return mono_exception_from_name_msg (mono_get_corlib (), "System", "InvalidProgramException", ""); else - return mono_exception_from_name_msg (mono_defaults.corlib, "System", "InvalidProgramException", error->full_message); + return mono_exception_from_name_msg (mono_get_corlib (), "System", "InvalidProgramException", error->full_message); } default: mono_error_set_execution_engine (error_out, "Invalid error-code %d", error->error_code); @@ -821,6 +849,10 @@ mono_error_prepare_exception (MonoError *oerror, MonoError *error_out) if (!exception) mono_error_set_out_of_memory (error_out, "Could not allocate exception object"); return exception; +#else + g_assert_not_reached (); + return NULL; +#endif } /* @@ -872,6 +904,7 @@ mono_error_move (MonoError *dest, MonoError *src) MonoErrorBoxed* mono_error_box (const MonoError *ierror, MonoImage *image) { +#ifndef RUNTIME_IL2CPP MonoErrorInternal *from = (MonoErrorInternal*)ierror; /* Don't know how to box a gchandle */ g_assert (!is_managed_exception (from)); @@ -904,6 +937,10 @@ mono_error_box (const MonoError *ierror, MonoImage *image) #undef DUP_STR return box; +#else + g_assert_not_reached (); + return NULL; +#endif } diff --git a/mono/utils/mono-filemap.c b/mono/utils/mono-filemap.c index 416ca2625d37..d96ae877869d 100644 --- a/mono/utils/mono-filemap.c +++ b/mono/utils/mono-filemap.c @@ -24,9 +24,30 @@ #include "mono-mmap.h" +static MonoFileMapOpen file_open_func = 0; +static MonoFileMapSize file_size_func = 0; +static MonoFileMapFd file_fd_func = 0; +static MonoFileMapClose file_close_func = 0; + MonoFileMapMap file_map_func = 0; + MonoFileMapUnmap file_unmap_func = 0; + +#if defined(ANDROID) +void mono_file_map_override(MonoFileMapOpen open_func, MonoFileMapSize size_func, MonoFileMapFd fd_func, MonoFileMapClose close_func, MonoFileMapMap map_func, MonoFileMapUnmap unmap_func) +{ + file_open_func = open_func; + file_size_func = size_func; + file_fd_func = fd_func; + file_close_func = close_func; + file_map_func = map_func; + file_unmap_func = unmap_func; +} +#endif + + MonoFileMap * mono_file_map_open (const char* name) { + if (file_open_func) return file_open_func(name); #ifdef WIN32 gunichar2 *wname = g_utf8_to_utf16 (name, -1, 0, 0, 0); MonoFileMap *result; @@ -47,6 +68,7 @@ mono_file_map_open (const char* name) guint64 mono_file_map_size (MonoFileMap *fmap) { + if (file_size_func) return file_size_func(fmap); struct stat stat_buf; if (fstat (mono_file_map_fd (fmap), &stat_buf) < 0) return 0; @@ -56,8 +78,9 @@ mono_file_map_size (MonoFileMap *fmap) int mono_file_map_fd (MonoFileMap *fmap) { + if (file_fd_func) return file_fd_func(fmap); #ifdef WIN32 - return fileno ((FILE*)fmap); + return _fileno ((FILE*)fmap); #else return (int)(size_t)fmap; #endif @@ -66,6 +89,7 @@ mono_file_map_fd (MonoFileMap *fmap) int mono_file_map_close (MonoFileMap *fmap) { + if (file_close_func) return file_close_func(fmap); #ifdef WIN32 return fclose ((FILE*)fmap); #else diff --git a/mono/utils/mono-hwcap-arm.c b/mono/utils/mono-hwcap-arm.c index a44f43ac9e74..7b34c8502e0c 100644 --- a/mono/utils/mono-hwcap-arm.c +++ b/mono/utils/mono-hwcap-arm.c @@ -94,6 +94,31 @@ mono_hwcap_arch_init (void) } /* TODO: Find a way to detect features like Thumb and VFP. */ +#elif defined (_WIN32) + /* From MSDN: + * Windows on ARM presumes that it is running on an ARMv7 architecture at all times. + * Floating-point support in the form of VFPv3-D32 or later must be present in hardware. + * The VFP must support both single-precision and double-precision floating-point in hardware. + * + * The Windows runtime does not support emulation of floating-point to enable running on non-VFP hardware. + * Advanced SIMD Extensions (NEON) support—this includes both integer and floating-point operations—must also be present in hardware. + * No run-time support for emulation is provided. + * + * Integer divide support (UDIV/SDIV) is strongly recommended but not required. + * Platforms that lack integer divide support may incur a performance penalty because + * these operations have to be trapped and possibly patched. + * + * The instruction set for Windows on ARM is strictly limited to Thumb-2. + * All code executed on this platform is expected to start and remain in Thumb mode at all times. + */ + mono_hwcap_arm_is_v5 = TRUE; + mono_hwcap_arm_is_v6 = TRUE; + mono_hwcap_arm_is_v7 = TRUE; + mono_hwcap_arm_has_vfp = TRUE; + mono_hwcap_arm_has_vfp3 = TRUE; + mono_hwcap_arm_has_vfp3_d16 = TRUE; + mono_hwcap_arm_has_thumb = TRUE; + mono_hwcap_arm_has_thumb2 = TRUE; #else /* We can't use the auxiliary vector on Android due to * permissions, so fall back to /proc/cpuinfo. We also diff --git a/mono/utils/mono-hwcap-x86.c b/mono/utils/mono-hwcap-x86.c index 7a4b859a8e44..ae66294df88e 100644 --- a/mono/utils/mono-hwcap-x86.c +++ b/mono/utils/mono-hwcap-x86.c @@ -147,7 +147,7 @@ mono_hwcap_arch_init (void) } } -#if defined(HAVE_UNISTD_H) +#if defined(HAVE_UNISTD_H) && !defined(NO_HAVE_ACCESS) mono_hwcap_x86_is_xen = !access ("/proc/xen", F_OK); #endif } diff --git a/mono/utils/mono-log-unity.c b/mono/utils/mono-log-unity.c new file mode 100644 index 000000000000..daddaf011aec --- /dev/null +++ b/mono/utils/mono-log-unity.c @@ -0,0 +1,24 @@ +#include "mono-logger-internals.h" + +#if defined(PLATFORM_UNITY) && defined(UNITY_USE_PLATFORM_STUBS) + +void +mono_log_open_syslog(const char *ident, void *userData) +{ + g_assert(0 && "This function is not yet implemented for the Unity platform."); + +} + +void +mono_log_write_syslog(const char *domain, GLogLevelFlags level, mono_bool hdr, const char *message) +{ + g_assert(0 && "This function is not yet implemented for the Unity platform."); +} + +void +mono_log_close_syslog() +{ + g_assert(0 && "This function is not yet implemented for the Unity platform."); +} + +#endif /* PLATFORM_UNITY && UNITY_USE_PLATFORM_STUBS */ diff --git a/mono/utils/mono-membar.h b/mono/utils/mono-membar.h index 7abf273a6508..33e4eac22a34 100644 --- a/mono/utils/mono-membar.h +++ b/mono/utils/mono-membar.h @@ -76,7 +76,25 @@ static inline void mono_memory_write_barrier (void) { mono_memory_barrier (); } -#else + +#elif defined(PLATFORM_UNITY) && defined(UNITY_USE_PLATFORM_STUBS) + +static inline void mono_memory_barrier (void) +{ + g_assert(0 && "This function is not yet implemented for the Unity platform."); +} + +static inline void mono_memory_read_barrier (void) +{ + g_assert(0 && "This function is not yet implemented for the Unity platform."); +} + +static inline void mono_memory_write_barrier (void) +{ + g_assert(0 && "This function is not yet implemented for the Unity platform."); +} + +#else #error "Don't know how to do memory barriers!" #endif diff --git a/mono/utils/mono-mmap.c b/mono/utils/mono-mmap.c index 4e5e717bce12..f4cbf6d84241 100644 --- a/mono/utils/mono-mmap.c +++ b/mono/utils/mono-mmap.c @@ -281,10 +281,20 @@ mono_vfree (void *addr, size_t length, MonoMemAccountType type) * \p ret_handle must point to a void*: this value must be used when unmapping * the memory area using \c mono_file_unmap(). */ +extern MonoFileMapMap file_map_func; +extern MonoFileMapUnmap file_unmap_func; + void* mono_file_map (size_t length, int flags, int fd, guint64 offset, void **ret_handle) { void *ptr; + if (file_map_func) + { + BEGIN_CRITICAL_SECTION; + ptr = file_map_func(length, flags, fd, offset, ret_handle); + END_CRITICAL_SECTION; + return ptr; + } int mflags = 0; int prot = prot_from_flags (flags); /* translate the flags */ @@ -320,7 +330,10 @@ mono_file_unmap (void *addr, void *handle) int res; BEGIN_CRITICAL_SECTION; - res = munmap (addr, (size_t)handle); + if (file_unmap_func) + res = file_unmap_func(addr, handle); + else + res = munmap(addr, (size_t)handle); END_CRITICAL_SECTION; return res; diff --git a/mono/utils/mono-mmap.h b/mono/utils/mono-mmap.h index 2e2c7cdf0367..e1568a8ff88d 100644 --- a/mono/utils/mono-mmap.h +++ b/mono/utils/mono-mmap.h @@ -84,5 +84,16 @@ typedef void (*mono_file_map_release_fn) (void *addr); MONO_API void mono_file_map_set_allocator (mono_file_map_alloc_fn alloc, mono_file_map_release_fn release); +typedef MonoFileMap* (*MonoFileMapOpen) (const char* name); +typedef guint64 (*MonoFileMapSize) (MonoFileMap *fmap); +typedef int (*MonoFileMapFd) (MonoFileMap *fmap); +typedef int (*MonoFileMapClose) (MonoFileMap *fmap); +typedef void * (*MonoFileMapMap) (size_t length, int flags, int fd, guint64 offset, void **ret_handle); +typedef int (*MonoFileMapUnmap) (void *addr, void *handle); + +#if defined(ANDROID) +MONO_API void mono_file_map_override(MonoFileMapOpen open_func, MonoFileMapSize size_func, MonoFileMapFd fd_func, MonoFileMapClose close_func, MonoFileMapMap map_func, MonoFileMapUnmap unmap_func); +#endif + #endif /* __MONO_UTILS_MMAP_H__ */ diff --git a/mono/utils/mono-os-wait-win32-uwp.c b/mono/utils/mono-os-wait-win32-uwp.c index bb8260003a37..d17d9ed559c4 100644 --- a/mono/utils/mono-os-wait-win32-uwp.c +++ b/mono/utils/mono-os-wait-win32-uwp.c @@ -9,7 +9,7 @@ #include #include "mono/utils/mono-compiler.h" -#if G_HAVE_API_SUPPORT(HAVE_UWP_WINAPI_SUPPORT) +#if G_HAVE_API_SUPPORT(HAVE_UWP_WINAPI_SUPPORT | HAVE_XBOXONE_WINAPI_SUPPORT) #include DWORD @@ -21,7 +21,7 @@ mono_win32_msg_wait_for_multiple_objects_ex (DWORD count, CONST HANDLE *handles, return WAIT_FAILED; } -#else /* G_HAVE_API_SUPPORT(HAVE_UWP_WINAPI_SUPPORT) */ +#else /* G_HAVE_API_SUPPORT(HAVE_UWP_WINAPI_SUPPORT | HAVE_XBOXONE_WINAPI_SUPPORT) */ MONO_EMPTY_SOURCE_FILE (mono_os_wait_win32_uwp); -#endif /* G_HAVE_API_SUPPORT(HAVE_UWP_WINAPI_SUPPORT) */ +#endif /* G_HAVE_API_SUPPORT(HAVE_UWP_WINAPI_SUPPORT | HAVE_XBOXONE_WINAPI_SUPPORT) */ diff --git a/mono/utils/mono-os-wait-win32.c b/mono/utils/mono-os-wait-win32.c index 43ca85e3f5c8..9f84a34da905 100644 --- a/mono/utils/mono-os-wait-win32.c +++ b/mono/utils/mono-os-wait-win32.c @@ -152,6 +152,9 @@ mono_win32_wait_for_multiple_objects_ex (DWORD count, CONST HANDLE *handles, BOO return result; } +/* See comment above ves_icall_System_Threading_WaitHandle_SignalAndWait_Internal */ +#if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) + DWORD mono_win32_signal_object_and_wait (HANDLE toSignal, HANDLE toWait, DWORD timeout, BOOL alertable) { @@ -173,6 +176,8 @@ mono_win32_signal_object_and_wait (HANDLE toSignal, HANDLE toWait, DWORD timeout return result; } +#endif + #if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) DWORD mono_win32_msg_wait_for_multiple_objects_ex (DWORD count, CONST HANDLE *handles, DWORD timeout, DWORD wakeMask, DWORD flags) diff --git a/mono/utils/mono-path.c b/mono/utils/mono-path.c index d0dd89b4c0da..66a4a9f90751 100644 --- a/mono/utils/mono-path.c +++ b/mono/utils/mono-path.c @@ -113,7 +113,7 @@ static gchar * resolve_symlink (const char *path) { char *p, *concat, *dir; - char buffer [PATH_MAX+1]; + char buffer [/*PATH_MAX+1*/ 257]; int n, iterations = 0; p = g_strdup (path); diff --git a/mono/utils/mono-proclib.c b/mono/utils/mono-proclib.c index 714d9eb7a245..9238356926db 100644 --- a/mono/utils/mono-proclib.c +++ b/mono/utils/mono-proclib.c @@ -32,8 +32,10 @@ #ifdef HAVE_SYS_SYSCTL_H #include #endif +#ifdef HAVE_SYS_RESOURCE_H #include #endif +#endif #if defined(__HAIKU__) #include #endif @@ -519,7 +521,7 @@ get_user_hz (void) { static int user_hz = 0; if (user_hz == 0) { -#ifdef _SC_CLK_TCK +#if defined (_SC_CLK_TCK) && defined (HAVE_SYSCONF) user_hz = sysconf (_SC_CLK_TCK); #endif if (user_hz == 0) @@ -761,7 +763,7 @@ mono_cpu_count (void) * [5] https://github.com/dotnet/coreclr/blob/7058273693db2555f127ce16e6b0c5b40fb04867/src/pal/src/misc/sysinfo.cpp#L148 */ -#ifdef _SC_NPROCESSORS_CONF +#if defined (_SC_NPROCESSORS_CONF) && defined (HAVE_SYSCONF) { int count = sysconf (_SC_NPROCESSORS_CONF); if (count > 0) @@ -778,7 +780,7 @@ mono_cpu_count (void) return CPU_COUNT (&set); } #endif -#ifdef _SC_NPROCESSORS_ONLN +#if defined (_SC_NPROCESSORS_ONLN) && defined (HAVE_SYSCONF) { int count = sysconf (_SC_NPROCESSORS_ONLN); if (count > 0) @@ -913,6 +915,7 @@ gint32 mono_cpu_usage (MonoCpuUsageState *prev) { gint32 cpu_usage = 0; +#ifdef HAVE_GETRUSAGE gint64 cpu_total_time; gint64 cpu_busy_time; struct rusage resource_usage; @@ -940,7 +943,7 @@ mono_cpu_usage (MonoCpuUsageState *prev) if (cpu_total_time > 0 && cpu_busy_time > 0) cpu_usage = (gint32)(cpu_busy_time * 100 / cpu_total_time); - +#endif return cpu_usage; } #endif /* !HOST_WIN32 */ diff --git a/mono/utils/mono-publib.h b/mono/utils/mono-publib.h index 14613b2bee01..19f804059320 100644 --- a/mono/utils/mono-publib.h +++ b/mono/utils/mono-publib.h @@ -67,6 +67,8 @@ typedef unsigned __int64 uint64_t; #define MONO_API #endif +#define UNITY_MONO_API MONO_API + typedef int32_t mono_bool; typedef uint8_t mono_byte; typedef uint16_t mono_unichar2; diff --git a/mono/utils/mono-stdlib.c b/mono/utils/mono-stdlib.c index 3685dcb996d4..e65f9645982f 100644 --- a/mono/utils/mono-stdlib.c +++ b/mono/utils/mono-stdlib.c @@ -35,7 +35,12 @@ mono_mkstemp (char *templ) len = strlen (templ); do { +#if HOST_WIN32 + t = _mktemp (templ); +#else t = mktemp (templ); +#endif + if (t == NULL) { errno = EINVAL; return -1; @@ -45,7 +50,11 @@ mono_mkstemp (char *templ) return -1; } - ret = open (templ, O_RDWR | O_BINARY | O_CREAT | O_EXCL, 0600); +#if HOST_WIN32 + ret = _open (templ, O_RDWR | O_BINARY | O_CREAT | O_EXCL, 0600); +#else + ret = open(templ, O_RDWR | O_BINARY | O_CREAT | O_EXCL, 0600); +#endif if (ret == -1) { if (errno != EEXIST) return -1; diff --git a/mono/utils/mono-threads-debug.h b/mono/utils/mono-threads-debug.h index c14acab00e84..36742b3db9b6 100644 --- a/mono/utils/mono-threads-debug.h +++ b/mono/utils/mono-threads-debug.h @@ -6,11 +6,19 @@ #define __MONO_UTILS_MONO_THREADS_DEBUG_H__ /* Logging - enable them below if you need specific logging for the category you need */ +#ifdef HOST_WIN32 +#define MOSTLY_ASYNC_SAFE_PRINTF(...) do { \ + char __buff[1024]; __buff [0] = '\0'; \ + g_snprintf (__buff, sizeof (__buff), __VA_ARGS__); \ + _write (1, __buff, (guint32)strlen (__buff)); \ +} while (0) +#else #define MOSTLY_ASYNC_SAFE_PRINTF(...) do { \ char __buff[1024]; __buff [0] = '\0'; \ g_snprintf (__buff, sizeof (__buff), __VA_ARGS__); \ write (1, __buff, (guint32)strlen (__buff)); \ } while (0) +#endif #if 1 #define THREADS_DEBUG(...) diff --git a/mono/utils/mono-threads-posix-signals.c b/mono/utils/mono-threads-posix-signals.c index b39277393f5d..bcb3effc00e7 100644 --- a/mono/utils/mono-threads-posix-signals.c +++ b/mono/utils/mono-threads-posix-signals.c @@ -84,7 +84,7 @@ static int suspend_signal_get (void) { #if defined(HOST_ANDROID) - return SIGPWR; + return SIGUSR1; #elif defined (SIGRTMIN) static int suspend_signum = -1; if (suspend_signum == -1) @@ -103,7 +103,7 @@ static int restart_signal_get (void) { #if defined(HOST_ANDROID) - return SIGXCPU; + return SIGUSR2; #elif defined (SIGRTMIN) static int restart_signum = -1; if (restart_signum == -1) diff --git a/mono/utils/mono-threads-posix.c b/mono/utils/mono-threads-posix.c index 6804024e156a..e89c9504c037 100644 --- a/mono/utils/mono-threads-posix.c +++ b/mono/utils/mono-threads-posix.c @@ -22,9 +22,11 @@ #include +/* #if defined(HOST_ANDROID) && !defined(TARGET_ARM64) && !defined(TARGET_AMD64) #define USE_TKILL_ON_ANDROID 1 #endif +*/ #ifdef USE_TKILL_ON_ANDROID extern int tkill (pid_t tid, int signal); @@ -76,7 +78,11 @@ mono_thread_platform_create_thread (MonoThreadStart thread_fn, gpointer thread_d #endif /* HAVE_PTHREAD_ATTR_SETSTACKSIZE */ /* Actually start the thread */ +#ifdef RUNTIME_IL2CPP + res = pthread_create (&thread, &attr, (gpointer (*)(gpointer)) thread_fn, thread_data); +#else res = mono_gc_pthread_create (&thread, &attr, (gpointer (*)(gpointer)) thread_fn, thread_data); +#endif if (res) { res = pthread_attr_destroy (&attr); if (res != 0) diff --git a/mono/utils/mono-threads-unity.c b/mono/utils/mono-threads-unity.c new file mode 100644 index 000000000000..89ef83535cbb --- /dev/null +++ b/mono/utils/mono-threads-unity.c @@ -0,0 +1,171 @@ +#include + +#if defined(PLATFORM_UNITY) && defined(UNITY_USE_PLATFORM_STUBS) + +#include "Thread-c-api.h" + +void +mono_threads_suspend_init (void) +{ + g_assert(0 && "This function is not yet implemented for the Unity platform."); +} + +gboolean +mono_threads_suspend_begin_async_suspend (MonoThreadInfo *info, gboolean interrupt_kernel) +{ + g_assert(0 && "This function is not yet implemented for the Unity platform."); + return FALSE; +} + +gboolean +mono_threads_suspend_check_suspend_result (MonoThreadInfo *info) +{ + g_assert(0 && "This function is not yet implemented for the Unity platform."); + return FALSE; +} + +void +mono_threads_suspend_abort_syscall (MonoThreadInfo *info) +{ + g_assert(0 && "This function is not yet implemented for the Unity platform."); +} + +gboolean +mono_threads_suspend_needs_abort_syscall (void) +{ + g_assert(0 && "This function is not yet implemented for the Unity platform."); + return FALSE; +} + +gboolean +mono_threads_suspend_begin_async_resume (MonoThreadInfo *info) +{ + g_assert(0 && "This function is not yet implemented for the Unity platform."); + return FALSE; +} + +void +mono_threads_suspend_register (MonoThreadInfo *info) +{ + g_assert(0 && "This function is not yet implemented for the Unity platform."); +} + +void +mono_threads_suspend_free (MonoThreadInfo *info) +{ + g_assert(0 && "This function is not yet implemented for the Unity platform."); +} + +void +mono_threads_suspend_init_signals (void) +{ + g_assert(0 && "This function is not yet implemented for the Unity platform."); +} + +gint +mono_threads_suspend_search_alternative_signal (void) +{ + g_assert(0 && "This function is not yet implemented for the Unity platform."); + g_assert_not_reached (); +} + +gint +mono_threads_suspend_get_suspend_signal (void) +{ + g_assert(0 && "This function is not yet implemented for the Unity platform."); + return -1; +} + +gint +mono_threads_suspend_get_restart_signal (void) +{ + g_assert(0 && "This function is not yet implemented for the Unity platform."); + return -1; +} + +gint +mono_threads_suspend_get_abort_signal (void) +{ + g_assert(0 && "This function is not yet implemented for the Unity platform."); + return -1; +} + +int +mono_threads_platform_create_thread (MonoThreadStart thread_fn, gpointer thread_data, gsize* const stack_size, MonoNativeThreadId *out_tid) +{ + g_assert(0 && "This function is not yet implemented for the Unity platform."); + return-1; +} + + +MonoNativeThreadId +mono_native_thread_id_get (void) +{ + return (MonoNativeThreadId)UnityPalGetCurrentThreadId(); +} + +gboolean +mono_native_thread_id_equals (MonoNativeThreadId id1, MonoNativeThreadId id2) +{ + return id1 == id2; +} + +gboolean +mono_native_thread_create (MonoNativeThreadId *tid, gpointer func, gpointer arg) +{ + g_assert(0 && "This function is not yet implemented for the Unity platform."); + return FALSE; +} + +gboolean +mono_native_thread_join (MonoNativeThreadId tid) +{ + g_assert(0 && "This function is not yet implemented for the Unity platform."); + return FALSE; +} + +void +mono_threads_platform_get_stack_bounds (guint8 **staddr, size_t *stsize) +{ + g_assert(0 && "This function is not yet implemented for the Unity platform."); +} + +void +mono_threads_platform_init (void) +{ + g_assert(0 && "This function is not yet implemented for the Unity platform."); +} + +gboolean +mono_threads_platform_in_critical_region (MonoNativeThreadId tid) +{ + g_assert(0 && "This function is not yet implemented for the Unity platform."); +} + +gboolean +mono_threads_platform_yield (void) +{ + g_assert(0 && "This function is not yet implemented for the Unity platform."); + return FALSE; +} + +void +mono_threads_platform_exit (gsize exit_code) +{ + g_assert(0 && "This function is not yet implemented for the Unity platform."); +} + +int +mono_threads_get_max_stack_size (void) +{ + g_assert(0 && "This function is not yet implemented for the Unity platform."); + return 0; +} + +void +mono_native_thread_set_name (MonoNativeThreadId tid, const char *name) +{ + g_assert(0 && "This function is not yet implemented for the Unity platform."); +} + +#endif //PLATFORM_UNITY && UNITY_USE_PLATFORM_STUBS diff --git a/mono/utils/mono-threads-windows.c b/mono/utils/mono-threads-windows.c index 5a55af20570b..18e83f545c76 100644 --- a/mono/utils/mono-threads-windows.c +++ b/mono/utils/mono-threads-windows.c @@ -29,13 +29,12 @@ mono_threads_suspend_begin_async_suspend (MonoThreadInfo *info, gboolean interru HANDLE handle; DWORD result; - handle = OpenThread (THREAD_ALL_ACCESS, FALSE, id); + handle = info->native_handle; g_assert (handle); result = SuspendThread (handle); THREADS_SUSPEND_DEBUG ("SUSPEND %p -> %d\n", (void*)id, ret); if (result == (DWORD)-1) { - CloseHandle (handle); return FALSE; } @@ -48,7 +47,6 @@ mono_threads_suspend_begin_async_suspend (MonoThreadInfo *info, gboolean interru CONTEXT context; context.ContextFlags = CONTEXT_INTEGER | CONTEXT_CONTROL; if (!GetThreadContext (handle, &context)) { - CloseHandle (handle); return FALSE; } @@ -57,7 +55,6 @@ mono_threads_suspend_begin_async_suspend (MonoThreadInfo *info, gboolean interru mono_threads_add_to_pending_operation_set (info); result = ResumeThread (handle); g_assert (result == 1); - CloseHandle (handle); THREADS_SUSPEND_DEBUG ("FAILSAFE RESUME/1 %p -> %d\n", (void*)id, 0); //XXX interrupt_kernel doesn't make sense in this case as the target is not in a syscall return TRUE; @@ -71,7 +68,6 @@ mono_threads_suspend_begin_async_suspend (MonoThreadInfo *info, gboolean interru THREADS_SUSPEND_DEBUG ("FAILSAFE RESUME/2 %p -> %d\n", (void*)info->native_handle, 0); } - CloseHandle (handle); return TRUE; } @@ -86,15 +82,9 @@ mono_threads_suspend_check_suspend_result (MonoThreadInfo *info) void mono_threads_suspend_abort_syscall (MonoThreadInfo *info) { - DWORD id = mono_thread_info_get_tid (info); - HANDLE handle; - - handle = OpenThread (THREAD_ALL_ACCESS, FALSE, id); - g_assert (handle); - - mono_win32_abort_wait (info, handle, id); - - CloseHandle (handle); + DWORD id = mono_thread_info_get_tid(info); + g_assert (info->native_handle); + mono_win32_abort_wait (info, info->native_handle, id); } gboolean @@ -104,9 +94,10 @@ mono_threads_suspend_begin_async_resume (MonoThreadInfo *info) HANDLE handle; DWORD result; - handle = OpenThread (THREAD_ALL_ACCESS, FALSE, id); + handle = info->native_handle; g_assert (handle); - + +#if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) if (info->async_target) { MonoContext ctx; CONTEXT context; @@ -119,7 +110,6 @@ mono_threads_suspend_begin_async_resume (MonoThreadInfo *info) context.ContextFlags = CONTEXT_INTEGER | CONTEXT_CONTROL; if (!GetThreadContext (handle, &context)) { - CloseHandle (handle); return FALSE; } @@ -131,13 +121,14 @@ mono_threads_suspend_begin_async_resume (MonoThreadInfo *info) context.ContextFlags = CONTEXT_INTEGER | CONTEXT_CONTROL; res = SetThreadContext (handle, &context); if (!res) { - CloseHandle (handle); return FALSE; } } +#else + g_assert(0 && "Not implemented due to lack of SetThreadContext"); +#endif result = ResumeThread (handle); - CloseHandle (handle); return result != (DWORD)-1; } @@ -146,11 +137,20 @@ mono_threads_suspend_begin_async_resume (MonoThreadInfo *info) void mono_threads_suspend_register (MonoThreadInfo *info) { + BOOL success; + HANDLE currentThreadHandle = NULL; + + success = DuplicateHandle(GetCurrentProcess(), GetCurrentThread(), GetCurrentProcess(), ¤tThreadHandle, 0, FALSE, DUPLICATE_SAME_ACCESS); + g_assert(success && "Failed to duplicate current thread handle"); + + info->native_handle = currentThreadHandle; } void mono_threads_suspend_free (MonoThreadInfo *info) { + CloseHandle(info->native_handle); + info->native_handle = NULL; } void @@ -242,6 +242,12 @@ mono_native_thread_join_handle (HANDLE thread_handle, gboolean close_handle) return res != WAIT_FAILED; } +/* + * Can't OpenThread on UWP until SDK 15063 (our minspec today is 10240), + * but this function doesn't seem to be used on Windows anyway + */ +#if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) + gboolean mono_native_thread_join (MonoNativeThreadId tid) { @@ -253,6 +259,8 @@ mono_native_thread_join (MonoNativeThreadId tid) return mono_native_thread_join_handle (handle, TRUE); } +#endif + #if HAVE_DECL___READFSDWORD==0 static MONO_ALWAYS_INLINE unsigned long long __readfsdword (unsigned long offset) @@ -269,7 +277,7 @@ void mono_threads_platform_get_stack_bounds (guint8 **staddr, size_t *stsize) { MEMORY_BASIC_INFORMATION meminfo; -#ifdef _WIN64 +#if defined(_WIN64) || defined(_M_ARM) /* win7 apis */ NT_TIB* tib = (NT_TIB*)NtCurrentTeb(); guint8 *stackTop = (guint8*)tib->StackBase; diff --git a/mono/utils/mono-threads.h b/mono/utils/mono-threads.h index 2cc3d54ff4fd..a25973253512 100644 --- a/mono/utils/mono-threads.h +++ b/mono/utils/mono-threads.h @@ -151,7 +151,7 @@ typedef struct _MonoThreadInfoInterruptToken MonoThreadInfoInterruptToken; typedef struct { MonoLinkedListSetNode node; guint32 small_id; /*Used by hazard pointers */ - MonoNativeThreadHandle native_handle; /* Valid on mach and android */ + MonoNativeThreadHandle native_handle; /* Valid on mach, android and Windows */ int thread_state; /*Tells if this thread was created by the runtime or not.*/ diff --git a/mono/utils/mono-tls.h b/mono/utils/mono-tls.h index b87ede880ba5..a7950d8f5b2a 100644 --- a/mono/utils/mono-tls.h +++ b/mono/utils/mono-tls.h @@ -36,6 +36,19 @@ typedef enum { #include +/* +* These APIs were added back in Windows SDK 14393. Let's redirect them to +* Fls* APIs on older SDKs just like Windows 8.1 headers do +*/ +#if G_HAVE_API_SUPPORT(HAVE_UWP_WINAPI_SUPPORT) +#if WINDOWS_SDK_BUILD_VERSION < 14393 +#define TlsAlloc() FlsAlloc(NULL) +#define TlsGetValue FlsGetValue +#define TlsSetValue FlsSetValue +#define TlsFree FlsFree +#endif +#endif + #define MonoNativeTlsKey DWORD #define mono_native_tls_alloc(key,destructor) ((*(key) = TlsAlloc ()) != TLS_OUT_OF_INDEXES && destructor == NULL) #define mono_native_tls_free TlsFree diff --git a/mono/utils/networking-posix.c b/mono/utils/networking-posix.c index caa2073a539e..a771f55e0e7c 100644 --- a/mono/utils/networking-posix.c +++ b/mono/utils/networking-posix.c @@ -36,8 +36,10 @@ get_address_from_sockaddr (struct sockaddr *sa) switch (sa->sa_family) { case AF_INET: return &((struct sockaddr_in*)sa)->sin_addr; +#ifdef HAVE_STRUCT_SOCKADDR_IN6 case AF_INET6: return &((struct sockaddr_in6*)sa)->sin6_addr; +#endif } return NULL; } @@ -92,9 +94,11 @@ mono_get_address_info (const char *hostname, int port, int flags, MonoAddressInf if (cur->family == PF_INET) { cur->address_len = sizeof (struct in_addr); cur->address.v4 = ((struct sockaddr_in*)res->ai_addr)->sin_addr; +#ifdef HAVE_STRUCT_SOCKADDR_IN6 } else if (cur->family == PF_INET6) { cur->address_len = sizeof (struct in6_addr); cur->address.v6 = ((struct sockaddr_in6*)res->ai_addr)->sin6_addr; +#endif } else { g_warning ("Cannot handle address family %d", cur->family); res = res->ai_next; diff --git a/mono/utils/networking-unity.c b/mono/utils/networking-unity.c new file mode 100644 index 000000000000..105868779981 --- /dev/null +++ b/mono/utils/networking-unity.c @@ -0,0 +1,121 @@ +#include +#include + + +#include + +#if defined(PLATFORM_UNITY) && defined(UNITY_USE_PLATFORM_STUBS) + +#include "Socket-c-api.h" + +static void +add_hostent(MonoAddressInfo *info, int flags, const char* name, gint family, char** aliases, void** addresses, int32_t addressSize) +{ + MonoAddressEntry *cur, *prev = info->entries; + int idx = 0; + int address_length = 0; + + if (!info->aliases) + info->aliases = g_strdupv(aliases); + + while (addresses[idx]) { + cur = g_new0(MonoAddressEntry, 1); + if (prev) + prev->next = cur; + else + info->entries = cur; + + if (flags & MONO_HINT_CANONICAL_NAME && name) + cur->canonical_name = g_strdup(name); + + cur->family = family; + cur->socktype = SOCK_STREAM; + cur->protocol = 0; /* Zero means the default stream protocol */ + address_length = addressSize; + cur->address_len = address_length; + memcpy(&cur->address, addresses[idx], address_length); + + prev = cur; + ++idx; + } +} + +static void free_null_terminated_array (void** array) +{ + if (array != NULL) + { + int i = 0; + while (array[i] != NULL) + { + g_free(array[i]); + i++; + } + } + g_free(array); +} + +int +mono_get_address_info(const char *hostname, int port, int flags, MonoAddressInfo **result) +{ + MonoAddressInfo *addr_info; + addr_info = g_new0(MonoAddressInfo, 1); + + char* name; + gint family; + char** aliases; + void** addresses; + int32_t addressSize; + + if (UnityPalGetHostByName(hostname, &name, &family, &aliases, &addresses, &addressSize) == kWaitStatusSuccess) + add_hostent(addr_info, flags, name, family, aliases, addresses, addressSize); + + g_free(name); + free_null_terminated_array(aliases); + free_null_terminated_array(addresses); + + if (!addr_info->entries) { + *result = NULL; + mono_free_address_info(addr_info); + return 1; + } + + *result = addr_info; + return 0; +} + +void * +mono_get_local_interfaces (int family, int *interface_count) +{ + g_assert(0 && "This function is not yet implemented for the Unity platform."); + return NULL; +} + +gboolean +mono_networking_addr_to_str (MonoAddress *address, char *buffer, socklen_t buflen) +{ + g_assert(0 && "This function is not yet implemented for the Unity platform."); + return FALSE; +} + +int +mono_networking_get_tcp_protocol (void) +{ + g_assert(0 && "This function is not yet implemented for the Unity platform."); + return 0; +} + +int +mono_networking_get_ip_protocol (void) +{ + g_assert(0 && "This function is not yet implemented for the Unity platform."); + return 0; +} + +int +mono_networking_get_ipv6_protocol (void) +{ + g_assert(0 && "This function is not yet implemented for the Unity platform."); + return 0; +} + +#endif /* PLATFORM_UNITY && UNITY_USE_PLATFORM_STUBS */ diff --git a/mono/utils/networking.c b/mono/utils/networking.c index 104f3e5fa841..6f643dfd6923 100644 --- a/mono/utils/networking.c +++ b/mono/utils/networking.c @@ -17,8 +17,10 @@ mono_address_size_for_family (int family) switch (family) { case AF_INET: return sizeof (struct in_addr); +#ifdef HAVE_STRUCT_SOCKADDR_IN6 case AF_INET6: return sizeof (struct in6_addr); +#endif } return 0; } @@ -53,6 +55,7 @@ mono_socket_address_init (MonoSocketAddress *sa, socklen_t *len, int family, con #if HAVE_SOCKADDR_IN_SIN_LEN sa->v4.sin_len = sizeof (*len); #endif +#ifdef HAVE_STRUCT_SOCKADDR_IN6 } else if (family == AF_INET6) { *len = sizeof (struct sockaddr_in6); @@ -61,6 +64,7 @@ mono_socket_address_init (MonoSocketAddress *sa, socklen_t *len, int family, con sa->v6.sin6_port = htons (port); #if HAVE_SOCKADDR_IN6_SIN_LEN sa->v6.sin6_len = sizeof (*len); +#endif #endif } else { g_error ("Cannot handle address family %d", family); diff --git a/mono/utils/networking.h b/mono/utils/networking.h index f9c5f63dbc02..357c29933986 100644 --- a/mono/utils/networking.h +++ b/mono/utils/networking.h @@ -54,7 +54,9 @@ struct _MonoAddressEntry { int address_len; union { struct in_addr v4; +#ifdef HAVE_STRUCT_SOCKADDR_IN6 struct in6_addr v6; +#endif } address; const char *canonical_name; MonoAddressEntry *next; @@ -67,7 +69,9 @@ typedef struct { typedef union { struct sockaddr_in v4; +#ifdef HAVE_STRUCT_SOCKADDR_IN6 struct sockaddr_in6 v6; +#endif struct sockaddr addr; } MonoSocketAddress; @@ -75,7 +79,9 @@ typedef struct { int family; union { struct in_addr v4; +#ifdef HAVE_STRUCT_SOCKADDR_IN6 struct in6_addr v6; +#endif } addr; } MonoAddress; diff --git a/mono/utils/os-event-unity.c b/mono/utils/os-event-unity.c new file mode 100644 index 000000000000..94409c191356 --- /dev/null +++ b/mono/utils/os-event-unity.c @@ -0,0 +1,43 @@ +#include "os-event.h" + +#if defined(PLATFORM_UNITY) && defined(UNITY_USE_PLATFORM_STUBS) + +void +mono_os_event_init (MonoOSEvent *event, gboolean initial) +{ + g_assert(0 && "This function is not yet implemented for the Unity platform."); +} + +void +mono_os_event_destroy (MonoOSEvent *event) +{ + g_assert(0 && "This function is not yet implemented for the Unity platform."); +} + +void +mono_os_event_set (MonoOSEvent *event) +{ + g_assert(0 && "This function is not yet implemented for the Unity platform."); +} + +void +mono_os_event_reset (MonoOSEvent *event) +{ + g_assert(0 && "This function is not yet implemented for the Unity platform."); +} + +MonoOSEventWaitRet +mono_os_event_wait_one (MonoOSEvent *event, guint32 timeout, gboolean alertable) +{ + g_assert(0 && "This function is not yet implemented for the Unity platform."); + return MONO_OS_EVENT_WAIT_RET_TIMEOUT; +} + +MonoOSEventWaitRet +mono_os_event_wait_multiple (MonoOSEvent **events, gsize nevents, gboolean waitall, guint32 timeout, gboolean alertable) +{ + g_assert(0 && "This function is not yet implemented for the Unity platform."); + return MONO_OS_EVENT_WAIT_RET_TIMEOUT; +} + +#endif /* PLATFORM_UNITY && UNITY_USE_PLATFORM_STUBS */ diff --git a/mono/utils/unity-rand.c b/mono/utils/unity-rand.c new file mode 100644 index 000000000000..37b67bc1014a --- /dev/null +++ b/mono/utils/unity-rand.c @@ -0,0 +1,96 @@ +/* + * mono-rand-unity.c: + * + */ + + +#include +#include "mono-error.h" +#include + +/** + * mono_rand_open: + * + * Returns: True if random source is global, false if mono_rand_init can be called repeatedly to get randomness instances. + * + * Initializes entire RNG system. Must be called once per process before calling mono_rand_init. + */ +gboolean mono_rand_open (void) +{ + return UnityPalOpenCryptographyProvider(); +} + +/** + * mono_rand_init: + * @seed: A string containing seed data + * @seed_size: Length of seed string + * + * Returns: On success, a non-NULL handle which can be used to fetch random data from mono_rand_try_get_bytes. On failure, NULL. + * + * Initializes an RNG client. + */ +gpointer +mono_rand_init (guchar *seed, gint seed_size) +{ + return UnityPalGetCryptographyProvider(); +} + +/** + * mono_rand_try_get_bytes: + * @handle: A pointer to an RNG handle. Handle is set to NULL on failure. + * @buffer: A buffer into which to write random data. + * @buffer_size: Number of bytes to write into buffer. + * @error: Set on error. + * + * Returns: FALSE on failure and sets @error, TRUE on success. + * + * Extracts bytes from an RNG handle. + */ +gboolean +mono_rand_try_get_bytes (gpointer *handle, guchar *buffer, gint buffer_size, MonoError *error) +{ + mono_error_init (error); + return UnityPalCryptographyFillBufferWithRandomBytes(*handle, buffer_size, buffer); +} + +/** + * mono_rand_close: + * @handle: An RNG handle. + * @buffer: A buffer into which to write random data. + * @buffer_size: Number of bytes to write into buffer. + * + * Releases an RNG handle. + */ +void +mono_rand_close (gpointer handle) +{ + UnityPalReleaseCryptographyProvider(handle); +} + + +/** + * mono_rand_try_get_uint32: + * @handle: A pointer to an RNG handle. Handle is set to NULL on failure. + * @val: A pointer to a 32-bit unsigned int, to which the result will be written. + * @min: Result will be greater than or equal to this value. + * @max: Result will be less than or equal to this value. + * + * Returns: FALSE on failure, TRUE on success. + * + * Extracts one 32-bit unsigned int from an RNG handle. + */ +gboolean +mono_rand_try_get_uint32 (gpointer *handle, guint32 *val, guint32 min, guint32 max, MonoError *error) +{ + g_assert (val); + if (!mono_rand_try_get_bytes (handle, (guchar*) val, sizeof (guint32), error)) + return FALSE; + + double randomDouble = ((gdouble) *val) / ( ((double)G_MAXUINT32) + 1 ); // Range is [0,1) + *val = (guint32) (randomDouble * (max - min + 1) + min); + + g_assert (*val >= min); + g_assert (*val <= max); + + return TRUE; +} diff --git a/mono/utils/unity-time.c b/mono/utils/unity-time.c new file mode 100644 index 000000000000..0d0b1b4b0d2e --- /dev/null +++ b/mono/utils/unity-time.c @@ -0,0 +1,45 @@ +#include +#include + +#include + +#ifdef HAVE_SYS_TIME_H + #include +#endif + +#include "Time-c-api.h" + +gint64 +mono_msec_ticks (void) +{ + return (gint64) UnityPalGetTicksMillisecondsMonotonic(); +} + +/* Returns the number of 100ns ticks from unspecified time: this should be monotonic */ +gint64 +mono_100ns_ticks (void) +{ + return (gint64) UnityPalGetTicks100NanosecondsMonotonic(); +} + +/* Returns the number of 100ns ticks since 1/1/1601, UTC timezone */ +gint64 +mono_100ns_datetime (void) +{ + return (gint64) UnityPalGetTicks100NanosecondsDateTime(); +} + +gint64 +mono_msec_boottime (void) +{ + return (gint64) UnityPalGetTicksMillisecondsMonotonic(); +} + +#ifndef HOST_WIN32 +gint64 mono_100ns_datetime_from_timeval (struct timeval tv) +{ + g_assert_not_reached(); + return 0; +} +#endif + diff --git a/mono/utils/w32api.h b/mono/utils/w32api.h index 1d582fb945f8..45544c78fcdd 100644 --- a/mono/utils/w32api.h +++ b/mono/utils/w32api.h @@ -51,7 +51,7 @@ typedef struct pollfd { } WSAPOLLFD, *PWSAPOLLFD, *LPWSAPOLLFD; #endif -#if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) +#if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT | HAVE_UWP_WINAPI_SUPPORT) #include #endif diff --git a/msvc/.gitignore b/msvc/.gitignore index bcd711d0f5a8..423fe4bf689c 100644 --- a/msvc/.gitignore +++ b/msvc/.gitignore @@ -13,3 +13,4 @@ mono.VC.db /package/ /build/ /dist/ +/.vs/ diff --git a/msvc/libgcbdwgc.vcxproj b/msvc/libgcbdwgc.vcxproj new file mode 100644 index 000000000000..3adf562efea5 --- /dev/null +++ b/msvc/libgcbdwgc.vcxproj @@ -0,0 +1,170 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {CF169633-14AF-4DB8-BEF9-26A6C8FE4C90} + libgcbdwgc + Win32Proj + 8.1 + libgcbdwgc + + + + StaticLibrary + Unicode + v140 + + + StaticLibrary + Unicode + v140 + + + StaticLibrary + Unicode + v140 + + + StaticLibrary + Unicode + v140 + + + + + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + $(MONO_BUILD_DIR_PREFIX)$(Platform)\lib\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\obj\$(ProjectName)\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\lib\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\obj\$(ProjectName)\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\lib\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\obj\$(ProjectName)\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\lib\$(Configuration)\ + $(MONO_BUILD_DIR_PREFIX)$(Platform)\obj\$(ProjectName)\$(Configuration)\ + + + $(VC_IncludePath);$(WindowsSDK_IncludePath); + + + + Disabled + $(MONO_LIBBDWGC_INCLUDE_DIR);$(MONO_LIBATOMICS_INCLUDE_DIR);%(AdditionalIncludeDirectories) + WIN32_THREADS;ALL_INTERIOR_POINTERS=1;GC_GCJ_SUPPORT=1;JAVA_FINALIZATION=1;NO_EXECUTE_PERMISSION=1;GC_NO_THREADS_DISCOVERY=1;IGNORE_DYNAMIC_LOADING=1;GC_DONT_REGISTER_MAIN_STATIC_DATA=1;GC_VERSION_MAJOR=7;GC_VERSION_MINOR=4;GC_VERSION_MICRO=0;GC_THREADS=1;USE_MMAP=1;USE_MUNMAP=1;GC_INSIDE_DLL=1 + true + EnableFastChecks + + + ProgramDatabase + CompileAsC + 4311;4312;4996;4005;%(DisableSpecificWarnings) + Level1 + $(IntDir)$(TargetName).pdb + + + + + $(OutDir)$(TargetName)$(TargetExt) + + + + + MinSpace + $(MONO_LIBBDWGC_INCLUDE_DIR);$(MONO_LIBATOMICS_INCLUDE_DIR);%(AdditionalIncludeDirectories) + WIN32_THREADS;ALL_INTERIOR_POINTERS=1;GC_GCJ_SUPPORT=1;JAVA_FINALIZATION=1;NO_EXECUTE_PERMISSION=1;GC_NO_THREADS_DISCOVERY=1;IGNORE_DYNAMIC_LOADING=1;GC_DONT_REGISTER_MAIN_STATIC_DATA=1;GC_VERSION_MAJOR=7;GC_VERSION_MINOR=4;GC_VERSION_MICRO=0;GC_THREADS=1;USE_MMAP=1;USE_MUNMAP=1; + + + ProgramDatabase + CompileAsC + $(IntDir)$(TargetName).pdb + + + + + $(OutDir)$(TargetName)$(TargetExt) + + + + + X64 + + + Disabled + $(MONO_LIBBDWGC_INCLUDE_DIR);$(MONO_LIBATOMICS_INCLUDE_DIR);%(AdditionalIncludeDirectories) + WIN32_THREADS;ALL_INTERIOR_POINTERS=1;GC_GCJ_SUPPORT=1;JAVA_FINALIZATION=1;NO_EXECUTE_PERMISSION=1;GC_NO_THREADS_DISCOVERY=1;IGNORE_DYNAMIC_LOADING=1;GC_DONT_REGISTER_MAIN_STATIC_DATA=1;GC_VERSION_MAJOR=7;GC_VERSION_MINOR=4;GC_VERSION_MICRO=0;GC_THREADS=1;USE_MMAP=1;USE_MUNMAP=1; + true + EnableFastChecks + + + ProgramDatabase + CompileAsC + 4311;4312;4996;4005;%(DisableSpecificWarnings) + $(IntDir)$(TargetName).pdb + + + + + $(OutDir)$(TargetName)$(TargetExt) + + + + + X64 + + + MinSpace + $(MONO_LIBBDWGC_INCLUDE_DIR);$(MONO_LIBATOMICS_INCLUDE_DIR);%(AdditionalIncludeDirectories) + WIN32_THREADS;ALL_INTERIOR_POINTERS=1;GC_GCJ_SUPPORT=1;JAVA_FINALIZATION=1;NO_EXECUTE_PERMISSION=1;GC_NO_THREADS_DISCOVERY=1;IGNORE_DYNAMIC_LOADING=1;GC_DONT_REGISTER_MAIN_STATIC_DATA=1;GC_VERSION_MAJOR=7;GC_VERSION_MINOR=4;GC_VERSION_MICRO=0;GC_THREADS=1;USE_MMAP=1;USE_MUNMAP=1; + + + ProgramDatabase + CompileAsC + $(IntDir)$(TargetName).pdb + + + + + $(OutDir)$(TargetName)$(TargetExt) + + + + + + + + + \ No newline at end of file diff --git a/msvc/libgcbdwgc.vcxproj.filters b/msvc/libgcbdwgc.vcxproj.filters new file mode 100644 index 000000000000..5b782e942120 --- /dev/null +++ b/msvc/libgcbdwgc.vcxproj.filters @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/msvc/libmini-unity.targets b/msvc/libmini-unity.targets new file mode 100644 index 000000000000..e0d66997ccb1 --- /dev/null +++ b/msvc/libmini-unity.targets @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/msvc/libmini-unity.targets.filters b/msvc/libmini-unity.targets.filters new file mode 100644 index 000000000000..85d28c72f684 --- /dev/null +++ b/msvc/libmini-unity.targets.filters @@ -0,0 +1,19 @@ + + + + + Source Files$(MonoMiniFilterSubFolder)\unity + + + Header Files$(MonoMiniFilterSubFolder)\common + + + Source Files$(MonoMiniFilterSubFolder)\common + + + + + {A8B401A4-3AAA-431C-90B2-9834DAFF7D84} + + + diff --git a/msvc/libmini.targets b/msvc/libmini.targets index 5202159d86ec..e7a1b046d4f4 100644 --- a/msvc/libmini.targets +++ b/msvc/libmini.targets @@ -6,4 +6,5 @@ + diff --git a/msvc/libmini.targets.filters b/msvc/libmini.targets.filters index 972f58bf8616..5c6f247cbbe1 100644 --- a/msvc/libmini.targets.filters +++ b/msvc/libmini.targets.filters @@ -6,6 +6,7 @@ + {b64924de-7e02-416b-9779-4cc7fe0270e6} diff --git a/msvc/libmono-dynamic.vcxproj b/msvc/libmono-dynamic.vcxproj index 186bd7ffc316..d63cc408b1e6 100644 --- a/msvc/libmono-dynamic.vcxproj +++ b/msvc/libmono-dynamic.vcxproj @@ -89,6 +89,12 @@ true + + false + + + false + @@ -104,6 +110,7 @@ 4996;4018;4244;%(DisableSpecificWarnings) Level3 true + 4716 _DEBUG;%(PreprocessorDefinitions) @@ -113,7 +120,7 @@ false - $(GC_LIB);%(AdditionalDependencies) + $(GC_LIB);%(AdditionalDependencies) %(AdditionalLibraryDirectories) @@ -143,6 +150,7 @@ 4996;4018;4244;%(DisableSpecificWarnings) Level3 true + 4716 _DEBUG;%(PreprocessorDefinitions) @@ -152,7 +160,7 @@ false - $(GC_LIB);%(AdditionalDependencies) + $(GC_LIB);%(AdditionalDependencies) %(AdditionalLibraryDirectories) @@ -176,6 +184,7 @@ Level3 + 4716 NDEBUG;%(PreprocessorDefinitions) @@ -183,7 +192,7 @@ - $(GC_LIB);%(AdditionalDependencies) + $(GC_LIB);%(AdditionalDependencies) %(AdditionalLibraryDirectories) @@ -215,6 +224,7 @@ Level3 + 4716 NDEBUG;%(PreprocessorDefinitions) @@ -222,7 +232,7 @@ - $(GC_LIB);%(AdditionalDependencies) + $(GC_LIB);%(AdditionalDependencies) %(AdditionalLibraryDirectories) diff --git a/msvc/libmono-static.vcxproj b/msvc/libmono-static.vcxproj index 0c606ddb6af1..558325428785 100644 --- a/msvc/libmono-static.vcxproj +++ b/msvc/libmono-static.vcxproj @@ -201,6 +201,9 @@ {eb56000b-c80b-4e8b-908d-d84d31b517d3} + + {CF169633-14AF-4DB8-BEF9-26A6C8FE4C90} + {c36612bd-22d3-4b95-85e2-7fdc4fc5d740} diff --git a/msvc/libmonoruntime-common.targets.filters b/msvc/libmonoruntime-common.targets.filters index a3ac56434536..76fd6bc7ae46 100644 --- a/msvc/libmonoruntime-common.targets.filters +++ b/msvc/libmonoruntime-common.targets.filters @@ -112,6 +112,12 @@ Source Files$(MonoRuntimeFilterSubFolder)\common + + Source Files$(MonoRuntimeFilterSubFolder)\common + + + Header Files$(MonoRuntimeFilterSubFolder)\common + Header Files$(MonoRuntimeFilterSubFolder)\common diff --git a/msvc/libmonoruntime-unity.targets b/msvc/libmonoruntime-unity.targets new file mode 100644 index 000000000000..6ab9b117ab82 --- /dev/null +++ b/msvc/libmonoruntime-unity.targets @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/msvc/libmonoruntime-unity.targets.filters b/msvc/libmonoruntime-unity.targets.filters new file mode 100644 index 000000000000..d01749153e47 --- /dev/null +++ b/msvc/libmonoruntime-unity.targets.filters @@ -0,0 +1,35 @@ + + + + + Source Files$(MonoRuntimeFilterSubFolder)\unity + + + Source Files$(MonoRuntimeFilterSubFolder)\unity + + + Header Files$(MonoRuntimeFilterSubFolder)\unity + + + Source Files$(MonoRuntimeFilterSubFolder)\unity + + + Header Files$(MonoRuntimeFilterSubFolder)\unity + + + Source Files$(MonoRuntimeFilterSubFolder)\unity + + + Source Files$(MonoRuntimeFilterSubFolder)\unity + + + + + + {8F21E3A7-2BB9-403D-8339-DE0C45C84CCB} + + + {A38D033E-5AFC-4BEB-9F12-9A76F00E7749} + + + diff --git a/msvc/libmonoruntime.targets b/msvc/libmonoruntime.targets index 3dcf845605ab..cde45a537b1f 100644 --- a/msvc/libmonoruntime.targets +++ b/msvc/libmonoruntime.targets @@ -3,4 +3,5 @@ + diff --git a/msvc/libmonoruntime.targets.filters b/msvc/libmonoruntime.targets.filters index 2653ecb2d840..8787fa1d7e8c 100644 --- a/msvc/libmonoruntime.targets.filters +++ b/msvc/libmonoruntime.targets.filters @@ -3,6 +3,7 @@ + {992766FD-0584-4B49-A4F7-B59947CD8488} diff --git a/msvc/libmonoruntime.vcxproj b/msvc/libmonoruntime.vcxproj index b9b512dddb3c..287a7c1236e3 100644 --- a/msvc/libmonoruntime.vcxproj +++ b/msvc/libmonoruntime.vcxproj @@ -170,4 +170,4 @@ - \ No newline at end of file + diff --git a/msvc/mono.props b/msvc/mono.props index c9bd97e59e98..b96720b8871a 100644 --- a/msvc/mono.props +++ b/msvc/mono.props @@ -6,13 +6,13 @@ $(MSBuildProjectDirectory)/./dist/ - sgen + bdwgc true true - false + true false @@ -25,9 +25,11 @@ $(MONO_DIR)/mono/eglib $(MONO_DIR)/libgc/include $(MONO_DIR)/libgc/src + $(MONO_DIR)/external/bdwgc/include + $(MONO_DIR)/external/bdwgc/src + $(MONO_DIR)/external/bdwgc/libatomic_ops/src $(MONO_INCLUDE_DIR)/jit $(MONO_INCLUDE_DIR)/jit - $(MONO_LIBGC_INCLUDE_DIR) $(MONO_EGLIB_SOURCE_DIR) @@ -38,7 +40,7 @@ MultiThreadedDebugDLL MultiThreadedDLL - + HAVE_SGEN_GC;HAVE_MOVING_COLLECTOR;HAVE_WRITE_BARRIERS;HAVE_CONC_GC_AS_DEFAULT $(SGEN_DEFINES) libgcmonosgen.lib @@ -49,8 +51,16 @@ HAVE_BOEHM_GC $(BOEHM_DEFINES) libgc.lib + $(MONO_LIBGC_INCLUDE_DIR) -boehm $(MONO_BUILD_DIR_PREFIX)boehm/ + + + HAVE_BDWGC_GC;HAVE_BOEHM_GC + libgcbdwgc.lib + $(MONO_LIBBDWGC_INCLUDE_DIR);$(MONO_LIBATOMICS_INCLUDE_DIR) + -bdwgc + $(MONO_BUILD_DIR_PREFIX)bdwgc/ libmonoutils.lib;libmonoruntime$(MONO_TARGET_SUFFIX).lib;libmini$(MONO_TARGET_SUFFIX).lib;$(GC_LIB) diff --git a/msvc/mono.sln b/msvc/mono.sln index ac103fb6ea69..184a1931d829 100644 --- a/msvc/mono.sln +++ b/msvc/mono.sln @@ -1,6 +1,6 @@ Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.25420.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26730.15 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "EmbeddedSamples", "EmbeddedSamples", "{5FE09AA5-C3C9-45EA-A323-36A11B653CEC}" EndProject @@ -194,6 +194,11 @@ EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libmini", "libmini.vcxproj", "{88D2EB79-592D-45F8-B849-AE021C1D983A}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libmono-dynamic", "libmono-dynamic.vcxproj", "{675F4175-FFB1-480D-AD36-F397578844D4}" + ProjectSection(ProjectDependencies) = postProject + {CF169633-14AF-4DB8-BEF9-26A6C8FE4C90} = {CF169633-14AF-4DB8-BEF9-26A6C8FE4C90} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libgcbdwgc", "libgcbdwgc.vcxproj", "{CF169633-14AF-4DB8-BEF9-26A6C8FE4C90}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -411,6 +416,14 @@ Global {675F4175-FFB1-480D-AD36-F397578844D4}.Release|Win32.Build.0 = Release|Win32 {675F4175-FFB1-480D-AD36-F397578844D4}.Release|x64.ActiveCfg = Release|x64 {675F4175-FFB1-480D-AD36-F397578844D4}.Release|x64.Build.0 = Release|x64 + {CF169633-14AF-4DB8-BEF9-26A6C8FE4C90}.Debug|Win32.ActiveCfg = Debug|Win32 + {CF169633-14AF-4DB8-BEF9-26A6C8FE4C90}.Debug|Win32.Build.0 = Debug|Win32 + {CF169633-14AF-4DB8-BEF9-26A6C8FE4C90}.Debug|x64.ActiveCfg = Debug|x64 + {CF169633-14AF-4DB8-BEF9-26A6C8FE4C90}.Debug|x64.Build.0 = Debug|x64 + {CF169633-14AF-4DB8-BEF9-26A6C8FE4C90}.Release|Win32.ActiveCfg = Release|Win32 + {CF169633-14AF-4DB8-BEF9-26A6C8FE4C90}.Release|Win32.Build.0 = Release|Win32 + {CF169633-14AF-4DB8-BEF9-26A6C8FE4C90}.Release|x64.ActiveCfg = Release|x64 + {CF169633-14AF-4DB8-BEF9-26A6C8FE4C90}.Release|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -449,8 +462,10 @@ Global {DC50997D-8A0D-4EB6-849B-9D7FBC39CE53} = {DE3617B4-17A8-4E5F-A00F-BA43D956881F} {88D2EB79-592D-45F8-B849-AE021C1D983A} = {0EBA83B7-0EB4-4C83-A900-77300A97E8B1} {675F4175-FFB1-480D-AD36-F397578844D4} = {DE3617B4-17A8-4E5F-A00F-BA43D956881F} + {CF169633-14AF-4DB8-BEF9-26A6C8FE4C90} = {21DF4C80-0EC9-4BFE-8552-2D47FCEF419A} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {E4974D6A-1C06-4A4A-BE57-FAE790743A90} AMDCaProjectFile = C:\Users\Owner\Development\monogit\mono\msvc\CodeAnalyst\mono.caw AMDCaPersistentStartup = mono AMDCaPersistentConfig = Debug|Win32 diff --git a/runtime/Makefile.am b/runtime/Makefile.am index ffd935656177..a96903ce9c20 100644 --- a/runtime/Makefile.am +++ b/runtime/Makefile.am @@ -56,6 +56,14 @@ if INSTALL_TESTING_AOT_FULL build_profiles += testing_aot_full endif +if INSTALL_UNITYJIT +build_profiles += unityjit +endif + +if INSTALL_UNITYAOT +build_profiles += unityaot +endif + if INSTALL_WINAOT build_profiles += winaot endif