Skip to content

Instantly share code, notes, and snippets.

@luhenry
Created December 13, 2018 17:04
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save luhenry/794b08919c7aca8a0bcdf9be3c619a97 to your computer and use it in GitHub Desktop.
Save luhenry/794b08919c7aca8a0bcdf9be3c619a97 to your computer and use it in GitHub Desktop.
This file has been truncated, but you can view the full file.
diff --git a/.clang-format b/.clang-format
new file mode 100644
index 00000000000..a4148517c7b
--- /dev/null
+++ b/.clang-format
@@ -0,0 +1,49 @@
+# This is a minimal clang-format file for Mono code. The code is not consistent
+# in its formatting, so this file is most often useful with git-clang-format [1],
+# which formats only changed lines.
+#
+# Usage:
+# * Make some changes to Mono C code or headers
+# * Run `git clang-format` (maybe add -f if there are line ending issues from git)
+# * Your changed code should meet the formatting guidelines for Mono
+#
+# Installation:
+# * Install LLVM tools (including clang-format) for your OS [2]
+# * Install Pythong on your OS
+#
+# Code style:
+# Our goal is to match the Mono code style, not define a new one. The style
+# options [3] are many. Here we try to capture only a few. If you find something
+# is missing, feel free to add configuration options.
+#
+# [1] https://github.com/llvm-mirror/clang/blob/master/tools/clang-format/git-clang-format
+# [2] http://releases.llvm.org/
+# [3] https://clang.llvm.org/docs/ClangFormatStyleOptions.html
+
+# All function declarations and calls should have a space after the name
+SpaceBeforeParens: Always
+
+# Use four space tabs
+UseTab: Always
+TabWidth: 4
+IndentWidth: 4
+
+# Handle curly braces, basically: functions get a line break, nothing else does
+BreakBeforeBraces: Custom
+BraceWrapping:
+ AfterControlStatement: false
+ AfterStruct: false
+ AfterFunction: true
+ AfterEnum: false
+ AfterStruct: false
+ AfterUnion: false
+ BeforeElse: false
+
+# Keep function return types on a different line from the function name
+# Note that often static function forward declarations don't follow this
+# approach, and have the return type on the same line. I'm not sure
+# clang-format can handle these two cases differently.
+AlwaysBreakAfterReturnType: TopLevel
+
+# Don't warp any long lines
+ColumnLimit: 0
\ No newline at end of file
diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 00000000000..f06c382dcef
--- /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/.gitignore b/.gitignore
index c6ef19a849b..14166d5d9ec 100644
--- a/.gitignore
+++ b/.gitignore
@@ -117,6 +117,13 @@ GTAGS
docs/doxygen*
docs/perlmod*
+# Bee
+artifacts
+.vs
+external/buildscripts/build.gen*
+
+# Allow
+!external/buildscripts/bee.exe
##############################################################################
# Mono-specific patterns
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
new file mode 100644
index 00000000000..52dc597ae97
--- /dev/null
+++ b/.gitlab-ci.yml
@@ -0,0 +1,238 @@
+stages:
+- runall
+- build
+- collate
+
+# This is just a config to help trigger rest of the builds
+run_all_builds:
+ image: ubuntu:latest
+ stage: runall
+ variables:
+ GIT_STRATEGY: none
+ script:
+ - pwd
+ when: manual
+ allow_failure: false
+
+# Build
+build_osx_runtime:
+ stage: build
+ tags:
+ - bokken-job
+ variables:
+ BOKKEN_VM: build_osx_runtime_vm
+ BOKKEN_JOB: |
+ resources:
+ - name: build_osx_runtime_vm
+ image: buildfarm/mac:latest
+ flavor: m1.mac
+ type: Unity::VM::osx
+ num_instances: 1
+ config:
+ env_vars:
+ - PATH=/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/opt/X11/bin
+ script:
+ - git submodule update --init --recursive
+ - cd external/buildscripts
+ - ./bee
+ - cd ../..
+ - perl external/buildscripts/build_runtime_osx.pl --stevedorebuilddeps=1
+ - mkdir -p incomingbuilds/osx-i386
+ - cp -r builds/ incomingbuilds/osx-i386/
+ artifacts:
+ paths:
+ - incomingbuilds/osx-i386
+ expire_in: 1 week
+# Important! Do not remove this after_script!!
+ after_script:
+ - /opt/post_build_script.sh
+
+build_osx_classlibs:
+ stage: build
+ tags:
+ - bokken-job
+ variables:
+ BOKKEN_VM: build_osx_classlibs_vm
+ BOKKEN_JOB: |
+ resources:
+ - name: build_osx_classlibs_vm
+ image: buildfarm/mac:latest
+ flavor: m1.mac
+ type: Unity::VM::osx
+ num_instances: 1
+ config:
+ env_vars:
+ - PATH=/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/opt/X11/bin
+ script:
+ - git submodule update --init --recursive
+ - cd external/buildscripts
+ - ./bee
+ - cd ../..
+ - perl external/buildscripts/build_classlibs_osx.pl --stevedorebuilddeps=1
+ - mkdir -p incomingbuilds/classlibs
+ - cp -r ZippedClasslibs.tar.gz incomingbuilds/classlibs/
+ - cd incomingbuilds/classlibs
+ - tar -pzxf ZippedClasslibs.tar.gz
+ - rm -f ZippedClasslibs.tar.gz
+ - cd ../..
+ artifacts:
+ paths:
+ - incomingbuilds/classlibs
+ expire_in: 1 week
+# Important! Do not remove this after_script!!
+ after_script:
+ - /opt/post_build_script.sh
+
+build_android:
+ stage: build
+ tags:
+ - bokken-job
+ variables:
+ BOKKEN_VM: build_android_vm
+ BOKKEN_JOB: |
+ resources:
+ - name: build_android_vm
+ image: buildfarm/mac:latest
+ flavor: m1.mac
+ type: Unity::VM::osx
+ num_instances: 1
+ config:
+ env_vars:
+ - PATH=/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/opt/X11/bin
+ script:
+ - git submodule update --init --recursive
+ - cd external/buildscripts
+ - ./bee
+ - cd ../..
+ - perl external/buildscripts/build_runtime_android.pl --stevedorebuilddeps=1
+ - mkdir -p incomingbuilds/android/
+ - cp -r builds/* incomingbuilds/android/
+ artifacts:
+ paths:
+ - incomingbuilds/android
+ expire_in: 1 week
+# Important! Do not remove this after_script!!
+ after_script:
+ - /opt/post_build_script.sh
+
+build_win:
+ stage: build
+ tags:
+ - buildfarm
+ - windows
+ script:
+ - git submodule update --init --recursive
+ - perl external/buildscripts/build_runtime_win64.pl --stevedorebuilddeps=1
+ - mkdir -p incomingbuilds/win64
+ - cp -r builds/* incomingbuilds/win64/
+ artifacts:
+ paths:
+ - incomingbuilds/win64
+ expire_in: 1 week
+# Important! Do not remove this after_script!!
+ after_script:
+ - C:\Users\builduser\post_build_script.bat
+
+build_win_x86:
+ stage: build
+ tags:
+ - buildfarm
+ - windows
+ script:
+ - git submodule update --init --recursive
+ - perl external/buildscripts/build_runtime_win.pl --stevedorebuilddeps=1
+ - mkdir -p incomingbuilds/win32
+ - cp -r builds/* incomingbuilds/win32/
+ artifacts:
+ paths:
+ - incomingbuilds/win32
+ expire_in: 1 week
+# Important! Do not remove this after_script!!
+ after_script:
+ - C:\Users\builduser\post_build_script.bat
+
+build_win_bare_minimum:
+ stage: build
+ tags:
+ - buildfarm
+ - windows
+ script:
+ - git submodule update --init --recursive
+ - perl external/buildscripts/build_unityscript_bareminimum_win.pl
+ - mkdir -p incomingbuilds/bareminimum
+ - cp -r builds/* incomingbuilds/bareminimum/
+ artifacts:
+ paths:
+ - incomingbuilds/bareminimum
+ expire_in: 1 week
+# Important! Do not remove this after_script!!
+ after_script:
+ - C:\Users\builduser\post_build_script.bat
+
+build_linux_x64:
+ stage: build
+ tags:
+ - buildfarm
+ - linux
+ script:
+ - git submodule update --init --recursive
+ - cd external/buildscripts
+ - ./bee
+ - cd ../..
+ - perl external/buildscripts/build_runtime_linux.pl -build64=1 --stevedorebuilddeps=1
+ - mkdir -p incomingbuilds/linux64
+ - cp -r builds/* incomingbuilds/linux64/
+ artifacts:
+ paths:
+ - incomingbuilds/linux64
+ expire_in: 1 week
+# Important! Do not remove this after_script!!
+ after_script:
+ - /opt/post_build_script.sh
+
+build_linux_x86:
+ stage: build
+ tags:
+ - buildfarm
+ - linux
+ script:
+ - git submodule update --init --recursive
+ - cd external/buildscripts
+ - ./bee
+ - cd ../..
+ - perl external/buildscripts/build_runtime_linux.pl --stevedorebuilddeps=1
+ - mkdir -p incomingbuilds/linux32
+ - cp -r builds/* incomingbuilds/linux32/
+ artifacts:
+ paths:
+ - incomingbuilds/linux32
+ expire_in: 1 week
+# Important! Do not remove this after_script!!
+ after_script:
+ - /opt/post_build_script.sh
+
+collate_builds:
+ image: ubuntu:latest
+ stage: collate
+ dependencies:
+ - build_android
+ - build_osx_runtime
+ - build_osx_classlibs
+ - build_win
+ - build_win_x86
+ - build_win_bare_minimum
+ - build_linux_x86
+ - build_linux_x64
+ before_script:
+ - apt-get update -qy && apt-get -qy upgrade
+ - apt-get install -qy perl
+ - apt-get install -qy zip unzip
+ - apt-get install -qy p7zip-full p7zip-rar
+ script:
+ - perl external/buildscripts/collect_allbuilds.pl
+ - pwd
+ - ls -al
+ artifacts:
+ paths:
+ - collectedbuilds/builds.7z
+ expire_in: 1 week
\ No newline at end of file
diff --git a/.gitmodules b/.gitmodules
index 4e968d7a066..04b5228b6be 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 f9dd1784c83..024324e3fc7 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 ce96d99aa05..1cd081794e3 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,55 @@
+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-\<version\>\[-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.3
+* [unity-2018.3](https://github.com/Unity-Technologies/mono/tree/unity-2018.3)
+* [unity-2018.3-mbe](https://github.com/Unity-Technologies/mono/tree/unity-2018.3-mbe)
+
+#### 2018.2
+* [unity-2018.2](https://github.com/Unity-Technologies/mono/tree/unity-2018.2)
+* [unity-2018.2-mbe](https://github.com/Unity-Technologies/mono/tree/unity-2018.2-mbe)
+
+#### 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 7c58e092150..88c2eded6c6 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 ec5b8e7ac67..53c48fdf65b 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/config.in b/data/config.in
index 282bc114950..d03bfe3e8b8 100644
--- a/data/config.in
+++ b/data/config.in
@@ -10,8 +10,8 @@
<dllmap dll="i:odbc32.dll" target="libiodbc.dylib" os="osx"/>
<dllmap dll="oci" target="libclntsh@libsuffix@" os="!windows"/>
<dllmap dll="db2cli" target="libdb2_36@libsuffix@" os="!windows"/>
- <dllmap dll="MonoPosixHelper" target="$mono_libdir/libMonoPosixHelper@libsuffix@" os="!windows" />
- <dllmap dll="libmono-btls-shared" target="$mono_libdir/libmono-btls-shared@libsuffix@" os="!windows" />
+ <dllmap dll="MonoPosixHelper" target="libMonoPosixHelper@libsuffix@" os="!windows" />
+ <dllmap dll="libmono-btls-shared" target="libmono-btls-shared@libsuffix@" os="!windows" />
<dllmap dll="i:msvcrt" target="@LIBC@" os="!windows"/>
<dllmap dll="i:msvcrt.dll" target="@LIBC@" os="!windows"/>
<dllmap dll="sqlite" target="@SQLITE@" os="!windows"/>
diff --git a/data/net_2_0/machine.config b/data/net_2_0/machine.config
index 2f8090f0288..9da7be98719 100644
--- a/data/net_2_0/machine.config
+++ b/data/net_2_0/machine.config
@@ -118,6 +118,9 @@
<add prefix="file" type="System.Net.FileWebRequestCreator, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<add prefix="ftp" type="System.Net.FtpRequestCreator, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
</webRequestModules>
+ <settings>
+ <ipv6 enabled="true"/>
+ </settings>
</system.net>
<system.runtime.remoting>
diff --git a/data/net_4_0/machine.config b/data/net_4_0/machine.config
index 30bc2105f3a..12839c1f6a3 100644
--- a/data/net_4_0/machine.config
+++ b/data/net_4_0/machine.config
@@ -135,6 +135,9 @@
<add prefix="file" type="System.Net.FileWebRequestCreator, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<add prefix="ftp" type="System.Net.FtpRequestCreator, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
</webRequestModules>
+ <settings>
+ <ipv6 enabled="true"/>
+ </settings>
</system.net>
<system.runtime.remoting>
diff --git a/data/net_4_5/machine.config b/data/net_4_5/machine.config
index d17369394e3..61f7889871f 100644
--- a/data/net_4_5/machine.config
+++ b/data/net_4_5/machine.config
@@ -138,6 +138,9 @@
<add prefix="file" type="System.Net.FileWebRequestCreator, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<add prefix="ftp" type="System.Net.FtpRequestCreator, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
</webRequestModules>
+ <settings>
+ <ipv6 enabled="true"/>
+ </settings>
</system.net>
<system.runtime.remoting>
diff --git a/external/bdwgc b/external/bdwgc
new file mode 160000
index 00000000000..c317f5379e1
--- /dev/null
+++ b/external/bdwgc
@@ -0,0 +1 @@
+Subproject commit c317f5379e16a412492f42383c891b3948234709
diff --git a/external/binary-reference-assemblies b/external/binary-reference-assemblies
index 9f07d0746d9..e048fe4a88d 160000
--- a/external/binary-reference-assemblies
+++ b/external/binary-reference-assemblies
@@ -1 +1 @@
-Subproject commit 9f07d0746d94d2c2b055e3e689814ca07431e5fd
+Subproject commit e048fe4a88d237d105ae02fe0363a68296099362
diff --git a/external/buildscripts/Build.bee.cs b/external/buildscripts/Build.bee.cs
new file mode 100644
index 00000000000..1cb8a1beeb3
--- /dev/null
+++ b/external/buildscripts/Build.bee.cs
@@ -0,0 +1,132 @@
+using System;
+using System.IO;
+using Bee.Core;
+using Bee.Stevedore;
+using NiceIO;
+using Unity.BuildTools;
+using System.Collections.Generic;
+using System.Text;
+using Bee.Stevedore.Program;
+
+namespace BuildProgram
+{
+ public class BuildProgram
+ {
+ internal static void Main()
+ {
+ if (IsRunningOnBuildMachine())
+ Console.WriteLine("\n>>> Running on build machine");
+
+ var monoRoot = GetMonoRootDir();
+ Console.WriteLine(">>> Mono root directory: " + monoRoot);
+
+ var buildScriptsRoot = monoRoot.Combine("external").Combine("buildscripts");
+ Console.WriteLine(">>> Build scripts directory: " + buildScriptsRoot);
+
+ var buildDependenciesConfigFile = buildScriptsRoot.Combine("buildDependencies.txt");
+ Console.WriteLine(">>> Mono build dependecies stevedore version config file: " + buildDependenciesConfigFile);
+
+ var stevedoreArtifactsDir = buildScriptsRoot.Combine("artifacts").Combine("Stevedore");
+ Console.WriteLine(">>> Stevedore artifacts directory: " + stevedoreArtifactsDir + "\n");
+
+ if (buildDependenciesConfigFile.Exists())
+ {
+ var artifactList = ParseBuildDependenciesConfigFile(buildDependenciesConfigFile.ToString());
+
+ foreach (var item in artifactList)
+ {
+ var artifactName = item.Item1;
+ var artifactId = item.Item2;
+ var repoName = item.Item3;
+ DownloadArtifact(artifactId, artifactName, repoName);
+ }
+ }
+ else
+ {
+ throw new Exception($"{buildDependenciesConfigFile} does not exist");
+ }
+ }
+
+ private static void DownloadArtifact(string artifactId, string artifactName, string repoName)
+ {
+ Console.WriteLine($">>> Registering artifact {artifactName}");
+ var artifact = new StevedoreArtifact(repoName, new ArtifactId(artifactId));
+ Backend.Current.Register(artifact);
+ }
+
+ private static NPath GetMonoRootDir()
+ {
+ var exePath = new NPath(System.Reflection.Assembly.GetEntryAssembly().Location);
+ var monoRoot = exePath;
+
+ //Assume "external" directory exists under monoRoot.
+ while (monoRoot.ToString().Contains("external"))
+ monoRoot = monoRoot.Parent;
+
+ return monoRoot;
+ }
+
+ private static bool IsRunningOnBuildMachine()
+ {
+ var buildMachine = Environment.GetEnvironmentVariable("UNITY_THISISABUILDMACHINE");
+ return buildMachine != null && buildMachine == "1";
+ }
+
+ //Sample config file format:
+ /*
+ # Dependencoes to pull down from Stevedore. Please follow the following format:
+ # name : <stevedore artifact name>
+ # id : <stevedore artifact id>
+ # repo : <stevedore repo name (can be testing/public/unityinternal)>
+
+ name: 7z
+ id: 7z/9df1e3b3b120_12ed325f6a47f0e5cebc247dbe9282a5da280d392cce4e6c9ed227d57ff1e2ff.7z
+ repo: testing
+
+ name: libgdiplus
+ id : libgdiplus/9df1e3b3b120_4cf7c08770db93922f54f38d2461b9122cddc898db58585864446e70c5ad3057.7z
+ repo: public
+ */
+ private static List<Tuple<string, string, string>> ParseBuildDependenciesConfigFile(string buildDependenciesConfigFile)
+ {
+ var artifactNameIdFilesDictionary = new List<Tuple<string, string, string>>();
+
+ var fileStream = new FileStream(buildDependenciesConfigFile, FileMode.Open, FileAccess.Read);
+ using (var streamReader = new StreamReader(fileStream, Encoding.UTF8))
+ {
+ string line;
+ while ((line = streamReader.ReadLine()) != null)
+ {
+ //Check if line contains a comment
+ if (!string.IsNullOrEmpty(line) && !line.Contains("#"))
+ {
+ if (line.Contains("name :") || line.Contains("name:"))
+ {
+ var name = "";
+ var id = "";
+ var repoName = "";
+
+ //read name
+ name = line.Split(':')[1].Trim();
+
+ //read id
+ if ((line = streamReader.ReadLine()) != null)
+ id = line.Split(':')[1].Trim();
+ else
+ throw new Exception($">>> Invalid {buildDependenciesConfigFile}, id name does not exist");
+
+ //read repo name
+ if ((line = streamReader.ReadLine()) != null)
+ repoName = line.Split(':')[1].Trim();
+ else
+ throw new Exception($">>> Invalid {buildDependenciesConfigFile}, repo name does not exist");
+
+ artifactNameIdFilesDictionary.Add(new Tuple<string, string, string>(name, id, repoName));
+ }
+ }
+ }
+ }
+ return artifactNameIdFilesDictionary;
+ }
+ }
+}
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 00000000000..a8360f86295
--- /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 00000000000..685963d34fc
--- /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 00000000000..de796470ff8
--- /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 00000000000..c7e0afc7f7c
--- /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 00000000000..3b3e4635ee5
--- /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 00000000000..7a48ace18ce
--- /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 00000000000..3ef693d443d
--- /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 00000000000..46c41b4744f
--- /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 00000000000..9b85997c392
--- /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 00000000000..4da80a1bc55
--- /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 00000000000..013920349f8
--- /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 00000000000..1a72b09096e
--- /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 00000000000..c21335b65c0
--- /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 00000000000..17db31ffd0b
--- /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 00000000000..20d79ca7d3b
--- /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 00000000000..c3ec2fbb896
--- /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 00000000000..60ba18fe8be
--- /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 00000000000..50b3a8e4499
--- /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/bee b/external/buildscripts/bee
new file mode 100755
index 00000000000..78715cd133a
--- /dev/null
+++ b/external/buildscripts/bee
@@ -0,0 +1,2 @@
+#!/bin/sh
+mono bee.exe "$@"
\ No newline at end of file
diff --git a/external/buildscripts/bee.exe b/external/buildscripts/bee.exe
new file mode 100644
index 00000000000..1e6347c24a5
Binary files /dev/null and b/external/buildscripts/bee.exe differ
diff --git a/external/buildscripts/build.pl b/external/buildscripts/build.pl
new file mode 100644
index 00000000000..431733b32a7
--- /dev/null
+++ b/external/buildscripts/build.pl
@@ -0,0 +1,1820 @@
+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;
+my $stevedoreBuildDeps=1;
+
+# 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,
+ 'stevedorebuilddeps=i'=>\$stevedoreBuildDeps,
+) 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
+{
+ if($stevedoreBuildDeps)
+ {
+ $externalBuildDeps = "$monoroot/external/buildscripts/artifacts/Stevedore";
+ }
+ else
+ {
+ $externalBuildDeps = "$monoroot/../../mono-build-deps/build";
+ }
+}
+print(">>> External build deps = $externalBuildDeps\n");
+
+# 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 $extraBuildTools = "$monoroot/../../mono-build-tools-extra/build";
+
+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 (!(-d "$extraBuildTools"))
+ {
+ # Check out on the fly
+ print(">>> Checking out mono build tools extra to : $extraBuildTools\n");
+ my $repo = 'git@github.cds.internal.unity3d.com:unity/mono-build-tools-extra.git';
+ print(">>> Cloning $repo at $extraBuildTools\n");
+ my $checkoutResult = system("git", "clone", "--recurse-submodules", $repo, "$extraBuildTools");
+
+ if ($checkoutResult ne 0)
+ {
+ die("Failed to checkout mono build tools extra\n");
+ }
+
+ # Only clean up if the dir exists. Otherwise abs_path will return empty string
+ $extraBuildTools = abs_path($extraBuildTools) if (-d $extraBuildTools);
+ }
+
+ if ($existingMonoRootPath eq "")
+ {
+ print(">>> No existing mono supplied. Checking for external...\n");
+
+ if (!(-d "$externalBuildDeps"))
+ {
+ if($stevedoreBuildDeps)
+ {
+ print(">>> Running bee to download build-deps...\n");
+ chdir($buildscriptsdir) eq 1 or die ("failed to chdir to $buildscriptsdir directory\n");
+ system("./bee") eq 0 or die ("failed to run bee\n");
+ chdir("$monoroot") eq 1 or die ("failed to chdir to $monoroot\n");
+ }
+ else
+ {
+ 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-2-69/autoconf-$autoconfVersion";
+ my $texinfoDir = "$externalBuildDeps/texinfo-4-8/texinfo-$texinfoVersion";
+ my $automakeDir = "$externalBuildDeps/automake-1-15/automake-$automakeVersion";
+ my $libtoolDir = "$externalBuildDeps/libtool-2-4-6/libtool-$libtoolVersion";
+ my $builtToolsDir = "$externalBuildDeps/built-tools";
+
+ $ENV{PATH} = "$builtToolsDir/bin:$ENV{PATH}";
+
+ if ($stevedoreBuildDeps)
+ {
+ $autoconfDir = "$externalBuildDeps/autoconf-src/autoconf-$autoconfVersion";
+ }
+ elsif (!(-d "$autoconfDir"))
+ {
+ print(">>> Extracting autoconf\n");
+ chdir("$externalBuildDeps/autoconf-2-69") 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");
+ }
+ if (-d "$autoconfDir")
+ {
+ print(">>> Installing autoconf from $autoconfDir\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 ($stevedoreBuildDeps and $windowsSubsystemForLinux)
+ {
+ $texinfoDir = "$externalBuildDeps/texinfo-src/texinfo-$texinfoVersion";
+ }
+ elsif (!(-d "$texinfoDir") and $windowsSubsystemForLinux)
+ {
+ print(">>> Extracting texinfo\n");
+ chdir("$externalBuildDeps/texinfo-4-8") 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");
+ }
+ if (-d "$texinfoDir")
+ {
+ print(">>> Installing texinfo from $texinfoDir\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 ($stevedoreBuildDeps)
+ {
+ $automakeDir = "$externalBuildDeps/automake-src/automake-$automakeVersion";
+ }
+ elsif (!(-d "$automakeDir"))
+ {
+ print(">>> Extracting automake\n");
+ chdir("$externalBuildDeps/automake-1-15") 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");
+ }
+ if (-d "$automakeDir")
+ {
+ my $automakeMakeFlags = "";
+ print(">>> Installing automake from $automakeDir\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 ($stevedoreBuildDeps)
+ {
+ $libtoolDir = "$externalBuildDeps/libtool-src/libtool-$libtoolVersion";
+ }
+ elsif (!(-d "$libtoolDir"))
+ {
+ print(">>> Extracting libtool\n");
+ chdir("$externalBuildDeps/libtool-2-4-6") 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");
+ }
+ if (-d "$libtoolDir")
+ {
+ print(">>> Installing libtool from $libtoolDir\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("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("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 = "r16b";
+ my $apiLevel = 16;
+ my $hostTriple = "";
+ my $platformRootPostfix = "";
+ my $useKraitPatch = 1;
+ my $kraitPatchPath = "$monoroot/../../android_krait_signal_handler/build";
+ my $toolChainExtension = "";
+
+ $ENV{ANDROID_PLATFORM} = "android-$apiLevel";
+
+ if ($androidArch eq "armv7a")
+ {
+ $hostTriple = "arm-linux-androideabi";
+ $platformRootPostfix = "arm";
+ }
+ elsif ($androidArch eq "x86")
+ {
+ $hostTriple = "i686-linux-android";
+ $platformRootPostfix = "x86";
+ $useKraitPatch = 0;
+ }
+ else
+ {
+ die("Unsupported android architecture: $androidArch\n");
+ }
+
+ 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");
+
+ my $ndkName = "";
+ if($^O eq "linux")
+ {
+ $ndkName = "android-ndk-$ndkVersion-linux/android-ndk-$ndkVersion-linux-x86_64.zip";
+ }
+ elsif($^O eq "darwin")
+ {
+ $ndkName = "android-ndk-$ndkVersion-darwin/android-ndk-$ndkVersion-darwin-x86_64.zip";
+ }
+ else
+ {
+ $ndkName = "android-$ndkVersion-r16b-windows/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/$hostTriple-clang";
+
+ print(">>> Generating android toolchain\n");
+ system("$androidNdkRoot/build/tools/make_standalone_toolchain.py --arch $platformRootPostfix --api $apiLevel --install-dir $androidToolchain");
+
+ 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 "armv7a")
+ {
+ $ENV{CFLAGS} = "-DARM_FPU_VFP=1 -march=armv7-a -target armv7-none-linux-androideabi -DHAVE_ARMV6=1 -funwind-tables $ENV{CFLAGS}";
+ $ENV{LDFLAGS} = "-Wl,--fix-cortex-a8 -Wl,-rpath-link=$androidPlatformRoot/usr/lib $ENV{LDFLAGS}";
+ }
+
+ my $compilerSysroot = "$androidNdkRoot/sysroot";
+ my $archISystem = "$compilerSysroot/usr/include/$hostTriple";
+ my $unifiedISystem = "$compilerSysroot/usr/include";
+
+ $ENV{CC} = "$androidToolchain/bin/clang -v -isystem $archISystem -isystem $unifiedISystem";
+ $ENV{CXX} = "$androidToolchain/bin/clang++ -isystem $archISystem -isystem $unifiedISystem";
+ $ENV{CPP} = "$androidToolchain/bin/clang -E -isystem $archISystem -isystem $unifiedISystem";
+ $ENV{CXXCPP} = "$androidToolchain/bin/clang++ -E -isystem $archISystem -isystem $unifiedISystem";
+
+ $ENV{CPATH} = "$androidPlatformRoot/usr/include";
+
+ $ENV{LD} = "$androidToolchain/bin/$hostTriple-ld";
+ $ENV{AS} = "$androidToolchain/bin/$hostTriple-as";
+ $ENV{AR} = "$androidToolchain/bin/$hostTriple-ar";
+ $ENV{RANLIB} = "$androidToolchain/bin/$hostTriple-ranlib";
+ $ENV{STRIP} = "$androidToolchain/bin/$hostTriple-strip";
+
+ $ENV{CFLAGS} = "-DANDROID -D__ANDROID_API__=16 -DPLATFORM_ANDROID -DLINUX -D__linux__ -DHAVE_USR_INCLUDE_MALLOC_H -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-v7a -lkrait-signal-handler $ENV{LDFLAGS}";
+ }
+
+ $ENV{LDFLAGS} = "--sysroot=$androidPlatformRoot -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");
+ }
+
+ push @configureparams, "--host=$hostTriple";
+
+ 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/linux-sdk-$sdkVersion/$sdkName";
+ my $depsSdkFinal = "$externalBuildDeps/linux-sdk-$sdkVersion/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";
+ push @configureparams, "--enable-minimal=shared_perfcounters";
+
+ 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");
+
+ my $stubResult = system("perl", "$buildscriptsdir/stub_classlibs.pl");
+
+ if ($stubResult ne 0)
+ {
+ die("Failed to run the profile stubber\n");
+ }
+ }
+}
+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','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");
+ }
+ print ">>> Copying libMonoPosixHelper.so\n";
+ system("cp", "$monoroot/support/.libs/libMonoPosixHelper.so","$embedDirArchDestination/libMonoPosixHelper.so") eq 0 or die ("failed copying libMonoPosixHelper.so\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/buildDependencies.txt b/external/buildscripts/buildDependencies.txt
new file mode 100644
index 00000000000..939dc6f38ac
--- /dev/null
+++ b/external/buildscripts/buildDependencies.txt
@@ -0,0 +1,60 @@
+# Dependencoes to pull down from Stevedore. Please follow the following format:
+# name : <stevedore artifact name>
+# id : <stevedore artifact id>
+# repo : <stevedore repo name (can be testing/public/unityinternal)>
+
+name : 7z
+id: 7z/9df1e3b3b120_12ed325f6a47f0e5cebc247dbe9282a5da280d392cce4e6c9ed227d57ff1e2ff.7z
+repo: testing
+
+name : libgdiplus
+id : libgdiplus/9df1e3b3b120_4cf7c08770db93922f54f38d2461b9122cddc898db58585864446e70c5ad3057.7z
+repo: testing
+
+name : MacBuildEnvironment
+id : MacBuildEnvironment/9df1e3b3b120_2fc8e616a2e5dfb7907fc42d9576b427e692223c266dc3bc305de4bf03714e30.7z
+repo: testing
+
+name : mono
+id : mono/9df1e3b3b120_f81c172b91f45b2e045f4ba52d5f65cc54041da1527f2c854bf9db3a99495007.7z
+repo: testing
+
+name : MonoBleedingEdge
+id : MonoBleedingEdge/9df1e3b3b120_ab6d2f131e6bd4fe2aacafb0f683e8fa4e1ccba35552b6fe89bf359b6ee16215.7z
+repo: testing
+
+name : reference-assemblies
+id : reference-assemblies/9df1e3b3b120_bbb4750c6bf0a1784bec7d7c04b8ef5881f31f6212136e014694f3864a388886.7z
+repo: testing
+
+name : linux-sdk-20170609
+id : linux-sdk-20170609/9df1e3b3b120_9a3a0847d5b3767579e908b5a9ce050936617b1b9275a79a8b71bb3229998957.7z
+repo: testing
+
+name : libtool-src
+id : libtool-src/2.4.6_49a0ed204b3b24572e044400cd05513f611bcca6ced0d0816a57ac3b17376257.7z
+repo: public
+
+name : texinfo-src
+id : texinfo-src/4.8_975b9657ebef8a4fe3897047ca450b757a0a956b05399dc813f63e84829bac6a.7z
+repo: public
+
+name : automake-src
+id : automake-src/1.15_de1f60706336df404881d3c789d8e04f0bc50e6bf577d78cae438b089b02d8ed.7z
+repo: public
+
+name : autoconf-src
+id : autoconf-src/2.69_0e4ba7a0363c68ad08a7d138b228596aecdaea68e1d8b8eefc645e6ac8fc85c7.7z
+repo: public
+
+name : android-ndk-r16b-darwin
+id : android-ndk-r16b-darwin/9df1e3b3b120_c7cda5a221dd72799b7e618597b3f8766df7183d386becb2785631c2d3ac0d75.7z
+repo: testing
+
+name : android-ndk-r16b-linux
+id : android-ndk-r16b-linux/9df1e3b3b120_fbabd18208d82cbc810266e8b566bb0ea4e1e438de38d450a92deaa3e23757b6.7z
+repo: testing
+
+name : android-ndk-r16b-windows
+id : android-ndk-r16b-windows/9df1e3b3b120_403e0d58eabae03f0d9e8d1d2cea2dbf1d14c380c3d1c7eeb6e8c60ffc15e1b8.7z
+repo: testing
\ No newline at end of file
diff --git a/external/buildscripts/build_all_linux.pl b/external/buildscripts/build_all_linux.pl
new file mode 100644
index 00000000000..a975f5e7b66
--- /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 00000000000..130a5592eb7
--- /dev/null
+++ b/external/buildscripts/build_all_osx.pl
@@ -0,0 +1,163 @@
+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");
+ }
+
+ for my $file ('libmonobdwgc-2.0.dylib','libmonosgen-2.0.dylib','libMonoPosixHelper.dylib')
+ {
+ print(">>> cp $embedDirSource64/$file $embedDirDestination/$file\n\n");
+ system ('cp', "$embedDirSource64/$file", "$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");
+ }
+
+ for my $file ('libMonoPosixHelper.dylib')
+ {
+ print(">>> cp $embedDirSource64/$file $distDirDestinationLib/$file\n\n");
+ system ('cp', "$embedDirSource64/$file", "$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 00000000000..65e099b4bec
--- /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 00000000000..b9dbb94dddf
--- /dev/null
+++ b/external/buildscripts/build_classlibs_osx.pl
@@ -0,0 +1,43 @@
+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;
+my $stevedoreBuildDeps=1;
+
+# 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,
+ 'stevedorebuilddeps=i'=>\$stevedoreBuildDeps,
+) 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",
+ "--stevedorebuilddeps=$stevedoreBuildDeps",
+ "--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 00000000000..9d65f1b7e2b
--- /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 00000000000..a8d2cde8ec2
--- /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 00000000000..8095de7d714
--- /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 00000000000..c81c9204b0b
--- /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;
+my $stevedoreBuildDeps = 1;
+
+GetOptions(
+ "androidarch=s"=>\$androidArch,
+ "clean=i"=>\$clean,
+ "windowssubsystemforlinux=i"=>\$windowsSubsystemForLinux,
+ "stevedorebuilddeps=i"=>\$stevedoreBuildDeps,
+) 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=armv7a", "--forcedefaultbuilddeps=1", "--windowssubsystemforlinux=$windowsSubsystemForLinux", "--stevedorebuilddeps=$stevedoreBuildDeps") 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", "--stevedorebuilddeps=$stevedoreBuildDeps") 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", "--stevedorebuilddeps=$stevedoreBuildDeps") 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 00000000000..2916d73d5e6
--- /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 00000000000..0c4b5bce456
--- /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 00000000000..21452053675
--- /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 00000000000..e52e4fb1e17
--- /dev/null
+++ b/external/buildscripts/build_runtime_linux.pl
@@ -0,0 +1,24 @@
+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 $stevedoreBuildDeps = 1;
+my $build64 = 0;
+
+GetOptions(
+ "build64=i"=>\$build64,
+ "stevedorebuilddeps=i"=>\$stevedoreBuildDeps,
+) 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", "--stevedorebuilddeps=$stevedoreBuildDeps") 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 00000000000..ccf3ff98e48
--- /dev/null
+++ b/external/buildscripts/build_runtime_osx.pl
@@ -0,0 +1,16 @@
+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 $stevedoreBuildDeps=1;
+
+GetOptions(
+ 'stevedorebuilddeps=i'=>\$stevedoreBuildDeps,
+) or die ("illegal cmdline options");
+
+system("perl", "$buildScriptsRoot/build_all_osx.pl", "--build=1", "--artifact=1", "--test=1", "--forcedefaultbuilddeps=1", "--stevedorebuilddeps=$stevedoreBuildDeps") 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 00000000000..b2eaaf63a0a
--- /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 00000000000..4d8fb005059
--- /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.sh b/external/buildscripts/build_runtime_tizen.sh
new file mode 100644
index 00000000000..f7bc324230e
--- /dev/null
+++ b/external/buildscripts/build_runtime_tizen.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 : Tizen support is removed. 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_tizen.txt
+
diff --git a/external/buildscripts/build_runtime_vs.pl b/external/buildscripts/build_runtime_vs.pl
new file mode 100644
index 00000000000..5460b34408b
--- /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 00000000000..9988dcd7a93
--- /dev/null
+++ b/external/buildscripts/build_runtime_win.pl
@@ -0,0 +1,19 @@
+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 $stevedoreBuildDeps = 1;
+
+GetOptions(
+ "stevedorebuilddeps=i"=>\$stevedoreBuildDeps,
+) or die ("illegal cmdline options");
+
+# 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", "--stevedorebuilddeps=$stevedoreBuildDeps") 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", "--stevedorebuilddeps=$stevedoreBuildDeps") 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 00000000000..72ee81c780b
--- /dev/null
+++ b/external/buildscripts/build_runtime_win64.pl
@@ -0,0 +1,20 @@
+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 $stevedoreBuildDeps = 1;
+
+GetOptions(
+ "stevedorebuilddeps=i"=>\$stevedoreBuildDeps,
+) or die ("illegal cmdline options");
+
+# 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", "--stevedorebuilddeps=$stevedoreBuildDeps") 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", "--stevedorebuilddeps=$stevedoreBuildDeps") 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 00000000000..ba8169be68e
--- /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 00000000000..af3d9a3e6d2
--- /dev/null
+++ b/external/buildscripts/build_unityscript_bareminimum_win.pl
@@ -0,0 +1,154 @@
+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
+{
+ 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");
+
+ 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 00000000000..66523d3c2e0
--- /dev/null
+++ b/external/buildscripts/build_us_and_boo.pl
@@ -0,0 +1,151 @@
+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");
+
+ 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 (!(-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 00000000000..f87fef338ef
--- /dev/null
+++ b/external/buildscripts/build_win_no_cygwin.pl
@@ -0,0 +1,242 @@
+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 = "";
+my $stevedoreBuildDeps=1;
+
+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,
+ 'stevedorebuilddeps=i'=>\$stevedoreBuildDeps,
+) 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
+{
+ if($stevedoreBuildDeps)
+ {
+ $externalBuildDeps = "$monoroot/external/buildscripts/artifacts/Stevedore";
+ }
+ else
+ {
+ $externalBuildDeps = "$monoroot/../../mono-build-deps/build";
+ }
+}
+print(">>> External build deps = $externalBuildDeps\n");
+
+my $existingExternalMonoRoot = "$externalBuildDeps\\mono";
+my $existingExternalMono = "$existingExternalMonoRoot\\win";
+
+if ($clean)
+{
+ print(">>> Cleaning $monoprefix\n");
+ rmtree($monoprefix);
+}
+
+# ******************* Build Stage **************************
+
+if ($build)
+{
+ if (!(-d "$externalBuildDeps"))
+ {
+ print(">>> mono-build-deps is not required for windows runtime builds...\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 00000000000..1b40fc71af1
--- /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=<path>\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=<path> 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 00000000000..c71964f8798
--- /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 00000000000..abf19dbbabe
--- /dev/null
+++ b/external/buildscripts/collect_allbuilds.pl
@@ -0,0 +1,80 @@
+use lib ('external/buildscripts/perl_lib');
+use Cwd 'abs_path';
+use File::Basename;
+use File::Copy::Recursive qw(dircopy rmove);
+use File::Path;
+use Tools qw(InstallNameTool);
+
+
+my $monoroot = File::Spec->rel2abs(dirname(__FILE__) . "/../..");
+my $monoroot = abs_path($monoroot);
+
+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");
+
+my $externalzip = "";
+if($^O eq "linux")
+{
+ $externalzip = "$monoroot/../../mono-build-deps/build/7z/linux64/7za";
+}
+elsif($^O eq 'darwin')
+{
+ $externalzip = "$monoroot/../../mono-build-deps/build/7z/osx/7za";
+}
+
+if($^O eq "linux" || $^O eq 'darwin')
+{
+ if(-f $externalzip)
+ {
+ system("$externalzip a builds.7z * -x!builds.zip") eq 0 or die("failed 7z up builds");
+ }
+ else
+ {
+ #Use 7z installed on the machine. If its not installed, please install it.
+ system("7z a builds.7z * -x!builds.zip") eq 0 or die("failed 7z up builds");
+ }
+}
+else
+{
+ die("Unsupported platform for build collection.")
+}
+
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 00000000000..c5fb2576f8d
--- /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<File::Copy> L<File::Spec>
+
+=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<http://drmuey.com/cpan_contact.pl>
+
+=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 00000000000..8b2d7a6a7e2
--- /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/stub_classlibs.pl b/external/buildscripts/stub_classlibs.pl
new file mode 100644
index 00000000000..83192f3cb1f
--- /dev/null
+++ b/external/buildscripts/stub_classlibs.pl
@@ -0,0 +1,52 @@
+use Cwd;
+use Cwd 'abs_path';
+use File::Basename;
+use File::Path;
+
+if($^O ne "darwin")
+{
+ print ">>> The ProfileStubber is only built and run in the class library build on macOS\n";
+ exit
+}
+
+my $monoroot = File::Spec->rel2abs(dirname(__FILE__) . "/../..");
+my $monoroot = abs_path($monoroot);
+my $extraBuildTools = "$monoroot/../../mono-build-tools-extra/build";
+
+print ">>> Building the ProfileStubber utility\n";
+
+my $result = system("xbuild",
+ "$extraBuildTools/mono-build-tools-extra.sln",
+ "/p:Configuration=Release");
+
+if ($result ne 0)
+{
+ die("Failed to build ProfileStubber utility\n");
+}
+
+my $profileRoot = "tmp/lib/mono";
+my $referenceProfile = "$profileRoot/4.7.1-api";
+
+print ">>> Modifying the unityjit profile to match the .NET 4.7.1 API\n";
+
+$result = system("mono",
+ "$extraBuildTools/build/ProfileStubber.exe",
+ "--reference-profile=$referenceProfile",
+ "--stub-profile=$profileRoot/unityjit");
+
+if ($result ne 0)
+{
+ die("Failed to stub the unityjit profile\n");
+}
+
+print ">>> Modifying the unityaot profile to match the .NET 4.7.1 API\n";
+
+$result = system("mono",
+ "$extraBuildTools/build/ProfileStubber.exe",
+ "--reference-profile=$referenceProfile",
+ "--stub-profile=$profileRoot/unityaot");
+
+if ($result ne 0)
+{
+ die("Failed to stub the unityaot profile\n");
+}
diff --git a/external/buildscripts/test-driver b/external/buildscripts/test-driver
new file mode 100644
index 00000000000..8a05be09ec4
--- /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 = <F>;
+ close(F);
+ return $out;
+}
diff --git a/external/corefx-bugfix/src/Common/src/System/Collections/Generic/LargeArrayBuilder.cs b/external/corefx-bugfix/src/Common/src/System/Collections/Generic/LargeArrayBuilder.cs
new file mode 100644
index 00000000000..80c9a1734f1
--- /dev/null
+++ b/external/corefx-bugfix/src/Common/src/System/Collections/Generic/LargeArrayBuilder.cs
@@ -0,0 +1,390 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Diagnostics;
+using System.Runtime.CompilerServices;
+
+namespace System.Collections.Generic
+{
+ /// <summary>
+ /// Represents a position within a <see cref="LargeArrayBuilder{T}"/>.
+ /// </summary>
+ [DebuggerDisplay("{DebuggerDisplay,nq}")]
+ internal struct CopyPosition
+ {
+ /// <summary>
+ /// Constructs a new <see cref="CopyPosition"/>.
+ /// </summary>
+ /// <param name="row">The index of the buffer to select.</param>
+ /// <param name="column">The index within the buffer to select.</param>
+ internal CopyPosition(int row, int column)
+ {
+ Debug.Assert(row >= 0);
+ Debug.Assert(column >= 0);
+
+ Row = row;
+ Column = column;
+ }
+
+ /// <summary>
+ /// Represents a position at the start of a <see cref="LargeArrayBuilder{T}"/>.
+ /// </summary>
+ public static CopyPosition Start => default(CopyPosition);
+
+ /// <summary>
+ /// The index of the buffer to select.
+ /// </summary>
+ internal int Row { get; }
+
+ /// <summary>
+ /// The index within the buffer to select.
+ /// </summary>
+ internal int Column { get; }
+
+ /// <summary>
+ /// If this position is at the end of the current buffer, returns the position
+ /// at the start of the next buffer. Otherwise, returns this position.
+ /// </summary>
+ /// <param name="endColumn">The length of the current buffer.</param>
+ public CopyPosition Normalize(int endColumn)
+ {
+ Debug.Assert(Column <= endColumn);
+
+ return Column == endColumn ?
+ new CopyPosition(Row + 1, 0) :
+ this;
+ }
+
+ /// <summary>
+ /// Gets a string suitable for display in the debugger.
+ /// </summary>
+ private string DebuggerDisplay => $"[{Row}, {Column}]";
+ }
+
+ /// <summary>
+ /// Helper type for building dynamically-sized arrays while minimizing allocations and copying.
+ /// </summary>
+ /// <typeparam name="T">The element type.</typeparam>
+ internal struct LargeArrayBuilder<T>
+ {
+ private const int StartingCapacity = 4;
+ private const int ResizeLimit = 8;
+
+ private readonly int _maxCapacity; // The maximum capacity this builder can have.
+ private T[] _first; // The first buffer we store items in. Resized until ResizeLimit.
+ private ArrayBuilder<T[]> _buffers; // After ResizeLimit * 2, we store previous buffers we've filled out here.
+ private T[] _current; // Current buffer we're reading into. If _count <= ResizeLimit, this is _first.
+ private int _index; // Index into the current buffer.
+ private int _count; // Count of all of the items in this builder.
+
+ /// <summary>
+ /// Constructs a new builder.
+ /// </summary>
+ /// <param name="initialize">Pass <c>true</c>.</param>
+ public LargeArrayBuilder(bool initialize)
+ : this(maxCapacity: int.MaxValue)
+ {
+ // This is a workaround for C# not having parameterless struct constructors yet.
+ // Once it gets them, replace this with a parameterless constructor.
+ Debug.Assert(initialize);
+ }
+
+ /// <summary>
+ /// Constructs a new builder with the specified maximum capacity.
+ /// </summary>
+ /// <param name="maxCapacity">The maximum capacity this builder can have.</param>
+ /// <remarks>
+ /// Do not add more than <paramref name="maxCapacity"/> items to this builder.
+ /// </remarks>
+ public LargeArrayBuilder(int maxCapacity)
+ : this()
+ {
+ Debug.Assert(maxCapacity >= 0);
+
+ _first = _current = Array.Empty<T>();
+ _maxCapacity = maxCapacity;
+ }
+
+ /// <summary>
+ /// Gets the number of items added to the builder.
+ /// </summary>
+ public int Count => _count;
+
+ /// <summary>
+ /// Adds an item to this builder.
+ /// </summary>
+ /// <param name="item">The item to add.</param>
+ /// <remarks>
+ /// Use <see cref="Add"/> if adding to the builder is a bottleneck for your use case.
+ /// Otherwise, use <see cref="SlowAdd"/>.
+ /// </remarks>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public void Add(T item)
+ {
+ Debug.Assert(_maxCapacity > _count);
+
+ if (_index == _current.Length)
+ {
+ AllocateBuffer();
+ }
+
+ _current[_index++] = item;
+ _count++;
+ }
+
+ /// <summary>
+ /// Adds a range of items to this builder.
+ /// </summary>
+ /// <param name="items">The sequence to add.</param>
+ /// <remarks>
+ /// It is the caller's responsibility to ensure that adding <paramref name="items"/>
+ /// does not cause the builder to exceed its maximum capacity.
+ /// </remarks>
+ public void AddRange(IEnumerable<T> items)
+ {
+ Debug.Assert(items != null);
+
+ using (IEnumerator<T> enumerator = items.GetEnumerator())
+ {
+ T[] destination = _current;
+ int index = _index;
+
+ // Continuously read in items from the enumerator, updating _count
+ // and _index when we run out of space.
+
+ while (enumerator.MoveNext())
+ {
+ if (index == destination.Length)
+ {
+ // No more space in this buffer. Resize.
+ _count += index - _index;
+ _index = index;
+ AllocateBuffer();
+ destination = _current;
+ index = _index; // May have been reset to 0
+ }
+
+ destination[index++] = enumerator.Current;
+ }
+
+ // Final update to _count and _index.
+ _count += index - _index;
+ _index = index;
+ }
+ }
+
+ /// <summary>
+ /// Copies the contents of this builder to the specified array.
+ /// </summary>
+ /// <param name="array">The destination array.</param>
+ /// <param name="arrayIndex">The index in <see cref="array"/> to start copying to.</param>
+ /// <param name="count">The number of items to copy.</param>
+ public void CopyTo(T[] array, int arrayIndex, int count)
+ {
+ Debug.Assert(arrayIndex >= 0);
+ Debug.Assert(count >= 0 && count <= Count);
+ Debug.Assert(array?.Length - arrayIndex >= count);
+
+ for (int i = 0; count > 0; i++)
+ {
+ // Find the buffer we're copying from.
+ T[] buffer = GetBuffer(index: i);
+
+ // Copy until we satisfy count, or we reach the end of the buffer.
+ int toCopy = Math.Min(count, buffer.Length);
+ Array.Copy(buffer, 0, array, arrayIndex, toCopy);
+
+ // Increment variables to that position.
+ count -= toCopy;
+ arrayIndex += toCopy;
+ }
+ }
+
+ /// <summary>
+ /// Copies the contents of this builder to the specified array.
+ /// </summary>
+ /// <param name="position">The position in this builder to start copying from.</param>
+ /// <param name="array">The destination array.</param>
+ /// <param name="arrayIndex">The index in <see cref="array"/> to start copying to.</param>
+ /// <param name="count">The number of items to copy.</param>
+ /// <returns>The position in this builder that was copied up to.</returns>
+ public CopyPosition CopyTo(CopyPosition position, T[] array, int arrayIndex, int count)
+ {
+ Debug.Assert(array != null);
+ Debug.Assert(arrayIndex >= 0);
+ Debug.Assert(count > 0 && count <= Count);
+ Debug.Assert(array.Length - arrayIndex >= count);
+
+ // Go through each buffer, which contains one 'row' of items.
+ // The index in each buffer is referred to as the 'column'.
+
+ /*
+ * Visual representation:
+ *
+ * C0 C1 C2 .. C31 .. C63
+ * R0: [0] [1] [2] .. [31]
+ * R1: [32] [33] [34] .. [63]
+ * R2: [64] [65] [66] .. [95] .. [127]
+ */
+
+ int row = position.Row;
+ int column = position.Column;
+
+ T[] buffer = GetBuffer(row);
+ int copied =
+#if __MonoCS__
+ CopyToCore(buffer, column, array, arrayIndex, count);
+#else
+ CopyToCore(buffer, column);
+#endif
+
+ if (count == 0)
+ {
+ return new CopyPosition(row, column + copied).Normalize(buffer.Length);
+ }
+
+ do
+ {
+ buffer = GetBuffer(++row);
+ copied =
+#if __MonoCS__
+ CopyToCore(buffer, 0, array, arrayIndex, count);
+#else
+ CopyToCore(buffer, 0);
+#endif
+ } while (count > 0);
+
+ return new CopyPosition(row, copied).Normalize(buffer.Length);
+
+#if __MonoCS__
+ }
+
+ static int CopyToCore(T[] sourceBuffer, int sourceIndex, T[] array, int arrayIndex, int count)
+#else
+ int CopyToCore(T[] sourceBuffer, int sourceIndex)
+#endif
+ {
+ Debug.Assert(sourceBuffer.Length > sourceIndex);
+
+ // Copy until we satisfy `count` or reach the end of the current buffer.
+ int copyCount = Math.Min(sourceBuffer.Length - sourceIndex, count);
+ Array.Copy(sourceBuffer, sourceIndex, array, arrayIndex, copyCount);
+
+ arrayIndex += copyCount;
+ count -= copyCount;
+
+ return copyCount;
+ }
+
+#if !__MonoCS__
+ }
+#endif
+
+ /// <summary>
+ /// Retrieves the buffer at the specified index.
+ /// </summary>
+ /// <param name="index">The index of the buffer.</param>
+ public T[] GetBuffer(int index)
+ {
+ Debug.Assert(index >= 0 && index < _buffers.Count + 2);
+
+ return index == 0 ? _first :
+ index <= _buffers.Count ? _buffers[index - 1] :
+ _current;
+ }
+
+ /// <summary>
+ /// Adds an item to this builder.
+ /// </summary>
+ /// <param name="item">The item to add.</param>
+ /// <remarks>
+ /// Use <see cref="Add"/> if adding to the builder is a bottleneck for your use case.
+ /// Otherwise, use <see cref="SlowAdd"/>.
+ /// </remarks>
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ public void SlowAdd(T item) => Add(item);
+
+ /// <summary>
+ /// Creates an array from the contents of this builder.
+ /// </summary>
+ public T[] ToArray()
+ {
+ if (TryMove(out T[] array))
+ {
+ // No resizing to do.
+ return array;
+ }
+
+ array = new T[_count];
+ CopyTo(array, 0, _count);
+ return array;
+ }
+
+ /// <summary>
+ /// Attempts to transfer this builder into an array without copying.
+ /// </summary>
+ /// <param name="array">The transferred array, if the operation succeeded.</param>
+ /// <returns><c>true</c> if the operation succeeded; otherwise, <c>false</c>.</returns>
+ public bool TryMove(out T[] array)
+ {
+ array = _first;
+ return _count == _first.Length;
+ }
+
+ private void AllocateBuffer()
+ {
+ // - On the first few adds, simply resize _first.
+ // - When we pass ResizeLimit, allocate ResizeLimit elements for _current
+ // and start reading into _current. Set _index to 0.
+ // - When _current runs out of space, add it to _buffers and repeat the
+ // above step, except with _current.Length * 2.
+ // - Make sure we never pass _maxCapacity in all of the above steps.
+
+ Debug.Assert((uint)_maxCapacity > (uint)_count);
+ Debug.Assert(_index == _current.Length, $"{nameof(AllocateBuffer)} was called, but there's more space.");
+
+ // If _count is int.MinValue, we want to go down the other path which will raise an exception.
+ if ((uint)_count < (uint)ResizeLimit)
+ {
+ // We haven't passed ResizeLimit. Resize _first, copying over the previous items.
+ Debug.Assert(_current == _first && _count == _first.Length);
+
+ int nextCapacity = Math.Min(_count == 0 ? StartingCapacity : _count * 2, _maxCapacity);
+
+ _current = new T[nextCapacity];
+ Array.Copy(_first, 0, _current, 0, _count);
+ _first = _current;
+ }
+ else
+ {
+ Debug.Assert(_maxCapacity > ResizeLimit);
+ Debug.Assert(_count == ResizeLimit ^ _current != _first);
+
+ int nextCapacity;
+ if (_count == ResizeLimit)
+ {
+ nextCapacity = ResizeLimit;
+ }
+ else
+ {
+ // Example scenario: Let's say _count == 64.
+ // Then our buffers look like this: | 8 | 8 | 16 | 32 |
+ // As you can see, our count will be just double the last buffer.
+ // Now, say _maxCapacity is 100. We will find the right amount to allocate by
+ // doing min(64, 100 - 64). The lhs represents double the last buffer,
+ // the rhs the limit minus the amount we've already allocated.
+
+ Debug.Assert(_count >= ResizeLimit * 2);
+ Debug.Assert(_count == _current.Length * 2);
+
+ _buffers.Add(_current);
+ nextCapacity = Math.Min(_count, _maxCapacity - _count);
+ }
+
+ _current = new T[nextCapacity];
+ _index = 0;
+ }
+ }
+ }
+}
diff --git a/mcs/Makefile b/mcs/Makefile
index 59db5e77267..87e5ace2c96 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 8bb64bc43a7..a6cdfdd1961 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 5463812acc6..a7cc2e81dc1 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 00000000000..9b69620953c
--- /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 00000000000..b943ecf40f9
--- /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 036ec852fa5..174df4af8ee 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 00000000000..19cd3907a86
--- /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 00000000000..f730763a925
--- /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 00000000000..719628dc7c6
--- /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 00000000000..b8c87d21f33
--- /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 00000000000..fe58b174b95
--- /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 00000000000..b16ae43ee30
--- /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 00000000000..8e33d4ddeae
--- /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 00000000000..310362270c7
--- /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 00000000000..71222db9e31
--- /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 00000000000..f2f622eb1bf
--- /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 00000000000..8e33d4ddeae
--- /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 00000000000..e82cdb0ad50
--- /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/System.Runtime.Serialization.Primitives/System.Runtime.Serialization.Primitives.dll.sources b/mcs/class/Facades/System.Runtime.Serialization.Primitives/System.Runtime.Serialization.Primitives.dll.sources
index fd4c99b18ad..719628dc7c6 100644
--- a/mcs/class/Facades/System.Runtime.Serialization.Primitives/System.Runtime.Serialization.Primitives.dll.sources
+++ b/mcs/class/Facades/System.Runtime.Serialization.Primitives/System.Runtime.Serialization.Primitives.dll.sources
@@ -1,4 +1,2 @@
TypeForwarders.cs
AssemblyInfo.cs
-
-../../../../external/corefx/src/System.Runtime.Serialization.Primitives/src/System/Runtime/Serialization/ISerializationSurrogateProvider.cs
diff --git a/mcs/class/Facades/System.Runtime.Serialization.Primitives/TypeForwarders.cs b/mcs/class/Facades/System.Runtime.Serialization.Primitives/TypeForwarders.cs
index ea71c80449c..8768234c08d 100644
--- a/mcs/class/Facades/System.Runtime.Serialization.Primitives/TypeForwarders.cs
+++ b/mcs/class/Facades/System.Runtime.Serialization.Primitives/TypeForwarders.cs
@@ -30,6 +30,7 @@
[assembly: System.Runtime.CompilerServices.TypeForwardedToAttribute(typeof(System.Runtime.Serialization.IExtensibleDataObject))]
[assembly: System.Runtime.CompilerServices.TypeForwardedToAttribute(typeof(System.Runtime.Serialization.IgnoreDataMemberAttribute))]
[assembly: System.Runtime.CompilerServices.TypeForwardedToAttribute(typeof(System.Runtime.Serialization.InvalidDataContractException))]
+[assembly: System.Runtime.CompilerServices.TypeForwardedToAttribute(typeof(System.Runtime.Serialization.ISerializationSurrogateProvider))]
[assembly: System.Runtime.CompilerServices.TypeForwardedToAttribute(typeof(System.Runtime.Serialization.KnownTypeAttribute))]
[assembly: System.Runtime.CompilerServices.TypeForwardedToAttribute(typeof(System.Runtime.Serialization.OnDeserializedAttribute))]
[assembly: System.Runtime.CompilerServices.TypeForwardedToAttribute(typeof(System.Runtime.Serialization.OnDeserializingAttribute))]
diff --git a/mcs/class/Facades/System.Security.Cryptography.Algorithms/System.Security.Cryptography.Algorithms.dll.sources b/mcs/class/Facades/System.Security.Cryptography.Algorithms/System.Security.Cryptography.Algorithms.dll.sources
index bc50224ae2c..a2f4cd1a9d7 100644
--- a/mcs/class/Facades/System.Security.Cryptography.Algorithms/System.Security.Cryptography.Algorithms.dll.sources
+++ b/mcs/class/Facades/System.Security.Cryptography.Algorithms/System.Security.Cryptography.Algorithms.dll.sources
@@ -1,4 +1,3 @@
TypeForwarders.cs
AssemblyInfo.cs
SR.cs
-../../../../external/corefx/src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/IncrementalHash.net46.cs
diff --git a/mcs/class/Facades/System.Security.Cryptography.Algorithms/TypeForwarders.cs b/mcs/class/Facades/System.Security.Cryptography.Algorithms/TypeForwarders.cs
index 2a7c09f4714..10ded3bedd9 100644
--- a/mcs/class/Facades/System.Security.Cryptography.Algorithms/TypeForwarders.cs
+++ b/mcs/class/Facades/System.Security.Cryptography.Algorithms/TypeForwarders.cs
@@ -43,6 +43,7 @@
[assembly: System.Runtime.CompilerServices.TypeForwardedToAttribute(typeof(System.Security.Cryptography.HMACSHA256))]
[assembly: System.Runtime.CompilerServices.TypeForwardedToAttribute(typeof(System.Security.Cryptography.HMACSHA384))]
[assembly: System.Runtime.CompilerServices.TypeForwardedToAttribute(typeof(System.Security.Cryptography.HMACSHA512))]
+[assembly: System.Runtime.CompilerServices.TypeForwardedToAttribute(typeof(System.Security.Cryptography.IncrementalHash))]
[assembly: System.Runtime.CompilerServices.TypeForwardedToAttribute(typeof(System.Security.Cryptography.MaskGenerationMethod))]
[assembly: System.Runtime.CompilerServices.TypeForwardedToAttribute(typeof(System.Security.Cryptography.MD5))]
[assembly: System.Runtime.CompilerServices.TypeForwardedToAttribute(typeof(System.Security.Cryptography.PKCS1MaskGenerationMethod))]
diff --git a/mcs/class/Facades/System.Security.SecureString/System.Security.SecureString.dll.sources b/mcs/class/Facades/System.Security.SecureString/System.Security.SecureString.dll.sources
index d12a84b6abd..719628dc7c6 100644
--- a/mcs/class/Facades/System.Security.SecureString/System.Security.SecureString.dll.sources
+++ b/mcs/class/Facades/System.Security.SecureString/System.Security.SecureString.dll.sources
@@ -1,3 +1,2 @@
TypeForwarders.cs
AssemblyInfo.cs
-../../../../external/corefx/src/System.Runtime.InteropServices/src/System/Security/SecureStringMarshal.cs
diff --git a/mcs/class/Facades/System.Security.SecureString/TypeForwarders.cs b/mcs/class/Facades/System.Security.SecureString/TypeForwarders.cs
index 4267f40e03b..e34303ce194 100644
--- a/mcs/class/Facades/System.Security.SecureString/TypeForwarders.cs
+++ b/mcs/class/Facades/System.Security.SecureString/TypeForwarders.cs
@@ -21,3 +21,4 @@
//
[assembly: System.Runtime.CompilerServices.TypeForwardedToAttribute(typeof(System.Security.SecureString))]
+[assembly: System.Runtime.CompilerServices.TypeForwardedToAttribute(typeof(System.Security.SecureStringMarshal))]
diff --git a/mcs/class/Facades/netstandard/Makefile b/mcs/class/Facades/netstandard/Makefile
index b9974695d6d..e6487dc44d1 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 99251693127..3901ea16eeb 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 13d7aae2873..03fc35fe3be 100644
--- a/mcs/class/Makefile
+++ b/mcs/class/Makefile
@@ -342,6 +342,29 @@ net_4_x_parallel_dirs := \
legacy/Mono.Cecil \
$(pcl_facade_dirs)
+unityjit_dirs := \
+ $(net_4_x_dirs) \
+ System.ComponentModel.Composition.4.5 \
+ System.Data.DataSetExtensions \
+ 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 \
+ System.Data.DataSetExtensions \
+ $(pcl_facade_dirs)
+
xbuild_2_0_dirs := \
Microsoft.Build.Framework \
Microsoft.Build.Utilities \
@@ -376,13 +399,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 602c827091d..e480555252e 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 @@ namespace Mono.Debugger.Soft
* 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 @@ namespace Mono.Debugger.Soft
TYPE = 23,
MODULE = 24,
FIELD = 25,
- EVENT = 64
+ EVENT = 64,
+ POINTER = 65
}
enum EventKind {
@@ -574,7 +575,8 @@ namespace Mono.Debugger.Soft
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 @@ namespace Mono.Debugger.Soft
GET_CHARS = 3
}
+ enum CmdPointer {
+ GET_VALUE = 1
+ }
+
enum CmdObjectRef {
GET_TYPE = 1,
GET_VALUES = 2,
@@ -730,10 +736,12 @@ namespace Mono.Debugger.Soft
}
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 @@ namespace Mono.Debugger.Soft
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 @@ namespace Mono.Debugger.Soft
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 @@ namespace Mono.Debugger.Soft
if (EnableConnectionLogging)
LogPacket (packet_id, encoded_packet, p, command_set, command, watch);
/* Run the callback on a tp thread to avoid blocking the receive thread */
- PacketReader r = new PacketReader (p);
+ PacketReader r = new PacketReader (this, p);
cb.BeginInvoke (r, null, null);
};
reply_cb_counts [id] = count;
@@ -1549,7 +1564,7 @@ namespace Mono.Debugger.Soft
if (reply_packets.ContainsKey (packetId)) {
byte[] reply = reply_packets [packetId];
reply_packets.Remove (packetId);
- PacketReader r = new PacketReader (reply);
+ PacketReader r = new PacketReader (this, reply);
if (EnableConnectionLogging)
LogPacket (packetId, encoded_packet, reply, command_set, command, watch);
@@ -2297,6 +2312,11 @@ namespace Mono.Debugger.Soft
return r.ReadId ();
}
+ internal int Type_GetValueSize (long id) {
+ PacketReader r = SendReceive (CommandSet.TYPE, (int)CmdType.GET_VALUE_SIZE, new PacketWriter ().WriteId (id));
+ return r.ReadInt ();
+ }
+
/*
* FIELD
*/
@@ -2475,7 +2495,16 @@ namespace Mono.Debugger.Soft
for (int i = 0; i < length; ++i)
res [i] = (char)r.ReadShort ();
return res;
- }
+ }
+
+ /*
+ * POINTERS
+ */
+
+ internal ValueImpl Pointer_GetValue (long address, TypeMirror type)
+ {
+ return SendReceive (CommandSet.POINTER, (int)CmdPointer.GET_VALUE, new PacketWriter ().WriteLong (address).WriteId (type.Id)).ReadValue ();
+ }
/*
* OBJECTS
diff --git a/mcs/class/Mono.Debugger.Soft/Mono.Debugger.Soft/PointerValue.cs b/mcs/class/Mono.Debugger.Soft/Mono.Debugger.Soft/PointerValue.cs
index 3fa359fcb5d..2cf9dfa418b 100644
--- a/mcs/class/Mono.Debugger.Soft/Mono.Debugger.Soft/PointerValue.cs
+++ b/mcs/class/Mono.Debugger.Soft/Mono.Debugger.Soft/PointerValue.cs
@@ -48,6 +48,16 @@ namespace Mono.Debugger.Soft
get { return type; }
}
+ // Since protocol version 2.46
+ public Value Value {
+ get {
+ if (Address == 0)
+ return null;
+
+ return vm.DecodeValue (vm.conn.Pointer_GetValue (Address, Type));
+ }
+ }
+
public override bool Equals (object obj) {
if (obj != null && obj is PointerValue)
return addr == (obj as PointerValue).addr;
diff --git a/mcs/class/Mono.Debugger.Soft/Mono.Debugger.Soft/TypeMirror.cs b/mcs/class/Mono.Debugger.Soft/Mono.Debugger.Soft/TypeMirror.cs
index f92dca03932..78c11a8d9af 100644
--- a/mcs/class/Mono.Debugger.Soft/Mono.Debugger.Soft/TypeMirror.cs
+++ b/mcs/class/Mono.Debugger.Soft/Mono.Debugger.Soft/TypeMirror.cs
@@ -842,6 +842,11 @@ namespace Mono.Debugger.Soft
return vm.GetObject (vm.conn.Type_CreateInstance (id));
}
+ // Since protocol version 2.46
+ public int GetValueSize () {
+ return vm.conn.Type_GetValueSize (id);
+ }
+
// Since protocol version 2.11
public TypeMirror[] GetInterfaces () {
if (ifaces == null)
diff --git a/mcs/class/Mono.Debugger.Soft/Mono.Debugger.Soft/VirtualMachine.cs b/mcs/class/Mono.Debugger.Soft/Mono.Debugger.Soft/VirtualMachine.cs
index 1eaaac8ec9d..9d60855a31a 100644
--- a/mcs/class/Mono.Debugger.Soft/Mono.Debugger.Soft/VirtualMachine.cs
+++ b/mcs/class/Mono.Debugger.Soft/Mono.Debugger.Soft/VirtualMachine.cs
@@ -616,8 +616,11 @@ namespace Mono.Debugger.Soft
}
internal Value DecodeValue (ValueImpl v, Dictionary<int, Value> 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 @@ namespace Mono.Debugger.Soft
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 82efc79e51d..341c247d342 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 struct AStruct : ITest2 {
}
}
+
+public struct BlittableStruct {
+ public int i;
+ public double d;
+}
+
public class GClass<T> {
public T field;
public static T static_field;
@@ -343,6 +349,8 @@ public class Tests : TestsBase, ITest2
gc_suspend ();
set_ip ();
step_filters ();
+ pointers ();
+ ref_return ();
if (args.Length > 0 && args [0] == "local-reflect")
local_reflect ();
if (args.Length > 0 && args [0] == "domain-test")
@@ -1720,6 +1728,38 @@ public class Tests : TestsBase, ITest2
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);
+ }
+
+ [MethodImplAttribute (MethodImplOptions.NoInlining)]
+ public static void ref_return () {
+
+ }
+
+ static int ret_val = 1;
+ public static ref int get_ref_int() {
+ return ref ret_val;
+ }
+
+ static string ref_return_string = "byref";
+ public static ref string get_ref_string() {
+ return ref ref_return_string;
+ }
+
+ static BlittableStruct ref_return_struct = new BlittableStruct () { i = 1, d = 2.0 };
+ public static ref BlittableStruct get_ref_struct () {
+ return ref ref_return_struct;
+ }
}
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 ccd3b6b7602..0bb6328eccb 100644
--- a/mcs/class/Mono.Debugger.Soft/Test/dtest.cs
+++ b/mcs/class/Mono.Debugger.Soft/Test/dtest.cs
@@ -324,6 +324,8 @@ public class DebuggerTests
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,73 @@ public class DebuggerTests
}
}
-}
+ [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);
+
+ }
+
+ [Test]
+ public void InvokeGenericMethod () {
+ Event e = run_until ("bp1");
+ StackFrame frame = e.Thread.GetFrames()[0];
+ TypeMirror t = frame.Method.DeclaringType;
+ MethodMirror m;
+ m = t.GetMethod ("generic_method");
+ AssertThrows<ArgumentException> (delegate {
+ t.InvokeMethod (e.Thread, m, null);
+ });
+ }
+
+ [Test]
+ public void InvokeRefReturnMethod () {
+ Event e = run_until ("ref_return");
+ StackFrame frame = e.Thread.GetFrames()[0];
+ TypeMirror t = frame.Method.DeclaringType;
+ MethodMirror m;
+
+ m = t.GetMethod ("get_ref_int");
+ var v = t.InvokeMethod (e.Thread, m, null);
+ AssertValue (1, v);
-}
+ m = t.GetMethod ("get_ref_string");
+ v = t.InvokeMethod (e.Thread, m, null);
+ AssertValue ("byref", v);
+
+ m = t.GetMethod ("get_ref_struct");
+ v = t.InvokeMethod (e.Thread, m, null);
+ Assert.IsTrue(v is StructMirror);
+ var mirror = (StructMirror)v;
+ AssertValue (1, mirror["i"]);
+ AssertValue (2.0, mirror["d"]);
+ }
+} // 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 d60b71b1f5b..738342c76e8 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 @@ namespace System.IO.Pipes
#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/common_System.Core.dll.sources b/mcs/class/System.Core/common_System.Core.dll.sources
index cfe271aeee0..7a83de3eb8f 100644
--- a/mcs/class/System.Core/common_System.Core.dll.sources
+++ b/mcs/class/System.Core/common_System.Core.dll.sources
@@ -278,7 +278,7 @@ System.Security.Cryptography/SHA512CryptoServiceProvider.cs
../../../external/corefx/src/Common/src/System/Collections/Generic/ArrayBuilder.cs
../../../external/corefx/src/Common/src/System/Collections/Generic/EnumerableHelpers.cs
../../../external/corefx/src/Common/src/System/Collections/Generic/EnumerableHelpers.Linq.cs
-../../../external/corefx/src/Common/src/System/Collections/Generic/LargeArrayBuilder.cs
+../../../external/corefx-bugfix/src/Common/src/System/Collections/Generic/LargeArrayBuilder.cs
../../../external/corefx/src/Common/src/System/Collections/Generic/SparseArrayBuilder.cs
../../../external/corefx/src/System.Linq.Expressions/src/System/Dynamic/Utils/CacheDict.cs
@@ -289,3 +289,5 @@ System.Security.Cryptography/SHA512CryptoServiceProvider.cs
../../../external/corefx/src/System.Linq.Expressions/src/System/Linq/Expressions/Compiler/DelegateHelpers.cs
../../../external/corefx/src/System.Linq.Expressions/src/System/Linq/Expressions/Compiler/DelegateHelpers.Generated.cs
+
+../../../external/corefx/src/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/IncrementalHash.net46.cs
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 00000000000..7953f1b8f0e
--- /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 00000000000..5ec6fe90918
--- /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 00000000000..e5681ff8ff5
--- /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 00000000000..87d9b19fbf8
--- /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.Design/System.Web.UI.Design.WebControls/CompositeControlDesigner.cs b/mcs/class/System.Design/System.Web.UI.Design.WebControls/CompositeControlDesigner.cs
index 17997212533..8a13185c5ab 100644
--- a/mcs/class/System.Design/System.Web.UI.Design.WebControls/CompositeControlDesigner.cs
+++ b/mcs/class/System.Design/System.Web.UI.Design.WebControls/CompositeControlDesigner.cs
@@ -35,7 +35,7 @@ using System.ComponentModel;
namespace System.Web.UI.Design.WebControls
{
- class CompositeControlDesigner : ControlDesigner
+ public class CompositeControlDesigner : ControlDesigner
{
public CompositeControlDesigner () {
throw new NotImplementedException ();
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 00000000000..0403fdc41fc
--- /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 00000000000..429636751c2
--- /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 00000000000..7d312678c9c
--- /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/System.Runtime.Serialization.dll.sources b/mcs/class/System.Runtime.Serialization/System.Runtime.Serialization.dll.sources
index c1ebbd98153..bdc4b9adcc2 100644
--- a/mcs/class/System.Runtime.Serialization/System.Runtime.Serialization.dll.sources
+++ b/mcs/class/System.Runtime.Serialization/System.Runtime.Serialization.dll.sources
@@ -16,3 +16,5 @@ ReferenceSources/XmlDataContract_static.cs
ReferenceSources/XmlFormatReaderGenerator_static.cs
ReferenceSources/XmlFormatWriterGenerator_static.cs
+
+../../../external/corefx/src/System.Runtime.Serialization.Primitives/src/System/Runtime/Serialization/ISerializationSurrogateProvider.cs
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 00000000000..6caafd41198
--- /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 00000000000..5feabf388cc
--- /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 74811394aa8..601f4574a99 100644
--- a/mcs/class/System.ServiceModel.Internals/EventLogEntryType.cs
+++ b/mcs/class/System.ServiceModel.Internals/EventLogEntryType.cs
@@ -41,7 +41,12 @@ using System;
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 00000000000..cbea0fae7b4
--- /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 989c4dddc52..588ada68ccf 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 @@ namespace System.ServiceModel.Dispatcher
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/System.ServiceModel.Channels/TransactionMessageProperty.cs b/mcs/class/System.ServiceModel/System.ServiceModel.Channels/TransactionMessageProperty.cs
index 7fc83b92bae..37d4688d6f8 100644
--- a/mcs/class/System.ServiceModel/System.ServiceModel.Channels/TransactionMessageProperty.cs
+++ b/mcs/class/System.ServiceModel/System.ServiceModel.Channels/TransactionMessageProperty.cs
@@ -36,7 +36,7 @@ using System.Xml;
namespace System.ServiceModel.Channels
{
- internal class TransactionMessageProperty
+ public class TransactionMessageProperty
{
Transaction tx;
Message msg;
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 00000000000..22ece5ce8ce
--- /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 00000000000..9e39dcc73b1
--- /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.Web/System.Web.UI.WebControls.WebParts/IPersonalizable.cs b/mcs/class/System.Web/System.Web.UI.WebControls.WebParts/IPersonalizable.cs
index 719371ad7be..8ffea688604 100644
--- a/mcs/class/System.Web/System.Web.UI.WebControls.WebParts/IPersonalizable.cs
+++ b/mcs/class/System.Web/System.Web.UI.WebControls.WebParts/IPersonalizable.cs
@@ -35,9 +35,6 @@ namespace System.Web.UI.WebControls.WebParts
{
public interface IPersonalizable
{
- void Load (IDictionary sharedState, IDictionary userState);
- void Save (IDictionary state);
-
bool IsDirty { get; }
}
}
diff --git a/mcs/class/System.XML/System.Xml.Serialization/XmlSerializationReader.cs b/mcs/class/System.XML/System.Xml.Serialization/XmlSerializationReader.cs
index de6710af0a5..e49e1feeca9 100644
--- a/mcs/class/System.XML/System.Xml.Serialization/XmlSerializationReader.cs
+++ b/mcs/class/System.XML/System.Xml.Serialization/XmlSerializationReader.cs
@@ -1193,10 +1193,15 @@ namespace System.Xml.Serialization
throw new NotImplementedException ();
}
- [MonoTODO]
protected string ReadString (string value, bool trim)
{
- throw new NotImplementedException ();
+ readCount++;
+ string str = reader.ReadString ();
+ if (str != null && trim)
+ str = str.Trim();
+ if (value == null || value.Length == 0)
+ return str;
+ return value + str;
}
[MonoTODO]
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 00000000000..b6630930f75
--- /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.Xaml/System.Xaml.Schema/XamlCollectionKind.cs b/mcs/class/System.Xaml/System.Xaml.Schema/XamlCollectionKind.cs
index 3e3253936fe..27fd119253e 100644
--- a/mcs/class/System.Xaml/System.Xaml.Schema/XamlCollectionKind.cs
+++ b/mcs/class/System.Xaml/System.Xaml.Schema/XamlCollectionKind.cs
@@ -25,7 +25,7 @@ using System.Collections.Generic;
namespace System.Xaml.Schema
{
- public enum XamlCollectionKind
+ public enum XamlCollectionKind : byte
{
None,
Collection,
diff --git a/mcs/class/System.Xaml/System.Xaml/XamlNodeType.cs b/mcs/class/System.Xaml/System.Xaml/XamlNodeType.cs
index b71fcdd23bb..eb3400f3700 100644
--- a/mcs/class/System.Xaml/System.Xaml/XamlNodeType.cs
+++ b/mcs/class/System.Xaml/System.Xaml/XamlNodeType.cs
@@ -28,7 +28,7 @@ using System.Windows.Markup;
namespace System.Xaml
{
- public enum XamlNodeType
+ public enum XamlNodeType : byte
{
None,
StartObject,
diff --git a/mcs/class/System/Mono.Net.Security/MonoTlsProviderFactory.cs b/mcs/class/System/Mono.Net.Security/MonoTlsProviderFactory.cs
index dcc640ad30f..7e2135f49c5 100644
--- a/mcs/class/System/Mono.Net.Security/MonoTlsProviderFactory.cs
+++ b/mcs/class/System/Mono.Net.Security/MonoTlsProviderFactory.cs
@@ -211,6 +211,7 @@ namespace Mono.Net.Security
#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 @@ namespace Mono.Net.Security
providerRegistration = new Dictionary<string,Tuple<Guid,string>> ();
providerCache = new Dictionary<Guid,MSI.MonoTlsProvider> ();
+#if UNITY
+ if (Mono.Unity.UnityTls.IsSupported)
+ {
+ var unityTlsEntry = new Tuple<Guid,String> (UnityTlsId, "Mono.Unity.UnityTlsProvider");
+ providerRegistration.Add ("default", unityTlsEntry);
+ providerRegistration.Add ("unitytls", unityTlsEntry);
+ return;
+ }
+#endif
+
var appleTlsEntry = new Tuple<Guid,String> (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 00000000000..a72a76b1eda
--- /dev/null
+++ b/mcs/class/System/Mono.UnityTls/CertHelper.cs
@@ -0,0 +1,55 @@
+#if SECURITY_DEP
+using System.Security.Cryptography.X509Certificates;
+
+using size_t = System.IntPtr;
+
+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, (size_t)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<intermediates.Count; ++i) {
+ AddCertificateToNativeChain (nativeCertificateChain, new X509Certificate (intermediates[i]), errorState);
+ }
+ }
+ }
+ }
+
+ public static X509CertificateCollection NativeChainToManagedCollection (UnityTls.unitytls_x509list_ref nativeCertificateChain, UnityTls.unitytls_errorstate* errorState)
+ {
+ X509CertificateCollection certificates = new X509CertificateCollection ();
+
+ var cert = UnityTls.NativeInterface.unitytls_x509list_get_x509 (nativeCertificateChain, (size_t)0, errorState);
+ for (int i = 0; cert.handle != UnityTls.NativeInterface.UNITYTLS_INVALID_HANDLE; ++i) {
+ size_t certBufferSize = UnityTls.NativeInterface.unitytls_x509_export_der (cert, null, (size_t)0, errorState);
+ var certBuffer = new byte[(int)certBufferSize]; // Need to reallocate every time since X509Certificate constructor takes no length but only a byte array.
+ fixed(byte* certBufferPtr = certBuffer) {
+ UnityTls.NativeInterface.unitytls_x509_export_der (cert, certBufferPtr, certBufferSize, errorState);
+ }
+ certificates.Add (new X509Certificate (certBuffer));
+
+ cert = UnityTls.NativeInterface.unitytls_x509list_get_x509 (nativeCertificateChain, (size_t)i, errorState);
+ }
+
+ return certificates;
+ }
+ }
+}
+#endif
\ No newline at end of file
diff --git a/mcs/class/System/Mono.UnityTls/Debug.cs b/mcs/class/System/Mono.UnityTls/Debug.cs
new file mode 100644
index 00000000000..74ab6941f28
--- /dev/null
+++ b/mcs/class/System/Mono.UnityTls/Debug.cs
@@ -0,0 +1,39 @@
+#if SECURITY_DEP
+#if MONO_SECURITY_ALIAS
+extern alias MonoSecurity;
+#endif
+
+#if MONO_SECURITY_ALIAS
+using MonoSecurity::Mono.Security.Interface;
+#else
+using Mono.Security.Interface;
+#endif
+
+namespace Mono.Unity
+{
+ internal static class Debug
+ {
+ public static void CheckAndThrow (UnityTls.unitytls_errorstate errorState, string context, AlertDescription defaultAlert = AlertDescription.InternalError)
+ {
+ if (errorState.code == UnityTls.unitytls_error_code.UNITYTLS_SUCCESS)
+ return;
+
+ string message = string.Format ("{0} - error code: {1}", context, errorState.code);
+ throw new TlsException (defaultAlert, message);
+ }
+
+ public static void CheckAndThrow(UnityTls.unitytls_errorstate errorState, UnityTls.unitytls_x509verify_result verifyResult, string context, AlertDescription defaultAlert = AlertDescription.InternalError)
+ {
+ // Ignore verify result if verification is not the issue.
+ if (verifyResult == UnityTls.unitytls_x509verify_result.UNITYTLS_X509VERIFY_SUCCESS) {
+ CheckAndThrow (errorState, context, defaultAlert);
+ return;
+ }
+
+ AlertDescription alert = UnityTlsConversions.VerifyResultToAlertDescription (verifyResult, defaultAlert);
+ string message = string.Format ("{0} - error code: {1}, verify result: {2}", context, errorState.code, verifyResult);
+ throw new TlsException (alert, message);
+ }
+ }
+}
+#endif
\ No newline at end of file
diff --git a/mcs/class/System/Mono.UnityTls/UnityTls.cs b/mcs/class/System/Mono.UnityTls/UnityTls.cs
new file mode 100644
index 00000000000..09d16daa461
--- /dev/null
+++ b/mcs/class/System/Mono.UnityTls/UnityTls.cs
@@ -0,0 +1,289 @@
+using System;
+using System.Runtime.InteropServices;
+using System.Runtime.CompilerServices;
+
+namespace Mono.Unity
+{
+ // Unitytls uses UInt8 to denote raw buffers and Int8/char for strings.
+ // Since we need to funnel all in- and outgoing strings through Encoding.UTF8 it is easier to let the Int8 alias point to Byte instead of SByte.
+ // The aliases here are just there to keep the semantic in the interface and make it more similar to the c original.
+ using UInt8 = Byte;
+ using Int8 = Byte;
+ using size_t = IntPtr;
+
+ unsafe internal static partial class UnityTls
+ {
+ // ------------------------------------
+ // Error Handling
+ // ------------------------------------
+ public enum unitytls_error_code : UInt32
+ {
+ UNITYTLS_SUCCESS = 0,
+ UNITYTLS_INVALID_ARGUMENT, // One of the arguments has an invalid value (e.g. null where not allowed)
+ UNITYTLS_INVALID_FORMAT, // The passed data does not have a valid format.
+ UNITYTLS_INVALID_PASSWORD, // Invalid password
+ UNITYTLS_INVALID_STATE, // The object operating being operated on is not in a state that allows this function call.
+ UNITYTLS_BUFFER_OVERFLOW, // A passed buffer was not large enough.
+ UNITYTLS_OUT_OF_MEMORY, // Out of memory error
+ UNITYTLS_INTERNAL_ERROR, // Internal implementation error.
+ UNITYTLS_NOT_SUPPORTED, // The requested action is not supported on the current platform/implementation.
+ UNITYTLS_ENTROPY_SOURCE_FAILED, // Failed to generate requested amount of entropy data.
+ UNITYTLS_STREAM_CLOSED, // The operation is not possible because the stream between the peers was closed.
+
+ UNITYTLS_USER_CUSTOM_ERROR_START = 0x100000,
+ UNITYTLS_USER_WOULD_BLOCK, // Can be set by the user to signal that a call (e.g. read/write callback) would block and needs to be called again.
+ // Some implementations may set this if not all bytes have been read/written.
+ UNITYTLS_USER_READ_FAILED, // Can be set by the user to indicate a failed read operation.
+ UNITYTLS_USER_WRITE_FAILED, // Can be set by the user to indicate a failed write operation.
+ UNITYTLS_USER_UNKNOWN_ERROR, // Can be set by the user to indicate a generic error.
+ UNITYTLS_USER_CUSTOM_ERROR_END = 0x200000,
+ }
+
+ [StructLayout (LayoutKind.Sequential)]
+ public struct unitytls_errorstate
+ {
+ private UInt32 magic;
+ public unitytls_error_code code;
+ private UInt64 reserved; // Implementation specific error code/handle.
+ }
+
+ // ------------------------------------
+ // Private Key
+ // ------------------------------------
+
+ public struct unitytls_key {}
+ [StructLayout (LayoutKind.Sequential)]
+ public struct unitytls_key_ref { public UInt64 handle; }
+
+ // ------------------------------------
+ // X.509 Certificate
+ // -----------------------------------
+ public struct unitytls_x509 {}
+ [StructLayout (LayoutKind.Sequential)]
+ public struct unitytls_x509_ref { public UInt64 handle; }
+
+ // ------------------------------------
+ // X.509 Certificate List
+ // ------------------------------------
+ public struct unitytls_x509list {}
+ [StructLayout (LayoutKind.Sequential)]
+ public struct unitytls_x509list_ref { public UInt64 handle; }
+
+ // ------------------------------------
+ // X.509 Certificate Verification
+ // ------------------------------------
+ [Flags]
+ public enum unitytls_x509verify_result : UInt32
+ {
+ UNITYTLS_X509VERIFY_SUCCESS = 0x00000000,
+ UNITYTLS_X509VERIFY_NOT_DONE = 0x80000000,
+ UNITYTLS_X509VERIFY_FATAL_ERROR = 0xFFFFFFFF,
+
+ UNITYTLS_X509VERIFY_FLAG_EXPIRED = 0x00000001,
+ UNITYTLS_X509VERIFY_FLAG_REVOKED = 0x00000002,
+ UNITYTLS_X509VERIFY_FLAG_CN_MISMATCH = 0x00000004,
+ UNITYTLS_X509VERIFY_FLAG_NOT_TRUSTED = 0x00000008,
+
+ UNITYTLS_X509VERIFY_FLAG_USER_ERROR1 = 0x00010000,
+ UNITYTLS_X509VERIFY_FLAG_USER_ERROR2 = 0x00020000,
+ UNITYTLS_X509VERIFY_FLAG_USER_ERROR3 = 0x00040000,
+ UNITYTLS_X509VERIFY_FLAG_USER_ERROR4 = 0x00080000,
+ UNITYTLS_X509VERIFY_FLAG_USER_ERROR5 = 0x00100000,
+ UNITYTLS_X509VERIFY_FLAG_USER_ERROR6 = 0x00200000,
+ UNITYTLS_X509VERIFY_FLAG_USER_ERROR7 = 0x00400000,
+ UNITYTLS_X509VERIFY_FLAG_USER_ERROR8 = 0x00800000,
+
+ UNITYTLS_X509VERIFY_FLAG_UNKNOWN_ERROR = 0x08000000,
+ }
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ public delegate unitytls_x509verify_result unitytls_x509verify_callback(void* userData, unitytls_x509_ref cert, unitytls_x509verify_result result, unitytls_errorstate* errorState);
+
+ // ------------------------------------
+ // TLS Context
+ // ------------------------------------
+ public struct unitytls_tlsctx {}
+ [StructLayout (LayoutKind.Sequential)]
+ public struct unitytls_tlsctx_ref { public UInt64 handle; }
+
+ public struct unitytls_x509name {}
+
+ public enum unitytls_ciphersuite : UInt32
+ {
+ // With exception of the INVALID value, this enum represents an IANA cipher ID.
+ UNITYTLS_CIPHERSUITE_INVALID = 0xFFFFFF
+ }
+
+ public enum unitytls_protocol : UInt32
+ {
+ UNITYTLS_PROTOCOL_TLS_1_0,
+ UNITYTLS_PROTOCOL_TLS_1_1,
+ UNITYTLS_PROTOCOL_TLS_1_2,
+
+ UNITYTLS_PROTOCOL_INVALID,
+ }
+ [StructLayout (LayoutKind.Sequential)]
+ public struct unitytls_tlsctx_protocolrange
+ {
+ public unitytls_protocol min;
+ public unitytls_protocol max;
+ };
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ public delegate size_t unitytls_tlsctx_write_callback(void* userData, UInt8* data, size_t bufferLen, unitytls_errorstate* errorState);
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ public delegate size_t unitytls_tlsctx_read_callback(void* userData, UInt8* buffer, size_t bufferLen, unitytls_errorstate* errorState);
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ public delegate void unitytls_tlsctx_trace_callback(void* userData, unitytls_tlsctx* ctx, Int8* traceMessage, size_t traceMessageLen);
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ public delegate void unitytls_tlsctx_certificate_callback(void* userData, unitytls_tlsctx* ctx, Int8* cn, size_t cnLen, unitytls_x509name* caList, size_t caListLen, unitytls_x509list_ref* chain, unitytls_key_ref* key, unitytls_errorstate* errorState);
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ public delegate unitytls_x509verify_result unitytls_tlsctx_x509verify_callback(void* userData, unitytls_x509list_ref chain, unitytls_errorstate* errorState);
+
+ [StructLayout (LayoutKind.Sequential)]
+ public struct unitytls_tlsctx_callbacks
+ {
+ public unitytls_tlsctx_read_callback read;
+ public unitytls_tlsctx_write_callback write;
+ public void* data;
+ };
+
+
+
+ // ------------------------------------------------------------------------
+ // unitytls interface defintion
+ // ------------------------------------------------------------------------
+
+ // This native struct is used to provide all necessary fields and function calls from unitytls to the mono-unitytls-binding.
+ // Native implementation lives in unity:Modules/TLS/InterfaceStruct.cpp and needs to be adapted to every change.
+ [StructLayout (LayoutKind.Sequential)]
+ public class unitytls_interface_struct
+ {
+ public readonly UInt64 UNITYTLS_INVALID_HANDLE;
+ public readonly unitytls_tlsctx_protocolrange UNITYTLS_TLSCTX_PROTOCOLRANGE_DEFAULT;
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ public delegate unitytls_errorstate unitytls_errorstate_create_t();
+ public unitytls_errorstate_create_t unitytls_errorstate_create;
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ public delegate void unitytls_errorstate_raise_error_t(unitytls_errorstate* errorState, unitytls_error_code errorCode);
+ public unitytls_errorstate_raise_error_t unitytls_errorstate_raise_error;
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ public delegate unitytls_key_ref unitytls_key_get_ref_t(unitytls_key* key, unitytls_errorstate* errorState);
+ public unitytls_key_get_ref_t unitytls_key_get_ref;
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ public delegate unitytls_key* unitytls_key_parse_der_t(UInt8* buffer, size_t bufferLen, Int8* password, size_t passwordLen, unitytls_errorstate* errorState);
+ public unitytls_key_parse_der_t unitytls_key_parse_der;
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ public delegate unitytls_key* unitytls_key_parse_pem_t(Int8* buffer, size_t bufferLen, Int8* password, size_t passwordLen, unitytls_errorstate* errorState);
+ public unitytls_key_parse_pem_t unitytls_key_parse_pem;
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ public delegate void unitytls_key_free_t(unitytls_key* key);
+ public unitytls_key_free_t unitytls_key_free;
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ public delegate size_t unitytls_x509_export_der_t(unitytls_x509_ref cert, UInt8* buffer, size_t bufferLen, unitytls_errorstate* errorState);
+ public unitytls_x509_export_der_t unitytls_x509_export_der;
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ public delegate unitytls_x509list_ref unitytls_x509list_get_ref_t(unitytls_x509list* list, unitytls_errorstate* errorState);
+ public unitytls_x509list_get_ref_t unitytls_x509list_get_ref;
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ public delegate unitytls_x509_ref unitytls_x509list_get_x509_t(unitytls_x509list_ref list, size_t index, unitytls_errorstate* errorState);
+ public unitytls_x509list_get_x509_t unitytls_x509list_get_x509;
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ public delegate unitytls_x509list* unitytls_x509list_create_t(unitytls_errorstate* errorState);
+ public unitytls_x509list_create_t unitytls_x509list_create;
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ public delegate void unitytls_x509list_append_t(unitytls_x509list* list, unitytls_x509_ref cert, unitytls_errorstate* errorState);
+ public unitytls_x509list_append_t unitytls_x509list_append;
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ public delegate void unitytls_x509list_append_der_t(unitytls_x509list* list, UInt8* buffer, size_t bufferLen, unitytls_errorstate* errorState);
+ public unitytls_x509list_append_der_t unitytls_x509list_append_der;
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ public delegate void unitytls_x509list_append_pem_t(unitytls_x509list* list, Int8* buffer, size_t bufferLen, unitytls_errorstate* errorState);
+ public unitytls_x509list_append_der_t unitytls_x509list_append_pem;
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ public delegate void unitytls_x509list_free_t(unitytls_x509list* list);
+ public unitytls_x509list_free_t unitytls_x509list_free;
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ public delegate unitytls_x509verify_result unitytls_x509verify_default_ca_t(unitytls_x509list_ref chain, Int8* cn, size_t cnLen, unitytls_x509verify_callback cb, void* userData, unitytls_errorstate* errorState);
+ public unitytls_x509verify_default_ca_t unitytls_x509verify_default_ca;
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ public delegate unitytls_x509verify_result unitytls_x509verify_explicit_ca_t(unitytls_x509list_ref chain, unitytls_x509list_ref trustCA, Int8* cn, size_t cnLen, unitytls_x509verify_callback cb, void* userData, unitytls_errorstate* errorState);
+ public unitytls_x509verify_explicit_ca_t unitytls_x509verify_explicit_ca;
+
+ // Note that we take UInt64 here instead of handles!
+ // This a workaround for an android specific crash, caused by a bug in Mono's implementation of native calls through the arm ABI.
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ public delegate unitytls_tlsctx* unitytls_tlsctx_create_server_t(unitytls_tlsctx_protocolrange supportedProtocols, unitytls_tlsctx_callbacks callbacks, UInt64 certChain, UInt64 leafCertificateKey, unitytls_errorstate* errorState);
+ public unitytls_tlsctx_create_server_t unitytls_tlsctx_create_server;
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ public delegate unitytls_tlsctx* unitytls_tlsctx_create_client_t(unitytls_tlsctx_protocolrange supportedProtocols, unitytls_tlsctx_callbacks callbacks, Int8* cn, size_t cnLen, unitytls_errorstate* errorState);
+ public unitytls_tlsctx_create_client_t unitytls_tlsctx_create_client;
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ public delegate void unitytls_tlsctx_server_require_client_authentication_t(unitytls_tlsctx* ctx, unitytls_x509list_ref clientAuthCAList, unitytls_errorstate* errorState);
+ public unitytls_tlsctx_server_require_client_authentication_t unitytls_tlsctx_server_require_client_authentication;
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ public delegate void unitytls_tlsctx_set_certificate_callback_t(unitytls_tlsctx* ctx, unitytls_tlsctx_certificate_callback cb, void* userData, unitytls_errorstate* errorState);
+ public unitytls_tlsctx_set_certificate_callback_t unitytls_tlsctx_set_certificate_callback;
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ public delegate void unitytls_tlsctx_set_trace_callback_t(unitytls_tlsctx* ctx, unitytls_tlsctx_trace_callback cb, void* userData, unitytls_errorstate* errorState);
+ public unitytls_tlsctx_set_trace_callback_t unitytls_tlsctx_set_trace_callback;
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ public delegate void unitytls_tlsctx_set_x509verify_callback_t(unitytls_tlsctx* ctx, unitytls_tlsctx_x509verify_callback cb, void* userData, unitytls_errorstate* errorState);
+ public unitytls_tlsctx_set_x509verify_callback_t unitytls_tlsctx_set_x509verify_callback;
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ public delegate void unitytls_tlsctx_set_supported_ciphersuites_t(unitytls_tlsctx* ctx, unitytls_ciphersuite* supportedCiphersuites, size_t supportedCiphersuitesLen, unitytls_errorstate* errorState);
+ public unitytls_tlsctx_set_supported_ciphersuites_t unitytls_tlsctx_set_supported_ciphersuites;
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ public delegate unitytls_ciphersuite unitytls_tlsctx_get_ciphersuite_t(unitytls_tlsctx* ctx, unitytls_errorstate* errorState);
+ public unitytls_tlsctx_get_ciphersuite_t unitytls_tlsctx_get_ciphersuite;
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ public delegate unitytls_protocol unitytls_tlsctx_get_protocol_t(unitytls_tlsctx* ctx, unitytls_errorstate* errorState);
+ public unitytls_tlsctx_get_protocol_t unitytls_tlsctx_get_protocol;
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ public delegate unitytls_x509verify_result unitytls_tlsctx_process_handshake_t(unitytls_tlsctx* ctx, unitytls_errorstate* errorState);
+ public unitytls_tlsctx_process_handshake_t unitytls_tlsctx_process_handshake;
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ public delegate size_t unitytls_tlsctx_read_t(unitytls_tlsctx* ctx, UInt8* buffer, size_t bufferLen, unitytls_errorstate* errorState);
+ public unitytls_tlsctx_read_t unitytls_tlsctx_read;
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ public delegate size_t unitytls_tlsctx_write_t(unitytls_tlsctx* ctx, UInt8* data, size_t bufferLen, unitytls_errorstate* errorState);
+ public unitytls_tlsctx_write_t unitytls_tlsctx_write;
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ public delegate void unitytls_tlsctx_notify_close_t(unitytls_tlsctx* ctx, unitytls_errorstate* errorState);
+ public unitytls_tlsctx_notify_close_t unitytls_tlsctx_notify_close;
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ public delegate void unitytls_tlsctx_free_t(unitytls_tlsctx* ctx);
+ public unitytls_tlsctx_free_t unitytls_tlsctx_free;
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ public delegate void unitytls_random_generate_bytes_t(UInt8 * buffer, size_t bufferLen, unitytls_errorstate * errorState);
+ public unitytls_random_generate_bytes_t unitytls_random_generate_bytes;
+ }
+
+ [MethodImplAttribute (MethodImplOptions.InternalCall)]
+ private static extern IntPtr GetUnityTlsInterface ();
+
+ private static unitytls_interface_struct marshalledInterface = null;
+
+ public static bool IsSupported => NativeInterface != null;
+
+ public static unitytls_interface_struct NativeInterface
+ {
+ get
+ {
+ if (marshalledInterface == null) {
+ IntPtr rawInterface = GetUnityTlsInterface ();
+ if (rawInterface == IntPtr.Zero)
+ return null;
+ marshalledInterface = Marshal.PtrToStructure<unitytls_interface_struct> (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 00000000000..17be4c3366e
--- /dev/null
+++ b/mcs/class/System/Mono.UnityTls/UnityTlsContext.cs
@@ -0,0 +1,509 @@
+#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;
+using size_t = System.IntPtr;
+
+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;
+
+ // Delegates we passed to native to ensure they are not garbage collected
+ UnityTls.unitytls_tlsctx_read_callback readCallback;
+ UnityTls.unitytls_tlsctx_write_callback writeCallback;
+ UnityTls.unitytls_tlsctx_trace_callback traceCallback;
+ UnityTls.unitytls_tlsctx_certificate_callback certificateCallback;
+ UnityTls.unitytls_tlsctx_x509verify_callback verifyCallback;
+
+ // States and certificates
+ X509Certificate localClientCertificate;
+ X509Certificate remoteCertificate;
+ MonoTlsConnectionInfo connectioninfo;
+ bool isAuthenticated = false;
+ bool hasContext = false;
+ bool closedGraceful = 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),
+ };
+
+ readCallback = ReadCallback;
+ writeCallback = WriteCallback;
+ 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, (size_t)targetHostUtf8.Length, &errorState);
+ }
+
+ certificateCallback = CertificateCallback;
+ UnityTls.NativeInterface.unitytls_tlsctx_set_certificate_callback (tlsContext, certificateCallback, (void*)(IntPtr)handle, &errorState);
+ }
+
+ verifyCallback = VerifyCallback;
+ UnityTls.NativeInterface.unitytls_tlsctx_set_x509verify_callback (tlsContext, verifyCallback, (void*)(IntPtr)handle, &errorState);
+
+ Mono.Unity.Debug.CheckAndThrow (errorState, "Failed to create UnityTls context");
+
+ #pragma warning disable CS0162 // Disable unreachable code warning
+ if (ActivateTracing) {
+ traceCallback = TraceCallback;
+ UnityTls.NativeInterface.unitytls_tlsctx_set_trace_callback (tlsContext, traceCallback, null, &errorState);
+ Mono.Unity.Debug.CheckAndThrow (errorState, "Failed to set trace callback");
+ }
+ #pragma warning restore CS0162 // Reenable unreachable code warning.
+
+ 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, (size_t)privateKeyDer.Length, null, (size_t)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)
+ {
+ int numBytesRead = 0;
+
+ lastException = null;
+ var errorState = UnityTls.NativeInterface.unitytls_errorstate_create ();
+ fixed (byte* bufferPtr = buffer) {
+ numBytesRead = (int)UnityTls.NativeInterface.unitytls_tlsctx_read (tlsContext, bufferPtr + offset, (size_t)count, &errorState);
+ }
+ if (lastException != null)
+ throw lastException;
+
+ switch (errorState.code)
+ {
+ case UnityTls.unitytls_error_code.UNITYTLS_SUCCESS:
+ // In contrast to some other APIs (like Apple security) WOULD_BLOCK is not set if we did a partial write.
+ // The Mono Api however requires us to set the wantMore flag also if we didn't read all the data.
+ return (numBytesRead, numBytesRead < count);
+
+ case UnityTls.unitytls_error_code.UNITYTLS_USER_WOULD_BLOCK:
+ return (numBytesRead, true);
+
+ case 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.
+
+ default:
+ if (!closedGraceful) {
+ Mono.Unity.Debug.CheckAndThrow (errorState, "Failed to read data to TLS context");
+ }
+ return (0, false);
+ }
+ }
+
+ public override (int ret, bool wantMore) Write (byte[] buffer, int offset, int count)
+ {
+ int numBytesWritten = 0;
+
+ lastException = null;
+ var errorState = UnityTls.NativeInterface.unitytls_errorstate_create ();
+ fixed (byte* bufferPtr = buffer) {
+ numBytesWritten = (int)UnityTls.NativeInterface.unitytls_tlsctx_write (tlsContext, bufferPtr + offset, (size_t)count, &errorState);
+ }
+ if (lastException != null)
+ throw lastException;
+
+ switch (errorState.code)
+ {
+ case UnityTls.unitytls_error_code.UNITYTLS_SUCCESS:
+ // In contrast to some other APIs (like Apple security) WOULD_BLOCK is not set if we did a partial write.
+ // The Mono Api however requires us to set the wantMore flag also if we didn't write all the data.
+ return (numBytesWritten, numBytesWritten < count);
+
+ case UnityTls.unitytls_error_code.UNITYTLS_USER_WOULD_BLOCK:
+ return (numBytesWritten, true);
+
+ case 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.
+
+ default:
+ Mono.Unity.Debug.CheckAndThrow (errorState, "Failed to write data to TLS context");
+ return (0, false);
+ }
+ }
+
+ 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, (size_t)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 only an error if we are a client. Even servers with AskForClientCertificate should ignore it since .Net client authentification is always optional.
+ if (IsServer && result == UnityTls.unitytls_x509verify_result.UNITYTLS_X509VERIFY_NOT_DONE) {
+ Unity.Debug.CheckAndThrow (errorState, "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 (!ValidateCertificate (null, null))
+ throw new TlsException (AlertDescription.HandshakeFailure, "Verification failure during handshake");
+ }
+ else
+ Unity.Debug.CheckAndThrow (errorState, result, "Handshake failed", AlertDescription.HandshakeFailure);
+
+ 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 < (int)bufferLen)
+ writeBuffer = new byte[(int)bufferLen];
+ Marshal.Copy ((IntPtr)data, writeBuffer, 0, (int)bufferLen);
+
+ if (!Parent.InternalWrite (writeBuffer, 0, (int)bufferLen)) {
+ UnityTls.NativeInterface.unitytls_errorstate_raise_error (errorState, UnityTls.unitytls_error_code.UNITYTLS_USER_WRITE_FAILED);
+ return (size_t)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 (size_t)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 < (int)bufferLen)
+ readBuffer = new byte [(int)bufferLen];
+
+ bool wouldBlock;
+ int numBytesRead = Parent.InternalRead (readBuffer, 0, (int)bufferLen, out wouldBlock);
+
+ // Non graceful exit.
+ if (numBytesRead < 0) {
+ UnityTls.NativeInterface.unitytls_errorstate_raise_error (errorState, UnityTls.unitytls_error_code.UNITYTLS_USER_READ_FAILED);
+ } else if (numBytesRead > 0) {
+ Marshal.Copy (readBuffer, 0, (IntPtr)buffer, (int)bufferLen);
+ } else { // numBytesRead == 0
+ // careful when rearranging this: wouldBlock might be true even if stream was closed abruptly.
+ if (wouldBlock) {
+ UnityTls.NativeInterface.unitytls_errorstate_raise_error (errorState, UnityTls.unitytls_error_code.UNITYTLS_USER_WOULD_BLOCK);
+ }
+ // indicates graceful exit.
+ // UnityTls only accepts an exit as gracful, if it was closed via a special TLS protocol message.
+ // Both .Net and MobileTlsContext have a different idea of this concept though!
+ else {
+ closedGraceful = true;
+ UnityTls.NativeInterface.unitytls_errorstate_raise_error (errorState, UnityTls.unitytls_error_code.UNITYTLS_USER_READ_FAILED);
+ }
+ }
+
+ // Note that UnityTls ignores this number when raising an error.
+ return (size_t)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 (size_t)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, (int)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 00000000000..e72f8e623c2
--- /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 00000000000..0dc8b1497d0
--- /dev/null
+++ b/mcs/class/System/Mono.UnityTls/UnityTlsProvider.cs
@@ -0,0 +1,119 @@
+#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
+
+using size_t = System.IntPtr;
+
+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, (size_t)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, (size_t)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 00000000000..9f99ae8e6a2
--- /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 72acfed3d50..1e7130f58f8 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 f3b840e8f7f..b667bdc9792 100644
--- a/mcs/class/System/ReferenceSources/AutoWebProxyScriptEngine.cs
+++ b/mcs/class/System/ReferenceSources/AutoWebProxyScriptEngine.cs
@@ -46,14 +46,22 @@ namespace System.Net
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 31372e2cc6c..de5ac5809fa 100644
--- a/mcs/class/System/ReferenceSources/SecureStringHelper.cs
+++ b/mcs/class/System/ReferenceSources/SecureStringHelper.cs
@@ -14,7 +14,18 @@ namespace System.Net
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 @@ namespace System.Net
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 e7719c1afaa..c3bda137bfa 100644
--- a/mcs/class/System/ReferenceSources/SettingsSectionInternal.cs
+++ b/mcs/class/System/ReferenceSources/SettingsSectionInternal.cs
@@ -30,6 +30,7 @@ namespace System.Net.Configuration {
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 @@ namespace System.Net.Configuration {
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 a18b9fba8f6..c4ee090e8ef 100644
--- a/mcs/class/System/ReferenceSources/Win32Exception.cs
+++ b/mcs/class/System/ReferenceSources/Win32Exception.cs
@@ -3,6 +3,9 @@ using Microsoft.Win32;
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 @@ namespace System.ComponentModel
[Out] StringBuilder lpBuffer, int nSize, IntPtr[] arguments);
#endif
+#if UNITY
+ static bool s_ErrorMessagesInitialized = false;
+ static Dictionary<int, string> s_ErrorMessage = new Dictionary<int, string>();
+#endif
+
internal static string GetErrorMessage (int error)
{
#if !MOBILE
@@ -29,7 +37,14 @@ namespace System.ComponentModel
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 @@ namespace System.ComponentModel
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.Diagnostics/Process.cs b/mcs/class/System/System.Diagnostics/Process.cs
index 35b7f3fac65..6dfebd9a197 100644
--- a/mcs/class/System/System.Diagnostics/Process.cs
+++ b/mcs/class/System/System.Diagnostics/Process.cs
@@ -60,9 +60,7 @@ namespace System.Diagnostics
* the Start_internal icall in
* mono/metadata/process.c
*/
- public IntPtr thread_handle;
public int pid; // Contains -GetLastError () on failure.
- public int tid;
public string[] envVariables;
public string UserName;
public string Domain;
diff --git a/mcs/class/System/System.Net.NetworkInformation/IPAddressCollection.cs b/mcs/class/System/System.Net.NetworkInformation/IPAddressCollection.cs
index 54b831f6a43..b8c824c415b 100644
--- a/mcs/class/System/System.Net.NetworkInformation/IPAddressCollection.cs
+++ b/mcs/class/System/System.Net.NetworkInformation/IPAddressCollection.cs
@@ -84,6 +84,25 @@ namespace System.Net.NetworkInformation {
return c;
}
+ public static Win32IPAddressCollection FromSocketAddress (Win32_SOCKET_ADDRESS addr)
+ {
+ Win32IPAddressCollection c = new Win32IPAddressCollection ();
+ if (addr.Sockaddr != IntPtr.Zero)
+ c.InternalAdd (addr.GetIPAddress ());
+ return c;
+ }
+
+ public static Win32IPAddressCollection FromWinsServer (IntPtr ptr)
+ {
+ Win32IPAddressCollection c = new Win32IPAddressCollection ();
+ Win32_IP_ADAPTER_WINS_SERVER_ADDRESS a;
+ for (IntPtr p = ptr; p != IntPtr.Zero; p = a.Next) {
+ a = (Win32_IP_ADAPTER_WINS_SERVER_ADDRESS) Marshal.PtrToStructure (p, typeof (Win32_IP_ADAPTER_WINS_SERVER_ADDRESS));
+ c.InternalAdd (a.Address.GetIPAddress ());
+ }
+ return c;
+ }
+
void AddSubsequentlyString (IntPtr head)
{
Win32_IP_ADDR_STRING a;
diff --git a/mcs/class/System/System.Net.NetworkInformation/IPGlobalProperties.cs b/mcs/class/System/System.Net.NetworkInformation/IPGlobalProperties.cs
index 92bd3ffb363..7246735678d 100644
--- a/mcs/class/System/System.Net.NetworkInformation/IPGlobalProperties.cs
+++ b/mcs/class/System/System.Net.NetworkInformation/IPGlobalProperties.cs
@@ -59,8 +59,17 @@ namespace System.Net.NetworkInformation {
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<byte> (bytes, 0);
return Encoding.ASCII.GetString (bytes, 0, len < 0 ? 256 : len);
}
@@ -613,6 +622,9 @@ namespace System.Net.NetworkInformation {
[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 @@ namespace System.Net.NetworkInformation {
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.NetworkInformation/IPInterfaceProperties.cs b/mcs/class/System/System.Net.NetworkInformation/IPInterfaceProperties.cs
index bcae621e00d..aa5bffa8307 100644
--- a/mcs/class/System/System.Net.NetworkInformation/IPInterfaceProperties.cs
+++ b/mcs/class/System/System.Net.NetworkInformation/IPInterfaceProperties.cs
@@ -341,13 +341,11 @@ namespace System.Net.NetworkInformation {
public override IPv4InterfaceProperties GetIPv4Properties ()
{
- Win32_IP_ADAPTER_INFO v4info = Win32NetworkInterface2.GetAdapterInfoByIndex (mib4.Index);
- return new Win32IPv4InterfaceProperties (v4info, mib4);
+ return new Win32IPv4InterfaceProperties (addr, mib4);
}
public override IPv6InterfaceProperties GetIPv6Properties ()
{
- Win32_IP_ADAPTER_INFO v6info = Win32NetworkInterface2.GetAdapterInfoByIndex (mib6.Index);
return new Win32IPv6InterfaceProperties (mib6);
}
@@ -371,10 +369,9 @@ namespace System.Net.NetworkInformation {
public override IPAddressCollection DhcpServerAddresses {
get {
- Win32_IP_ADAPTER_INFO v4info = Win32NetworkInterface2.GetAdapterInfoByIndex (mib4.Index);
// FIXME: should ipv6 DhcpServer be considered?
try {
- return new Win32IPAddressCollection (v4info.DhcpServer);
+ return Win32IPAddressCollection.FromSocketAddress (addr.Dhcpv4Server);
} catch (IndexOutOfRangeException) {
return Win32IPAddressCollection.Empty;
}
@@ -393,28 +390,17 @@ namespace System.Net.NetworkInformation {
get {
var col = new GatewayIPAddressInformationCollection ();
try {
- Win32_IP_ADAPTER_INFO v4info = Win32NetworkInterface2.GetAdapterInfoByIndex (mib4.Index);
// FIXME: should ipv6 DhcpServer be considered?
-
- var a = v4info.GatewayList;
- if (!String.IsNullOrEmpty (a.IpAddress)) {
- col.InternalAdd(new SystemGatewayIPAddressInformation(IPAddress.Parse (a.IpAddress)));
- AddSubsequently (a.Next, col);
+ Win32_IP_ADAPTER_GATEWAY_ADDRESS a;
+ for (IntPtr p = addr.FirstGatewayAddress; p != IntPtr.Zero; p = a.Next) {
+ a = (Win32_IP_ADAPTER_GATEWAY_ADDRESS) Marshal.PtrToStructure (p, typeof (Win32_IP_ADAPTER_GATEWAY_ADDRESS));
+ col.InternalAdd (new SystemGatewayIPAddressInformation (a.Address.GetIPAddress ()));
}
} catch (IndexOutOfRangeException) {}
return col;
}
}
- static void AddSubsequently (IntPtr head, GatewayIPAddressInformationCollection col)
- {
- Win32_IP_ADDR_STRING a;
- for (IntPtr p = head; p != IntPtr.Zero; p = a.Next) {
- a = (Win32_IP_ADDR_STRING) Marshal.PtrToStructure (p, typeof (Win32_IP_ADDR_STRING));
- col.InternalAdd (new SystemGatewayIPAddressInformation (IPAddress.Parse (a.IpAddress)));
- }
- }
-
public override bool IsDnsEnabled {
get { return Win32NetworkInterface.FixedInfo.EnableDns != 0; }
}
@@ -444,7 +430,6 @@ namespace System.Net.NetworkInformation {
public override UnicastIPAddressInformationCollection UnicastAddresses {
get {
try {
- Win32_IP_ADAPTER_INFO ai = Win32NetworkInterface2.GetAdapterInfoByIndex (mib4.Index);
// FIXME: should ipv6 DhcpServer be considered?
return Win32FromUnicast (addr.FirstUnicastAddress);
} catch (IndexOutOfRangeException) {
@@ -467,9 +452,7 @@ namespace System.Net.NetworkInformation {
public override IPAddressCollection WinsServersAddresses {
get {
try {
- Win32_IP_ADAPTER_INFO v4info = Win32NetworkInterface2.GetAdapterInfoByIndex (mib4.Index);
- // FIXME: should ipv6 DhcpServer be considered?
- return new Win32IPAddressCollection (v4info.PrimaryWinsServer, v4info.SecondaryWinsServer);
+ return Win32IPAddressCollection.FromWinsServer (addr.FirstWinsServerAddress);
} catch (IndexOutOfRangeException) {
return Win32IPAddressCollection.Empty;
}
diff --git a/mcs/class/System/System.Net.NetworkInformation/IPv4InterfaceProperties.cs b/mcs/class/System/System.Net.NetworkInformation/IPv4InterfaceProperties.cs
index 86fba917ab9..ab92dd05f90 100644
--- a/mcs/class/System/System.Net.NetworkInformation/IPv4InterfaceProperties.cs
+++ b/mcs/class/System/System.Net.NetworkInformation/IPv4InterfaceProperties.cs
@@ -129,13 +129,13 @@ namespace System.Net.NetworkInformation {
[DllImport ("iphlpapi.dll")]
static extern int GetPerAdapterInfo (int IfIndex, Win32_IP_PER_ADAPTER_INFO pPerAdapterInfo, ref int pOutBufLen);
- Win32_IP_ADAPTER_INFO ainfo;
+ Win32_IP_ADAPTER_ADDRESSES addr;
Win32_IP_PER_ADAPTER_INFO painfo;
Win32_MIB_IFROW mib;
- public Win32IPv4InterfaceProperties (Win32_IP_ADAPTER_INFO ainfo, Win32_MIB_IFROW mib)
+ public Win32IPv4InterfaceProperties (Win32_IP_ADAPTER_ADDRESSES addr, Win32_MIB_IFROW mib)
{
- this.ainfo = ainfo;
+ this.addr = addr;
this.mib = mib;
// get per-adapter info.
@@ -160,7 +160,7 @@ namespace System.Net.NetworkInformation {
}
public override bool IsDhcpEnabled {
- get { return ainfo.DhcpEnabled != 0; }
+ get { return addr.DhcpEnabled; }
}
public override bool IsForwardingEnabled {
@@ -173,7 +173,7 @@ namespace System.Net.NetworkInformation {
}
public override bool UsesWins {
- get { return ainfo.HaveWins; }
+ get { return addr.FirstWinsServerAddress != IntPtr.Zero; }
}
}
diff --git a/mcs/class/System/System.Net.NetworkInformation/NetworkInterface.cs b/mcs/class/System/System.Net.NetworkInformation/NetworkInterface.cs
index fedf95dbb4d..9743e0c58dc 100644
--- a/mcs/class/System/System.Net.NetworkInformation/NetworkInterface.cs
+++ b/mcs/class/System/System.Net.NetworkInformation/NetworkInterface.cs
@@ -465,9 +465,13 @@ namespace System.Net.NetworkInformation {
{
IntPtr ptr = IntPtr.Zero;
int len = 0;
- GetAdaptersAddresses (0, 0, IntPtr.Zero, ptr, ref len);
+ uint flags = Win32_IP_ADAPTER_ADDRESSES.GAA_FLAG_INCLUDE_WINS_INFO | Win32_IP_ADAPTER_ADDRESSES.GAA_FLAG_INCLUDE_GATEWAYS;
+ GetAdaptersAddresses (0, flags, IntPtr.Zero, ptr, ref len);
+ if (Marshal.SizeOf (typeof (Win32_IP_ADAPTER_ADDRESSES)) > len)
+ throw new NetworkInformationException ();
+
ptr = Marshal.AllocHGlobal(len);
- int ret = GetAdaptersAddresses (0, 0, IntPtr.Zero, ptr, ref len);
+ int ret = GetAdaptersAddresses (0, flags, IntPtr.Zero, ptr, ref len);
if (ret != 0)
throw new NetworkInformationException (ret);
@@ -829,14 +833,6 @@ namespace System.Net.NetworkInformation {
[DllImport ("iphlpapi.dll", SetLastError = true)]
static extern int GetIfEntry (ref Win32_MIB_IFROW row);
- public static Win32_IP_ADAPTER_INFO GetAdapterInfoByIndex (int index)
- {
- foreach (Win32_IP_ADAPTER_INFO info in GetAdaptersInfo ())
- if (info.Index == index)
- return info;
- throw new IndexOutOfRangeException ("No adapter found for index " + index);
- }
-
static Win32_IP_ADAPTER_INFO [] GetAdaptersInfo ()
{
int len = 0;
diff --git a/mcs/class/System/System.Net.NetworkInformation/Win32NetworkInterfaceMarshal.cs b/mcs/class/System/System.Net.NetworkInformation/Win32NetworkInterfaceMarshal.cs
index 88ae0b8e358..66742871321 100644
--- a/mcs/class/System/System.Net.NetworkInformation/Win32NetworkInterfaceMarshal.cs
+++ b/mcs/class/System/System.Net.NetworkInformation/Win32NetworkInterfaceMarshal.cs
@@ -121,15 +121,37 @@ namespace System.Net.NetworkInformation
public NetworkInterfaceType IfType;
public OperationalStatus OperStatus;
public int Ipv6IfIndex;
- [MarshalAs (UnmanagedType.ByValArray, SizeConst = 16 * 4)]
+ [MarshalAs (UnmanagedType.ByValArray, SizeConst = 16)]
public uint [] ZoneIndices;
-
- // Note that Vista-only members and XP-SP1-only member are
- // omitted.
+ public IntPtr FirstPrefix; // to PIP_ADAPTER_PREFIX
+ public UInt64 TransmitLinkSpeed;
+ public UInt64 ReceiveLinkSpeed;
+ public IntPtr FirstWinsServerAddress; // to PIP_ADAPTER_WINS_SERVER_ADDRESS_LH
+ public IntPtr FirstGatewayAddress; // to PIP_ADAPTER_GATEWAY_ADDRESS_LH
+ public uint Ipv4Metric;
+ public uint Ipv6Metric;
+ public UInt64 Luid;
+ public Win32_SOCKET_ADDRESS Dhcpv4Server;
+ public uint CompartmentId;
+ public UInt64 NetworkGuid;
+ public int ConnectionType;
+ public int TunnelType;
+ public Win32_SOCKET_ADDRESS Dhcpv6Server;
+ [MarshalAs (UnmanagedType.ByValArray, SizeConst = MAX_DHCPV6_DUID_LENGTH)]
+ public byte [] Dhcpv6ClientDuid;
+ public ulong Dhcpv6ClientDuidLength;
+ public ulong Dhcpv6Iaid;
+ public IntPtr FirstDnsSuffix; // to PIP_ADAPTER_DNS_SUFFIX
+
+ //Flags For GetAdapterAddresses
+ public const int GAA_FLAG_INCLUDE_WINS_INFO = 0x0040;
+ public const int GAA_FLAG_INCLUDE_GATEWAYS = 0x0080;
const int MAX_ADAPTER_ADDRESS_LENGTH = 8;
+ const int MAX_DHCPV6_DUID_LENGTH = 130;
const int IP_ADAPTER_DDNS_ENABLED = 1;
+ const int IP_ADAPTER_DHCP_ENABLED = 4;
const int IP_ADAPTER_RECEIVE_ONLY = 8;
const int IP_ADAPTER_NO_MULTICAST = 0x10;
@@ -137,6 +159,10 @@ namespace System.Net.NetworkInformation
get { return (Flags & IP_ADAPTER_DDNS_ENABLED) != 0; }
}
+ public bool DhcpEnabled {
+ get { return (Flags & IP_ADAPTER_DHCP_ENABLED) != 0; }
+ }
+
public bool IsReceiveOnly {
get { return (Flags & IP_ADAPTER_RECEIVE_ONLY) != 0; }
}
@@ -267,6 +293,22 @@ namespace System.Net.NetworkInformation
public Win32_SOCKET_ADDRESS Address;
}
+ [StructLayout (LayoutKind.Sequential)]
+ struct Win32_IP_ADAPTER_GATEWAY_ADDRESS
+ {
+ public Win32LengthFlagsUnion LengthFlags;
+ public IntPtr Next; // to Win32_IP_ADAPTER_GATEWAY_ADDRESS
+ public Win32_SOCKET_ADDRESS Address;
+ }
+
+ [StructLayout (LayoutKind.Sequential)]
+ struct Win32_IP_ADAPTER_WINS_SERVER_ADDRESS
+ {
+ public Win32LengthFlagsUnion LengthFlags;
+ public IntPtr Next; // to Win32_IP_ADAPTER_WINS_SERVER_ADDRESS
+ public Win32_SOCKET_ADDRESS Address;
+ }
+
[StructLayout (LayoutKind.Sequential)]
struct Win32_IP_ADAPTER_UNICAST_ADDRESS
{
diff --git a/mcs/class/System/System.Net.Sockets/Socket.cs b/mcs/class/System/System.Net.Sockets/Socket.cs
index fe7099144ec..8de0daf46ca 100644
--- a/mcs/class/System/System.Net.Sockets/Socket.cs
+++ b/mcs/class/System/System.Net.Sockets/Socket.cs
@@ -1160,7 +1160,24 @@ namespace System.Net.Sockets
// while skipping entries that do not match the address family
DnsEndPoint dep = e.RemoteEndPoint as DnsEndPoint;
if (dep != null) {
- addresses = Dns.GetHostAddresses (dep.Host);
+ if (dep.AddressFamily == AddressFamily.Unspecified)
+ {
+ addresses = Dns.GetHostAddresses(dep.Host);
+ } else {
+ 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 +2810,16 @@ namespace System.Net.Sockets
}
}
+#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 d971cdd8412..1d2502e11df 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/System/Platform.cs b/mcs/class/System/System/Platform.cs
index f4214393fc3..46395ff291a 100644
--- a/mcs/class/System/System/Platform.cs
+++ b/mcs/class/System/System/Platform.cs
@@ -59,26 +59,40 @@ namespace System {
}
IntPtr buf = Marshal.AllocHGlobal (8192);
- if (uname (buf) == 0) {
- string os = Marshal.PtrToStringAnsi (buf);
- switch (os) {
- case "Darwin":
- isMacOS = true;
- break;
- case "FreeBSD":
- isFreeBSD = true;
- break;
+ try {
+ if (uname (buf) == 0) {
+ string os = Marshal.PtrToStringAnsi (buf);
+ switch (os) {
+ case "Darwin":
+ isMacOS = true;
+ break;
+ case "FreeBSD":
+ isFreeBSD = true;
+ break;
+ }
}
}
- Marshal.FreeHGlobal (buf);
- checkedOS = true;
+ finally {
+ Marshal.FreeHGlobal (buf);
+ checkedOS = true;
+ }
}
#endif
public static bool IsMacOS {
get {
if (!checkedOS)
+#if UNITY
+ try {
+ CheckOS();
+ }
+ catch (DllNotFoundException e) {
+ // libc does not exist, so this is not MacOS
+ isMacOS = false;
+ }
+#else
CheckOS();
+#endif
return isMacOS;
}
}
diff --git a/mcs/class/System/common.sources b/mcs/class/System/common.sources
index 418336ceef9..29ca5d4b9cf 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
@@ -923,3 +931,5 @@ corefx/SR.cs
../../../external/corefx/src/System.Private.Uri/src/System/UriBuilder.cs
../../../external/corefx/src/System.Runtime.Extensions/src/System/CodeDom/Compiler/IndentedTextWriter.cs
+
+../../../external/corefx/src/System.Runtime.InteropServices/src/System/Security/SecureStringMarshal.cs
diff --git a/mcs/class/System/unityaot_System.dll.sources b/mcs/class/System/unityaot_System.dll.sources
new file mode 100644
index 00000000000..9bd62cd0ec2
--- /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 00000000000..beb6f2415cf
--- /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 54b21cdf3ba..2d2de030429 100644
--- a/mcs/class/corlib/Assembly/AssemblyInfo.cs
+++ b/mcs/class/corlib/Assembly/AssemblyInfo.cs
@@ -59,7 +59,7 @@ using System.Runtime.InteropServices;
[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/LinkerDescriptor/mscorlib.xml b/mcs/class/corlib/LinkerDescriptor/mscorlib.xml
index 4d36758a43c..304d4b03c7f 100644
--- a/mcs/class/corlib/LinkerDescriptor/mscorlib.xml
+++ b/mcs/class/corlib/LinkerDescriptor/mscorlib.xml
@@ -4,7 +4,6 @@
<!-- domain.c: mono_defaults.appdomain_class -->
<type fullname="System.AppDomain" preserve="fields">
- <method name="DoDomainUnload" />
<!-- appdomain.c: mono_domain_try_type_resolve -->
<method name="DoTypeResolve" />
<!-- appdomain.c: mono_try_assembly_resolve -->
@@ -20,7 +19,10 @@
</type>
<!-- appdomain.c: mono_runtime_init -->
- <type fullname="System.AppDomainSetup" preserve="fields" />
+ <type fullname="System.AppDomainSetup" preserve="fields" >
+ <!-- appdomain.c mono_object_new_checked in mono_domain_create_appdomain_checked -->
+ <method signature="System.Void .ctor()" />
+ </type>
<!-- exception.c: mono_get_exception_appdomain_unloaded (used in several places), threadpool.c -->
<type fullname="System.AppDomainUnloadedException">
@@ -123,7 +125,10 @@
<!-- domain.c: mono_defaults.stack_frame_class -->
<!-- used in mini-exceptions.c to create array and MonoStackFrame instance, i.e. only fields are required to be preserved -->
- <type fullname="System.Diagnostics.StackFrame" preserve="fields" />
+ <type fullname="System.Diagnostics.StackFrame" preserve="fields" >
+ <!-- threads.c mono_object_new_checked in mono_threads_get_thread_dump -->
+ <method signature="System.Void .ctor()" />
+ </type>
<!-- domain.c: mono_defaults.stack_trace_class -->
<!-- does not seems used outside the g_assert in domain.c (maybe it could be removed) -->
@@ -255,7 +260,10 @@
</type>
<!-- threadpool.c: mono_thread_pool_init (assert) -->
- <type fullname="System.MonoAsyncCall" preserve="fields" />
+ <type fullname="System.MonoAsyncCall" preserve="fields" >
+ <!-- threadpool.c mono_object_new_checked in mono_threadpool_begin_invoke -->
+ <method signature="System.Void .ctor()" />
+ </type>
<!-- mono-mlist.c (managed list): used in threadpool.c and gc.c -->
<type fullname="System.MonoListItem" preserve="fields" />
@@ -304,6 +312,8 @@
<!-- TransparentProxy.cs, RemotingServices.cs -->
<method name="FieldGetter" feature="remoting" />
<method name="FieldSetter" feature="remoting" />
+ <!-- appdomain.c mono_object_new_checked in create_domain_objects -->
+ <method signature="System.Void .ctor()" />
</type>
<!-- appdomain.c (create_domain_objects) domain->out_of_memory_ex -->
@@ -498,13 +508,6 @@
note: there's no fields (static type) but that will mark the type itself -->
<type fullname="System.Math" preserve="fields" />
- <type fullname="System.Reflection.MonoAssembly">
- <method name=".ctor" />
- </type>
- <type fullname="System.Reflection.MonoModule">
- <method name=".ctor" />
- </type>
-
<!-- appdomain.c: ves_icall_System_AppDomain_GetAssemblies -->
<type fullname="System.Reflection.Assembly" preserve="fields"/>
@@ -532,42 +535,71 @@
</type>
<!-- reflection.c: mono_method_body_get_object -->
- <type fullname="System.Reflection.ExceptionHandlingClause" preserve="fields" />
+ <type fullname="System.Reflection.ExceptionHandlingClause" preserve="fields" >
+ <!-- reflection.c mono_object_new_checked in add_exception_handling_clause_to_array -->
+ <method signature="System.Void .ctor()" />
+ </type>
<!-- domain.c: mono_defaults.field_info_class -->
<type fullname="System.Reflection.FieldInfo" preserve="fields" />
<!-- reflection.c: mono_method_body_get_object -->
- <type fullname="System.Reflection.LocalVariableInfo" preserve="fields" />
+ <type fullname="System.Reflection.LocalVariableInfo" preserve="fields" >
+ <!-- reflection.c mono_object_new_checked in add_local_var_info_to_array -->
+ <method signature="System.Void .ctor()" />
+ </type>
<!-- reflection.c: mono_method_body_get_object -->
- <type fullname="System.Reflection.MethodBody" preserve="fields" />
+ <type fullname="System.Reflection.MethodBody" preserve="fields" >
+ <!-- reflection.c mono_object_new_checked in method_body_object_construct -->
+ <method signature="System.Void .ctor()" />
+ </type>
<!-- domain.c: mono_defaults.method_info_class -->
<type fullname="System.Reflection.MethodInfo" preserve="fields" />
<type fullname="System.Reflection.Module" preserve="fields" />
- <type fullname="System.Reflection.MonoAssembly" preserve="fields" />
- <type fullname="System.Reflection.MonoModule" preserve="fields" />
- <type fullname="System.Reflection.MonoCMethod" preserve="fields" />
+ <type fullname="System.Reflection.MonoAssembly" preserve="fields" >
+ <method name=".ctor" />
+ </type>
+ <type fullname="System.Reflection.MonoModule" preserve="fields" >
+ <method name=".ctor" />
+ </type>
+ <type fullname="System.Reflection.MonoCMethod" preserve="fields" >
+ <!-- reflection.c mono_object_new_checked in method_object_construct -->
+ <method signature="System.Void .ctor()" />
+ </type>
<type fullname="System.Reflection.MonoEvent" preserve="fields" />
- <type fullname="System.Reflection.MonoEventInfo" preserve="fields" />
- <type fullname="System.Reflection.MonoField" preserve="fields" />
-
+ <type fullname="System.Reflection.MonoEventInfo" preserve="fields" >
+ <!-- reflection.c mono_object_new_checked in event_object_construct -->
+ <method signature="System.Void .ctor()" />
+ </type>
+ <type fullname="System.Reflection.MonoField" preserve="fields" >
+ <!-- reflection.c mono_object_new_checked in field_object_construct -->
+ <method signature="System.Void .ctor()" />
+ </type>
<!-- reflection.c: mono_method_get_object uses both MonoGeneric[C]Method / will crash for ves_icall_Type_GetConstructors_internal -->
<type fullname="System.Reflection.MonoGenericMethod" preserve="fields" />
<type fullname="System.Reflection.MonoGenericCMethod" preserve="fields" />
- <type fullname="System.Reflection.MonoMethod" preserve="fields" />
+ <type fullname="System.Reflection.MonoMethod" preserve="fields" >
+ <!-- reflection.c mono_object_new_checked in method_object_construct -->
+ <method signature="System.Void .ctor()" />
+ </type>
<type fullname="System.Reflection.MonoMethodInfo" preserve="fields" />
<type fullname="System.Reflection.MonoPropertyInfo" preserve="fields" />
<type fullname="System.Reflection.MonoProperty" preserve="fields">
<method name="GetterAdapterFrame" />
<method name="StaticGetterAdapterFrame" />
+ <!-- reflection.c mono_object_new_checked in add_parameter_object_to_array -->
+ <method signature="System.Void .ctor()" />
</type>
<type fullname="System.Reflection.ParameterInfo" preserve="fields" />
<!-- reflection.c: ves_icall_get_parameter_info -->
- <type fullname="System.Reflection.MonoParameterInfo" preserve="fields" />
+ <type fullname="System.Reflection.MonoParameterInfo" preserve="fields" >
+ <!-- reflection.c mono_object_new_checked in event_object_construct -->
+ <method signature="System.Void .ctor()" />
+ </type>
<!-- object.c: mono_field_get_value_object and mono_runtime_invoke_array -->
<type fullname="System.Reflection.Pointer" >
@@ -594,39 +626,39 @@
</type>
<type fullname="System.Reflection.Emit.AssemblyBuilder" preserve="fields" feature="sre">
- <method name="AddPermissionRequests" />
- <method name="AddModule" />
- <method name="DefineIconResource" />
- <method name="AddTypeForwarder" />
- <method name="EmbedResourceFile" />
+ <method name="AddPermissionRequests" feature="sre" />
+ <method name="AddModule" feature="sre" />
+ <method name="DefineIconResource" feature="sre" />
+ <method name="AddTypeForwarder" feature="sre" />
+ <method name="EmbedResourceFile" feature="sre" />
</type>
<type fullname="System.Reflection.Emit.ConstructorBuilder" preserve="fields" feature="sre">
- <method name="RuntimeResolve" />
+ <method name="RuntimeResolve" feature="sre" />
</type>
<type fullname="System.Reflection.Emit.CustomAttributeBuilder" preserve="fields" feature="sre" />
- <type fullname="System.Reflection.Emit.DynamicMethod" preserve="fields" />
- <type fullname="System.Reflection.Emit.EnumBuilder" preserve="fields" />
- <type fullname="System.Reflection.Emit.EventBuilder" preserve="fields" />
- <type fullname="System.Reflection.Emit.FieldBuilder" preserve="fields" >
- <method name="RuntimeResolve" />
+ <type fullname="System.Reflection.Emit.DynamicMethod" preserve="fields" feature="sre" />
+ <type fullname="System.Reflection.Emit.EnumBuilder" preserve="fields" feature="sre" />
+ <type fullname="System.Reflection.Emit.EventBuilder" preserve="fields" feature="sre" />
+ <type fullname="System.Reflection.Emit.FieldBuilder" preserve="fields" feature="sre" >
+ <method name="RuntimeResolve" feature="sre" />
</type>
<type fullname="System.Reflection.Emit.GenericTypeParameterBuilder" preserve="fields" feature="sre" >
- <method name="RuntimeResolve" />
+ <method name="RuntimeResolve" feature="sre" />
</type>
<type fullname="System.Reflection.Emit.ILExceptionBlock" preserve="fields" feature="sre" />
- <type fullname="System.Reflection.Emit.ILExceptionInfo" preserve="fields" />
- <type fullname="System.Reflection.Emit.ILGenerator" preserve="fields">
- <method name="Mono_GetCurrentOffset" />
+ <type fullname="System.Reflection.Emit.ILExceptionInfo" preserve="fields" feature="sre" />
+ <type fullname="System.Reflection.Emit.ILGenerator" preserve="fields" feature="sre" >
+ <method name="Mono_GetCurrentOffset" feature="sre" />
</type>
<type fullname="System.Reflection.Emit.LocalBuilder" preserve="fields" feature="sre" >
- <method name="Mono_GetLocalIndex" />
+ <method name="Mono_GetLocalIndex" feature="sre" />
</type>
<type fullname="System.Reflection.Emit.MethodBuilder" preserve="fields" feature="sre" >
- <method name="RuntimeResolve" />
+ <method name="RuntimeResolve" feature="sre" />
</type>
<type fullname="System.Reflection.Emit.ModuleBuilder" preserve="fields" feature="sre">
- <method name="Mono_GetGuid" />
- <method name="RuntimeResolve" />
+ <method name="Mono_GetGuid" feature="sre" />
+ <method name="RuntimeResolve" feature="sre" />
</type>
<type fullname="System.Reflection.Emit.MonoResource" preserve="fields" feature="sre" />
<type fullname="System.Reflection.Emit.MonoWin32Resource" preserve="fields" feature="sre" />
@@ -634,34 +666,34 @@
<type fullname="System.Reflection.Emit.PropertyBuilder" preserve="fields" feature="sre" />
<type fullname="System.Reflection.Emit.SignatureHelper" preserve="fields" feature="sre" />
<type fullname="System.Reflection.Emit.TypeBuilder" preserve="fields" feature="sre">
- <method name="SetCharSet" />
+ <method name="SetCharSet" feature="sre" />
<!-- reflection.c mono_reflection_call_is_assignable_to () -->
- <method name="IsAssignableTo" />
+ <method name="IsAssignableTo" feature="sre" />
</type>
<type fullname="System.Reflection.Emit.UnmanagedMarshal" preserve="fields" feature="sre" >
- <method name="DefineCustom" />
- <method name="DefineLPArrayInternal" />
+ <method name="DefineCustom" feature="sre" />
+ <method name="DefineLPArrayInternal" feature="sre" />
</type>
<type fullname="System.Reflection.Emit.TypeBuilderInstantiation" preserve="fields" feature="sre" >
- <method name="RuntimeResolve" />
+ <method name="RuntimeResolve" feature="sre" />
</type>
<type fullname="System.Reflection.Emit.ArrayType" preserve="fields" feature="sre" >
- <method name="RuntimeResolve" />
+ <method name="RuntimeResolve" feature="sre" />
</type>
<type fullname="System.Reflection.Emit.ByRefType" preserve="fields" feature="sre" >
- <method name="RuntimeResolve" />
+ <method name="RuntimeResolve" feature="sre" />
</type>
<type fullname="System.Reflection.Emit.PointerType" preserve="fields" feature="sre" >
- <method name="RuntimeResolve" />
+ <method name="RuntimeResolve" feature="sre" />
</type>
<type fullname="System.Reflection.Emit.FieldOnTypeBuilderInst" preserve="fields" feature="sre" >
- <method name="RuntimeResolve" />
+ <method name="RuntimeResolve" feature="sre" />
</type>
<type fullname="System.Reflection.Emit.MethodOnTypeBuilderInst" preserve="fields" feature="sre" >
- <method name="RuntimeResolve" />
+ <method name="RuntimeResolve" feature="sre" />
</type>
<type fullname="System.Reflection.Emit.ConstructorOnTypeBuilderInst" preserve="fields" feature="sre" >
- <method name="RuntimeResolve" />
+ <method name="RuntimeResolve" feature="sre" />
</type>
<!-- domain.c: mono_defaults.internals_visible_class -->
@@ -712,22 +744,36 @@
<!-- domain.c: mono_defaults.asyncresult_class (Stubify can't be applied on this type) -->
<!-- object.c MONO_OBJECT_SETREF in mono_async_result_new -->
<!-- threadpool.c: MONO_OBJECT_SETREF in create_simple_asyncresult -->
- <type fullname="System.Runtime.Remoting.Messaging.AsyncResult" preserve="fields" />
+ <type fullname="System.Runtime.Remoting.Messaging.AsyncResult" preserve="fields" >
+ <!-- object.c mono_object_new_checked in mono_async_result_new -->
+ <method signature="System.Void .ctor()" />
+ </type>
<!-- marshal.c: mono_remoting_marshal_init / removed with DISABLE_REMOTING -->
<type fullname="System.Runtime.Remoting.Messaging.CallContext" feature="remoting" >
<method name="SetCurrentCallContext" />
</type>
+
+ <!-- domain.c: mono_defaults.mono_method_message_class -->
<type fullname="System.Runtime.Remoting.Messaging.MonoMethodMessage" preserve="fields" feature="remoting" >
+ <!-- object.c: mono_message_init -->
<method name="InitMessage" />
+ <!-- marshal.c mono_object_new_checked in mono_delegate_end_invoke-->
+ <method name=".ctor" feature="remoting" />
</type>
+ <!-- domain.c: mono_defaults.real_proxy_class / removed with DISABLE_REMOTING -->
<type fullname="System.Runtime.Remoting.Proxies.RealProxy" preserve="fields" feature="remoting" >
<method name="PrivateInvoke" />
<method name="GetAppDomainTarget" />
+ <!-- object.c mono_object_new_checked in make_transparent_proxy-->
+ <method name=".ctor" feature="remoting" />
</type>
+ <!-- domain.c: mono_defaults.transparent_proxy_class / removed with DISABLE_REMOTING -->
<type fullname="System.Runtime.Remoting.Proxies.TransparentProxy" preserve="fields" feature="remoting" >
<method name="LoadRemoteFieldNew" />
<method name="StoreRemoteField" />
+ <!-- icall.c mono_object_new_checked in ves_icall_Remoting_RealProxy_GetTransparentProxy -->
+ <method signature="System.Void .ctor()" feature="remoting" />
</type>
<type fullname="System.Runtime.Remoting.RemotingServices" feature="remoting" >
<method name="SerializeCallData" />
@@ -735,18 +781,6 @@
<method name="SerializeExceptionData" />
</type>
- <!-- domain.c: mono_defaults.mono_method_message_class -->
- <type fullname="System.Runtime.Remoting.Messaging.MonoMethodMessage" preserve="fields">
- <!-- object.c: mono_message_init -->
- <method name="InitMessage" />
- </type>
-
- <!-- domain.c: mono_defaults.real_proxy_class / removed with DISABLE_REMOTING -->
- <type fullname="System.Runtime.Remoting.Proxies.RealProxy" feature="remoting" />
-
- <!-- domain.c: mono_defaults.transparent_proxy_class / removed with DISABLE_REMOTING -->
- <type fullname="System.Runtime.Remoting.Proxies.TransparentProxy" feature="remoting" />
-
<!-- object.c: mono_object_new_specific_checked -->
<type fullname="System.Runtime.Remoting.Activation.ActivationServices" >
<method name="CreateProxyForType"/>
@@ -853,5 +887,16 @@
<type fullname="Mono.RuntimeStructs/HandleStackMark" />
<!-- marshal.c (mono_marshal_get_native_wrapper) -->
<type fullname="Mono.RuntimeStructs/MonoError" />
+
+ <!-- IL2CPP enum sharing -->
+ <type fullname="System.SByteEnum" />
+ <type fullname="System.Int16Enum" />
+ <type fullname="System.Int32Enum" />
+ <type fullname="System.Int64Enum" />
+
+ <type fullname="System.ByteEnum" />
+ <type fullname="System.UInt16Enum" />
+ <type fullname="System.UInt32Enum" />
+ <type fullname="System.UInt64Enum" />
</assembly>
</linker>
diff --git a/mcs/class/corlib/Makefile b/mcs/class/corlib/Makefile
index 910f7b672f4..a5cfd954198 100644
--- a/mcs/class/corlib/Makefile
+++ b/mcs/class/corlib/Makefile
@@ -42,7 +42,6 @@ MODULE_DEPS = $(IL_REPLACE)
endif
RESOURCE_FILES = \
- resources/charinfo.nlp \
resources/collation.core.bin \
resources/collation.tailoring.bin \
resources/collation.cjkCHS.bin \
diff --git a/mcs/class/corlib/System.IO/DriveInfo.cs b/mcs/class/corlib/System.IO/DriveInfo.cs
index 6c4c7eee87c..b71e5d00389 100644
--- a/mcs/class/corlib/System.IO/DriveInfo.cs
+++ b/mcs/class/corlib/System.IO/DriveInfo.cs
@@ -140,10 +140,9 @@ namespace System.IO {
}
}
- [MonoTODO("It always returns true")]
public bool IsReady {
get {
- return true;
+ return Directory.Exists (Name);
}
}
diff --git a/mcs/class/corlib/System.IO/MonoIO.cs b/mcs/class/corlib/System.IO/MonoIO.cs
index 3567809b9da..68418f794f3 100644
--- a/mcs/class/corlib/System.IO/MonoIO.cs
+++ b/mcs/class/corlib/System.IO/MonoIO.cs
@@ -733,6 +733,9 @@ namespace System.IO
[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 bf0093e1203..8aaa49340d2 100644
--- a/mcs/class/corlib/System.IO/Path.cs
+++ b/mcs/class/corlib/System.IO/Path.cs
@@ -422,6 +422,9 @@ namespace System.IO {
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.Reflection/MonoProperty.cs b/mcs/class/corlib/System.Reflection/MonoProperty.cs
index 16f44ec583b..a4c807d3de6 100644
--- a/mcs/class/corlib/System.Reflection/MonoProperty.cs
+++ b/mcs/class/corlib/System.Reflection/MonoProperty.cs
@@ -378,7 +378,7 @@ namespace System.Reflection {
{
if (index == null || index.Length == 0) {
/*FIXME we should check if the number of arguments matches the expected one, otherwise the error message will be pretty criptic.*/
-#if !FULL_AOT_RUNTIME
+#if !FULL_AOT_RUNTIME && !UNITY_AOT
if (cached_getter == null) {
MethodInfo method = GetGetMethod (true);
if (!DeclaringType.IsValueType && !method.ContainsGenericParameters) { //FIXME find a way to build an invoke delegate for value types.
diff --git a/mcs/class/corlib/System.Runtime.InteropServices/LIBFLAGS.cs b/mcs/class/corlib/System.Runtime.InteropServices/LIBFLAGS.cs
index f58f6a608dc..9dccb0a5537 100644
--- a/mcs/class/corlib/System.Runtime.InteropServices/LIBFLAGS.cs
+++ b/mcs/class/corlib/System.Runtime.InteropServices/LIBFLAGS.cs
@@ -34,7 +34,7 @@ namespace System.Runtime.InteropServices
{
[Obsolete]
[Flags, Serializable]
- public enum LIBFLAGS
+ public enum LIBFLAGS : short
{
LIBFLAG_FRESTRICTED = 1,
LIBFLAG_FCONTROL = 2,
diff --git a/mcs/class/corlib/System.Runtime.InteropServices/Marshal.cs b/mcs/class/corlib/System.Runtime.InteropServices/Marshal.cs
index e94898a5c38..e12d825cd58 100644
--- a/mcs/class/corlib/System.Runtime.InteropServices/Marshal.cs
+++ b/mcs/class/corlib/System.Runtime.InteropServices/Marshal.cs
@@ -53,14 +53,14 @@ namespace System.Runtime.InteropServices
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 @@ namespace System.Runtime.InteropServices
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 @@ namespace System.Runtime.InteropServices
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 @@ namespace System.Runtime.InteropServices
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 @@ namespace System.Runtime.InteropServices
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 @@ namespace System.Runtime.InteropServices
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 @@ namespace System.Runtime.InteropServices
return m.GetHINSTANCE ();
}
-#endif // !FULL_AOT_RUNTIME
+#endif // !FULL_AOT_RUNTIME || UNITY_AOT
public static int GetExceptionCode ()
{
@@ -453,14 +457,14 @@ namespace System.Runtime.InteropServices
[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 @@ namespace System.Runtime.InteropServices
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 @@ namespace System.Runtime.InteropServices
{
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 @@ namespace System.Runtime.InteropServices
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 @@ namespace System.Runtime.InteropServices
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 @@ namespace System.Runtime.InteropServices
public static T GetObjectForNativeVariant<T> (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 @@ namespace System.Runtime.InteropServices
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 @@ namespace System.Runtime.InteropServices
public static T[] GetObjectsForNativeVariants<T> (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 @@ namespace System.Runtime.InteropServices
[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 @@ namespace System.Runtime.InteropServices
throw new PlatformNotSupportedException ();
}
-#if !MOBILE
+#if !MOBILE || UNITY_AOT
[MethodImplAttribute (MethodImplOptions.InternalCall)]
public extern static bool IsComObject (object o);
#else
@@ -815,14 +824,14 @@ namespace System.Runtime.InteropServices
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 @@ namespace System.Runtime.InteropServices
[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 @@ namespace System.Runtime.InteropServices
[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 @@ namespace System.Runtime.InteropServices
#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 @@ namespace System.Runtime.InteropServices
{
}
-#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/Debug.cs b/mcs/class/corlib/System/Debug.cs
new file mode 100644
index 00000000000..aa111394c50
--- /dev/null
+++ b/mcs/class/corlib/System/Debug.cs
@@ -0,0 +1,13 @@
+//Stubs for Assert used by CharUnicodeInfo pulled in from corert
+namespace System.Globalization
+{
+ public static partial class CharUnicodeInfo
+ {
+ internal static class Debug
+ {
+ internal static void Assert(bool condition, string message)
+ {
+ }
+ }
+ }
+}
diff --git a/mcs/class/corlib/System/Delegate.cs b/mcs/class/corlib/System/Delegate.cs
index 48d78605147..958b70ce816 100644
--- a/mcs/class/corlib/System/Delegate.cs
+++ b/mcs/class/corlib/System/Delegate.cs
@@ -134,6 +134,8 @@ namespace System
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/EnumSharing.cs b/mcs/class/corlib/System/EnumSharing.cs
new file mode 100644
index 00000000000..aa1def33769
--- /dev/null
+++ b/mcs/class/corlib/System/EnumSharing.cs
@@ -0,0 +1,18 @@
+using System;
+
+#if UNITY_AOT
+
+namespace System
+{
+ enum SByteEnum : sbyte {}
+ enum Int16Enum : short {}
+ enum Int32Enum : int {}
+ enum Int64Enum : long {}
+
+ enum ByteEnum : byte {}
+ enum UInt16Enum : ushort {}
+ enum UInt32Enum : uint {}
+ enum UInt64Enum : ulong {}
+}
+
+#endif
diff --git a/mcs/class/corlib/System/TimeZone.cs b/mcs/class/corlib/System/TimeZone.cs
index 1cfa2ee9bcc..b3219535966 100644
--- a/mcs/class/corlib/System/TimeZone.cs
+++ b/mcs/class/corlib/System/TimeZone.cs
@@ -210,5 +210,18 @@ namespace System
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, out bool daylight_inverted);
+#endif
}
}
diff --git a/mcs/class/corlib/System/TimeZoneInfo.Unity.cs b/mcs/class/corlib/System/TimeZoneInfo.Unity.cs
new file mode 100644
index 00000000000..bc79e413993
--- /dev/null
+++ b/mcs/class/corlib/System/TimeZoneInfo.Unity.cs
@@ -0,0 +1,168 @@
+//
+// System.TimeZoneInfo helper for Unity
+// because the devices cannot access the file system to read the data
+//
+// Authors:
+// Michael DeRoy <michaelde@unity3d.com>
+// Jonathan Chambers <jonathan@unity3d.com>
+//
+// 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
+ {
+ DaylightSavingFirstTransitionIdx,
+ DaylightSavingSecondTransitionIdx,
+ UtcOffsetIdx,
+ AdditionalDaylightOffsetIdx
+ };
+
+ enum TimeZoneNames
+ {
+ StandardNameIdx,
+ DaylightNameIdx
+ };
+
+ static List<AdjustmentRule> CreateAdjustmentRule (int year, out Int64[] data, out string[] names, string standardNameCurrentYear, string daylightNameCurrentYear)
+ {
+ List<AdjustmentRule> rulesForYear = new List<AdjustmentRule> ();
+ bool dst_inverted;
+ if (!System.CurrentSystemTimeZone.GetTimeZoneData(year, out data, out names, out dst_inverted))
+ return rulesForYear;
+ var firstTransition = new DateTime (data[(int)TimeZoneData.DaylightSavingFirstTransitionIdx]);
+ var secondTransition = new DateTime (data[(int)TimeZoneData.DaylightSavingSecondTransitionIdx]);
+ 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 rulesForYear;
+ if(daylightNameCurrentYear != names[(int)TimeZoneNames.DaylightNameIdx])
+ return rulesForYear;
+
+ var beginningOfYear = new DateTime (year, 1, 1, 0, 0, 0, 0);
+ var endOfYearDay = new DateTime (year, 12, DateTime.DaysInMonth (year, 12));
+ var endOfYearMaxTimeout = new DateTime (year, 12, DateTime.DaysInMonth(year, 12), 23, 59, 59, 999);
+
+ if (!dst_inverted) {
+ // For daylight savings time that happens between jan and dec, create a rule from jan 1 to dec 31 (the entire year)
+
+ // This rule (for the whole year) specifies the starting and ending months of daylight savings time.
+ var startOfDaylightSavingsTime = TransitionTime.CreateFixedDateRule (new DateTime (1,1,1).Add (firstTransition.TimeOfDay),
+ firstTransition.Month, firstTransition.Day);
+ var endOfDaylightSavingsTime = TransitionTime.CreateFixedDateRule (new DateTime (1,1,1).Add (secondTransition.TimeOfDay),
+ secondTransition.Month, secondTransition.Day);
+
+ var fullYearRule = TimeZoneInfo.AdjustmentRule.CreateAdjustmentRule (beginningOfYear,
+ endOfYearDay,
+ daylightOffset,
+ startOfDaylightSavingsTime,
+ endOfDaylightSavingsTime);
+ rulesForYear.Add (fullYearRule);
+ } else {
+ // Some timezones (Australia/Sydney) have daylight savings over the new year.
+ // Our icall returns the transitions for the current year, so we need two adjustment rules each year for this case
+
+ // The first rule specifies daylight savings starting at jan 1 and ending at the first transition.
+ var startOfFirstDaylightSavingsTime = TransitionTime.CreateFixedDateRule (new DateTime (1,1,1), 1, 1);
+ var endOfFirstDaylightSavingsTime = TransitionTime.CreateFixedDateRule (new DateTime (1,1,1).Add (firstTransition.TimeOfDay),
+ firstTransition.Month, firstTransition.Day);
+
+ var transitionOutOfDaylightSavingsRule = TimeZoneInfo.AdjustmentRule.CreateAdjustmentRule (
+ new DateTime (year, 1, 1),
+ new DateTime (firstTransition.Year, firstTransition.Month, firstTransition.Day),
+ daylightOffset,
+ startOfFirstDaylightSavingsTime,
+ endOfFirstDaylightSavingsTime);
+ rulesForYear.Add (transitionOutOfDaylightSavingsRule);
+
+ // The second rule specifies daylight savings time starting the day after we transition out of daylight savings
+ // and ending at the end of the year, with daylight savings starting near the end and ending on the last day of the year
+ var startOfSecondDaylightSavingsTime = TransitionTime.CreateFixedDateRule (new DateTime (1,1,1).Add (secondTransition.TimeOfDay),
+ secondTransition.Month, secondTransition.Day);
+ var endOfSecondDaylightSavingsTime = TransitionTime.CreateFixedDateRule (new DateTime (1,1,1).Add (endOfYearMaxTimeout.TimeOfDay),
+ endOfYearMaxTimeout.Month, endOfYearMaxTimeout.Day);
+
+ var transitionIntoDaylightSavingsRule = TimeZoneInfo.AdjustmentRule.CreateAdjustmentRule (
+ new DateTime (firstTransition.Year, firstTransition.Month, firstTransition.Day).AddDays (1),
+ endOfYearDay,
+ daylightOffset,
+ startOfSecondDaylightSavingsTime,
+ endOfSecondDaylightSavingsTime);
+ rulesForYear.Add (transitionIntoDaylightSavingsRule);
+ }
+ return rulesForYear;
+ }
+
+ static TimeZoneInfo CreateLocalUnity ()
+ {
+ Int64[] data;
+ string[] names;
+ //Some timezones start in DST on january first and disable it during the summer
+ bool dst_inverted;
+ int currentYear = DateTime.UtcNow.Year;
+ if (!System.CurrentSystemTimeZone.GetTimeZoneData (currentYear, out data, out names, out dst_inverted))
+ 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 adjustmentRulesList = new List<AdjustmentRule> ();
+ 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 rulesForCurrentYear = CreateAdjustmentRule (year, out data, out names, standardDisplayName, daylightDisplayName);
+ //breakout if no more rules
+ if (rulesForCurrentYear.Count > 0)
+ adjustmentRulesList.AddRange (rulesForCurrentYear);
+ else
+ break;
+
+ }
+
+ for (int year = currentYear - 1; year >= firstSupportedDate; year--) {
+ var rulesForCurrentYear = CreateAdjustmentRule (year, out data, out names, standardDisplayName, daylightDisplayName);
+ //breakout if no more rules
+ if (rulesForCurrentYear.Count > 0)
+ adjustmentRulesList.AddRange (rulesForCurrentYear);
+ else
+ break;
+ }
+
+ adjustmentRulesList.Sort ( (rule1, rule2) => rule1.DateStart.CompareTo (rule2.DateStart) );
+ }
+ return TimeZoneInfo.CreateCustomTimeZone ("Local",
+ utcOffsetTS,
+ displayName,
+ standardDisplayName,
+ daylightDisplayName,
+ adjustmentRulesList.ToArray (),
+ disableDaylightSavings);
+ }
+ }
+}
+
+#endif
diff --git a/mcs/class/corlib/System/TimeZoneInfo.cs b/mcs/class/corlib/System/TimeZoneInfo.cs
index a1eaf2a7cf3..d05ff302d81 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 @@ namespace System
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 @@ namespace System
}
#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 @@ namespace System
}
}
+#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 72de431d172..b7a377935d1 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 26c449615b3..19a4bd894dc 100644
--- a/mcs/class/corlib/Test/System/DelegateTest.cs
+++ b/mcs/class/corlib/Test/System/DelegateTest.cs
@@ -1395,6 +1395,23 @@ namespace MonoTests.System
Assert.IsTrue (d (0, 0));
}
+ [Test]
+ public void EnumBaseTypeConversion2 () {
+ Func<Enum22, int> dm = EnumArg;
+ var d = (Func<int, int>)Delegate.CreateDelegate (typeof (Func<int, int>), 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/TimeZoneInfoTest.cs b/mcs/class/corlib/Test/System/TimeZoneInfoTest.cs
index b6384d11162..25adc0c7d0a 100644
--- a/mcs/class/corlib/Test/System/TimeZoneInfoTest.cs
+++ b/mcs/class/corlib/Test/System/TimeZoneInfoTest.cs
@@ -124,13 +124,388 @@ namespace MonoTests.System
} catch (DllNotFoundException e) {
return;
}
-#if !MONOTOUCH && !XAMMAC
+#if !MONOTOUCH && !XAMMAC && !UNITY
// this assumption is incorrect for iOS, tvO, watchOS and OSX
Assert.IsTrue (TimeZoneInfo.Local.Id != "Local", "Local timezone id should not be \"Local\"");
#endif
}
}
+#if UNITY
+ [TestFixture]
+ public class UnityTests
+ {
+ public TimeZoneInfo GetLocalUnity ()
+ {
+ return (TimeZoneInfo)typeof (TimeZoneInfo).GetMethod ("CreateLocalUnity", BindingFlags.NonPublic | BindingFlags.Static).Invoke (null, null);
+ }
+
+ public void AssertNoDLS (TimeZoneInfo local, DateTime beforeDLSStart, DateTime afterDLSStart, DateTime beforeDLSEnd, DateTime afterDLSEnd)
+ {
+ Assert.IsFalse (local.IsDaylightSavingTime(beforeDLSStart), "Expected Not Daylight Savings " + beforeDLSStart.ToString ());
+ Assert.IsFalse (local.IsDaylightSavingTime(afterDLSStart), "Expected Not Daylight Savings " + afterDLSStart.ToString ());
+ Assert.IsFalse (local.IsDaylightSavingTime(beforeDLSEnd), "Expected Not Daylight Savings " + beforeDLSEnd.ToString ());
+ Assert.IsFalse (local.IsDaylightSavingTime(afterDLSEnd), "Expected Not Daylight Savings " + afterDLSEnd.ToString ());
+ }
+
+ public void AssertDLS (TimeZoneInfo local, DateTime beforeDLSStart, DateTime afterDLSStart, DateTime beforeDLSEnd, DateTime afterDLSEnd)
+ {
+ Assert.IsFalse (local.IsDaylightSavingTime (beforeDLSStart), "Expected Not Daylight Savings " + beforeDLSStart.ToString ());
+ Assert.IsTrue (local.IsDaylightSavingTime (afterDLSStart), "Expected Daylight Savings " + afterDLSStart.ToString ());
+ Assert.IsTrue (local.IsDaylightSavingTime (beforeDLSEnd), "Expected Daylight Savings " + beforeDLSEnd.ToString ());
+ Assert.IsFalse (local.IsDaylightSavingTime (afterDLSEnd), "Expected Not Daylight Savings " + afterDLSEnd.ToString ());
+ }
+
+ //Similar to Above but for Timezones that begin in daylight savings time jan 1
+ public void AssertDLSInverse (TimeZoneInfo local, DateTime beforeDLSEnd, DateTime afterDLSEnd, DateTime beforeDLSStart, DateTime afterDLSStart)
+ {
+ Assert.IsTrue (local.IsDaylightSavingTime (beforeDLSEnd), "Expected Daylight Savings " + beforeDLSEnd.ToString ());
+ Assert.IsFalse (local.IsDaylightSavingTime (afterDLSEnd), "Expected Not Daylight Savings " + afterDLSEnd.ToString ());
+ Assert.IsFalse (local.IsDaylightSavingTime (beforeDLSStart), "Expected Not Daylight Savings " + beforeDLSStart.ToString ());
+ Assert.IsTrue (local.IsDaylightSavingTime (afterDLSStart), "Expected Daylight Savings " + afterDLSStart.ToString ());
+ }
+
+ [Test]
+ public void CanGetLocalUnity ()
+ {
+ TimeZoneInfo local = GetLocalUnity ();
+ Assert.IsNotNull (local);
+ Assert.IsTrue (local.Id == "Local");
+ }
+
+ [Test]
+ public void LocalIsNotLocalUnityOnDesktop ()
+ {
+ TimeZoneInfo local = GetLocalUnity ();
+ Assert.IsNotNull (local);
+ Assert.AreNotEqual (local, TimeZoneInfo.Local);
+ }
+
+ [Test]
+ public void EST ()
+ {
+ Environment.SetEnvironmentVariable ("TZ", "America/New_York");
+ TimeZoneInfo local = GetLocalUnity ();
+
+ Assert.IsNotNull (local);
+ Assert.AreEqual ("-05:00:00", local.BaseUtcOffset.ToString ());
+ Assert.AreEqual ("Local", local.Id);
+ Assert.AreEqual ("EST", local.StandardName);
+ Assert.AreEqual ("EDT", local.DaylightName);
+ Assert.IsTrue (local.SupportsDaylightSavingTime);
+ Assert.AreEqual ("(GMT-05:00) Local Time", local.DisplayName);
+
+ var UTCInStandardMonth = new DateTime (2018,2,5,11,22,56);
+ var StandardTimeConverted = TimeZoneInfo.ConvertTimeFromUtc (UTCInStandardMonth, local);
+ Assert.AreEqual(6, StandardTimeConverted.Hour);
+
+ var UTCInDaylightMonth = new DateTime (2018,7,5,11,22,56);
+ var DaylightTimeConverted = TimeZoneInfo.ConvertTimeFromUtc (UTCInDaylightMonth, local);
+ Assert.AreEqual (7, DaylightTimeConverted.Hour);
+
+ //Before DLS Supported Year
+ AssertNoDLS (local,
+ new DateTime (1970,4,25),
+ new DateTime (1970,4,27),
+ new DateTime (1970,10,24),
+ new DateTime (1970,10,26)
+ );
+
+ //First DLS Supported Year
+ AssertDLS (local,
+ new DateTime (1971,4,24),
+ new DateTime (1971,4,26),
+ new DateTime (1971,10,30),
+ new DateTime (1971,11,1)
+ );
+
+ //Near current year
+ AssertDLS (local,
+ new DateTime (2018,3,10),
+ new DateTime (2018,3,12),
+ new DateTime (2018,11,3),
+ new DateTime (2018,11,5)
+ );
+
+ //Last DLS Supported Year
+ AssertDLS (local,
+ new DateTime (2037,3,7),
+ new DateTime (2037,3,9),
+ new DateTime (2037,10,30),
+ new DateTime (2037,11,2)
+ );
+
+ //After Last DLS Supported Year
+ AssertNoDLS (local,
+ new DateTime (2038,2,1),
+ new DateTime (2038,5,1),
+ new DateTime (2038,6,1),
+ new DateTime (2038,12,1)
+ );
+ }
+
+ [Test]
+ public void PST ()
+ {
+ Environment.SetEnvironmentVariable ("TZ", "America/Los_Angeles");
+ TimeZoneInfo local = GetLocalUnity ();
+
+ Assert.IsNotNull (local);
+ Assert.AreEqual ("-08:00:00", local.BaseUtcOffset.ToString ());
+ Assert.AreEqual ("Local", local.Id);
+ Assert.AreEqual ("PST", local.StandardName);
+ Assert.AreEqual ("PDT", local.DaylightName);
+ Assert.IsTrue (local.SupportsDaylightSavingTime);
+ Assert.AreEqual ("(GMT-08:00) Local Time", local.DisplayName);
+
+ var UTCInStandardMonth = new DateTime (2018,2,5,11,22,56);
+ var StandardTimeConverted = TimeZoneInfo.ConvertTimeFromUtc (UTCInStandardMonth, local);
+ Assert.AreEqual (3, StandardTimeConverted.Hour);
+
+ var UTCInDaylightMonth = new DateTime (2018,7,5,11,22,56);
+ var DaylightTimeConverted = TimeZoneInfo.ConvertTimeFromUtc (UTCInDaylightMonth, local);
+ Assert.AreEqual (4, DaylightTimeConverted.Hour);
+
+ //Before DLS Supported Year
+ AssertNoDLS (local,
+ new DateTime (1970,4,25),
+ new DateTime (1970,4,27),
+ new DateTime (1970,10,24),
+ new DateTime (1970,10,26)
+ );
+
+ //First DLS Supported Year
+ AssertDLS (local,
+ new DateTime (1971,4,24),
+ new DateTime (1971,4,26),
+ new DateTime (1971,10,30),
+ new DateTime (1971,11,1)
+ );
+
+ //Near current year
+ AssertDLS (local,
+ new DateTime (2018,3,10),
+ new DateTime (2018,3,12),
+ new DateTime (2018,11,3),
+ new DateTime (2018,11,5)
+ );
+
+ //Last DLS Supported Year
+ AssertDLS (local,
+ new DateTime (2037,3,7),
+ new DateTime (2037,3,9),
+ new DateTime (2037,10,30),
+ new DateTime (2037,11,2)
+ );
+
+ //After Last DLS Supported Year
+ AssertNoDLS (local,
+ new DateTime (2038,2,1),
+ new DateTime (2038,5,1),
+ new DateTime (2038,6,1),
+ new DateTime (2038,12,1)
+ );
+ }
+
+ [Test]
+ public void MST_Arizona ()
+ {
+ //Arizona is special in that there hasn't been daylight savings since 1967 (before our first supported year)
+ Environment.SetEnvironmentVariable ("TZ", "America/Phoenix");
+ TimeZoneInfo local = GetLocalUnity ();
+ Assert.IsNotNull (local);
+ Assert.AreEqual ("-07:00:00", local.BaseUtcOffset.ToString ());
+ Assert.AreEqual ("Local", local.Id);
+ Assert.AreEqual ("MST", local.StandardName);
+ Assert.AreEqual ("", local.DaylightName);
+ Assert.IsFalse (local.SupportsDaylightSavingTime);
+ Assert.AreEqual ("(GMT-07:00) Local Time", local.DisplayName);
+
+ var UTCInStandardMonth = new DateTime (2018,2,5,11,22,56);
+ var StandardTimeConverted = TimeZoneInfo.ConvertTimeFromUtc (UTCInStandardMonth, local);
+ Assert.AreEqual (4, StandardTimeConverted.Hour);
+ }
+
+ [Test]
+ public void EET_Egypt ()
+ {
+ //Egypt is special in that it stopped doing daylight savings in 2014 (after our first supported year)
+ Environment.SetEnvironmentVariable ("TZ", "Egypt");
+ TimeZoneInfo local = GetLocalUnity ();
+ Assert.IsNotNull (local);
+ Assert.AreEqual ("02:00:00", local.BaseUtcOffset.ToString ());
+ Assert.AreEqual ("Local", local.Id);
+ Assert.AreEqual ("EET", local.StandardName);
+ Assert.AreEqual ("", local.DaylightName);
+ Assert.IsFalse (local.SupportsDaylightSavingTime);
+ Assert.AreEqual ("(GMT+02:00) Local Time", local.DisplayName);
+
+ var UTCInStandardMonth = new DateTime (2018,2,5,11,22,56);
+ var StandardTimeConverted = TimeZoneInfo.ConvertTimeFromUtc (UTCInStandardMonth, local);
+ Assert.AreEqual (13, StandardTimeConverted.Hour);
+ }
+
+ [Test]
+ public void MSK_Crimea ()
+ {
+ //Crimea is special, because they switched form EET(with dls) to MSK (without dls) due to world conflicts in 2014
+ //C# timezoneinfo class only supports a single utc offset and transition times only account for daylight savings changes.
+ //In this case, it will display MSK with no support for daylight savings
+ Environment.SetEnvironmentVariable ("TZ", "Europe/Simferopol");
+ TimeZoneInfo local = GetLocalUnity ();
+ Assert.IsNotNull (local);
+ Assert.AreEqual ("03:00:00", local.BaseUtcOffset.ToString ());
+ Assert.AreEqual ("Local", local.Id);
+ Assert.AreEqual ("MSK", local.StandardName);
+ Assert.AreEqual ("", local.DaylightName);
+ Assert.IsFalse (local.SupportsDaylightSavingTime);
+ Assert.AreEqual ("(GMT+03:00) Local Time", local.DisplayName);
+
+ var UTCInStandardMonth = new DateTime (2018,2,5,11,22,56);
+ var StandardTimeConverted = TimeZoneInfo.ConvertTimeFromUtc (UTCInStandardMonth, local);
+ Assert.AreEqual (14, StandardTimeConverted.Hour);
+ }
+
+ [Test]
+ public void SA_Samoa ()
+ {
+ //Samoa is special, switched form -10/-11 to +13/+14 in 2011...The Timezoneinfo class only supports a single base utcoffset so
+ //years before 2011 will not have daylight savings information
+ Environment.SetEnvironmentVariable ("TZ", "Pacific/Apia");
+ TimeZoneInfo local = GetLocalUnity ();
+ Assert.IsNotNull (local);
+ Assert.AreEqual ("13:00:00", local.BaseUtcOffset.ToString ());
+ Assert.AreEqual ("Local", local.Id);
+ Assert.AreEqual ("+13", local.StandardName);
+ Assert.AreEqual ("+14", local.DaylightName);
+ Assert.IsTrue (local.SupportsDaylightSavingTime);
+ Assert.AreEqual ("(GMT+13:00) Local Time", local.DisplayName);
+
+ var UTCInStandardMonth = new DateTime (2018,4,5,1,22,56);
+ var StandardTimeConverted = TimeZoneInfo.ConvertTimeFromUtc (UTCInStandardMonth, local);
+ Assert.AreEqual (14, StandardTimeConverted.Hour);
+
+ var UTCInDaylightMonth = new DateTime (2018,11,5,1,22,56);
+ var DaylightTimeConverted = TimeZoneInfo.ConvertTimeFromUtc (UTCInDaylightMonth, local);
+ Assert.AreEqual (15, DaylightTimeConverted.Hour);
+
+ //2011 transitioned from utc -10 to utc +14...since we switched timezones in this year, we shouldn't have any DLS info for this year and prior
+ AssertNoDLS (local,
+ new DateTime (2011,4,1),
+ new DateTime (2011,4,3),
+ new DateTime (2011,12,28),
+ new DateTime (2011,12,31)
+ );
+ AssertNoDLS (local,
+ new DateTime (2010,9,24),
+ new DateTime (2010,9,26),
+ new DateTime (2010,12,28),
+ new DateTime (2010,12,31)
+ );
+
+ //Near current year
+ AssertDLSInverse (local,
+ new DateTime (2018,3,31),
+ new DateTime (2018,4,2),
+ new DateTime (2018,9,29),
+ new DateTime (2018,10,1)
+ );
+ }
+
+ [Test]
+ public void AEST ()
+ {
+ //Timezone that begins Jan 1 in DLS time
+ Environment.SetEnvironmentVariable ("TZ", "Australia/Sydney");
+ TimeZoneInfo local = GetLocalUnity ();
+ Assert.IsNotNull (local);
+ Assert.AreEqual ("10:00:00", local.BaseUtcOffset.ToString ());
+ Assert.AreEqual ("Local", local.Id);
+ Assert.AreEqual ("AEST", local.StandardName);
+ Assert.AreEqual ("AEDT", local.DaylightName);
+ Assert.IsTrue (local.SupportsDaylightSavingTime);
+ Assert.AreEqual ("(GMT+10:00) Local Time", local.DisplayName);
+ Assert.IsTrue (local.GetAdjustmentRules ().Length > 0);
+
+ var UTCInStandardMonth = new DateTime (2018,5,5,11,22,56);
+ var StandardTimeConverted = TimeZoneInfo.ConvertTimeFromUtc (UTCInStandardMonth, local);
+ Assert.AreEqual (21, StandardTimeConverted.Hour);
+
+ var UTCInDaylightMonth = new DateTime (2018,1,5,11,22,56);
+ var DaylightTimeConverted = TimeZoneInfo.ConvertTimeFromUtc (UTCInDaylightMonth, local);
+ Assert.AreEqual (22, DaylightTimeConverted.Hour);
+
+ //Before DLS Supported Year
+ AssertNoDLS (local,
+ new DateTime (1970,4,25),
+ new DateTime (1970,4,27),
+ new DateTime (1970,10,24),
+ new DateTime (1970,10,26)
+ );
+
+ //First DLS Supported Year...Austrialia did not start DLS until oct of 71
+ AssertNoDLS (local,
+ new DateTime (1971,10,30),
+ new DateTime (1971,11,1),
+ new DateTime (1971,2,26),
+ new DateTime (1971,2,28)
+ );
+
+ AssertDLSInverse (local,
+ new DateTime (1972,2,26),
+ new DateTime (1972,2,28),
+ new DateTime (1972,10,28),
+ new DateTime (1972,10,30)
+ );
+
+ //Near current year
+ AssertDLSInverse (local,
+ new DateTime (2018,3,31),
+ new DateTime (2018,4,2),
+ new DateTime (2018,10,6),
+ new DateTime (2018,10,8)
+ );
+
+ //Last DLS Supported Year
+ AssertDLSInverse (local,
+ new DateTime (2037,4,4),
+ new DateTime (2037,4,6),
+ new DateTime (2037,10,3),
+ new DateTime (2037,10,5)
+ );
+
+ //After Last DLS Supported Year
+ AssertNoDLS (local,
+ new DateTime (2038,2,1),
+ new DateTime (2038,5,1),
+ new DateTime (2038,6,1),
+ new DateTime (2038,12,1)
+ );
+ }
+
+ [Test]
+ public void Singapore ()
+ {
+ //Singapore changes it's timezone from +0730 to +08...use the latest offsets
+ Environment.SetEnvironmentVariable ("TZ", "Asia/Singapore");
+ TimeZoneInfo local = GetLocalUnity ();
+ Assert.IsNotNull (local);
+
+ Assert.AreEqual ("08:00:00", local.BaseUtcOffset.ToString ());
+ Assert.AreEqual ("Local", local.Id);
+ Assert.AreEqual ("+08", local.StandardName);
+ Assert.AreEqual ("", local.DaylightName);
+ Assert.IsFalse (local.SupportsDaylightSavingTime);
+ Assert.AreEqual ("(GMT+08:00) Local Time", local.DisplayName);
+
+ var UTCInStandardMonth = new DateTime (2018,5,5,11,22,56);
+ var StandardTimeConverted = TimeZoneInfo.ConvertTimeFromUtc (UTCInStandardMonth, local);
+ Assert.AreEqual (19, StandardTimeConverted.Hour);
+ }
+
+ }
+#endif
+
[TestFixture]
public class CreateCustomTimezoneTests
{
diff --git a/mcs/class/corlib/Test/System/TypeTest.cs b/mcs/class/corlib/Test/System/TypeTest.cs
index 6608ef9cc43..2c9bd2728af 100644
--- a/mcs/class/corlib/Test/System/TypeTest.cs
+++ b/mcs/class/corlib/Test/System/TypeTest.cs
@@ -4886,6 +4886,30 @@ namespace MonoTests.System
}
}
+ // https://github.com/mono/mono/issues/6579
+ [Test]
+ public void GetInterfaceCaseInsensitiveTest()
+ {
+ var type = typeof(Dictionary<string, object>);
+
+ 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<T> {
}
diff --git a/mcs/class/corlib/corlib.dll.sources b/mcs/class/corlib/corlib.dll.sources
index fa940530add..bd2fd295fdc 100644
--- a/mcs/class/corlib/corlib.dll.sources
+++ b/mcs/class/corlib/corlib.dll.sources
@@ -104,6 +104,7 @@ System/Delegate.cs
System/DelegateSerializationHolder.cs
System/DomainManagerInitializationFlags.cs
System/EmptyArray.cs
+System/EnumSharing.cs
System/Environment.cs
System/EnvironmentVariableTarget.cs
System/Guid.cs
@@ -142,6 +143,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
@@ -1110,7 +1112,9 @@ ReferenceSources/AppContextDefaultValues.cs
../referencesource/mscorlib/system/globalization/CalendricalCalculationsHelper.cs
../referencesource/mscorlib/system/globalization/calendardata.cs
../referencesource/mscorlib/system/globalization/calendarweekrule.cs
-../referencesource/mscorlib/system/globalization/charunicodeinfo.cs
+System/Debug.cs
+../../../external/corert/src/System.Private.CoreLib/src/System/Globalization/CharUnicodeInfo.cs
+../../../external/corert/src/System.Private.CoreLib/src/System/Globalization/CharUnicodeInfoData.cs
../referencesource/mscorlib/system/globalization/chineselunisolarcalendar.cs
../referencesource/mscorlib/system/globalization/compareinfo.cs
../referencesource/mscorlib/system/globalization/culturenotfoundexception.cs
diff --git a/mcs/class/referencesource/System.Core/System/Linq/Enumerable.cs b/mcs/class/referencesource/System.Core/System/Linq/Enumerable.cs
index 84a04355718..91fdedb40f9 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 @@ namespace System.Linq
{
get
{
+#if UNITY_AOT
+ return SR.EmptyEnumerable;
+#else
return Strings.EmptyEnumerable;
+#endif
}
}
}
@@ -2829,4 +2833,49 @@ namespace System.Linq
[System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.Never)]
private int count;
}
+
+#if UNITY_AOT
+ // <summary>
+ /// An iterator that can produce an array or <see cref="List{TElement}"/> through an optimized path.
+ /// </summary>
+ internal interface IIListProvider<TElement> : IEnumerable<TElement>
+ {
+ /// <summary>
+ /// Produce an array of the sequence through an optimized path.
+ /// </summary>
+ /// <returns>The array.</returns>
+ TElement[] ToArray();
+
+ /// <summary>
+ /// Produce a <see cref="List{TElement}"/> of the sequence through an optimized path.
+ /// </summary>
+ /// <returns>The <see cref="List{TElement}"/>.</returns>
+ List<TElement> ToList();
+
+ /// <summary>
+ /// Returns the count of elements in the sequence.
+ /// </summary>
+ /// <param name="onlyIfCheap">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.</param>
+ /// <returns>The number of elements.</returns>
+ 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 5b5c81384b8..8bfb15ee1d3 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 @@ namespace System.Diagnostics {
}
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/net/System/Net/UnicodeDecodingConformance.cs b/mcs/class/referencesource/System/net/System/Net/UnicodeDecodingConformance.cs
index 5b4ce450211..2441d13b665 100644
--- a/mcs/class/referencesource/System/net/System/Net/UnicodeDecodingConformance.cs
+++ b/mcs/class/referencesource/System/net/System/Net/UnicodeDecodingConformance.cs
@@ -16,7 +16,7 @@ namespace System.Net.Configuration
/// See http://www.w3.org/International/questions/qa-escapes#bytheway for more information
/// on how Unicode characters in the SMP are supposed to be encoded in HTML.
/// </remarks>
-#if !MOBILE
+#if !MOBILE || UNITY_AOT
public
#endif
enum UnicodeDecodingConformance
diff --git a/mcs/class/referencesource/System/net/System/Net/UnicodeEncodingConformance.cs b/mcs/class/referencesource/System/net/System/Net/UnicodeEncodingConformance.cs
index 7ac444e1a16..670954cca7a 100644
--- a/mcs/class/referencesource/System/net/System/Net/UnicodeEncodingConformance.cs
+++ b/mcs/class/referencesource/System/net/System/Net/UnicodeEncodingConformance.cs
@@ -16,7 +16,7 @@ namespace System.Net.Configuration
/// See http://www.w3.org/International/questions/qa-escapes#bytheway for more information
/// on how Unicode characters in the SMP are supposed to be encoded in HTML.
/// </remarks>
-#if !MOBILE
+#if !MOBILE || UNITY_AOT
public
#endif
enum UnicodeEncodingConformance
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 4fc2f7c2078..10fb4ffe220 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 @@ namespace System.Diagnostics {
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 85d996b827a..c774c51d173 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 @@ namespace System.Diagnostics {
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 94fa2f43bbd..80e77f748dd 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 @@ namespace System.Diagnostics {
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/collections/generic/list.cs b/mcs/class/referencesource/mscorlib/system/collections/generic/list.cs
index 44210ced5e3..2c68adc1838 100644
--- a/mcs/class/referencesource/mscorlib/system/collections/generic/list.cs
+++ b/mcs/class/referencesource/mscorlib/system/collections/generic/list.cs
@@ -732,9 +732,13 @@ namespace System.Collections.Generic {
Array.Copy(_items, index+count, _items, index*2, _size-index);
}
else {
+#if MONO
+ c.CopyTo(_items, index);
+#else
T[] itemsToInsert = new T[count];
c.CopyTo(itemsToInsert, 0);
itemsToInsert.CopyTo(_items, index);
+#endif
}
_size += count;
}
diff --git a/mcs/class/referencesource/mscorlib/system/reflection/binder.cs b/mcs/class/referencesource/mscorlib/system/reflection/binder.cs
index 3d14d37f29c..dd8d60f2f50 100644
--- a/mcs/class/referencesource/mscorlib/system/reflection/binder.cs
+++ b/mcs/class/referencesource/mscorlib/system/reflection/binder.cs
@@ -52,7 +52,7 @@ namespace System.Reflection {
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 61b46433b34..42a445bc5cf 100644
--- a/mcs/class/referencesource/mscorlib/system/rttype.cs
+++ b/mcs/class/referencesource/mscorlib/system/rttype.cs
@@ -3413,9 +3413,12 @@ namespace System
#if MONO
List<RuntimeType> 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<RuntimeType> (2);
diff --git a/mcs/class/referencesource/mscorlib/system/runtime/interopservices/attributes.cs b/mcs/class/referencesource/mscorlib/system/runtime/interopservices/attributes.cs
index a970216007b..1c5f52bcbb2 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 15a0c70d64d..9ef7580c9e3 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 @@ namespace System.Runtime.InteropServices.WindowsRuntime
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 98e2f3fb73e..4c5290eb74a 100644
--- a/mcs/class/referencesource/mscorlib/system/threading/synchronizationcontext.cs
+++ b/mcs/class/referencesource/mscorlib/system/threading/synchronizationcontext.cs
@@ -252,7 +252,7 @@ namespace System.Threading
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 ef7472f5016..1f337f0c1fe 100644
--- a/mcs/class/referencesource/mscorlib/system/type.cs
+++ b/mcs/class/referencesource/mscorlib/system/type.cs
@@ -1249,7 +1249,7 @@ namespace System {
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 @@ namespace System {
// 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 0e45b1a9049..c9e05589e4d 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 c9ed9317350..54902e03e7b 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/assembly.cs b/mcs/mcs/assembly.cs
index aa4c54317a2..96e43e70d99 100644
--- a/mcs/mcs/assembly.cs
+++ b/mcs/mcs/assembly.cs
@@ -554,7 +554,8 @@ namespace Mono.CSharp
if (prop != null) {
AttributeEncoder encoder = new AttributeEncoder ();
encoder.EncodeNamedPropertyArgument (prop, new BoolLiteral (Compiler.BuiltinTypes, true, Location.Null));
- SetCustomAttribute (pa.Constructor, encoder.ToArray ());
+ SetCustomAttribute (pa.Constructor, encoder.ToArray (out var references));
+ module.AddAssemblyReferences (references);
}
}
}
diff --git a/mcs/mcs/attribute.cs b/mcs/mcs/attribute.cs
index 4f520b7487e..669a9927d0d 100644
--- a/mcs/mcs/attribute.cs
+++ b/mcs/mcs/attribute.cs
@@ -1053,8 +1053,10 @@ namespace Mono.CSharp {
}
byte[] cdata;
+ List<Assembly> references;
if (pos_args == null && named_values == null) {
cdata = AttributeEncoder.Empty;
+ references = null;
} else {
AttributeEncoder encoder = new AttributeEncoder ();
@@ -1127,7 +1129,7 @@ namespace Mono.CSharp {
encoder.EncodeEmptyNamedArguments ();
}
- cdata = encoder.ToArray ();
+ cdata = encoder.ToArray (out references);
}
if (!IsConditionallyExcluded (ctor.DeclaringType)) {
@@ -1146,6 +1148,8 @@ namespace Mono.CSharp {
Error_AttributeEmitError (e.Message);
return;
}
+
+ context.Module.AddAssemblyReferences (references);
}
if (!usage_attr.AllowMultiple && allEmitted != null) {
@@ -1404,6 +1408,7 @@ namespace Mono.CSharp {
byte[] buffer;
int pos;
const ushort Version = 1;
+ List<Assembly> imports;
static AttributeEncoder ()
{
@@ -1583,7 +1588,15 @@ namespace Mono.CSharp {
public void EncodeTypeName (TypeSpec type)
{
var old_type = type.GetMetaInfo ();
- Encode (type.MemberDefinition.IsImported ? old_type.AssemblyQualifiedName : old_type.FullName);
+ if (type.MemberDefinition.IsImported) {
+ if (imports == null)
+ imports = new List<Assembly> ();
+
+ imports.Add (old_type.Assembly);
+ Encode (old_type.AssemblyQualifiedName);
+ } else {
+ Encode (old_type.FullName);
+ }
}
public void EncodeTypeName (TypeContainer type)
@@ -1664,8 +1677,10 @@ namespace Mono.CSharp {
Encode (value);
}
- public byte[] ToArray ()
+ public byte[] ToArray (out List<Assembly> assemblyReferences)
{
+ assemblyReferences = imports;
+
byte[] buf = new byte[pos];
Array.Copy (buffer, buf, pos);
return buf;
@@ -1977,7 +1992,8 @@ namespace Mono.CSharp {
encoder.Encode ((int) state);
encoder.EncodeEmptyNamedArguments ();
- builder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), encoder.ToArray ());
+ builder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), encoder.ToArray (out var references));
+ module.AddAssemblyReferences (references);
}
}
@@ -2011,7 +2027,8 @@ namespace Mono.CSharp {
encoder.Encode ((int) modes);
encoder.EncodeEmptyNamedArguments ();
- builder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), encoder.ToArray ());
+ builder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), encoder.ToArray (out var references));
+ module.AddAssemblyReferences (references);
}
}
@@ -2037,7 +2054,8 @@ namespace Mono.CSharp {
encoder.Encode ((uint) bits[0]);
encoder.EncodeEmptyNamedArguments ();
- builder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), encoder.ToArray ());
+ builder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), encoder.ToArray (out var references));
+ module.AddAssemblyReferences (references);
}
public void EmitAttribute (FieldBuilder builder, decimal value, Location loc)
@@ -2055,7 +2073,8 @@ namespace Mono.CSharp {
encoder.Encode ((uint) bits[0]);
encoder.EncodeEmptyNamedArguments ();
- builder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), encoder.ToArray ());
+ builder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), encoder.ToArray (out var references));
+ module.AddAssemblyReferences (references);
}
}
@@ -2079,7 +2098,8 @@ namespace Mono.CSharp {
encoder.EncodeTypeName (type);
encoder.EncodeEmptyNamedArguments ();
- builder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), encoder.ToArray ());
+ builder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), encoder.ToArray (out var references));
+ module.AddAssemblyReferences (references);
}
}
diff --git a/mcs/mcs/class.cs b/mcs/mcs/class.cs
index da3ec32d6fb..a2ef29f206c 100644
--- a/mcs/mcs/class.cs
+++ b/mcs/mcs/class.cs
@@ -2105,7 +2105,8 @@ namespace Mono.CSharp
encoder.Encode (GetAttributeDefaultMember ());
encoder.EncodeEmptyNamedArguments ();
- TypeBuilder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), encoder.ToArray ());
+ TypeBuilder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), encoder.ToArray (out var references));
+ Module.AddAssemblyReferences (references);
}
public override void VerifyMembers ()
diff --git a/mcs/mcs/convert.cs b/mcs/mcs/convert.cs
index f4012fbd222..2fd5bcc5585 100644
--- a/mcs/mcs/convert.cs
+++ b/mcs/mcs/convert.cs
@@ -1232,6 +1232,13 @@ namespace Mono.CSharp {
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/mcs/field.cs b/mcs/mcs/field.cs
index 86bb028defc..8c667328143 100644
--- a/mcs/mcs/field.cs
+++ b/mcs/mcs/field.cs
@@ -542,7 +542,7 @@ namespace Mono.CSharp
}
);
- fixed_buffer_type.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), encoder.ToArray ());
+ fixed_buffer_type.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), encoder.ToArray (out _));
#endif
//
// Don't emit FixedBufferAttribute attribute for private types
@@ -559,7 +559,8 @@ namespace Mono.CSharp
encoder.Encode (buffer_size);
encoder.EncodeEmptyNamedArguments ();
- FieldBuilder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), encoder.ToArray ());
+ FieldBuilder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), encoder.ToArray (out var references));
+ Module.AddAssemblyReferences (references);
}
}
diff --git a/mcs/mcs/module.cs b/mcs/mcs/module.cs
index 00afac6c604..f990325e137 100644
--- a/mcs/mcs/module.cs
+++ b/mcs/mcs/module.cs
@@ -472,6 +472,18 @@ namespace Mono.CSharp
attributes.AddAttribute (attr);
}
+ public void AddAssemblyReferences (List<Assembly> names)
+ {
+ if (names == null)
+ return;
+
+#if STATIC
+ foreach (var name in names) {
+ Builder.__GetAssemblyToken (name);
+ }
+#endif
+ }
+
public override void AddTypeContainer (TypeContainer tc)
{
AddTypeContainerMember (tc);
diff --git a/mcs/tests/gtest-647.cs b/mcs/tests/gtest-647.cs
new file mode 100644
index 00000000000..4aae641f85f
--- /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 3d4d271f3db..4180824c10d 100644
--- a/mcs/tests/ver-il-net_4_x.xml
+++ b/mcs/tests/ver-il-net_4_x.xml
@@ -11064,7 +11064,7 @@
</type>
<type name="X">
<method name="Int32 Beer(System.Nullable`1[IrishPub])" attrs="145">
- <size>72</size>
+ <size>60</size>
</method>
<method name="Int32 Test(System.Nullable`1[System.Int32])" attrs="145">
<size>62</size>
@@ -19505,7 +19505,7 @@
</type>
<type name="C">
<method name="Int32 Main()" attrs="150">
- <size>267</size>
+ <size>255</size>
</method>
<method name="Void .ctor()" attrs="6278">
<size>7</size>
@@ -20144,6 +20144,21 @@
</method>
</type>
</test>
+ <test name="gtest-647.cs">
+ <type name="Program">
+ <method name="Int32 Main()" attrs="150">
+ <size>99</size>
+ </method>
+ <method name="Void .ctor()" attrs="6278">
+ <size>7</size>
+ </method>
+ </type>
+ <type name="Program+MyStruct">
+ <method name="Int32 op_Implicit(System.Nullable`1[Program+MyStruct])" attrs="2198">
+ <size>22</size>
+ </method>
+ </type>
+ </test>
<test name="gtest-anontype-01.cs">
<type name="Test">
<method name="Int32 Main()" attrs="150">
diff --git a/mono/arch/arm64/arm64-codegen.h b/mono/arch/arm64/arm64-codegen.h
index 0156b110c06..9bee5485214 100644
--- a/mono/arch/arm64/arm64-codegen.h
+++ b/mono/arch/arm64/arm64-codegen.h
@@ -170,7 +170,7 @@ arm_is_bl_disp (void *code, void *target)
static G_GNUC_UNUSED inline unsigned int
arm_get_disp (void *p, void *target)
{
- unsigned int disp = ((char*)target - (char*)p) / 4;
+ unsigned int disp = (unsigned int)(((char*)target - (char*)p) / 4);
if (target)
g_assert (arm_is_bl_disp (p, target));
@@ -196,7 +196,7 @@ arm_is_disp19 (void *code, void *target)
static G_GNUC_UNUSED inline unsigned int
arm_get_disp19 (void *p, void *target)
{
- unsigned int disp = ((char*)target - (char*)p) / 4;
+ unsigned int disp = (unsigned int)(((char*)target - (char*)p) / 4);
if (target)
g_assert (arm_is_disp19 (p, target));
@@ -224,7 +224,7 @@ arm_get_disp19 (void *p, void *target)
static G_GNUC_UNUSED inline unsigned int
arm_get_disp15 (void *p, void *target)
{
- unsigned int disp = ((char*)target - (char*)p) / 4;
+ unsigned int disp = (unsigned int)(((char*)target - (char*)p) / 4);
return (disp & 0x7fff);
}
diff --git a/mono/eglib/gdate-unity.c b/mono/eglib/gdate-unity.c
new file mode 100644
index 00000000000..c25eda90920
--- /dev/null
+++ b/mono/eglib/gdate-unity.c
@@ -0,0 +1,8 @@
+#include <glib.h>
+#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 00000000000..a3d8eec30e9
--- /dev/null
+++ b/mono/eglib/gdir-unity.c
@@ -0,0 +1,134 @@
+#include <glib.h>
+
+#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 00000000000..c7c6edf232f
--- /dev/null
+++ b/mono/eglib/gfile-unity.c
@@ -0,0 +1,107 @@
+#include <config.h>
+#include <glib.h>
+#include <errno.h>
+
+#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 333639f677a..4babfcede50 100644
--- a/mono/eglib/glib.h
+++ b/mono/eglib/glib.h
@@ -14,7 +14,11 @@
#endif
#include <stdint.h>
+
+/* inttypes.h is only available from VS2013 */
+#if !defined(_MSC_VER) || (_MSC_VER >= 1800)
#include <inttypes.h>
+#endif
#include <eglib-config.h>
#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
/*
@@ -230,6 +238,9 @@ gint g_vasprintf (gchar **ret, const gchar *fmt, va_list ap);
#define g_vsprintf vsprintf
#define g_vsnprintf vsnprintf
+typedef void (*vprintf_func)(const char* msg, va_list args);
+void set_vprintf_func(vprintf_func func);
+
gsize g_strlcpy (gchar *dest, const gchar *src, gsize dest_size);
gchar *g_stpcpy (gchar *dest, const char *src);
@@ -881,7 +892,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 00000000000..b1d32812e74
--- /dev/null
+++ b/mono/eglib/gmisc-unity.c
@@ -0,0 +1,77 @@
+#include <stdlib.h>
+#include <glib.h>
+
+#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/goutput.c b/mono/eglib/goutput.c
index e785170621c..1e293362550 100644
--- a/mono/eglib/goutput.c
+++ b/mono/eglib/goutput.c
@@ -36,6 +36,8 @@ static GLogLevelFlags fatal = G_LOG_LEVEL_ERROR;
static GLogFunc default_log_func;
static gpointer default_log_func_user_data;
static GPrintFunc stdout_handler, stderr_handler;
+typedef void (*vprintf_func)(const char* msg, va_list args);
+static vprintf_func our_vprintf = vprintf;
static void default_stdout_handler (const gchar *string);
static void default_stderr_handler (const gchar *string);
@@ -274,3 +276,31 @@ g_set_printerr_handler (GPrintFunc func)
return old;
}
+void wrap_our_vprintf(const gchar *format, ...)
+{
+ va_list args;
+ va_start (args, format);
+ our_vprintf (format, args);
+ va_end (args);
+}
+
+static void
+unity_vprintf_GPrintFunc_adapter (const gchar *string)
+{
+ wrap_our_vprintf ("%s", string);
+}
+
+static void
+unity_vprintf_GLogFunc_adapter (const gchar *log_domain, GLogLevelFlags log_level, const gchar *message, gpointer user_data)
+{
+ wrap_our_vprintf ("%s", message);
+}
+
+// Redirect all stdout output to unity vprintf function
+void set_vprintf_func(vprintf_func func)
+{
+ our_vprintf = func;
+ g_set_print_handler (unity_vprintf_GPrintFunc_adapter);
+ g_log_set_default_handler (unity_vprintf_GLogFunc_adapter, NULL);
+}
+
diff --git a/mono/eglib/gpath.c b/mono/eglib/gpath.c
index 21e77704603..01113ee0ce6 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 ef36ffc17f5..359ed245843 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 a35cfcd48c1..993583629ca 100644
--- a/mono/eglib/gunicode-win32.c
+++ b/mono/eglib/gunicode-win32.c
@@ -7,7 +7,7 @@
#include <config.h>
#include <glib.h>
-#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 <windows.h>
@@ -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 1ea96434ef5..c0e5065842f 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 304432e39c3..db8304213e6 100644
--- a/mono/metadata/appdomain.c
+++ b/mono/metadata/appdomain.c
@@ -198,6 +198,7 @@ create_domain_objects (MonoDomain *domain)
mono_error_assert_ok (&error);
mono_field_static_set_value (string_vt, string_empty_fld, empty_str);
domain->empty_string = empty_str;
+ mono_gc_wbarrier_generic_nostore (&domain->empty_string);
/*
* Create an instance early since we can't do it when there is no memory.
@@ -205,6 +206,7 @@ create_domain_objects (MonoDomain *domain)
arg = mono_string_new_checked (domain, "Out of memory", &error);
mono_error_assert_ok (&error);
domain->out_of_memory_ex = mono_exception_from_name_two_strings_checked (mono_defaults.corlib, "System", "OutOfMemoryException", arg, NULL, &error);
+ mono_gc_wbarrier_generic_nostore (&domain->out_of_memory_ex);
mono_error_assert_ok (&error);
/*
@@ -214,14 +216,17 @@ create_domain_objects (MonoDomain *domain)
arg = mono_string_new_checked (domain, "A null value was found where an object instance was required", &error);
mono_error_assert_ok (&error);
domain->null_reference_ex = mono_exception_from_name_two_strings_checked (mono_defaults.corlib, "System", "NullReferenceException", arg, NULL, &error);
+ mono_gc_wbarrier_generic_nostore (&domain->null_reference_ex);
mono_error_assert_ok (&error);
arg = mono_string_new_checked (domain, "The requested operation caused a stack overflow.", &error);
mono_error_assert_ok (&error);
domain->stack_overflow_ex = mono_exception_from_name_two_strings_checked (mono_defaults.corlib, "System", "StackOverflowException", arg, NULL, &error);
+ mono_gc_wbarrier_generic_nostore (&domain->stack_overflow_ex);
mono_error_assert_ok (&error);
/*The ephemeron tombstone i*/
domain->ephemeron_tombstone = mono_object_new_checked (domain, mono_defaults.object_class, &error);
+ mono_gc_wbarrier_generic_nostore (&domain->ephemeron_tombstone);
mono_error_assert_ok (&error);
if (domain != old_domain) {
@@ -292,7 +297,9 @@ mono_runtime_init_checked (MonoDomain *domain, MonoThreadStartCB start_cb, MonoT
ad->data = domain;
domain->domain = ad;
+ mono_gc_wbarrier_generic_nostore (&domain->domain);
domain->setup = setup;
+ mono_gc_wbarrier_generic_nostore (&domain->setup);
mono_thread_attach (domain);
@@ -2072,12 +2079,18 @@ mono_domain_assembly_search (MonoAssemblyName *aname,
GSList *tmp;
MonoAssembly *ass;
gboolean refonly = GPOINTER_TO_UINT (user_data);
+ const gboolean strong_name = aname->public_key_token[0] != 0;
+ /* If it's not a strong name, any version that has the right simple
+ * name is good enough to satisfy the request. .NET Framework also
+ * ignores case differences in this case. */
+ const MonoAssemblyNameEqFlags eq_flags = strong_name ? MONO_ANAME_EQ_IGNORE_CASE :
+ (MONO_ANAME_EQ_IGNORE_PUBKEY | MONO_ANAME_EQ_IGNORE_VERSION | MONO_ANAME_EQ_IGNORE_CASE);
mono_domain_assemblies_lock (domain);
for (tmp = domain->domain_assemblies; tmp; tmp = tmp->next) {
ass = (MonoAssembly *)tmp->data;
/* Dynamic assemblies can't match here in MS.NET */
- if (assembly_is_dynamic (ass) || refonly != ass->ref_only || !mono_assembly_names_equal (aname, &ass->aname))
+ if (assembly_is_dynamic (ass) || refonly != ass->ref_only || !mono_assembly_names_equal_flags (aname, &ass->aname, eq_flags))
continue;
mono_domain_assemblies_unlock (domain);
@@ -2175,6 +2188,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/appdomain.h b/mono/metadata/appdomain.h
index 9d42bdda490..6cbe6000c71 100644
--- a/mono/metadata/appdomain.h
+++ b/mono/metadata/appdomain.h
@@ -26,6 +26,7 @@ typedef struct _MonoAppDomain MonoAppDomain;
typedef struct _MonoJitInfo MonoJitInfo;
typedef void (*MonoDomainFunc) (MonoDomain *domain, void* user_data);
+typedef void (*MonoDomainAssemblyFunc) (MonoAssembly *assembly, void* user_data);
MONO_API MonoDomain*
mono_init (const char *filename);
@@ -85,6 +86,9 @@ mono_domain_get_id (MonoDomain *domain);
MONO_API const char *
mono_domain_get_friendly_name (MonoDomain *domain);
+MonoAssembly*
+m_domain_get_corlib (MonoDomain *domain);
+
MONO_API mono_bool
mono_domain_set (MonoDomain *domain, mono_bool force);
@@ -108,6 +112,9 @@ mono_domain_from_appdomain (MonoAppDomain *appdomain);
MONO_API void
mono_domain_foreach (MonoDomainFunc func, void* user_data);
+MONO_API void
+mono_domain_assembly_foreach (MonoDomain* domain, MonoDomainAssemblyFunc func, void* user_data);
+
MONO_API MonoAssembly *
mono_domain_assembly_open (MonoDomain *domain, const char *name);
diff --git a/mono/metadata/assembly-internals.h b/mono/metadata/assembly-internals.h
index 65dc09f8712..3116ffae122 100644
--- a/mono/metadata/assembly-internals.h
+++ b/mono/metadata/assembly-internals.h
@@ -9,6 +9,24 @@
#include <glib.h>
#include <mono/metadata/assembly.h>
+#include <mono/metadata/metadata-internals.h>
+
+/* Flag bits for mono_assembly_names_equal_flags (). */
+typedef enum {
+ /* Default comparison: all fields must match */
+ MONO_ANAME_EQ_NONE = 0x0,
+ /* Don't compare public key token */
+ MONO_ANAME_EQ_IGNORE_PUBKEY = 0x1,
+ /* Don't compare the versions */
+ MONO_ANAME_EQ_IGNORE_VERSION = 0x2,
+ /* When comparing simple names, ignore case differences */
+ MONO_ANAME_EQ_IGNORE_CASE = 0x4,
+
+ MONO_ANAME_EQ_MASK = 0x7
+} MonoAssemblyNameEqFlags;
+
+gboolean
+mono_assembly_names_equal_flags (MonoAssemblyName *l, MonoAssemblyName *r, MonoAssemblyNameEqFlags flags);
MONO_API MonoImage* mono_assembly_load_module_checked (MonoAssembly *assembly, uint32_t idx, MonoError *error);
diff --git a/mono/metadata/assembly.c b/mono/metadata/assembly.c
index 4d4409d9656..3b5c81d75df 100644
--- a/mono/metadata/assembly.c
+++ b/mono/metadata/assembly.c
@@ -63,18 +63,6 @@ typedef struct {
gboolean framework_facade_assembly;
} AssemblyVersionMap;
-/* Flag bits for assembly_names_equal_flags (). */
-typedef enum {
- /* Default comparison: all fields must match */
- ANAME_EQ_NONE = 0x0,
- /* Don't compare public key token */
- ANAME_EQ_IGNORE_PUBKEY = 0x1,
- /* Don't compare the versions */
- ANAME_EQ_IGNORE_VERSION = 0x2,
-
- ANAME_EQ_MASK = 0x3
-} AssemblyNameEqFlags;
-
/* the default search path is empty, the first slot is replaced with the computed value */
static const char*
default_path [] = {
@@ -359,9 +347,6 @@ mono_assembly_is_in_gac (const gchar *filanem);
static MonoAssembly*
prevent_reference_assembly_from_running (MonoAssembly* candidate, gboolean refonly);
-static gboolean
-assembly_names_equal_flags (MonoAssemblyName *l, MonoAssemblyName *r, AssemblyNameEqFlags flags);
-
/* Assembly name matching */
static gboolean
exact_sn_match (MonoAssemblyName *wanted_name, MonoAssemblyName *candidate_name);
@@ -441,6 +426,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)
{
@@ -635,16 +670,32 @@ check_policy_versions (MonoAssemblyBindingInfo *info, MonoAssemblyName *name)
gboolean
mono_assembly_names_equal (MonoAssemblyName *l, MonoAssemblyName *r)
{
- return assembly_names_equal_flags (l, r, ANAME_EQ_NONE);
+ return mono_assembly_names_equal_flags (l, r, MONO_ANAME_EQ_NONE);
}
+/**
+ * mono_assembly_names_equal_flags:
+ * \param l first assembly name
+ * \param r second assembly name
+ * \param flags flags that affect what is compared.
+ *
+ * Compares two \c MonoAssemblyName instances and returns whether they are equal.
+ *
+ * This compares the simple names and cultures and optionally the versions and
+ * public key tokens, depending on the \c flags.
+ *
+ * \returns TRUE if both assembly names are equal.
+ */
gboolean
-assembly_names_equal_flags (MonoAssemblyName *l, MonoAssemblyName *r, AssemblyNameEqFlags flags)
+mono_assembly_names_equal_flags (MonoAssemblyName *l, MonoAssemblyName *r, MonoAssemblyNameEqFlags flags)
{
if (!l->name || !r->name)
return FALSE;
- if (strcmp (l->name, r->name))
+ if ((flags & MONO_ANAME_EQ_IGNORE_CASE) != 0 && g_strcasecmp (l->name, r->name))
+ return FALSE;
+
+ if ((flags & MONO_ANAME_EQ_IGNORE_CASE) == 0 && strcmp (l->name, r->name))
return FALSE;
if (l->culture && r->culture && strcmp (l->culture, r->culture))
@@ -652,11 +703,11 @@ assembly_names_equal_flags (MonoAssemblyName *l, MonoAssemblyName *r, AssemblyNa
if ((l->major != r->major || l->minor != r->minor ||
l->build != r->build || l->revision != r->revision) &&
- (flags & ANAME_EQ_IGNORE_VERSION) == 0)
+ (flags & MONO_ANAME_EQ_IGNORE_VERSION) == 0)
if (! ((l->major == 0 && l->minor == 0 && l->build == 0 && l->revision == 0) || (r->major == 0 && r->minor == 0 && r->build == 0 && r->revision == 0)))
return FALSE;
- if (!l->public_key_token [0] || !r->public_key_token [0] || (flags & ANAME_EQ_IGNORE_PUBKEY) != 0)
+ if (!l->public_key_token [0] || !r->public_key_token [0] || (flags & MONO_ANAME_EQ_IGNORE_PUBKEY) != 0)
return TRUE;
if (!mono_public_tokens_are_equal (l->public_key_token, r->public_key_token))
@@ -777,7 +828,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 +836,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;
@@ -3576,13 +3627,13 @@ framework_assembly_sn_match (MonoAssemblyName *wanted_name, MonoAssemblyName *ca
if (vmap) {
if (!vmap->framework_facade_assembly) {
/* If the wanted name is a framework assembly, it's enough for the name/version/culture to match. If the assembly was remapped, the public key token is likely unrelated. */
- gboolean result = assembly_names_equal_flags (wanted_name, candidate_name, ANAME_EQ_IGNORE_PUBKEY);
+ gboolean result = mono_assembly_names_equal_flags (wanted_name, candidate_name, MONO_ANAME_EQ_IGNORE_PUBKEY);
mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_ASSEMBLY, "Predicate: candidate and wanted names %s (ignoring the public key token)", result ? "match, returning TRUE" : "don't match, returning FALSE");
return result;
} else {
/* For facades, the name and public key token should
* match, but the version doesn't matter. */
- gboolean result = assembly_names_equal_flags (wanted_name, candidate_name, ANAME_EQ_IGNORE_VERSION);
+ gboolean result = mono_assembly_names_equal_flags (wanted_name, candidate_name, MONO_ANAME_EQ_IGNORE_VERSION);
mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_ASSEMBLY, "Predicate: candidate and wanted names %s (ignoring version)", result ? "match, returning TRUE" : "don't match, returning FALSE");
return result;
}
diff --git a/mono/metadata/assembly.h b/mono/metadata/assembly.h
index 1a6f3519840..a34b5ed6c0e 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 462d3a11525..9a72862bf77 100644
--- a/mono/metadata/boehm-gc.c
+++ b/mono/metadata/boehm-gc.c
@@ -40,6 +40,10 @@
#if HAVE_BOEHM_GC
+#if !HAVE_BDWGC_GC
+#define GC_dirty(x)
+#endif
+
#undef TRUE
#undef FALSE
#define THREAD_LOCAL_ALLOC 1
@@ -55,6 +59,8 @@ void *pthread_get_stackaddr_np(pthread_t);
#define MIN_BOEHM_MAX_HEAP_SIZE (MIN_BOEHM_MAX_HEAP_SIZE_IN_MB << 20)
static gboolean gc_initialized = FALSE;
+static gboolean gc_strict_wbarriers = FALSE;
+static gboolean gc_dont_gc_env = FALSE;
static mono_mutex_t mono_gc_lock;
typedef void (*GC_push_other_roots_proc)(void);
@@ -112,6 +118,8 @@ void
mono_gc_base_init (void)
{
char *env;
+ char *params_opts = NULL;
+ char *debug_opts = NULL;
if (gc_initialized)
return;
@@ -180,25 +188,30 @@ 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
+
+ debug_opts = mono_gc_debug_get();
+ if (debug_opts)
{
- if ((env = g_getenv ("MONO_GC_DEBUG"))) {
- char **opts = g_strsplit (env, ",", -1);
- for (char **ptr = opts; ptr && *ptr; ptr ++) {
- char *opt = *ptr;
- if (!strcmp (opt, "do-not-finalize")) {
- mono_do_not_finalize = 1;
- } else if (!strcmp (opt, "log-finalizers")) {
- log_finalizers = 1;
- }
+ char **opts = g_strsplit (debug_opts, ",", -1);
+ for (char **ptr = opts; ptr && *ptr; ptr ++) {
+ char *opt = *ptr;
+ if (!strcmp (opt, "do-not-finalize")) {
+ mono_do_not_finalize = 1;
+ } else if (!strcmp (opt, "log-finalizers")) {
+ log_finalizers = 1;
}
- g_free (env);
}
+ g_strfreev (opts);
+ g_free (debug_opts);
}
+ /* cache value rather than calling during collection since g_hasenv may take locks and can deadlock */
+ gc_dont_gc_env = g_hasenv ("GC_DONT_GC");
+
GC_init ();
GC_set_warn_proc (mono_gc_warning);
@@ -208,10 +221,12 @@ mono_gc_base_init (void)
GC_init_gcj_malloc (5, NULL);
GC_allow_register_threads ();
- if ((env = g_getenv ("MONO_GC_PARAMS"))) {
- char **ptr, **opts = g_strsplit (env, ",", -1);
+ params_opts = mono_gc_params_get();
+ if (params_opts) {
+ char **ptr, **opts = g_strsplit (params_opts, ",", -1);
for (ptr = opts; *ptr; ++ptr) {
char *opt = *ptr;
+
if (g_str_has_prefix (opt, "max-heap-size=")) {
size_t max_heap;
@@ -230,7 +245,23 @@ mono_gc_base_init (void)
} else if (g_str_has_prefix (opt, "toggleref-test")) {
register_test_toggleref_callback ();
continue;
- } else {
+ } else if (g_str_has_prefix (opt, "incremental=")) {
+ size_t time_limit;
+
+ opt = strchr (opt, '=') + 1;
+ if (*opt && mono_gc_parse_environment_string_extract_number (opt, &time_limit)) {
+ GC_enable_incremental ();
+ #if HAVE_BDWGC_GC
+ if (time_limit != 0)
+ // value is in milliseconds
+ GC_set_time_limit (time_limit);
+ #endif
+ }
+ continue;
+ } else if (g_str_has_prefix (opt, "strict-wbarriers")) {
+ gc_strict_wbarriers = TRUE;
+ continue;
+ }else {
/* Could be a parameter for sgen */
/*
fprintf (stderr, "MONO_GC_PARAMS must be a comma-delimited list of one or more of the following:\n");
@@ -239,8 +270,8 @@ mono_gc_base_init (void)
*/
}
}
- g_free (env);
g_strfreev (opts);
+ g_free (params_opts);
}
mono_thread_callbacks_init ();
@@ -256,6 +287,24 @@ mono_gc_base_init (void)
gc_initialized = TRUE;
}
+void
+mono_gc_dirty(void **ptr)
+{
+ GC_dirty (ptr);
+}
+
+void
+mono_gc_dirty_range(void **ptr, size_t size)
+{
+ if (G_UNLIKELY(gc_strict_wbarriers))
+ {
+ for (int i = 0; i < size/sizeof(void*); i++)
+ GC_dirty(ptr + i);
+ }
+ else
+ GC_dirty (ptr);
+}
+
void
mono_gc_base_cleanup (void)
{
@@ -283,6 +332,13 @@ mono_gc_collect (int generation)
GC_gcollect ();
}
+
+int
+mono_gc_collect_a_little()
+{
+ return GC_collect_a_little();
+}
+
/**
* mono_gc_max_generation:
*
@@ -370,6 +426,34 @@ mono_gc_get_heap_size (void)
return GC_get_heap_size ();
}
+int64_t
+mono_gc_get_max_time_slice_ns()
+{
+#if HAVE_BDWGC_GC
+ return GC_get_time_limit_ns();
+#else
+ return 0;
+#endif
+}
+
+void
+mono_gc_set_max_time_slice_ns(int64_t maxTimeSlice)
+{
+#if HAVE_BDWGC_GC
+ GC_set_time_limit_ns(maxTimeSlice);
+#endif
+}
+
+MonoBoolean
+mono_gc_is_incremental()
+{
+#if HAVE_BDWGC_GC
+ return GC_is_incremental_mode();
+#else
+ return FALSE;
+#endif
+}
+
gboolean
mono_gc_is_gc_thread (void)
{
@@ -393,6 +477,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 +578,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;
@@ -622,6 +714,7 @@ mono_gc_weak_link_add (void **link_addr, MonoObject *obj, gboolean track)
{
/* libgc requires that we use HIDE_POINTER... */
*link_addr = (void*)HIDE_POINTER (obj);
+ mono_gc_dirty (link_addr);
if (track)
GC_REGISTER_LONG_LINK (link_addr, obj);
else
@@ -866,49 +959,60 @@ void
mono_gc_wbarrier_set_field (MonoObject *obj, gpointer field_ptr, MonoObject* value)
{
*(void**)field_ptr = value;
+ mono_gc_dirty (field_ptr);
}
void
mono_gc_wbarrier_set_arrayref (MonoArray *arr, gpointer slot_ptr, MonoObject* value)
{
*(void**)slot_ptr = value;
+ mono_gc_dirty (slot_ptr);
}
void
mono_gc_wbarrier_arrayref_copy (gpointer dest_ptr, gpointer src_ptr, int count)
{
mono_gc_memmove_aligned (dest_ptr, src_ptr, count * sizeof (gpointer));
+ mono_gc_dirty_range (dest_ptr, count * sizeof(gpointer));
}
void
mono_gc_wbarrier_generic_store (gpointer ptr, MonoObject* value)
{
*(void**)ptr = value;
+ mono_gc_dirty (ptr);
}
void
mono_gc_wbarrier_generic_store_atomic (gpointer ptr, MonoObject *value)
{
mono_atomic_store_ptr ((volatile gpointer *)ptr, value);
+ mono_gc_dirty (ptr);
}
void
mono_gc_wbarrier_generic_nostore (gpointer ptr)
{
+ mono_gc_dirty (ptr);
}
void
mono_gc_wbarrier_value_copy (gpointer dest, gpointer src, int count, MonoClass *klass)
{
- mono_gc_memmove_atomic (dest, src, count * mono_class_value_size (klass, NULL));
+ size_t size = count * mono_class_value_size (klass, NULL);
+ mono_gc_memmove_atomic (dest, src, size);
+ mono_gc_dirty_range (dest, size);
}
void
mono_gc_wbarrier_object_copy (MonoObject* obj, MonoObject *src)
{
/* do not copy the sync state */
- mono_gc_memmove_aligned ((char*)obj + sizeof (MonoObject), (char*)src + sizeof (MonoObject),
- mono_object_class (obj)->instance_size - sizeof (MonoObject));
+ size_t size = mono_object_class (obj)->instance_size - sizeof (MonoObject);
+ char * dstPtr = (char*)obj + sizeof (MonoObject);
+ mono_gc_memmove_aligned (dstPtr, (char*)src + sizeof (MonoObject),
+ size);
+ mono_gc_dirty_range ((void**)dstPtr, size);
}
void
@@ -969,6 +1073,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 +1288,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 +1324,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 +1356,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,14 +1399,51 @@ mono_gc_get_managed_allocator_by_type (int atype, ManagedAllocatorVariant varian
guint32
mono_gc_get_managed_allocator_types (void)
{
- return ATYPE_NUM;
+ return 0;
}
+static MonoMethod *write_barrier_conc_method;
MonoMethod*
mono_gc_get_write_barrier (void)
{
- g_assert_not_reached ();
- return NULL;
+ MonoMethod *res;
+ MonoMethodBuilder *mb;
+ MonoMethodSignature *sig;
+ MonoMethod **write_barrier_method_addr;
+ WrapperInfo *info;
+
+ write_barrier_method_addr = &write_barrier_conc_method;
+
+ if (*write_barrier_method_addr)
+ return *write_barrier_method_addr;
+
+ /* Create the IL version of mono_gc_barrier_generic_store () */
+ sig = mono_metadata_signature_alloc (mono_defaults.corlib, 1);
+ sig->ret = &mono_defaults.void_class->byval_arg;
+ sig->params [0] = &mono_defaults.int_class->byval_arg;
+
+ mb = mono_mb_new (mono_defaults.object_class, "wbarrier_conc", MONO_WRAPPER_WRITE_BARRIER);
+
+ mono_mb_emit_ldarg (mb, 0);
+ mono_mb_emit_icall (mb, mono_gc_wbarrier_generic_nostore);
+ mono_mb_emit_byte (mb, MONO_CEE_RET);
+
+ res = mono_mb_create_method (mb, sig, 16);
+ info = mono_wrapper_info_create (mb, WRAPPER_SUBTYPE_NONE);
+ mono_marshal_set_wrapper_info (res, info);
+ mono_mb_free (mb);
+
+ if (*write_barrier_method_addr) {
+ /* Already created */
+ mono_free_method (res);
+ } else {
+ /* double-checked locking */
+ mono_memory_barrier ();
+ *write_barrier_method_addr = res;
+ }
+
+ return *write_barrier_method_addr;
+
}
#else
@@ -1330,11 +1478,48 @@ mono_gc_get_managed_allocator_types (void)
return 0;
}
+static MonoMethod *write_barrier_conc_method;
MonoMethod*
mono_gc_get_write_barrier (void)
{
- g_assert_not_reached ();
- return NULL;
+ MonoMethod *res;
+ MonoMethodBuilder *mb;
+ MonoMethodSignature *sig;
+ MonoMethod **write_barrier_method_addr;
+ WrapperInfo *info;
+
+ write_barrier_method_addr = &write_barrier_conc_method;
+
+ if (*write_barrier_method_addr)
+ return *write_barrier_method_addr;
+
+ /* Create the IL version of mono_gc_barrier_generic_store () */
+ sig = mono_metadata_signature_alloc (mono_defaults.corlib, 1);
+ sig->ret = &mono_defaults.void_class->byval_arg;
+ sig->params [0] = &mono_defaults.int_class->byval_arg;
+
+ mb = mono_mb_new (mono_defaults.object_class, "wbarrier_conc", MONO_WRAPPER_WRITE_BARRIER);
+
+ mono_mb_emit_ldarg (mb, 0);
+ mono_mb_emit_icall (mb, mono_gc_wbarrier_generic_nostore);
+ mono_mb_emit_byte (mb, MONO_CEE_RET);
+
+ res = mono_mb_create_method (mb, sig, 16);
+ info = mono_wrapper_info_create (mb, WRAPPER_SUBTYPE_NONE);
+ mono_marshal_set_wrapper_info (res, info);
+ mono_mb_free (mb);
+
+ if (*write_barrier_method_addr) {
+ /* Already created */
+ mono_free_method (res);
+ } else {
+ /* double-checked locking */
+ mono_memory_barrier ();
+ *write_barrier_method_addr = res;
+ }
+
+ return *write_barrier_method_addr;
+
}
#endif
@@ -1367,7 +1552,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
@@ -1379,13 +1564,17 @@ mono_gc_set_desktop_mode (void)
gboolean
mono_gc_is_moving (void)
{
+#if HAVE_BDWGC_GC
+ return GC_is_incremental_mode ();
+#else
return FALSE;
+#endif
}
gboolean
mono_gc_is_disabled (void)
{
- if (GC_dont_gc || g_hasenv ("GC_DONT_GC"))
+ if (GC_dont_gc || gc_dont_gc_env)
return TRUE;
else
return FALSE;
@@ -1394,7 +1583,8 @@ mono_gc_is_disabled (void)
void
mono_gc_wbarrier_range_copy (gpointer _dest, gpointer _src, int size)
{
- g_assert_not_reached ();
+ memcpy (_dest, _src, size);
+ mono_gc_dirty_range (_dest, size);
}
void*
@@ -1406,7 +1596,6 @@ mono_gc_get_range_copy_func (void)
guint8*
mono_gc_get_card_table (int *shift_bits, gpointer *card_mask)
{
- g_assert_not_reached ();
return NULL;
}
@@ -1435,16 +1624,6 @@ mono_gc_get_logfile (void)
return NULL;
}
-void
-mono_gc_params_set (const char* options)
-{
-}
-
-void
-mono_gc_debug_set (const char* options)
-{
-}
-
void
mono_gc_conservatively_scan_area (void *start, void *end)
{
@@ -1505,7 +1684,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 +1718,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 +1759,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 +1823,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)
@@ -1738,6 +1935,7 @@ handle_data_grow (HandleData *handles, gboolean track)
gpointer *entries;
entries = (void **)mono_gc_alloc_fixed (sizeof (*handles->entries) * new_size, NULL, MONO_ROOT_SOURCE_GC_HANDLE, NULL, "GC Handle Table (Boehm)");
mono_gc_memmove_aligned (entries, handles->entries, sizeof (*handles->entries) * handles->size);
+ mono_gc_dirty_range (entries, new_size * sizeof (*handles->entries));
mono_gc_free_fixed (handles->entries);
handles->entries = entries;
}
@@ -1770,6 +1968,7 @@ alloc_handle (HandleData *handles, MonoObject *obj, gboolean track)
mono_gc_weak_link_add (&(handles->entries [slot]), obj, track);
} else {
handles->entries [slot] = obj;
+ mono_gc_dirty (handles->entries + slot);
}
#ifndef DISABLE_PERFCOUNTERS
@@ -1887,6 +2086,7 @@ mono_gchandle_set_target (guint32 gchandle, MonoObject *obj)
handles->domain_ids [slot] = (obj ? mono_object_get_domain (obj) : mono_domain_get ())->domain_id;
} else {
handles->entries [slot] = obj;
+ mono_gc_dirty (handles->entries + slot);
}
} else {
/* print a warning? */
@@ -1965,6 +2165,7 @@ mono_gchandle_free (guint32 gchandle)
mono_gc_weak_link_remove (&handles->entries [slot], handles->type == HANDLE_WEAK_TRACK);
} else {
handles->entries [slot] = NULL;
+ mono_gc_dirty (handles->entries + slot);
}
vacate_slot (handles, slot);
} else {
@@ -1990,7 +2191,7 @@ mono_gchandle_free_domain (MonoDomain *domain)
{
guint type;
- for (type = HANDLE_TYPE_MIN; type < HANDLE_PINNED; ++type) {
+ for (type = HANDLE_TYPE_MIN; type <= HANDLE_PINNED; ++type) {
guint slot;
HandleData *handles = &gc_handles [type];
lock_handles (handles);
@@ -2007,6 +2208,7 @@ mono_gchandle_free_domain (MonoDomain *domain)
if (handles->entries [slot] && mono_object_domain (handles->entries [slot]) == domain) {
vacate_slot (handles, slot);
handles->entries [slot] = NULL;
+ mono_gc_dirty (handles->entries + slot);
}
}
}
@@ -2021,6 +2223,30 @@ mono_gc_register_obj_with_weak_fields (void *obj)
g_error ("Weak fields not supported by boehm gc");
}
+void
+mono_gc_strong_handle_foreach(GFunc func, gpointer user_data)
+{
+ int gcHandleTypeIndex;
+ uint32_t i;
+
+ lock_handles(handles);
+
+ for (gcHandleTypeIndex = HANDLE_NORMAL; gcHandleTypeIndex <= HANDLE_PINNED; gcHandleTypeIndex++)
+ {
+ HandleData* handles = &gc_handles[gcHandleTypeIndex];
+
+ for (i = 0; i < handles->size; i++)
+ {
+ if (!slot_occupied(handles, i))
+ continue;
+ if (handles->entries[i] != NULL)
+ func(handles->entries[i], user_data);
+ }
+ }
+
+ unlock_handles(handles);
+}
+
#else
MONO_EMPTY_SOURCE_FILE (boehm_gc);
diff --git a/mono/metadata/class-inlines.h b/mono/metadata/class-inlines.h
index d57d5310cc5..4b4fb2eb518 100644
--- a/mono/metadata/class-inlines.h
+++ b/mono/metadata/class-inlines.h
@@ -93,4 +93,10 @@ mono_class_has_static_metadata (MonoClass *klass)
return klass->type_token && !klass->image->dynamic && !mono_class_is_ginst (klass);
}
+static inline gboolean
+m_class_is_initialized (MonoClass* klass)
+{
+ return klass->inited;
+}
+
#endif
diff --git a/mono/metadata/class-internals.h b/mono/metadata/class-internals.h
index f7d946c0a19..b07662b7851 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;
@@ -381,6 +385,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 +1266,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 82927e85285..b4199592dec 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;
@@ -816,6 +817,14 @@ inflate_generic_type (MonoImage *image, MonoType *type, MonoGenericContext *cont
nt->data.generic_class = gclass;
return nt;
}
+ case MONO_TYPE_PTR: {
+ MonoType *nt, *inflated = inflate_generic_type (image, type->data.type, context, error);
+ if (!inflated || !mono_error_ok (error))
+ return NULL;
+ nt = mono_metadata_type_dup (image, type);
+ nt->data.type = inflated;
+ return nt;
+ }
default:
return NULL;
}
@@ -1842,9 +1851,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 */
@@ -9679,6 +9693,7 @@ mono_field_get_flags (MonoClassField *field)
guint32
mono_field_get_offset (MonoClassField *field)
{
+ mono_class_setup_fields(field->parent);
return field->offset;
}
diff --git a/mono/metadata/cominterop.c b/mono/metadata/cominterop.c
index 1caa6ca0f99..ed3964dbc5b 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 00000000000..97376f4c95a
--- /dev/null
+++ b/mono/metadata/console-unity.c
@@ -0,0 +1,47 @@
+#include <mono/metadata/console-io.h>
+#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 6d8042c0768..a55277ff94e 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/domain.c b/mono/metadata/domain.c
index 2947589dbb7..aa10ceb9f65 100644
--- a/mono/metadata/domain.c
+++ b/mono/metadata/domain.c
@@ -299,16 +299,16 @@ gc_alloc_fixed_non_heap_list (size_t size)
if (mono_gc_is_moving ())
return g_malloc0 (size);
else
- return mono_gc_alloc_fixed (appdomain_list_size * sizeof (void*), MONO_GC_DESCRIPTOR_NULL, MONO_ROOT_SOURCE_DOMAIN, NULL, "Domain List");
+ return mono_gc_alloc_fixed (size, MONO_GC_DESCRIPTOR_NULL, MONO_ROOT_SOURCE_DOMAIN, NULL, "Domain List");
}
static void
gc_free_fixed_non_heap_list (void *ptr)
{
if (mono_gc_is_moving ())
- return g_free (ptr);
+ g_free (ptr);
else
- return mono_gc_free_fixed (ptr);
+ mono_gc_free_fixed (ptr);
}
/*
* Allocate an id for domain and set domain->domain_id.
@@ -853,6 +853,8 @@ mono_cleanup (void)
{
mono_close_exe_image ();
+ mono_thread_info_cleanup ();
+
mono_defaults.corlib = NULL;
mono_config_cleanup ();
@@ -923,6 +925,7 @@ mono_domain_set_internal_with_options (MonoDomain *domain, gboolean migrate_exce
SET_APPDOMAIN (domain);
SET_APPCONTEXT (domain->default_context);
+ mono_gc_wbarrier_generic_nostore (&domain->default_context);
if (migrate_exception) {
thread = mono_thread_internal_current ();
@@ -982,6 +985,27 @@ mono_domain_foreach (MonoDomainFunc func, gpointer user_data)
gc_free_fixed_non_heap_list (copy);
}
+MONO_API void
+mono_domain_assembly_foreach (MonoDomain* domain, MonoDomainAssemblyFunc func, void* user_data)
+{
+ MonoAssembly* assembly;
+ GSList *iter;
+
+ /* Skipping internal assembly builders created by remoting,
+ as it is done in ves_icall_System_AppDomain_GetAssemblies
+ */
+ mono_domain_assemblies_lock(domain);
+ for (iter = domain->domain_assemblies; iter; iter = iter->next)
+ {
+ assembly = (MonoAssembly *)iter->data;
+ if (assembly->corlib_internal)
+ continue;
+
+ func(assembly, user_data);
+ }
+ mono_domain_assemblies_unlock(domain);
+}
+
/* FIXME: maybe we should integrate this with mono_assembly_open? */
/**
* mono_domain_assembly_open:
@@ -1227,8 +1251,12 @@ mono_domain_free (MonoDomain *domain, gboolean force)
domain->setup = NULL;
+#if !HAVE_BDWGC_GC
+ // This crashes in bdwgc because we never register such a root.
+ // Not sure why/how it works in sgen, or if it is needed?
if (mono_gc_is_moving ())
mono_gc_deregister_root ((char*)&(domain->MONO_DOMAIN_FIRST_GC_TRACKED));
+#endif
mono_appdomains_lock ();
appdomains_list [domain->domain_id] = NULL;
@@ -1293,6 +1321,12 @@ mono_domain_get_friendly_name (MonoDomain *domain)
return domain->friendly_name;
}
+MonoAssembly*
+m_domain_get_corlib (MonoDomain *domain)
+{
+ return domain->domain->mbr.obj.vtable->klass->image->assembly;
+}
+
/*
* mono_domain_alloc:
*
diff --git a/mono/metadata/file-mmap-unity.c b/mono/metadata/file-mmap-unity.c
new file mode 100644
index 00000000000..cc338f10797
--- /dev/null
+++ b/mono/metadata/file-mmap-unity.c
@@ -0,0 +1,110 @@
+
+#include <config.h>
+#include <glib.h>
+
+#include <mono/metadata/file-mmap.h>
+#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 7c3cb014666..22f556eafee 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);
@@ -140,6 +140,8 @@ MonoGCDescriptor mono_gc_make_descr_for_string (gsize *bitmap, int numbits);
void mono_gc_register_obj_with_weak_fields (void *obj);
+void mono_gc_strong_handle_foreach(GFunc func, gpointer user_data);
+
void mono_gc_register_for_finalization (MonoObject *obj, void *user_data);
void mono_gc_add_memory_pressure (gint64 value);
MONO_API int mono_gc_register_root (char *start, size_t size, MonoGCDescriptor descr, MonoGCRootSource source, void *key, const char *msg);
@@ -358,6 +360,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 99ba7244fce..956938f8cb4 100644
--- a/mono/metadata/gc.c
+++ b/mono/metadata/gc.c
@@ -87,6 +87,12 @@ static MonoCoopCond pending_done_cond;
static MonoCoopMutex pending_done_mutex;
#endif
+static char* gc_params_options;
+static char* gc_debug_options;
+
+#define MONO_GC_PARAMS_NAME "MONO_GC_PARAMS"
+#define MONO_GC_DEBUG_NAME "MONO_GC_DEBUG"
+
static void object_register_finalizer (MonoObject *obj, void (*callback)(void *, void*));
static void reference_queue_proccess_all (void);
@@ -161,6 +167,48 @@ coop_cond_timedwait_alertable (MonoCoopCond *cond, MonoCoopMutex *mutex, guint32
return res;
}
+void
+mono_gc_params_set (const char* options)
+{
+ if (gc_params_options)
+ g_free (gc_params_options);
+
+ gc_params_options = g_strdup (options);
+}
+
+char *
+mono_gc_params_get ()
+{
+ char *env;
+ if ((env = g_getenv (MONO_GC_PARAMS_NAME)) || gc_params_options) {
+ char *params_opts = g_strdup_printf ("%s,%s", gc_params_options ? gc_params_options : "", env ? env : "");
+ g_free (env);
+ return params_opts;
+ }
+ return NULL;
+}
+
+void
+mono_gc_debug_set (const char* options)
+{
+ if (gc_debug_options)
+ g_free (gc_debug_options);
+
+ gc_debug_options = g_strdup (options);
+}
+
+char *
+mono_gc_debug_get ()
+{
+ char *env;
+ if ((env = g_getenv (MONO_GC_DEBUG_NAME)) || gc_debug_options) {
+ char *debug_opts = g_strdup_printf ("%s,%s", gc_debug_options ? gc_debug_options : "", env ? env : "");
+ g_free (env);
+ return debug_opts;
+ }
+ return NULL;
+}
+
/*
* actually, we might want to queue the finalize requests in a separate thread,
* but we need to be careful about the execution domain of the thread...
@@ -708,11 +756,11 @@ 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
- if (mono_gc_is_null ())
+ if (mono_gc_is_null () || mono_gc_is_disabled())
return;
#ifdef HOST_WASM
diff --git a/mono/metadata/handle.h b/mono/metadata/handle.h
index 5355a5b950a..a83618d6b15 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 c7aa0b5766d..4e6d11f6a54 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 c172b8404bc..64b73398053 100644
--- a/mono/metadata/icall-internals.h
+++ b/mono/metadata/icall-internals.h
@@ -10,6 +10,10 @@
#include <glib.h>
#include <mono/metadata/object-internals.h>
+// UNITY
+guint32
+ves_icall_System_CurrentSystemTimeZone_GetTimeZoneData (guint32 year, MonoArray **data, MonoArray **names, MonoBoolean *daylight_inverted);
+
// 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 d91754d9861..befabf51c48 100644
--- a/mono/metadata/icall.c
+++ b/mono/metadata/icall.c
@@ -85,6 +85,7 @@
#include <mono/metadata/w32mutex.h>
#include <mono/metadata/w32semaphore.h>
#include <mono/metadata/w32event.h>
+#include <mono/metadata/unity-utils.h>
#include <mono/utils/monobitset.h>
#include <mono/utils/mono-time.h>
#include <mono/utils/mono-proclib.h>
@@ -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: {
@@ -2471,6 +2479,7 @@ ves_icall_RuntimeType_GetInterfaces (MonoReflectionTypeHandle ref_type, MonoErro
g_hash_table_destroy (iface_hash);
if (!domain->empty_types) {
domain->empty_types = mono_array_new_cached (domain, mono_defaults.runtimetype_class, 0, error);
+ mono_gc_wbarrier_generic_nostore (&domain->empty_types);
goto_if_nok (error, fail);
}
return MONO_HANDLE_NEW (MonoArray, domain->empty_types);
@@ -3941,7 +3950,7 @@ mono_class_get_methods_by_name (MonoClass *klass, const char *name, guint32 bfla
compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
/* An optimization for calls made from Delegate:CreateDelegate () */
- if (klass->delegate && name && !strcmp (name, "Invoke") && (bflags == (BFLAGS_Public | BFLAGS_Static | BFLAGS_Instance))) {
+ if (klass->delegate && klass != mono_defaults.delegate_class && klass != mono_defaults.multicastdelegate_class&& name && !strcmp (name, "Invoke") && (bflags == (BFLAGS_Public | BFLAGS_Static | BFLAGS_Instance))) {
method = mono_get_delegate_invoke (klass);
g_assert (method);
@@ -7050,6 +7059,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 00000000000..62d1500e5d3
--- /dev/null
+++ b/mono/metadata/il2cpp-compat-metadata.h
@@ -0,0 +1,36 @@
+#pragma once
+
+#ifdef RUNTIME_IL2CPP
+
+#include <mono/sgen/sgen-conf.h>
+#include <mono/metadata/mono-gc.h>
+
+#if defined(_POSIX_VERSION)
+#include <pthread.h>
+#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 548e52715e1..b0b9b285ae5 100644
--- a/mono/metadata/image.c
+++ b/mono/metadata/image.c
@@ -41,6 +41,7 @@
#include <mono/metadata/verify-internals.h>
#include <mono/metadata/verify.h>
#include <mono/metadata/image-internals.h>
+#include <mono/metadata/unity-utils.h>
#include <sys/types.h>
#include <sys/stat.h>
#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 3344679e812..cc04f866005 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 edced98b6d9..8c7a8b7b923 100644
--- a/mono/metadata/loader.c
+++ b/mono/metadata/loader.c
@@ -40,6 +40,7 @@
#include <mono/metadata/marshal.h>
#include <mono/metadata/lock-tracer.h>
#include <mono/metadata/verify-internals.h>
+#include <mono/metadata/unity-utils.h>
#include <mono/utils/mono-logger-internals.h>
#include <mono/utils/mono-dl.h>
#include <mono/utils/mono-membar.h>
@@ -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
*/
@@ -2137,6 +2159,10 @@ mono_method_get_marshal_info (MonoMethod *method, MonoMarshalSpec **mspecs)
return;
}
+ /* dynamic method added to non-dynamic image */
+ if (method->dynamic)
+ return;
+
mono_class_init (klass);
methodt = &klass->image->tables [MONO_TABLE_METHOD];
diff --git a/mono/metadata/marshal.c b/mono/metadata/marshal.c
index d2859202fbe..395c2b5a847 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 ();
}
@@ -3930,6 +3936,11 @@ get_runtime_invoke_type (MonoType *t, gboolean ret)
if (t->byref) {
if (t->type == MONO_TYPE_GENERICINST && mono_class_is_nullable (mono_class_from_mono_type (t)))
return t;
+
+ /* The result needs loaded indirectly */
+ if (ret)
+ return t;
+
/* Can't share this with 'I' as that needs another indirection */
return &mono_defaults.int_class->this_arg;
}
@@ -4137,8 +4148,18 @@ handle_enum:
}
if (sig->ret->byref) {
- /* fixme: */
- g_assert_not_reached ();
+ int ldind_op;
+ /* perform indirect load and return by value */
+ MonoType* ret_byval = &mono_class_from_mono_type (sig->ret)->byval_arg;
+ g_assert (!ret_byval->byref);
+ ldind_op = mono_type_to_ldind (ret_byval);
+ /* taken from similar code in mini-generic-sharing.c
+ * we need to use mono_mb_emit_op to add method data when loading
+ * a structure since method-to-ir needs this data for wrapper methods */
+ if (ldind_op == CEE_LDOBJ)
+ mono_mb_emit_op (mb, CEE_LDOBJ, mono_class_from_mono_type (ret_byval));
+ else
+ mono_mb_emit_byte (mb, ldind_op);
}
switch (sig->ret->type) {
diff --git a/mono/metadata/mempool.c b/mono/metadata/mempool.c
index be5af1083f2..c8b79af882c 100644
--- a/mono/metadata/mempool.c
+++ b/mono/metadata/mempool.c
@@ -434,3 +434,21 @@ mono_mempool_get_bytes_allocated (void)
{
return UnlockedRead64 (&total_bytes_allocated);
}
+
+void
+mono_mempool_foreach_block(MonoMemPool* pool, mono_mempool_block_proc callback, void* user_data)
+{
+ MonoMemPool *current = pool;
+
+ while (current)
+ {
+ gpointer start = (guint8*)current + SIZEOF_MEM_POOL;
+ gpointer end = (guint8*)current + current->size;
+
+ callback(start, end, user_data);
+ current = current->next;
+ }
+}
+
+
+
diff --git a/mono/metadata/mempool.h b/mono/metadata/mempool.h
index 1abc25cc406..7e75cd138ca 100644
--- a/mono/metadata/mempool.h
+++ b/mono/metadata/mempool.h
@@ -41,6 +41,11 @@ mono_mempool_strdup (MonoMemPool *pool, const char *s);
MONO_API uint32_t
mono_mempool_get_allocated (MonoMemPool *pool);
+typedef void(*mono_mempool_block_proc)(void* start, void* end, void* user_data);
+
+MONO_API void
+mono_mempool_foreach_block(MonoMemPool* pool, mono_mempool_block_proc callback, void* user_data);
+
MONO_END_DECLS
#endif
diff --git a/mono/metadata/metadata-internals.h b/mono/metadata/metadata-internals.h
index e849706e19e..dd10e13c65c 100644
--- a/mono/metadata/metadata-internals.h
+++ b/mono/metadata/metadata-internals.h
@@ -621,6 +621,8 @@ typedef struct {
char *aot_options;
} MonoAotCacheConfig;
+typedef void(*MonoImageSetFunc) (MonoImageSet *imageSet, void* user_data);
+
#define MONO_SIZEOF_METHOD_SIGNATURE (sizeof (struct _MonoMethodSignature) - MONO_ZERO_LEN_ARRAY * SIZEOF_VOID_P)
static inline gboolean
@@ -722,6 +724,8 @@ mono_image_set_unlock (MonoImageSet *set);
char*
mono_image_set_strdup (MonoImageSet *set, const char *s);
+void mono_metadata_image_set_foreach(MonoImageSetFunc func, gpointer user_data);
+
#define mono_image_set_new0(image,type,size) ((type *) mono_image_set_alloc0 (image, sizeof (type)* (size)))
gboolean
@@ -964,5 +968,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 b2d75f335d8..89635ffc53a 100644
--- a/mono/metadata/metadata.c
+++ b/mono/metadata/metadata.c
@@ -2401,6 +2401,12 @@ retry:
}
}
+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
@@ -5072,6 +5080,66 @@ mono_metadata_generic_class_is_valuetype (MonoGenericClass *gclass)
return gclass->container_class->valuetype;
}
+typedef struct
+{
+ MonoGenericClassFunc func;
+ gpointer user_data;
+} GenericClassForeachData;
+
+
+static void
+generic_class_foreach_callback(gpointer key, gpointer value, gpointer user_data)
+{
+ GenericClassForeachData* data = (GenericClassForeachData*)user_data;
+ data->func(key, data->user_data);
+}
+
+void
+mono_metadata_generic_class_foreach(MonoGenericClassFunc func, void* user_data)
+{
+ GenericClassForeachData data;
+ guint i;
+
+ data.func = func;
+ data.user_data = user_data;
+
+ for(i = 0; i < HASH_TABLE_SIZE; ++i)
+ {
+ MonoImageSet* imageSet = img_set_cache[i];
+
+ if (imageSet == NULL || imageSet->gclass_cache == NULL)
+ continue;
+
+ mono_image_set_lock(imageSet);
+
+ mono_conc_hashtable_foreach(imageSet->gclass_cache, generic_class_foreach_callback, &data);
+
+ mono_image_set_unlock(imageSet);
+ }
+}
+
+void
+mono_metadata_image_set_foreach(MonoImageSetFunc func, gpointer user_data)
+{
+ GenericClassForeachData data;
+ guint i;
+
+ data.func = func;
+ data.user_data = user_data;
+
+ for (i = 0; i < HASH_TABLE_SIZE; ++i)
+ {
+ MonoImageSet* imageSet = img_set_cache[i];
+
+ if (imageSet == NULL)
+ continue;
+
+ mono_image_set_lock(imageSet);
+ func(imageSet, user_data);
+ mono_image_set_unlock(imageSet);
+ }
+}
+
static gboolean
_mono_metadata_generic_class_equal (const MonoGenericClass *g1, const MonoGenericClass *g2, gboolean signature_only)
{
@@ -6599,6 +6667,18 @@ mono_type_is_byref (MonoType *type)
return type->byref;
}
+/**
+ * mono_type_get_attrs:
+ * @type: the MonoType operated on
+ *
+ * Returns: the param attributes.
+ */
+uint32_t
+mono_type_get_attrs (MonoType *type)
+{
+ return type->attrs;
+}
+
/**
* mono_type_get_type:
* \param type the \c MonoType operated on
@@ -6640,6 +6720,13 @@ mono_type_get_class (MonoType *type)
return type->data.klass;
}
+MonoGenericClass*
+m_type_get_generic_class (MonoType *type)
+{
+ /* FIXME: review the runtime users before adding the assert here */
+ return type->data.generic_class;
+}
+
/**
* mono_type_get_array_type:
* \param type the \c MonoType operated on
diff --git a/mono/metadata/metadata.h b/mono/metadata/metadata.h
index 874852c9b07..b4a75a2ff05 100644
--- a/mono/metadata/metadata.h
+++ b/mono/metadata/metadata.h
@@ -332,9 +332,14 @@ typedef enum {
MONO_PARSE_FIELD
} MonoParseTypeMode;
+typedef void(*MonoGenericClassFunc) (MonoGenericClass *genericClass, void* user_data);
+
MONO_API mono_bool
mono_type_is_byref (MonoType *type);
+MONO_API uint32_t
+mono_type_get_attrs (MonoType *type);
+
MONO_API int
mono_type_get_type (MonoType *type);
@@ -346,6 +351,9 @@ mono_type_get_signature (MonoType *type);
MONO_API MonoClass*
mono_type_get_class (MonoType *type);
+MonoGenericClass*
+m_type_get_generic_class (MonoType *type);
+
MONO_API MonoArrayType*
mono_type_get_array_type (MonoType *type);
@@ -423,6 +431,7 @@ MONO_API int mono_type_stack_size (MonoType *type,
MONO_API mono_bool mono_type_generic_inst_is_valuetype (MonoType *type);
MONO_API mono_bool mono_metadata_generic_class_is_valuetype (MonoGenericClass *gclass);
+MONO_API void mono_metadata_generic_class_foreach(MonoGenericClassFunc func, void* user_data);
MONO_API unsigned int mono_metadata_type_hash (MonoType *t1);
MONO_API mono_bool mono_metadata_type_equal (MonoType *t1, MonoType *t2);
diff --git a/mono/metadata/mono-gc.h b/mono/metadata/mono-gc.h
index 455209aa8dc..4908626761b 100644
--- a/mono/metadata/mono-gc.h
+++ b/mono/metadata/mono-gc.h
@@ -104,12 +104,16 @@ typedef enum {
} MonoGCHandleType;
MONO_API void mono_gc_collect (int generation);
+MONO_API int mono_gc_collect_a_little ();
MONO_API int mono_gc_max_generation (void);
MONO_API int mono_gc_get_generation (MonoObject *object);
MONO_API int mono_gc_collection_count (int generation);
MONO_API int64_t mono_gc_get_used_size (void);
MONO_API int64_t mono_gc_get_heap_size (void);
+MONO_API int64_t mono_gc_get_max_time_slice_ns ();
+MONO_API void mono_gc_set_max_time_slice_ns (int64_t maxTimeSlice);
MONO_API MonoBoolean mono_gc_pending_finalizers (void);
+MONO_API MonoBoolean mono_gc_is_incremental (void);
MONO_API void mono_gc_finalize_notify (void);
MONO_API int mono_gc_invoke_finalizers (void);
/* heap walking is only valid in the pre-stop-world event callback */
diff --git a/mono/metadata/mono-hash.c b/mono/metadata/mono-hash.c
index b62947b8341..bf099f65349 100644
--- a/mono/metadata/mono-hash.c
+++ b/mono/metadata/mono-hash.c
@@ -32,6 +32,7 @@
#include <glib.h>
#include "mono-hash.h"
#include "metadata/gc-internals.h"
+#include "metadata/il2cpp-compat-metadata.h"
#include <mono/utils/checked-build.h>
#include <mono/utils/mono-threads-coop.h>
#include <mono/utils/unlocked.h>
diff --git a/mono/metadata/null-gc.c b/mono/metadata/null-gc.c
index 6e35625cbeb..6fd1f57fb55 100644
--- a/mono/metadata/null-gc.c
+++ b/mono/metadata/null-gc.c
@@ -91,6 +91,23 @@ mono_gc_get_heap_size (void)
return 2*1024*1024;
}
+int64_t
+mono_gc_get_max_time_slice_ns()
+{
+ return 0;
+}
+
+void
+mono_gc_set_max_time_slice_ns(int64_t maxTimeSlice)
+{
+}
+
+MonoBoolean
+mono_gc_is_incremental()
+{
+ return FALSE;
+}
+
gboolean
mono_gc_is_gc_thread (void)
{
@@ -296,6 +313,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)
{
@@ -453,16 +475,6 @@ mono_gc_get_logfile (void)
return NULL;
}
-void
-mono_gc_params_set (const char* options)
-{
-}
-
-void
-mono_gc_debug_set (const char* options)
-{
-}
-
void
mono_gc_conservatively_scan_area (void *start, void *end)
{
diff --git a/mono/metadata/object-internals.h b/mono/metadata/object-internals.h
index cb42761d6c2..ed7bdd3f188 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 3d69dca594e..054ce963438 100644
--- a/mono/metadata/object.c
+++ b/mono/metadata/object.c
@@ -2084,6 +2084,10 @@ mono_class_create_runtime_vtable (MonoDomain *domain, MonoClass *klass, MonoErro
/* it's a pointer type: add check */
g_assert ((fklass->byval_arg.type == MONO_TYPE_PTR) || (fklass->byval_arg.type == MONO_TYPE_FNPTR));
*t = *(char *)data;
+ /* This is not needed by sgen, as it does not seem
++ to need write barriers for uncollectable objects (like the vtables storing static
++ fields), but it is needed for incremental boehm. */
+ mono_gc_wbarrier_generic_nostore (t);
}
continue;
}
@@ -3294,6 +3298,11 @@ mono_field_static_set_value (MonoVTable *vt, MonoClassField *field, void *value)
dest = (char*)mono_vtable_get_static_field_data (vt) + field->offset;
}
mono_copy_value (field->type, dest, value, FALSE);
+ /* This is not needed by sgen, as it does not seem
+ to need write barriers for uncollectable objects (like the vtables storing static
++ fields), but it is needed for incremental boehm. */
+ if (field->offset == -1)
+ mono_gc_wbarrier_generic_nostore (dest);
}
/**
@@ -5196,7 +5205,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 +6294,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 +6322,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 +6395,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 00000000000..f58fa138985
--- /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 <pete.lewis@unity3d.com>
+ *
+ * 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 <config.h>
+#include <glib.h>
+#include <string.h>
+#include <sys/stat.h>
+
+#include <mono/utils/mono-compiler.h>
+#include <mono/utils/mono-logger.h>
+#include <mono/utils/mono-membar.h>
+#include <mono/utils/mono-counters.h>
+#include <mono/metadata/object.h>
+#include <mono/metadata/object-internals.h>
+#include <mono/metadata/domain-internals.h>
+#include <mono/metadata/class-internals.h>
+#include <mono/metadata/assembly.h>
+#include <mono/metadata/exception.h>
+#include <mono/metadata/metadata-internals.h>
+#include <mono/metadata/gc-internals.h>
+#include <mono/metadata/appdomain.h>
+#include <mono/metadata/mono-config.h>
+#include <mono/metadata/threads-types.h>
+#include <metadata/threads.h>
+#include <metadata/profiler-private.h>
+#include <mono/metadata/coree.h>
+
+#ifdef _M_X64
+#include <mono/mini/mini-amd64.h>
+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;
+}
+
+MONO_API 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 5e933d0c9fb..c603ca22432 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 3c0fe896c4f..6b5b0be860e 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 69c7e8030b3..a4c7a71c6e0 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 11ddd4b71d4..f8602169841 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/reflection.c b/mono/metadata/reflection.c
index 6ee43541974..3bc5145f333 100644
--- a/mono/metadata/reflection.c
+++ b/mono/metadata/reflection.c
@@ -534,7 +534,10 @@ mono_type_get_object_checked (MonoDomain *domain, MonoType *type, MonoError *err
mono_g_hash_table_insert (domain->type_hash, type, res);
if (type->type == MONO_TYPE_VOID)
+ {
domain->typeof_void = (MonoObject*)res;
+ mono_gc_wbarrier_generic_nostore (&domain->typeof_void);
+ }
mono_domain_unlock (domain);
mono_loader_unlock ();
@@ -1084,6 +1087,15 @@ mono_param_get_objects_internal (MonoDomain *domain, MonoMethod *method, MonoCla
return res;
}
+ /* UNITY: wrapper methods are being captured in callstacks, even thought users should not encounter them.
+ * The logic in param_objects_construct cannot handle this. Just return empty array (case 1073634) */
+ if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE) {
+ MonoArrayHandle res = mono_array_new_handle (domain, mono_class_get_mono_parameter_info_class (), 0, error);
+ goto_if_nok (error, fail);
+
+ return res;
+ }
+
/* Note: the cache is based on the address of the signature into the method
* since we already cache MethodInfos with the method as keys.
*/
diff --git a/mono/metadata/security-manager.h b/mono/metadata/security-manager.h
index d9f49ceb510..d92e169d216 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 800b8c87989..1c60625e6d7 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)
{
@@ -2826,6 +2831,23 @@ mono_gc_get_heap_size (void)
return (int64_t)sgen_gc_get_total_heap_allocation ();
}
+int64_t
+mono_gc_get_max_time_slice_ns()
+{
+ return 0;
+}
+
+MonoBoolean
+mono_gc_is_incremental()
+{
+ return FALSE;
+}
+
+void
+mono_gc_set_max_time_slice_ns(int64_t maxTimeSlice)
+{
+}
+
MonoGCDescriptor
mono_gc_make_root_descr_user (MonoGCRootMarkFunc marker)
{
diff --git a/mono/metadata/threadpool.c b/mono/metadata/threadpool.c
index 7bf9a28edaf..ebc915b8497 100644
--- a/mono/metadata/threadpool.c
+++ b/mono/metadata/threadpool.c
@@ -432,7 +432,11 @@ mono_threadpool_begin_invoke (MonoDomain *domain, MonoObject *target, MonoMethod
error_init (error);
- message = mono_method_call_message_new (method, params, mono_get_delegate_invoke (method->klass), (params != NULL) ? (&async_callback) : NULL, (params != NULL) ? (&state) : NULL, error);
+ MonoMethod* invoke = NULL;
+ if (mono_class_is_delegate(method->klass->parent))
+ invoke = mono_get_delegate_invoke (method->klass);
+
+ message = mono_method_call_message_new (method, params, invoke, (params != NULL) ? (&async_callback) : NULL, (params != NULL) ? (&state) : NULL, error);
return_val_if_nok (error, NULL);
async_call = (MonoAsyncCall*) mono_object_new_checked (domain, async_call_klass, error);
diff --git a/mono/metadata/threads-types.h b/mono/metadata/threads-types.h
index 2feb0ba4f84..4189f7a7509 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 205e733936b..60611ff3618 100644
--- a/mono/metadata/threads.c
+++ b/mono/metadata/threads.c
@@ -55,6 +55,8 @@
#include <mono/utils/w32api.h>
#include <mono/utils/mono-os-wait.h>
+#include <mono/metadata/unity-utils.h>
+
#ifdef HAVE_SIGNAL_H
#include <signal.h>
#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;
@@ -520,6 +523,7 @@ set_current_thread_for_domain (MonoDomain *domain, MonoInternalThread *thread, M
g_assert (!*current_thread_ptr);
*current_thread_ptr = current;
+ mono_gc_wbarrier_generic_nostore (current_thread_ptr);
}
static MonoThread*
@@ -1398,6 +1402,7 @@ ves_icall_System_Threading_Thread_ConstructInternalThread (MonoThread *this_obj)
internal->state = ThreadState_Unstarted;
mono_atomic_cas_ptr ((volatile gpointer *)&this_obj->internal_thread, internal, NULL);
+ mono_gc_wbarrier_generic_nostore (&this_obj->internal_thread);
}
MonoThread *
@@ -1778,6 +1783,7 @@ mono_thread_current (void)
if (!*current_thread_ptr) {
g_assert (domain != mono_get_root_domain ());
*current_thread_ptr = create_thread_object (domain, internal);
+ mono_gc_wbarrier_generic_nostore (current_thread_ptr);
}
return *current_thread_ptr;
}
@@ -1795,6 +1801,7 @@ mono_thread_current_for_thread (MonoInternalThread *internal)
if (!*current_thread_ptr) {
g_assert (domain != mono_get_root_domain ());
*current_thread_ptr = create_thread_object (domain, internal);
+ mono_gc_wbarrier_generic_nostore (current_thread_ptr);
}
return *current_thread_ptr;
}
@@ -1983,6 +1990,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 +2024,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,14 +3050,14 @@ thread_detach (MonoThreadInfo *info)
g_assert (info);
+ mono_gc_thread_detach (info);
+
if (!mono_thread_info_try_get_internal_thread_gchandle (info, &gchandle))
return;
internal = (MonoInternalThread*) mono_gchandle_get_target (gchandle);
g_assert (internal);
- mono_gchandle_free (gchandle);
-
mono_thread_detach_internal (internal);
}
@@ -3208,7 +3224,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 */
}
@@ -4127,10 +4143,13 @@ mono_alloc_static_data (gpointer **static_data_ptr, guint32 offset, void *alloc_
if (mono_gc_user_markers_supported ())
static_data [i] = g_malloc0 (static_data_size [i]);
else
+ {
static_data [i] = mono_gc_alloc_fixed (static_data_size [i], MONO_GC_DESCRIPTOR_NULL,
threadlocal ? MONO_ROOT_SOURCE_THREAD_STATIC : MONO_ROOT_SOURCE_CONTEXT_STATIC,
alloc_key,
threadlocal ? "ThreadStatic Fields" : "ContextStatic Fields");
+ mono_gc_wbarrier_generic_nostore (static_data + i);
+ }
}
}
@@ -4209,6 +4228,7 @@ context_adjust_static_data (MonoAppContext *ctx)
if (context_static_info.offset || context_static_info.idx > 0) {
guint32 offset = MAKE_SPECIAL_STATIC_OFFSET (context_static_info.idx, context_static_info.offset, 0);
mono_alloc_static_data (&ctx->static_data, offset, ctx, FALSE);
+ mono_gc_wbarrier_generic_nostore (&ctx->static_data);
ctx->data->static_data = ctx->static_data;
}
}
@@ -4238,6 +4258,7 @@ alloc_context_static_data_helper (gpointer key, gpointer value, gpointer user)
guint32 offset = GPOINTER_TO_UINT (user);
mono_alloc_static_data (&ctx->static_data, offset, ctx, FALSE);
+ mono_gc_wbarrier_generic_nostore (&ctx->static_data);
ctx->data->static_data = ctx->static_data;
}
@@ -4848,7 +4869,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 +5390,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 00000000000..03ec5b6dc3a
--- /dev/null
+++ b/mono/metadata/unity-icall.c
@@ -0,0 +1,225 @@
+/**
+ * \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 <config.h>
+#include <glib.h>
+#include "mono/utils/mono-compiler.h"
+#include <mono/metadata/class-internals.h>
+#include <mono/metadata/domain-internals.h>
+#include <mono/metadata/exception.h>
+#include <mono/metadata/metadata-internals.h>
+#include <mono/metadata/object.h>
+#include <mono/metadata/object-internals.h>
+
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#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, MonoBoolean *daylight_inverted)
+{
+ MonoError error;
+#ifndef PLATFORM_WIN32
+ MonoDomain *domain = mono_domain_get ();
+ struct tm start, tt;
+ time_t t;
+
+ long int gmtoff_start;
+ long int gmtoff;
+ int is_transitioned = 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));
+ *daylight_inverted = 0;
+ return 1;
+ }
+
+ *daylight_inverted = start.tm_isdst;
+
+ gmtoff = gmt_offset (&start, t);
+ gmtoff_start = gmtoff;
+
+ /* 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_transitioned) {
+ if (!start.tm_isdst)
+ mono_array_setref ((*names), 0, mono_string_new_checked (domain, tzone, &error));
+ else
+ mono_array_setref ((*names), 1, mono_string_new_checked (domain, tzone, &error));
+
+ mono_array_set ((*data), gint64, 1, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
+ return 1;
+ } else {
+ if (!start.tm_isdst)
+ mono_array_setref ((*names), 1, mono_string_new_checked (domain, tzone, &error));
+ else
+ mono_array_setref ((*names), 0, mono_string_new_checked (domain, tzone, &error));
+
+ mono_array_set ((*data), gint64, 0, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
+ is_transitioned = 1;
+ }
+
+ /* This is only set once when we enter daylight saving. */
+ if (*daylight_inverted == 0) {
+ mono_array_set ((*data), gint64, 2, (gint64)gmtoff * 10000000L);
+ mono_array_set ((*data), gint64, 3, (gint64)(gmt_offset (&tt, t) - gmtoff) * 10000000L);
+ } else {
+ mono_array_set ((*data), gint64, 2, (gint64)(gmtoff_start + (gmt_offset (&tt, t) - gmtoff)) * 10000000L);
+ mono_array_set ((*data), gint64, 3, (gint64)(gmtoff - gmt_offset (&tt, t)) * 10000000L);
+ }
+
+
+ gmtoff = gmt_offset (&tt, t);
+ }
+ }
+
+ if (!is_transitioned) {
+ 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);
+ *daylight_inverted = 0;
+ }
+
+ return 1;
+#else
+ //On Windows, we should always load timezones in managed
+ return 0;
+#endif
+}
diff --git a/mono/metadata/unity-liveness.c b/mono/metadata/unity-liveness.c
new file mode 100644
index 00000000000..d5f13ecead7
--- /dev/null
+++ b/mono/metadata/unity-liveness.c
@@ -0,0 +1,646 @@
+#include <config.h>
+#include <glib.h>
+#include <mono/metadata/object.h>
+#include <mono/metadata/object-internals.h>
+#include <mono/metadata/metadata.h>
+#include <mono/metadata/tabledefs.h>
+#include <mono/metadata/class-internals.h>
+#include <mono/metadata/domain-internals.h>
+#include <mono/utils/mono-error.h>
+
+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 00000000000..461d9f0d011
--- /dev/null
+++ b/mono/metadata/unity-memory-info.c
@@ -0,0 +1,699 @@
+#include <config.h>
+#include <mono/utils/mono-publib.h>
+#include "unity-memory-info.h"
+#include <mono/metadata/assembly.h>
+#include <mono/metadata/class.h>
+#include <mono/metadata/class-internals.h>
+#include <mono/metadata/image.h>
+#include <mono/metadata/metadata-internals.h>
+#include <mono/metadata/object-internals.h>
+#include <mono/metadata/tabledefs.h>
+#include <mono/metadata/tokentype.h>
+#include <mono/metadata/gc-internals.h>
+#include <glib.h>
+#include <stdlib.h>
+
+#if HAVE_BDWGC_GC
+
+#include "external/bdwgc/include/gc.h"
+
+typedef struct CollectMetadataContext
+{
+ GHashTable *allTypes;
+ int currentIndex;
+ MonoMetadataSnapshot* metadata;
+} CollectMetadataContext;
+
+static void
+ContextRecurseClassData (CollectMetadataContext *context, MonoClass *klass)
+{
+ gpointer orig_key, value;
+ gpointer iter = NULL;
+ MonoClassField *field = NULL;
+ int fieldCount;
+
+ /* use g_hash_table_lookup_extended as it returns boolean to indicate if value was found.
+ * If we use g_hash_table_lookup it returns the value which we were comparing to NULL. The problem is
+ * that 0 is a valid class index and was confusing our logic.
+ */
+ if (klass->inited && !g_hash_table_lookup_extended (context->allTypes, klass, &orig_key, &value)) {
+ g_hash_table_insert (context->allTypes, klass, GINT_TO_POINTER (context->currentIndex++));
+
+ fieldCount = mono_class_num_fields (klass);
+
+ if (fieldCount > 0) {
+ while ((field = mono_class_get_fields (klass, &iter))) {
+ MonoClass *fieldKlass = mono_class_from_mono_type (field->type);
+
+ if (fieldKlass != klass)
+ ContextRecurseClassData (context, fieldKlass);
+ }
+ }
+ }
+}
+
+static void
+CollectHashMapClass (gpointer key, gpointer value, gpointer user_data)
+{
+ CollectMetadataContext *context = (CollectMetadataContext *)user_data;
+ MonoClass *klass = (MonoClass *)value;
+ ContextRecurseClassData (context, klass);
+}
+
+static void
+CollectHashMapListClasses (gpointer key, gpointer value, gpointer user_data)
+{
+ CollectMetadataContext *context = (CollectMetadataContext *)user_data;
+ GSList *list = (GSList *)value;
+
+ while (list != NULL) {
+ MonoClass *klass = (MonoClass *)list->data;
+ ContextRecurseClassData (context, klass);
+
+ list = g_slist_next (list);
+ }
+}
+
+static void
+CollectGenericClass (MonoGenericClass *genericClass, gpointer user_data)
+{
+ CollectMetadataContext *context = (CollectMetadataContext *)user_data;
+
+ if (genericClass->cached_class != NULL)
+ ContextRecurseClassData (context, genericClass->cached_class);
+}
+
+static void
+CollectImageMetaData (MonoImage *image, gpointer value, CollectMetadataContext *context)
+{
+ int i;
+ MonoTableInfo *tdef = &image->tables[MONO_TABLE_TYPEDEF];
+ GSList *list;
+
+ if (image->dynamic) {
+ GHashTableIter iter;
+ gpointer key;
+ MonoDynamicImage *dynamicImage = (MonoDynamicImage *)image;
+ g_hash_table_iter_init (&iter, dynamicImage->typeref);
+
+ while (g_hash_table_iter_next (&iter, &key, NULL)) {
+ MonoType *monoType = (MonoType *)key;
+ MonoClass *klass = mono_class_from_mono_type (monoType);
+
+ if (klass)
+ ContextRecurseClassData (context, klass);
+ }
+ }
+
+ /* Some classes are only in this list.
+ They are added in reflection_setup_internal_class_internal.
+ */
+ list = image->reflection_info_unregister_classes;
+
+ while (list) {
+ MonoClass *klass = (MonoClass *)list->data;
+
+ if (klass)
+ ContextRecurseClassData (context, klass);
+
+ list = list->next;
+ }
+
+ for (i = 1; i < tdef->rows; ++i) {
+ MonoClass *klass;
+ MonoError error;
+
+ guint32 token = (i + 1) | MONO_TOKEN_TYPE_DEF;
+
+ klass = mono_class_get_checked (image, token, &error);
+
+ if (klass)
+ ContextRecurseClassData (context, klass);
+ }
+
+ if (image->array_cache)
+ g_hash_table_foreach (image->array_cache, CollectHashMapListClasses, context);
+
+ if (image->szarray_cache)
+ g_hash_table_foreach (image->szarray_cache, CollectHashMapClass, context);
+
+ if (image->ptr_cache)
+ g_hash_table_foreach (image->ptr_cache, CollectHashMapClass, context);
+}
+
+static int
+FindClassIndex (GHashTable *hashTable, MonoClass *klass)
+{
+ gpointer orig_key, value;
+
+ if (!g_hash_table_lookup_extended (hashTable, klass, &orig_key, &value))
+ return -1;
+
+ return GPOINTER_TO_INT (value);
+}
+
+static void
+AddMetadataType (gpointer key, gpointer value, gpointer user_data)
+{
+ MonoClass *klass = (MonoClass *)key;
+
+ int index = GPOINTER_TO_INT (value);
+ CollectMetadataContext *context = (CollectMetadataContext *)user_data;
+ MonoMetadataSnapshot *metadata = context->metadata;
+ MonoMetadataType *type = &metadata->types[index];
+
+ if (klass->rank > 0) {
+ type->flags = (MonoMetadataTypeFlags) (kArray | (kArrayRankMask & (klass->rank << 16)));
+ type->baseOrElementTypeIndex = FindClassIndex (context->allTypes, mono_class_get_element_class (klass));
+ } else {
+ gpointer iter = NULL;
+ int fieldCount = 0;
+ MonoClassField *field;
+ MonoClass *baseClass;
+ MonoVTable *vtable;
+ void *statics_data;
+
+ type->flags = (klass->valuetype || klass->byval_arg.type == MONO_TYPE_PTR) ? kValueType : kNone;
+ type->fieldCount = 0;
+ fieldCount = mono_class_num_fields (klass);
+ if (fieldCount > 0) {
+ type->fields = g_new (MonoMetadataField, fieldCount);
+
+ while ((field = mono_class_get_fields (klass, &iter))) {
+ MonoMetadataField *metaField = &type->fields[type->fieldCount];
+ MonoClass *typeKlass = mono_class_from_mono_type (field->type);
+
+ metaField->typeIndex = FindClassIndex (context->allTypes, typeKlass);
+
+ // This will happen if fields type is not initialized
+ // It's OK to skip it, because it means the field is guaranteed to be null on any object
+ if (metaField->typeIndex == -1) {
+ continue;
+ }
+
+ // literals have no actual storage, and are not relevant in this context.
+ if ((field->type->attrs & FIELD_ATTRIBUTE_LITERAL) != 0)
+ continue;
+
+ metaField->isStatic = (field->type->attrs & FIELD_ATTRIBUTE_STATIC) != 0;
+
+ metaField->offset = field->offset;
+ metaField->name = field->name;
+ type->fieldCount++;
+ }
+ }
+
+ vtable = mono_class_try_get_vtable (mono_domain_get (), klass);
+ statics_data = vtable ? mono_vtable_get_static_field_data (vtable) : NULL;
+
+ type->staticsSize = statics_data ? mono_class_data_size (klass) : 0;
+ type->statics = NULL;
+
+ if (type->staticsSize > 0) {
+ type->statics = g_new0 (uint8_t, type->staticsSize);
+ memcpy (type->statics, statics_data, type->staticsSize);
+ }
+
+ baseClass = mono_class_get_parent (klass);
+ type->baseOrElementTypeIndex = baseClass ? FindClassIndex (context->allTypes, baseClass) : -1;
+ }
+
+ type->assemblyName = mono_class_get_image (klass)->assembly->aname.name;
+ type->name = mono_type_get_name_full (&klass->byval_arg, MONO_TYPE_NAME_FORMAT_IL);
+ type->typeInfoAddress = (uint64_t)klass;
+ type->size = (klass->valuetype) != 0 ? (mono_class_instance_size (klass) - sizeof (MonoObject)) : mono_class_instance_size (klass);
+}
+
+static void CollectMetadata(MonoMetadataSnapshot* metadata, GHashTable* monoImages)
+{
+ CollectMetadataContext context;
+
+ context.allTypes = g_hash_table_new(NULL, NULL);
+ context.currentIndex = 0;
+ context.metadata = metadata;
+
+ g_hash_table_foreach(monoImages, (GHFunc)CollectImageMetaData, &context);
+
+ mono_metadata_generic_class_foreach(CollectGenericClass, &context);
+
+ metadata->typeCount = g_hash_table_size(context.allTypes);
+ metadata->types = g_new0(MonoMetadataType, metadata->typeCount);
+
+ g_hash_table_foreach(context.allTypes, AddMetadataType, &context);
+
+ g_hash_table_destroy(context.allTypes);
+}
+
+static void MonoMemPoolNumChunksCallback(void* start, void* end, void* user_data)
+{
+ int* count = (int*)user_data;
+ (*count)++;
+}
+
+static int MonoMemPoolNumChunks(MonoMemPool* pool)
+{
+ int count = 0;
+ mono_mempool_foreach_block(pool, MonoMemPoolNumChunksCallback, &count);
+ return count;
+}
+
+typedef struct SectionIterationContext
+{
+ MonoManagedMemorySection* currentSection;
+} SectionIterationContext;
+
+static void AllocateMemoryForSection(void* context, void* sectionStart, void* sectionEnd)
+{
+ ptrdiff_t sectionSize;
+
+ SectionIterationContext* ctx = (SectionIterationContext*)context;
+ MonoManagedMemorySection* section = ctx->currentSection;
+
+ section->sectionStartAddress = (uint64_t)sectionStart;
+ sectionSize = (uint8_t*)(sectionEnd)-(uint8_t*)(sectionStart);
+
+ section->sectionSize = (uint32_t)(sectionSize);
+ section->sectionBytes = g_new(uint8_t, section->sectionSize);
+
+ ctx->currentSection++;
+}
+
+static void AllocateMemoryForMemPoolChunk(void* chunkStart, void* chunkEnd, void* context)
+{
+ AllocateMemoryForSection(context, chunkStart, chunkEnd);
+}
+
+static void CopyHeapSection(void* context, void* sectionStart, void* sectionEnd)
+{
+ SectionIterationContext* ctx = (SectionIterationContext*)(context);
+ MonoManagedMemorySection* section = ctx->currentSection;
+
+ g_assert(section->sectionStartAddress == (uint64_t)(sectionStart));
+ g_assert(section->sectionSize == (uint8_t*)(sectionEnd)-(uint8_t*)(sectionStart));
+ memcpy(section->sectionBytes, sectionStart, section->sectionSize);
+
+ ctx->currentSection++;
+}
+
+static void CopyMemPoolChunk(void* chunkStart, void* chunkEnd, void* context)
+{
+ CopyHeapSection(context, chunkStart, chunkEnd);
+}
+
+static void IncrementCountForImageMemPoolNumChunks(MonoImage *image, gpointer* value, void *user_data)
+{
+ int* count = (int*)user_data;
+ (*count) += MonoMemPoolNumChunks(image->mempool);
+}
+
+static int MonoImagesMemPoolNumChunks(GHashTable* monoImages)
+{
+ int count = 0;
+
+ g_hash_table_foreach(monoImages, (GHFunc)IncrementCountForImageMemPoolNumChunks, &count);
+ return count;
+}
+
+static void AllocateMemoryForMemPool(MonoMemPool* pool, void *user_data)
+{
+ mono_mempool_foreach_block(pool, AllocateMemoryForMemPoolChunk, user_data);
+}
+
+static void AllocateMemoryForImageMemPool(MonoImage *image, gpointer value, void *user_data)
+{
+ AllocateMemoryForMemPool(image->mempool, user_data);
+}
+
+static void CopyMemPool(MonoMemPool *pool, SectionIterationContext *context)
+{
+ mono_mempool_foreach_block(pool, CopyMemPoolChunk, context);
+}
+
+static void CopyImageMemPool(MonoImage *image, gpointer value, SectionIterationContext *context)
+{
+ CopyMemPool(image->mempool, context);
+}
+
+static void AllocateMemoryForImageClassCache(MonoImage *image, gpointer *value, void *user_data)
+{
+ AllocateMemoryForSection(user_data, image->class_cache.table, ((uint8_t*)image->class_cache.table) + image->class_cache.size);
+}
+
+static void CopyImageClassCache(MonoImage *image, gpointer value, SectionIterationContext *context)
+{
+ CopyHeapSection(context, image->class_cache.table, ((uint8_t*)image->class_cache.table) + image->class_cache.size);
+}
+
+static void IncrementCountForImageSetMemPoolNumChunks(MonoImageSet *imageSet, void *user_data)
+{
+ int* count = (int*)user_data;
+ (*count) += MonoMemPoolNumChunks(imageSet->mempool);
+}
+
+static int MonoImageSetsMemPoolNumChunks()
+{
+ int count = 0;
+ mono_metadata_image_set_foreach(IncrementCountForImageSetMemPoolNumChunks, &count);
+ return count;
+}
+
+static void AllocateMemoryForImageSetMemPool(MonoImageSet* imageSet, void *user_data)
+{
+ AllocateMemoryForMemPool(imageSet->mempool, user_data);
+}
+
+static void CopyImageSetMemPool(MonoImageSet* imageSet, void *user_data)
+{
+ CopyMemPool(imageSet->mempool, user_data);
+}
+
+typedef struct
+{
+ MonoManagedHeap* heap;
+ GHashTable* monoImages;
+
+} CaptureHeapInfoData;
+
+static void* CaptureHeapInfo(void* user)
+{
+ CaptureHeapInfoData* data = (CaptureHeapInfoData*)user;
+ MonoManagedHeap* heap = data->heap;
+ GHashTable* monoImages = data->monoImages;
+
+ MonoDomain* domain = mono_domain_get();
+ MonoDomain* rootDomain = mono_get_root_domain();
+ SectionIterationContext iterationContext;
+
+ // Increment count for each heap section
+ heap->sectionCount = GC_get_heap_section_count();
+ // Increment count for the domain mem pool chunk
+ heap->sectionCount += MonoMemPoolNumChunks(rootDomain->mp);
+ heap->sectionCount += MonoMemPoolNumChunks(domain->mp);
+ // Increment count for each image mem pool chunk
+ heap->sectionCount += MonoImagesMemPoolNumChunks(monoImages);
+ // Increment count for each image->class_cache hash table.
+ heap->sectionCount += g_hash_table_size(monoImages);
+ // Increment count for each image set mem pool chunk
+ heap->sectionCount += MonoImageSetsMemPoolNumChunks();
+
+ heap->sections = g_new0(MonoManagedMemorySection, heap->sectionCount);
+
+ iterationContext.currentSection = heap->sections;
+
+ // Allocate memory for each heap section
+ GC_foreach_heap_section(&iterationContext, AllocateMemoryForSection);
+ // Allocate memory for the domain mem pool chunk
+ mono_domain_lock(rootDomain);
+ mono_mempool_foreach_block(rootDomain->mp, AllocateMemoryForMemPoolChunk, &iterationContext);
+ mono_domain_unlock(rootDomain);
+ mono_domain_lock(domain);
+ mono_mempool_foreach_block(domain->mp, AllocateMemoryForMemPoolChunk, &iterationContext);
+ mono_domain_unlock(domain);
+ // Allocate memory for each image mem pool chunk
+ g_hash_table_foreach(monoImages, (GHFunc)AllocateMemoryForImageMemPool, &iterationContext);
+ // Allocate memory for each image->class_cache hash table.
+ g_hash_table_foreach(monoImages, (GHFunc)AllocateMemoryForImageClassCache, &iterationContext);
+ // Allocate memory for each image->class_cache hash table.
+ mono_metadata_image_set_foreach(AllocateMemoryForImageSetMemPool, &iterationContext);
+
+ return NULL;
+}
+
+static void FreeMonoManagedHeap(MonoManagedHeap* heap)
+{
+ uint32_t i;
+
+ for (i = 0; i < heap->sectionCount; i++)
+ {
+ g_free(heap->sections[i].sectionBytes);
+ }
+
+ g_free(heap->sections);
+}
+
+typedef struct VerifyHeapSectionStillValidIterationContext
+{
+ MonoManagedMemorySection* currentSection;
+ gboolean wasValid;
+} VerifyHeapSectionStillValidIterationContext;
+
+static void VerifyHeapSectionIsStillValid(void* context, void* sectionStart, void* sectionEnd)
+{
+ VerifyHeapSectionStillValidIterationContext* iterationContext = (VerifyHeapSectionStillValidIterationContext*)context;
+ if (iterationContext->currentSection->sectionSize != (uint8_t*)(sectionEnd)-(uint8_t*)(sectionStart))
+ iterationContext->wasValid = FALSE;
+ else if (iterationContext->currentSection->sectionStartAddress != (uint64_t)(sectionStart))
+ iterationContext->wasValid = FALSE;
+
+ iterationContext->currentSection++;
+}
+
+static gboolean MonoManagedHeapStillValid(MonoManagedHeap* heap, GHashTable* monoImages)
+{
+ MonoDomain* rootDomain = mono_get_root_domain();
+ MonoDomain* domain = mono_domain_get();
+
+ VerifyHeapSectionStillValidIterationContext iterationContext;
+ int currentSectionCount;
+
+ currentSectionCount = GC_get_heap_section_count();
+ currentSectionCount += MonoMemPoolNumChunks(rootDomain->mp);
+ currentSectionCount += MonoMemPoolNumChunks(domain->mp);
+ currentSectionCount += MonoImagesMemPoolNumChunks(monoImages);
+ currentSectionCount += g_hash_table_size(monoImages); // image->class_cache hash table.
+ currentSectionCount += MonoImageSetsMemPoolNumChunks();
+
+ if (heap->sectionCount != currentSectionCount)
+ return FALSE;
+
+ iterationContext.currentSection = heap->sections;
+ iterationContext.wasValid = TRUE;
+
+ GC_foreach_heap_section(&iterationContext, VerifyHeapSectionIsStillValid);
+
+ return iterationContext.wasValid;
+}
+
+// The difficulty in capturing the managed snapshot is that we need to do quite some work with the world stopped,
+// to make sure that our snapshot is "valid", and didn't change as we were copying it. However, stopping the world,
+// makes it so you cannot take any lock or allocations. We deal with it like this:
+//
+// 1) We take note of the amount of heap sections and their sizes, and we allocate memory to copy them into.
+// 2) We stop the world.
+// 3) We check if the amount of heapsections and their sizes didn't change in the mean time. If they did, try again.
+// 4) Now, with the world still stopped, we memcpy() the memory from the real heapsections, into the memory that we
+// allocated for their copies.
+// 5) Start the world again.
+
+static void CaptureManagedHeap(MonoManagedHeap* heap, GHashTable* monoImages)
+{
+ MonoDomain* rootDomain = mono_get_root_domain();
+ MonoDomain* domain = mono_domain_get();
+ SectionIterationContext iterationContext;
+
+ CaptureHeapInfoData data;
+
+ data.heap = heap;
+ data.monoImages = monoImages;
+
+ CaptureHeapInfo(&data);
+
+ iterationContext.currentSection = heap->sections;
+
+ GC_foreach_heap_section(&iterationContext, CopyHeapSection);
+ mono_mempool_foreach_block(rootDomain->mp, CopyMemPoolChunk, &iterationContext);
+ mono_mempool_foreach_block(domain->mp, CopyMemPoolChunk, &iterationContext);
+ g_hash_table_foreach(monoImages, (GHFunc)CopyImageMemPool, &iterationContext);
+ g_hash_table_foreach(monoImages, (GHFunc)CopyImageClassCache, &iterationContext);
+ mono_metadata_image_set_foreach(CopyImageSetMemPool, &iterationContext);
+}
+
+static void GCHandleIterationCallback(MonoObject* managedObject, GList** managedObjects)
+{
+ *managedObjects = g_list_append(*managedObjects, managedObject);
+}
+
+static inline void CaptureGCHandleTargets(MonoGCHandles* gcHandles)
+{
+ uint32_t i;
+ GList* trackedObjects, *trackedObject;
+
+ trackedObjects = NULL;
+
+ mono_gc_strong_handle_foreach((GFunc)GCHandleIterationCallback, &trackedObjects);
+
+ gcHandles->trackedObjectCount = (uint32_t)g_list_length(trackedObjects);
+ gcHandles->pointersToObjects = (uint64_t*)g_new0(uint64_t, gcHandles->trackedObjectCount);
+
+ trackedObject = trackedObjects;
+
+ for (i = 0; i < gcHandles->trackedObjectCount; i++)
+ {
+ gcHandles->pointersToObjects[i] = (uint64_t)trackedObject->data;
+ trackedObject = g_list_next(trackedObject);
+ }
+
+ g_list_free(trackedObjects);
+}
+
+static void FillRuntimeInformation(MonoRuntimeInformation* runtimeInfo)
+{
+ runtimeInfo->pointerSize = (uint32_t)(sizeof(void*));
+ runtimeInfo->objectHeaderSize = (uint32_t)(sizeof(MonoObject));
+ runtimeInfo->arrayHeaderSize = offsetof(MonoArray, vector);
+ runtimeInfo->arraySizeOffsetInHeader = offsetof(MonoArray, max_length);
+ runtimeInfo->arrayBoundsOffsetInHeader = offsetof(MonoArray, bounds);
+ runtimeInfo->allocationGranularity = (uint32_t)(2 * sizeof(void*));
+}
+
+static gboolean ManagedHeapContainsAddress(MonoManagedHeap* heap, uint64_t address)
+{
+ uint32_t i;
+
+ for (i = 0; i < heap->sectionCount; ++i)
+ {
+ MonoManagedMemorySection* section = &heap->sections[i];
+ uint64_t sectionBegin = section->sectionStartAddress;
+ uint64_t sectionEnd = sectionBegin + section->sectionSize;
+
+ if (address >= sectionBegin && address <= sectionEnd)
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static void VerifySnapshot(MonoManagedMemorySnapshot* snapshot, GHashTable* monoImages)
+{
+ uint32_t i;
+ FILE* file;
+ GHashTableIter iter;
+ gpointer key;
+ MonoMetadataSnapshot* meta = &snapshot->metadata;
+
+ file = fopen("MonoMemorySnapshotLog.txt", "w");
+
+ g_hash_table_iter_init(&iter, monoImages);
+
+ while (g_hash_table_iter_next(&iter, &key, NULL))
+ {
+ MonoImage* image = (MonoImage*)key;
+ fprintf(file, "MonoImage [0x%016llX] dynamic: %i name: '%s'\n", (uint64_t)image, image->dynamic, image->name);
+ }
+
+ /* Verify that we have collected memory sections for all types */
+ for (i = 0; i < meta->typeCount; ++i)
+ {
+ MonoMetadataType* type = &meta->types[i];
+
+ if (!ManagedHeapContainsAddress(&snapshot->heap, type->typeInfoAddress))
+ {
+ fprintf(file, "The memory for type '%s' @ 0x%016llX is not the part the snapshot.\n", type->name, type->typeInfoAddress);
+ }
+ }
+
+ fclose(file);
+}
+
+static void CollectMonoImage(MonoImage* image, GHashTable* monoImages)
+{
+ if (g_hash_table_lookup(monoImages, image) != NULL)
+ return;
+
+ g_hash_table_insert(monoImages, image, image);
+
+ if (image->assembly->image != NULL &&
+ image != image->assembly->image)
+ {
+ CollectMonoImage(image->assembly->image, monoImages);
+ }
+
+ if (image->module_count > 0)
+ {
+ int i;
+
+ for (i = 0; i < image->module_count; ++i)
+ {
+ MonoImage* moduleImage = image->modules[i];
+
+ if (moduleImage)
+ CollectMonoImage(moduleImage, monoImages);
+ }
+ }
+}
+
+static void CollectMonoImageFromAssembly(MonoAssembly *assembly, void *user_data)
+{
+ GHashTable* monoImages = (GHashTable*)user_data;
+ CollectMonoImage(assembly->image, monoImages);
+}
+
+MonoManagedMemorySnapshot* mono_unity_capture_memory_snapshot()
+{
+ GC_disable();
+ GC_stop_world_external();
+
+ MonoManagedMemorySnapshot* snapshot;
+ snapshot = g_new0(MonoManagedMemorySnapshot, 1);
+
+ GHashTable* monoImages = g_hash_table_new(NULL, NULL);
+
+ mono_domain_assembly_foreach(mono_domain_get(), CollectMonoImageFromAssembly, monoImages);
+
+ CollectMetadata(&snapshot->metadata, monoImages);
+ CaptureManagedHeap(&snapshot->heap, monoImages);
+ CaptureGCHandleTargets(&snapshot->gcHandles);
+ FillRuntimeInformation(&snapshot->runtimeInformation);
+
+#if _DEBUG
+// VerifySnapshot(snapshot, monoImages);
+#endif
+
+ g_hash_table_destroy(monoImages);
+
+ GC_start_world_external();
+ GC_enable();
+
+ return snapshot;
+}
+
+void mono_unity_free_captured_memory_snapshot(MonoManagedMemorySnapshot* snapshot)
+{
+ uint32_t i;
+ MonoMetadataSnapshot* metadata = &snapshot->metadata;
+
+ FreeMonoManagedHeap(&snapshot->heap);
+
+ g_free(snapshot->gcHandles.pointersToObjects);
+
+ for (i = 0; i < metadata->typeCount; i++)
+ {
+ if ((metadata->types[i].flags & kArray) == 0)
+ {
+ g_free(metadata->types[i].fields);
+ g_free(metadata->types[i].statics);
+ }
+
+ g_free(metadata->types[i].name);
+ }
+
+ g_free(metadata->types);
+ g_free(snapshot);
+}
+
+#else
+
+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);
+}
+
+#endif
\ 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 00000000000..f8b777b06ee
--- /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 <glib.h>
+
+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 00000000000..97a7f2b699e
--- /dev/null
+++ b/mono/metadata/unity-utils.c
@@ -0,0 +1,1374 @@
+#include <config.h>
+
+
+#include <mono/utils/mono-publib.h>
+
+/* 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 <mono/metadata/unity-utils.h>
+#include <stdio.h>
+#include <stdlib.h>
+#ifdef WIN32
+#include <fcntl.h>
+#endif
+#include <mono/metadata/exception.h>
+#include <mono/metadata/object.h>
+#include <mono/metadata/metadata.h>
+#include <mono/metadata/tabledefs.h>
+#include <mono/metadata/class-internals.h>
+#include <mono/metadata/object-internals.h>
+#include <mono/metadata/marshal.h>
+#include <mono/metadata/metadata-internals.h>
+#include <mono/metadata/profiler-private.h>
+#include <mono/metadata/profiler.h>
+#include <mono/metadata/reflection-internals.h>
+#include <mono/metadata/threads.h>
+#include <mono/metadata/threadpool.h>
+#include <mono/metadata/tokentype.h>
+#include <mono/utils/mono-string.h>
+
+#if HAVE_BDWGC_GC
+#include <mono/utils/gc_wrapper.h>
+#endif
+
+#include <glib.h>
+
+#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 <Module> */
+ 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;
+}
+
+// gc
+MONO_API void mono_unity_gc_enable()
+{
+#if HAVE_BDWGC_GC
+ GC_enable();
+#else
+ g_assert_not_reached ();
+#endif
+}
+
+MONO_API void mono_unity_gc_disable()
+{
+#if HAVE_BDWGC_GC
+ GC_disable();
+#else
+ g_assert_not_reached ();
+#endif
+}
+
+MONO_API int mono_unity_gc_is_disabled()
+{
+#if HAVE_BDWGC_GC
+ return GC_is_disabled ();
+#else
+ g_assert_not_reached ();
+ return 0;
+#endif
+}
+
+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);
+}
+
+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_generic_argument_at (MonoClass* klass, guint32 index)
+{
+ if (!mono_class_is_ginst (klass))
+ return NULL;
+
+ MonoGenericClass* generic_class = mono_class_get_generic_class (klass);
+
+ if (index >= generic_class->context.class_inst->type_argc)
+ return NULL;
+
+ return mono_class_from_mono_type (generic_class->context.class_inst->type_argv[index]);
+}
+
+MONO_API guint32
+mono_unity_class_get_generic_argument_count (MonoClass* klass)
+{
+ if (!mono_class_is_ginst (klass))
+ return NULL;
+
+ MonoGenericClass* generic_class = mono_class_get_generic_class (klass);
+
+ return generic_class->context.class_inst->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 00000000000..c476a5ef92d
--- /dev/null
+++ b/mono/metadata/unity-utils.h
@@ -0,0 +1,203 @@
+#ifndef __UNITY_MONO_UTILS_H
+#define __UNITY_MONO_UTILS_H
+
+#include <glib.h>
+#include <stdio.h>
+#include <mono/metadata/object.h>
+#include <mono/metadata/marshal.h>
+
+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);
+
+// gc
+MONO_API void mono_unity_gc_enable();
+MONO_API void mono_unity_gc_disable();
+MONO_API int mono_unity_gc_is_disabled();
+
+//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 821de196bdd..51a996c7674 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 00000000000..5617f52f549
--- /dev/null
+++ b/mono/metadata/w32error-unity.c
@@ -0,0 +1,27 @@
+#include <config.h>
+#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 00000000000..e1a570ba0f8
--- /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 00000000000..786c41111bd
--- /dev/null
+++ b/mono/metadata/w32file-unity.c
@@ -0,0 +1,554 @@
+#include <config.h>
+#include <glib.h>
+
+
+
+#include "Directory-c-api.h"
+#include "File-c-api.h"
+#include "w32error.h"
+#include "w32file.h"
+#include "utils/strenc.h"
+#include <mono/metadata/w32handle.h>
+
+
+#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 94d9b547da3..b170a3872af 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 7d08aefdeeb..f428031a7a3 100644
--- a/mono/metadata/w32file-win32.c
+++ b/mono/metadata/w32file-win32.c
@@ -11,6 +11,8 @@
#include <winsock2.h>
#include <windows.h>
#include "mono/metadata/w32file-win32-internals.h"
+#include "mono/metadata/profiler-private.h"
+#include "mono/metadata/w32error.h"
void
mono_w32file_init (void)
@@ -81,23 +83,59 @@ mono_w32file_delete (const gunichar2 *name)
return res;
}
-gboolean
-mono_w32file_read(gpointer handle, gpointer buffer, guint32 numbytes, guint32 *bytesread)
+static void
+cancel_w32_io (HANDLE file_handle)
{
- gboolean res;
- MONO_ENTER_GC_SAFE;
- res = ReadFile (handle, buffer, numbytes, bytesread, NULL);
- MONO_EXIT_GC_SAFE;
+ CancelIoEx (file_handle, NULL);
+}
+
+gboolean
+mono_w32file_read (gpointer handle, gpointer buffer, guint32 numbytes, guint32 *bytesread)
+{
+ gboolean res = FALSE;
+ gboolean interrupted;
+
+ mono_thread_info_install_interrupt (cancel_w32_io, handle, &interrupted);
+ if (!interrupted)
+ {
+ guint32 last_error;
+ MONO_ENTER_GC_SAFE;
+ res = ReadFile (handle, buffer, numbytes, bytesread, NULL);
+ MONO_PROFILER_RAISE (fileio, (1, *bytesread));
+ MONO_EXIT_GC_SAFE;
+
+ /* need to save and restore since clients expect error code set for
+ * failed IO calls and mono_thread_info_uninstall_interrupt overwrites value */
+ last_error = mono_w32error_get_last ();
+ mono_thread_info_uninstall_interrupt (&interrupted);
+ mono_w32error_set_last (last_error);
+ }
+
return res;
}
gboolean
mono_w32file_write (gpointer handle, gconstpointer buffer, guint32 numbytes, guint32 *byteswritten)
{
- gboolean res;
- MONO_ENTER_GC_SAFE;
- res = WriteFile (handle, buffer, numbytes, byteswritten, NULL);
- MONO_EXIT_GC_SAFE;
+ gboolean res = FALSE;
+ gboolean interrupted;
+
+ mono_thread_info_install_interrupt (cancel_w32_io, handle, &interrupted);
+ if (!interrupted)
+ {
+ guint32 last_error;
+ MONO_ENTER_GC_SAFE;
+ res = WriteFile (handle, buffer, numbytes, byteswritten, NULL);
+ MONO_PROFILER_RAISE (fileio, (0, *byteswritten));
+ MONO_EXIT_GC_SAFE;
+
+ /* need to save and restore since clients expect error code set for
+ * failed IO calls and mono_thread_info_uninstall_interrupt overwrites value */
+ last_error = mono_w32error_get_last ();
+ mono_thread_info_uninstall_interrupt (&interrupted);
+ mono_w32error_set_last (last_error);
+ }
+
return res;
}
diff --git a/mono/metadata/w32file.c b/mono/metadata/w32file.c
index 2fbb9a0005a..88f9664bb2f 100644
--- a/mono/metadata/w32file.c
+++ b/mono/metadata/w32file.c
@@ -34,6 +34,7 @@
#include <mono/metadata/exception.h>
#include <mono/metadata/appdomain.h>
#include <mono/metadata/marshal.h>
+#include <mono/metadata/unity-utils.h>
#include <mono/utils/strenc.h>
#include <utils/mono-io-portability.h>
#include <mono/metadata/w32handle.h>
@@ -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);
}
@@ -398,6 +481,11 @@ ves_icall_System_IO_MonoIO_SetFileAttributes (const gunichar2 *path, gint32 attr
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_set_attributes (path,
@@ -405,6 +493,9 @@ ves_icall_System_IO_MonoIO_SetFileAttributes (const gunichar2 *path, gint32 attr
if(ret==FALSE) {
*error=mono_w32error_get_last ();
}
+
+ g_free (path_remapped);
+
return(ret);
}
@@ -430,6 +521,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 +535,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 +547,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 +586,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 5ba22cab55c..7ba74ef23fc 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 00000000000..f58205fca35
--- /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 00000000000..0b79fe25286
--- /dev/null
+++ b/mono/metadata/w32process-unity.c
@@ -0,0 +1,182 @@
+#include <mono/metadata/w32process.h>
+#include <mono/metadata/w32process-internals.h>
+
+#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 48d5e7af846..e2100d266e8 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
@@ -2061,10 +2062,6 @@ process_create (const gunichar2 *appname, const gunichar2 *cmdline,
if (process_info != NULL) {
process_info->process_handle = handle;
process_info->pid = pid;
-
- /* FIXME: we might need to handle the thread info some day */
- process_info->thread_handle = INVALID_HANDLE_VALUE;
- process_info->tid = 0;
}
mono_w32handle_unref (handle_data);
@@ -2217,20 +2214,18 @@ ves_icall_System_Diagnostics_Process_ShellExecuteEx_internal (MonoW32ProcessStar
}
/* Shell exec should not return a process handle when it spawned a GUI thing, like a browser. */
mono_w32handle_close (process_info->process_handle);
- process_info->process_handle = NULL;
+ process_info->process_handle = INVALID_HANDLE_VALUE;
}
done:
if (ret == FALSE) {
process_info->pid = -mono_w32error_get_last ();
} else {
- process_info->thread_handle = NULL;
#if !defined(MONO_CROSS_COMPILE)
process_info->pid = mono_w32process_get_pid (process_info->process_handle);
#else
process_info->pid = 0;
#endif
- process_info->tid = 0;
}
return ret;
diff --git a/mono/metadata/w32process-win32.c b/mono/metadata/w32process-win32.c
index 24fb97ce4d4..2b90f908f3b 100644
--- a/mono/metadata/w32process-win32.c
+++ b/mono/metadata/w32process-win32.c
@@ -111,13 +111,11 @@ ves_icall_System_Diagnostics_Process_ShellExecuteEx_internal (MonoW32ProcessStar
process_info->pid = -GetLastError ();
} else {
process_info->process_handle = shellex.hProcess;
- process_info->thread_handle = NULL;
#if !defined(MONO_CROSS_COMPILE)
process_info->pid = GetProcessId (shellex.hProcess);
#else
process_info->pid = 0;
#endif
- process_info->tid = 0;
}
return ret;
@@ -335,11 +333,9 @@ ves_icall_System_Diagnostics_Process_CreateProcess_internal (MonoW32ProcessStart
if (ret) {
process_info->process_handle = procinfo.hProcess;
/*process_info->thread_handle=procinfo.hThread;*/
- process_info->thread_handle = NULL;
if (procinfo.hThread != NULL && procinfo.hThread != INVALID_HANDLE_VALUE)
CloseHandle (procinfo.hThread);
process_info->pid = procinfo.dwProcessId;
- process_info->tid = procinfo.dwThreadId;
} else {
process_info->pid = -GetLastError ();
}
diff --git a/mono/metadata/w32process.h b/mono/metadata/w32process.h
index 0565ac1eb68..41c3a3154d9 100644
--- a/mono/metadata/w32process.h
+++ b/mono/metadata/w32process.h
@@ -34,9 +34,7 @@ typedef enum {
typedef struct
{
gpointer process_handle;
- gpointer thread_handle;
guint32 pid; /* Contains mono_w32error_get_last () on failure */
- guint32 tid;
MonoArray *env_variables;
MonoString *username;
MonoString *domain;
diff --git a/mono/metadata/w32semaphore-unity.c b/mono/metadata/w32semaphore-unity.c
new file mode 100644
index 00000000000..778cb1693cc
--- /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 62e2eb154c9..7557818a630 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 00000000000..38729c773d9
--- /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 076500687ba..ff89617d270 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 8fab506185d..4e9121f0edf 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 b03ac936738..4208591c41f 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 af434f4218a..0fb8914a992 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 498fd7029c0..535e2069dae 100755
--- a/mono/mini/Makefile.am.in
+++ b/mono/mini/Makefile.am.in
@@ -18,12 +18,20 @@ libgc_libs=$(monodir)/libgc/libmonogc.la
libgc_static_libs=$(monodir)/libgc/libmonogc-static.la
endif
+libbdwgc_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 +44,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_libs)
+
sgen_static_libs = \
$(monodir)/mono/metadata/libmonoruntimesgen-static.la \
$(monodir)/mono/sgen/libmonosgen-static.la \
@@ -102,15 +116,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 +154,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 +167,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 +206,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 +233,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 +269,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 +293,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 +344,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 +545,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 +703,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 +711,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 8b7ea714ee8..1b42c452463 100644
--- a/mono/mini/debugger-agent.c
+++ b/mono/mini/debugger-agent.c
@@ -53,9 +53,12 @@
#include <sys/endian.h>
#endif
+#ifndef RUNTIME_IL2CPP
#include <mono/metadata/mono-debug.h>
#include <mono/metadata/debug-internals.h>
+#endif
#include <mono/metadata/gc-internals.h>
+#ifndef RUNTIME_IL2CPP
#include <mono/metadata/environment.h>
#include <mono/metadata/threads-types.h>
#include <mono/metadata/threadpool.h>
@@ -63,7 +66,9 @@
#include <mono/metadata/runtime.h>
#include <mono/metadata/verify-internals.h>
#include <mono/metadata/reflection-internals.h>
+#endif
#include <mono/metadata/w32socket.h>
+#include <mono/metadata/w32socket-internals.h>
#include <mono/utils/mono-coop-mutex.h>
#include <mono/utils/mono-coop-semaphore.h>
#include <mono/utils/mono-error-internals.h>
@@ -73,12 +78,21 @@
#include <mono/utils/networking.h>
#include <mono/utils/mono-proclib.h>
#include <mono/utils/w32api.h>
-#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 <mono/metadata/seq-points-data.h>
+#include <mono/metadata/profiler.h>
+#include <mono/metadata/tokentype.h>
+#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,16 @@
#include <mono/utils/mono-os-mutex.h>
-#define THREAD_TO_INTERNAL(thread) (thread)->internal_thread
+#define THREAD_TO_INTERNAL(thread) thread->internal_thread
+
+#include "debugger-agent.h"
+
+#ifdef RUNTIME_IL2CPP
+extern Il2CppMonoDefaults il2cpp_mono_defaults;
+extern Il2CppMonoDebugOptions il2cpp_mono_debug_options;
+const Il2CppDebuggerMetadataRegistration *g_il2cpp_metadata;
+#endif
+
typedef struct {
gboolean enabled;
@@ -138,7 +161,11 @@ typedef struct
*/
MonoMethod *api_method;
MonoContext ctx;
+#ifndef RUNTIME_IL2CPP
MonoDebugMethodJitInfo *jit;
+#else
+ Il2CppSequencePointExecutionContext* frame_context;
+#endif
MonoJitInfo *ji;
MonoInterpFrameHandle interp_frame;
int flags;
@@ -175,6 +202,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 +238,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 +275,9 @@ typedef struct {
InvokeData *invoke;
StackFrameInfo catch_frame;
+#ifdef RUNTIME_IL2CPP
+ MonoException *exception;
+#endif
gboolean has_catch_frame;
/*
@@ -274,7 +310,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 +326,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 +532,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 +556,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 +634,7 @@ typedef struct {
char *category, *message;
/* For EVENT_KIND_TYPE_LOAD */
MonoClass *klass;
-} EventInfo;
+} DebuggerEventInfo;
typedef struct {
guint8 *buf, *p, *end;
@@ -604,8 +646,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 +795,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 +837,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 +862,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 +890,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 +1071,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 +1111,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 +1130,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 +1141,27 @@ 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, int frameCountAdjust);
+ void(*il2cpp_debugger_free_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 +1289,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 +1474,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 +1503,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 +1757,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 +2282,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 +2341,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 +2376,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 +2403,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 +2475,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 +2507,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 +2567,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 +2595,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 +2629,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 +2658,7 @@ get_top_method_ji (gpointer ip, MonoDomain **domain, gpointer *out_ip)
}
return ji;
}
+#endif
/*
* save_thread_context:
@@ -2526,10 +2674,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, 0);
+#endif // !RUNTIME_IL2CPP
}
/* Number of threads suspended */
@@ -2596,7 +2748,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 +2833,7 @@ thread_interrupt (DebuggerTlsData *tls, MonoThreadInfo *info, MonoJitInfo *ji)
}
}
}
+#endif
/*
* reset_native_thread_suspend_state:
@@ -2716,6 +2869,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 +2883,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 +2921,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 +2955,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 +3084,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 +3379,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 +3387,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 +3395,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 +3419,34 @@ 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->executionContexts[frame_index]->currentSequencePoint;
+ StackFrame* frame = g_new0(StackFrame, 1);
+ MonoMethod *sp_method = il2cpp_get_seq_point_method(seq_point);
+ frame->method = sp_method;
+ frame->actual_method = tls->il2cpp_context->executionContexts[frame_index]->method;
+ frame->frame_context = tls->il2cpp_context->executionContexts[frame_index];
+ 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 +3464,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 +3583,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 +3628,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 +3665,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;
@@ -3477,9 +3704,9 @@ create_event_list (EventKind event, GPtrArray *reqs, MonoJitInfo *ji, EventInfo
if (mod->data.thread != mono_thread_internal_current ())
filtered = TRUE;
} 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))
+ if (mod->data.exc_class && mod->subclasses && !mono_class_is_assignable_from (mod->data.exc_class, mono_object_get_class (ei->exc)))
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 != mono_object_get_class (ei->exc))
filtered = TRUE;
if (ei->caught && !mod->caught)
filtered = TRUE;
@@ -3492,20 +3719,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] == mono_image_get_assembly (mono_class_get_image (mono_method_get_class (sp_method))))
+ 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,37 +3764,31 @@ 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) {
char *s;
- s = mono_type_full_name (&ei->klass->byval_arg);
+ s = mono_type_full_name (mono_class_get_type(ei->klass));
if (!g_hash_table_lookup (mod->data.type_names, s))
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 +3809,7 @@ create_event_list (EventKind event, GPtrArray *reqs, MonoJitInfo *ji, EventInfo
if (ji->dbg_non_user_code)
filtered = TRUE;
}
+#endif
}
}
@@ -3619,7 +3865,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 +3958,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 +3983,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 +3995,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 +4010,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 +4089,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 +4100,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,11 +4161,29 @@ 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");
+#ifdef RUNTIME_IL2CPP
+ il2cpp_gc_wbarrier_set_field(tls, (void**)&tls->thread, thread);
+ tls->il2cpp_context = il2cpp_debugger_get_thread_context ();
+#else
tls->thread = thread;
+#endif
mono_native_tls_set_value (debugger_tls_id, tls);
DEBUG_PRINTF (1, "[%p] Thread started, obj=%p, tls=%p.\n", (gpointer)tid, thread, tls);
@@ -3932,12 +4213,18 @@ 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
+#ifdef RUNTIME_IL2CPP
+ il2cpp_gc_wbarrier_set_field(tls, (void**)&tls->thread, NULL);
+#else
tls->thread = NULL;
+#endif
}
}
mono_loader_unlock ();
@@ -4030,6 +4317,7 @@ assembly_load (MonoProfiler *prof, MonoAssembly *assembly)
dbg_unlock ();
}
+#ifndef RUNTIME_IL2CPP
static void
assembly_unload (MonoProfiler *prof, MonoAssembly *assembly)
{
@@ -4041,6 +4329,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 +4389,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 +4415,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 +4464,9 @@ typedef struct {
guint8 *ip;
MonoJitInfo *ji;
MonoDomain *domain;
+#ifdef RUNTIME_IL2CPP
+ Il2CppSequencePoint* seq_point;
+#endif
} BreakpointInstance;
/*
@@ -4208,6 +4509,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 +4600,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 +4626,17 @@ remove_breakpoint (BreakpointInstance *inst)
#else
NOT_IMPLEMENTED;
#endif
-}
+}
+
+#endif // !RUNTIME_IL2CPP
+
+#if RUNTIME_IL2CPP
+
+int32_t il2cpp_mono_methods_match(const MethodInfo* left, const MethodInfo* right);
+MonoImage* il2cpp_mono_assembly_get_image(MonoAssembly* assembly);
+void il2cpp_mono_free_method_signatures(void);
+
+#endif // RUNTIME_IL2CPP
/*
* This doesn't take any locks.
@@ -4334,6 +4648,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 +4674,7 @@ bp_matches_method (MonoBreakpoint *bp, MonoMethod *method)
}
return FALSE;
+#endif // RUNTIME_IL2CPP
}
/*
@@ -4367,6 +4685,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 +4734,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 +4768,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 +4818,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 (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 +4870,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 +4887,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) : "<all>", (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 +4963,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 +4999,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 +5040,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 +5069,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 +5089,7 @@ ensure_jit (StackFrame* frame)
}
return TRUE;
}
+#endif
/*
* ss_update:
@@ -4660,12 +5099,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 +5141,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 +5152,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,19 +5182,86 @@ 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)
{
- return bp->method && bp->method->klass->image->assembly == assembly;
+ return bp->method && mono_image_get_assembly (mono_class_get_image (mono_method_get_class (bp->method))) == 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 +5272,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*
@@ -4802,12 +5318,12 @@ get_async_method_builder (StackFrame *frame)
if (!this_addr)
return NULL;
- if (frame->method->klass->valuetype) {
+ if (mono_class_is_valuetype (frame->method->klass)) {
guint8 *vtaddr = *(guint8**)this_addr;
- builder = (char*)vtaddr + builder_field->offset - sizeof (MonoObject);
+ builder = (char*)vtaddr + mono_field_get_offset (builder_field) - sizeof (MonoObject);
} else {
this_obj = *(MonoObject**)this_addr;
- builder = (char*)this_obj + builder_field->offset;
+ builder = (char*)this_obj + mono_field_get_offset (builder_field);
}
return builder;
@@ -4844,7 +5360,7 @@ get_this_async_id (StackFrame *frame)
tls->disable_breakpoints = TRUE;
}
- method = get_object_id_for_debugger_method (mono_class_from_mono_type (builder_field->type));
+ method = get_object_id_for_debugger_method (mono_class_from_mono_type (mono_field_get_type (builder_field)));
obj = mono_runtime_try_invoke (method, builder, NULL, &ex, &error);
mono_error_assert_ok (&error);
@@ -4866,7 +5382,7 @@ set_set_notification_for_wait_completion_flag (StackFrame *frame)
gboolean arg = TRUE;
MonoError error;
args [0] = &arg;
- mono_runtime_invoke_checked (get_set_notification_method (mono_class_from_mono_type (builder_field->type)), builder, args, &error);
+ mono_runtime_invoke_checked (get_set_notification_method (mono_class_from_mono_type (mono_field_get_type (builder_field))), builder, args, &error);
mono_error_assert_ok (&error);
}
@@ -4875,6 +5391,9 @@ static MonoMethod* notify_debugger_of_wait_completion_method_cache = NULL;
static MonoMethod*
get_notify_debugger_of_wait_completion_method (void)
{
+#if UNITY_TINY
+ return NULL;
+#else
if (notify_debugger_of_wait_completion_method_cache != NULL)
return notify_debugger_of_wait_completion_method_cache;
MonoError error;
@@ -4885,8 +5404,10 @@ get_notify_debugger_of_wait_completion_method (void)
notify_debugger_of_wait_completion_method_cache = (MonoMethod *)g_ptr_array_index (array, 0);
g_ptr_array_free (array, TRUE);
return notify_debugger_of_wait_completion_method_cache;
+#endif // UNITY_TINY
}
+#ifndef RUNTIME_IL2CPP
static void
process_breakpoint (DebuggerTlsData *tls, gboolean from_signal)
{
@@ -4957,7 +5478,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 +5526,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 +5558,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 +5579,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 +5603,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 +5642,7 @@ resume_from_signal_handler (void *sigctx, void *func)
#endif
}
+#ifndef RUNTIME_IL2CPP
void
mono_debugger_agent_breakpoint_hit (void *sigctx)
{
@@ -5130,6 +5653,7 @@ mono_debugger_agent_breakpoint_hit (void *sigctx)
*/
resume_from_signal_handler (sigctx, process_breakpoint_from_signal);
}
+#endif
typedef struct {
gboolean found;
@@ -5169,16 +5693,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 +5731,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,10 +5748,16 @@ 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 () */
if (suspend_count - tls->resume_count == 0)
@@ -5233,14 +5773,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 +5797,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 +5835,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 +5847,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->executionContexts[tls->il2cpp_context->frameCount - 1]->currentSequencePoint;
+ 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] == mono_image_get_assembly (mono_class_get_image (mono_method_get_class (sp_method))))
+ {
+ 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 +5928,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 +5947,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 +5957,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 +5991,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 +6007,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 +6024,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 +6138,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 +6199,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 +6379,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 +6428,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->executionContexts[tls->il2cpp_context->frameCount - 1]->currentSequencePoint);
+
+ 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->executionContexts[tls->il2cpp_context->frameCount - 2]->currentSequencePoint;
+ 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 +6512,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 +6552,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->executionContexts[tls->il2cpp_context->frameCount - 1]->currentSequencePoint;
+ 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 +6661,7 @@ ss_create (MonoInternalThread *thread, StepSize size, StepDepth depth, StepFilte
if (frames)
free_frames (frames, nframes);
+#endif
return ERR_NONE;
}
@@ -5965,7 +6706,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 +6726,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 +6749,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, N
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment